puppethub 0.1.0__tar.gz

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.
Files changed (49) hide show
  1. puppethub-0.1.0/LICENSE +21 -0
  2. puppethub-0.1.0/PKG-INFO +213 -0
  3. puppethub-0.1.0/README.md +188 -0
  4. puppethub-0.1.0/puppethub/__init__.py +19 -0
  5. puppethub-0.1.0/puppethub/__main__.py +6 -0
  6. puppethub-0.1.0/puppethub/appdir.py +421 -0
  7. puppethub-0.1.0/puppethub/autonomous.py +230 -0
  8. puppethub-0.1.0/puppethub/builder.py +304 -0
  9. puppethub-0.1.0/puppethub/builtin_plugins/__init__.py +7 -0
  10. puppethub-0.1.0/puppethub/builtin_plugins/default_prompt.py +221 -0
  11. puppethub-0.1.0/puppethub/builtin_plugins/file_storage.py +54 -0
  12. puppethub-0.1.0/puppethub/builtin_plugins/openai_compat.py +116 -0
  13. puppethub-0.1.0/puppethub/bus.py +220 -0
  14. puppethub-0.1.0/puppethub/catalog.py +44 -0
  15. puppethub-0.1.0/puppethub/chat.py +870 -0
  16. puppethub-0.1.0/puppethub/cli.py +579 -0
  17. puppethub-0.1.0/puppethub/cockpit.py +876 -0
  18. puppethub-0.1.0/puppethub/compat.py +91 -0
  19. puppethub-0.1.0/puppethub/config_edit.py +123 -0
  20. puppethub-0.1.0/puppethub/context.py +253 -0
  21. puppethub-0.1.0/puppethub/controlplane.py +136 -0
  22. puppethub-0.1.0/puppethub/fusion.py +510 -0
  23. puppethub-0.1.0/puppethub/gui_tools.py +720 -0
  24. puppethub-0.1.0/puppethub/home.py +652 -0
  25. puppethub-0.1.0/puppethub/hub.py +306 -0
  26. puppethub-0.1.0/puppethub/humanedit.py +77 -0
  27. puppethub-0.1.0/puppethub/keys.py +392 -0
  28. puppethub-0.1.0/puppethub/memory.py +239 -0
  29. puppethub-0.1.0/puppethub/orchestrator.py +746 -0
  30. puppethub-0.1.0/puppethub/plugins.py +447 -0
  31. puppethub-0.1.0/puppethub/protocol.py +216 -0
  32. puppethub-0.1.0/puppethub/recent.py +127 -0
  33. puppethub-0.1.0/puppethub/remote.py +221 -0
  34. puppethub-0.1.0/puppethub/render.py +1058 -0
  35. puppethub-0.1.0/puppethub/sandbox.py +129 -0
  36. puppethub-0.1.0/puppethub/secrets.py +376 -0
  37. puppethub-0.1.0/puppethub/session.py +876 -0
  38. puppethub-0.1.0/puppethub/society.py +735 -0
  39. puppethub-0.1.0/puppethub/theme.py +329 -0
  40. puppethub-0.1.0/puppethub/verify.py +93 -0
  41. puppethub-0.1.0/puppethub/window.py +321 -0
  42. puppethub-0.1.0/puppethub.egg-info/PKG-INFO +213 -0
  43. puppethub-0.1.0/puppethub.egg-info/SOURCES.txt +47 -0
  44. puppethub-0.1.0/puppethub.egg-info/dependency_links.txt +1 -0
  45. puppethub-0.1.0/puppethub.egg-info/entry_points.txt +2 -0
  46. puppethub-0.1.0/puppethub.egg-info/requires.txt +2 -0
  47. puppethub-0.1.0/puppethub.egg-info/top_level.txt +1 -0
  48. puppethub-0.1.0/pyproject.toml +47 -0
  49. puppethub-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 None-Ptr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,213 @@
