@mokuyoaxis/dsh-iris 0.1.1 → 0.1.3
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/CHANGELOG.md +75 -1
- package/README.en.md +259 -0
- package/README.md +70 -7
- package/bin/dsh-iris.js +23 -0
- package/cordis.patch.yml +1 -1
- package/docs/ARCHITECTURE.md +81 -0
- package/docs/FAULT_INJECTION.md +26 -0
- package/docs/PROVIDER_SUBMISSION_CONTRACT.md +60 -0
- package/docs/ROADMAP.md +25 -8
- package/docs/SECURITY.md +53 -0
- package/docs/TASK_SEMANTICS.md +147 -0
- package/docs/assets/diagrams/iris-architecture.drawio +1 -0
- package/docs/assets/diagrams/iris-architecture.png +0 -0
- package/docs/assets/diagrams/iris-architecture.svg +63 -0
- package/docs/assets/diagrams/iris-task-lifecycle.drawio +1 -0
- package/docs/assets/diagrams/iris-task-lifecycle.png +0 -0
- package/docs/assets/diagrams/iris-task-lifecycle.svg +64 -0
- package/docs/assets/diagrams/iris-workflow-compose.drawio +1 -0
- package/docs/assets/diagrams/iris-workflow-compose.png +0 -0
- package/docs/assets/diagrams/iris-workflow-compose.svg +41 -0
- package/docs/assets/examples/iris-flower-generated.webp +0 -0
- package/docs/assets/screenshots/image-task-succeeded.webp +0 -0
- package/docs/assets/screenshots/prompt-general-after.webp +0 -0
- package/docs/assets/screenshots/prompt-general-before.webp +0 -0
- package/docs/assets/screenshots/prompt-general-preview.webp +0 -0
- package/docs/assets/screenshots/prompt-image-before.webp +0 -0
- package/docs/assets/screenshots/prompt-image-preview.webp +0 -0
- package/docs/releases/0.1.2.md +26 -0
- package/docs/releases/0.1.3.md +30 -0
- package/docs/screenshots.md +34 -0
- package/lib/actions.js +609 -175
- package/lib/api.js +122 -18
- package/lib/bundled-skills.js +62 -0
- package/lib/client.js +460 -22
- package/lib/doctor.js +243 -0
- package/lib/index.js +57 -46
- package/lib/prompt-optimizer-config.js +170 -0
- package/lib/prompt-optimizer.js +244 -0
- package/lib/provider-contract.js +234 -0
- package/lib/task-semantics.js +209 -0
- package/lib/tasks.js +473 -29
- package/package.json +13 -4
- package/screenshots.json +6 -0
- package/user_guide.md +84 -3
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# v0.1.3 故障注入矩阵
|
|
2
|
+
|
|
3
|
+
状态:本矩阵全部使用本地 fixture、Fake Provider、Mock Fetch 或临时目录,不发送真实供应商请求。
|
|
4
|
+
|
|
5
|
+
| 场景 | 预期事实 | 自动重复提交 | 证据 |
|
|
6
|
+
|---|---|---:|---|
|
|
7
|
+
| 请求前/上传前失败 | `not_accepted`;可以尝试下一候选 | 仅下一候选一次 | `provider-contract.mjs`、`generation-actions.mjs` |
|
|
8
|
+
| 上传成功、提交响应 500/丢失 | `acceptance=unknown` | 0 | `transcribe-task-acceptance-unknown.mjs`、`video-task-acceptance-unknown.mjs` |
|
|
9
|
+
| 图片 500、断网或缺远端 ID | `acceptance/outcome=unknown` | 0 | `image-task-acceptance-unknown.mjs` |
|
|
10
|
+
| 已受理后结果落盘失败 | 保留已受理结果并返回本地 persist 错误 | 0 | `provider-contract.mjs` |
|
|
11
|
+
| 已受理后轮询 429/500/超时 | `watchState=exhausted`、`outcome=unknown` | 0 | `task-runtime-faults-v2.mjs` |
|
|
12
|
+
| 供应商明确返回任务失败 | `outcome=failed` | 0 | `task-runtime-faults-v2.mjs` |
|
|
13
|
+
| 已成功但下载/本地写入失败 | `outcome=succeeded`、`deliveryState=failed` | 0 | `task-store-v2.mjs`、`image-task-mixed-v2.mjs` |
|
|
14
|
+
| 进程在 submitting 阶段退出 | 无受理证据时转为 unknown,禁止恢复提交 | 0 | `task-store-v2.mjs` |
|
|
15
|
+
| 进程在 accepted/running 阶段退出 | 只恢复观察;供应商缺失则 suspended | 0 | `task-runtime-faults-v2.mjs` |
|
|
16
|
+
| 已成功、交付中途退出 | 保留 succeeded,交付标 failed | 0 | `task-runtime-faults-v2.mjs` |
|
|
17
|
+
| 取消时无法确认远端结果 | `cancelState/outcome=unknown` | 0 | `task-store-v2.mjs`、`task-manual-recovery-v2.mjs` |
|
|
18
|
+
| tasks/config 截断或结构损坏 | 隔离原文件并保留证据 | 0 | `damage.mjs`、`doctor.mjs` |
|
|
19
|
+
| SSE 断开、重连、迟到快照、慢消费者 | 全量快照收敛;旧序号被拒绝;背压只保留最新 | 0 | `api.mjs`、`client.mjs` |
|
|
20
|
+
| 上传中断、过期文件与 `.part` 残留 | 临时文件清理;不影响正式产物 | 0 | `api.mjs` |
|
|
21
|
+
| 旧任务附件超出最近索引 | 从完整任务历史解析,不依赖最近 50 条 | 0 | `generation-actions.mjs` |
|
|
22
|
+
| 人工重新观察/重新交付 | 只轮询或下载,不提交 | 0 | `task-manual-recovery-v2.mjs` |
|
|
23
|
+
| 标为已读/恢复提醒 | 只写本地提醒审计元数据,不改变任务事实 | 0 | `task-manual-recovery-v2.mjs` |
|
|
24
|
+
| 用户知情人工重试 | 独立确认、建立新 Task 关系并归档原提醒 | 明确授权后 1 | `task-manual-recovery-v2.mjs` |
|
|
25
|
+
|
|
26
|
+
矩阵的硬性规则是:只要已有 `accepted` 或 `unknown` 事实,任何自动路径的生成提交次数增量必须为 **0**。人工重试不属于自动恢复;它必须由用户逐次确认,并在数据中保留新旧 Task 的关系。
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Iris Provider 提交契约 v0
|
|
2
|
+
|
|
3
|
+
状态:**v0.1.3 最小内部契约,已覆盖现有生成能力。** 图片、视频、转写与 TTS 均执行本契约;完整 discovery、poll、cancel、download conformance 留到 v0.1.4。
|
|
4
|
+
|
|
5
|
+
## 提交结果
|
|
6
|
+
|
|
7
|
+
Provider `submit()` 必须返回以下四种结构之一:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
{ kind: 'completed', value }
|
|
11
|
+
{ kind: 'accepted', remoteTaskId }
|
|
12
|
+
{ kind: 'not_accepted', error }
|
|
13
|
+
{ kind: 'acceptance_unknown', error }
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- `completed`:同步请求已成功完成,是明确受理证据。
|
|
17
|
+
- `accepted`:异步请求已受理,必须包含非空 `remoteTaskId`。
|
|
18
|
+
- `not_accepted`:有证据确认生成请求未被受理,是唯一允许自动切换候选的结果。
|
|
19
|
+
- `acceptance_unknown`:请求可能已到达供应商,但没有拿到受理证据;必须停止自动提交。
|
|
20
|
+
|
|
21
|
+
适配器抛出的普通异常默认转换为 `acceptance_unknown`。只有显式携带 `acceptance: 'not_accepted'` 的结构化错误才允许 failover;`retryable`、429、500、timeout 或 network 等分类不能单独授权重新提交。
|
|
22
|
+
|
|
23
|
+
## 写前与写后 Hook
|
|
24
|
+
|
|
25
|
+
候选调度必须接收 `beforeAttempt`:
|
|
26
|
+
|
|
27
|
+
1. 生成 Attempt 的 ordinal、Provider 与复合模型身份;
|
|
28
|
+
2. 调用 `beforeAttempt` 原子持久化,并返回稳定、非空的 Attempt ID;Hook 不得覆盖候选身份;
|
|
29
|
+
3. 只有 Hook 成功后才能调用 Provider;
|
|
30
|
+
4. Provider 返回后用 `afterResult` 保存受理事实。
|
|
31
|
+
|
|
32
|
+
`beforeAttempt` 失败时供应商调用次数必须为 0。`afterResult` 失败时,无论供应商结果为何,都必须停止候选调度;若已经受理,受理事实不能因为本地落盘失败而被降级。
|
|
33
|
+
|
|
34
|
+
## 安全错误记录
|
|
35
|
+
|
|
36
|
+
可持久化错误只包含:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"stage": "submit",
|
|
41
|
+
"category": "network",
|
|
42
|
+
"acceptance": "unknown",
|
|
43
|
+
"retryable": true,
|
|
44
|
+
"httpStatus": 503,
|
|
45
|
+
"providerCode": "optional-safe-code",
|
|
46
|
+
"safeMessage": "redacted message"
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
错误 stage 固定为 `validate/prepare/upload/submit/response/poll/cancel/download/persist/emit`;category 固定为 `invalid_request/authentication/quota/rate_limit/network/timeout/aborted/provider/protocol/local_io/unknown`。
|
|
51
|
+
|
|
52
|
+
错误记录不得包含 `cause`、stack、请求体、响应正文、API Key、Authorization、POSIX/Windows 私有绝对路径或签名 URL。调用方可以在当前进程中保留原始异常用于调试,但不得把它当作 Task/Attempt JSON 或事件载荷。
|
|
53
|
+
|
|
54
|
+
## 当前接入边界
|
|
55
|
+
|
|
56
|
+
`lib/provider-contract.js`、Task v2 复制落盘原语和零网络 Fake Provider 已冻结本契约。完整图片能力现在都会在请求前写入 Attempt:DashScope 旧异步返回远端 ID 后进入观察;DashScope 新同步与 OpenAI Images 的成功响应记为 `completed/accepted`,随后独立推进本地产物交付。异步与同步候选可以在同一个 Task 中安全切换。
|
|
57
|
+
|
|
58
|
+
429 等可证明未创建任务的明确 4xx 拒绝可进入下一候选;408、409、425、499、5xx、网络异常、超时和成功响应缺少必要结果一律停止并记录 `acceptance=unknown`。同步生成已经成功后,下载或落盘失败记录为 `outcome=succeeded / deliveryState=failed`,不会重新生成。
|
|
59
|
+
|
|
60
|
+
视频、转写与 TTS 也已使用相同边界:视频和转写分别持久化 `prepare/upload/submit` stage,上传失败只表示生成请求未受理;TTS 同步成功则先记 `completed/accepted` 再交付音频。工作台已经消费稳定的人类状态,并提供重新观察、重新交付、提醒已读/恢复和需确认费用的知情重试;v0.1.4 再完成 discovery、poll、cancel、download 等完整 Provider conformance。
|
package/docs/ROADMAP.md
CHANGED
|
@@ -15,9 +15,9 @@ dsh-iris 已具备媒体生成、视觉处理和任务管理主流程。长期
|
|
|
15
15
|
- 浏览器上传、会话附件和宿主路径输入
|
|
16
16
|
- 异步任务恢复、取消传播、SSE 状态更新和授权媒体链接
|
|
17
17
|
- 面向 Agent 与用户的统一视频生成实现
|
|
18
|
-
-
|
|
18
|
+
- 两个随包 Agent Skills:UI 视觉验收与多步骤媒体编排;0.1.2 会在插件启用时自动注册
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
当前发布版本为 `v0.1.2`。0.1.1 完成配置独立、安全与工程收口,并把 Web loader 适配固定到已验证的 DSH `0.1.2-rc.1` 接口;更高预览版在进入支持范围前需要重新运行宿主 canary。
|
|
21
21
|
|
|
22
22
|
## 已完成:0.1.1
|
|
23
23
|
|
|
@@ -29,22 +29,37 @@ dsh-iris 已具备媒体生成、视觉处理和任务管理主流程。长期
|
|
|
29
29
|
- 绑定供应商凭据与协议端点,统一私有存储权限和流式原子落盘,并验证损坏配置恢复。
|
|
30
30
|
- 将付费能力实测改为单项显式确认,视频与转写不做空样本自动探针。
|
|
31
31
|
- 默认将 Iris HTTP 路由限制在回环 Host,为反代提供显式信任列表和认证部署说明。
|
|
32
|
-
- 增加 Linux/Windows 与 Node.js 20.
|
|
32
|
+
- 增加 Linux/Windows 与 Node.js 20.10/22 CI 矩阵、发布前测试护栏,并以当前 DSH 预览版完成宿主烟测。
|
|
33
33
|
- 核对打包清单,记录真实环境和未验证平台。
|
|
34
34
|
|
|
35
|
+
## 已完成:0.1.2
|
|
36
|
+
|
|
37
|
+
### 可见、可达与唯一身份
|
|
38
|
+
|
|
39
|
+
- 保留 npm 包名 `@mokuyoaxis/dsh-iris`,以 “Iris Media for DSH” 作为展示名,并使用唯一 Cordis 行 ID 避免与另一款 `dsh-iris` 同装冲突。
|
|
40
|
+
- 插件启用时自动注册两项随包 Skill,不要求用户克隆仓库、切换 cwd 或修改默认 Skill 搜索目录。
|
|
41
|
+
- 中英文 README 直接展示已脱敏的 Android 真机截图与代表性生成图,完整流程保留独立画廊;根目录 `screenshots.json` 控制插件市场展示顺序。
|
|
42
|
+
- 在 DSH 对话输入框提供可独立关闭的无框 🫧 提示词优化入口:使用半透明玻璃悬浮窗和窄屏底部面板,支持当前会话/固定模型路由、独立 thinking 策略与保守输出预算、预览写回,以及 JSON 导入导出和恢复默认。
|
|
43
|
+
- 泡泡快捷历史只展示运行中任务与成功产物;功能状态灯不再依赖用户逐张点开卡片。
|
|
44
|
+
- 本版不新增供应商分支,也不声称已完成独立 Core、任务语义 v2 或离线诊断。
|
|
45
|
+
|
|
35
46
|
## 下一步
|
|
36
47
|
|
|
37
|
-
###
|
|
48
|
+
### 当前发行候选 0.1.3:可信任务与适配边界
|
|
38
49
|
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
50
|
+
- 图片、视频、转写与 TTS 已区分未受理、已受理与受理未知,并使用一个 Task、多 Attempt、独立观察/交付/取消事实;规范见[Task/Attempt v2 语义契约](TASK_SEMANTICS.md)。
|
|
51
|
+
- 零网络故障矩阵已覆盖提交响应丢失、受理后持久化失败、轮询耗尽、取消未知、各阶段重启、下载/落盘、上传残留、SSE 慢消费者与人工接管;证据见[故障注入矩阵](FAULT_INJECTION.md)。
|
|
52
|
+
- 最小 Provider 提交契约和 Core 依赖守卫已冻结;完整 Host Adapter 和 Provider conformance 顺延到 0.1.4,避免把可靠性修复变成大重构。
|
|
53
|
+
- 离线 `doctor()`、`dsh-iris doctor [--json]`、[架构](ARCHITECTURE.md)与[安全边界](SECURITY.md)已经提供;依赖 DSH 运行时的扩展诊断顺延到 0.1.4。
|
|
54
|
+
- 在具备稳定录制条件后补充真实短视频证据;不以伪造或不稳定链接阻塞 0.1.2。
|
|
42
55
|
|
|
43
56
|
### 0.2.0:独立 Core 与产物记录
|
|
44
57
|
|
|
45
58
|
- 统一 Agent、工作台与 CLI 的命令执行核心,将 DSH 集成集中到宿主适配器。
|
|
46
59
|
- 为产物保存内容哈希、来源和派生关系,支持检查与导出。
|
|
47
60
|
- 在未安装 DSH 的干净环境完成本地动作和供应商任务验收。
|
|
61
|
+
- 建立 Iris 正式产品视觉身份:以简约鸢尾花和泡泡为核心母题,完成可缩放 Logo、图标、单色版与深浅色适配,并替换临时字标。
|
|
62
|
+
- 在统一 Provider Adapter 与 conformance 测试稳定后,依次接入 Gemini、Fal,并把 Replicate 排入后续 0.2.x。
|
|
48
63
|
|
|
49
64
|
### 后续方向
|
|
50
65
|
|
|
@@ -60,7 +75,7 @@ dsh-iris 已具备媒体生成、视觉处理和任务管理主流程。长期
|
|
|
60
75
|
- WSL、远程浏览器和容器部署应优先使用上传或会话附件,避免混淆浏览器路径与宿主路径。
|
|
61
76
|
- HTML 截图运行在离线沙箱中,远程资源和页面脚本不可用。
|
|
62
77
|
- 模型发现只能列出候选项,具体能力需要通过实际请求确认。
|
|
63
|
-
- Node 测试调度器不依赖 Bash
|
|
78
|
+
- Node 测试调度器不依赖 Bash,Linux/Windows × Node.js 20.10/22 自动化矩阵已经通过;原生 Windows/WSL 的 DSH 宿主实机冒烟仍待补充。
|
|
64
79
|
|
|
65
80
|
## 质量要求
|
|
66
81
|
|
|
@@ -81,3 +96,5 @@ dsh-iris 已具备媒体生成、视觉处理和任务管理主流程。长期
|
|
|
81
96
|
- 在本地工作台阶段建设公网 SaaS、组织账号和多租户系统。
|
|
82
97
|
- 自动探测全部模型能力并触发可能计费的请求。
|
|
83
98
|
- 仅为未来可能使用的供应商预建没有调用方的适配层。
|
|
99
|
+
- 为 0.1.2 临时接入尚无统一契约与测试基线的新供应商。
|
|
100
|
+
- 为展示效果伪造实机截图、生成结果或短视频证据。
|
package/docs/SECURITY.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Iris 安全边界
|
|
2
|
+
|
|
3
|
+
状态:v0.1.3 当前实现。安全目标是避免凭据泄露、路径越权、跨站写入和因错误重试造成重复计费;Iris 与 DSH 仍是本机同一信任域内的预览软件,不构成多租户安全边界。
|
|
4
|
+
|
|
5
|
+
## 信任模型
|
|
6
|
+
|
|
7
|
+
- DSH Host、Iris 插件进程和 `$DSH_HOME` 当前属于同一操作系统用户。
|
|
8
|
+
- 浏览器工作台只通过 Iris 的同源 Host 路由访问数据;默认只接受回环 Host。显式 `IRIS_TRUSTED_HOSTS` 只扩展 Host 校验,不等于认证。
|
|
9
|
+
- API Key 只在 Host 侧配置与供应商请求中使用。工作台、状态 API、任务记录、错误和 Doctor 输出不得返回完整 Key。
|
|
10
|
+
- DSH 仍处于快速演进阶段。Iris 的兼容范围不是对 DSH 本身安全性或生产就绪度的背书。
|
|
11
|
+
|
|
12
|
+
## 凭据与配置
|
|
13
|
+
|
|
14
|
+
供应商凭据保存在 `$DSH_HOME/iris/v1/providers.json`。POSIX 上 Iris 创建的目录和文件分别使用 `0700` 与 `0600`,启动时会在不跟随符号链接的前提下收紧既有 Iris 树。Windows mode 不等同于 ACL,仍依赖当前用户目录和系统账户权限。
|
|
15
|
+
|
|
16
|
+
API、SSE 和 Doctor 只返回凭据存在性或掩码提示。Provider 错误会移除 Bearer token、常见 Key、签名查询参数、堆栈和私有绝对路径。不要把 `providers.json`、环境变量或含签名的临时 URL 上传到 Issue。
|
|
17
|
+
|
|
18
|
+
`ai-paint` 是维护者未公开的本地前身,不是用户依赖。Iris 只有在用户显式设置 `IRIS_IMPORT_WORKBENCH_CONFIG` 为绝对路径且自身配置为空时才做一次性导入,不扫描其他项目,也不回写来源文件。
|
|
19
|
+
|
|
20
|
+
## 受理与费用安全
|
|
21
|
+
|
|
22
|
+
- 所有生成 Attempt 在网络副作用前落盘。
|
|
23
|
+
- 只有供应商明确证明未受理时才允许自动 failover。
|
|
24
|
+
- 500、超时、连接重置、响应丢失、轮询失败、事件失败和本地落盘失败都不能授权自动重提。
|
|
25
|
+
- “重新观察”只查询已有远端任务;“重新交付”只查询并下载已成功产物。
|
|
26
|
+
- “知情重试”必须单独确认可能重复任务或重复计费,并创建带 `retryOf/manualRetries` 关系的新 Task。创建后只归档原提醒,不改写原任务的未知事实;当前只对能从安全记录无损重建的文生图和文生视频开放,文件型输入和截断文本要求用户从原始输入重新发起。
|
|
27
|
+
- “标为已读/恢复提醒”只操作有界的本地 `attentionEvents` 审计元数据,不发送网络请求,也不把用户处置等同于供应商已经受理。
|
|
28
|
+
- Iris 当前没有凭空假设 DashScope 的远端取消协议。停止本地观察后若远端结果无法确认,状态保持 unknown。
|
|
29
|
+
|
|
30
|
+
## 文件、上传与媒体访问
|
|
31
|
+
|
|
32
|
+
- 浏览器上传使用大小上限、随机文件名、`.part` 临时文件和完成后的原子改名;中断时清理临时文件,过期副本按 TTL 回收。
|
|
33
|
+
- 输出文件名由 Iris 生成或通过 `basename` 收口,API 不返回宿主绝对路径。
|
|
34
|
+
- 媒体播放链接使用随机能力令牌。令牌应视为临时访问凭据,不应发布到公网。
|
|
35
|
+
- 清理任务元数据默认不删除产物;删除孤儿产物需要独立确认。
|
|
36
|
+
- 符号链接不会被私有树权限收紧逻辑跟随。Doctor 会把 Iris 数据根为符号链接视为硬错误。
|
|
37
|
+
|
|
38
|
+
## Web 与渲染
|
|
39
|
+
|
|
40
|
+
- 修改状态的路由拒绝明确跨站请求,并限制 JSON/上传 Body 大小。
|
|
41
|
+
- HTML 截图在离线沙箱中运行,不具备 Iris/宿主同源权限;远程资源和页面脚本不可用。
|
|
42
|
+
- SSE 使用同源连接、节流和背压合并;慢消费者只保留最新快照,避免积压历史状态。
|
|
43
|
+
- 如果把 DSH 通过 LAN、反向代理或隧道暴露,必须由部署者另加真正的认证、TLS、访问控制和来源限制。
|
|
44
|
+
|
|
45
|
+
## 离线 Doctor
|
|
46
|
+
|
|
47
|
+
`dsh-iris doctor` 不启动 DSH,不发送供应商或计费请求,也不打印 API Key。它会在 Iris 数据目录或最近可写父目录创建一个随机小文件并立即删除,用于验证真实写权限。`--json` 与文本输出使用同一结果模型,退出码为:`0` 正常、`1` 有警告、`2` 有硬错误。
|
|
48
|
+
|
|
49
|
+
Doctor 不能证明 DSH 工具注册、浏览器、附件服务、客户端资源或真实 Provider 在线;这些属于后续 Host 扩展诊断。
|
|
50
|
+
|
|
51
|
+
## 报告问题
|
|
52
|
+
|
|
53
|
+
报告安全问题前请移除 API Key、Authorization、完整 `providers.json`、私有路径、媒体能力令牌和供应商签名 URL。建议提供版本、平台、Doctor 的脱敏输出、最小复现步骤及是否发生真实费用。
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Iris Task/Attempt v2 语义契约
|
|
2
|
+
|
|
3
|
+
状态:**v0.1.3 已实现。** Task v2 已覆盖图片、视频、转写与 TTS,包括同步/异步、上传/提交、混合协议候选、工作台稳定用户态、状态流防倒退、重新观察、重新交付、提醒已读/恢复和知情人工重试。正式 Artifact Manifest、完整 Provider/Host Adapter 和宿主扩展诊断仍属于后续版本。
|
|
4
|
+
|
|
5
|
+
## 1. 为什么需要 v2
|
|
6
|
+
|
|
7
|
+
媒体生成可能在供应商侧产生费用。网络断开并不能证明请求没有被受理,轮询失败也不能证明远端任务失败,下载失败更不能抹掉已经成功的生成结果。Iris 必须分别记录“有没有提交”“供应商是否受理”“远端结果是什么”“是否仍在观察”“产物是否已取回”和“取消是否得到确认”。
|
|
8
|
+
|
|
9
|
+
本契约使用以下规范词:**必须**表示不可违反的安全或事实约束;**应该**表示除非有记录充分的理由,否则需要遵守;**可以**表示可选行为。
|
|
10
|
+
|
|
11
|
+
## 2. 核心对象
|
|
12
|
+
|
|
13
|
+
- **Task**:一次用户意图。无论尝试过多少供应商,一个用户请求只能创建一个 Task。
|
|
14
|
+
- **Attempt**:Task 针对一个 `providerId::modelId` 的一次提交尝试。Attempt 必须在可能发送计费请求前持久化。
|
|
15
|
+
- **受理证据**:远端任务 ID、同步成功响应,或供应商明确声明已受理的其他稳定标识。
|
|
16
|
+
- **观察**:对已受理远端任务进行轮询或恢复接管,不等同于再次提交。
|
|
17
|
+
- **交付**:把远端结果下载、校验并原子保存为 Iris 本地产物。
|
|
18
|
+
|
|
19
|
+
Task 与 Attempt 使用稳定 ID。Attempt 的 `model` 与 Task 的权威 `modelRef` 必须保存复合身份 `providerId::modelId`;迁移期 Task 仍可额外保留裸 `model` 供 v0.1.2 UI 读取,但新逻辑不得以该兼容字段判断模型身份。
|
|
20
|
+
|
|
21
|
+
## 3. 正交状态
|
|
22
|
+
|
|
23
|
+
Task v2 至少包含以下事实轴;字段值采用可序列化的 snake_case 英文枚举:
|
|
24
|
+
|
|
25
|
+
| 字段 | 值 | 含义 |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `phase` | `queued` · `submitting` · `accepted` · `running` · `terminal` | Iris 当前是否还会自动推进该任务 |
|
|
28
|
+
| `acceptance` | `none` · `not_accepted` · `accepted` · `unknown` | 当前/最终 Attempt 的远端受理事实 |
|
|
29
|
+
| `watchState` | `idle` · `active` · `suspended` · `exhausted` | Iris 是否仍在观察远端任务 |
|
|
30
|
+
| `outcome` | `none` · `succeeded` · `failed` · `canceled` · `unknown` | 远端生成或确定性本地动作的结果 |
|
|
31
|
+
| `deliveryState` | `none` · `pending` · `downloading` · `ready` · `failed` | 成功结果是否已经可靠落成本地产物 |
|
|
32
|
+
| `cancelState` | `none` · `requested` · `remote_confirmed` · `local_confirmed` · `unknown` | 取消请求及其确认边界 |
|
|
33
|
+
|
|
34
|
+
`status` 仅为旧消费者保留,不再是真相来源。新代码必须读取上述字段。
|
|
35
|
+
|
|
36
|
+
### 3.1 旧 `status` 的保守派生
|
|
37
|
+
|
|
38
|
+
| v2 事实 | 旧 `status` |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `outcome=succeeded` 且 `deliveryState=ready` | `succeeded` |
|
|
41
|
+
| `outcome=failed` | `failed` |
|
|
42
|
+
| `outcome=canceled` 且取消已由远端或确定性本地动作确认 | `canceled` |
|
|
43
|
+
| 其余,包括受理未知、观察耗尽和交付失败 | `running` |
|
|
44
|
+
|
|
45
|
+
四态旧字段无法无损表达“需要人工处理”。派生时宁可保持非终态,也不得伪造失败、成功或取消。现代 UI 必须使用 v2 事实轴。
|
|
46
|
+
|
|
47
|
+
## 4. 受理与自动 failover
|
|
48
|
+
|
|
49
|
+
自动 failover 的许可只由受理事实决定:
|
|
50
|
+
|
|
51
|
+
| `acceptance` | 允许自动切换 Provider | 说明 |
|
|
52
|
+
|---|---:|---|
|
|
53
|
+
| `none` | 否 | 尚未形成最终分类,必须先收敛为明确状态 |
|
|
54
|
+
| `not_accepted` | 是 | 已确认计费/生成请求没有被供应商受理 |
|
|
55
|
+
| `accepted` | 否 | 已有受理证据,再次提交可能重复计费 |
|
|
56
|
+
| `unknown` | 否 | 请求可能已经被受理,必须保守停止 |
|
|
57
|
+
|
|
58
|
+
以下信息都**不能**单独授权自动 failover:`retryable=true`、HTTP 429/500、超时、连接重置、JSON 解析失败、轮询失败、下载失败、本地持久化失败或事件发布失败。
|
|
59
|
+
|
|
60
|
+
### 4.1 分类规则
|
|
61
|
+
|
|
62
|
+
- 本地参数校验失败、请求发送前明确中止,或供应商明确拒绝且确认未创建任务:`not_accepted`。
|
|
63
|
+
- 收到远端任务 ID、同步成功响应或等价证据:`accepted`。
|
|
64
|
+
- 请求可能已经离开本机,但响应在获得受理证据前丢失:`unknown`。
|
|
65
|
+
- 无法证明“未受理”时,必须选择 `unknown`,不得为了可用性猜测 `not_accepted`。
|
|
66
|
+
|
|
67
|
+
如果供应商支持幂等键,Attempt 应记录并复用该键;幂等能力可以帮助查询或安全恢复,但在未经合约证明前,不能把“发了幂等键”等同于“可以随意重试”。
|
|
68
|
+
|
|
69
|
+
最小 Provider 返回结构、写前/写后 Hook 和错误字段详见[Provider 提交契约 v0](PROVIDER_SUBMISSION_CONTRACT.md)。
|
|
70
|
+
|
|
71
|
+
## 5. Attempt 写前记录
|
|
72
|
+
|
|
73
|
+
每次 Attempt 必须在可能发送生成请求前至少保存:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"id": "attempt_...",
|
|
78
|
+
"ordinal": 1,
|
|
79
|
+
"providerId": "provider-a",
|
|
80
|
+
"model": "provider-a::model-a",
|
|
81
|
+
"acceptance": "none",
|
|
82
|
+
"stage": "preparing",
|
|
83
|
+
"idempotencyKey": "optional-provider-key",
|
|
84
|
+
"startedAt": "2026-09-06T00:00:00.000Z"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
上传临时输入与提交生成任务必须是不同 stage。上传成功并不等于生成请求已受理;但上传、提交和响应解析的错误证据都必须保留为脱敏分类,而不是一段不可机读的字符串。
|
|
89
|
+
|
|
90
|
+
## 6. 远端结果与产物交付
|
|
91
|
+
|
|
92
|
+
- 远端返回成功后立即记录 `outcome=succeeded`,然后进入 `deliveryState=pending/downloading`。
|
|
93
|
+
- 下载、校验或本地落盘失败时,保持 `outcome=succeeded`,写入 `deliveryState=failed`。
|
|
94
|
+
- 交付失败只允许重新下载/落盘,不允许重新生成。
|
|
95
|
+
- 只有本地产物完成原子落盘并可读后,才写 `deliveryState=ready`。
|
|
96
|
+
- 供应商明确返回生成失败时才写 `outcome=failed`。
|
|
97
|
+
|
|
98
|
+
## 7. 观察、超时与恢复
|
|
99
|
+
|
|
100
|
+
- 单次或连续轮询失败只改变观察事实;不得据此写 `outcome=failed`。
|
|
101
|
+
- 达到本地盯守上限时写 `watchState=exhausted`,结果通常为 `outcome=unknown`。
|
|
102
|
+
- 插件关闭或进程退出导致观察停止时,应保留可恢复信息;重启只能恢复观察,不能重新提交已受理或受理未知的 Attempt。
|
|
103
|
+
- `accepted` 的异步 Attempt 若供应商配置暂不可用,应进入 `watchState=suspended` 并给出修复建议,不能伪造远端失败。
|
|
104
|
+
- `unknown` 且没有远端任务 ID 时,只能等待供应商查询能力、幂等查询或用户知情决策。
|
|
105
|
+
|
|
106
|
+
## 8. 取消
|
|
107
|
+
|
|
108
|
+
- 用户请求取消时先写 `cancelState=requested`。
|
|
109
|
+
- 供应商明确确认取消后,写 `cancelState=remote_confirmed` 与 `outcome=canceled`。
|
|
110
|
+
- 纯本地、尚未产生远端副作用的动作确定停止后,可以写 `cancelState=local_confirmed` 与 `outcome=canceled`。
|
|
111
|
+
- 仅停止本地轮询不等于远端取消。
|
|
112
|
+
- 取消请求超时、断网、供应商不支持取消或结果无法确认时,写 `cancelState=unknown`;`outcome` 也不得伪造为 `canceled`。
|
|
113
|
+
|
|
114
|
+
## 9. 错误与隐私
|
|
115
|
+
|
|
116
|
+
结构化错误至少应区分 stage、category、HTTP 状态、供应商错误码、受理状态和可安全展示的信息。任务、Attempt、事件与日志不得保存 API Key、Authorization 头、完整请求体、私有绝对路径或带临时签名的结果 URL。
|
|
117
|
+
|
|
118
|
+
错误是否“可重试”与是否“允许自动重新提交”是两个不同问题。前者描述技术性质,后者只能由 `acceptance=not_accepted` 授权。
|
|
119
|
+
|
|
120
|
+
## 10. 事件与 UI
|
|
121
|
+
|
|
122
|
+
- 每次 Task v2 持久化变更得到单调递增的 Task `revision`。完整状态快照另带进程 `stateEpoch/stateRevision`;客户端拒绝同一 epoch 内迟到的旧快照,SSE 重连后以持久化全量快照收敛。
|
|
123
|
+
- SSE 慢消费者进入背压时只保留最新待发快照,避免旧状态排队造成内存增长或视觉倒退。
|
|
124
|
+
- UI 应把事实映射成“排队中、运行中、观察暂停、需要确认、结果待取回、已完成、明确失败、已取消”等人类状态,不应在手机界面直接堆叠所有内部字段。
|
|
125
|
+
- `acceptance=unknown`、`cancelState=unknown` 和 `deliveryState=failed` 必须提供明确的人工接管入口;任何可能再次计费的操作都需要单独确认。
|
|
126
|
+
- 提醒处置与任务事实正交:标为已读只把任务移出主动提醒队列,恢复提醒只重新开放该队列;两者都不得修改受理、观察、结果、交付或取消事实。
|
|
127
|
+
- 知情重试创建并关联新 Task 后,原提醒自动记录为“已通过重试处理”。原任务保留原始未知事实和审计记录,但不继续产生重复角标;用户可从历史详情恢复提醒。
|
|
128
|
+
|
|
129
|
+
## 11. 兼容与迁移
|
|
130
|
+
|
|
131
|
+
- v0.1.x 只允许向现有 JSON 记录增加字段,不执行破坏性批量迁移,不顺带引入 SQLite/JSONL。
|
|
132
|
+
- 旧记录缺少 v2 字段时,由纯兼容规范化器生成内存视图:既有成功记录保留成功证据;转存失败映射为远端成功但交付失败;轮询失败、无远端 ID 的运行记录和旧取消记录映射到 `unknown`,不能猜测失败、未受理或远端已取消。
|
|
133
|
+
- 读取旧任务不应立即重写整个文件;只有真实更新发生时才按原子写规则保存扩展后的记录。
|
|
134
|
+
- 在 v2 UI 和消费者完成迁移前继续输出派生 `status`。
|
|
135
|
+
|
|
136
|
+
## 12. 必须通过的故障证据
|
|
137
|
+
|
|
138
|
+
故障注入至少覆盖:请求发送前失败、提交响应丢失、获得远端 ID 后本地落盘失败、轮询 429/500/超时、远端成功后下载失败、取消响应丢失,以及 `submitting/accepted/running` 阶段的进程退出与恢复。
|
|
139
|
+
|
|
140
|
+
每个场景必须同时断言最终事实字段和供应商提交调用次数。对于 `accepted` 或 `unknown`,自动重复提交次数必须为 **0**。
|
|
141
|
+
|
|
142
|
+
## 13. 本版非目标
|
|
143
|
+
|
|
144
|
+
- 不在语义冻结阶段重写全部任务存储或 UI。
|
|
145
|
+
- 不新增 Gemini、Fal、Replicate 等供应商分支。
|
|
146
|
+
- v0.1.3 包含零网络、可独立运行的离线 Doctor v0 与最薄 CLI;依赖 DSH `ctx` 的宿主扩展诊断、完整 Host Adapter 和 Artifact Manifest 不属于本版。
|
|
147
|
+
- 不用更多自动重试换取表面成功率。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<mxfile host="iris-docs"><diagram id="iris-architecture" name="页 1"><mxGraphModel dx="1000" dy="700" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1180" pageHeight="800" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="host" value="DeepSeek Harness 宿主进程 · Iris 插件(复用宿主工具 / 路由 / 生命周期服务)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#b9c2ce;verticalAlign=top;align=left;spacingLeft=10;spacingTop=6;fontColor=#5b6472;fontSize=12;" vertex="1" parent="1"><mxGeometry x="36" y="96" width="1108" height="560" as="geometry"/></mxCell><mxCell id="tools" value="Agent 工具(14 个)<br>iris_draw_image · iris_generate_video · …" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;" vertex="1" parent="1"><mxGeometry x="66" y="138" width="300" height="72" as="geometry"/></mxCell><mxCell id="cards" value="GUI 动作卡<br>会话内的 Iris 操作入口" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;" vertex="1" parent="1"><mxGeometry x="440" y="138" width="300" height="72" as="geometry"/></mxCell><mxCell id="bench" value="Iris 工作台(三座位)<br>设置 · 进度 · 悬浮泡泡" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;" vertex="1" parent="1"><mxGeometry x="790" y="138" width="290" height="72" as="geometry"/></mxCell><mxCell id="actions" value="统一动作层 · lib/actions.js<br>参数校验 · 输入解析(上传 / 会话附件 / 宿主路径)· failover 编排" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="200" y="268" width="540" height="74" as="geometry"/></mxCell><mxCell id="models" value="模型池 · lib/models.js + capability.js<br>providerId::modelId 复合身份 · 能力分配 · 有序候选" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="66" y="396" width="430" height="74" as="geometry"/></mxCell><mxCell id="adapters" value="Provider 适配 · lib/adapters.js<br>DashScope 媒体协议 · OpenAI Images 兼容" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="550" y="396" width="430" height="74" as="geometry"/></mxCell><mxCell id="tasks" value="任务系统 · lib/tasks.js<br>异步轮询 · 重启恢复 · 取消传播" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eaf7ef;strokeColor=#2e9e5b;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="66" y="524" width="340" height="74" as="geometry"/></mxCell><mxCell id="files" value="文件与媒体 · lib/media.js<br>uploads/ outputs/ · 令牌媒体链接 · Range 流式" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eaf7ef;strokeColor=#2e9e5b;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="430" y="524" width="300" height="74" as="geometry"/></mxCell><mxCell id="client" value="Web 客户端 · lib/client.js<br>三座位 UI · 共享状态订阅 + SSE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="790" y="524" width="290" height="74" as="geometry"/></mxCell><mxCell id="skillreg" value="Skill registry<br>随包注册 iris-verify-ui / iris-compose-media" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;" vertex="1" parent="1"><mxGeometry x="790" y="268" width="290" height="74" as="geometry"/></mxCell><mxCell id="datanote" value="本地数据 · $DSH_HOME/iris/v1/<br>providers.json · tasks.json · uploads/ · outputs/(POSIX 0700 / 0600)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#b9c2ce;fontColor=#5b6472;fontSize=11;dashed=1;" vertex="1" parent="1"><mxGeometry x="66" y="690" width="470" height="56" as="geometry"/></mxCell><mxCell id="providers" value="媒体 / 视觉服务商<br>DashScope 百炼 · OpenAI Images 兼容服务(凭据只发往官方 HTTPS 域名)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;" vertex="1" parent="1"><mxGeometry x="580" y="706" width="560" height="64" as="geometry"/></mxCell><mxCell id="c1" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tools" target="actions"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="216" y="239"/><mxPoint x="308" y="239"/></Array></mxGeometry></mxCell><mxCell id="c2" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="cards" target="actions"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="590" y="239"/><mxPoint x="470" y="239"/></Array></mxGeometry></mxCell><mxCell id="c3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="bench" target="actions"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="848" y="239"/><mxPoint x="740" y="239"/></Array></mxGeometry></mxCell><mxCell id="c4" value="选择候选模型" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="actions" target="models"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="362" y="369"/><mxPoint x="281" y="369"/></Array></mxGeometry></mxCell><mxCell id="c5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="actions" target="adapters"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="578" y="369"/><mxPoint x="765" y="369"/></Array></mxGeometry></mxCell><mxCell id="c6" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=1;exitY=0.5;entryX=0;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="models" target="adapters"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c7" value="创建任务" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="actions" target="tasks"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="524" y="480"/><mxPoint x="236" y="480"/></Array></mxGeometry></mxCell><mxCell id="c8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=1;exitY=0.5;entryX=0;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tasks" target="files"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c9" value="状态事件" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;dashed=1;exitX=0.5;exitY=1;entryX=0.5;entryY=1;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tasks" target="client"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="236" y="640"/><mxPoint x="935" y="640"/></Array></mxGeometry></mxCell><mxCell id="c10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;dashed=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="bench" target="skillreg"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c11" value="HTTPS" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="adapters" target="providers"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="765" y="676"/><mxPoint x="860" y="676"/></Array></mxGeometry></mxCell></root></mxGraphModel></diagram></mxfile>
|
|
Binary file
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1180" height="800" viewBox="0 0 1180 800" role="img" aria-label="Iris 架构总览(DSH 插件形态)">
|
|
2
|
+
<defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#6b7686"/></marker></defs>
|
|
3
|
+
<rect width="1180" height="800" fill="#ffffff"/>
|
|
4
|
+
<text x="48" y="52" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="21" font-weight="700" fill="#1f2328">Iris 架构总览(DSH 插件形态)</text>
|
|
5
|
+
<text x="48" y="78" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="13" fill="#5b6472">三个入口共用同一套动作实现;凭据与数据只留在宿主侧,插件不额外监听端口</text>
|
|
6
|
+
<rect x="36" y="96" width="1108" height="560" rx="10" fill="none" stroke="#b9c2ce" stroke-width="1.4"/>
|
|
7
|
+
<text x="50" y="120" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12.5" fill="#5b6472">DeepSeek Harness 宿主进程 · Iris 插件(复用宿主工具 / 路由 / 生命周期服务)</text>
|
|
8
|
+
<path d="M216,210 L216,239 L308,239 L308,268" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
9
|
+
<path d="M590,210 L590,239 L470,239 L470,268" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
10
|
+
<path d="M848,210 L848,239 L740,239 L740,268" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
11
|
+
<path d="M362,342 L362,369 L281,369 L281,396" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
12
|
+
<rect x="321" y="346" width="82" height="19" rx="4" fill="#ffffff"/>
|
|
13
|
+
<text x="362" y="359.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">选择候选模型</text>
|
|
14
|
+
<path d="M578,342 L578,369 L765,369 L765,396" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
15
|
+
<path d="M496,433 L550,433" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
16
|
+
<path d="M524,342 L524,480 L236,480 L236,524" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
17
|
+
<rect x="353" y="488.5" width="58" height="19" rx="4" fill="#ffffff"/>
|
|
18
|
+
<text x="382" y="502" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">创建任务</text>
|
|
19
|
+
<path d="M406,561 L430,561" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
20
|
+
<path d="M236,598 L236,640 L935,640 L935,598" fill="none" stroke="#6b7686" stroke-width="1.6" stroke-dasharray="5 4" marker-end="url(#arr)"/>
|
|
21
|
+
<rect x="351" y="620.5" width="58" height="19" rx="4" fill="#ffffff"/>
|
|
22
|
+
<text x="380" y="634" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">状态事件</text>
|
|
23
|
+
<path d="M935,210 L935,268" fill="none" stroke="#6b7686" stroke-width="1.6" stroke-dasharray="5 4" marker-end="url(#arr)"/>
|
|
24
|
+
<path d="M765,470 L765,676 L860,676 L860,706" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
25
|
+
<rect x="790.2" y="666.5" width="43.6" height="19" rx="4" fill="#ffffff"/>
|
|
26
|
+
<text x="812" y="680" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">HTTPS</text>
|
|
27
|
+
<rect x="66" y="138" width="300" height="72" rx="9" fill="#f5f6f8" stroke="#b9c2ce" stroke-width="1.6"/>
|
|
28
|
+
<text x="216" y="170" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">Agent 工具(14 个)</text>
|
|
29
|
+
<text x="216" y="190.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">iris_draw_image · iris_generate_video · …</text>
|
|
30
|
+
<rect x="440" y="138" width="300" height="72" rx="9" fill="#f5f6f8" stroke="#b9c2ce" stroke-width="1.6"/>
|
|
31
|
+
<text x="590" y="170" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">GUI 动作卡</text>
|
|
32
|
+
<text x="590" y="190.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">会话内的 Iris 操作入口</text>
|
|
33
|
+
<rect x="790" y="138" width="290" height="72" rx="9" fill="#f5f6f8" stroke="#b9c2ce" stroke-width="1.6"/>
|
|
34
|
+
<text x="935" y="170" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">Iris 工作台(三座位)</text>
|
|
35
|
+
<text x="935" y="190.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">设置 · 进度 · 悬浮泡泡</text>
|
|
36
|
+
<rect x="200" y="268" width="540" height="74" rx="9" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
37
|
+
<text x="470" y="301" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">统一动作层 · lib/actions.js</text>
|
|
38
|
+
<text x="470" y="321.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">参数校验 · 输入解析(上传 / 会话附件 / 宿主路径)· failover 编排</text>
|
|
39
|
+
<rect x="66" y="396" width="430" height="74" rx="9" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
40
|
+
<text x="281" y="429" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">模型池 · lib/models.js + capability.js</text>
|
|
41
|
+
<text x="281" y="449.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">providerId::modelId 复合身份 · 能力分配 · 有序候选</text>
|
|
42
|
+
<rect x="550" y="396" width="430" height="74" rx="9" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
43
|
+
<text x="765" y="429" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">Provider 适配 · lib/adapters.js</text>
|
|
44
|
+
<text x="765" y="449.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">DashScope 媒体协议 · OpenAI Images 兼容</text>
|
|
45
|
+
<rect x="66" y="524" width="340" height="74" rx="9" fill="#eaf7ef" stroke="#2e9e5b" stroke-width="1.6"/>
|
|
46
|
+
<text x="236" y="557" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">任务系统 · lib/tasks.js</text>
|
|
47
|
+
<text x="236" y="577.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">异步轮询 · 重启恢复 · 取消传播</text>
|
|
48
|
+
<rect x="430" y="524" width="300" height="74" rx="9" fill="#eaf7ef" stroke="#2e9e5b" stroke-width="1.6"/>
|
|
49
|
+
<text x="580" y="557" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">文件与媒体 · lib/media.js</text>
|
|
50
|
+
<text x="580" y="577.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">uploads/ outputs/ · 令牌媒体链接 · Range 流式</text>
|
|
51
|
+
<rect x="790" y="524" width="290" height="74" rx="9" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
52
|
+
<text x="935" y="557" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">Web 客户端 · lib/client.js</text>
|
|
53
|
+
<text x="935" y="577.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">三座位 UI · 共享状态订阅 + SSE</text>
|
|
54
|
+
<rect x="790" y="268" width="290" height="74" rx="9" fill="#f5f6f8" stroke="#b9c2ce" stroke-width="1.6"/>
|
|
55
|
+
<text x="935" y="301" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">Skill registry</text>
|
|
56
|
+
<text x="935" y="321.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">随包注册 iris-verify-ui / iris-compose-media</text>
|
|
57
|
+
<rect x="66" y="690" width="470" height="56" rx="8" fill="#ffffff" stroke="#b9c2ce" stroke-width="1.3" stroke-dasharray="5 4"/>
|
|
58
|
+
<text x="301" y="714" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">本地数据 · $DSH_HOME/iris/v1/</text>
|
|
59
|
+
<text x="301" y="734.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">providers.json · tasks.json · uploads/ · outputs/(POSIX 0700 / 0600)</text>
|
|
60
|
+
<rect x="580" y="706" width="560" height="64" rx="9" fill="#f5f6f8" stroke="#b9c2ce" stroke-width="1.6"/>
|
|
61
|
+
<text x="860" y="734" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">媒体 / 视觉服务商</text>
|
|
62
|
+
<text x="860" y="754.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">DashScope 百炼 · OpenAI Images 兼容服务(凭据只发往官方 HTTPS 域名)</text>
|
|
63
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<mxfile host="iris-docs"><diagram id="iris-task-lifecycle" name="页 1"><mxGraphModel dx="1000" dy="700" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1240" pageHeight="740" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="start" value="Agent 工具 / GUI 动作卡<br>提交生成请求" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="40" y="300" width="180" height="60" as="geometry"/></mxCell><mxCell id="create" value="创建本地任务<br>status = running" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="268" y="300" width="180" height="60" as="geometry"/></mxCell><mxCell id="attempt" value="提交供应商(Attempt)<br>上传 · 提交 · 同步生成" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff6e5;strokeColor=#c98a1b;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="496" y="298" width="220" height="64" as="geometry"/></mxCell><mxCell id="decide" value="远端受理?" style="rhombus;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="764" y="280" width="180" height="100" as="geometry"/></mxCell><mxCell id="accepted" value="已受理<br>remoteTaskId 落盘" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eaf7ef;strokeColor=#2e9e5b;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="996" y="300" width="200" height="60" as="geometry"/></mxCell><mxCell id="failover" value="failover:切换下一候选模型" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fceded;strokeColor=#c94f4f;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="496" y="140" width="220" height="58" as="geometry"/></mxCell><mxCell id="exhausted" value="候选耗尽<br>任务失败" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fceded;strokeColor=#c94f4f;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="240" y="141" width="200" height="56" as="geometry"/></mxCell><mxCell id="watch" value="后台轮询盯守<br>重启后自动接管 running 任务" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eef3ff;strokeColor=#4d6bfe;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="700" y="440" width="240" height="56" as="geometry"/></mxCell><mxCell id="succeeded" value="succeeded<br>产物转存 DSH 附件 + 令牌媒体链接" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#eaf7ef;strokeColor=#2e9e5b;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="700" y="560" width="240" height="60" as="geometry"/></mxCell><mxCell id="failed" value="failed<br>保留错误说明" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fceded;strokeColor=#c94f4f;fontColor=#1f2328;fontSize=12;strokeWidth=1.5;" vertex="1" parent="1"><mxGeometry x="460" y="560" width="190" height="60" as="geometry"/></mxCell><mxCell id="canceled" value="canceled<br>取消信号传播" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f6f8;strokeColor=#b9c2ce;fontColor=#1f2328;fontSize=12;" vertex="1" parent="1"><mxGeometry x="230" y="560" width="180" height="60" as="geometry"/></mxCell><mxCell id="note1" value="黄金规则:远端受理后绝不自动重提<br>重提只发生在提交阶段的模型候选切换,避免重复计费" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#b9c2ce;fontColor=#5b6472;fontSize=11;dashed=1;" vertex="1" parent="1"><mxGeometry x="40" y="650" width="560" height="64" as="geometry"/></mxCell><mxCell id="note2" value="启动恢复与取消<br>有 remoteTaskId 的任务继续盯守;孤儿提交清理为 failed;取消传播到本地等待与轮询" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#b9c2ce;fontColor=#5b6472;fontSize=11;dashed=1;" vertex="1" parent="1"><mxGeometry x="640" y="650" width="556" height="64" as="geometry"/></mxCell><mxCell id="c1" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=1;exitY=0.5;entryX=0;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="start" target="create"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c2" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=1;exitY=0.5;entryX=0;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="create" target="attempt"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=1;exitY=0.5;entryX=0;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="attempt" target="decide"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c4" value="是" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=1;exitY=0.5;entryX=0;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="decide" target="accepted"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c5" value="否" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=0;entryX=1;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="decide" target="failover"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="854" y="169"/><mxPoint x="716" y="169"/></Array></mxGeometry></mxCell><mxCell id="c6" value="重试提交" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="failover" target="attempt"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0;exitY=0.5;entryX=1;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="failover" target="exhausted"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c8" value="转入盯守" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=1;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="accepted" target="watch"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="1096" y="468"/><mxPoint x="940" y="468"/></Array></mxGeometry></mxCell><mxCell id="c9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="watch" target="succeeded"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="c10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;dashed=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="watch" target="failed"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="760" y="534"/><mxPoint x="555" y="534"/></Array></mxGeometry></mxCell><mxCell id="c11" value="轮询耗尽 / 取消 / 错误" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#6b7686;strokeWidth=1.5;fontColor=#5b6472;fontSize=11;labelBackgroundColor=#ffffff;dashed=1;exitX=0;exitY=0.5;entryX=0.5;entryY=0;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="watch" target="canceled"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="660" y="468"/><mxPoint x="660" y="524"/><mxPoint x="320" y="524"/></Array></mxGeometry></mxCell></root></mxGraphModel></diagram></mxfile>
|
|
Binary file
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1240" height="740" viewBox="0 0 1240 740" role="img" aria-label="生成任务生命周期与受理边界">
|
|
2
|
+
<defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#6b7686"/></marker></defs>
|
|
3
|
+
<rect width="1240" height="740" fill="#ffffff"/>
|
|
4
|
+
<text x="48" y="52" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="21" font-weight="700" fill="#1f2328">生成任务生命周期与受理边界</text>
|
|
5
|
+
<text x="48" y="78" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="13" fill="#5b6472">failover 只发生在上传 / 提交 / 同步生成阶段;远端一旦受理,绝不自动重提</text>
|
|
6
|
+
<path d="M220,330 L268,330" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
7
|
+
<path d="M448,330 L496,330" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
8
|
+
<path d="M716,330 L764,330" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
9
|
+
<path d="M944,330 L996,330" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
10
|
+
<rect x="959" y="320.5" width="22" height="19" rx="4" fill="#ffffff"/>
|
|
11
|
+
<text x="970" y="334" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">是</text>
|
|
12
|
+
<path d="M854,280 L854,169 L716,169 L716,169" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
13
|
+
<rect x="843" y="215" width="22" height="19" rx="4" fill="#ffffff"/>
|
|
14
|
+
<text x="854" y="228.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">否</text>
|
|
15
|
+
<path d="M606,198 L606,298" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
16
|
+
<rect x="577" y="238.5" width="58" height="19" rx="4" fill="#ffffff"/>
|
|
17
|
+
<text x="606" y="252" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">重试提交</text>
|
|
18
|
+
<path d="M496,169 L440,169" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
19
|
+
<path d="M1096,360 L1096,468 L940,468 L940,468" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
20
|
+
<rect x="1067" y="404.5" width="58" height="19" rx="4" fill="#ffffff"/>
|
|
21
|
+
<text x="1096" y="418" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">转入盯守</text>
|
|
22
|
+
<path d="M820,496 L820,560" fill="none" stroke="#6b7686" stroke-width="1.6" marker-end="url(#arr)"/>
|
|
23
|
+
<path d="M760,496 L760,534 L555,534 L555,560" fill="none" stroke="#6b7686" stroke-width="1.6" stroke-dasharray="5 4" marker-end="url(#arr)"/>
|
|
24
|
+
<path d="M700,468 L660,468 L660,524 L320,524 L320,560" fill="none" stroke="#6b7686" stroke-width="1.6" stroke-dasharray="5 4" marker-end="url(#arr)"/>
|
|
25
|
+
<rect x="416.84000000000003" y="508.5" width="146.32" height="19" rx="4" fill="#ffffff"/>
|
|
26
|
+
<text x="490" y="522" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" fill="#5b6472">轮询耗尽 / 取消 / 错误</text>
|
|
27
|
+
<rect x="40" y="300" width="180" height="60" rx="30" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
28
|
+
<text x="130" y="326" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">Agent 工具 / GUI 动作卡</text>
|
|
29
|
+
<text x="130" y="346.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">提交生成请求</text>
|
|
30
|
+
<rect x="268" y="300" width="180" height="60" rx="9" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
31
|
+
<text x="358" y="326" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">创建本地任务</text>
|
|
32
|
+
<text x="358" y="346.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">status = running</text>
|
|
33
|
+
<rect x="496" y="298" width="220" height="64" rx="9" fill="#fff6e5" stroke="#c98a1b" stroke-width="1.6"/>
|
|
34
|
+
<text x="606" y="326" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">提交供应商(Attempt)</text>
|
|
35
|
+
<text x="606" y="346.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">上传 · 提交 · 同步生成</text>
|
|
36
|
+
<path d="M854,280 L944,330 L854,380 L764,330 Z" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
37
|
+
<text x="854" y="335.25" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">远端受理?</text>
|
|
38
|
+
<rect x="996" y="300" width="200" height="60" rx="9" fill="#eaf7ef" stroke="#2e9e5b" stroke-width="1.6"/>
|
|
39
|
+
<text x="1096" y="326" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">已受理</text>
|
|
40
|
+
<text x="1096" y="346.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">remoteTaskId 落盘</text>
|
|
41
|
+
<rect x="496" y="140" width="220" height="58" rx="9" fill="#fceded" stroke="#c94f4f" stroke-width="1.6"/>
|
|
42
|
+
<text x="606" y="174.25" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">failover:切换下一候选模型</text>
|
|
43
|
+
<rect x="240" y="141" width="200" height="56" rx="9" fill="#fceded" stroke="#c94f4f" stroke-width="1.6"/>
|
|
44
|
+
<text x="340" y="165" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">候选耗尽</text>
|
|
45
|
+
<text x="340" y="185.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">任务失败</text>
|
|
46
|
+
<rect x="700" y="440" width="240" height="56" rx="9" fill="#eef3ff" stroke="#4d6bfe" stroke-width="1.6"/>
|
|
47
|
+
<text x="820" y="464" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">后台轮询盯守</text>
|
|
48
|
+
<text x="820" y="484.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">重启后自动接管 running 任务</text>
|
|
49
|
+
<rect x="700" y="560" width="240" height="60" rx="9" fill="#eaf7ef" stroke="#2e9e5b" stroke-width="1.6"/>
|
|
50
|
+
<text x="820" y="586" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">succeeded</text>
|
|
51
|
+
<text x="820" y="606.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">产物转存 DSH 附件 + 令牌媒体链接</text>
|
|
52
|
+
<rect x="460" y="560" width="190" height="60" rx="9" fill="#fceded" stroke="#c94f4f" stroke-width="1.6"/>
|
|
53
|
+
<text x="555" y="586" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">failed</text>
|
|
54
|
+
<text x="555" y="606.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">保留错误说明</text>
|
|
55
|
+
<rect x="230" y="560" width="180" height="60" rx="9" fill="#f5f6f8" stroke="#b9c2ce" stroke-width="1.6"/>
|
|
56
|
+
<text x="320" y="586" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">canceled</text>
|
|
57
|
+
<text x="320" y="606.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">取消信号传播</text>
|
|
58
|
+
<rect x="40" y="650" width="560" height="64" rx="8" fill="#ffffff" stroke="#b9c2ce" stroke-width="1.3" stroke-dasharray="5 4"/>
|
|
59
|
+
<text x="320" y="678" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">黄金规则:远端受理后绝不自动重提</text>
|
|
60
|
+
<text x="320" y="698.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">重提只发生在提交阶段的模型候选切换,避免重复计费</text>
|
|
61
|
+
<rect x="640" y="650" width="556" height="64" rx="8" fill="#ffffff" stroke="#b9c2ce" stroke-width="1.3" stroke-dasharray="5 4"/>
|
|
62
|
+
<text x="918" y="678" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="14.5" font-weight="600" fill="#1f2328">启动恢复与取消</text>
|
|
63
|
+
<text x="918" y="698.5" text-anchor="middle" font-family="'PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Noto Sans SC','Microsoft YaHei',sans-serif" font-size="12" font-weight="400" fill="#5b6472">有 remoteTaskId 的任务继续盯守;孤儿提交清理为 failed;取消传播到本地等待与轮询</text>
|
|
64
|
+
</svg>
|