dsh-auto-flow 0.1.4 → 0.1.6

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/lib/client.js CHANGED
@@ -7225,12 +7225,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7225
7225
  * 写 `'*'` 等于广播给任何来源。
7226
7226
  */
7227
7227
  function postHostContext(frame, context, targetOrigin) {
7228
- frame?.contentWindow?.postMessage({
7229
- type: HOST_CONTEXT_MESSAGE_TYPE,
7230
- theme: context.theme,
7231
- sessionId: context.sessionId,
7232
- hostOrigin: context.hostOrigin
7233
- }, targetOrigin);
7228
+ const target = frame?.contentWindow;
7229
+ if (target === null || target === void 0) return;
7230
+ try {
7231
+ target.postMessage({
7232
+ type: HOST_CONTEXT_MESSAGE_TYPE,
7233
+ theme: context.theme,
7234
+ sessionId: context.sessionId,
7235
+ hostOrigin: context.hostOrigin
7236
+ }, targetOrigin);
7237
+ } catch {}
7234
7238
  }
7235
7239
  //#endregion
7236
7240
  //#region \0dsh-css:C:\Users\Administrator\Desktop\projects\dsh\dsh-plugins\packages\business\dsh-auto-flow\src\client\features\workflow-overlay\WorkflowOverlay.module.css.mjs
@@ -7245,14 +7249,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7245
7249
  }
7246
7250
  var WorkflowOverlay_module_css_default = {
7247
7251
  "bar": "_3sfATW_bar",
7248
- "stage": "_3sfATW_stage",
7249
- "frame": "_3sfATW_frame",
7250
- "noticeActions": "_3sfATW_noticeActions",
7252
+ "notice": "_3sfATW_notice",
7253
+ "noticeText": "_3sfATW_noticeText",
7251
7254
  "dialog": "_3sfATW_dialog",
7255
+ "noticeActions": "_3sfATW_noticeActions",
7252
7256
  "layer": "_3sfATW_layer",
7253
7257
  "noticeReason": "_3sfATW_noticeReason",
7254
- "notice": "_3sfATW_notice",
7255
- "noticeText": "_3sfATW_noticeText"
7258
+ "frame": "_3sfATW_frame",
7259
+ "stage": "_3sfATW_stage"
7256
7260
  };
7257
7261
  //#endregion
7258
7262
  //#region src/client/features/workflow-overlay/WorkflowOverlay.tsx
package/lib/index.js CHANGED
@@ -22,6 +22,7 @@ import { zValidator } from "@hono/zod-validator";
22
22
  import { Hono } from "hono";
23
23
  import { bodyLimit } from "hono/body-limit";
24
24
  import { HTTPException } from "hono/http-exception";
25
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
25
26
  //#region ../../shared/workflow/src/approval.ts
26
27
  /** 审批节点的默认选项:通过(继续)/ 驳回(中止)。 */