1
+ Metadata-Version: 2.4
2
+ Name: puppethub
3
+ Version: 0.1.0
4
+ Summary: OpenPuppet 的搭建与运行软件:让 LLM 孕育并驱动应用。
5
+ Author: None-Ptr
6
+ License-Expression: MIT
7
+ Keywords: agent,llm,gui,flet,app-builder
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: MacOS
11
+ Classifier: Operating System :: Microsoft :: Windows
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: User Interfaces
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: openpuppet-language<2.2,>=2.1
23
+ Requires-Dist: flet==0.86.5
24
+ Dynamic: license-file
25
+
26
+ # PuppetHub
27
+
28
+ **搭 app 的软件**——不是 app 运行时框架,也不是 UI 库。
29
+
30
+ 人用**自然语言**描述想要什么,内置 LLM 把它翻译成**命令批**,引擎校验后写回真源并渲染。
31
+ 造出的 app **不含聊天框**:聊天只存在于 PuppetHub 自己的窗口里。
32
+
33
+ > **An app is an agent.** 应用本身就是会感知、决策、行动、记忆、调用工具的 agent;
34
+ > 自然语言对话只是驱动它的一种**输入方式**,不是它的输出。
35
+
36
+ ## 三层分工
37
+
38
+ | 层 | 内容 |
39
+ |---|---|
40
+ | `puppet`(PyPI:`openpuppet-language`) | 语言规范 + 语义引擎 + 自证套件,零第三方依赖 |
41
+ | **`puppethub`(本仓)** | 搭建 / 运行 / 运行时定制 / 未来的融合 |
42
+ | `puppetOS` | 基于 Linux 内核的发行版,**仅设计文档,不实现** |
43
+
44
+ ## 安装与运行
45
+
46
+ ```bash
47
+ # 语言标准实现(本阶段:本机仓库可编辑安装)
48
+ pip install -e ../Puppet
49
+
50
+ pip install -e .
51
+ puppethub new myapp
52
+ puppethub run myapp # 带窗口:左 app + 右驾驶舱
53
+ puppethub run myapp --no-llm # 无 LLM 实例:stdio 控制面,驱动者即写者
54
+ puppethub remote myapp # 远程/多客户端(TCP 无头绑定,写者=驱动者)
55
+ puppethub repl myapp # 手写程序模式:人作驱动者的命令批 REPL
56
+ puppethub verify-ci # 自证以退出码说话(CI/自动化用)
57
+ puppethub hub <父目录> up|down|status|list # 多 app 编排(生命周期,不制造第二写者)
58
+ puppethub fuse <A> <B> --yes # 融合:把 B 并入 A(审计→干跑→确认式合并→B 归档)
59
+ puppethub edit <app> # 正式手写程序模式:编辑器整份替换(确认前先干跑校验)
60
+ ```
61
+
62
+ ## 设计
63
+
64
+ - **第一原则:杜绝静默失败**。任何"降级 / 丢弃 / 无效 / 上限"都必须产生诊断、日志或事件。
65
+ 判据一句话:这条路径失败时,agent 看得到吗?看不到就是 bug。
66
+ - **仅 LLM 能写**。人是纯操作者:不用编辑器改程序,只能通过对话表达写入意图。
67
+ 命令批是改 `app.puppet` 的唯一方式(它带校验、行号诊断与批末原子写回)。
68
+ - **两本账物理分离**。程序(`app.puppet` + `capabilities.py`)与状态(`.puppet/`)
69
+ 不混存;引擎只写状态,**绝不改程序**——记忆因此不可能污染程序。
70
+ - **真源是程序 IR 的打印件**。注释与排版会在每次写回时被重排,故意图的唯一载体是
71
+ `DESIGN.md`,而不是程序里的注释。
72
+
73
+ 设计依据(决议表、已推翻决议及原因、spike 结论)在本仓 `docs/`:
74
+
75
+ - `docs/design-v1-draft.md` —— V1 实现依据
76
+ - `docs/spike-1-flet-coverage.md` —— flet 四层全覆盖三档清单 + 图标别名表
77
+ - `docs/spike-2-flet-verify.md` —— conformance 可行性、能力声明策略、并发桥接
78
+ - `docs/probe-flet-fields.py` —— 渲染层依赖的 flet 字段面(重跑即校验)
79
+
80
+ ## 配置与插件
81
+
82
+ `puppethub.toml`(可选的,**零配置也能跑**):三个槽位 + 每个插件自己的选项。
83
+
84
+ ```toml
85
+ llm_provider = "openai-compat" # 单选
86
+ storage = "file" # 单选
87
+ prompt = ["default"] # 多选叠加,按顺序跑
88
+
89
+ [plugins.openai-compat]
90
+ base_url = "https://api.openai.com/v1"
91
+ model = "gpt-4o-mini"
92
+ key_env = "OPENAI_API_KEY" # **只存变量名**:toml 会被 git 跟踪、进 dist、被打包
93
+ context_limit = 128000 # provider 自报窗口上限(宿主据此做超限的显式省略)
94
+ ```
95
+
96
+ 插件放在 `~/.puppethub/plugins/*.py`,**放文件即生效**(不必安装)。一个插件长这样:
97
+
98
+ ```python
99
+ NAME = "my-provider"
100
+ PROVIDES = ["llm_provider"] # 可选槽位:llm_provider / storage / prompt
101
+
102
+ def create_llm_provider(api): # 每个槽位一个工厂
103
+ return MyProvider(api)
104
+ ```
105
+
106
+ 三条边界(不是约定,是机制):**插件只产出值**(`PluginAPI` 不给任何引擎句柄)·
107
+ **策略在宿主、机制在插件**(storage 的可写路径只有 `.puppet/` 与 `.puppethub/`)·
108
+ **失败必须可见**(加载失败、槽位写错名、插件重名、路径越界,一律报出来,且坏插件不阻止启动)。
109
+
110
+ ## 当前进度
111
+
112
+ 已实现:
113
+
114
+ - `new` / `run` / `remote` / `repl` / `verify-ci` 子命令;语言版本**与数据文件**不齐**拒绝启动**
115
+ - app 目录契约:`app.puppet` · `capabilities.py` · `DESIGN.md` · `assets/` ·
116
+ `puppethub.toml` · `.puppethub/` · `.puppet/{state,memory,snapshots}`
117
+ - service 层:装载 → 命令批 → 批末整份写回真源 → **写前自动快照**
118
+ - 渲染层:程序 IR + 观察面 → flet 控件树(控件 / 属性 / 动效 / 图标四层映射)
119
+ - **共作者 LLM**:对话通道(后台线程 + 流式上屏)· 指令块协议(命令批 / 整体替换 /
120
+ 受限文件写入 / 反问)· 诊断回灌 · 卡住检测 · 危险动作两层确认 · 执行 / 讨论两档
121
+ - 插件体系:三槽位 + 目录扫描发现 + 失败隔离;内置 provider / storage / prompt
122
+ - 驾驶舱:对话 / 观察流与诊断 / 程序只读面板 + 命名快照 · 回滚 · 重载 · 重置 ·
123
+ 清记忆 · 自证 · 查看本轮 prompt;**关窗前拦脏状态**
124
+ - **自证**:`puppethub.protocol` 把产品渲染器包成 conformance 可驱动的子进程,
125
+ `自证`按钮跑它 → **118/118 通过(跳过 0)**
126
+ - **无 LLM 实例**:`run <app> --no-llm` 进入控制面(stdio 协议),驱动者就是写者——
127
+ 走的还是"引擎校验 → 批末写回真源 → 写前自动快照"那条路
128
+ - **运行期记忆**:`.puppet/memory/`(可读可改的 JSONL)· 每次写入留诊断 · 上限 + 语义化裁剪 ·
129
+ 自动裁剪与人主动清空**可区分** · **重置保留**,清空要显式(`--wipe-memory` / 驾驶舱按钮)
130
+ - **快照 / 引擎状态走 storage 槽位**:派生数据落盘走同一条通道(白名单 / 原子写 / 写失败标脏);
131
+ 程序资产(`app.puppet` / `capabilities.py`)走命令批与受限写入——两条通道各司其职
132
+ - **人工接管**:卡住 / 停手时驾驶舱亮接管栏(运行期开关,恢复留痕 `LLM_RESUME`)
133
+ - **确认卡细化**:待确认动作展示**将做什么 / 可逆性 / 撤销路径**,确认是判断不是点头
134
+ - **写者状态机 + 运行期自主 LLM**(`docs/design-v2-autonomous.md`):llm / autonomous / none
135
+ 互斥切换,切换写决策流水;自主当值时共作者退化为只读提问;**自主的边界更硬**——
136
+ 危险能力默认拒绝(白名单只能人预先给 `[autonomous] allow_calls`)、批行数与频次预算、
137
+ 连续失败熔断切回无人(可选自动回滚);每步在 `.puppethub/autonomous.jsonl` 留审计;
138
+ 驾驶舱自主面板显示写者 / 预算 / 最近决策(含被拒的)
139
+ - **热重载**:`capabilities.py` 盘上变化自动重载(可见 `CAPABILITY_RELOAD`);
140
+ 插件热重载带护栏(流式中 / 待确认时拒绝)
141
+ - **沙箱**:`[sandbox] enabled = true` 把 storage 插件跑进子进程(内置插件诚实拒绝沙箱化并说明理由)
142
+ - **远程 / 多客户端**:`remote` 子命令 = TCP 上的新绑定,同一套协议操作,单写者不破例
143
+ - **多 app 编排**:`hub` 子命令(V3 提前落地的最小形态)——发现父目录下的 app、
144
+ 以 remote 子进程拉起(**等握手才算数**,幂等)、按账本停止、TCP hello 健康检查;
145
+ **不制造第二个写者**。融合的语义设计见 `docs/design-v3-fusion.md`(草案)
146
+ - **融合端到端**(`fuse` 子命令):机制做体检(依赖对照 / id 与能力审计 / 多窗口拒绝),
147
+ LLM 出方案、人 `--yes` 确认;改名在 **IR 层**做(文本替换救不了 `#cafe` 这种
148
+ 颜色/地址歧义),窗口子树嫁接进 A 的窗口,合并先**干跑校验**再落盘;
149
+ B 归档改名不删除,决策流水留痕
150
+ - **正式手写程序模式**(`edit` 子命令):编辑器整份替换,人作驱动者——绕过对话,
151
+ 不绕过纪律(确认前干跑校验;拒稿留底 `app.puppet.rejected`、真源恢复原样;
152
+ 兜底快照 + 决策流水)
153
+ - **CI**:`.github/workflows/ci.yml`(conformance 自证 + **机制冒烟** + 编译检查。
154
+ 设计文档不进版本库是既定决议;机制冒烟 / 探针经 `.gitignore` 白名单进库,
155
+ flet 无头运行用 xvfb——CI 的信号从此不只 conformance,机制回归也有防线)
156
+ - **移动端前置**:触摸语义提案 `spec/proposals/touch-semantics.md`(语言仓,
157
+ T1-T4 条款,目标 2.2)
158
+ - **产物形态**:`packaging/` 下有 PyInstaller spec 与 Dockerfile(容器跑无头绑定,
159
+ 桌面窗口需要显示服务器——不声明做不到的)。**PyInstaller 已实测**:构建成功、
160
+ 产物 `verify-ci` 118/118 全绿(含三颗雷的修复:可编辑安装的 pathex、flet 数据文件、
161
+ 冻结态自证链的 python 替身垫片——详见 spec 头注释)
162
+ - **GUI 覆盖 CLI("所有仅 CLI 功能都有图形入口")**:驾驶舱「操作 » 凭据」是
163
+ **模型设置**(base_url / 模型 / 凭据名 / 凭据值 + 探活;端点可落"仅本 app"或
164
+ "本机 profile",**凭据可落钥匙串或环境变量**——落点写在选择旁边,含代价说明与
165
+ "清掉环境变量那把"的撤销路径);「工具」抽屉把 CLI 每条命令搬成浮层——
166
+ `new` 新建 app · `edit` **人的写入**(整份替换:干跑 → 兜底快照 → 拒稿留底)·
167
+ `repl` 命令批(origin=driver)· `build` 打包(生成工程 / 连跑 flet build)·
168
+ `hub` 编排(list/up/down/status/bus)· `remote` 服务化(真起无头进程)·
169
+ `fuse` 融合(先体检干跑再执行)。**每个动作都是可被冒烟直接调用的方法**
170
+ (`gui_tools.py`),浮层只是薄壳;语义一律在 service 层——CLI 与 GUI 同源,
171
+ 靠 `smoke-gui.py` 第 8 节机制化断言
172
+ - **凭据体系(V5)**:`docs/design-credentials.md`——**三层解析**(进程环境变量 →
173
+ 本机钥匙串 `~/.puppethub/secrets.toml` 0600 → 报错说清试过哪两层)· **机器级 profile**
174
+ (`~/.puppethub/providers.toml` 存端点/模型/凭据名,app 里只写 `[llm] profile = "名字"`,
175
+ 因此 **app 可以安全分享**)· **探活**把 401/403/404/429/超时/连不上分开说清 ·
176
+ **泄漏自检**真去 app 内文本文件里找明文(命中只报位置)· CLI `puppethub keys list|set|check`
177
+ 与驾驶舱「操作 » 凭据」共用同一实现。铁律:只有 `secrets.resolve()` 取明文,
178
+ 一切输出只给**名字/来源/长度**(连掩码都不给)
179
+ - **Agent 社会(V4)**:`docs/design-v4-society.md`——app 即服务(服务清单挂在 hello、
180
+ `call` 操作借出能力、**借出白名单缺省空 = 默认拒绝**)· 协作总线(`hub up` 自动拉起,
181
+ 消息 = 刺激不是写入,投递进对方观察流并触发其自主回路,审计落账 `hub bus`)·
182
+ 深度自主(`goal` 块定方向 + 定期反思沉淀记忆 + 同胞消息触发;目标跨会话可见)。
183
+ 铁律在协作里依然成立:**协作 = 说话与调用对方借出的能力,永远不写对方的程序**
184
+ - **移动端**:`build --target android|web` **已实现并实测**——生成独立 flet 工程
185
+ (纯 app 实例、写者=无、`pointer=touch` 自述、真源快照内嵌、REQUIRES 进 requirements、
186
+ **构建期解析**(缺包生成期就拒)+ **凭据 manifest**(capabilities.py 静态扫描 →
187
+ `manifest.json`,移动容器按它注入环境变量)、干跑门),生成的工程可独立装载与交互
188
+ (headless 子进程实测);最终 `flet build apk` 需 Android SDK(`--run-flet-build`
189
+ 代跑,失败如实上报)。触摸语义规范见语言仓 05 §10
190
+
191
+ 尚未实现(均**可见地**说明,不做假成功):
192
+
193
+ - `flet build apk` 的实际执行(需 Android SDK / 真机——生成工程与前置全部就绪)·
194
+ 融合的 `drops`(V3.1,B 归档保证不丢)· 多写者语义(V4 方向)
195
+
196
+ ## 自证脚本(都不联网,可重复跑)
197
+
198
+ ```bash
199
+ python docs/probe-flet-fields.py # 渲染层依赖的 flet 字段面
200
+ python docs/smoke-render.py # 无 GUI:装载 → 渲染 → 命令批 → 写回 → 交互
201
+ python docs/smoke-window.py # 真实窗口(隐藏):界面粘合 + 后台线程跑 LLM
202
+ python docs/smoke-llm.py # 对话回路机制(用脚本化 provider)
203
+ python docs/smoke-protocol.py --full # 协议外壳桥接 + 自证全量(分钟级)
204
+ python docs/smoke-controlplane.py # run --no-llm:驱动者即写者
205
+ python docs/smoke-memory.py # 运行期记忆:写入留痕 / 可读可改 / 语义化裁剪
206
+ python docs/smoke-v2.py # V2:写者状态机 / 自主回路 / 热重载 / 沙箱 / 远程
207
+ python docs/smoke-hub.py # 多 app 编排:发现 / 等握手拉起 / 幂等 / 停止
208
+ python docs/smoke-fusion.py # 融合:审计停下 / IR 改名 / 干跑 / 归档 / CLI 全链
209
+ python docs/smoke-edit.py # 手写程序模式:干跑守卫 / 拒稿留底 / 真源恢复
210
+ python docs/smoke-build.py # 设备打包:manifest 凭据 / REQUIRES 构建期解析 / 独立装载
211
+ python docs/smoke-society.py # V4:服务化 / 协作总线 / 深度自主,铁律不破
212
+ ```
213
+
@@ -0,0 +1,188 @@
1
+ # PuppetHub
2
+
3
+ **搭 app 的软件**——不是 app 运行时框架,也不是 UI 库。
4
+
5
+ 人用**自然语言**描述想要什么,内置 LLM 把它翻译成**命令批**,引擎校验后写回真源并渲染。
6
+ 造出的 app **不含聊天框**:聊天只存在于 PuppetHub 自己的窗口里。
7
+
8
+ > **An app is an agent.** 应用本身就是会感知、决策、行动、记忆、调用工具的 agent;
9
+ > 自然语言对话只是驱动它的一种**输入方式**,不是它的输出。
10
+
11
+ ## 三层分工
12
+
13
+ | 层 | 内容 |
14
+ |---|---|
15
+ | `puppet`(PyPI:`openpuppet-language`) | 语言规范 + 语义引擎 + 自证套件,零第三方依赖 |
16
+ | **`puppethub`(本仓)** | 搭建 / 运行 / 运行时定制 / 未来的融合 |
17
+ | `puppetOS` | 基于 Linux 内核的发行版,**仅设计文档,不实现** |
18
+
19
+ ## 安装与运行
20
+
21
+ ```bash
22
+ # 语言标准实现(本阶段:本机仓库可编辑安装)
23
+ pip install -e ../Puppet
24
+
25
+ pip install -e .
26
+ puppethub new myapp
27
+ puppethub run myapp # 带窗口:左 app + 右驾驶舱
28
+ puppethub run myapp --no-llm # 无 LLM 实例:stdio 控制面,驱动者即写者
29
+ puppethub remote myapp # 远程/多客户端(TCP 无头绑定,写者=驱动者)
30
+ puppethub repl myapp # 手写程序模式:人作驱动者的命令批 REPL
31
+ puppethub verify-ci # 自证以退出码说话(CI/自动化用)
32
+ puppethub hub <父目录> up|down|status|list # 多 app 编排(生命周期,不制造第二写者)
33
+ puppethub fuse <A> <B> --yes # 融合:把 B 并入 A(审计→干跑→确认式合并→B 归档)
34
+ puppethub edit <app> # 正式手写程序模式:编辑器整份替换(确认前先干跑校验)
35
+ ```
36
+
37
+ ## 设计
38
+
39
+ - **第一原则:杜绝静默失败**。任何"降级 / 丢弃 / 无效 / 上限"都必须产生诊断、日志或事件。
40
+ 判据一句话:这条路径失败时,agent 看得到吗?看不到就是 bug。
41
+ - **仅 LLM 能写**。人是纯操作者:不用编辑器改程序,只能通过对话表达写入意图。
42
+ 命令批是改 `app.puppet` 的唯一方式(它带校验、行号诊断与批末原子写回)。
43
+ - **两本账物理分离**。程序(`app.puppet` + `capabilities.py`)与状态(`.puppet/`)
44
+ 不混存;引擎只写状态,**绝不改程序**——记忆因此不可能污染程序。
45
+ - **真源是程序 IR 的打印件**。注释与排版会在每次写回时被重排,故意图的唯一载体是
46
+ `DESIGN.md`,而不是程序里的注释。
47
+
48
+ 设计依据(决议表、已推翻决议及原因、spike 结论)在本仓 `docs/`:
49
+
50
+ - `docs/design-v1-draft.md` —— V1 实现依据
51
+ - `docs/spike-1-flet-coverage.md` —— flet 四层全覆盖三档清单 + 图标别名表
52
+ - `docs/spike-2-flet-verify.md` —— conformance 可行性、能力声明策略、并发桥接
53
+ - `docs/probe-flet-fields.py` —— 渲染层依赖的 flet 字段面(重跑即校验)
54
+
55
+ ## 配置与插件
56
+
57
+ `puppethub.toml`(可选的,**零配置也能跑**):三个槽位 + 每个插件自己的选项。
58
+
59
+ ```toml
60
+ llm_provider = "openai-compat" # 单选
61
+ storage = "file" # 单选
62
+ prompt = ["default"] # 多选叠加,按顺序跑
63
+
64
+ [plugins.openai-compat]
65
+ base_url = "https://api.openai.com/v1"
66
+ model = "gpt-4o-mini"
67
+ key_env = "OPENAI_API_KEY" # **只存变量名**:toml 会被 git 跟踪、进 dist、被打包
68
+ context_limit = 128000 # provider 自报窗口上限(宿主据此做超限的显式省略)
69
+ ```
70
+
71
+ 插件放在 `~/.puppethub/plugins/*.py`,**放文件即生效**(不必安装)。一个插件长这样:
72
+
73
+ ```python
74
+ NAME = "my-provider"
75
+ PROVIDES = ["llm_provider"] # 可选槽位:llm_provider / storage / prompt
76
+
77
+ def create_llm_provider(api): # 每个槽位一个工厂
78
+ return MyProvider(api)
79
+ ```
80
+
81
+ 三条边界(不是约定,是机制):**插件只产出值**(`PluginAPI` 不给任何引擎句柄)·
82
+ **策略在宿主、机制在插件**(storage 的可写路径只有 `.puppet/` 与 `.puppethub/`)·
83
+ **失败必须可见**(加载失败、槽位写错名、插件重名、路径越界,一律报出来,且坏插件不阻止启动)。
84
+
85
+ ## 当前进度
86
+
87
+ 已实现:
88
+
89
+ - `new` / `run` / `remote` / `repl` / `verify-ci` 子命令;语言版本**与数据文件**不齐**拒绝启动**
90
+ - app 目录契约:`app.puppet` · `capabilities.py` · `DESIGN.md` · `assets/` ·
91
+ `puppethub.toml` · `.puppethub/` · `.puppet/{state,memory,snapshots}`
92
+ - service 层:装载 → 命令批 → 批末整份写回真源 → **写前自动快照**
93
+ - 渲染层:程序 IR + 观察面 → flet 控件树(控件 / 属性 / 动效 / 图标四层映射)
94
+ - **共作者 LLM**:对话通道(后台线程 + 流式上屏)· 指令块协议(命令批 / 整体替换 /
95
+ 受限文件写入 / 反问)· 诊断回灌 · 卡住检测 · 危险动作两层确认 · 执行 / 讨论两档
96
+ - 插件体系:三槽位 + 目录扫描发现 + 失败隔离;内置 provider / storage / prompt
97
+ - 驾驶舱:对话 / 观察流与诊断 / 程序只读面板 + 命名快照 · 回滚 · 重载 · 重置 ·
98
+ 清记忆 · 自证 · 查看本轮 prompt;**关窗前拦脏状态**
99
+ - **自证**:`puppethub.protocol` 把产品渲染器包成 conformance 可驱动的子进程,
100
+ `自证`按钮跑它 → **118/118 通过(跳过 0)**
101
+ - **无 LLM 实例**:`run <app> --no-llm` 进入控制面(stdio 协议),驱动者就是写者——
102
+ 走的还是"引擎校验 → 批末写回真源 → 写前自动快照"那条路
103
+ - **运行期记忆**:`.puppet/memory/`(可读可改的 JSONL)· 每次写入留诊断 · 上限 + 语义化裁剪 ·
104
+ 自动裁剪与人主动清空**可区分** · **重置保留**,清空要显式(`--wipe-memory` / 驾驶舱按钮)
105
+ - **快照 / 引擎状态走 storage 槽位**:派生数据落盘走同一条通道(白名单 / 原子写 / 写失败标脏);
106
+ 程序资产(`app.puppet` / `capabilities.py`)走命令批与受限写入——两条通道各司其职
107
+ - **人工接管**:卡住 / 停手时驾驶舱亮接管栏(运行期开关,恢复留痕 `LLM_RESUME`)
108
+ - **确认卡细化**:待确认动作展示**将做什么 / 可逆性 / 撤销路径**,确认是判断不是点头
109
+ - **写者状态机 + 运行期自主 LLM**(`docs/design-v2-autonomous.md`):llm / autonomous / none
110
+ 互斥切换,切换写决策流水;自主当值时共作者退化为只读提问;**自主的边界更硬**——
111
+ 危险能力默认拒绝(白名单只能人预先给 `[autonomous] allow_calls`)、批行数与频次预算、
112
+ 连续失败熔断切回无人(可选自动回滚);每步在 `.puppethub/autonomous.jsonl` 留审计;
113
+ 驾驶舱自主面板显示写者 / 预算 / 最近决策(含被拒的)
114
+ - **热重载**:`capabilities.py` 盘上变化自动重载(可见 `CAPABILITY_RELOAD`);
115
+ 插件热重载带护栏(流式中 / 待确认时拒绝)
116
+ - **沙箱**:`[sandbox] enabled = true` 把 storage 插件跑进子进程(内置插件诚实拒绝沙箱化并说明理由)
117
+ - **远程 / 多客户端**:`remote` 子命令 = TCP 上的新绑定,同一套协议操作,单写者不破例
118
+ - **多 app 编排**:`hub` 子命令(V3 提前落地的最小形态)——发现父目录下的 app、
119
+ 以 remote 子进程拉起(**等握手才算数**,幂等)、按账本停止、TCP hello 健康检查;
120
+ **不制造第二个写者**。融合的语义设计见 `docs/design-v3-fusion.md`(草案)
121
+ - **融合端到端**(`fuse` 子命令):机制做体检(依赖对照 / id 与能力审计 / 多窗口拒绝),
122
+ LLM 出方案、人 `--yes` 确认;改名在 **IR 层**做(文本替换救不了 `#cafe` 这种
123
+ 颜色/地址歧义),窗口子树嫁接进 A 的窗口,合并先**干跑校验**再落盘;
124
+ B 归档改名不删除,决策流水留痕
125
+ - **正式手写程序模式**(`edit` 子命令):编辑器整份替换,人作驱动者——绕过对话,
126
+ 不绕过纪律(确认前干跑校验;拒稿留底 `app.puppet.rejected`、真源恢复原样;
127
+ 兜底快照 + 决策流水)
128
+ - **CI**:`.github/workflows/ci.yml`(conformance 自证 + **机制冒烟** + 编译检查。
129
+ 设计文档不进版本库是既定决议;机制冒烟 / 探针经 `.gitignore` 白名单进库,
130
+ flet 无头运行用 xvfb——CI 的信号从此不只 conformance,机制回归也有防线)
131
+ - **移动端前置**:触摸语义提案 `spec/proposals/touch-semantics.md`(语言仓,
132
+ T1-T4 条款,目标 2.2)
133
+ - **产物形态**:`packaging/` 下有 PyInstaller spec 与 Dockerfile(容器跑无头绑定,
134
+ 桌面窗口需要显示服务器——不声明做不到的)。**PyInstaller 已实测**:构建成功、
135
+ 产物 `verify-ci` 118/118 全绿(含三颗雷的修复:可编辑安装的 pathex、flet 数据文件、
136
+ 冻结态自证链的 python 替身垫片——详见 spec 头注释)
137
+ - **GUI 覆盖 CLI("所有仅 CLI 功能都有图形入口")**:驾驶舱「操作 » 凭据」是
138
+ **模型设置**(base_url / 模型 / 凭据名 / 凭据值 + 探活;端点可落"仅本 app"或
139
+ "本机 profile",**凭据可落钥匙串或环境变量**——落点写在选择旁边,含代价说明与
140
+ "清掉环境变量那把"的撤销路径);「工具」抽屉把 CLI 每条命令搬成浮层——
141
+ `new` 新建 app · `edit` **人的写入**(整份替换:干跑 → 兜底快照 → 拒稿留底)·
142
+ `repl` 命令批(origin=driver)· `build` 打包(生成工程 / 连跑 flet build)·
143
+ `hub` 编排(list/up/down/status/bus)· `remote` 服务化(真起无头进程)·
144
+ `fuse` 融合(先体检干跑再执行)。**每个动作都是可被冒烟直接调用的方法**
145
+ (`gui_tools.py`),浮层只是薄壳;语义一律在 service 层——CLI 与 GUI 同源,
146
+ 靠 `smoke-gui.py` 第 8 节机制化断言
147
+ - **凭据体系(V5)**:`docs/design-credentials.md`——**三层解析**(进程环境变量 →
148
+ 本机钥匙串 `~/.puppethub/secrets.toml` 0600 → 报错说清试过哪两层)· **机器级 profile**
149
+ (`~/.puppethub/providers.toml` 存端点/模型/凭据名,app 里只写 `[llm] profile = "名字"`,
150
+ 因此 **app 可以安全分享**)· **探活**把 401/403/404/429/超时/连不上分开说清 ·
151
+ **泄漏自检**真去 app 内文本文件里找明文(命中只报位置)· CLI `puppethub keys list|set|check`
152
+ 与驾驶舱「操作 » 凭据」共用同一实现。铁律:只有 `secrets.resolve()` 取明文,
153
+ 一切输出只给**名字/来源/长度**(连掩码都不给)
154
+ - **Agent 社会(V4)**:`docs/design-v4-society.md`——app 即服务(服务清单挂在 hello、
155
+ `call` 操作借出能力、**借出白名单缺省空 = 默认拒绝**)· 协作总线(`hub up` 自动拉起,
156
+ 消息 = 刺激不是写入,投递进对方观察流并触发其自主回路,审计落账 `hub bus`)·
157
+ 深度自主(`goal` 块定方向 + 定期反思沉淀记忆 + 同胞消息触发;目标跨会话可见)。
158
+ 铁律在协作里依然成立:**协作 = 说话与调用对方借出的能力,永远不写对方的程序**
159
+ - **移动端**:`build --target android|web` **已实现并实测**——生成独立 flet 工程
160
+ (纯 app 实例、写者=无、`pointer=touch` 自述、真源快照内嵌、REQUIRES 进 requirements、
161
+ **构建期解析**(缺包生成期就拒)+ **凭据 manifest**(capabilities.py 静态扫描 →
162
+ `manifest.json`,移动容器按它注入环境变量)、干跑门),生成的工程可独立装载与交互
163
+ (headless 子进程实测);最终 `flet build apk` 需 Android SDK(`--run-flet-build`
164
+ 代跑,失败如实上报)。触摸语义规范见语言仓 05 §10
165
+
166
+ 尚未实现(均**可见地**说明,不做假成功):
167
+
168
+ - `flet build apk` 的实际执行(需 Android SDK / 真机——生成工程与前置全部就绪)·
169
+ 融合的 `drops`(V3.1,B 归档保证不丢)· 多写者语义(V4 方向)
170
+
171
+ ## 自证脚本(都不联网,可重复跑)
172
+
173
+ ```bash
174
+ python docs/probe-flet-fields.py # 渲染层依赖的 flet 字段面
175
+ python docs/smoke-render.py # 无 GUI:装载 → 渲染 → 命令批 → 写回 → 交互
176
+ python docs/smoke-window.py # 真实窗口(隐藏):界面粘合 + 后台线程跑 LLM
177
+ python docs/smoke-llm.py # 对话回路机制(用脚本化 provider)
178
+ python docs/smoke-protocol.py --full # 协议外壳桥接 + 自证全量(分钟级)
179
+ python docs/smoke-controlplane.py # run --no-llm:驱动者即写者
180
+ python docs/smoke-memory.py # 运行期记忆:写入留痕 / 可读可改 / 语义化裁剪
181
+ python docs/smoke-v2.py # V2:写者状态机 / 自主回路 / 热重载 / 沙箱 / 远程
182
+ python docs/smoke-hub.py # 多 app 编排:发现 / 等握手拉起 / 幂等 / 停止
183
+ python docs/smoke-fusion.py # 融合:审计停下 / IR 改名 / 干跑 / 归档 / CLI 全链
184
+ python docs/smoke-edit.py # 手写程序模式:干跑守卫 / 拒稿留底 / 真源恢复
185
+ python docs/smoke-build.py # 设备打包:manifest 凭据 / REQUIRES 构建期解析 / 独立装载
186
+ python docs/smoke-society.py # V4:服务化 / 协作总线 / 深度自主,铁律不破
187
+ ```
188
+
@@ -0,0 +1,19 @@
1
+ """PuppetHub:搭 app 的软件(搭建 / 运行 / 运行时定制 / 未来的融合)。
2
+
3
+ 它不是 app 运行时框架,也不是 UI 库:人用自然语言描述想要什么,内置 LLM 把它
4
+ 翻译成**命令批**,引擎校验后写回真源并渲染。造出的 app **不含聊天框**——聊天只在
5
+ PuppetHub 自己的窗口里。
6
+
7
+ 三层分工:`puppet`(语言与语义引擎,零第三方依赖)· **`puppethub`(本包)** ·
8
+ `puppetOS`(发行版,仅设计文档)。
9
+
10
+ 本模块**刻意保持轻量**:不导入 flet。`puppethub new` 不该为了建目录而加载渲染栈,
11
+ `import puppethub` 也用不上面向窗口的那部分。
12
+ """
13
+
14
+ from .compat import (SPEC_RANGE, DataFilesMissing, SpecMismatch,
15
+ check_data_files, check_spec_version)
16
+
17
+ __version__ = "0.1.0"
18
+ __all__ = ["SPEC_RANGE", "SpecMismatch", "DataFilesMissing",
19
+ "check_spec_version", "check_data_files", "__version__"]
@@ -0,0 +1,6 @@
1
+ """`python -m puppethub` 入口(等价于安装后的 `puppethub` 脚本)。"""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ raise SystemExit(main())