better-dsh 0.0.0 → 0.2.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/LICENSE +24 -0
- package/README.md +294 -4
- package/control-prompt.md +37 -0
- package/cordis.patch.yml +53 -0
- package/docs/00_adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
- package/docs/00_adr/0002-masking-is-presentation-only.md +15 -0
- package/docs/10_plans/A2A-messaging-channel-test-archive.md +256 -0
- package/docs/10_plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
- package/docs/10_plans/dashr-blueprint-review.md +201 -0
- package/docs/10_plans/dashr-blueprint.md +561 -0
- package/docs/10_plans/dashr-compaction-window-and-archive.md +307 -0
- package/docs/10_plans/dashr-profile-layer-feasibility.md +367 -0
- package/docs/10_plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
- package/docs/10_plans/dashr-security-sandbox-analysis.md +187 -0
- package/docs/10_plans/dashr-surface-invariant-and-omp-imports.md +97 -0
- package/docs/10_plans/ipython-kernel-interactive-interface-test-report.md +152 -0
- package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
- package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
- package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
- package/docs/10_plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
- package/docs/10_plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
- package/docs/10_plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
- package/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
- package/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
- package/docs/10_plans/recallable-compaction.md +147 -0
- package/docs/10_plans/spike-tag-repro.mjs +102 -0
- package/docs/10_plans/upstream-analysis.md +128 -0
- package/docs/50_test-reports/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
- package/docs/50_test-reports/kernel-provisioning.md +44 -0
- package/docs/50_test-reports/repl-kernel-provisioning-test-report.md +87 -0
- package/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-local-test-report.md +81 -0
- package/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-report.md +93 -0
- package/docs/50_test-reports/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
- package/docs/50_test-reports/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
- package/docs/50_test-reports/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
- package/docs/50_test-reports/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
- package/docs/50_test-reports/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/README.md +138 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +74 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +3890 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +544 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +592 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +30 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +1236 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +592 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +516 -0
- package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +54 -0
- package/docs/50_test-reports/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
- package/docs/50_test-reports/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
- package/docs/50_test-reports/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +7 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +6 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +8 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +4 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +5 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +7 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +7 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +4 -0
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +13 -0
- package/docs/50_test-reports/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
- package/docs/50_test-reports/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
- package/docs/50_test-reports/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
- package/docs/50_test-reports/v0.2.1d-/345/256/236/346/265/213/346/212/245/345/221/212.md +67 -0
- package/docs/50_test-reports/v0.2.1e-P1-/345/256/236/346/265/213/346/212/245/345/221/212.md +136 -0
- package/docs/50_test-reports/v0.2.1ef-dev-audit-report.md +73 -0
- package/docs/50_test-reports/v0.2.1f-plugin-shipped-ui-patches/345/256/236/346/265/213/346/212/245/345/221/212.md +102 -0
- package/docs/60_exploration-and-research/cordis-research.md +350 -0
- package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +186 -0
- package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +310 -0
- package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +300 -0
- package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +324 -0
- package/docs/60_exploration-and-research/web-frontend-composability-research.md +191 -0
- package/docs/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
- package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
- package/docs/adr/0002-masking-is-presentation-only.md +15 -0
- package/docs/distro-blueprint.md +81 -0
- package/docs/dsh-webUI-with-rlm-mode.png +0 -0
- package/docs/plans/A2A-messaging-channel-test-archive.md +256 -0
- package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
- package/docs/plans/dashr-blueprint-review.md +201 -0
- package/docs/plans/dashr-blueprint.md +561 -0
- package/docs/plans/dashr-compaction-window-and-archive.md +307 -0
- package/docs/plans/dashr-profile-layer-feasibility.md +367 -0
- package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
- package/docs/plans/dashr-security-sandbox-analysis.md +187 -0
- package/docs/plans/dashr-surface-invariant-and-omp-imports.md +97 -0
- package/docs/plans/ipython-kernel-interactive-interface-test-report.md +152 -0
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
- package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
- package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
- package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
- package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
- package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
- package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
- package/docs/plans/recallable-compaction.md +147 -0
- package/docs/plans/spike-tag-repro.mjs +102 -0
- package/docs/plans/upstream-analysis.md +128 -0
- package/docs/repositioning-and-rebranding.md +102 -0
- package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
- package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
- package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
- package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
- package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
- package/docs/v0.1.8d_artifacts/README.md +138 -0
- package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +74 -0
- package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +3890 -0
- package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +544 -0
- package/docs/v0.1.8d_artifacts/functions.json +592 -0
- package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +30 -0
- package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +1236 -0
- package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +592 -0
- package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +516 -0
- package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +54 -0
- package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
- package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
- package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
- package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +7 -0
- package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +6 -0
- package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +8 -0
- package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +4 -0
- package/docs/v0.2.0b_artifacts/hashline-probe.md +5 -0
- package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +7 -0
- package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +7 -0
- package/docs/v0.2.0b_artifacts/slowprobe/build.rs +4 -0
- package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +13 -0
- package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
- package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
- package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
- package/lib/client/index.js +473 -0
- package/lib/index.d.ts +736 -0
- package/lib/index.js +11518 -0
- package/lib/kernel-env-hxaihi9C.js +195 -0
- package/lib/kernel-env.d.ts +80 -0
- package/lib/kernel-env.js +3 -0
- package/lib/py-sdk-BCaOGYz7.d.ts +125 -0
- package/lib/py-sdk-CbgYiX8O.js +691 -0
- package/lib/py-sdk.d.ts +2 -0
- package/lib/py-sdk.js +3 -0
- package/package.json +325 -4
- package/scripts/kernel-provision.mjs +35 -0
- package/index.js +0 -3
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# iOS 原生 Chat App 桥接 DSH 调研(Chatbox / Cherry Studio)
|
|
2
|
+
|
|
3
|
+
- 日期:2026-09-02
|
|
4
|
+
- 结论状态:调研完成,未实施
|
|
5
|
+
- 目标:让没有 iOS App 的 Agent(DSH)借用已有原生 iOS App 的壳,获得原生移动端体验。核心思路:把 DSH 桥接成 OpenAI-compatible 的数据流(`/v1/chat/completions` SSE),供 Chatbox / Cherry Studio 消费。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
| 问题 | 答案 |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Chatbox 有 iOS App 吗 | **有,已上架 App Store**([id6471368056](https://apps.apple.com/us/app/chatbox-powerful-ai-client/id6471368056),4.6★),Google Play/APK 也有 |
|
|
14
|
+
| Chatbox iOS 能接自定义 OpenAI 兼容端点吗 | **能**。自定义 provider 只支持 OpenAI 规范(`apiHost` + `apiPath`,默认 `/v1/chat/completions`),且支持 JSON/deep-link 一键导入(v1.15.1+) |
|
|
15
|
+
| Cherry Studio iOS 过了测试期吗 | **没有**。截至 2026-09-02 仍是 TestFlight 内测 + IPA 侧载,最新版 v0.1.7(2026-02-27),未上 App Store |
|
|
16
|
+
| DSH 能被桥接吗 | **能,且不需改 harness 内核**。官方已有 4 个程序化表面:`headless` 一次性 CLI、Python/TS SDK(JSON-RPC over stdio,带事件流)、ACP server(标准 Agent Client Protocol)、webhook。推荐:OpenAI shim + Python SDK |
|
|
17
|
+
| 推荐路线(2026-09-02 下午更新,见 §9) | **主路线:ACP 直连** —— iOS ACP 客户端已存在且在 App Store(Agmente 等),DSH 自带 `--profile acp`,套一层 stdio→wss 即零开发直连;**兜底:Chatbox + OpenAI shim**(§4)。Cherry Studio 观望其 GA |
|
|
18
|
+
| iOS 上有"Cherry Studio × Chatbox 整合体"吗 | **有,Agmente**:原生 iOS、App Store 在架、直接说 ACP(thinking/tool call/权限审批全语义)、支持远端 `wss://`(见 §9) |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. Chatbox 现状
|
|
23
|
+
|
|
24
|
+
### 1.1 基本信息
|
|
25
|
+
|
|
26
|
+
- 仓库:[chatboxai/chatbox](https://github.com/chatboxai/chatbox)(Community Edition,**GPLv3**,Electron 桌面端开源;官方注明"regularly sync code from the pro repo",iOS/Android 由 pro 仓库构建发布)。
|
|
27
|
+
- iOS:**App Store 正式在架**([Chatbox - Powerful AI Client](https://apps.apple.com/us/app/chatbox-powerful-ai-client/id6471368056),"Designed for iPad",4.6★/595 ratings)。Android:Google Play(`xyz.chatboxapp.chatbox`)+ 官网 APK。
|
|
28
|
+
- 特性(App Store 页自述):多模型接入、"**Flexibly configure your own model services**"(自定义模型服务)、文档理解、图片生成、Markdown/LaTeX/HTML 渲染、本地优先存储、流式回复。
|
|
29
|
+
|
|
30
|
+
### 1.2 Provider 协议(桥接的关键契约)
|
|
31
|
+
|
|
32
|
+
官方[导入第三方提供方配置文档](https://raw.githubusercontent.com/chatboxai/chatbox-docs/main/guides/providers/import-config.md)(v1.15.1+)定义的 `ProviderConfig`:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
{
|
|
36
|
+
id: string, name: string,
|
|
37
|
+
type: 'openai', // 目前仅支持 openai 规范的 API
|
|
38
|
+
urls: { website, getApiKey?, docs?, models? },
|
|
39
|
+
settings: {
|
|
40
|
+
apiHost: string, // 如 https://bridge.pc.randomhash.app
|
|
41
|
+
apiPath?: string, // 默认 /v1/chat/completions
|
|
42
|
+
apiKey?: string, // 桥的 Bearer token
|
|
43
|
+
models: ModelInfo[] // modelId/nickname/_type/capabilities/contextWindow/maxOutput
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- **对我们最重要的一条**:自定义 provider 走且仅走 **OpenAI Chat Completions 规范**——这正好是桥接层要实现的东西,无需任何私有协议。
|
|
49
|
+
- 一键导入:`chatbox://provider/import?config=$BASE64_JSON`(deep link,iOS Safari 点击即入 App)。可以做一个"扫码/点链接即配好"的 onboarding 页面。
|
|
50
|
+
- `ModelInfo.capabilities`(`vision | reasoning | tool_use`)与 `contextWindow/maxOutput` 决定 Chatbox 的调用方式与限流,桥应在 `/v1/models` + 导入配置里如实声明。
|
|
51
|
+
|
|
52
|
+
### 1.3 对桥接的含义
|
|
53
|
+
|
|
54
|
+
- Chatbox 把**完整对话历史**随每个请求发来(OpenAI API 无状态语义)→ 桥可以无状态化,也可以做"粘性会话"(见 §4.3)。
|
|
55
|
+
- Chatbox 支持图片输入(vision)→ OpenAI `image_url` 消息可映射到 DSH SDK 的 `SdkEncodedImageBlock`。
|
|
56
|
+
- Chatbox 是纯 chat UI,不渲染 function-call 协议 → agent 的工具调用必须在**服务端**由 DSH 自己闭环,进度只能以文本增量呈现。
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 2. Cherry Studio 移动端现状(用户 asked:测试过了没?)
|
|
61
|
+
|
|
62
|
+
**答案:还没。截至 2026-09-02 仍是内测(TestFlight),未上 App Store。**
|
|
63
|
+
|
|
64
|
+
### 2.1 版本时间线([releases](https://github.com/CherryHQ/cherry-studio-app/releases))
|
|
65
|
+
|
|
66
|
+
| 版本 | 日期 | 要点 |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| 0.1.0 | 2025-10-31 | Day one 内测:[iOS TestFlight](https://testflight.apple.com/join/Mdd3bqvT) + IPA/APK 侧载([LINUX.do 公告](https://linux.do/t/topic/1109448)) |
|
|
69
|
+
| 0.1.1 | 2025-11-04 | CherryAI 免费模型、token 用量展示、局域网同步、provider 增删改修复 |
|
|
70
|
+
| 0.1.2 | 2025-11-20 | Gemini 3 适配、响应式布局、ai-core 升级 |
|
|
71
|
+
| 0.1.5 | 2025-12-25 | 左滑 Topic、粘贴图片、局域网传输改 TCP |
|
|
72
|
+
| 0.1.6 | 2026-01-08 | PDF 上传、**StreamableHTTP MCP**、迁移 pnpm |
|
|
73
|
+
| **0.1.7(最新)** | **2026-02-27** | HeroUI 重构、流式自动滚动开关等;此后 ~6 个月无新 release |
|
|
74
|
+
|
|
75
|
+
### 2.2 仓库与 Roadmap
|
|
76
|
+
|
|
77
|
+
- 仓库:[CherryHQ/cherry-studio-app](https://github.com/CherryHQ/cherry-studio-app)(Expo React Native + Tamagui + Redux,开源)。
|
|
78
|
+
- [Roadmap #234](https://github.com/CherryHQ/cherry-studio-app/issues/234)(最后更新 2026-04-25,仍 open):待办 = 同步桌面端 V2 数据结构、WebDAV、桌面↔移动数据同步、升级 RN 0.83/Expo 55。
|
|
79
|
+
- README:多 LLM provider"逐步集成 OpenAI, Gemini, Anthropic 等";provider/渠道管理已可用(0.1.1 起修复增删改)。
|
|
80
|
+
|
|
81
|
+
### 2.3 判断
|
|
82
|
+
|
|
83
|
+
- 用户两个月前(~2026-07)"在测试"的信息**今天仍成立**:最新 release 停在 2026-02 的 0.1.7,roadmap 未完成,未见 App Store listing。
|
|
84
|
+
- 移动端已有 OpenAI 规范 provider + 自定义渠道 + MCP(StreamableHTTP)——**一旦桥做好,Cherry Studio 移动端同样能直接消费**(它的 provider 模型与桌面版同源:自定义 apiHost + OpenAI 兼容格式)。
|
|
85
|
+
- 风险:项目节奏慢(半年没发版)、iOS 侧载 IPA 需自签(个人 Apple ID 7 天过期)、TestFlight 席位可能满。**不宜作为第一落地目标**。
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 3. DSH 侧可桥接面盘点(本机 upstream `dsh-v0.1.2-alpha.5` 源码实证)
|
|
90
|
+
|
|
91
|
+
DSH 官方已有 **4 个程序化驱动表面**,桥接完全不需要 hack web GUI:
|
|
92
|
+
|
|
93
|
+
| 表面 | 入口 | 特性 | 适配桥接度 |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| **headless profile** | `dsh --profile headless "task"` | 跑一个任务、打印最终答案、exit code 表达成败;不开端口、不留进程 | ★★★(最简 MVP,但**无增量流式**、一次一任务) |
|
|
96
|
+
| **Python SDK**(`pip install deepseek-harness-sdk`,[PyPI 已发布](https://pypi.org/project/deepseek-harness-sdk/):v0.1.2a3 2026-09-01 上架,owner `DeepSeek-Harness`,MIT,随包捆绑同版本 `deepseek-harness-runtime-bin` dsh runtime wheel,无需系统 Node) | `DeepSeekHarness(dsh_home, cwd, provider, model, reasoning_effort, max_tokens)` → `harness.run(prompt, session_id=...)` | 启动 `dsh --profile sdk` 子进程,newline-JSON-RPC over stdio;`RunResult(final_response, finish_reason, events, notifications)`;**`session.event` 通知流 = 增量文本块 → 可转 SSE**;session_id 复用即续会话(durable);支持图片块 | ★★★★★(推荐主通道) |
|
|
97
|
+
| **TS SDK / JSON-RPC server** | `dsh-sdk-client` ↔ `dsh-sdk-jsonrpc-server` 插件 | 同一协议的 TS 实现(`initialize` / `session/prompt` / `session.event` / `session.status` / `subagent.*`) | ★★★★(若桥用 Node 写) |
|
|
98
|
+
| **ACP server** | `dsh --profile acp` | 标准 Agent Client Protocol(JSON-RPC stdio):建/列/续/关会话、发文本+图片、收语义更新、**答权限询问**、取消 | ★★★★(标准化更好,但生态里 chat app 不讲 ACP,最终仍要 shim) |
|
|
99
|
+
| webhook 子系统 | `webhook-github` 等 | 已验证的外部事件 → 创建 Session(fire-and-forget) | ★★(触发型,非对话型) |
|
|
100
|
+
| web GUI 私有协议 | 3080 端口 typertGateway Remote 层 | token 认证 + 私有 typed 协议,**非公开稳定 API**,streaming 刻意在其外 | ✗(不建议第三方 App 直连) |
|
|
101
|
+
|
|
102
|
+
两个额外发现:
|
|
103
|
+
|
|
104
|
+
1. **`packages/test-support/llm-mock-server`(`dsh-llm-mock-server`)——是测试替身,不是桥,对 Python 桥参考价值≈0**:只存在于 upstream 源码 `test-support/` 区(**不随 prod npm 包分发**;入口是 monorepo 根的 `pnpm run mock:llm`)。协议层它确实是 OpenAI-compatible `POST /v1/chat/completions` + Bearer + SSE。但用途是给 **DSH 自己的 LLM 客户端**当假供应商:按预写剧本(FIFO)回放流重置/429/500/畸形 chunk 等抽风行为,在真实 HTTP 边界测 DSH 的重试/退避/超时——这活儿真供应商和 openai 官方 SDK(客户端库)都演不出来,所以 DSH 才自己造了个假服务端。**它不连模型、不跑 agent,把 Chatbox 指上去只会收到剧本假响应**。注意桥的协议契约的权威是 **OpenAI 规范 + Chatbox 实际发送/期待的行为**,不是 DSH 的测试代码——mock server 被 DSH 测试验证过,对 Chatbox 兼容性没有任何背书。Python 桥的正确参考物:openai 官方 Python SDK 的 pydantic 类型(可直接 import 解析请求/构造响应)+ FastAPI/sse-starlette(SSE 分帧),测试时把 openai 官方客户端指向桥跑通即可。mock server 仅在选 TS/Node 桥(用 `dsh-sdk-client`)时才有同语言搬运价值。
|
|
105
|
+
2. **安全默认**:SDK/ACP 是 automation-only(无人值守),`DeepSeekHarness` 必须显式 `dsh_home`(绝不读 `~/.dsh`)——桥应使用独立 DSH_HOME(如 `.dsh-bridge/`),与 prod `~/.dsh` 隔离,天然规避误操作。
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 4. 桥接架构提案(`dsh-openai-bridge`)
|
|
110
|
+
|
|
111
|
+
### 4.1 组件图
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
┌─────────────┐ OpenAI 规范 ┌──────────────────────────┐ JSON-RPC/stdio ┌────────────────┐
|
|
115
|
+
│ Chatbox iOS │ ──────────────▶ │ dsh-openai-bridge │ ───────────────▶ │ dsh --profile │
|
|
116
|
+
│ (App Store) │ GET /v1/models │ (FastAPI, 常驻) │ session/prompt │ sdk (子进程池) │
|
|
117
|
+
│ Cherry 移动端│ POST /v1/chat/ │ Bearer 校验 │ session.event │ → 工具/模型/ │
|
|
118
|
+
│ (TestFlight)│ completions │ model→profile 映射 │ ◀── 通知流 │ 会话持久化 │
|
|
119
|
+
└─────────────┘ (SSE stream) └──────────────────────────┘ └────────────────┘
|
|
120
|
+
▲ │
|
|
121
|
+
│ chatbox://provider/import │ 独立 DSH_HOME(隔离 prod)
|
|
122
|
+
└──── onboarding 页(一键导入配置) │ 部署: LAN 直连 / Caddy 反代(需批准) / Tailscale
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4.2 协议映射
|
|
126
|
+
|
|
127
|
+
| OpenAI 侧 | DSH 侧 |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `POST /v1/chat/completions` | `harness.run(prompt, session_id=…)` |
|
|
130
|
+
| `messages[]`(含图片 `image_url`) | 文本拼装为任务 prompt;图片 → `SdkEncodedImageBlock` |
|
|
131
|
+
| `model: "dsh-agent"` / `"dsh-web"` / … | 伪模型名 → (profile / provider / reasoning_effort) 映射表 |
|
|
132
|
+
| SSE `delta.content` | `session.event` 通知流中的文本块增量(`on_notification`) |
|
|
133
|
+
| `finish_reason: stop/length` | `RunResult.finish_reason`: `completed`→stop、`max-tokens`→length、`error`→stop+错误文本 |
|
|
134
|
+
| `GET /v1/models` | 映射表导出(同时生成 Chatbox `ProviderConfig` JSON) |
|
|
135
|
+
| `Authorization: Bearer <key>` | 桥自有 API key(用户填进 Chatbox 的 apiKey 字段) |
|
|
136
|
+
|
|
137
|
+
### 4.3 会话连续性(关键设计点)
|
|
138
|
+
|
|
139
|
+
OpenAI 请求无状态(全量 history 每次都发),两条路线:
|
|
140
|
+
|
|
141
|
+
- **A. 无状态(MVP)**:每次请求把整段 history 压成一个 prompt,跑一次性任务(headless 或新 session)。实现最简,语义忠实;代价是 DSH 侧上下文/工具状态不复用、每请求冷启动。
|
|
142
|
+
- **B. 粘性会话(推荐 V1)**:以 (chat 标识 + history 前缀哈希) 映射到稳定 `session_id`,只发**最新一轮 user 消息**,DSH 侧 durable session 保留上下文与工作区状态;检测到 history 被编辑/回退则重开 session。SDK 明确支持:*"Reusing both a harness and session id continues the durable conversation"*。
|
|
143
|
+
- 进程模型:常驻 `DeepSeekHarness` 子进程池(按 session 粘住),避免每请求 spawn dsh(冷启动秒级)。
|
|
144
|
+
|
|
145
|
+
### 4.4 流式与长任务
|
|
146
|
+
|
|
147
|
+
- Agent 一轮可能跑数分钟(工具循环)。SSE 需周期性 keep-alive(注释帧/心跳 delta),防止 iOS URLSession/Chatbox 超时断流。
|
|
148
|
+
- 工具活动不可用 function-call 协议呈现 → 约定**文本化进度**:如 `⚙️ running bash …` 细节折叠(Chatbox 渲染 Markdown,可用 `> ` 引用块或 `<details>`),最终只保留 assistant 正文。
|
|
149
|
+
- 非流式兜底:`stream:false` 直接回 `RunResult.final_response`。
|
|
150
|
+
|
|
151
|
+
### 4.5 部署拓扑(贴合本机现状)
|
|
152
|
+
|
|
153
|
+
- 桥进程:systemd user unit,监听 `127.0.0.1:<port>`;独立 `DSH_HOME=~/.dsh-bridge`。
|
|
154
|
+
- 暴露三选一:① LAN 直连(iPhone 同 WiFi,`http://192.168.31.130:port/v1`,Chatbox 允许 http 自定义 host);② **Caddy 反代**加子域(如 `dshapi.pc.randomhash.app` → 桥端口,HTTPS 自动证书,外网可达)——改 `/etc/caddy/Caddyfile` 按 AGENTS.md 需明确批准;③ Tailscale(最省事且不暴露公网)。
|
|
155
|
+
- 凭据:桥的 Bearer key 即 Chatbox 里填的 API key;`.env` 沿用 `~/.dsh/.env` 的真实 key 供 DSH 模型侧使用。
|
|
156
|
+
|
|
157
|
+
### 4.6 安全
|
|
158
|
+
|
|
159
|
+
- 桥 = 公网可打到的 agent 执行面:必须有 Bearer 鉴权、限流、超时;建议白名单 workspace(`cwd` 固定到专用目录)+ sandbox 策略(workspace-write、危险操作 guard)。
|
|
160
|
+
- automation 表面无人工确认(ACP 才有 permission answer 循环,SDK 直接跑)→ 远端触发 `bash` 等工具的风险要靠 DSH 侧 sandbox/permission profile 约束,而不是靠 App。
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 5. 先例(prior art)
|
|
165
|
+
|
|
166
|
+
- [i-am-logger/claude-code-proxy](https://github.com/i-am-logger/claude-code-proxy)、[AntonioAEMartins/claude-code-proxy](https://github.com/AntonioAEMartins/claude-code-proxy):把 Claude Code CLI 包成 OpenAI Chat Completions API(含 SSE)——**同一模式的成熟先例**,证明"CLI agent → OpenAI 兼容端点 → 任意 chat App"路线可行且社区有需求。
|
|
167
|
+
- keenturbo/[2API](https://github.com/keenturbo/2API):各家模型互转 OpenAI 兼容 API 的教程集。
|
|
168
|
+
- 桥的 OpenAI 协议面:openai 官方 Python SDK(客户端库;其 pydantic 类型可 import 来做服务端解析/构造,也是测试桥的首选客户端)+ FastAPI/sse-starlette;DSH repo 内 `dsh-llm-mock-server`(TS,测试替身)仅在 TS 桥路线下可搬运其服务端代码(见 §3)。
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 6. 风险与缺口
|
|
173
|
+
|
|
174
|
+
| 风险 | 影响 | 缓解 |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| Cherry Studio 移动端长期 0.1.x、半年无 release | 第二目标不确定 | 先落地 Chatbox;Cherry 观望 v0.2/GA |
|
|
177
|
+
| 长任务 SSE 被移动端掐断 | 体验中断 | 心跳帧 + 非流式兜底 + 断线后按 session_id 拉回结果 |
|
|
178
|
+
| 每请求冷启动慢(spawn dsh) | 首字延迟 | 常驻子进程池 + 粘性会话 |
|
|
179
|
+
| 无 function-call 透传,工具过程只能文本化 | 可视化降级 | 约定 Markdown 进度样式;未来可发富卡片(仅 dsh web 有) |
|
|
180
|
+
| 公网暴露 agent 执行面 | 安全 | Bearer + 限流 + sandbox profile + Tailscale 优先 |
|
|
181
|
+
| Chatbox 移动端与桌面端 provider 能力可能有差 | 配置不通 | iOS 实测验证(App Store 版当前支持自定义 provider,见 §1.1);deep link 导入兜底 |
|
|
182
|
+
| GPLv3(Chatbox CE) | 仅 API 互通无碍;若 fork 其代码需遵守 GPL | 我们只做服务端,不碰其代码 |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 7. 建议路线
|
|
187
|
+
|
|
188
|
+
1. **MVP(半天级)**:FastAPI 单文件桥:`POST /v1/chat/completions`(`stream:false`)→ 每请求 `dsh --profile headless` 拼全量 history 跑一次;`/v1/models` 假列表 + Chatbox 导入 JSON。局域网 iPhone 实测 Chatbox 连通。
|
|
189
|
+
2. **V1(1–2 天)**:换 Python SDK 常驻进程池 + 粘性 session_id + `session.event`→SSE 增量流 + 心跳;onboarding 页生成 `chatbox://provider/import` deep link;Caddy/Tailscale 暴露。
|
|
190
|
+
3. **V2(按需)**:图片输入(vision)、`model` 后缀映射 reasoning_effort、多 profile 伪模型(dsh-fast/dsh-max)、Cherry Studio 移动端接入验证、ACP 后端可替换实现。
|
|
191
|
+
|
|
192
|
+
> 附带红利:桥一旦存在,**任何** OpenAI 兼容客户端(不止这两个 App:LobeChat、OpenWebUI、Raycast、快捷指令……)都能直接消费 DSH agent。
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 8. 参考
|
|
197
|
+
|
|
198
|
+
- Chatbox:[GitHub](https://github.com/chatboxai/chatbox) · [App Store](https://apps.apple.com/us/app/chatbox-powerful-ai-client/id6471368056) · [官网](https://chatboxai.app) · [provider 导入配置文档](https://raw.githubusercontent.com/chatboxai/chatbox-docs/main/guides/providers/import-config.md)
|
|
199
|
+
- Cherry Studio 移动端:[GitHub](https://github.com/CherryHQ/cherry-studio-app) · [Releases](https://github.com/CherryHQ/cherry-studio-app/releases) · [Roadmap #234](https://github.com/CherryHQ/cherry-studio-app/issues/234) · [TestFlight](https://testflight.apple.com/join/Mdd3bqvT) · [发布公告 (LINUX.do)](https://linux.do/t/topic/1109448)
|
|
200
|
+
- DSH(本机源码 `upstream/deepseek-harness` @ `dsh-v0.1.2-alpha.5`):`python/README.md`、`python/sdk/README.md`、`packages/sdk/protocol/README.md`、`packages/bundle/headless/README.md`、`packages/acp/README.md`、`packages/api/README.md`、`packages/test-support/llm-mock-server/README.md`
|
|
201
|
+
- 先例:[claude-code-proxy (i-am-logger)](https://github.com/i-am-logger/claude-code-proxy) · [claude-code-proxy (AntonioAEMartins)](https://github.com/AntonioAEMartins/claude-code-proxy) · [2API](https://github.com/keenturbo/2API)
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 9. 追加调研(2026-09-02 下午):ACP 路线成立,OpenClaw 官方 iOS 已上架
|
|
206
|
+
|
|
207
|
+
> 背景:用户把目标升级为"iOS 上现成的、能接 **Agent**(非纯 LLM)的 App"——即 Cherry Studio(Agent 接口完善)× Chatbox(App Store 入场券)的整合体。结论:**这个整合体已经存在,而且不止一个。**
|
|
208
|
+
|
|
209
|
+
### 9.1 iOS 上的 ACP 原生客户端([ACP 官方 clients 页](https://agentclientprotocol.com/get-started/clients) Mobile clients 专区)
|
|
210
|
+
|
|
211
|
+
| App | App Store | 协议/形态 | 远端连接 | 备注 |
|
|
212
|
+
|---|---|---|---|---|
|
|
213
|
+
| **[Agmente](https://github.com/rebornix/Agmente)** ⭐首推 | ✅ [id6756249477](https://apps.apple.com/us/app/agmente/id6756249477) | **原生 ACP** + Codex app-server;Swift 原生、MIT;工具调用/结果/会话历史全渲染 | ✅ 官方路径:远端 host 起 agent → `stdio→wss`(`npx -y @rebornix/stdio-to-ws --persist --grace-period 604800 "<agent> --acp" --port 8765`)→ TLS → App 填 `wss://`;支持 Bearer + Cloudflare Access | 作者 rebornix(GitHub 资深工程师);README 明示支持 Copilot CLI/Gemini CLI/Claude Code adapters/Qwen/Mistral Vibe 等"任何 ACP agent" |
|
|
214
|
+
| [Shellular](https://github.com/shellular-org/app) | ✅ [id6761985327](https://apps.apple.com/us/app/shellular/id6761985327) | Claude Code/Codex/Pi 手机遥控(ACP 类) | ✅ | 2026-07 HN 热帖"用手机跑编程 agent" |
|
|
215
|
+
| [MobileVibe/Mobvibe](https://github.com/Eric-Song-Nop/mobvibe) | ✅ [id6758524635](https://apps.apple.com/tw/app/mobilevibe/id6758524635) | Claude Code Remote Control | ✅ | LINUX.do 作者帖(封号后自做) |
|
|
216
|
+
| [Happy](https://github.com/slopus/happy) | ✅ [id6748571505](https://apps.apple.com/us/app/happy-claude-code-client/id6748571505) | Claude Code/Codex 专用(`happy` CLI 包装 + 自家 E2E relay) | ✅(自家 server 中转) | 产品成熟但**绑定 claude/codex 两个 CLI**,对任意 ACP agent 不通用 |
|
|
217
|
+
| ACP UI(formulahendry/acp-ui) | 未逐个核实 | 声称 iOS/Android/Web | — | 备选 |
|
|
218
|
+
|
|
219
|
+
**对 DSH 的意义——零开发直连路径(理论,待 iPhone 实测)**:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# PC 侧(DSH 自带 ACP server profile):
|
|
223
|
+
DSH_HOME=~/.dsh-acp npx -y @rebornix/stdio-to-ws --persist --grace-period 604800 \
|
|
224
|
+
"dsh --profile acp" --port 8765
|
|
225
|
+
# Caddy 给 wss:// 套 TLS(改 Caddyfile 需批准,AGENTS.md 约定)
|
|
226
|
+
# iPhone Agmente 填 wss://<host> + Bearer
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
ACP 的表达力正是 OpenAI shim 给不了的:**thinking 过程、tool call 事件、权限审批(permission request→iOS 上点批准)、cancel**,DSH 的 ACP server(`packages/acp`:建/续/关会话、MCP attach、模型选择、文本+图片 prompt、语义更新、答权限、取消)全部原生覆盖。原 §4 的 OpenAI shim 方案**降级为兜底**(覆盖 Chatbox 等纯 LLM 壳 App 仍有价值)。
|
|
230
|
+
|
|
231
|
+
### 9.2 OpenClaw:官方 iOS App **已于 2026-06-30 上架** App Store + Google Play
|
|
232
|
+
|
|
233
|
+
- 多源报道(2026-06-30):[新浪](https://finance.sina.com.cn/roll/2026-06-30/doc-inifczzw4921295.shtml)、[ZOL](https://ai.zol.com.cn/1207/12079539.html)、[太平洋](https://www.pconline.com.cn/ai/article/1612736.html)、[MacMagazine](https://macmagazine.com.br/post/2026/06/30/openclaw-ganha-aplicativo-para-ios-com-controle-remoto-de-agentes/)、[36氪("OpenClaw和Cursor杀入手机")](https://www.36kr.com/p/3875041298961416);repo 有 `apps/ios/`;设计方向见 [issue #85731](https://github.com/openclaw/openclaw/issues/85731)(含 approvals/approval queue 界面 = 权限审批一等公民)。
|
|
234
|
+
- 对 DSH:**无直接消费价值**——OpenClaw App 只连 OpenClaw 自家 gateway(它本身是 agent 运行时,不是通用 agent 客户端)。除非把 DSH 包装成 OpenClaw 的 skill/agent(不建议)。但生态信号明确:OpenClaw 也在向 ACP 收敛(acpx CLI 在 ACP clients 榜单、`@openclaw/acp-standard` plugin PR #28662)。
|
|
235
|
+
- 用户问"OpenClaw 有没有 iOS 计划"——答案:不只是计划,**已上架两个月**。
|
|
236
|
+
|
|
237
|
+
### 9.3 Cherry Studio iOS 状态复查(2026-09-02 当日二次核实)
|
|
238
|
+
|
|
239
|
+
- repo **活跃**:`pushed_at = 2026-09-02T13:12Z`(当天数小时前还在推代码);stars 3776。
|
|
240
|
+
- 但 **最新 release 仍是 v0.1.7(2026-02-27),TestFlight 仍在,App Store 仍无 listing**——用户在 App Store 搜不到是准确的。判断:v0.2/桌面端 V2 数据同步重构进行中(roadmap #234),上架遥遥无期,继续观望。
|
|
241
|
+
- **协议考证(纠正)**:用户猜测 Cherry Studio 接 OpenClaw 走 ACP。经官方文档 ask 接口核实:Cherry 官方文档中 **Cherry Agent 的后端协议要求是 Anthropic 兼容(`/v1/messages`)**([providers 文档](https://docs.cherryai.com.cn/pre-basic/providers.md):"Cherry Agent 需要此类型(Anthropic 兼容)"),文档中未见 ACP。网上"Cherry Studio 接 OpenClaw"教程大概率是把 OpenClaw 的 **Anthropic 兼容端点**当 provider 用。若 Cherry iOS 将来上架,DSH 对接它的正确姿势可能是 **Anthropic `/v1/messages` shim**(而非 ACP bridge),比 OpenAI shim 多一层 thinking/tool_use 块语义,工作量相近。
|
|
242
|
+
- DeepWiki 显示 cherry-studio 桌面版有 "Code Tools and CLI Integration"(Claude Code 等 CLI 集成)章节,其协议(ACP 或内部 spawn)未证实——若为 ACP,则 Cherry 桌面/未来 iOS 亦可直连 DSH ACP server。
|
|
243
|
+
|
|
244
|
+
### 9.4 更新后的路线排序
|
|
245
|
+
|
|
246
|
+
1. **主路线(ACP 直连,≈零开发)**:Agmente + `@rebornix/stdio-to-ws` + `dsh --profile acp` + Caddy TLS。先 iPhone 实测握手兼容性(DSH ACP 是标准 Zed 式 ACP,理论兼容,未实测)。
|
|
247
|
+
2. **兜底(OpenAI shim,1–2 天)**:§4 方案不变,覆盖 Chatbox 等一切 OpenAI 兼容客户端。
|
|
248
|
+
3. **观望**:Cherry Studio iOS(若上架,按 Anthropic-compat shim 对接);OpenClaw App(与 DSH 无消费关系)。
|
|
249
|
+
|
|
250
|
+
### 9.5 本机 runtime 网络接口扫描(2026-09-02 实测;用户已装 Agmente,确认其服务端形态 = WS/WSS + Bearer)
|
|
251
|
+
|
|
252
|
+
**问题**:本机已装的 agent 运行时,有没有原生就挂 WS/WSS(说 ACP)的?——**答案:没有。**
|
|
253
|
+
|
|
254
|
+
| Runtime(本机实测) | 网络原生接口 | ACP 传输层 | Agmente 直连? |
|
|
255
|
+
|---|---|---|---|
|
|
256
|
+
| **Hermes** v0.20.6 | HTTP API ×4 个 profile 常驻(`0.0.0.0:8642-8645`,JSON+SSE:`/api/sessions/{id}/chat`、`/v1/runs`、OpenAI 兼容子集);**WebSocket 仅 `/v1/browser-control/ws`**(浏览器控制通道,一次性 ticket + 子协议,非 agent 对话入口)——源码 `~/.hermes/hermes-agent/gateway/platforms/api_server.py` 实证 | `hermes acp` = **stdio only**(`--help` 无任何 port/ws 参数,面向 Zed/VS Code/JetBrains) | ❌ HTTP API 是 Hermes 私有 REST,非 ACP |
|
|
257
|
+
| **OpenCode** 1.17.13 | `opencode serve`(自家 HTTP API + basic auth) | `opencode acp --port N` 的 **port 是它内部 HTTP server**(供 ACP 层经 SDK 调 opencode 本体),ACP wire 本身接在 stdin/stdout(二进制字符串实证:handler 把 `process.stdin` ReadableStream 喂给 ACP connection,stdout 做 sink) | ❌ 矩阵文档"stdio + HTTP"的 HTTP 部分不承载 ACP |
|
|
258
|
+
| **DSH** 0.1.2-alpha.3/5 | web GUI 私有协议(3080/3081/4999) | `dsh --profile acp` = stdio(upstream `packages/acp` 明确 JSON-RPC over stdio) | ❌ |
|
|
259
|
+
| Pi / Claude Code / agy | 无 HTTP/WS daemon | 无原生 ACP(Claude 有 `@agentclientprotocol/claude-agent-acp` adapter) | ❌(Claude 走 adapter+wrapper) |
|
|
260
|
+
| OpenClaw | WS gateway :18789 是**自家协议**非 ACP;且不在本机(在 dev4) | `openclaw acp`(bridge to gateway) | ❌ |
|
|
261
|
+
|
|
262
|
+
**结论与对策**:ACP 生态目前的远端标准形态就是"远端 host 起 stdio ACP agent → `stdio-to-ws` 包成 wss"(Agmente 官方 quick start 即如此)。`@rebornix/stdio-to-ws` v0.2.0(npm 实查:Apache-2.0,31KB,仅依赖 ws+minimist,`--persist --grace-period 604800` 断连后子进程保活 7 天)就是为这个缺口而生的通用件。零代码拓扑:
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
iPhone Agmente ─wss+Bearer→ Caddy(TLS) → stdio-to-ws → stdio → ┬─ dsh --profile acp (DSH_HOME=~/.dsh-acp)
|
|
266
|
+
├─ hermes acp
|
|
267
|
+
└─ opencode acp
|
|
268
|
+
```
|
|
269
|
+
每个 agent 一个 wrapper 实例/端口。若要**单端点多路复用多 agent**(一个 wss,session 级路由到不同 agent),才需要自研小 ACP-over-WS 网关(Node+ws 几百行,newSession 时路由)——建议先跑通单 agent 实测 Agmente 兼容性再决定。
|
|
270
|
+
|
|
271
|
+
⚠️ 顺手发现:Hermes 4 个 API server 绑 `0.0.0.0`(全网卡监听);已有 `API_SERVER_KEY` 认证(`~/.hermes/.env`),但建议确认 LAN 暴露是否合意。
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 10. DSH-ACP 实测记录(2026-09-02 晚,全部通过)
|
|
276
|
+
|
|
277
|
+
测试环境:`DSH_HOME=<ws>/.dsh-test`(隔离测试 home,真实模型 key),agent 工作目录 `.scratch/acp-playground`,模型 `deepseek-official/deepseek-v4-flash`(3 次真实小回合)。脚本:`.scratch/acp_smoke.py`(stdio 直连)、`.scratch/acp_ws_test.py`(WS 两阶段,含断线重连)。
|
|
278
|
+
|
|
279
|
+
### 10.1 Phase 1 — stdio 直连 `dsh --profile acp`:✅ PASS
|
|
280
|
+
|
|
281
|
+
| 步骤 | 结果 |
|
|
282
|
+
|---|---|
|
|
283
|
+
| `initialize` | 1.7s 返回;agentInfo `deepseek-harness-acp v0.0.1`;caps:mcp.http=true、sessionCapabilities **close/list/resume**、promptCapabilities image=false |
|
|
284
|
+
| `session/new` | sessionId + configOptions(model select:deepseek-official/deepseek-v4-flash) |
|
|
285
|
+
| `session/prompt`("Reply with exactly: ACP-OK") | 流式 `agent_message_chunk` + `usage_update`;stopReason=end_turn;回复正是 `ACP-OK` |
|
|
286
|
+
| `session/close` + stdin EOF | 干净退出 |
|
|
287
|
+
|
|
288
|
+
### 10.2 Phase 2 — WebSocket(Agmente 确切路径):✅ PASS
|
|
289
|
+
|
|
290
|
+
`npx -y @rebornix/stdio-to-ws --persist --grace-period 604800 "dsh --profile acp" --port 8800`
|
|
291
|
+
|
|
292
|
+
- **Phase A**:connect → 信封帧 `{"type":"connected","clientId":…}` → initialize → session/new → prompt → **`WS-ACP-OK`**;期间观察到 `agent_thought_chunk`(思维流)、`agent_message_chunk`、`usage_update`。
|
|
293
|
+
- **Phase B(断线重连)**:断开 → 带 `X-Client-Id` 头重连 → 信封 `{"type":"reconnect",…}`(**同一 dsh 子进程被重新挂上**)→ `session/list` 列出 2 个会话(含 Phase 1 stdio 测试的历史会话 = 跨进程持久化)→ 对原 sessionId 直接 prompt "What was the secret word?" → 回答 **`KIWI-7741`**(断线前埋的秘密词)→ **memory-across-reconnect: PASS**。
|
|
294
|
+
|
|
295
|
+
### 10.3 踩坑记录(对给 Agmente 配 DSH 有直接参考价值)
|
|
296
|
+
|
|
297
|
+
1. **换行分隔必须由客户端补**:wrapper 是纯字节管道,ACP 是 newline-delimited JSON-RPC。发 JSON 不带 `\n` → dsh 行读取器永远等待 → 表现为"子进程沉默卡死"。补 `\n` 后立刻全通。
|
|
298
|
+
2. **wrapper 信封协议**:每连接首帧 `{"type":"connected","clientId"}`;重连须带 `X-Client-Id` 请求头 → 收 `{"type":"reconnect"}` 并回放断线期间缓冲的消息。ACP 消息解析前要跳过信封帧。
|
|
299
|
+
3. **黏包**:一个 stdout chunk 的多条 JSON 可能黏在一个 WS 帧里,客户端须按行拆分。
|
|
300
|
+
4. **`session/load` 不存在**(-32601);DSH 的会话恢复按 caps 是 **`session/resume`**。且 `--persist` 同子进程存活期间,直接对原 sessionId `session/prompt` 也能续(B 阶段即如此)。
|
|
301
|
+
5. `promptCapabilities.image=false`:当前默认路由不接受图片 prompt。
|
|
302
|
+
|
|
303
|
+
### 10.4 结论与服务端建议命令
|
|
304
|
+
|
|
305
|
+
DSH → iOS Agmente 的服务端链路**已在协议层全通**(stdio 与 WS 两种传输、断线重连、跨进程会话持久化、思维流/工具事件通道均验证)。剩余步骤只有网络暴露与 iPhone 真机连接:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
# systemd user service 建议形态
|
|
309
|
+
Environment=DSH_HOME=/home/u1/workspaces/dashr/.dsh-acp # 建议专用 home,与 .dsh-test/prod 分离
|
|
310
|
+
Environment=npm_config_cache=/home/u1/workspaces/dashr/.scratch/npm-cache
|
|
311
|
+
ExecStart=/usr/bin/env npx -y @rebornix/stdio-to-ws --persist --grace-period 604800 \
|
|
312
|
+
"dsh --profile acp" --port 8800
|
|
313
|
+
# Caddy: dshacp.pc.randomhash.app { reverse_proxy 127.0.0.1:8800 } → iPhone Agmente 填 wss://dshacp.pc.randomhash.app
|
|
314
|
+
# (改 Caddyfile 需批准;wrapper 本身不带 Bearer 校验,认证依赖 TLS + Cloudflare Access 或前置网关,见 §9.1 Agmente 的 Access 支持)
|
|
315
|
+
|
|
316
|
+
### 10.5 iPhone Agmente 真机首连(2026-09-02 深夜)— 首连成功,notice 已定性
|
|
317
|
+
|
|
318
|
+
用户 iPhone Agmente 连 `ws://192.168.31.130:8800`:服务器被识别(deepseek-harness-acp v0.0.1),随后 App 弹 `Session…NotSupported` 提示。wrapper 日志定性:
|
|
319
|
+
|
|
320
|
+
- Agmente 连接序列:initialize(clientInfo "Agmente iOS")→ `session/list` → **`session/load {sessionId:"capability-probe"}` 能力探测** → -32601 → 弹 notice。它还实测了 X-Client-Id 重连(wrapper 信封 reconnect 正常工作)。
|
|
321
|
+
- **规范定性(ACP schema 原文)**:`session/resume` = "Resumes an existing session without returning previous messages (unlike session/load)"。DSH 实现的是 resume(与它宣告的 `sessionCapabilities.resume{}` 一致),未实现 `session/load`(完整 transcript 回放)。**该 notice 是能力降级提示,非故障**——Agmente 自己的 App Store 描述就是这个模式的说明(历史本地存、agent 记得即可续)。
|
|
322
|
+
- **聊天主路径已验证**:模拟 Agmente 全序列(initialize→list→load 探测→session/new cwd=/tmp→中文 prompt)→ stopReason=end_turn、回复正常。**用户操作:关掉 notice,新建对话直接聊。**
|
|
323
|
+
- 次要坑:Agmente 发过 `cwd:"~/.dsh-acp"` 被 DSH 拒(-32602 要求绝对路径)——App 里 workspace/目录字段须填绝对路径(如 `/tmp` 或 `/home/u1/workspaces/dashr/.scratch/acp-playground`),不能带 `~`。
|
|
324
|
+
- 消除 notice/获得完整回放需给 DSH 实现 `session/load`(upstream 功能缺口,非配置项);当前 resume-only 已满足移动端使用。
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Web 前端空间可组合性调研
|
|
2
|
+
|
|
3
|
+
> 记录:2026-08-25 · 一手核验:MDN Web Components/Custom Elements/DSD 文档、webpack
|
|
4
|
+
> Module Federation 官方 docs、module-federation.io、native-federation.com、Angular DI
|
|
5
|
+
> 官方指南、qiankun/wujie 源码级对比(掘金 deep-dive)、htmx 官方 essays、Islands
|
|
6
|
+
> Architecture(Bridgetown / islands-architecture.com)。
|
|
7
|
+
> 本文是 `cordis-research.md` 的 Web 侧对照:把 Cordis 的"时空可组合性"结论拿到浏览器端,
|
|
8
|
+
> 回答"HTML 前端能不能也做到模块即插即用(先只看空间维)"。
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. 一句话结论
|
|
13
|
+
|
|
14
|
+
**能,且分三层粒度,但空间维被浏览器"半完成"了:**
|
|
15
|
+
- **时间维(可逆效应 / 即插即拔)**——浏览器**原生已实现**:Custom Element 的
|
|
16
|
+
`connectedCallback` / `disconnectedCallback` 就是一对平台级的可逆效应(插=setup,拔=teardown,
|
|
17
|
+
元素移出 DOM 即触发、重新插入再触发,甚至元素 *移动* 都会重跑一遍)。
|
|
18
|
+
- **空间维(反应式余效应 / 依赖→激活停用)**——**只完成了一半**:
|
|
19
|
+
- 「封装 + 组合」这半(Shadow DOM、`<slot>` 投影、`::part`、CSS custom properties、scoped
|
|
20
|
+
registry)**原生已实现**;
|
|
21
|
+
- 「依赖声明 → 自动拓扑 → 依赖齐/缺自动激活/停用」这半(Cordis 的 `inject` + `epoch`)——
|
|
22
|
+
**浏览器没有原生对应,也没有哪个框架做到反应式**。最接近的是 Module Federation 的
|
|
23
|
+
share scope(运行时依赖协商,但只在 bootstrap 一次性、按 semver 匹配、app 粒度、非反应式)。
|
|
24
|
+
|
|
25
|
+
**判定**:把 Cordis 的 `epoch`(依赖满足度签名 → 提供者撤走依赖者先停、回归自动恢复)搬到
|
|
26
|
+
浏览器,是当前 Web 生态的**真空区**。这也是"Web 版 Cordis"最值钱的研究方向。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. 三层粒度测绘
|
|
31
|
+
|
|
32
|
+
HTML 前端的"模块"有三个正交的粒度,各有一套即插即用机制,别混为一谈:
|
|
33
|
+
|
|
34
|
+
| 粒度 | 单元 | 即插即用机制 | 代表 |
|
|
35
|
+
|---|---|---|---|
|
|
36
|
+
| **元素/组件层** | 单个自定义元素 | Custom Elements + Shadow DOM + slot + scoped registry | `<video>`、Shoelace、Lit |
|
|
37
|
+
| **应用层** | 独立构建/部署的前端应用 | Module Federation / single-spa / qiankun / wujie / iframe | 微前端 |
|
|
38
|
+
| **岛屿层** | 页面里一块独立水合的 SSR 区域 | DSD + partial hydration + `connectedCallback` | Astro、Bridgetown |
|
|
39
|
+
|
|
40
|
+
三层不是互斥,是叠加:一个微前端(应用层)内部用 Web Components(元素层)组装,页面壳用
|
|
41
|
+
Islands(岛屿层)做选择性水合。Cordis 的"space dimension"在浏览器里被摊到了这三层上。
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 3. 空间维映射(Cordis → Web 逐项对照)
|
|
46
|
+
|
|
47
|
+
Cordis 空间维 = **Reactive Coeffects**:组件声明依赖(`inject`)→ 自动拓扑编排 → 依赖齐
|
|
48
|
+
ACTIVE、缺 INACTIVE、提供者撤走依赖者先停、回归自动恢复。逐项找 Web 对应:
|
|
49
|
+
|
|
50
|
+
| Cordis 概念 | Web 对应 | 是否原生 | 缺口 |
|
|
51
|
+
|---|---|---|---|
|
|
52
|
+
| `Context`(运行时 proxy,属性走服务解析器) | 全局 registry / import map / Angular root injector | 部分 | 无"作用域 proxy 透明代理服务" |
|
|
53
|
+
| `inject`(依赖声明) | Angular 构造器注入 / React `useContext` / import specifier / MF `shared` | ✅ | 语义等价,但**绑定即终态**,不响应变化 |
|
|
54
|
+
| `ReflectService`(`provide`/`inject` 服务解析) | **Angular 分层注入器**(ElementInjector / EnvironmentInjector) | ✅ | 最接近的单体;但图是静态的 |
|
|
55
|
+
| `Service`(`super(ctx,name)` 注册 + 随 fiber 卸载自动注销) | Angular `providers:[...]` + 组件销毁→服务销毁 | ✅ | 生命周期销毁对齐;无"重新提供" |
|
|
56
|
+
| **`epoch`(依赖满足度签名 → 激活/停用)** | **无原生对应** | ❌ | **核心真空**(见 §5) |
|
|
57
|
+
| 提供者撤走→依赖者先停→回归自动恢复 | single-spa `activeWhen`(仅路由谓词);无通用版 | ❌ | 仅路由键,非依赖键 |
|
|
58
|
+
| Scoped registry(作用域内定义) | **Scoped Custom Element Registries**(`CustomElementRegistry()` 构造器) | ✅(新) | 最干净的平行项,见下 |
|
|
59
|
+
| 上层 patch 按 id 整行替换插件 | Angular `{provide: X, useClass: Y}` provider override | ✅ | 子树级覆盖,静态声明 |
|
|
60
|
+
|
|
61
|
+
**Scoped Custom Element Registries 是最新、最干净的原生平行项**:它让一个 shadow tree 有自己
|
|
62
|
+
独立的元素定义表,不同子树可定义同名元素互不冲突——这正是 Cordis `Context.extend()` /
|
|
63
|
+
`isolate()` 作用域在 DOM 侧的镜像。2019 年前只有全局 `customElements` 单例,跨库组合必撞名;
|
|
64
|
+
现在作用域注册表把"组合"变成浏览器内置能力。
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 4. 时间维映射(可逆效应)
|
|
69
|
+
|
|
70
|
+
Cordis 时间维 = **Revertible Effects**:每次上下文修改配显式逆函数,叠成撤销链,卸载时反向
|
|
71
|
+
执行(LIFO)。
|
|
72
|
+
|
|
73
|
+
| Cordis | Web 对应 | 性质 |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `Fiber.effect(execute, label)` → 收集 disposer | `connectedCallback()`(setup) | 平台级 effect |
|
|
76
|
+
| 卸载时 disposers **逆序 LIFO**(`splice(0).reverse()`) | `disconnectedCallback()`(teardown)+ DOM 树移除天然后序 | 平台级逆函数 |
|
|
77
|
+
| 元素移动重跑 | `adoptedCallback` / 移动触发重 connected/disconnected | 比 Cordis 更激进 |
|
|
78
|
+
| single-spa `bootstrap→mount→unmount→unload` | 微前端显式可逆效应(Promise 化) | 框架级 effect/disposer |
|
|
79
|
+
|
|
80
|
+
**判定**:时间维在浏览器是**原生完成且免费**的——浏览器自己保证 `disconnectedCallback` 在元素
|
|
81
|
+
离开 DOM 时被调,不管元素是被 `innerHTML` 覆盖、被别的代码 `remove()`、还是整个子树被替换。
|
|
82
|
+
这正是 htmx 社区那句"everything in htmx has a DOM-based lifecycle"能成立的原因。**即插即拔这个
|
|
83
|
+
诉求,Web 从 2018 年起就已经交付了。**
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 5. 关键缺口:反应式依赖激活(`epoch`)为何 Web 没有
|
|
88
|
+
|
|
89
|
+
这是全文的题眼。Cordis 空间维的皇冠是 `epoch`:每个 fiber 持有一个"依赖满足度签名",遍历每个
|
|
90
|
+
`inject` 声明,任一缺失 → INACTIVE → `_unload()`;全部存在 → 激活;提供者 uid 变化 → 依赖者先
|
|
91
|
+
unload 再 reload。**这是运行时、持续、反应式的**。
|
|
92
|
+
|
|
93
|
+
Web 为什么没有:
|
|
94
|
+
|
|
95
|
+
1. **Web 的依赖单元是 ES module,静态、构建期解析**。`import` 绑定即终态,没有"服务"这个可以
|
|
96
|
+
在运行时上线/下线的概念。Cordis 有 `Service`(注册即提供、随 fiber 卸载即注销),浏览器
|
|
97
|
+
DOM 里没有等价物。
|
|
98
|
+
2. **仅有的运行时依赖协商是一次的**:Module Federation 的 share scope(`singleton`/`requiredVersion`/
|
|
99
|
+
`strictVersion`)和 Native Federation 的 import map 都是在**宿主 bootstrap 时**合并一次、
|
|
100
|
+
按 semver 匹配后固化。没有"某个 shared 依赖之后被移除 → 消费它的 remote 自动卸载"这回事。
|
|
101
|
+
3. **仅有的反应式激活是路由键的**:single-spa 的 `activeWhen` 谓词在路由变化时
|
|
102
|
+
mount/unmount,但键是 **URL**,不是**依赖**。没有框架拿"某个服务/能力是否在线"当激活键。
|
|
103
|
+
|
|
104
|
+
**推论(非事实,标记为待证)**:要在浏览器补上 `epoch`,最小改动路径是——
|
|
105
|
+
- 用一个运行时"服务注册表"(service registry)+ 自定义元素上的依赖声明属性(如
|
|
106
|
+
`<x-panel requires="ctx.llm ctx.tools">`),
|
|
107
|
+
- 服务上线/下线时触发一次拓扑重算,把依赖缺失的元素 `disconnectedCallback` 掉、依赖回归时重新
|
|
108
|
+
`connectedCallback`。
|
|
109
|
+
- 这套东西用原生 Custom Elements 生命周期 + Scoped Registry + 一个 observer 就能搭出来,不需要
|
|
110
|
+
改浏览器。**换句话说:Cordis 的空间维,浏览器已经备齐了所有原料(时间维免费的、组合原生的),
|
|
111
|
+
只差"谁把依赖图接上生命周期"这一小段胶水。** 这就是"Web 版 Cordis"的定义。
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 6. 竞品矩阵(空间可组合性维度)
|
|
116
|
+
|
|
117
|
+
按"同时具备 时间维可逆 + 空间维封装 + 空间维反应式依赖"三维打分:
|
|
118
|
+
|
|
119
|
+
| 方案 | 语言 | 时间维(可逆) | 空间维·封装组合 | 空间维·反应式依赖 | 免重启装卸 |
|
|
120
|
+
|---|---|---|---|---|---|
|
|
121
|
+
| **Custom Elements + Shadow DOM**(原生) | JS | ✅ connected/disconnected | ✅ slot/::part/scoped registry | ❌ | ✅ |
|
|
122
|
+
| **Angular 分层 DI** | TS | ✅ ngOnDestroy/scope teardown | 部分(组件树) | ❌(静态图) | 部分 |
|
|
123
|
+
| **single-spa** | JS | ✅ mount/unmount | ❌(靠 iframe/WC 补) | ⚠️ 仅路由键 activeWhen | ✅ |
|
|
124
|
+
| **Module Federation**(1.0/2.0) | JS | ❌(无卸载语义) | ❌ | ⚠️ share scope 一次性协商 | ❌ |
|
|
125
|
+
| **Native Federation**(import map + ESM) | JS | ❌ | ❌ | ⚠️ externals registry 一次性去重 | ❌ |
|
|
126
|
+
| **qiankun**(single-spa + Proxy 沙箱) | JS | ✅ 继承 single-spa | ✅ Shadow/scoped CSS | ❌ | ✅ |
|
|
127
|
+
| **wujie**(iframe + Web Components + Proxy) | JS | ✅ | ✅ 原生 iframe 隔离 | ❌ | ✅(保活) |
|
|
128
|
+
| **Astro / Bridgetown Islands** | JS/Ruby | ✅ island 独立水合 | ✅ DSD 封装 | ❌ | ✅ |
|
|
129
|
+
| **htmx + Web Components** | JS/HTML | ✅ DOM 生命周期 | ✅(可选 shadow) | ❌ | ✅ |
|
|
130
|
+
| **Cordis**(参照系) | TS | ✅ `effect` LIFO | ✅ `inject`+scoped ctx | ✅ **`epoch` 反应式** | ✅ |
|
|
131
|
+
|
|
132
|
+
**判定**:Web 生态在"时间维 + 空间维·封装"两项上完全覆盖 Cordis(且时间维还是原生免费的);
|
|
133
|
+
**全表唯一没有的,就是空间维·反应式依赖这一列**。整张表就 Cordis 一个 ✅。这就是差距,也是
|
|
134
|
+
"HTML 前端即插即用"这问题最诚实的答案:**即插即用(时间维)早就有了;依赖驱动的即插即用
|
|
135
|
+
(空间维)没有,且是所有主流前端框架共同的盲区。**
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 7. 微前端沙箱的附带发现(与 Cordis 异构桥呼应)
|
|
140
|
+
|
|
141
|
+
`cordis-research.md` §5 的结论是"跨语言 = 进程边界 + IPC 桥"。微前端沙箱是同一思想的 DOM 侧翻版:
|
|
142
|
+
|
|
143
|
+
- **qiankun 3.0**:`Proxy` + `with` + `Compartment` 三层模拟一个假 window(`Membrane` 拦截
|
|
144
|
+
get/set、`rebindTarget2Fn` 重绑 native 函数防 `Illegal invocation`、patch `addEventListener`/
|
|
145
|
+
`setInterval` 以便卸载时清理)。
|
|
146
|
+
- **wujie**:**隐藏 iframe 提供真实独立 window/document/history/location**(原生隔离),DOM 操作
|
|
147
|
+
经 Proxy 代理到 Shadow DOM。**这是"用原生沙箱(iframe)当隔离边界 + Proxy 当桥"**——与 Cordis
|
|
148
|
+
"Python 子进程 + fd3 帧协议"是同构的:**隔离靠真边界,桥接靠显式协议,消费者无感。**
|
|
149
|
+
|
|
150
|
+
对应关系:Cordis 的 `ctx.codeRuntime`(Python 子进程 + fd3)↔ 微前端的 iframe(子应用 window)
|
|
151
|
+
+ Proxy(DOM 桥)。都在说同一件事:**真隔离必须用运行时原生边界,桥是净新增的显式工作**。
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 8. 落到 dsh 的意义(为何这个调研现在做)
|
|
156
|
+
|
|
157
|
+
dsh 是 Web-first(`cordis-research.md` 提过其 Web 表面像 DeepSeek 官方 chat 页,append-only
|
|
158
|
+
session log、trajectory view)。它的插件在 **Cordis 层**已实现时空可组合性,但它的**前端表面
|
|
159
|
+
**目前仍是单体页面(React/自研栈),插件对 UI 的贡献是硬编码的。
|
|
160
|
+
|
|
161
|
+
若要让 dsh 的"everything is plugin"穿透到 UI 层——即**插件自带前端面板、即插即用**——现成的三
|
|
162
|
+
条路:
|
|
163
|
+
1. **Web Components**:插件暴露 `<dsh-*>` 自定义元素,走原生 slot/::part 组合(元素层,最小侵入)。
|
|
164
|
+
2. **Islands**:SSR 壳 + 插件面板作为可选择性水合岛屿(岛屿层)。
|
|
165
|
+
3. **微前端**:重型插件独立构建,Module Federation / Native Federation 运行时装载(应用层)。
|
|
166
|
+
|
|
167
|
+
**判定**:元素层(Web Components)+ 岛屿层已能覆盖绝大多数插件 UI 诉求,且与 Cordis 的"最小
|
|
168
|
+
侵入、零特权核心"哲学一致——插件注册一个自定义元素就像注册一个 Cordis Service。真正的难点
|
|
169
|
+
仍在 §5:**若插件 UI 依赖某服务(如 `ctx.llm` 未配)而该服务下线,UI 面板要不要自动灰掉/卸载?
|
|
170
|
+
** 答案是当前 Web 生态做不到反应式,除非自建 §5 的"服务注册表 + 依赖声明 + observer"胶水。
|
|
171
|
+
这恰好是 Cordis 已有、而前端缺失的那一块。
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 来源
|
|
176
|
+
|
|
177
|
+
- MDN:`Using custom elements`(含 Scoped Custom Element Registries、`:state()`、`::part`)、
|
|
178
|
+
`Web Components`、`Using templates and slots`、`Declarative Shadow DOM`(web.dev)
|
|
179
|
+
- webpack:`Module Federation` concepts(Container/ContainerReference、shared scope、singleton)
|
|
180
|
+
- module-federation.io(MF 2.0:Manifest / Federation Runtime / Runtime Plugin System)
|
|
181
|
+
- native-federation.com:`Runtime`(import map + externals registry 去重)、`Mental Model`、
|
|
182
|
+
`Architecture`(Core/Adapter/Runtime/Orchestrator 四层)
|
|
183
|
+
- single-spa:`bootstrap/mount/unmount/unload` 生命周期 + `activeWhen` 路由谓词
|
|
184
|
+
- qiankun(umijs/qiankun 3.0):Membrane/Compartment/Patchers 沙箱、strictStyleIsolation
|
|
185
|
+
- wujie(Tencent/wujie):iframe 原生隔离 + Web Components + Proxy 双容器架构
|
|
186
|
+
- Angular:`Hierarchical injectors`、`Defining dependency providers`(ElementInjector /
|
|
187
|
+
EnvironmentInjector / provider override / lazy-module injector / teardown)
|
|
188
|
+
- htmx:`Web Components Work Great with htmx`、`htmx.process(shadowRoot)`、shadow DOM host selector
|
|
189
|
+
- Islands:islands-architecture.com(Katie Sylor-Miller / Jason Miller)、Bridgetown DSD/Islands、
|
|
190
|
+
Codrops `Server-first Web Components with DSD, HTMX, and Islands`
|
|
191
|
+
- 掘金《Qiankun vs Wujie:微前端框架深度对比》(沙箱/隔离/插件系统源码级矩阵)
|