27
28
  const DEFAULT_APPROVAL_OPTIONS = [{
@@ -11598,6 +11599,93 @@ function missingParam(issue) {
11598
11599
  return name === void 0 ? "查询串结构不符合约定" : `缺少查询参数 ${String(name)}`;
11599
11600
  }
11600
11601
  //#endregion
11602
+ //#region src/host/features/app-unit/unit-token.ts
11603
+ /**
11604
+ * 单元入口的**自有令牌**与同源判据 —— 桌面端能打开面板的原因。
11605
+ *
11606
+ * 【它解决什么】桌面端顶层文档的 origin 是自定义协议(实测控制台里的 `dsh-app://app`),而单元是
11607
+ * `http://127.0.0.1:<端口>`:两者**跨站**。宿主的门靠一枚 `SameSite=Strict` 的签名 cookie 记住认证
11608
+ * (见 `@deepseek-ai/dsh-host-*` 的 `sessionCookie`),而跨站 iframe 里那个 cookie **永远不会被发送**
11609
+ * —— 于是"令牌换 cookie"那一步永远白做,入口每次都是 401。浏览器形态(`dsh web`,顶层也在
11610
+ * `http://127.0.0.1`)没有这个问题:那里同站,cookie 正常。
11611
+ *
11612
+ * 本模块给出两条不依赖 cookie 的判据(合起来由 `gateOf` 用在宿主门之前):
11613
+ * 1. **地址里的令牌**({@link hasUnitToken}):装配点把令牌拼进单元地址,门在**任意路径**上认它。
11614
+ * 宿主的门只在 `GET /` 上认一次令牌、随后 303 丢掉,所以它必须靠 cookie 续命。
11615
+ * 2. **同源请求**({@link isSameOrigin}):单元自己的页面发起的取数与帧内刷新走这一条。
11616
+ *
11617
+ * 【为什么令牌要绑定 authority】`hmac(secret, host)` 里的 host 取自请求的 `Host` 头(`127.0.0.1:<端口>`):
11618
+ * 一个单元地址上的令牌拿到另一个单元上不成立 —— 单元之间不互相开门。
11619
+ *
11620
+ * 【为什么是 HMAC 而不是随机串比对】随机串得存一份;HMAC 只用"每进程一份的 secret"就能按 authority
11621
+ * 现场算出来,比较还走常数时间。secret 不落盘、不进日志,重启即全部失效 —— 与"地址由宿主现发"一致。
11622
+ */
11623
+ /** 令牌在单元地址里的查询串键名。 */
11624
+ const UNIT_TOKEN_PARAM = "unitToken";
11625
+ /**
11626
+ * 造一份本进程的签名 secret。
11627
+ *
11628
+ * @returns 32 字节随机数(不落盘、不进日志)。
11629
+ */
11630
+ function createUnitTokenSecret() {
11631
+ return randomBytes(32);
11632
+ }
11633
+ /**
11634
+ * 算某个 authority 的单元令牌。
11635
+ *
11636
+ * @param secret - {@link createUnitTokenSecret} 的产物。
11637
+ * @param authority - 请求的 `Host` 头取值(例如 `127.0.0.1:5174`)。
11638
+ * @returns base64url 文本(URL 安全,可直接放进查询串)。
11639
+ */
11640
+ function unitTokenOf(secret, authority) {
11641
+ return createHmac("sha256", secret).update(authority).digest("base64url");
11642
+ }
11643
+ /**
11644
+ * 把令牌拼进单元地址。
11645
+ *
11646
+ * @param url - 宿主给的地址(它自己的令牌已经在里面)。
11647
+ * @param secret - 本进程的 secret。
11648
+ * @returns 追加了 `unitToken` 的地址;authority 与其余查询串保持不变。
11649
+ */
11650
+ function withUnitToken(url, secret) {
11651
+ const parsed = new URL(url);
11652
+ parsed.searchParams.set(UNIT_TOKEN_PARAM, unitTokenOf(secret, parsed.host));
11653
+ return parsed.href;
11654
+ }
11655
+ /**
11656
+ * 这条请求带的令牌对不对。
11657
+ *
11658
+ * @param secret - 本进程的 secret。
11659
+ * @param request - 请求(读 `Host` 与 `url`)。
11660
+ * @returns 地址里的 `unitToken` 与本 authority 的期望值**完全一致**时为 `true`;缺 `Host`、缺令牌、
11661
+ * 长度不符或值不符都是 `false`。
11662
+ */
11663
+ function hasUnitToken(secret, request) {
11664
+ const authority = request.headers.host;
11665
+ if (authority === void 0 || authority === "") return false;
11666
+ const presented = new URL(request.url ?? "/", "http://unit.invalid").searchParams.get(UNIT_TOKEN_PARAM);
11667
+ if (presented === null) return false;
11668
+ const actual = Buffer.from(presented, "utf8");
11669
+ const expected = Buffer.from(unitTokenOf(secret, authority), "utf8");
11670
+ return actual.byteLength === expected.byteLength && timingSafeEqual(actual, expected);
11671
+ }
11672
+ /**
11673
+ * 这条请求是不是**单元自己的页面**发起的。
11674
+ *
11675
+ * 【为什么这条可以当判据】`Sec-Fetch-Site` 由浏览器自己写,页面里的 JS 不能伪造它;跨站页面发起的
11676
+ * 请求标 `cross-site`,被这一条挡在外面。它覆盖两件"地址里的令牌"覆盖不到的事:单元前端对自己
11677
+ * `/api` 的取数,以及帧内刷新/深链(带令牌的那一次导航之后,地址栏里就没有令牌了)。
11678
+ *
11679
+ * 【已知代价,明写】非浏览器的**本地进程**可以自己伪造这个请求头,而宿主的签名 cookie 伪造不了 ——
11680
+ * 这是为了让桌面端能用而接受的放宽。浏览器侧的跨站攻击面没有变化(那一档本来就进不来)。
11681
+ *
11682
+ * @param request - 请求。
11683
+ * @returns `Sec-Fetch-Site: same-origin` 时为 `true`(其余取值一律 `false`)。
11684
+ */
11685
+ function isSameOrigin(request) {
11686
+ return request.headers["sec-fetch-site"] === "same-origin";
11687
+ }
11688
+ //#endregion
11601
11689
  //#region src/host/features/app-unit/connection.ts
11602
11690
  /**
11603
11691
  * 读 `connection` 服务。
@@ -11613,16 +11701,30 @@ function connectionOf(ctx) {
11613
11701
  return connection;
11614
11702
  }
11615
11703
  /**
11616
- * 把平台的门折成 `app-unit` 的 `gate`。
11704
+ * 把平台的门折成 `app-unit` 的 `gate` —— 并在它**之前**加上我们自己的两条判据。
11705
+ *
11706
+ * 【为什么要加】宿主的门靠一枚 `SameSite=Strict` 的签名 cookie 记住认证;桌面端顶层文档是自定义协议
11707
+ * (实测控制台里的 `dsh-app://app`)而单元在 `http://127.0.0.1:<端口>`:两者跨站,那枚 cookie 在跨站
11708
+ * iframe 里**永远不会被发送** —— 于是"令牌换 cookie"白做,入口每次 401(现象:"dsh web authentication
11709
+ * required",面板打不开)。我们自己的判据(地址里的令牌 / `Sec-Fetch-Site: same-origin`)不依赖 cookie,
11710
+ * 桌面端与浏览器端都成立;判据与已知代价写在 `./unit-token.ts` 的文件头。
11617
11711
  *
11618
- * 【两个方法为什么直通、不加工】档位差异(入口可以自己作答 303/401;其余只回答"放行还是拒绝")是
11619
- * 上游的语义,本插件不再叠一层 —— 复述一遍就是给自己造第二个真源。
11712
+ * 【为什么保留宿主那两条兜底】没有我们令牌的地址(例如有人直接拿宿主打印的地址访问)仍然按宿主的规则
11713
+ * 走:浏览器形态下 `authorizeIndex` 照旧走"令牌换 cookie",行为与改动前一致。
11620
11714
  */
11621
- function gateOf(ctx) {
11715
+ function gateOf(ctx, secret) {
11622
11716
  const connection = connectionOf(ctx);
11717
+ /** 我们自己的两条判据:命中就不去打扰宿主的门(宿主那条会写响应或作答 401)。 */
11718
+ const ours = (request) => hasUnitToken(secret, request) || isSameOrigin(request);
11623
11719
  return {
11624
- authorizeIndex: (req, res) => connection.authorizeIndex(req, res),
11625
- requestRejection: (req) => connection.requestRejection(req)
11720
+ authorizeIndex: (req, res) => {
11721
+ if (ours(req)) return true;
11722
+ return connection.authorizeIndex(req, res);
11723
+ },
11724
+ requestRejection: (req) => {
11725
+ if (ours(req)) return void 0;
11726
+ return connection.requestRejection(req);
11727
+ }
11626
11728
  };
11627
11729
  }
11628
11730
  //#endregion
@@ -11665,15 +11767,16 @@ const WORKSPACE_LIST_TIMEOUT_MS = 1e4;
11665
11767
  * @throws 装配接口本身形状不对时同步抛出(那是本文件自己的错误,与"端口被占用"这类环境问题不同)。
11666
11768
  */
11667
11769
  function mountUnits(ctx, deps) {
11770
+ const secret = createUnitTokenSecret();
11668
11771
  return mountAppUnits(ctx, {
11669
11772
  pluginDir: pluginDirOf(),
11670
11773
  units: APP_UNITS,
11671
- gate: gateOf(ctx),
11774
+ gate: gateOf(ctx, secret),
11672
11775
  bff: () => createEditorHandler({
11673
11776
  ...deps,
11674
11777
  listWorkspaceDir: workspaceDirLister(ctx)
11675
11778
  }),
11676
- authenticate: (origin) => connectionOf(ctx).authenticatedUrl(`${origin}/`),
11779
+ authenticate: (origin) => withUnitToken(connectionOf(ctx).authenticatedUrl(`${origin}/`), secret),
11677
11780
  onNotice: (message) => {
11678
11781
  ctx.logger.warn("auto-flow: %s", message);
11679
11782
  }
@@ -0,0 +1,226 @@
1
+ import { z } from "zod";
2
+ //#region ../../shared/script-contract/src/types.ts
3
+ const JsonValueSchema = z.lazy(() => z.union([
4
+ z.string(),
5
+ z.number(),
6
+ z.boolean(),
7
+ z.null(),
8
+ z.array(JsonValueSchema),
9
+ z.record(z.string(), JsonValueSchema)
10
+ ]));
11
+ z.record(z.string(), JsonValueSchema);
12
+ /** 下拉选项(label = 展示,value = 传给脚本的值)。 */
13
+ const ScriptSelectOptionSchema = z.object({
14
+ label: z.string(),
15
+ value: JsonValueSchema
16
+ });
17
+ /** 显隐条件:判据键取到该值时才显示本字段。 */
18
+ /**
19
+ * 字段条件的运算符白名单(**真源在这里**,`workflow` 的 `FieldCondition` 直接用它)。
20
+ *
21
+ * 【为什么放在最底层】`workflow` 依赖 `script-contract`(产物规则的真源在这里),
22
+ * 所以共用词汇只能由下层定义、上层复用 —— 反向依赖会造出一个环。
23
+ * 与条件节点的 `CONDITION_OPERATORS` 同一套思路:宁可少几种写法,也不要一个能执行任意代码的入口。
24
+ */
25
+ const SCRIPT_FIELD_CONDITION_OPERATORS = [
26
+ "eq",
27
+ "not",
28
+ "gte",
29
+ "lte",
30
+ "gt",
31
+ "lt",
32
+ "startsWith",
33
+ "endsWith",
34
+ "includes",
35
+ "regex",
36
+ "exists"
37
+ ];
38
+ const ScriptParamVisibilitySchema = z.lazy(() => z.object({
39
+ key: z.string(),
40
+ op: z.enum(SCRIPT_FIELD_CONDITION_OPERATORS).optional(),
41
+ value: JsonValueSchema.optional(),
42
+ values: z.array(JsonValueSchema).optional()
43
+ }));
44
+ const ScriptParamVariantSchema = z.lazy(() => z.object({
45
+ when: z.string(),
46
+ value: JsonValueSchema,
47
+ children: z.array(ScriptParamFieldSchema)
48
+ }));
49
+ const ScriptParamFieldSchema = z.lazy(() => z.object({
50
+ key: z.string(),
51
+ label: z.string(),
52
+ type: z.enum([
53
+ "string",
54
+ "number",
55
+ "boolean",
56
+ "select",
57
+ "datetime",
58
+ "array",
59
+ "object",
60
+ "file"
61
+ ]),
62
+ required: z.boolean().optional(),
63
+ defaultValue: JsonValueSchema.optional(),
64
+ options: z.array(ScriptSelectOptionSchema).optional(),
65
+ multiple: z.boolean().optional(),
66
+ format: z.string().optional(),
67
+ placeholder: z.string().optional(),
68
+ description: z.string().optional(),
69
+ children: z.array(ScriptParamFieldSchema),
70
+ variants: z.array(ScriptParamVariantSchema).optional(),
71
+ discriminantOptions: z.array(ScriptSelectOptionSchema).optional(),
72
+ discriminantKey: z.object({
73
+ key: z.string(),
74
+ label: z.string()
75
+ }).optional(),
76
+ visibleWhen: ScriptParamVisibilitySchema.optional()
77
+ }));
78
+ /**
79
+ * 产物装配规则:告诉工作流引擎「本脚本产出的文件路径放在返回数据的哪个键上」。
80
+ *
81
+ * 为什么需要它:工作流下游脚本节点的 payload 由「上游表单值 + 上游脚本返回值 + 上游产物文件」
82
+ * 三路合并而成(auto-flow 的 src/workflow/payload.ts),而产物文件注入哪个键由**下游脚本**声明。
83
+ * 不声明则工作流拿不到文件,只会拿到路径字符串。
84
+ */
85
+ const ScriptArtifactSpecSchema = z.object({
86
+ /** 返回数据里存放文件路径列表的键名。 */
87
+ filesKey: z.string().optional(),
88
+ /** 路径的形状(缺省按普通路径列表处理;prompt-pairs 表示每份产物配一组提示词)。 */
89
+ filesShape: z.enum(["paths", "prompt-pairs"]).optional(),
90
+ /** 与图片一一对应的提示词所在键(仅图片类产物用)。 */
91
+ filesPromptKey: z.string().optional()
92
+ });
93
+ z.object({
94
+ /** 库内脚本名(稳定路由键,如 `dxf/analyze`);对外身份是 `<来源 id>/<本名>`。 */
95
+ name: z.string(),
96
+ /** 展示名。 */
97
+ label: z.string(),
98
+ /** 用途说明(供 listScripts / 模型工具展示)。 */
99
+ description: z.string(),
100
+ /** 参数清单(JSON 安全,供工作流 UI 渲染表单)。 */
101
+ params: z.array(ScriptParamFieldSchema),
102
+ /** 产物装配规则(缺省不消费上游文件)。 */
103
+ artifacts: ScriptArtifactSpecSchema.optional()
104
+ });
105
+ const ScriptErrorSchema = z.object({
106
+ /** 稳定错误码(机器可路由)。 */
107
+ code: z.string(),
108
+ /** 给人看的说明。 */
109
+ message: z.string()
110
+ });
111
+ const ScriptRunMetaSchema = z.object({
112
+ startedAt: z.number(),
113
+ finishedAt: z.number(),
114
+ durationMs: z.number()
115
+ });
116
+ z.discriminatedUnion("ok", [z.object({
117
+ ok: z.literal(true),
118
+ script: z.string(),
119
+ data: JsonValueSchema,
120
+ meta: ScriptRunMetaSchema
121
+ }), z.object({
122
+ ok: z.literal(false),
123
+ script: z.string(),
124
+ error: ScriptErrorSchema,
125
+ meta: ScriptRunMetaSchema
126
+ })]);
127
+ /**
128
+ * 浏览器品牌通道。
129
+ *
130
+ * 【为什么在契约包里而不是某个脚本库】它是 `ScriptRunOptions.browser.channel` 的取值域,
131
+ * 属于运行选项契约的一部分。原先两个脚本库各存一份同名 schema,其中一方多了 `browser`——
132
+ * **同名不同形**,而契约正是为了让工作流引擎不必对脚本库分分支而存在的。
133
+ * 现在取并集:不跑浏览器的脚本库接受并忽略 `browser`,跑浏览器的脚本库照旧使用它。
134
+ *
135
+ * 为什么没有「留空 = 用自带 Chromium」这个状态:自带 Chromium 要额外下载数百 MB,
136
+ * 且与系统浏览器的反检测环境不同;留空会让「没配置」和「显式要求不要品牌通道」两种意图
137
+ * 混在一起,最终静默走到自带浏览器上。需要扩展时在这里加一项,各脚本库的 config 校验与
138
+ * 工作流节点的类型同步生效。
139
+ */
140
+ const BROWSER_CHANNELS = ["msedge", "chrome"];
141
+ /**
142
+ * 判定一个值是不是合法的浏览器品牌通道。
143
+ *
144
+ * 【为什么需要它】`channel` 的来源之一是**用户手写的画布节点数据**(`inline.browser`),
145
+ * 那边取到的只是 `string` —— 信任边界。按本仓库的政策「校验只做在信任边界上,且只做一次」,
146
+ * 校验就在这里做一次;不识别的取值应被**丢弃**,而不是透传给脚本库。
147
+ *
148
+ * @param value - 任意值(通常是节点数据里的 `browser` 字段)。
149
+ * @returns 是取值域内的通道时为 `true`,调用方据此收窄成 {@link BrowserChannel}。
150
+ */
151
+ function isBrowserChannel(value) {
152
+ return typeof value === "string" && BROWSER_CHANNELS.includes(value);
153
+ }
154
+ z.object({
155
+ /** 本次运行的产物根目录(工作流引擎传入;缺省由插件配置兜底)。 */
156
+ baseDir: z.string().optional(),
157
+ /** 本次运行的子目录名(工作流引擎传入 `<序号>-<脚本名>`)。 */
158
+ runId: z.string().optional(),
159
+ /** 浏览器选项;只有驱动浏览器的脚本库会读它,其余脚本库接受并忽略。 */
160
+ browser: z.object({
161
+ headless: z.boolean().optional(),
162
+ channel: z.enum(BROWSER_CHANNELS).optional()
163
+ }).optional(),
164
+ /** 本次运行的硬超时(毫秒;非正数表示不限)。 */
165
+ timeoutMs: z.number().optional()
166
+ });
167
+ //#endregion
168
+ //#region ../../shared/workflow/src/types.ts
169
+ /**
170
+ * 脚本「上游产物文件 → payload」装配规则:真源在共享包 `script-contract`,这里转出。
171
+ * 原先本文件手写了一份同形 interface,与共享契约逐字段相同——纯重复,已消除。
172
+ * 既 import 又 export:本文件下面有接口把它当字段类型用,`export type { X } from` 不会把 X 带进本地作用域。
173
+ */
174
+ /**
175
+ * 重试路径上的**跳过策略**。
176
+ *
177
+ * - `rerun-all`(**默认**):不跳过,该做的都做 —— 与正常执行等价(只是保留同一次运行的身份);
178
+ * - `skip-succeeded`:只补做台账里 `status !== 'ok'` 的 key。
179
+ *
180
+ * 【为什么默认不跳过】默认跳过会让「我改了提示词想重跑」变成一个**用户想不通的静默行为**;
181
+ * 跳过是重试路径上用户显式要的东西,不该成为整个体系的默认。**这是我的判断**,
182
+ * 不是从别处抄的;若认为默认应当跳过,改这一个常量即可,不影响其它设计。
183
+ */
184
+ const RESUME_MODES = ["rerun-all", "skip-succeeded"];
185
+ /** 缺省的重试跳过策略(见 {@link ResumeMode} 的理由)。 */
186
+ const DEFAULT_RESUME_MODE = "rerun-all";
187
+ /**
188
+ * 当前工作流文档格式版本(显式版本化,便于未来演进与迁移)。
189
+ *
190
+ * v2 = item 流:节点有唯一 `name`、引用按名字;`RunStep` 装批的汇总与样本。
191
+ * 旧文档(v1)**响亮拒绝**,不写迁移(项目无历史债务)。
192
+ */
193
+ const WORKFLOW_FORMAT_VERSION = 2;
194
+ /**
195
+ * 节点的一条**运行前必填项**:该字段取到空白就报诊断(运行前 fail-fast)。
196
+ *
197
+ * 取代原先按节点类型写死的 `if / else if` 链 —— 那段链每加一种节点就要改一次校验文件。
198
+ */
199
+ /**
200
+ * 字段条件的运算符白名单:**真源在 `script-contract`**(下层),这里复用。
201
+ *
202
+ * 【为什么不各写一份】`workflow` 依赖 `script-contract`(产物规则的真源在下层),共享词汇
203
+ * 只能由下层定义。各写一份字面量联合虽然结构上相等,但两处漂移时只有运行期的
204
+ * `typert-gen` 结构比对会发现 —— 复用同一个常量就没有这个缝。
205
+ */
206
+ const FIELD_CONDITION_OPERATORS = SCRIPT_FIELD_CONDITION_OPERATORS;
207
+ /** 运行终止事件。 */
208
+ /**
209
+ * 运行**终态**集合:`run-end` 的 `stopReason` 只能取自这里。
210
+ *
211
+ * 【为什么单独成一个常量而不是把字面量写进接口】`RunState['status']` 是 6 值联合
212
+ * (多出 `running` / `waiting` / `crashed`),而一次运行**结束时**只可能是这三者之一:
213
+ * 引擎的三个出口分别置 `completed` / `failed` / `cancelled`;`waiting` 期间
214
+ * `runInner` 根本不返回(审批等待是 `await`),`crashed` 由宿主扫尾赋值、不经 `run()`。
215
+ * 把这三值提成常量,是为了让**发射点**能显式取它 —— 先前那里直接写 `stopReason: state.status`,
216
+ * 类型上把 6 值塞进 3 值(`emit` 通道是 `unknown`,编译器不拦),类型与事实脱节。
217
+ */
218
+ const RUN_TERMINAL_STATUSES = [
219
+ "completed",
220
+ "failed",
221
+ "cancelled"
222
+ ];
223
+ //#endregion
224
+ export { WORKFLOW_FORMAT_VERSION as a, RUN_TERMINAL_STATUSES as i, FIELD_CONDITION_OPERATORS as n, isBrowserChannel as o, RESUME_MODES as r, DEFAULT_RESUME_MODE as t };
225
+
226
+ //# sourceMappingURL=types-DFA-SFER.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-auto-flow",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "可视化工作流编辑器与执行引擎:画布编排、脚本节点、人工审批、运行历史,让 dsh 按确定流程跑长任务。",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -9,13 +9,8 @@
9
9
  ],
10
10
  "license": "MIT",
11
11
  "files": [
12
- "lib/index.js",
13
- "lib/index.d.ts",
14
- "lib/types.js",
15
- "lib/types.d.ts",
16
- "lib/types-*.d.ts",
17
- "lib/client.js",
18
- "lib/client.*.js",
12
+ "lib/*.js",
13
+ "lib/*.d.ts",
19
14
  "lib/typert.host.js",
20
15
  "lib/typert.host.d.ts",
21
16
  "lib/typert.remote-client.js",
@@ -98,11 +93,11 @@
98
93
  "typescript": "^6.0.3",
99
94
  "vitest": "^4.1.8",
100
95
  "app-unit": "0.1.0",
101
- "test-support": "0.1.0",
96
+ "script-contract": "0.1.0",
102
97
  "host-signal": "0.1.0",
103
- "workflow-engine": "0.1.0",
98
+ "test-support": "0.1.0",
104
99
  "workflow": "0.1.0",
105
- "script-contract": "0.1.0"
100
+ "workflow-engine": "0.1.0"
106
101
  },
107
102
  "peerDependencies": {
108
103
  "@deepseek-ai/cordis": "^4.0.4",