aitable-workflow-server 0.1.28-beta.1789632898670 → 0.1.28
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 +207 -105
- package/dist/index.js +11 -11
- package/package.json +3 -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,
|
|
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';
|
|
3
3
|
import * as core from '@midwayjs/core';
|
|
4
4
|
|
|
5
5
|
type WorkspaceOptions = {
|
|
@@ -267,6 +267,146 @@ declare class LocalWorkflowInstanceStore implements WorkflowInstanceStore {
|
|
|
267
267
|
deleteProjectState(projectId: string): Promise<void>;
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
/**
|
|
271
|
+
* run 阶段运行模式(P0/P1 分化)。
|
|
272
|
+
* - `"local"`:服务端进程内跑引擎 + SSE(缺省,无 DB / 未配调度器)。
|
|
273
|
+
* - `"server-run-relay-agent"`:服务端进程内跑引擎 + SSE,但 `coding.run()` 经 relay 投递到本地 daemon(P0)。
|
|
274
|
+
* - `"workflow-pull-claim"`:不启引擎,翻转 DB 期望态等 daemon 认领整条 workflow(P1)。
|
|
275
|
+
*/
|
|
276
|
+
type RunMode = "local" | "server-run-relay-agent" | "workflow-pull-claim";
|
|
277
|
+
/** 在线机器快照(供路由 / 账号中心展示;relay gateway 侧生产,接口层只读)。 */
|
|
278
|
+
interface RelayMachineInfo {
|
|
279
|
+
machineId: string;
|
|
280
|
+
runtimes: string[];
|
|
281
|
+
hasDws: boolean;
|
|
282
|
+
hostname: string;
|
|
283
|
+
os: string;
|
|
284
|
+
/** 认证出的属主 userId(若已知);供 per-owner 连接配额跨实例聚合。 */
|
|
285
|
+
ownerUserId?: string;
|
|
286
|
+
lastSeen: number;
|
|
287
|
+
}
|
|
288
|
+
/** run 阶段调度状态快照(relay 模式,workflow-pull-claim §3.2)。契约在 core(前端共享)。 */
|
|
289
|
+
type RunScheduleStatus = RunScheduleDTO;
|
|
290
|
+
/**
|
|
291
|
+
* run 阶段调度器(P1):把「运行工作流」从"在本进程 createApp"改为"翻转 DB 期望态,
|
|
292
|
+
* 由用户机器 daemon 认领执行"。**归属执行域**(不新增 ServerServices 顶层字段)。
|
|
293
|
+
*
|
|
294
|
+
* local 不提供(`runScheduler` 为 undefined)→ 路由走现状进程内 run-runtime,
|
|
295
|
+
* 本机调试行为零变化。
|
|
296
|
+
*/
|
|
297
|
+
interface RunScheduler {
|
|
298
|
+
/** 用户点「启动」:desired_state='running'(幂等)+ 唤醒候选机器。 */
|
|
299
|
+
start(projectId: string): Promise<RunScheduleStatus>;
|
|
300
|
+
/** 用户点「停止」:desired_state='stopped'(daemon 下次心跳收 stop 并优雅退出)。 */
|
|
301
|
+
stop(projectId: string): Promise<RunScheduleStatus>;
|
|
302
|
+
getStatus(projectId: string): Promise<RunScheduleStatus>;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* 工单记录读模型契约在 core(前端与服务端共享):`RunRecordDTO` /
|
|
306
|
+
* `RunRecordsPageDTO`。此处只声明执行域端口,不重复定义数据形状。
|
|
307
|
+
*/
|
|
308
|
+
type RunRecordsPage = RunRecordsPageDTO;
|
|
309
|
+
/**
|
|
310
|
+
* relay 模式的工单投影读端口(gateway 用 PG `work_items` 适配注入)。
|
|
311
|
+
* local 不需要——`LocalRunController` 直接读 runSnapshot。
|
|
312
|
+
*/
|
|
313
|
+
interface RunRecordsReader {
|
|
314
|
+
listRecords(projectId: string, opts?: {
|
|
315
|
+
limit?: number;
|
|
316
|
+
}): Promise<RunRecordsPageDTO>;
|
|
317
|
+
}
|
|
318
|
+
interface ExecutionBackend {
|
|
319
|
+
readonly kind: "local" | "relay";
|
|
320
|
+
/**
|
|
321
|
+
* run 阶段运行模式(决定 POST /run 走 LocalRunController 还是 RelayRunController)。
|
|
322
|
+
* local backend 恒为 "local";relay backend 由装配方指定(P0 = server-run-relay-agent,P1 = workflow-pull-claim)。
|
|
323
|
+
*/
|
|
324
|
+
readonly runMode: RunMode;
|
|
325
|
+
/**
|
|
326
|
+
* stage 入口前置校验:relay 无在线机器时抛 `NO_ONLINE_MACHINE`(status 503,
|
|
327
|
+
* 由调用方在启动 SSE 前转 JSON 错误);local 恒通过。
|
|
328
|
+
*/
|
|
329
|
+
ensureAvailable(): void;
|
|
330
|
+
/**
|
|
331
|
+
* design 阶段执行器(绑定优先路由,异步解析机器)。
|
|
332
|
+
* local 返回 undefined → runWithExecutor 透明本机 spawn。
|
|
333
|
+
*/
|
|
334
|
+
buildDesignExecutor(ctx: {
|
|
335
|
+
projectId: string;
|
|
336
|
+
agent: AgentType | undefined;
|
|
337
|
+
projectDir: string;
|
|
338
|
+
}): Promise<AgentExecutor | undefined>;
|
|
339
|
+
/**
|
|
340
|
+
* setup 阶段执行器(能力匹配,同步选择;无在线机器返回 undefined)。
|
|
341
|
+
*/
|
|
342
|
+
buildSetupExecutor(ctx: {
|
|
343
|
+
projectId: string;
|
|
344
|
+
projectDir: string;
|
|
345
|
+
}): AgentExecutor | undefined;
|
|
346
|
+
/**
|
|
347
|
+
* run 阶段执行器(P0:服务端 workflow + relay agent step)。
|
|
348
|
+
* local 返回 undefined → runWithExecutor 透明本机 spawn。
|
|
349
|
+
* relay 复用 design 的绑定优先机器选择逻辑,把 `coding.run()` 投递到本地 daemon。
|
|
350
|
+
*/
|
|
351
|
+
buildRunExecutor(ctx: {
|
|
352
|
+
projectId: string;
|
|
353
|
+
projectDir: string;
|
|
354
|
+
agent?: AgentType;
|
|
355
|
+
}): Promise<AgentExecutor | undefined>;
|
|
356
|
+
/** setup 阶段 dws runner;local 返回 undefined → dws 本机 spawn。 */
|
|
357
|
+
buildDwsRunner(): DwsRunner | undefined;
|
|
358
|
+
/** 在线机器列表;local 合成单元素「本机运行时」(管理面 engine 选择器用)。 */
|
|
359
|
+
listMachines(): RelayMachineInfo[] | undefined;
|
|
360
|
+
/** 指定机器是否在线;local 仅本机这一台恒 true。 */
|
|
361
|
+
isMachineOnline(machineId: string): boolean;
|
|
362
|
+
/** 项目当前绑定的执行机器;local 恒返回 LOCAL_MACHINE_ID(engine 面视为 bound)。 */
|
|
363
|
+
getProjectMachine(projectId: string): Promise<string | null>;
|
|
364
|
+
/** 绑定项目到执行机器;local 幂等接受(只有本机可选,无需真实绑定)。 */
|
|
365
|
+
bindProjectMachine(projectId: string, machineId: string): Promise<void>;
|
|
366
|
+
/** 解绑项目的执行机器(项目删除级联);local no-op。 */
|
|
367
|
+
unbindProjectMachine(projectId: string): Promise<void>;
|
|
368
|
+
/**
|
|
369
|
+
* run 阶段调度器(P1,relay 模式)。undefined = 未启用 → 路由走进程内 run-runtime
|
|
370
|
+
* (local 与未配 DB 的 gateway 装配均如此,行为与现状一致)。
|
|
371
|
+
*/
|
|
372
|
+
readonly runScheduler?: RunScheduler;
|
|
373
|
+
/**
|
|
374
|
+
* 工单投影读源(P1.5,relay 模式)。undefined = 未启用(local 与未配 DB 的
|
|
375
|
+
* gateway)→ `GET /run/records` 由 LocalRunController 读 runSnapshot。
|
|
376
|
+
*/
|
|
377
|
+
readonly runRecords?: RunRecordsReader;
|
|
378
|
+
}
|
|
379
|
+
/** local 模式合成出的「本机运行时」标识:无 relay,引擎即本进程所在机器。 */
|
|
380
|
+
declare const LOCAL_MACHINE_ID = "local";
|
|
381
|
+
/**
|
|
382
|
+
* 把「本机探测到的 Coding Agent」纯映射成引擎管理面要展示的机器快照。
|
|
383
|
+
* 与探测解耦成纯函数,便于单测直接喂 fixture(不 spawn 子进程)。
|
|
384
|
+
* runtimes 取已安装 agent 的 id(如 qoder/qwen),dws 恒 true(本机 dws 可用是 local 前提)。
|
|
385
|
+
*/
|
|
386
|
+
declare function buildLocalMachineInfo(detected: readonly DetectedCodingAgent[], now?: number): RelayMachineInfo;
|
|
387
|
+
declare class LocalExecutionBackend implements ExecutionBackend {
|
|
388
|
+
readonly kind: "local";
|
|
389
|
+
readonly runMode: RunMode;
|
|
390
|
+
private localMachineCache;
|
|
391
|
+
ensureAvailable(): void;
|
|
392
|
+
buildDesignExecutor(): Promise<AgentExecutor | undefined>;
|
|
393
|
+
buildSetupExecutor(): AgentExecutor | undefined;
|
|
394
|
+
buildRunExecutor(): Promise<AgentExecutor | undefined>;
|
|
395
|
+
buildDwsRunner(): DwsRunner | undefined;
|
|
396
|
+
/**
|
|
397
|
+
* local 无 relay,但管理面仍要能展示「本机运行时」而非空列表(plan:engine unbound→bound)。
|
|
398
|
+
* 探测带 TTL 缓存;spawn 失败降级为空 runtimes,不让 GET 整条挂掉。
|
|
399
|
+
*/
|
|
400
|
+
listMachines(): RelayMachineInfo[] | undefined;
|
|
401
|
+
/** local 只有本机这一台,恒在线(就是当前进程所在机器)。 */
|
|
402
|
+
isMachineOnline(machineId: string): boolean;
|
|
403
|
+
/** local 无「绑定」概念,直接把每个 project 的引擎视为跑在本机。 */
|
|
404
|
+
getProjectMachine(): Promise<string | null>;
|
|
405
|
+
/** local 恒等于本机,绑定动作是幂等接受(前端选择器只会给出 LOCAL_MACHINE_ID)。 */
|
|
406
|
+
bindProjectMachine(): Promise<void>;
|
|
407
|
+
unbindProjectMachine(): Promise<void>;
|
|
408
|
+
}
|
|
409
|
+
|
|
270
410
|
type RunExecutionEvent = Parameters<RunEventSink>[0];
|
|
271
411
|
|
|
272
412
|
type RunAppFactory = (configPath: string, onRunEvent?: (event: RunExecutionEvent) => void) => Promise<App>;
|
|
@@ -283,7 +423,20 @@ type ServerRuntime = {
|
|
|
283
423
|
};
|
|
284
424
|
type RunSseWriter = (res: ServerResponse, event: string, data: unknown) => void;
|
|
285
425
|
declare function createServerRuntime(appFactory: RunAppFactory): ServerRuntime;
|
|
286
|
-
declare function handleRunRuntime(projectId: string, workspace: Workspace, projectStateStore: WorkflowInstanceStore, runtime: ServerRuntime, res: ServerResponse, writeSse: RunSseWriter): Promise<void>;
|
|
426
|
+
declare function handleRunRuntime(projectId: string, workspace: Workspace, projectStateStore: WorkflowInstanceStore, runtime: ServerRuntime, res: ServerResponse, writeSse: RunSseWriter, execution?: ExecutionBackend): Promise<void>;
|
|
427
|
+
/** 重放缓冲总上限(沿用原实现的 100)。 */
|
|
428
|
+
declare const RUN_REPLAY_EVENT_CAP = 100;
|
|
429
|
+
/** 重放缓冲里逐轮工具流的单独上限:超了先从最旧一条 agent_event 丢弃。 */
|
|
430
|
+
declare const RUN_REPLAY_AGENT_CAP = 60;
|
|
431
|
+
/**
|
|
432
|
+
* 就地收敛重放缓冲(新事件已 push 在末尾)。
|
|
433
|
+
*
|
|
434
|
+
* 两条规则,先后顺序有意义:
|
|
435
|
+
* 1. 先把工具流压到 {@link RUN_REPLAY_AGENT_CAP} 条以内 —— 否则一轮 agent 执行就能把
|
|
436
|
+
* 工单/步骤事件整段挤出缓冲,刷新页面续流时右侧只剩一堆 `↩ 工具返回结果`;
|
|
437
|
+
* 2. 再守总量上限,保持原有「最多重放 100 条」的语义不变。
|
|
438
|
+
*/
|
|
439
|
+
declare function trimRunReplayEvents(events: RunEventDTO[]): void;
|
|
287
440
|
|
|
288
441
|
/** 带内容创建工作流的初始载荷。 */
|
|
289
442
|
type CreateWorkflowInit = {
|
|
@@ -380,106 +533,6 @@ declare class LocalProjectStore implements ProjectStore {
|
|
|
380
533
|
cascadeDelete(_projectId: string): Promise<void>;
|
|
381
534
|
}
|
|
382
535
|
|
|
383
|
-
/** 在线机器快照(供路由 / 账号中心展示;relay gateway 侧生产,接口层只读)。 */
|
|
384
|
-
interface RelayMachineInfo {
|
|
385
|
-
machineId: string;
|
|
386
|
-
runtimes: string[];
|
|
387
|
-
hasDws: boolean;
|
|
388
|
-
hostname: string;
|
|
389
|
-
os: string;
|
|
390
|
-
/** 认证出的属主 userId(若已知);供 per-owner 连接配额跨实例聚合。 */
|
|
391
|
-
ownerUserId?: string;
|
|
392
|
-
lastSeen: number;
|
|
393
|
-
}
|
|
394
|
-
/** run 阶段调度状态快照(relay 模式,workflow-pull-claim §3.2)。契约在 core(前端共享)。 */
|
|
395
|
-
type RunScheduleStatus = RunScheduleDTO;
|
|
396
|
-
/**
|
|
397
|
-
* run 阶段调度器(P1):把「运行工作流」从"在本进程 createApp"改为"翻转 DB 期望态,
|
|
398
|
-
* 由用户机器 daemon 认领执行"。**归属执行域**(不新增 ServerServices 顶层字段)。
|
|
399
|
-
*
|
|
400
|
-
* local 不提供(`runScheduler` 为 undefined)→ 路由走现状进程内 run-runtime,
|
|
401
|
-
* 本机调试行为零变化。
|
|
402
|
-
*/
|
|
403
|
-
interface RunScheduler {
|
|
404
|
-
/** 用户点「启动」:desired_state='running'(幂等)+ 唤醒候选机器。 */
|
|
405
|
-
start(projectId: string): Promise<RunScheduleStatus>;
|
|
406
|
-
/** 用户点「停止」:desired_state='stopped'(daemon 下次心跳收 stop 并优雅退出)。 */
|
|
407
|
-
stop(projectId: string): Promise<RunScheduleStatus>;
|
|
408
|
-
getStatus(projectId: string): Promise<RunScheduleStatus>;
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* 工单记录读模型契约在 core(前端与服务端共享):`RunRecordDTO` /
|
|
412
|
-
* `RunRecordsPageDTO`。此处只声明执行域端口,不重复定义数据形状。
|
|
413
|
-
*/
|
|
414
|
-
type RunRecordsPage = RunRecordsPageDTO;
|
|
415
|
-
/**
|
|
416
|
-
* relay 模式的工单投影读端口(gateway 用 PG `work_items` 适配注入)。
|
|
417
|
-
* local 不需要——`LocalRunController` 直接读 runSnapshot。
|
|
418
|
-
*/
|
|
419
|
-
interface RunRecordsReader {
|
|
420
|
-
listRecords(projectId: string, opts?: {
|
|
421
|
-
limit?: number;
|
|
422
|
-
}): Promise<RunRecordsPageDTO>;
|
|
423
|
-
}
|
|
424
|
-
interface ExecutionBackend {
|
|
425
|
-
readonly kind: "local" | "relay";
|
|
426
|
-
/**
|
|
427
|
-
* stage 入口前置校验:relay 无在线机器时抛 `NO_ONLINE_MACHINE`(status 503,
|
|
428
|
-
* 由调用方在启动 SSE 前转 JSON 错误);local 恒通过。
|
|
429
|
-
*/
|
|
430
|
-
ensureAvailable(): void;
|
|
431
|
-
/**
|
|
432
|
-
* design 阶段执行器(绑定优先路由,异步解析机器)。
|
|
433
|
-
* local 返回 undefined → runWithExecutor 透明本机 spawn。
|
|
434
|
-
*/
|
|
435
|
-
buildDesignExecutor(ctx: {
|
|
436
|
-
projectId: string;
|
|
437
|
-
agent: AgentType | undefined;
|
|
438
|
-
projectDir: string;
|
|
439
|
-
}): Promise<AgentExecutor | undefined>;
|
|
440
|
-
/**
|
|
441
|
-
* setup 阶段执行器(能力匹配,同步选择;无在线机器返回 undefined)。
|
|
442
|
-
*/
|
|
443
|
-
buildSetupExecutor(ctx: {
|
|
444
|
-
projectId: string;
|
|
445
|
-
projectDir: string;
|
|
446
|
-
}): AgentExecutor | undefined;
|
|
447
|
-
/** setup 阶段 dws runner;local 返回 undefined → dws 本机 spawn。 */
|
|
448
|
-
buildDwsRunner(): DwsRunner | undefined;
|
|
449
|
-
/** 在线机器列表;local 无此能力(gateway 的 /api/relay/machines 用)。 */
|
|
450
|
-
listMachines(): RelayMachineInfo[] | undefined;
|
|
451
|
-
/** 指定机器是否在线;local 恒 false(无 relay 概念)。 */
|
|
452
|
-
isMachineOnline(machineId: string): boolean;
|
|
453
|
-
/** 项目当前绑定的执行机器;local 恒 null(无绑定概念,engine 路由回 unbound)。 */
|
|
454
|
-
getProjectMachine(projectId: string): Promise<string | null>;
|
|
455
|
-
/** 绑定项目到执行机器;local 抛 NOT_AVAILABLE(503,引擎管理不可用)。 */
|
|
456
|
-
bindProjectMachine(projectId: string, machineId: string): Promise<void>;
|
|
457
|
-
/** 解绑项目的执行机器(项目删除级联);local no-op。 */
|
|
458
|
-
unbindProjectMachine(projectId: string): Promise<void>;
|
|
459
|
-
/**
|
|
460
|
-
* run 阶段调度器(P1,relay 模式)。undefined = 未启用 → 路由走进程内 run-runtime
|
|
461
|
-
* (local 与未配 DB 的 gateway 装配均如此,行为与现状一致)。
|
|
462
|
-
*/
|
|
463
|
-
readonly runScheduler?: RunScheduler;
|
|
464
|
-
/**
|
|
465
|
-
* 工单投影读源(P1.5,relay 模式)。undefined = 未启用(local 与未配 DB 的
|
|
466
|
-
* gateway)→ `GET /run/records` 由 LocalRunController 读 runSnapshot。
|
|
467
|
-
*/
|
|
468
|
-
readonly runRecords?: RunRecordsReader;
|
|
469
|
-
}
|
|
470
|
-
declare class LocalExecutionBackend implements ExecutionBackend {
|
|
471
|
-
readonly kind: "local";
|
|
472
|
-
ensureAvailable(): void;
|
|
473
|
-
buildDesignExecutor(): Promise<AgentExecutor | undefined>;
|
|
474
|
-
buildSetupExecutor(): AgentExecutor | undefined;
|
|
475
|
-
buildDwsRunner(): DwsRunner | undefined;
|
|
476
|
-
listMachines(): RelayMachineInfo[] | undefined;
|
|
477
|
-
isMachineOnline(): boolean;
|
|
478
|
-
getProjectMachine(): Promise<string | null>;
|
|
479
|
-
bindProjectMachine(): Promise<void>;
|
|
480
|
-
unbindProjectMachine(): Promise<void>;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
536
|
/**
|
|
484
537
|
* 服务集合:**3 个业务接缝 + 2 个数据字段**,封口不再扩张——
|
|
485
538
|
* local/gateway 的任何行为分化必须归入 store / execution / identity 之一
|
|
@@ -555,6 +608,13 @@ declare class SystemController {
|
|
|
555
608
|
* 阶段据此渲染引擎选择;app 部署下前端改用机器 runtimes,不调本端点。
|
|
556
609
|
*/
|
|
557
610
|
agents(): Promise<void>;
|
|
611
|
+
/**
|
|
612
|
+
* 全局执行载体列表(形态感知、跨 project):local = 本机探测快照一台;
|
|
613
|
+
* relay = 在线 daemon(gateway 本实例连接 + bus 跨实例合并)。
|
|
614
|
+
* 与 apps/gateway 私有的 /api/relay/machines 区分:本路由两形态同构,
|
|
615
|
+
* 供管理面(如 Agents 页 runtime 选项)不绑定具体项目地读运行时并集。
|
|
616
|
+
*/
|
|
617
|
+
machines(): Promise<void>;
|
|
558
618
|
}
|
|
559
619
|
|
|
560
620
|
declare class ProjectsController {
|
|
@@ -562,12 +622,22 @@ declare class ProjectsController {
|
|
|
562
622
|
serverServices: ServerServices;
|
|
563
623
|
list(): Promise<void>;
|
|
564
624
|
create(): Promise<void>;
|
|
625
|
+
importZip(): Promise<void>;
|
|
565
626
|
remove(): Promise<void>;
|
|
566
627
|
updateMeta(): Promise<void>;
|
|
567
628
|
/** raw handler:handleInit 直接写原生 req/res(JSON/SSE),本方法不再写响应。 */
|
|
568
629
|
init(): Promise<void>;
|
|
569
630
|
getEngine(): Promise<void>;
|
|
570
631
|
bindEngine(): Promise<void>;
|
|
632
|
+
/**
|
|
633
|
+
* 暴露登记表位置与列名映射(identity.registry)+ 现有智能体行(管理面列表)。
|
|
634
|
+
* 无配置 → registry:null、agents:[],UI 隐藏建号入口。
|
|
635
|
+
* 读列表失败**不静默吞**(relay 形态下 dws 经全局兜底 runner 走远端,错误恰恰
|
|
636
|
+
* 最需要看见):agents 置空并带 listError,由 UI 渲染错误横幅。
|
|
637
|
+
*/
|
|
638
|
+
getAgents(): Promise<void>;
|
|
639
|
+
/** 在登记表里新建一个智能体行,返回新行 recordId(= 该智能体不可变 agent_id)。 */
|
|
640
|
+
createAgent(): Promise<void>;
|
|
571
641
|
listFiles(): Promise<void>;
|
|
572
642
|
replaceFiles(): Promise<void>;
|
|
573
643
|
patchFiles(): Promise<void>;
|
|
@@ -620,6 +690,11 @@ declare class StagesController {
|
|
|
620
690
|
designEvents(): Promise<void>;
|
|
621
691
|
setup(): Promise<void>;
|
|
622
692
|
runHumanAction(): Promise<void>;
|
|
693
|
+
/**
|
|
694
|
+
* 启动 run。可选请求体 `{runMode}`(Phase 1.0 快速切片,per-project 配置落地前的验证入口):
|
|
695
|
+
* 仅允许 `workflow-pull-claim` / `server-run-relay-agent` 覆盖部署缺省;非法 400。
|
|
696
|
+
* 粘性优先:项目已有活跃 lease 时忽略缺省、固定走 relay 控制器(详见 resolveRunController)。
|
|
697
|
+
*/
|
|
623
698
|
run(): Promise<void>;
|
|
624
699
|
runStop(): Promise<void>;
|
|
625
700
|
runStatus(): Promise<void>;
|
|
@@ -789,6 +864,11 @@ type ServeConfig = {
|
|
|
789
864
|
declare function resolveServeConfig(overrides?: ServeConfigOverrides, env?: NodeJS.ProcessEnv): ServeConfig;
|
|
790
865
|
|
|
791
866
|
declare function readJson<T>(req: IncomingMessage): Promise<T>;
|
|
867
|
+
/**
|
|
868
|
+
* 读取请求体。传 `maxBytes` 时超限抛 413(PAYLOAD_TOO_LARGE);
|
|
869
|
+
* 超限后仍把剩余字节排空(drain)但不继续累积进内存,避免半读状态下连接悬挂。
|
|
870
|
+
*/
|
|
871
|
+
declare function readBuffer(req: IncomingMessage, maxBytes?: number): Promise<Buffer>;
|
|
792
872
|
declare function sendJson(res: ServerResponse, body: unknown, status?: number): void;
|
|
793
873
|
/**
|
|
794
874
|
* 与 Hono `c.text()` 字节一致的纯文本响应(含 `charset=UTF-8` 大写拼写、无尾部换行)。
|
|
@@ -970,7 +1050,29 @@ declare class RelayRunController implements RunController {
|
|
|
970
1050
|
limit?: number;
|
|
971
1051
|
}): Promise<RunRecordsPageDTO>;
|
|
972
1052
|
}
|
|
973
|
-
/**
|
|
974
|
-
|
|
1053
|
+
/**
|
|
1054
|
+
* 请求级显式指定的执行模式(Phase 1.0 快速切片:per-project 配置落地前的临时入口,
|
|
1055
|
+
* 见 docs/plans/2026-09-21-server-run-relay-recipe-plan.md §Phase 1.0)。
|
|
1056
|
+
* 只允许两个 relay 模式:`local` 是部署形态(本机 serve 无 scheduler/lease 基建),
|
|
1057
|
+
* 不是请求可选项。
|
|
1058
|
+
*/
|
|
1059
|
+
type RequestedRunMode = Exclude<RunMode, "local">;
|
|
1060
|
+
/** 校验请求体 `runMode`;缺省(无字段/空 body)返回 undefined 走部署默认。 */
|
|
1061
|
+
declare function parseRequestedRunMode(value: unknown): RequestedRunMode | undefined;
|
|
1062
|
+
/**
|
|
1063
|
+
* 按执行域 runMode 装配控制器(P0/P1 分化 + Phase 1.0 project/request 粒度覆盖)。
|
|
1064
|
+
*
|
|
1065
|
+
* 解析顺序:**活跃 lease(粘性)> 请求指定 > 部署缺省(execution.runMode)**。
|
|
1066
|
+
*
|
|
1067
|
+
* - `"local"` / `"server-run-relay-agent"` → LocalRunController:进程内启引擎 + SSE,
|
|
1068
|
+
* 后者通过 buildRunExecutor 把 `coding.run()` 投递到 relay daemon(P0)。
|
|
1069
|
+
* - `"workflow-pull-claim"` → RelayRunController:不启引擎,翻转 DB 期望态等 daemon 认领整条 workflow(P1)。
|
|
1070
|
+
* - 粘性判定只在「否则会落 LocalRunController」且 `runScheduler` 存在时执行——
|
|
1071
|
+
* 部署缺省已是 pull-claim 时结果相同,不白读一次 DB。
|
|
1072
|
+
*
|
|
1073
|
+
* 注意:不能靠 `runScheduler` 存在性判定模式——P0 的 relay backend 也有 runScheduler(DB 存在时装配),
|
|
1074
|
+
* 但 POST /run 必须走 LocalRunController 才能启动引擎。
|
|
1075
|
+
*/
|
|
1076
|
+
declare function resolveRunController(services: ServerServices, projectId?: string, requestedMode?: RequestedRunMode): Promise<RunController>;
|
|
975
1077
|
|
|
976
|
-
export { type ActorContext, type CreateProjectInit, type CreateProjectResult, type CreateWorkflowInit, type CreateWorkflowResult, DEFAULT_SERVE_HOST, DEFAULT_SERVE_PORT, type ExecutionBackend, type FilesPatch, type IdentityService, LocalExecutionBackend, LocalIdentityService, LocalProjectMutexStore, LocalProjectRepository, LocalProjectStore, LocalRunController, LocalWorkflowInstanceStore, type MaterializeOptions, type MaterializeResult, type ProjectFileKind, type ProjectMutexStore, type ProjectRepository, type ProjectStore, type RelayMachineInfo, RelayRunController, type RequestIdentity, type RunAppFactory, type RunControlResult, type RunController, 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, 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, prepareWorkdirGuarded, readDesignManifest, readJson, removeLegacyViewsFiles, removeProjectFiles, replaceProjectFiles, resetProjectWorkflow, resolveProject, resolveRunController, resolveServeConfig, scopeOf, sendError, sendJson, sendText, sendUnauthorized, silentLoggerFactory, startServer, touchProject, updateProjectMeta, validateConfigScene, validateDesignArtifacts, warnDeprecatedBootstrapKey, withoutLeakedMidwayPortEnv, workflowFileKind, writeDesignManifest, writeProjectFiles };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)}
|
|
3
|
-
`)}
|
|
4
|
-
`));return}
|
|
1
|
+
var Je=Object.defineProperty;var wn=Object.getOwnPropertyDescriptor;var s=(t,e)=>Je(t,"name",{value:e,configurable:!0});var hn=(t,e)=>{for(var r in e)Je(t,r,{get:e[r],enumerable:!0})};var u=(t,e,r,n)=>{for(var o=n>1?void 0:n?wn(e,r):e,i=t.length-1,a;i>=0;i--)(a=t[i])&&(o=(n?a(e,r,o):a(o))||o);return n&&o&&Je(e,r,o),o};function he(t){let e=Array.isArray(t)?t[0]:t;return e!=null&&e!==""?e:null}s(he,"firstQueryValue");function O(t){return t.state.scope??{}}s(O,"scopeOf");function Vi(t){return t.state.identity}s(Vi,"identityOf");var We={};hn(We,{Configuration:()=>re,CorsMiddleware:()=>X,ErrorMappingMiddleware:()=>te,IdentityMiddleware:()=>V,ProjectsController:()=>v,ResolveProjectMiddleware:()=>G,ServerConfiguration:()=>re,StagesController:()=>R,StaticWebMiddleware:()=>K,SystemController:()=>M,WorkflowsController:()=>W});import{Configuration as Bn,App as Un}from"@midwayjs/core";import{Middleware as jn}from"@midwayjs/core";import yn from"crypto";function ht(t,e){Sn(t,e),e.setHeader("access-control-allow-methods","GET,POST,PUT,PATCH,DELETE,OPTIONS"),e.setHeader("access-control-allow-headers","content-type, authorization")}s(ht,"setCors");function Sn(t,e){let r=vn();if(!r){e.setHeader("access-control-allow-origin","*");return}let n=t.headers.origin,o=Array.isArray(n)?n[0]:n;o&&r.includes(o)&&(e.setHeader("access-control-allow-origin",o),e.setHeader("vary","Origin"))}s(Sn,"applyCorsOrigin");function vn(){let t=process.env.AITABLE_WORKFLOW_ALLOWED_ORIGINS;if(typeof t!="string")return;let e=t.split(",").map(r=>r.trim()).filter(Boolean);return e.length?e:void 0}s(vn,"readAllowedOrigins");function Pn(){let t=process.env.AITABLE_WORKFLOW_API_TOKEN,e=typeof t=="string"?t.trim():"";return e||void 0}s(Pn,"readServerApiToken");function yt(t){let e=Pn();if(!e)return!0;let r=t.headers.authorization,n=Array.isArray(r)?r[0]:r;if(!n)return!1;let i=/^Bearer\s+(.+)$/i.exec(n.trim())?.[1]?.trim();return i?xn(i,e):!1}s(yt,"isRequestAuthorized");function xn(t,e){let r=Buffer.from(t),n=Buffer.from(e);return r.length!==n.length?!1:yn.timingSafeEqual(r,n)}s(xn,"timingSafeEqualString");function St(t){return Array.isArray(t)?t[0]:t}s(St,"headerValue");function vt(t,e){let r=e.toUpperCase();return r==="OPTIONS"||r==="GET"&&t==="/api/health"||r==="GET"&&t==="/api/public-config"||r==="GET"&&t==="/check.node"}s(vt,"isAuthExempt");var X=class{resolve(){return async(e,r)=>{if(ht(e.req,e.res),e.method.toUpperCase()==="OPTIONS"){e.respond=!1,e.res.writeHead(204),e.res.end();return}await r()}}static getName(){return"aitableCors"}};s(X,"CorsMiddleware"),X=u([jn()],X);import{Middleware as Dn}from"@midwayjs/core";import{logger as Ge}from"aitable-workflow-core";async function k(t){let r=(await He(t)).toString("utf8").trim();return r?JSON.parse(r):{}}s(k,"readJson");async function He(t,e){let r=[],n=0,o=!1;for await(let i of t){if(o)continue;let a=Buffer.isBuffer(i)?i:Buffer.from(i);if(n+=a.length,e!==void 0&&n>e){o=!0,r.length=0;continue}r.push(a)}if(o)throw Object.assign(new Error(`\u8BF7\u6C42\u4F53\u8D85\u8FC7\u4E0A\u9650 ${e} \u5B57\u8282\uFF0C\u5DF2\u62D2\u7EDD\uFF08\u5F53\u524D\u5DF2\u7D2F\u8BA1 ${n} \u5B57\u8282\uFF09`),{code:"PAYLOAD_TOO_LARGE",status:413});return Buffer.concat(r)}s(He,"readBuffer");function f(t,e,r=200){t.writeHead(r,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify(e)}
|
|
2
|
+
`)}s(f,"sendJson");function Pt(t,e,r=200){t.writeHead(r,{"content-type":"text/plain; charset=UTF-8"}),t.end(e)}s(Pt,"sendText");function S(t,e,r,n,o){f(t,{error:{code:r,message:n,details:o}},e)}s(S,"sendError");function xt(t){t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify({error:"unauthorized"})}
|
|
3
|
+
`)}s(xt,"sendUnauthorized");function pe(t){return{code:F(t),message:P(t),details:$(t)}}s(pe,"apiError");function ee(t){return typeof t=="object"&&t!==null&&"status"in t&&typeof t.status=="number"?t.status:500}s(ee,"errorStatus");function F(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}s(F,"errorCode");function P(t){return t instanceof Error?t.message:String(t)}s(P,"errorMessage");function $(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}s($,"errorDetails");function Ve(t){return t instanceof Error?t.stack:void 0}s(Ve,"errorStack");function Tn(t){if(ee(t)!==404||typeof t!="object"||t===null)return!1;let{code:e,name:r}=t;return e==="404"||e===404||r==="NotFoundError"}s(Tn,"isFrameworkRouteMiss");var te=class{resolve(){return async(e,r)=>{try{await r(),e.res.headersSent||(e.respond=!1,S(e.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728"))}catch(n){if(e.res.headersSent){Ge.error("http",`${e.method} ${e.path} \u54CD\u5E94\u5DF2\u53D1\u51FA\u540E\u629B\u9519\uFF0C\u8FDE\u63A5\u4E2D\u65AD`,{method:e.method,path:e.path,code:F(n),reason:P(n),stack:Ve(n)}),e.res.writableEnded||e.res.end();return}if(e.respond=!1,Tn(n)){S(e.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728");return}let o=ee(n),i=F(n),a=P(n);o>=500?Ge.error("http",`${e.method} ${e.path} ${o} ${i}`,{method:e.method,path:e.path,status:o,code:i,reason:a,stack:Ve(n)}):Ge.warn("http",`${e.method} ${e.path} ${o} ${i}`,{method:e.method,path:e.path,status:o,code:i,reason:a}),S(e.res,o,i,a,$(n))}}}static getName(){return"aitableErrorMapping"}};s(te,"ErrorMappingMiddleware"),te=u([Dn()],te);import{Middleware as Rn,Inject as On}from"@midwayjs/core";import{enrichLogContext as In}from"aitable-workflow-core";var V=class{serverServices;resolve(){return async(e,r)=>{let{identityService:n}=this.serverServices;if(vt(e.path,e.method)){e.state.scope={},await r();return}let o=await n.resolveIdentity(e.req);if(e.state.identity=o,e.state.scope=o.actor,In({uid:o.machine?o.machine.ownerUserId??void 0:o.user?.openId??o.actor.actorId}),!o.authenticated){if(e.respond=!1,o.loginUrl){kn(e.req)?(e.res.writeHead(302,{location:o.loginUrl}),e.res.end()):(e.res.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.res.end(`${JSON.stringify({error:{code:"UNAUTHORIZED",message:"\u672A\u767B\u5F55",loginUrl:o.loginUrl}})}
|
|
4
|
+
`));return}xt(e.res);return}await r()}}static getName(){return"aitableIdentity"}};s(V,"IdentityMiddleware"),u([On()],V.prototype,"serverServices",2),V=u([Rn()],V);function kn(t){let e=(t.method??"").toUpperCase();if(e!=="GET"&&e!=="HEAD")return!1;let r=t.headers.accept??"";return(Array.isArray(r)?r.join(","):r).includes("text/html")}s(kn,"shouldRedirectBrowser");import{Middleware as bn,Inject as En}from"@midwayjs/core";var An=new Set(["import-zip"]);function _n(t){let r=/^\/api\/projects\/([^/?#]+)/.exec(t)?.[1];if(r&&!An.has(r))try{return decodeURIComponent(r)}catch{return r}}s(_n,"projectIdFromPath");var G=class{serverServices;resolve(){return async(e,r)=>{let n=_n(e.path);n&&!e.state.project&&(e.state.project=await this.serverServices.projectStore.projects.resolve(n,O(e))),await r()}}static getName(){return"aitableResolveProject"}};s(G,"ResolveProjectMiddleware"),u([En()],G.prototype,"serverServices",2),G=u([bn()],G);import{Middleware as Mn,Inject as Cn}from"@midwayjs/core";import Ke from"path";import{readFile as Fn,access as Wn}from"fs/promises";import{resolveInsideRoot as Nn}from"aitable-workflow-core";var Ln={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".ico":"image/x-icon",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json; charset=utf-8",".txt":"text/plain; charset=utf-8"};async function jt(t,e,r,n){let o=Ke.resolve(t),i=Ke.join(o,"index.html"),a=decodeURIComponent(e).replace(/^\/+/,""),c;try{c=a===""?i:Nn(o,a,{allowRoot:!1})}catch{c=i}try{await Wn(c)}catch{c=i}try{let d=await Fn(c),p=Ke.extname(c).toLowerCase(),w=Ln[p]??"application/octet-stream";if(n.writeHead(200,{"Content-Type":w,"Content-Length":d.byteLength}),r.method==="HEAD"){n.end();return}n.end(d)}catch{S(n,404,"WEB_NOT_BUILT","\u672C\u5730 web \u8D44\u6E90\u4E0D\u5B58\u5728\uFF08\u8BF7\u5148\u6784\u5EFA\u524D\u7AEF\u6216\u68C0\u67E5 --web-root\uFF09")}}s(jt,"serveStaticWeb");var K=class{serverServices;resolve(){return async(e,r)=>{let n=this.serverServices.webRoot,o=e.method.toUpperCase(),i=e.path;if(n&&(o==="GET"||o==="HEAD")&&!i.startsWith("/api/")&&i!=="/check.node"){e.respond=!1,await jt(n,i,e.req,e.res);return}await r()}}static getName(){return"aitableStaticWeb"}};s(K,"StaticWebMiddleware"),u([Cn()],K.prototype,"serverServices",2),K=u([Mn()],K);var re=class{app;async onReady(){this.app.useMiddleware([X,te,K,V,G])}};s(re,"ServerConfiguration"),u([Un()],re.prototype,"app",2),re=u([Bn({namespace:"aitableServer"})],re);import{Controller as $n,Get as ye,Inject as Dt}from"@midwayjs/core";import{detectAgents as qn}from"aitable-workflow-core";var M=class{ctx;serverServices;async health(){this.ctx.respond=!1,f(this.ctx.res,{ok:!0})}async checkNode(){this.ctx.respond=!1,Pt(this.ctx.res,"success")}async publicConfig(){let e=process.env.RELAY_PUBLIC_GATEWAY_URL?.trim();this.ctx.respond=!1,f(this.ctx.res,{authEnabled:this.serverServices.identityService.authRequired,...e?{relayGatewayUrl:e}:{}})}async agents(){this.ctx.respond=!1,f(this.ctx.res,qn())}async machines(){this.ctx.respond=!1,f(this.ctx.res,{machines:this.serverServices.execution.listMachines()??[]})}};s(M,"SystemController"),u([Dt()],M.prototype,"ctx",2),u([Dt()],M.prototype,"serverServices",2),u([ye("/api/health")],M.prototype,"health",1),u([ye("/check.node")],M.prototype,"checkNode",1),u([ye("/api/public-config")],M.prototype,"publicConfig",1),u([ye("/api/agents")],M.prototype,"agents",1),u([ye("/api/machines")],M.prototype,"machines",1),M=u([$n("/")],M);import ne from"path";import{Controller as Xo,Del as es,Get as ce,Inject as Dr,Patch as ct,Post as me,Put as Tr}from"@midwayjs/core";import{validateDesignArtifacts as ts,buildEnvSource as rs,loadWorkflowTemplate as Rr,loadSettings as Or}from"aitable-workflow-core";import{DwsClient as Tt,dwsPayload as Ye,findArrayPayload as Rt}from"aitable-workflow-core";function zn(t,e){let r={},n=s((o,i)=>{o&&i!==void 0&&(typeof i=="string"&&i.trim()===""||(r[o]=i))},"put");return n(t.name,e.name),n(t.type,e.type),n(t.owner,e.owner),n(t.runtime,e.runtime),n(t.online,e.online),n(t.visibility,e.visibility),n(t.enabled,e.enabled),n(t.description,e.description),r}s(zn,"buildRegistryCells");function Ot(t){let e=new Map;for(let r of Rt(t)){let n=r;n.fieldId&&n.fieldName&&e.set(n.fieldName,n.fieldId)}return e}s(Ot,"fieldIdByName");function Jn(t,e){let r={};for(let[n,o]of Object.entries(t)){let i=e.get(n);i&&(r[i]=o)}return r}s(Jn,"translateCellsToIds");async function It(t){let{registry:e,input:r}=t,n=t.dws??new Tt({bin:"dws"}),o=await n.runJson(["aitable","field","list","--base-id",e.base_id,"--table-id",e.table_id]),i=Ot(Ye(o)),a=Jn(zn(e.fields,r),i);if(Object.keys(a).length===0)throw new Error("\u767B\u8BB0\u8868\u5217\u540D\u4E0E identity.registry.fields \u4E0D\u5339\u914D\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u5355\u5143\u683C");let c=await n.runJson(["aitable","record","create","--base-id",e.base_id,"--table-id",e.table_id,"--records",JSON.stringify([{cells:a}]),"--yes"]),p=Ye(c)?.newRecordIds?.[0];if(!p)throw new Error("dws \u672A\u8FD4\u56DE\u65B0\u884C recordId");return{recordId:p}}s(It,"createRegistryAgent");function Ze(t){if(t==null)return;if(typeof t=="boolean"||typeof t=="string")return t;if(typeof t=="number")return String(t);if(Array.isArray(t))return t.map(n=>Ze(n)).filter(n=>n!==void 0).map(String).join("\u3001");let e=t,r=e.name??e.text??e.value;if(r!==void 0)return Ze(r)}s(Ze,"cellToScalar");function se(t,e,r){if(!r)return;let n=e.get(r);if(n)return Ze(t[n])}s(se,"readColumn");async function kt(t){let{registry:e}=t,r=t.dws??new Tt({bin:"dws"}),n=await r.runJson(["aitable","field","list","--base-id",e.base_id,"--table-id",e.table_id]),o=Ot(Ye(n)),i=await r.runJson(["aitable","record","list","--base-id",e.base_id,"--table-id",e.table_id]),a=[];for(let c of Rt(i)){let d=c;if(!d.recordId||!d.cells)continue;let p=d.cells,w=se(p,o,e.fields.enabled);a.push({recordId:d.recordId,name:String(se(p,o,e.fields.name)??""),type:se(p,o,e.fields.type),owner:se(p,o,e.fields.owner),runtime:se(p,o,e.fields.runtime),online:se(p,o,e.fields.online),visibility:se(p,o,e.fields.visibility),enabled:typeof w=="boolean"?w:w===void 0?void 0:!!w,description:se(p,o,e.fields.description)})}return a}s(kt,"listRegistryAgents");import{isTerminalPhase as Vn,logger as Gn}from"aitable-workflow-core";var Se=new Set,ie=new Map,Hn=8,ue=new Map;function bt(t){let e=ie.get(t);if(e)return{buffer:e.buffer,live:!0};let r=ue.get(t);return r?{buffer:r,live:!1}:null}s(bt,"retainedDesignBuffer");function Qe(t,e,r){t.write(`id: ${e}
|
|
5
5
|
`),t.write(`event: ${r.type}
|
|
6
6
|
`),t.write(`data: ${JSON.stringify(r)}
|
|
7
7
|
|
|
8
|
-
`)}
|
|
9
|
-
`,"utf8")}
|
|
10
|
-
`,"utf8")}n(Te,"writeProjectMeta");function Mt(t){return t==="views.yml"||t.endsWith("/views.yml")}n(Mt,"isLegacyViewsPath");async function Oe(t,e=t){let r=await Ye(e,{withFileTypes:!0}).catch(()=>[]);await Promise.all(r.map(async o=>{if(o.name==="node_modules"||o.name==="runtime"||o.name==="traces")return;let s=P.join(e,o.name);if(o.isDirectory()){await Oe(t,s);return}if(!o.isFile())return;let i=P.relative(t,s).split(P.sep).join("/");Mt(i)&&await Ze(s,{force:!0})}))}n(Oe,"removeLegacyViewsFiles");async function Ct(t,e,r){let o=await Ye(e,{withFileTypes:!0}).catch(()=>[]);for(let s of o){if(Lo(t,P.join(e,s.name),s.name))continue;let i=P.join(e,s.name);if(s.isDirectory()){await Ct(t,i,r);continue}if(!s.isFile()||!Fo.test(s.name))continue;let a=P.relative(t,i).split(P.sep).join("/");if(Mt(a))continue;let c=await Qe(i,"utf8").catch(()=>"");r.push({path:a,content:c})}}n(Ct,"walk");function Lo(t,e,r){return r==="node_modules"||r==="traces"||r==="runtime"||r===".aitable"||r==="project.json"?!0:P.relative(t,e).split(P.sep).join("/").startsWith(".aitable/")}n(Lo,"isHiddenProjectFile");function K(t,e,r){if(e==="design"){let o=te.get(t);return o?{sessionLocal:!0,cursor:o.buffer.cursor}:{sessionLocal:!1}}return e==="run"?{sessionLocal:r.hasRunSession(t)}:{sessionLocal:!1}}n(K,"stageFactsFor");function Bt(t,e){return Uo(t,(r,o)=>Bo({projectId:t.projectId,stage:r,state:o.state,facts:K(t.projectId,r,e)}))}n(Bt,"decorateProjectState");async function ke(t,e){let r=await t.projectStore.instances.getRecoverableState(e),o=await Go(t,e,r),s={hasRunSession:n(c=>t.runtime.runSessions.has(c),"hasRunSession")},i=t.execution.runScheduler;if(!i)return Bt(o,s);let a=await i.getStatus(e.id).catch(()=>null);return Bt(a?Jo(o,a):o,s)}n(ke,"readProjectState");async function Go(t,e,r){if(r.stages.init||!await Promise.all([$t(L(e)),$t(Ho.join(e.dir,"workflow.yml"))]).then(a=>a.some(Boolean)))return r;let s=new Date().toISOString(),i=$o("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:i})}n(Go,"backfillImportedInit");function Jo(t,e){let r=Mo(e),o=t.stages.run;if(!o&&r.phase==="stopped")return t;let s=new Date().toISOString();return Co(t,"run",{identity:o?.identity??{id:`run_relay_${t.projectId}`,projectId:t.projectId,stage:"run",attempt:1,startedAt:e.lastHeartbeatAt??s,updatedAt:s},state:r})}n(Jo,"injectRelayRunState");function $t(t){return qo(t).then(()=>!0,()=>!1)}n($t,"fileExists");function Ut(t,e=1){let r=t.replace(/\s+/g," ").trim();if(!r)return`\u5DE5\u4F5C\u6D41 #${e}`;let o=r.split(/[。.!!?\n]/u)[0]?.split(/[::,,;;]/u)[0]?.trim();return o?o.length>16?o.slice(0,16):o:`\u5DE5\u4F5C\u6D41 #${e}`}n(Ut,"deriveProjectTitleFromSop");async function Ht(t,e,r,o,s,i){let a=await k(e,t),c=await I(o),p=await z.open({project:a,stage:"init",store:r,driver:"init.http",facts:n(()=>K(a.id,"init",{hasRunSession:n(()=>!1,"hasRunSession")}),"facts")});await p.advance({phase:"configuring"});try{let d=Xo(c),w=await Yo({answers:d,cwd:a.dir,force:!0}),f=await Qo(Re.join(a.dir,"profile","profile.yml"),c.roles??[]);c.machineId&&i&&await i(t,c.machineId).catch(()=>{});let l=await _(a),v=f.skippedKnowledgeBindings.map(oe=>`\u89D2\u8272 ${oe.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 profile\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${oe.knowledge.join(", ")}`);await p.advance({phase:"ready",warnings:v,roleFiles:[]});let M=Ut(c.sop,1),b=await ce(l,{title:M});m(s,{project:b,scaffold:w,roleFiles:[],files:await D(l),warnings:v})}catch(d){throw await p.advance({phase:"failed",error:{code:W(d),message:j(d),retryable:!0,details:C(d)}}),d}}n(Ht,"handleInit");async function Gt(t,e,r,o){let s=await k(e.workspace,t),a=(await I(r)).tableId?.trim()??"";if(!a)throw Object.assign(new Error("Table Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"TABLE_ID_REQUIRED",status:422});let c=L(s),p=await qt(c,"utf8"),d=tt.parse(p);if(!pe(d)||!pe(d.tracker)){let f=pe(d)&&pe(d.workflows);throw Object.assign(new Error(f?"\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:f?"TABLE_ID_PER_WORKFLOW":"CONFIG_TRACKER_MISSING",status:f?422:500})}d.tracker.table_id=a,await zo(c,tt.stringify(d),"utf8");let w=await _(s);m(o,{project:w,files:await D(w),state:await ke(e,w)})}n(Gt,"handleUpdateProjectTableId");async function Jt(t,e,r,o,s,i,a){let c=await k(e,t),p=await I(i);if(p.action!=="confirm"&&p.action!=="terminate")throw Object.assign(new Error("\u4EBA\u5DE5\u64CD\u4F5C\u53EA\u652F\u6301 confirm \u6216 terminate"),{code:"INVALID_HUMAN_ACTION",status:422});let d=o.runSessions.get(t)?.app;if(!d)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=p.action==="confirm"?d.settings.tracker.states.active[0]:d.settings.tracker.states.terminal.find(M=>M==="\u5DF2\u5173\u95ED")??d.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 f=p.action==="confirm"?"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EE7\u7EED\u6D41\u7A0B":"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EC8\u6B62\u6D41\u7A0B",l=null;p.action==="confirm"&&(l=await Zo(d,s)),await d.tracker.updateState(s,w),l&&await d.tracker.updateCurrentStep(s,l),await d.tracker.appendEvent(s,f);let v=await r.updateRunSnapshotRecord(c,s,p.action==="confirm"?{state:w,status:"running",currentStepId:l??void 0}:{state:w,status:"done",currentStepId:null},f);m(a,{action:p.action,recordId:s,state:v})}n(Jt,"handleRunHumanAction");async function Zo(t,e){let[r]=await t.tracker.fetchItemsByIds([e]).catch(()=>[]),o=r?.currentStep;if(!o)return null;let s=t.workflow.orderedStepIds.indexOf(o);return s<0?null:t.workflow.orderedStepIds[s+1]??null}n(Zo,"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:ts(t.agentsSelected),scene:es(t),baseId:e,llmProvider:r,llmModel:r?t.llmModel.trim()||rs(r):"",llmApiKeyEnv:r?os(r):"",confirmed:!0}}n(Xo,"toInitAnswers");function es(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"}n(es,"buildScene");function ts(t){return t.includes("qwenwork")?"qwenwork":t.includes("qoder")?"qoder":t.includes("codex")?"codex":"claudecode"}n(ts,"toAgentType");function rs(t){return t==="openai"?"gpt-4o":t==="anthropic"?"claude-sonnet-4-20250514":t==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}n(rs,"defaultModel");function os(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"}n(os,"defaultApiKeyEnv");async function zt(t,e){let r=Re.join(t.dir,"aitable-workflow.config.yml");try{await Ko(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 ss(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")}n(zt,"augmentProjectFileValidation");async function ss(t){try{let r=tt.parse(await qt(Re.join(t,"profile","profile.yml"),"utf8"));if(pe(r)&&pe(r.roles)&&Object.keys(r.roles).length>0)return!0}catch{}return(await Vo(Re.join(t,"roles")).catch(()=>[])).some(r=>r.endsWith(".role.yml")||r.endsWith(".role.yaml"))}n(ss,"hasAnyRoleDefinition");import Kt from"fs";import ns from"path";var is=/requiresAgent\s*:\s*(true|false)/,Vt=new Map;function Yt(t,e){if(!e)return!1;for(let r of[".recipe.ts",".recipe.js"]){let o=ns.join(t,`${e}${r}`);try{let s=Kt.statSync(o);if(!s.isFile())continue;let i=`${s.mtimeMs}:${s.size}`,a=Vt.get(o);if(a?.signature===i)return a.requiresAgent;let p=Kt.readFileSync(o,"utf8").match(is),d=p?p[1]==="true":!1;return Vt.set(o,{signature:i,requiresAgent:d}),d}catch(s){if(s.code==="ENOENT")continue;return!1}}return!1}n(Yt,"readRecipeRequiresAgent");import{rm as Zt,mkdir as as,writeFile as cs}from"fs/promises";import Se from"path";import ps from"yaml";import{isRecord as ds,resolveInsideRoot as us}from"aitable-workflow-core";var Qt=/\.(json|ya?ml|ts|js|md|txt)$/i,ls=new Set(["runtime","traces","node_modules"]),Xt="aitable-workflow.config.yml";function er(t,e){try{us(t,e,{allowRoot:!1})}catch{throw Object.assign(new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u76EE\u5F55: ${e}`),{code:"invalid_path",status:400})}}n(er,"assertSafeRelativePath");function rt(t,e){er(t.dir,e)}n(rt,"assertSafeProjectPath");function Ua(t){er("/workflow-root",t)}n(Ua,"assertSafeWorkflowPath");function tr(t){let r=ot(t).split("/")[0]??"";return ls.has(r)}n(tr,"isForbiddenWritable");function rr(t){if(sr(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(tr(t))throw Object.assign(new Error(`\u7981\u6B62\u5199\u5165\u53D7\u4FDD\u62A4\u76EE\u5F55: ${t}`),{code:"invalid_path",status:400});if(!Qt.test(t))throw Object.assign(new Error(`\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8\u5199\u5165: ${t}\uFF08\u4EC5\u5141\u8BB8 ${Qt.source}\uFF09`),{code:"invalid_path",status:400})}n(rr,"assertWritableKind");function or(t){let e=ot(t);return e===Xt||e.endsWith(".config.yml")?"config":e==="workflow.yml"?"workflow":e.startsWith("recipes/")?"recipe":e.startsWith("roles/")?"role":"other"}n(or,"kindOf");function sr(t){let e=ot(t);return e==="views.yml"||e.endsWith("/views.yml")}n(sr,"isLegacyViewsPath");function ot(t){return Se.posix.normalize(t.replace(/\\/g,"/")).replace(/^\.\//,"")}n(ot,"normalizeLogicalPath");function fs(t){let e=[],r;try{r=ps.parse(t)}catch(s){return e.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),e}if(!ds(r))return e.push("aitable-workflow.config.yml \u9876\u5C42\u5E94\u4E3A\u5BF9\u8C61"),e;let o=r.scene;return(typeof o!="string"||o.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}n(fs,"validateConfigScene");async function Ie(t,e){let r=[],o=[];for(let s of e){rt(t,s.path),rr(s.path);let i=Se.join(t.dir,s.path);await as(Se.dirname(i),{recursive:!0}),await cs(i,s.content,"utf8"),r.push({path:s.path,content:s.content}),s.path===Xt&&o.push(...fs(s.content))}return{written:r,warnings:o}}n(Ie,"writeProjectFiles");async function nr(t,e){for(let r of e){if(rt(t,r),tr(r))throw Object.assign(new Error(`\u7981\u6B62\u5220\u9664\u53D7\u4FDD\u62A4\u76EE\u5F55: ${r}`),{code:"invalid_path",status:400});await Zt(Se.join(t.dir,r),{force:!0})}}n(nr,"removeProjectFiles");async function ir(t,e){for(let o of e)rt(t,o.path),rr(o.path);let r=await ms(t);for(let o of r)await Zt(Se.join(t.dir,o),{force:!0}).catch(()=>{});return await Oe(t.dir),Ie(t,e)}n(ir,"replaceProjectFiles");async function ms(t){return(await D(t)).map(r=>r.path).filter(r=>or(r)!=="other"||sr(r))}n(ms,"collectBusinessFiles");function gs(t){return he(t.content)}n(gs,"checksumFile");async function ar(t){let e=await D(t),r=e.map(o=>({path:o.path,sha256:gs(o)}));return{project:t,files:e,checksums:r,exportedAt:new Date().toISOString()}}n(ar,"buildProjectExport");var ws="coding-agents.config.json";function cr(t){let e=[],r=t.files,o=t.checksums,s=r.findIndex(i=>i.path===ws);if(s>=0){let i=r[s],a=i.content;try{let c=JSON.parse(i.content);if(c&&typeof c=="object"&&!Array.isArray(c)){let p=c.agents;if(p&&typeof p=="object"&&!Array.isArray(p)){let d=!1;for(let w of Object.keys(p)){let f=p[w];if(!f||typeof f!="object"||Array.isArray(f))continue;let l=f.env;if(l&&typeof l=="object"&&!Array.isArray(l)){let v=l;if(Object.values(v).some(b=>typeof b=="string"&&b!=="")){for(let b of Object.keys(v))v[b]="";d=!0}}}d&&(a=JSON.stringify(c,null,2)+`
|
|
11
|
-
`)}}}catch{}if(a!==i.content){let c={path:i.path,content:a};r=r.map((d,w)=>w===s?c:d);let p=he(a);o=o.map((d,w)=>w===s?{path:d.path,sha256:p}:d),e.push(i.path)}}return{...t,files:r,checksums:o,redacted:e.length>0?e:t.redacted}}n(cr,"redactExportBundle");var y=class{ctx;serverServices;async list(){let e=await this.serverServices.projectStore.projects.list(O(this.ctx));this.ctx.respond=!1,m(this.ctx.res,{projects:e})}async create(){let e=this.serverServices,r=O(this.ctx),o=await I(this.ctx.req),s=await e.projectStore.projects.create(r,{title:o.title,files:o.files});await T(s,e);let i={project:s};s.files&&(i.files=s.files),s.warnings&&s.warnings.length>0&&(i.warnings=s.warnings),this.ctx.respond=!1,m(this.ctx.res,i)}async remove(){let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project;if(this.ctx.respond=!1,e.runtime.runSessions.has(o.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(o,r),await xe(o),await xt(e,o.id),m(this.ctx.res,{ok:!0,id:o.id})}async updateMeta(){let e=this.serverServices,r=O(this.ctx),o=await I(this.ctx.req),s=await e.projectStore.projects.updateMeta(this.ctx.state.project,{title:o.title},r);this.ctx.respond=!1,m(this.ctx.res,{project:s})}async init(){let e=this.serverServices,r=this.ctx.state.project;this.ctx.respond=!1,await T(r,e);let o=e.execution;await Ht(r.id,e.workspace,e.projectStore.instances,this.ctx.req,this.ctx.res,(s,i)=>o.bindProjectMachine(s,i)),await we(e,r,"init")}async getEngine(){let e=this.ctx.state.project,r=this.serverServices.execution,o=await r.getProjectMachine(e.id);if(this.ctx.respond=!1,!o){m(this.ctx.res,{machineId:null,machine:null,status:"unbound"});return}let s=r.isMachineOnline(o),a=(r.listMachines()??[]).find(c=>c.machineId===o);m(this.ctx.res,{machineId:o,machine:a??null,status:s?"online":"offline"})}async bindEngine(){let e=await I(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),m(this.ctx.res,{ok:!0,machineId:e.machineId})}async listFiles(){let e=this.ctx.state.project,r=await D(e);this.ctx.respond=!1,m(this.ctx.res,{project:e,files:r})}async replaceFiles(){let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project,s=await I(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 i=await e.projectStore.projects.replaceFiles(o,s.files,r),a=await T(o,e);m(this.ctx.res,{project:a.project,files:i})}async patchFiles(){let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project,s=await I(this.ctx.req),i=await e.projectStore.projects.updateFiles(o,{upsert:s.upsert,remove:s.remove},r),a=await T(o,e);this.ctx.respond=!1,m(this.ctx.res,{project:a.project,files:i})}async exportProject(){let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project,s=await e.projectStore.projects.exportProject(o,r),i=cr(s),a=e.projectStore.workflows;if(a){let c=await Promise.all((await a.list(o.id,r)).map(async p=>{let d=await a.exportWorkflow(o.id,p.id,r);return{workflow:d.workflow,files:d.files}}));this.ctx.respond=!1,m(this.ctx.res,{...i,workflows:c});return}this.ctx.respond=!1,m(this.ctx.res,i)}async validate(){let e=this.ctx.state.project,r=await ys({workDir:e.dir,configPath:Z.join(e.dir,"aitable-workflow.config.yml"),workflows:[],workflowPath:Z.join(e.dir,"workflow.yml"),recipeDir:Z.join(e.dir,"recipes")});await zt(e,r),this.ctx.respond=!1,m(this.ctx.res,r)}async getWorkflow(){let e=this.ctx.state.project,r=await vs(e.dir),o=await Ps(e,this.serverServices.projectStore.workflows,je(this.ctx.query?.workflowId),O(this.ctx)),s=await ur(o,{envSource:r}).catch(()=>ur(o)),i=Z.join(Z.dirname(o),"recipes"),a=s.steps.map(c=>({...c,requires_agent:c.recipe?Yt(i,c.recipe):!!c.prompt}));this.ctx.respond=!1,m(this.ctx.res,{workflow:{...s,steps:a}})}async resetWorkflow(){let e=await At(this.ctx.state.project),r=await D(e);this.ctx.respond=!1,m(this.ctx.res,{project:e,files:r})}async getState(){let e=this.serverServices,r=this.ctx.state.project,o=await ke(e,r);this.ctx.respond=!1,m(this.ctx.res,o)}async updateTableId(){let e=this.serverServices;this.ctx.respond=!1,await Gt(this.ctx.state.project.id,e,this.ctx.req,this.ctx.res)}};n(y,"ProjectsController"),u([pr()],y.prototype,"ctx",2),u([pr()],y.prototype,"serverServices",2),u([de("/")],y.prototype,"list",1),u([be("/")],y.prototype,"create",1),u([Ss("/:projectId")],y.prototype,"remove",1),u([st("/:projectId")],y.prototype,"updateMeta",1),u([be("/:projectId/init")],y.prototype,"init",1),u([de("/:projectId/engine")],y.prototype,"getEngine",1),u([dr("/:projectId/engine")],y.prototype,"bindEngine",1),u([de("/:projectId/files")],y.prototype,"listFiles",1),u([dr("/:projectId/files")],y.prototype,"replaceFiles",1),u([st("/:projectId/files")],y.prototype,"patchFiles",1),u([de("/:projectId/export")],y.prototype,"exportProject",1),u([be("/:projectId/validate")],y.prototype,"validate",1),u([de("/:projectId/workflow")],y.prototype,"getWorkflow",1),u([be("/:projectId/reset-workflow")],y.prototype,"resetWorkflow",1),u([de("/:projectId/state")],y.prototype,"getState",1),u([st("/:projectId/table-id")],y.prototype,"updateTableId",1),y=u([hs("/api/projects")],y);async function Ps(t,e,r,o){let s=r&&/^[A-Za-z0-9_-]+$/.test(r)?r:null;if(s&&e){let c=await e.resolve(t.id,s,o);return Z.join(t.dir,c.templatePath)}let i=await D(t);if(s){let c=`workflows/${s}/workflow.yml`;if(i.some(p=>p.path===c))return Z.join(t.dir,c)}if(i.some(c=>c.path==="workflow.yml"))return Z.join(t.dir,"workflow.yml");let a=i.find(c=>/^workflows\/[^/]+\/workflow\.ya?ml$/.test(c.path));return Z.join(t.dir,a?.path??"workflow.yml")}n(Ps,"resolvePreviewWorkflowPath");import js from"path";import{Controller as Ds,Del as xs,Get as lr,Inject as fr,Patch as Ts,Post as Os,Put as ks}from"@midwayjs/core";import{loadWorkflowTemplate as Rs}from"aitable-workflow-core";var A=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,m(this.ctx.res,{workflows:await Is(r)});return}let o=O(this.ctx);this.ctx.respond=!1,m(this.ctx.res,{workflows:await e.projectStore.workflows.list(r.id,o)})}async create(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project,s=await I(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 i=await e.projectStore.workflows.create(o.id,{name:s.name,templatePath:s.templatePath,files:s.files},r);await T(o,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,m(this.ctx.res,a)}async get(){let e=this.serverServices,r=this.ctx.state.project,o=this.ctx.params.workflowId??"";if(!e.projectStore.workflows){let a=await bs(r,o);if(this.ctx.respond=!1,!a){S(this.ctx.res,404,"WORKFLOW_NOT_FOUND","\u5DE5\u4F5C\u6D41\u4E0D\u5B58\u5728");return}m(this.ctx.res,a);return}let s=O(this.ctx),i=await e.projectStore.workflows.exportWorkflow(r.id,o,s);this.ctx.respond=!1,m(this.ctx.res,{workflow:i.workflow,files:i.files})}async remove(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project;if(e.runtime.runSessions.has(o.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(o.id,this.ctx.params.workflowId??"",r);await e.projectStore.workflows.delete(s,r),await T(o,e),this.ctx.respond=!1,m(this.ctx.res,{ok:!0,id:s.id})}async replaceFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project,s=await e.projectStore.workflows.resolve(o.id,this.ctx.params.workflowId??"",r),i=await I(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(s,i.files,r);await T(o,e),this.ctx.respond=!1,m(this.ctx.res,{workflow:s,files:a})}async updateFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),o=this.ctx.state.project,s=await e.projectStore.workflows.resolve(o.id,this.ctx.params.workflowId??"",r),i=await I(this.ctx.req),a=await e.projectStore.workflows.updateFiles(s,{upsert:i.upsert,remove:i.remove},r);await T(o,e),this.ctx.respond=!1,m(this.ctx.res,{workflow:s,files:a})}};n(A,"WorkflowsController"),u([fr()],A.prototype,"ctx",2),u([fr()],A.prototype,"serverServices",2),u([lr("/:projectId/workflows")],A.prototype,"list",1),u([Os("/:projectId/workflows")],A.prototype,"create",1),u([lr("/:projectId/workflows/:workflowId")],A.prototype,"get",1),u([xs("/:projectId/workflows/:workflowId")],A.prototype,"remove",1),u([ks("/:projectId/workflows/:workflowId/files")],A.prototype,"replaceFiles",1),u([Ts("/:projectId/workflows/:workflowId/files")],A.prototype,"updateFiles",1),A=u([Ds("/api/projects")],A);async function Is(t){let e=await D(t),r=mr(e);return(await Promise.all(r.map(s=>Sr(t,s,e)))).sort((s,i)=>s.name.localeCompare(i.name))}n(Is,"listLocalWorkflows");async function bs(t,e){let r=await D(t),o=mr(r).find(c=>gr(c)===e);if(!o)return null;let s=await Sr(t,o,r),i=wr(o),a=r.filter(c=>hr(c.path,o)).map(c=>({...c,path:c.path.slice(i.length)}));return{workflow:s,files:a}}n(bs,"exportLocalWorkflow");function mr(t){return t.map(e=>e.path).filter(e=>e==="workflow.yml"||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(e))}n(mr,"localWorkflowTemplatePaths");function gr(t){return t==="workflow.yml"?"main":t.split("/")[1]??"main"}n(gr,"localWorkflowId");function wr(t){return t==="workflow.yml"?"":t.replace(/workflow\.ya?ml$/,"")}n(wr,"workflowBase");function hr(t,e){let r=wr(e);return r?t.startsWith(r):t==="workflow.yml"||t.startsWith("recipes/")}n(hr,"belongsToWorkflow");async function Sr(t,e,r){let o=gr(e),s=await Rs(js.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=>hr(a.path,e)).length;return{id:o,projectId:t.id,name:s?.meta.name??o,domain:s?.meta.domain,templatePath:e,tableId:s?.tracker?.table_id,fileCount:i,createdAt:t.createdAt,updatedAt:t.updatedAt}}n(Sr,"buildLocalWorkflow");import{Controller as Pn,Get as dt,Inject as Nr,Post as re}from"@midwayjs/core";import{logger as yr}from"aitable-workflow-core";function Pr(t){return{appFactory:t,runSessions:new Map}}n(Pr,"createServerRuntime");async function jr(t,e,r,o,s,i){let a=await k(e,t),c=o.runSessions.get(t);if(c){vr(c,s,i);return}let p=await z.open({project:a,stage:"run",store:r,driver:"run.local",facts:n(()=>K(a.id,"run",{hasRunSession:n(f=>o.runSessions.has(f),"hasRunSession")}),"facts")}),d=p.state;if(d?.phase==="starting"||d?.phase==="listening"){let f="\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",l=await p.advance({phase:"failed",error:{code:"RUN_SESSION_LOST",message:f,retryable:!0}});i(s,"stage.changed",{type:"stage.changed",stage:"run",stageState:l}),i(s,"error",{type:"error",error:{code:"RUN_SESSION_LOST",message:f}}),s.end();return}let w={taskId:"",subscribers:new Set,events:[],app:null,snapshotWrite:Promise.resolve()};o.runSessions.set(t,w),vr(w,s,i),As(a,p,w,o,r,i)}n(jr,"handleRunRuntime");async function As(t,e,r,o,s,i){let a=n(c=>{Ws(r,c,i),Fs(c)&&(yr.info("run-runtime","publish run execution event",_s(c)),r.snapshotWrite=r.snapshotWrite.then(()=>s.appendRunSnapshotEvent(t,c)).catch(p=>{yr.error("run-runtime","\u5199\u5165\u8FD0\u884C\u5FEB\u7167\u5931\u8D25",{projectId:t.id,event:c.type,error:p instanceof Error?p.message:String(p)})}))},"send");e.emit=c=>a({type:"stage.changed",stage:"run",stageState:c});try{await e.advance({phase:"starting"}),r.taskId=e.taskId??"";let c=await o.appFactory(L(t),p=>a(Es(p)));r.app=c,await e.advance({phase:"listening",workflowName:c.workflow.meta.name,stepCount:c.workflow.orderedStepIds.length,intervalMs:c.settings.polling.interval_ms}),await c.start(),await e.advance({phase:"stopped",reason:"user"})}catch(c){await e.advance({phase:"failed",error:{code:Dr(c),message:xr(c),retryable:!0,details:Tr(c)}}),a({type:"error",error:Ls(c)})}finally{o.runSessions.delete(t.id),Ns(r)}}n(As,"startRunSession");function Es(t){switch(t.type){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}}}n(Es,"toRunEventDTO");function Fs(t){return t.type.startsWith("run.record.")||t.type.startsWith("run.step.")}n(Fs,"isRunExecutionEvent");function _s(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}}n(_s,"summarizeRunExecutionEvent");function vr(t,e,r){t.subscribers.add(e);for(let o of t.events)r(e,o.type,o);e.on("close",()=>{t.subscribers.delete(e)})}n(vr,"attachRunSubscriber");function Ws(t,e,r){t.events.push(e),t.events.length>100&&t.events.shift();for(let o of t.subscribers){if(o.destroyed||o.writableEnded){t.subscribers.delete(o);continue}try{r(o,e.type,e)}catch{t.subscribers.delete(o)}}}n(Ws,"publishRunEvent");function Ns(t){for(let e of t.subscribers)e.end();t.subscribers.clear()}n(Ns,"closeRunSubscribers");function Ls(t){return{code:Dr(t),message:xr(t),details:Tr(t)}}n(Ls,"apiError");function Dr(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}n(Dr,"errorCode");function xr(t){return t instanceof Error?t.message:String(t)}n(xr,"errorMessage");function Tr(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}n(Tr,"errorDetails");function Ms(){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}n(Ms,"readSseHeartbeatMs");function ne(t){t.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),Cs(t)}n(ne,"startSse");function Cs(t){let e=Ms(),r=setInterval(()=>{if(t.writableEnded||!t.writable){clearInterval(r);return}try{t.write(`:keepalive
|
|
8
|
+
`)}s(Qe,"writeDesignSse");function Et(t,e){let r=t.buffer.push(e);for(let n of t.subscribers){if(n.destroyed||n.writableEnded){t.subscribers.delete(n);continue}try{Qe(n,r.seq,e)}catch{t.subscribers.delete(n)}}}s(Et,"publishDesignEvent");function At(t){Se.delete(t);let e=ie.get(t);if(ie.delete(t),!!e){for(ue.delete(t),ue.set(t,e.buffer);ue.size>Hn;){let r=ue.keys().next();if(r.done)break;ue.delete(r.value)}for(let r of e.subscribers)if(!r.writableEnded)try{r.end()}catch{}e.subscribers.clear()}}s(At,"closeDesignSession");function _t(t,e){let r=t.searchParams.get("cursor")??St(e.headers["last-event-id"]);if(r==null||r==="")return;let n=Number(r);return Number.isFinite(n)?n:void 0}s(_t,"parseReconnectCursor");function Kn(t,e){return t.runtime.runSessions.has(e)||Se.has(e)}s(Kn,"isStageActiveFor");function T(t,e){return e.projectStore.prepareWorkdir(t,{isStageActive:s(()=>Kn(e,t.id),"isStageActive")})}s(T,"prepareWorkdirGuarded");async function ve(t,e,r){try{let o=(await t.projectStore.instances.getState(e)).stages[r];if(!o||!Vn(r,o.state))return;await t.projectStore.commitWorkdir(e,{stage:r})}catch(n){Gn.warn("stage-sync","stage \u6D41\u56DE\u5199\u6743\u5A01\u6E90\u5931\u8D25",{projectId:e.id,stage:r,error:P(n)})}}s(ve,"commitStageOnTerminal");async function Ft(t,e){await t.projectStore.cascadeDelete(e).catch(()=>{}),await t.execution.unbindProjectMachine(e).catch(()=>{})}s(Ft,"cascadeDeleteProject");import be from"path";import{readFile as Xt,writeFile as wo,access as ho,readdir as yo}from"fs/promises";import st from"yaml";import{scaffold as So,writeProfileRoles as vo,isRecord as fe}from"aitable-workflow-core";import{isTerminalPhase as Wt,nextFor as Yn,transition as Zn}from"aitable-workflow-core";var Y=class t{constructor(e,r){this.options=e;this.currentState=r?.state??null,this.identity=r?.identity??null,this.diagnostics=r?.diagnostics}options;static{s(this,"StageWriter")}currentState;identity;diagnostics;tail=Promise.resolve();emit;static async open(e){let n=(await e.store.getState(e.project)).stages[e.stage];return new t(e,n??null)}get state(){return this.currentState}get taskId(){return this.identity?.id??null}get attempt(){return this.identity?.attempt??0}get startedAt(){return this.identity?.startedAt??null}setDiagnostics(e){this.diagnostics=e}advance(e){let r=this.tail.then(()=>this.write(e),()=>this.write(e));return this.tail=r.then(()=>{},()=>{}),r}advanceDetached(e,r){this.advance(e).catch(r)}async write(e){let{project:r,stage:n,store:o,driver:i}=this.options,a=Zn(n,this.currentState,e,i);if(a===this.currentState&&this.identity)return this.decorate({identity:this.identity,state:a,...this.diagnostics?{diagnostics:this.diagnostics}:{}});let c=!this.identity||this.currentState!==null&&Wt(n,this.currentState),d=new Date().toISOString(),p=c?await o.createStageIdentity(r,n):{...this.identity,updatedAt:d},m={identity:Wt(n,a)?{...p,completedAt:p.completedAt??d}:p,state:a,...this.diagnostics?{diagnostics:this.diagnostics}:{}};return await o.putStageState(r,n,m),this.currentState=a,this.identity=m.identity,this.decorate(m)}decorate(e){let{project:r,stage:n}=this.options,o={...e,next:Yn({projectId:r.id,stage:n,state:e.state,facts:this.options.facts()})};return this.emit?.(o),o}};import{deriveRelayRunState as io,mergeStageIntoState as ao,nextFor as co,transition as po,withStageNext as uo}from"aitable-workflow-core";import{access as lo}from"fs/promises";import fo from"path";import{createHash as Qn,randomUUID as Xn}from"crypto";import{mkdir as Xe,readdir as et,readFile as tt,rm as rt,stat as Nt,writeFile as Lt}from"fs/promises";import x from"path";var eo=x.resolve(process.cwd(),".sandbox","aitable-workflow-server"),Mt=/^[a-zA-Z0-9_-]+$/,to=/\.(json|ya?ml|ts|js|md|txt)$/i,ro=["workflow.yml","recipes","traces"];function Ct(t={}){let e=x.resolve(t.dataRoot??process.env.AITABLE_WORKFLOW_DATA_DIR??eo);return{dataRoot:e,projectsRoot:x.join(e,"projects")}}s(Ct,"createWorkspace");async function Bt(t){await Xe(t.projectsRoot,{recursive:!0});let e=new Date().toISOString(),r=(await nt(t)).length+1,n={id:`wf_${Xn().slice(0,8)}`,title:`\u5DE5\u4F5C\u6D41 #${r}`,dir:"",createdAt:e,updatedAt:e};return n.dir=Ht(t,n.id),await Xe(n.dir,{recursive:!0}),await Oe(n),n}s(Bt,"createProject");async function le(t,e){let r=await b({dataRoot:x.dirname(x.dirname(t.dir)),projectsRoot:x.dirname(t.dir)},t.id),n={...r,...e,title:e.title?.trim()||r.title,updatedAt:new Date().toISOString()};return await Oe(n),n}s(le,"updateProjectMeta");async function nt(t){let e=await et(t.projectsRoot,{withFileTypes:!0}).catch(()=>[]);return(await Promise.all(e.filter(n=>n.isDirectory()&&Mt.test(n.name)).map(n=>b(t,n.name).catch(()=>null)))).filter(n=>n!==null).sort((n,o)=>o.updatedAt.localeCompare(n.updatedAt))}s(nt,"listProjects");async function b(t,e){Vt(e);let r=Ht(t,e);if(!(await Nt(r).catch(()=>null))?.isDirectory())throw Object.assign(new Error(`\u9879\u76EE\u4E0D\u5B58\u5728: ${e}`),{code:"PROJECT_NOT_FOUND",status:404});let o=x.join(r,"project.json"),i=await tt(o,"utf8").catch(()=>"");if(!i){let c=new Date().toISOString(),d={id:e,dir:r,createdAt:c,updatedAt:c};return await Oe(d),d}return{...JSON.parse(i),dir:r}}s(b,"resolveProject");async function C(t){let e={...t,updatedAt:new Date().toISOString()};return await Oe(e),e}s(C,"touchProject");async function Ut(t){return await Promise.all([...ro.map(e=>rt(x.join(t.dir,e),{recursive:!0,force:!0})),Ie(t.dir)]),await C(t)}s(Ut,"resetProjectWorkflow");async function Re(t){await rt(t.dir,{recursive:!0,force:!0})}s(Re,"deleteProject");async function no(t){let e=await tt(Jt(t),"utf8").catch(()=>"");return e.trim()?JSON.parse(e):null}s(no,"readDesignManifest");async function ot(t,e){await Xe(zt(t),{recursive:!0}),await Lt(Jt(t),`${JSON.stringify(e,null,2)}
|
|
9
|
+
`,"utf8")}s(ot,"writeDesignManifest");async function $t(t){let e=await no(t);if(!e)return{status:"missing_manifest",manifest:null,errors:["\u7F3A\u5C11 Design \u4EA7\u7269\u6E05\u5355"],missing:["runtime/artifacts/design-manifest.json"]};if(e.status!=="ready"||!e.validation.passed)return{status:"invalid",manifest:e,errors:e.validation.errors.length?e.validation.errors:["Design \u4EA7\u7269\u6E05\u5355\u672A\u5C31\u7EEA"],missing:[]};let r=e.generated.filter(o=>o.required).map(o=>o.path),n=[];for(let o of r)(await Nt(x.join(t.dir,o)).catch(()=>null))?.isFile()||n.push(o);return n.length>0?{status:"artifact_missing",manifest:e,errors:[`\u7F3A\u5C11 Design \u4EA7\u7269\uFF1A${n.join(", ")}`],missing:n}:{status:"ready",manifest:e,errors:[],missing:[]}}s($t,"validateDesignArtifacts");function Pe(t){return Qn("sha256").update(t).digest("hex")}s(Pe,"checksumContent");async function j(t){let e=[];return await Kt(t.dir,t.dir,e),e.sort((r,n)=>r.path.localeCompare(n.path))}s(j,"listProjectFiles");function A(t){return x.join(t.dir,"aitable-workflow.config.yml")}s(A,"configPath");function qt(t,e,r){let n=new URLSearchParams({entrance:"data",sheetId:e});return r?.trim()&&n.set("viewId",r.trim()),`https://alidocs.dingtalk.com/i/nodes/${t}?iframeQuery=${encodeURIComponent(n.toString())}`}s(qt,"buildAITableUrl");function oo(t){return x.join(t.dir,"runtime")}s(oo,"runtimeDir");function zt(t){return x.join(oo(t),"artifacts")}s(zt,"artifactsDir");function Jt(t){return x.join(zt(t),"design-manifest.json")}s(Jt,"designManifestPath");function Ht(t,e){return Vt(e),x.join(t.projectsRoot,e)}s(Ht,"projectDir");function Vt(t){if(!Mt.test(t))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${t}`),{code:"INVALID_PROJECT_ID"})}s(Vt,"assertProjectId");async function Oe(t){await Lt(x.join(t.dir,"project.json"),`${JSON.stringify(t,null,2)}
|
|
10
|
+
`,"utf8")}s(Oe,"writeProjectMeta");function Gt(t){return t==="views.yml"||t.endsWith("/views.yml")}s(Gt,"isLegacyViewsPath");async function Ie(t,e=t){let r=await et(e,{withFileTypes:!0}).catch(()=>[]);await Promise.all(r.map(async n=>{if(n.name==="node_modules"||n.name==="runtime"||n.name==="traces")return;let o=x.join(e,n.name);if(n.isDirectory()){await Ie(t,o);return}if(!n.isFile())return;let i=x.relative(t,o).split(x.sep).join("/");Gt(i)&&await rt(o,{force:!0})}))}s(Ie,"removeLegacyViewsFiles");async function Kt(t,e,r){let n=await et(e,{withFileTypes:!0}).catch(()=>[]);for(let o of n){if(so(t,x.join(e,o.name),o.name))continue;let i=x.join(e,o.name);if(o.isDirectory()){await Kt(t,i,r);continue}if(!o.isFile()||!to.test(o.name))continue;let a=x.relative(t,i).split(x.sep).join("/");if(Gt(a))continue;let c=await tt(i,"utf8").catch(()=>"");r.push({path:a,content:c})}}s(Kt,"walk");function so(t,e,r){return r==="node_modules"||r==="traces"||r==="runtime"||r===".aitable"||r==="project.json"?!0:x.relative(t,e).split(x.sep).join("/").startsWith(".aitable/")}s(so,"isHiddenProjectFile");function Z(t,e,r){if(e==="design"){let n=ie.get(t);return n?{sessionLocal:!0,cursor:n.buffer.cursor}:{sessionLocal:!1}}return e==="run"?{sessionLocal:r.hasRunSession(t)}:{sessionLocal:!1}}s(Z,"stageFactsFor");function Yt(t,e){return uo(t,(r,n)=>co({projectId:t.projectId,stage:r,state:n.state,facts:Z(t.projectId,r,e)}))}s(Yt,"decorateProjectState");async function ke(t,e){let r=await t.projectStore.instances.getRecoverableState(e),n=await mo(t,e,r),o={hasRunSession:s(c=>t.runtime.runSessions.has(c),"hasRunSession")},i=t.execution.runScheduler;if(!i)return Yt(n,o);let a=await i.getStatus(e.id).catch(()=>null);return Yt(a?go(n,a):n,o)}s(ke,"readProjectState");async function mo(t,e,r){if(r.stages.init||!await Promise.all([Zt(A(e)),Zt(fo.join(e.dir,"workflow.yml"))]).then(a=>a.some(Boolean)))return r;let o=new Date().toISOString(),i=po("init",null,{phase:"ready",warnings:[],roleFiles:[]},"system");return await t.projectStore.instances.putStageState(e,"init",{identity:{id:`init_import_${e.id}`,projectId:e.id,stage:"init",attempt:1,startedAt:e.createdAt||o,updatedAt:o,completedAt:o},state:i})}s(mo,"backfillImportedInit");function go(t,e){let r=io(e),n=t.stages.run;if(!n&&r.phase==="stopped")return t;let o=new Date().toISOString();return ao(t,"run",{identity:n?.identity??{id:`run_relay_${t.projectId}`,projectId:t.projectId,stage:"run",attempt:1,startedAt:e.lastHeartbeatAt??o,updatedAt:o},state:r})}s(go,"injectRelayRunState");function Zt(t){return lo(t).then(()=>!0,()=>!1)}s(Zt,"fileExists");function Qt(t,e=1){let r=t.replace(/\s+/g," ").trim();if(!r)return`\u5DE5\u4F5C\u6D41 #${e}`;let n=r.split(/[。.!!?\n]/u)[0]?.split(/[::,,;;]/u)[0]?.trim();return n?n.length>16?n.slice(0,16):n:`\u5DE5\u4F5C\u6D41 #${e}`}s(Qt,"deriveProjectTitleFromSop");async function er(t,e,r,n,o,i){let a=await b(e,t),c=await k(n),d=await Y.open({project:a,stage:"init",store:r,driver:"init.http",facts:s(()=>Z(a.id,"init",{hasRunSession:s(()=>!1,"hasRunSession")}),"facts")});await d.advance({phase:"configuring"});try{let p=xo(c),w=await So({answers:p,cwd:a.dir,force:!0}),m=await vo(be.join(a.dir,"profile","profile.yml"),c.roles??[]);c.machineId&&i&&await i(t,c.machineId).catch(()=>{});let g=await C(a),l=m.skippedKnowledgeBindings.map(I=>`\u89D2\u8272 ${I.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 profile\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${I.knowledge.join(", ")}`);await d.advance({phase:"ready",warnings:l,roleFiles:[]});let D=Qt(c.sop,1),E=await le(g,{title:D});f(o,{project:E,scaffold:w,roleFiles:[],files:await j(g),warnings:l})}catch(p){throw await d.advance({phase:"failed",error:{code:F(p),message:P(p),retryable:!0,details:$(p)}}),p}}s(er,"handleInit");async function tr(t,e,r,n){let o=await b(e.workspace,t),a=(await k(r)).tableId?.trim()??"";if(!a)throw Object.assign(new Error("Table Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"TABLE_ID_REQUIRED",status:422});let c=A(o),d=await Xt(c,"utf8"),p=st.parse(d);if(!fe(p)||!fe(p.tracker)){let m=fe(p)&&fe(p.workflows);throw Object.assign(new Error(m?"\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u7684 table_id \u5C5E\u4E8E\u5404\u81EA\u7684 workflows/<id>/workflow.yml\uFF0C\u8BF7\u76F4\u63A5\u6539\u5BF9\u5E94\u6587\u4EF6\u7684 tracker.table_id":"\u914D\u7F6E\u6587\u4EF6\u7F3A\u5C11 tracker\uFF0C\u65E0\u6CD5\u5199\u56DE Table Id"),{code:m?"TABLE_ID_PER_WORKFLOW":"CONFIG_TRACKER_MISSING",status:m?422:500})}p.tracker.table_id=a,await wo(c,st.stringify(p),"utf8");let w=await C(o);f(n,{project:w,files:await j(w),state:await ke(e,w)})}s(tr,"handleUpdateProjectTableId");async function rr(t,e,r,n,o,i,a){let c=await b(e,t),d=await k(i);if(d.action!=="confirm"&&d.action!=="terminate")throw Object.assign(new Error("\u4EBA\u5DE5\u64CD\u4F5C\u53EA\u652F\u6301 confirm \u6216 terminate"),{code:"INVALID_HUMAN_ACTION",status:422});let p=n.runSessions.get(t)?.app;if(!p)throw Object.assign(new Error("\u8FD0\u884C\u670D\u52A1\u672A\u542F\u52A8\uFF0C\u65E0\u6CD5\u5904\u7406\u4EBA\u5DE5\u786E\u8BA4\u64CD\u4F5C"),{code:"RUN_SESSION_REQUIRED",status:409});let w=d.action==="confirm"?p.settings.tracker.states.active[0]:p.settings.tracker.states.terminal.find(D=>D==="\u5DF2\u5173\u95ED")??p.settings.tracker.states.terminal.at(-1);if(!w)throw Object.assign(new Error("\u672A\u914D\u7F6E\u53EF\u7528\u4E8E\u4EBA\u5DE5\u64CD\u4F5C\u7684\u76EE\u6807\u72B6\u6001"),{code:"HUMAN_ACTION_STATE_MISSING",status:500});let m=d.action==="confirm"?"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EE7\u7EED\u6D41\u7A0B":"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EC8\u6B62\u6D41\u7A0B",g=null;d.action==="confirm"&&(g=await Po(p,o)),await p.tracker.updateState(o,w),g&&await p.tracker.updateCurrentStep(o,g),await p.tracker.appendEvent(o,m);let l=await r.updateRunSnapshotRecord(c,o,d.action==="confirm"?{state:w,status:"running",currentStepId:g??void 0}:{state:w,status:"done",currentStepId:null},m);f(a,{action:d.action,recordId:o,state:l})}s(rr,"handleRunHumanAction");async function Po(t,e){let[r]=await t.tracker.fetchItemsByIds([e]).catch(()=>[]),n=r?.currentStep;if(!n)return null;let o=t.workflow.orderedStepIds.indexOf(n);return o<0?null:t.workflow.orderedStepIds[o+1]??null}s(Po,"resolveNextStepId");function xo(t){let e=t.tableBaseId.trim();if(!e)throw Object.assign(new Error("Base Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"BASE_ID_REQUIRED",status:422});let r=t.llmProvider.trim();return{agentType:Do(t.agentsSelected),scene:jo(t),baseId:e,llmProvider:r,llmModel:r?t.llmModel.trim()||To(r):"",llmApiKeyEnv:r?Ro(r):"",confirmed:!0}}s(xo,"toInitAnswers");function jo(t){return t.sop.trim()||"\u7528\u6237\u5728 AI \u8868\u683C\u4E2D\u63D0\u4EA4\u4E1A\u52A1\u8BB0\u5F55\uFF0C\u7CFB\u7EDF\u81EA\u52A8\u5B8C\u6210\u5206\u7C7B\u3001\u5904\u7406\u3001\u5BA1\u6838\u4E0E\u56DE\u5199\u3002"}s(jo,"buildScene");function Do(t){return t.includes("qwenwork")?"qwenwork":t.includes("qoder")?"qoder":t.includes("codex")?"codex":"claudecode"}s(Do,"toAgentType");function To(t){return t==="openai"?"gpt-4o":t==="anthropic"?"claude-sonnet-4-20250514":t==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}s(To,"defaultModel");function Ro(t){return t==="openai"?"OPENAI_API_KEY":t==="anthropic"?"ANTHROPIC_API_KEY":t==="dashscope"?"DASHSCOPE_API_KEY":t==="idealab"?"IDEALAB_API_KEY":"LLM_API_KEY"}s(Ro,"defaultApiKeyEnv");async function nr(t,e){let r=be.join(t.dir,"aitable-workflow.config.yml");try{await ho(r)}catch{e.warnings.push("aitable-workflow.config.yml \u4E0D\u5B58\u5728\uFF08\u9879\u76EE\u7EA7\u914D\u7F6E\u7F3A\u5931\uFF0C\u8FD0\u884C\u524D\u9700\u8981\u751F\u6210\uFF09")}await Oo(t.dir)||e.warnings.push("\u672A\u627E\u5230\u4EFB\u4F55\u89D2\u8272\u5B9A\u4E49\uFF08profile/profile.yml \u7684 roles \u6BB5\u6216 roles/*.role.yml\uFF0Cdesign \u9636\u6BB5 requiresAgent \u7684 step \u9700\u7ED1\u5B9A role\uFF09")}s(nr,"augmentProjectFileValidation");async function Oo(t){try{let r=st.parse(await Xt(be.join(t,"profile","profile.yml"),"utf8"));if(fe(r)&&fe(r.roles)&&Object.keys(r.roles).length>0)return!0}catch{}return(await yo(be.join(t,"roles")).catch(()=>[])).some(r=>r.endsWith(".role.yml")||r.endsWith(".role.yaml"))}s(Oo,"hasAnyRoleDefinition");import or from"fs";import Io from"path";var ko=/requiresAgent\s*:\s*(true|false)/,sr=new Map;function ir(t,e){if(!e)return!1;for(let r of[".recipe.ts",".recipe.js"]){let n=Io.join(t,`${e}${r}`);try{let o=or.statSync(n);if(!o.isFile())continue;let i=`${o.mtimeMs}:${o.size}`,a=sr.get(n);if(a?.signature===i)return a.requiresAgent;let d=or.readFileSync(n,"utf8").match(ko),p=d?d[1]==="true":!1;return sr.set(n,{signature:i,requiresAgent:p}),p}catch(o){if(o.code==="ENOENT")continue;return!1}}return!1}s(ir,"readRecipeRequiresAgent");import{rm as cr,mkdir as bo,writeFile as Eo}from"fs/promises";import xe from"path";import Ao from"yaml";import{isRecord as _o,resolveInsideRoot as Fo}from"aitable-workflow-core";var ar=/\.(json|ya?ml|ts|js|md|txt)$/i,Wo=new Set(["runtime","traces","node_modules"]),dr="aitable-workflow.config.yml";function pr(t,e){try{Fo(t,e,{allowRoot:!1})}catch{throw Object.assign(new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u76EE\u5F55: ${e}`),{code:"invalid_path",status:400})}}s(pr,"assertSafeRelativePath");function it(t,e){pr(t.dir,e)}s(it,"assertSafeProjectPath");function Mc(t){pr("/workflow-root",t)}s(Mc,"assertSafeWorkflowPath");function ur(t){let r=at(t).split("/")[0]??"";return Wo.has(r)}s(ur,"isForbiddenWritable");function lr(t){if(mr(t))throw Object.assign(new Error(`\u5DF2\u5E9F\u5F03\u7684\u89C6\u56FE\u6587\u4EF6\u5FC5\u987B\u5185\u8054\u5230 workflow.yml \u7684 tracker.views: ${t}`),{code:"invalid_path",status:400});if(ur(t))throw Object.assign(new Error(`\u7981\u6B62\u5199\u5165\u53D7\u4FDD\u62A4\u76EE\u5F55: ${t}`),{code:"invalid_path",status:400});if(!ar.test(t))throw Object.assign(new Error(`\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8\u5199\u5165: ${t}\uFF08\u4EC5\u5141\u8BB8 ${ar.source}\uFF09`),{code:"invalid_path",status:400})}s(lr,"assertWritableKind");function fr(t){let e=at(t);return e===dr||e.endsWith(".config.yml")?"config":e==="workflow.yml"?"workflow":e.startsWith("recipes/")?"recipe":e.startsWith("roles/")?"role":"other"}s(fr,"kindOf");function mr(t){let e=at(t);return e==="views.yml"||e.endsWith("/views.yml")}s(mr,"isLegacyViewsPath");function at(t){return xe.posix.normalize(t.replace(/\\/g,"/")).replace(/^\.\//,"")}s(at,"normalizeLogicalPath");function No(t){let e=[],r;try{r=Ao.parse(t)}catch(o){return e.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),e}if(!_o(r))return e.push("aitable-workflow.config.yml \u9876\u5C42\u5E94\u4E3A\u5BF9\u8C61"),e;let n=r.scene;return(typeof n!="string"||n.trim()==="")&&e.push("aitable-workflow.config.yml \u7F3A\u5C11 scene \u5B57\u6BB5\uFF08\u5EFA\u8BAE\u586B\u5199\u4E1A\u52A1\u573A\u666F\u63CF\u8FF0\uFF09"),e}s(No,"validateConfigScene");async function Ee(t,e){let r=[],n=[];for(let o of e){it(t,o.path),lr(o.path);let i=xe.join(t.dir,o.path);await bo(xe.dirname(i),{recursive:!0}),await Eo(i,o.content,"utf8"),r.push({path:o.path,content:o.content}),o.path===dr&&n.push(...No(o.content))}return{written:r,warnings:n}}s(Ee,"writeProjectFiles");async function gr(t,e){for(let r of e){if(it(t,r),ur(r))throw Object.assign(new Error(`\u7981\u6B62\u5220\u9664\u53D7\u4FDD\u62A4\u76EE\u5F55: ${r}`),{code:"invalid_path",status:400});await cr(xe.join(t.dir,r),{force:!0})}}s(gr,"removeProjectFiles");async function wr(t,e){for(let n of e)it(t,n.path),lr(n.path);let r=await Lo(t);for(let n of r)await cr(xe.join(t.dir,n),{force:!0}).catch(()=>{});return await Ie(t.dir),Ee(t,e)}s(wr,"replaceProjectFiles");async function Lo(t){return(await j(t)).map(r=>r.path).filter(r=>fr(r)!=="other"||mr(r))}s(Lo,"collectBusinessFiles");function Mo(t){return Pe(t.content)}s(Mo,"checksumFile");async function hr(t){let e=await j(t),r=e.map(n=>({path:n.path,sha256:Mo(n)}));return{project:t,files:e,checksums:r,exportedAt:new Date().toISOString()}}s(hr,"buildProjectExport");var Co="coding-agents.config.json";function yr(t){let e=[],r=t.files,n=t.checksums,o=r.findIndex(i=>i.path===Co);if(o>=0){let i=r[o],a=i.content;try{let c=JSON.parse(i.content);if(c&&typeof c=="object"&&!Array.isArray(c)){let d=c.agents;if(d&&typeof d=="object"&&!Array.isArray(d)){let p=!1;for(let w of Object.keys(d)){let m=d[w];if(!m||typeof m!="object"||Array.isArray(m))continue;let g=m.env;if(g&&typeof g=="object"&&!Array.isArray(g)){let l=g;if(Object.values(l).some(E=>typeof E=="string"&&E!=="")){for(let E of Object.keys(l))l[E]="";p=!0}}}p&&(a=JSON.stringify(c,null,2)+`
|
|
11
|
+
`)}}}catch{}if(a!==i.content){let c={path:i.path,content:a};r=r.map((p,w)=>w===o?c:p);let d=Pe(a);n=n.map((p,w)=>w===o?{path:p.path,sha256:d}:p),e.push(i.path)}}return{...t,files:r,checksums:n,redacted:e.length>0?e:t.redacted}}s(yr,"redactExportBundle");import Sr from"path";import{strFromU8 as vr,unzipSync as Bo}from"fflate";var Uo=/\.(json|ya?ml|ts|js|md|txt)$/i,$o=new Set(["runtime","traces","node_modules"]),qo=new Set(["__MACOSX"]),zo=/(^|\/)\.(_|DS_Store)/,Jo="project-manifest.json",Ho="project.json",Pr=20*1024*1024,Vo=5e3,Go=100*1024*1024;function xr(t,e={}){let r=e.maxEntries??Vo,n=e.maxTotalUncompressedBytes??Go,o=0,i=0,a,c;try{c=Bo(new Uint8Array(t),{filter:s(l=>l.name.endsWith("/")||a?!1:(o+=1,i+=l.originalSize,o>r?(a=`zip \u6761\u76EE\u6570\u8D85\u8FC7\u4E0A\u9650\uFF08${r}\uFF09`,!1):i>n?(a=`zip \u89E3\u538B\u540E\u603B\u5927\u5C0F\u8D85\u8FC7\u4E0A\u9650\uFF08${n} \u5B57\u8282\uFF09`,!1):!0),"filter")})}catch(l){throw a?Object.assign(new Error(`zip \u8D85\u8FC7\u5BFC\u5165\u5BB9\u91CF\u4E0A\u9650\uFF1A${a}`),{code:"ZIP_TOO_LARGE",status:413}):Object.assign(new Error(`zip \u89E3\u6790\u5931\u8D25: ${l instanceof Error?l.message:String(l)}`),{code:"INVALID_ZIP",status:400})}if(a)throw Object.assign(new Error(`zip \u8D85\u8FC7\u5BFC\u5165\u5BB9\u91CF\u4E0A\u9650\uFF1A${a}`),{code:"ZIP_TOO_LARGE",status:413});let d=Object.entries(c).filter(([l])=>!l.endsWith("/")).map(([l,D])=>({path:Ko(l),data:D})).filter(l=>!!l.path),p=Yo(d.map(l=>l.path)),w=new Map,m;for(let l of d){let D=p(l.path);if(D===Jo){let I=vr(l.data);m=Qo(I)??m;continue}if(!D||Zo(D))continue;let E=vr(l.data);w.set(D,{path:D,content:E})}let g=Array.from(w.values()).sort((l,D)=>l.path.localeCompare(D.path));if(g.length===0)throw Object.assign(new Error("zip \u4E2D\u672A\u89E3\u6790\u5230\u53EF\u5BFC\u5165\u7684\u9879\u76EE\u6587\u4EF6\uFF08\u4EC5\u652F\u6301 .json/.yml/.yaml/.ts/.js/.md/.txt\uFF0C\u4E14\u4E0D\u80FD\u4F4D\u4E8E runtime/traces/node_modules\uFF09"),{code:"EMPTY_ZIP_PROJECT",status:422});return{files:g,title:m}}s(xr,"parseProjectZip");function Ko(t){let e=t.replace(/\\/g,"/").replace(/^\/+/,"");if(!e||e.includes("\0"))return null;let r=Sr.posix.normalize(e).replace(/^\.\//,"");return!r||r==="."||r===".."||r.startsWith("../")||Sr.posix.isAbsolute(r)?null:r}s(Ko,"normalizeZipPath");function Yo(t){let e=t.filter(a=>!jr(a)),r=new Set,n=!1;for(let a of e){let c=a.split("/",2),d=c[0],p=c[1];if(!d||!p){n=!0;break}r.add(d)}if(n||r.size!==1)return a=>a;let[o]=Array.from(r);if(!o)return a=>a;let i=`${o}/`;return a=>a.startsWith(i)?a.slice(i.length):a}s(Yo,"detectSingleTopDir");function Zo(t){if(!t||t===Ho||jr(t))return!0;let e=t.split("/")[0]??"";return $o.has(e)?!0:!Uo.test(t)}s(Zo,"shouldSkipPath");function jr(t){let e=t.split("/")[0]??"";return qo.has(e)||zo.test(t)}s(jr,"isJunkPath");function Qo(t){try{let e=JSON.parse(t);return typeof e.title=="string"&&e.title.trim()?e.title.trim():void 0}catch{return}}s(Qo,"readManifestTitle");var v=class{ctx;serverServices;async list(){let e=await this.serverServices.projectStore.projects.list(O(this.ctx));this.ctx.respond=!1,f(this.ctx.res,{projects:e})}async create(){let e=this.serverServices,r=O(this.ctx),n=await k(this.ctx.req),o=await e.projectStore.projects.create(r,{title:n.title,files:n.files});await T(o,e);let i={project:o};o.files&&(i.files=o.files),o.warnings&&o.warnings.length>0&&(i.warnings=o.warnings),this.ctx.respond=!1,f(this.ctx.res,i)}async importZip(){let e=this.serverServices,r=O(this.ctx),n=await He(this.ctx.req,Pr),o=xr(n),i=he(this.ctx.query?.title)?.trim()||o.title||"\u5BFC\u5165\u9879\u76EE",a=await e.projectStore.projects.create(r,{title:i,files:o.files});await T(a,e);let c={project:a,files:a.files,imported:{source:"zip",fileCount:o.files.length}};a.warnings&&a.warnings.length>0&&(c.warnings=a.warnings),this.ctx.respond=!1,f(this.ctx.res,c)}async remove(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project;if(this.ctx.respond=!1,e.runtime.runSessions.has(n.id)){S(this.ctx.res,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664");return}await e.projectStore.projects.delete(n,r),await Re(n),await Ft(e,n.id),f(this.ctx.res,{ok:!0,id:n.id})}async updateMeta(){let e=this.serverServices,r=O(this.ctx),n=await k(this.ctx.req),o=await e.projectStore.projects.updateMeta(this.ctx.state.project,{title:n.title},r);this.ctx.respond=!1,f(this.ctx.res,{project:o})}async init(){let e=this.serverServices,r=this.ctx.state.project;this.ctx.respond=!1,await T(r,e);let n=e.execution;await er(r.id,e.workspace,e.projectStore.instances,this.ctx.req,this.ctx.res,(o,i)=>n.bindProjectMachine(o,i)),await ve(e,r,"init")}async getEngine(){let e=this.ctx.state.project,r=this.serverServices.execution,n=await r.getProjectMachine(e.id);if(this.ctx.respond=!1,!n){f(this.ctx.res,{machineId:null,machine:null,status:"unbound"});return}let o=r.isMachineOnline(n),a=(r.listMachines()??[]).find(c=>c.machineId===n);f(this.ctx.res,{machineId:n,machine:a??null,status:o?"online":"offline"})}async bindEngine(){let e=await k(this.ctx.req);if(this.ctx.respond=!1,!e.machineId){S(this.ctx.res,422,"INVALID_INPUT","machineId \u4E0D\u80FD\u4E3A\u7A7A");return}await this.serverServices.execution.bindProjectMachine(this.ctx.state.project.id,e.machineId),f(this.ctx.res,{ok:!0,machineId:e.machineId})}async getAgents(){let e=this.ctx.state.project;this.ctx.respond=!1;let r;try{r=await Or(A(e),{lenientEnv:!0})}catch(o){f(this.ctx.res,{registry:null,agents:[],listError:P(o)});return}let n=r.identity?.registry??null;if(!n){f(this.ctx.res,{registry:null,agents:[]});return}try{let o=await kt({registry:n});f(this.ctx.res,{registry:n,agents:o})}catch(o){f(this.ctx.res,{registry:n,agents:[],listError:P(o)})}}async createAgent(){let e=this.ctx.state.project,r=await k(this.ctx.req);if(this.ctx.respond=!1,!r?.name||!r.name.trim()){S(this.ctx.res,422,"INVALID_INPUT","\u667A\u80FD\u4F53\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");return}let o=(await Or(A(e),{lenientEnv:!0})).identity?.registry;if(!o){S(this.ctx.res,409,"NO_REGISTRY","\u8BE5\u9879\u76EE\u672A\u914D\u7F6E identity.registry\uFF0C\u767B\u8BB0\u8868\u7BA1\u7406\u9762\u4E0D\u53EF\u7528\u3002");return}let{recordId:i}=await It({registry:o,input:r});f(this.ctx.res,{ok:!0,recordId:i})}async listFiles(){let e=this.ctx.state.project,r=await j(e);this.ctx.respond=!1,f(this.ctx.res,{project:e,files:r})}async replaceFiles(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await k(this.ctx.req);if(this.ctx.respond=!1,!Array.isArray(o.files)){S(this.ctx.res,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");return}let i=await e.projectStore.projects.replaceFiles(n,o.files,r),a=await T(n,e);f(this.ctx.res,{project:a.project,files:i})}async patchFiles(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await k(this.ctx.req),i=await e.projectStore.projects.updateFiles(n,{upsert:o.upsert,remove:o.remove},r),a=await T(n,e);this.ctx.respond=!1,f(this.ctx.res,{project:a.project,files:i})}async exportProject(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await e.projectStore.projects.exportProject(n,r),i=yr(o),a=e.projectStore.workflows;if(a){let c=await Promise.all((await a.list(n.id,r)).map(async d=>{let p=await a.exportWorkflow(n.id,d.id,r);return{workflow:p.workflow,files:p.files}}));this.ctx.respond=!1,f(this.ctx.res,{...i,workflows:c});return}this.ctx.respond=!1,f(this.ctx.res,i)}async validate(){let e=this.ctx.state.project,r=await ts({workDir:e.dir,configPath:ne.join(e.dir,"aitable-workflow.config.yml"),workflows:[],workflowPath:ne.join(e.dir,"workflow.yml"),recipeDir:ne.join(e.dir,"recipes")});await nr(e,r),this.ctx.respond=!1,f(this.ctx.res,r)}async getWorkflow(){let e=this.ctx.state.project,r=await rs(e.dir),n=await ns(e,this.serverServices.projectStore.workflows,he(this.ctx.query?.workflowId),O(this.ctx)),o=await Rr(n,{envSource:r}).catch(()=>Rr(n)),i=ne.join(ne.dirname(n),"recipes"),a=o.steps.map(c=>({...c,requires_agent:c.recipe?ir(i,c.recipe):!!c.prompt}));this.ctx.respond=!1,f(this.ctx.res,{workflow:{...o,steps:a}})}async resetWorkflow(){let e=await Ut(this.ctx.state.project),r=await j(e);this.ctx.respond=!1,f(this.ctx.res,{project:e,files:r})}async getState(){let e=this.serverServices,r=this.ctx.state.project,n=await ke(e,r);this.ctx.respond=!1,f(this.ctx.res,n)}async updateTableId(){let e=this.serverServices;this.ctx.respond=!1,await tr(this.ctx.state.project.id,e,this.ctx.req,this.ctx.res)}};s(v,"ProjectsController"),u([Dr()],v.prototype,"ctx",2),u([Dr()],v.prototype,"serverServices",2),u([ce("/")],v.prototype,"list",1),u([me("/")],v.prototype,"create",1),u([me("/import-zip")],v.prototype,"importZip",1),u([es("/:projectId")],v.prototype,"remove",1),u([ct("/:projectId")],v.prototype,"updateMeta",1),u([me("/:projectId/init")],v.prototype,"init",1),u([ce("/:projectId/engine")],v.prototype,"getEngine",1),u([Tr("/:projectId/engine")],v.prototype,"bindEngine",1),u([ce("/:projectId/agents")],v.prototype,"getAgents",1),u([me("/:projectId/agents")],v.prototype,"createAgent",1),u([ce("/:projectId/files")],v.prototype,"listFiles",1),u([Tr("/:projectId/files")],v.prototype,"replaceFiles",1),u([ct("/:projectId/files")],v.prototype,"patchFiles",1),u([ce("/:projectId/export")],v.prototype,"exportProject",1),u([me("/:projectId/validate")],v.prototype,"validate",1),u([ce("/:projectId/workflow")],v.prototype,"getWorkflow",1),u([me("/:projectId/reset-workflow")],v.prototype,"resetWorkflow",1),u([ce("/:projectId/state")],v.prototype,"getState",1),u([ct("/:projectId/table-id")],v.prototype,"updateTableId",1),v=u([Xo("/api/projects")],v);async function ns(t,e,r,n){let o=r&&/^[A-Za-z0-9_-]+$/.test(r)?r:null;if(o&&e){let c=await e.resolve(t.id,o,n);return ne.join(t.dir,c.templatePath)}let i=await j(t);if(o){let c=`workflows/${o}/workflow.yml`;if(i.some(d=>d.path===c))return ne.join(t.dir,c)}if(i.some(c=>c.path==="workflow.yml"))return ne.join(t.dir,"workflow.yml");let a=i.find(c=>/^workflows\/[^/]+\/workflow\.ya?ml$/.test(c.path));return ne.join(t.dir,a?.path??"workflow.yml")}s(ns,"resolvePreviewWorkflowPath");import os from"path";import{Controller as ss,Del as is,Get as Ir,Inject as kr,Patch as as,Post as cs,Put as ds}from"@midwayjs/core";import{loadWorkflowTemplate as ps}from"aitable-workflow-core";var W=class{ctx;serverServices;guardNotConfigured(){return this.serverServices.projectStore.workflows?!1:(this.ctx.respond=!1,S(this.ctx.res,501,"WORKFLOWS_NOT_CONFIGURED","\u5DE5\u4F5C\u6D41\u6301\u4E45\u5316\u672A\u914D\u7F6E\uFF08\u9700\u8981 AITABLE_DB_URL\uFF09"),!0)}async list(){let e=this.serverServices,r=this.ctx.state.project;if(!e.projectStore.workflows){this.ctx.respond=!1,f(this.ctx.res,{workflows:await us(r)});return}let n=O(this.ctx);this.ctx.respond=!1,f(this.ctx.res,{workflows:await e.projectStore.workflows.list(r.id,n)})}async create(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await k(this.ctx.req);if(!o.name||!o.name.trim()){this.ctx.respond=!1,S(this.ctx.res,422,"INVALID_INPUT","\u5DE5\u4F5C\u6D41\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");return}let i=await e.projectStore.workflows.create(n.id,{name:o.name,templatePath:o.templatePath,files:o.files},r);await T(n,e);let a={workflow:i.workflow};i.files&&(a.files=i.files),i.warnings&&i.warnings.length>0&&(a.warnings=i.warnings),this.ctx.respond=!1,f(this.ctx.res,a)}async get(){let e=this.serverServices,r=this.ctx.state.project,n=this.ctx.params.workflowId??"";if(!e.projectStore.workflows){let a=await ls(r,n);if(this.ctx.respond=!1,!a){S(this.ctx.res,404,"WORKFLOW_NOT_FOUND","\u5DE5\u4F5C\u6D41\u4E0D\u5B58\u5728");return}f(this.ctx.res,a);return}let o=O(this.ctx),i=await e.projectStore.workflows.exportWorkflow(r.id,n,o);this.ctx.respond=!1,f(this.ctx.res,{workflow:i.workflow,files:i.files})}async remove(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project;if(e.runtime.runSessions.has(n.id)){this.ctx.respond=!1,S(this.ctx.res,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664\u5DE5\u4F5C\u6D41");return}let o=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r);await e.projectStore.workflows.delete(o,r),await T(n,e),this.ctx.respond=!1,f(this.ctx.res,{ok:!0,id:o.id})}async replaceFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r),i=await k(this.ctx.req);if(!Array.isArray(i.files)){this.ctx.respond=!1,S(this.ctx.res,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");return}let a=await e.projectStore.workflows.replaceFiles(o,i.files,r);await T(n,e),this.ctx.respond=!1,f(this.ctx.res,{workflow:o,files:a})}async updateFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r),i=await k(this.ctx.req),a=await e.projectStore.workflows.updateFiles(o,{upsert:i.upsert,remove:i.remove},r);await T(n,e),this.ctx.respond=!1,f(this.ctx.res,{workflow:o,files:a})}};s(W,"WorkflowsController"),u([kr()],W.prototype,"ctx",2),u([kr()],W.prototype,"serverServices",2),u([Ir("/:projectId/workflows")],W.prototype,"list",1),u([cs("/:projectId/workflows")],W.prototype,"create",1),u([Ir("/:projectId/workflows/:workflowId")],W.prototype,"get",1),u([is("/:projectId/workflows/:workflowId")],W.prototype,"remove",1),u([ds("/:projectId/workflows/:workflowId/files")],W.prototype,"replaceFiles",1),u([as("/:projectId/workflows/:workflowId/files")],W.prototype,"updateFiles",1),W=u([ss("/api/projects")],W);async function us(t){let e=await j(t),r=br(e);return(await Promise.all(r.map(o=>Fr(t,o,e)))).sort((o,i)=>o.name.localeCompare(i.name))}s(us,"listLocalWorkflows");async function ls(t,e){let r=await j(t),n=br(r).find(c=>Er(c)===e);if(!n)return null;let o=await Fr(t,n,r),i=Ar(n),a=r.filter(c=>_r(c.path,n)).map(c=>({...c,path:c.path.slice(i.length)}));return{workflow:o,files:a}}s(ls,"exportLocalWorkflow");function br(t){return t.map(e=>e.path).filter(e=>e==="workflow.yml"||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(e))}s(br,"localWorkflowTemplatePaths");function Er(t){return t==="workflow.yml"?"main":t.split("/")[1]??"main"}s(Er,"localWorkflowId");function Ar(t){return t==="workflow.yml"?"":t.replace(/workflow\.ya?ml$/,"")}s(Ar,"workflowBase");function _r(t,e){let r=Ar(e);return r?t.startsWith(r):t==="workflow.yml"||t.startsWith("recipes/")}s(_r,"belongsToWorkflow");async function Fr(t,e,r){let n=Er(e),o=await ps(os.join(t.dir,e)).catch(a=>(console.warn(`\u52A0\u8F7D\u672C\u5730\u5DE5\u4F5C\u6D41\u6A21\u677F\u5931\u8D25 [${e}]\uFF1A`,a instanceof Error?a.message:String(a)),null)),i=r.filter(a=>_r(a.path,e)).length;return{id:n,projectId:t.id,name:o?.meta.name??n,domain:o?.meta.domain,templatePath:e,tableId:o?.tracker?.table_id,fileCount:i,createdAt:t.createdAt,updatedAt:t.updatedAt}}s(Fr,"buildLocalWorkflow");import{Controller as di,Get as mt,Inject as tn,Post as ae}from"@midwayjs/core";import{logger as Wr,loadSettings as fs,runWithExecutor as ms}from"aitable-workflow-core";function Lr(t){return{appFactory:t,runSessions:new Map}}s(Lr,"createServerRuntime");async function Mr(t,e,r,n,o,i,a){let c=await b(e,t),d=a,p=n.runSessions.get(t);if(p){Nr(p,o,i);return}let w=await Y.open({project:c,stage:"run",store:r,driver:"run.local",facts:s(()=>Z(c.id,"run",{hasRunSession:s(l=>n.runSessions.has(l),"hasRunSession")}),"facts")}),m=w.state;if(m?.phase==="starting"||m?.phase==="listening"){let l="\u540E\u7AEF\u8FD0\u884C\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u53EF\u80FD\u662F\u670D\u52A1\u91CD\u542F\u3002\u8BF7\u91CD\u8BD5\u8FD0\u884C\u3002",D=await w.advance({phase:"failed",error:{code:"RUN_SESSION_LOST",message:l,retryable:!0}});i(o,"stage.changed",{type:"stage.changed",stage:"run",stageState:D}),i(o,"error",{type:"error",error:{code:"RUN_SESSION_LOST",message:l}}),o.end();return}let g={taskId:"",subscribers:new Set,events:[],app:null,snapshotWrite:Promise.resolve()};n.runSessions.set(t,g),Nr(g,o,i),gs(c,w,g,n,r,i,d)}s(Mr,"handleRunRuntime");async function gs(t,e,r,n,o,i,a){let c=s(d=>{Ss(r,d,i),hs(d)&&(Wr.info("run-runtime","publish run execution event",ys(d)),r.snapshotWrite=r.snapshotWrite.then(()=>o.appendRunSnapshotEvent(t,d)).catch(p=>{Wr.error("run-runtime","\u5199\u5165\u8FD0\u884C\u5FEB\u7167\u5931\u8D25",{projectId:t.id,event:d.type,error:p instanceof Error?p.message:String(p)})}))},"send");e.emit=d=>c({type:"stage.changed",stage:"run",stageState:d});try{await e.advance({phase:"starting"}),r.taskId=e.taskId??"";let d;if(a){let w;try{w=(await fs(A(t),{lenientEnv:!0})).agent.engine}catch{}d=await a.buildRunExecutor({projectId:t.id,projectDir:t.dir,agent:w})}let p=await n.appFactory(A(t),w=>c(ws(w)));r.app=p,await e.advance({phase:"listening",workflowName:p.workflow.meta.name,stepCount:p.workflow.orderedStepIds.length,intervalMs:p.settings.polling.interval_ms}),await ms(d,async()=>{await p.start()}),await e.advance({phase:"stopped",reason:"user"})}catch(d){await e.advance({phase:"failed",error:{code:Cr(d),message:Br(d),retryable:!0,details:Ur(d)}}),c({type:"error",error:Ds(d)})}finally{n.runSessions.delete(t.id),js(r)}}s(gs,"startRunSession");function ws(t){switch(t.type){case"run.agent_event":return t;case"record.observed":return{type:"run.record.detected",record:t.record};case"step.started":return{type:"run.step.started",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName};case"step.succeeded":return{type:"run.step.succeeded",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,logs:t.logs};case"step.failed":return{type:"run.step.failed",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,error:t.error,logs:t.logs};case"record.blocked":return{type:"run.record.blocked",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,reason:t.reason,logs:t.logs};case"record.completed":return{type:"run.record.completed",itemId:t.itemId}}}s(ws,"toRunEventDTO");function hs(t){return t.type.startsWith("run.record.")||t.type.startsWith("run.step.")}s(hs,"isRunExecutionEvent");function ys(t){return t.type==="run.record.detected"?{type:t.type,itemId:t.record.id,state:t.record.state,currentStep:t.record.currentStep}:t.type==="run.record.completed"?{type:t.type,itemId:t.itemId}:{type:t.type,itemId:t.itemId,stepId:t.stepId}}s(ys,"summarizeRunExecutionEvent");function Nr(t,e,r){t.subscribers.add(e);for(let n of t.events)r(e,n.type,n);e.on("close",()=>{t.subscribers.delete(e)})}s(Nr,"attachRunSubscriber");function Ss(t,e,r){t.events.push(e),xs(t.events);for(let n of t.subscribers){if(n.destroyed||n.writableEnded){t.subscribers.delete(n);continue}try{r(n,e.type,e)}catch{t.subscribers.delete(n)}}}s(Ss,"publishRunEvent");var vs=100,Ps=60;function xs(t){let e=0;for(let r of t)r.type==="run.agent_event"&&(e+=1);for(;e>Ps;){let r=t.findIndex(n=>n.type==="run.agent_event");if(r<0)break;t.splice(r,1),e-=1}for(;t.length>vs;)t.shift()}s(xs,"trimRunReplayEvents");function js(t){for(let e of t.subscribers)e.end();t.subscribers.clear()}s(js,"closeRunSubscribers");function Ds(t){return{code:Cr(t),message:Br(t),details:Ur(t)}}s(Ds,"apiError");function Cr(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}s(Cr,"errorCode");function Br(t){return t instanceof Error?t.message:String(t)}s(Br,"errorMessage");function Ur(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}s(Ur,"errorDetails");function Ts(){let t=process.env.AITABLE_WORKFLOW_SSE_HEARTBEAT_MS,e=typeof t=="string"?t.trim():"";if(!e)return 15e3;let r=Number.parseInt(e,10);return Number.isFinite(r)&&r>0?r:15e3}s(Ts,"readSseHeartbeatMs");function de(t){t.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),Rs(t)}s(de,"startSse");function Rs(t){let e=Ts(),r=setInterval(()=>{if(t.writableEnded||!t.writable){clearInterval(r);return}try{t.write(`:keepalive
|
|
12
12
|
|
|
13
|
-
`)}catch{clearInterval(r)}},e);r.unref?.();let
|
|
13
|
+
`)}catch{clearInterval(r)}},e);r.unref?.();let n=s(()=>clearInterval(r),"stop");t.on("close",n),t.on("finish",n)}s(Rs,"startSseHeartbeat");function Ae(t,e,r){t.write(`event: ${e}
|
|
14
14
|
`),t.write(`data: ${JSON.stringify(r)}
|
|
15
15
|
|
|
16
|
-
`)}n(Ae,"writeSse");var nt=class{constructor(e){this.services=e}services;static{n(this,"LocalRunController")}mode="local";async start(e,r){ne(r),await jr(e,this.services.workspace,this.services.projectStore.instances,this.services.runtime,r,Ae)}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 o=await k(this.services.workspace,e),i=(await this.services.projectStore.instances.getState(o)).runSnapshot?.records??[],a=r?.limit??100;return{items:[...i].sort((p,d)=>d.updatedAt-p.updatedAt).slice(0,a).map(p=>({itemId:p.id,title:p.title,state:p.state,currentStepId:p.currentStepId,doneStepIds:p.doneStepIds,completedAt:p.status==="done"?new Date(p.updatedAt).toISOString():null,updatedAt:new Date(p.updatedAt).toISOString(),status:p.status})),counts:{total:i.length,completed:i.filter(p=>p.status==="done").length}}}},it=class{constructor(e,r){this.scheduler=e;this.records=r}scheduler;records;static{n(this,"RelayRunController")}mode="relay";async start(e,r){m(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}}}};function ue(t){let{runScheduler:e,runRecords:r}=t.execution;return e?new it(e,r):new nt(t)}n(ue,"resolveRunController");import{collectDesignContext as kr,runDesign as Bs,runClarifyRound as $s,syncFieldsFromWorkflow as Us,summarizeForms as qs,validateFormAnswers as Hs,pruneHiddenAnswers as Gs,nextFor as Js,isDesignGenerating as Rr,logger as Fe}from"aitable-workflow-core";var Ee=class{static{n(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 Ir={hasRunSession:n(()=>!1,"hasRunSession")};async function zs(t,e,r){return{...(await e.getState(t)).stages.design,state:r,next:Js({projectId:t.id,stage:"design",state:r,facts:K(t.id,"design",Ir)})}}n(zs,"currentEntry");function at(t,e,r){return z.open({project:t,stage:"design",store:e,driver:r,facts:n(()=>K(t.id,"design",Ir),"facts")})}n(at,"designWriter");async function br(t,e,r,o,s){let i=await k(e,t),a=await at(i,r,"design.discovery"),c=a.state;if(Rr(c)){S(o,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 p=await kr({configPath:L(i),yes:!0}),d=p.agentType?await $s(p,{...await Ar(s,i,p.agentType),timeoutMs:p.agentTimeoutMs,interactive:!0,judgeOnly:!0}):void 0;if(!d?.form){let f=p.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 a.advance({phase:"precheck",confirmed:{form:{id:"clarify",title:"\u65E0\u9700\u6F84\u6E05",questions:[]},answers:{},clarifications:f,summary:f,...d?.sessionId?{agentSessionId:d.sessionId}:{}}});m(o,{stageState:l});return}let w=await a.advance({phase:"clarify_awaiting",form:d.form,answers:Ks(d.form),...d.sessionId?{agentSessionId:d.sessionId}:{}});m(o,{stageState:w})}catch(p){let d=await a.advance({phase:"clarify_failed",error:{code:"DESIGN_PRECHECK_FAILED",message:j(p),retryable:!0,details:C(p)}});m(o,{stageState:d,error:ie(p)},500)}}n(br,"handleDesignDiscovery");async function Ar(t,e,r){let o=await t.buildDesignExecutor({projectId:e.id,agent:r,projectDir:e.dir});return o?{executor:o}:{}}n(Ar,"relayExecutorFor");function Ks(t){let e=Object.fromEntries(t.questions.map(r=>[r.id,r.defaultValue??(r.type==="checkbox"?[]:"")]));return Gs(t,e)}n(Ks,"seedAnswers");async function Er(t,e,r,o,s){let i=await k(e,t),a=await at(i,r,"design.discovery"),c=a.state;if(Rr(c)){m(s,{stageState:await zs(i,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 p=o.answers,d=p&&Object.keys(p).length>0?p:c.answers,w=Hs(c.form,d);if(w.length>0){S(s,400,"DISCOVERY_INVALID_ANSWERS",`\u9700\u6C42\u6F84\u6E05\u7B54\u6848\u4E0D\u5B8C\u6574\uFF1A${w.map(v=>v.message).join("\uFF1B")}`,{issues:w});return}let f=qs([{form:c.form,answers:d}]),l=await a.advance({phase:"precheck",confirmed:{form:c.form,answers:d,clarifications:f,summary:f.replace(/\s+/g," ").trim(),...c.agentSessionId?{agentSessionId:c.agentSessionId}:{}}});m(s,{stageState:l})}n(Er,"handleDesignDiscoveryConfirm");function Fr(t,e){let r=vt(t);if(!r){m(e,{events:[],lastSeq:0,live:!1,retained:!1});return}let o=r.buffer.replayAfter(void 0);m(e,{events:o.map(s=>s.event),lastSeq:r.buffer.cursor,live:r.live,retained:!0})}n(Fr,"handleDesignEventLog");async function _r(t,e,r,o,s,i){let a=await k(e,t);try{s.ensureAvailable()}catch(h){S(o,se(h),W(h),j(h));return}let c=te.get(a.id);if(c){ne(o);for(let h of c.buffer.replayAfter(i))Ke(o,h.seq,h.event);c.subscribers.add(o),o.on("close",()=>c.subscribers.delete(o));return}let p=await at(a,r,"design.stream"),d=p.state;if(!(d?.phase==="precheck"||d?.phase==="generating"||d?.phase==="validating"||d?.phase==="syncing_schema")&&d?.phase!=="generate_failed"){S(o,409,d?.phase==="clarify_awaiting"?"DISCOVERY_NOT_CONFIRMED":"DESIGN_NOT_READY",d?.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 f=d.confirmed;ge.add(a.id),ne(o);let l={buffer:new Ee,subscribers:new Set([o])};te.set(a.id,l),o.on("close",()=>l.subscribers.delete(o));let v=n(h=>Pt(l,h),"send");p.emit=h=>v({type:"stage.changed",stage:"design",stageState:h});let M=Date.now(),b=M,oe=0,B=[],$=[],R=n((h,E)=>{let F=Date.now(),U=F-M,q=F-b;b=F,B.push({label:h,at:new Date(F).toISOString(),elapsedMs:U,...E?{detail:E}:{}}),B.length>40&&B.shift(),p.setDiagnostics({timeline:B,recentAgentEvents:$}),Fe.info("design-runtime",h,{projectId:a.id,taskId:p.taskId,elapsedMs:U,deltaMs:q,...E?{detail:E}:{}})},"trace"),Pe="",fe=!1,me=!1,X=n(async()=>{if(fe){me=!0;return}fe=!0;try{do{me=!1;let E=(await D(a)).filter(F=>F.path!=="project.json").map(F=>`${F.path}:${F.content}`).join("|");if(E&&E!==Pe){Pe=E;let F=await _(a),U=await D(F);R(`\u540C\u6B65 ${U.length} \u4E2A\u751F\u6210\u6587\u4EF6`,{fileCount:U.length}),v({type:"design.files",files:U})}}while(me)}finally{fe=!1}},"sendFileSnapshot");try{p.state&&p.state.phase!=="precheck"&&(p.state.phase!=="generate_failed"&&await p.advance({phase:"generate_failed",confirmed:f,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 p.advance({phase:"precheck",confirmed:f})),await X();let h,E;try{R("\u8BFB\u53D6 Design \u914D\u7F6E"),E=L(a),h=await kr({configPath:E,yes:!0}),R("Design \u914D\u7F6E\u8BFB\u53D6\u5B8C\u6210",{agent:h.agentType,timeoutMs:h.agentTimeoutMs})}catch(g){await p.advance({phase:"generate_failed",confirmed:f,error:{code:"DESIGN_PRECHECK_FAILED",message:j(g),retryable:!0,details:C(g)}}),v({type:"error",error:ie(g)}),o.end();return}h.clarifications=f.clarifications,R("\u542F\u52A8 Coding Agent \u751F\u6210\u6D41\u7A0B\u65B9\u6848",{agent:h.agentType,timeoutSource:"disabled"});let F=!1,U=n(g=>{Fe.warn("design-runtime","\u9636\u6BB5\u72B6\u6001\u5199\u5165\u5931\u8D25",{projectId:a.id,error:j(g)})},"onDetachedError"),q=await Bs(h,{...await Ar(s,a,h.agentType),...f.agentSessionId?{resume:{sessionId:f.agentSessionId,answered:[{form:f.form,answers:f.answers}]}}:{},timeoutMs:null,onRoundStart:n((g,ee)=>{R(`\u7B2C ${g} \u8F6E ${ee?"\u4FEE\u6B63":"\u751F\u6210"}\u5F00\u59CB`,{round:g,isFix:ee}),p.advanceDetached({phase:"generating",confirmed:f,round:g,isFix:ee},U)},"onRoundStart"),onEvent:n(g=>{Vs(g)&&($.push(Ys(g)),$.length>30&&$.shift(),F||(F=!0,R(`\u6536\u5230 Agent \u9996\u4E2A\u4E8B\u4EF6\uFF1A${g.type}`,{eventType:g.type})),g.type==="tool_use"&&R("Agent \u8C03\u7528\u5DE5\u5177",{toolName:g.toolName}),(g.type==="text"||g.type==="thinking")&&Date.now()-oe>5e3&&(oe=Date.now(),R(g.type==="thinking"?"Agent \u6B63\u5728\u63A8\u7406":"Agent \u8F93\u51FA\u5185\u5BB9",{eventType:g.type,preview:g.content?.replace(/\s+/g," ").slice(0,120)})),v({type:"design.agent_event",event:g}),(g.type==="tool_use"||g.type==="tool_result")&&X())},"onEvent"),onAgentLifecycle:n(g=>{R(Qs(g),Zs(g))},"onAgentLifecycle"),onValidationStart:n(g=>{R("\u5F00\u59CB\u6821\u9A8C\u6D41\u7A0B\u65B9\u6848\u914D\u7F6E",{round:g}),p.advanceDetached({phase:"validating",confirmed:f,round:g,errors:[]},U)},"onValidationStart"),onValidation:n((g,ee)=>{R(g.valid?"\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u901A\u8FC7":`\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u53D1\u73B0 ${g.errors.length} \u4E2A\u95EE\u9898`,{round:ee,valid:g.valid,errorCount:g.errors.length}),p.setDiagnostics({timeline:B,recentAgentEvents:$,validation:g}),p.advanceDetached({phase:"validating",confirmed:f,round:ee,errors:g.errors},U),X()},"onValidation")});if(!q.success){await X(),p.setDiagnostics({timeline:B,recentAgentEvents:$,...q.validation?{validation:q.validation}:{}}),await p.advance({phase:"generate_failed",confirmed:f,error:{code:"DESIGN_VALIDATION_FAILED",message:q.response,retryable:!0}}),await Or(a,p,q.response),o.end();return}await p.advance({phase:"syncing_schema",confirmed:f}),R("\u540C\u6B65\u5B57\u6BB5\u8BA1\u5212\u5230\u914D\u7F6E");for(let g of h.workflows)await Us({workflowPath:g.workflowPath,configPath:E,autoUpdate:!0}).catch(ee=>(Fe.warn("design","\u5B57\u6BB5\u540C\u6B65\u5931\u8D25(\u4E0D\u963B\u65AD)",{workflow:g.id,error:j(ee)}),null));await X(),R("\u5199\u5165 Design \u4EA7\u7269\u6E05\u5355");let Vr=await D(a),ut=Xs(a,p,Vr);await et(a,ut),p.setDiagnostics({timeline:B,recentAgentEvents:$,...q.validation?{validation:q.validation}:{}}),await p.advance({phase:"ready",confirmed:f,manifest:ut,rounds:q.rounds}),o.end()}catch(h){await X().catch(()=>{}),p.setDiagnostics({timeline:B,recentAgentEvents:$}),await p.advance({phase:"generate_failed",confirmed:f,error:{code:W(h)==="INTERNAL_ERROR"?"DESIGN_GENERATION_FAILED":W(h),message:j(h),retryable:!0,details:C(h)}}).catch(E=>{Fe.warn("design-runtime","\u5199\u5165\u5931\u8D25\u72B6\u6001\u672A\u6210\u529F",{error:j(E)})}),await Or(a,p,j(h)).catch(()=>{}),v({type:"error",error:ie(h)}),o.end()}finally{jt(a.id)}}n(_r,"handleDesign");function Vs(t){return t.type!=="text"&&t.type!=="thinking"?!0:typeof t.content=="string"&&t.content.trim().length>0}n(Vs,"isDisplayableAgentEvent");function Ys(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}}n(Ys,"summarizeAgentEvent");function Qs(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"}}n(Qs,"agentLifecycleMessage");function Zs(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}:{}}}n(Zs,"sanitizeAgentLifecycle");function Xs(t,e,r){let o=r.filter(a=>en(a.path)).map(a=>({path:a.path,kind:tn(a.path),checksum:he(a.content),required:rn(a.path)})),s=o.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:s,generated:o,validation:{passed:!0,errors:[],warnings:[]},createdAt:e.startedAt??i,updatedAt:i}}n(Xs,"buildDesignManifest");function en(t){return t==="workflow.yml"||t.startsWith("recipes/")||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(t)||/^workflows\/[^/]+\/recipes\/.+\.(ts|js)$/.test(t)}n(en,"isDesignArtifactPath");function tn(t){return t.endsWith("workflow.yml")||t.endsWith("workflow.yaml")?"workflow":"recipe"}n(tn,"designArtifactKind");function rn(t){return!0}n(rn,"isRequiredDesignArtifact");async function Or(t,e,r){let o=new Date().toISOString();await et(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??o,updatedAt:o})}n(Or,"writeInvalidDesignManifest");import{loadSettings as un,resolveConfigPath as ln,loadWorkflowTemplate as fn,initTable as mn,ensureTableExists as gn,runWithExecutor as wn,runWithDwsRunner as hn,DwsError as Sn,logger as yn}from"aitable-workflow-core";var on={singleSelect:"single_select",multipleSelect:"multiple_select",date:"datetime"},sn={Grid:"grid",FormDesigner:"form",Kanban:"kanban",Calendar:"calendar",Gantt:"gantt"};function Wr(t,e){let r=new Map,o=new Map((t.tracker.field_definitions??[]).map(c=>[c.name,c])),s=n((c,p,d="text",w)=>{if(!c?.trim()||r.has(c))return;let f=o.get(c);r.set(c,{id:pn(c),name:c,type:cn(f?.type??d),...f?.options??w?{options:f?.options??w}:{},group:p})},"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",an(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 i=nn(t.tracker.views??[],e).map(c=>({id:c.id,name:c.name,kind:sn[c.type]??"grid",desc:c.description??dn(c)})),a=[...r.values()];return{fieldCount:a.length,viewCount:i.length,fields:a,views:i}}n(Wr,"buildSetupSchemaSummary");function nn(t,e){let r=[],o=2;for(let s of t){if(!s.for_each_step){r.push(s);continue}let i=e.steps.filter(a=>s.for_each_step==="needs_human"?!!a.needs_human:!0);for(let a of i){let c=String.fromCodePoint(9311+o);r.push({...s,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??s.description,for_each_step:void 0}),o++}}return r}n(nn,"expandViews");function an(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,o)=>!!e&&o.indexOf(e)===r)}n(an,"stateOptions");function cn(t){return on[t]??t}n(cn,"displayFieldType");function pn(t){return`fld_${t.replace(/[^\p{L}\p{N}]+/gu,"_").replace(/^_+|_+$/g,"")||"field"}`}n(pn,"fieldId");function dn(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"}n(dn,"viewDescription");var ct=new Set;async function pt(t,e,r,o,s){let i=await k(e,t);try{s.ensureAvailable()}catch(l){S(o,se(l),W(l),j(l));return}if(ct.has(i.id)){S(o,409,"SETUP_IN_PROGRESS","AI \u8868\u683C\u642D\u5EFA\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019\u3002");return}let a=await z.open({project:i,stage:"setup",store:r,driver:"setup.stream",facts:n(()=>K(i.id,"setup",{hasRunSession:n(()=>!1,"hasRunSession")}),"facts")});ct.add(i.id),ne(o);let c=n(l=>Ae(o,l.type,l),"send");a.emit=l=>c({type:"stage.changed",stage:"setup",stageState:l});let p=n((l,v)=>{yn.info("setup",l,{projectId:i.id,taskId:a.taskId,...v?{detail:v}:{}})},"trace"),d=[],w=s.buildSetupExecutor({projectId:i.id,projectDir:i.dir}),f=s.buildDwsRunner();try{await wn(w,async()=>{await hn(f,async()=>{await a.advance({phase:"preflight"}),p("\u52A0\u8F7D\u914D\u7F6E\u4E0E\u5DE5\u4F5C\u6D41\u6A21\u677F");let l=await un(L(i),{lenientEnv:!0}),v=await fn(l.workflowTemplatePath,{envSource:l.envSource}),M=l.tracker.base_id==="__placeholder__"?void 0:l.tracker,b=M??v.tracker,oe=!!b&&!b.table_id.trim();if(b&&!b.table_id.trim()){await a.advance({phase:"provisioning_table"});let R=M?await ln(L(i)):l.workflowTemplatePath,Pe=M?l:{...l,tracker:b},fe=await gn({trackerFilePath:R,settings:Pe,workflow:v,onProgress:n((me,X)=>p(me,{checkpoint:X}),"onProgress")});l={...l,tracker:fe.tracker}}await a.advance({phase:"syncing_schema",warnings:[]}),p("\u5F00\u59CB\u521B\u5EFA\u5B57\u6BB5\u548C\u89C6\u56FE");let B=await mn({settings:l,workflow:v,cleanEmptyRows:!0,tableJustCreated:oe});d.push(...B.warnings.map(R=>R.message));let $=Wr(l,v);await _(i),await a.advance({phase:"ready",tableUrl:Ft(l.tracker.base_id,l.tracker.table_id),baseId:l.tracker.base_id,tableId:l.tracker.table_id,schema:$,warnings:d}),o.end()})})}catch(l){if(vn(l)){await a.advance({phase:"auth_awaiting",error:{code:"SETUP_AUTH_REQUIRED",message:`\u6388\u6743\u6216\u6743\u9650\u4E0D\u8DB3\uFF1A${j(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"}}}),o.end();return}await a.advance({phase:"failed",error:{code:W(l),message:j(l),retryable:!0,details:C(l)}}),c({type:"error",error:ie(l)}),o.end()}finally{ct.delete(i.id)}}n(pt,"handleSetup");function vn(t){let e=j(t).toLowerCase(),r=t instanceof Sn?t.stderr.toLowerCase():"",o=`${e} ${r}`;return["auth","login","permission","unauthorized","forbidden","access denied"].some(s=>o.includes(s))}n(vn,"isSetupAuthBlocker");var x=class{ctx;serverServices;async taskAction(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project,o=this.ctx.params.stage??"",s=this.ctx.params.taskAction??"",i=s==="start"||s==="continue"||s==="retry";if(i&&o==="setup"){await T(r,e),await pt(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution);return}if(i&&o==="run"){await T(r,e),await ue(e).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 br(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 o=await I(this.ctx.req);await Er(r.id,e.workspace,e.projectStore.instances,o,this.ctx.res)}async design(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e);let o=new URL(this.ctx.req.url??"/","http://localhost"),s=Dt(o,this.ctx.req);await _r(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution,s),await we(e,r,"design")}async designEvents(){this.ctx.respond=!1,Fr(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 pt(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution),await we(e,r,"setup")}async runHumanAction(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e),await Jt(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;await T(r,e),await ue(e).start(r.id,this.ctx.res)}async runStop(){let e=await ue(this.serverServices).stop(this.ctx.state.project.id);this.ctx.respond=!1,m(this.ctx.res,e)}async runStatus(){let e=await ue(this.serverServices).status(this.ctx.state.project.id);this.ctx.respond=!1,m(this.ctx.res,e)}async runRecords(){let e=Number(je(this.ctx.query?.limit)),r=Number.isInteger(e)&&e>0?e:void 0,o=await ue(this.serverServices).listRecords(this.ctx.state.project.id,{limit:r});this.ctx.respond=!1,m(this.ctx.res,o)}};n(x,"StagesController"),u([Nr()],x.prototype,"ctx",2),u([Nr()],x.prototype,"serverServices",2),u([re("/:projectId/tasks/:stage/:taskAction")],x.prototype,"taskAction",1),u([re("/:projectId/design/discovery")],x.prototype,"designDiscovery",1),u([re("/:projectId/design/discovery/confirm")],x.prototype,"designDiscoveryConfirm",1),u([re("/:projectId/design")],x.prototype,"design",1),u([dt("/:projectId/design/events")],x.prototype,"designEvents",1),u([re("/:projectId/setup")],x.prototype,"setup",1),u([re("/:projectId/run/records/:recordId/human-action")],x.prototype,"runHumanAction",1),u([re("/:projectId/run")],x.prototype,"run",1),u([re("/:projectId/run/stop")],x.prototype,"runStop",1),u([dt("/:projectId/run/status")],x.prototype,"runStatus",1),u([dt("/:projectId/run/records")],x.prototype,"runRecords",1),x=u([Pn("/api/projects")],x);import*as qe from"@midwayjs/core";import*as Kn from"@midwayjs/koa";import{createApp as Hn,logger as Gn}from"aitable-workflow-core";var We=class{static{n(this,"LocalProjectRepository")}workspace;constructor(e){this.workspace=e}async create(e,r){let o=await bt(this.workspace),s=[];if(r?.files&&r.files.length>0){let i=await Ie(o,r.files);s.push(...i.warnings);let a=await _(o);return r.title&&r.title.trim()&&(a=await ce(a,{title:r.title.trim()})),{...a,files:i.written,warnings:s}}if(r?.title&&r.title.trim()){let i=await ce(o,{title:r.title.trim()});return s.length?{...i,warnings:s}:{...i}}return s.length?{...o,warnings:s}:{...o}}async list(e){return Xe(this.workspace)}async resolve(e,r){return k(this.workspace,e)}async updateMeta(e,r,o){return ce(e,r)}async delete(e,r){await xe(e)}async updateFiles(e,r,o){return r.remove&&r.remove.length>0&&await nr(e,r.remove),r.upsert&&r.upsert.length>0&&await Ie(e,r.upsert),await _(e),D(e)}async replaceFiles(e,r,o){return await ir(e,r),await _(e),D(e)}async exportProject(e,r){return ar(e)}async syncHotFields(){}};import{randomUUID as jn}from"crypto";import{mkdir as Dn,readFile as xn,rm as Tn,writeFile as On}from"fs/promises";import ye from"path";import{applyRunExecutionEvent as kn,emptyProjectState as Rn,mergeStageIntoState as Lr,normalizeProjectState as In,patchRunSnapshotRecord as bn,recoverDesignFromArtifacts as An,stageStateOf as En}from"aitable-workflow-core";var Ne=new Map,Fn=/^[a-zA-Z0-9_-]+$/,Le=class{static{n(this,"LocalWorkflowInstanceStore")}workspace;constructor(e){this.workspace=e}getState(e){return le(e)}getRecoverableState(e){return Bn(e)}createStageIdentity(e,r){return Nn(e,r)}putStageState(e,r,o){return Ln(e,r,o)}appendRunSnapshotEvent(e,r){return Mn(e,r)}updateRunSnapshotRecord(e,r,o,s){return Cn(e,r,o,s)}deleteProjectState(e){return _n(this.workspace,e)}};async function _n(t,e){$r(e);let r=Wn(t,e);await Tn(ye.join(r,"runtime"),{recursive:!0,force:!0})}n(_n,"deleteProjectState");function Wn(t,e){return $r(e),ye.join(t.projectsRoot,e)}n(Wn,"projectDir");async function Nn(t,e){let o=((await le(t)).stages[e]?.identity.attempt??0)+1,s=new Date().toISOString();return{id:`task_${jn().slice(0,8)}`,projectId:t.id,stage:e,attempt:o,startedAt:s,updatedAt:s}}n(Nn,"createStageIdentity");async function Ln(t,e,r){return Me(t,async()=>{let o=await le(t),s=Lr(o,e,r);return await ve(t,s),s})}n(Ln,"putStageState");async function le(t){await Br(t);let e=await xn(Cr(t),"utf8").catch(()=>"");if(e.trim()){let r=Un(e),o=In(t,r);return r.repaired&&await ve(t,o),o}return Rn(t)}n(le,"getState");async function Mn(t,e){return Me(t,async()=>{let r=await le(t),o=kn(r.runSnapshot??{records:[],logs:[]},e),s={...r,runSnapshot:o,updatedAt:new Date().toISOString()};return await ve(t,s),s})}n(Mn,"appendRunSnapshotEvent");async function Cn(t,e,r,o){return Me(t,async()=>{let s=await le(t);if(!s.runSnapshot)return s;let i={...s,runSnapshot:bn(s.runSnapshot,e,r,o),updatedAt:new Date().toISOString()};return await ve(t,i),i})}n(Cn,"updateRunSnapshotRecord");async function Bn(t){return Me(t,async()=>{let e=await le(t),r=En(e,"design"),o=await Et(t),s=An(r,o);if(!s)return e;let i=e.stages.design;if(!i)return e;let a=new Date().toISOString(),c=Lr(e,"design",{...i,state:s,identity:{...i.identity,updatedAt:a,completedAt:i.identity.completedAt??a}});return await ve(t,c),c})}n(Bn,"getRecoverableState");function Mr(t){return ye.join(t.dir,"runtime")}n(Mr,"runtimeDir");function $n(t){return ye.join(Mr(t),"artifacts")}n($n,"artifactsDir");function Cr(t){return ye.join(Mr(t),"state.json")}n(Cr,"statePath");async function Br(t){await Dn($n(t),{recursive:!0})}n(Br,"ensureRuntimeDirs");async function ve(t,e){await Br(t),await On(Cr(t),`${JSON.stringify(e,null,2)}
|
|
17
|
-
`,"utf8")}
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aitable-workflow-server",
|
|
3
|
-
"version": "0.1.28
|
|
3
|
+
"version": "0.1.28",
|
|
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,9 +22,10 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"aitable-workflow-core": "0.1.28
|
|
25
|
+
"aitable-workflow-core": "0.1.28",
|
|
26
26
|
"@midwayjs/core": "^3.20.4",
|
|
27
27
|
"@midwayjs/koa": "^3.20.4",
|
|
28
|
+
"fflate": "^0.8.2",
|
|
28
29
|
"yaml": "^2.8.1"
|
|
29
30
|
}
|
|
30
31
|
}
|