@clawos-dev/clawd 0.2.259 → 0.2.261
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs
CHANGED
|
@@ -33,322 +33,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
33
|
mod
|
|
34
34
|
));
|
|
35
35
|
|
|
36
|
-
// ../protocol/src/methods.ts
|
|
37
|
-
var METHOD_NAMES;
|
|
38
|
-
var init_methods = __esm({
|
|
39
|
-
"../protocol/src/methods.ts"() {
|
|
40
|
-
"use strict";
|
|
41
|
-
METHOD_NAMES = [
|
|
42
|
-
"session:create",
|
|
43
|
-
"session:list",
|
|
44
|
-
"session:get",
|
|
45
|
-
"session:update",
|
|
46
|
-
"session:delete",
|
|
47
|
-
"session:send",
|
|
48
|
-
// per-turn sender 2026-07-08 spec §4.6:MCP servers (ticket / inbox ...) 走 HTTP RPC
|
|
49
|
-
// /rpc/session:currentTurnSender(Bearer)拉当前 turn caller;WS handler 同名
|
|
50
|
-
"session:currentTurnSender",
|
|
51
|
-
"session:stop",
|
|
52
|
-
// 温柔中断当前轮次,不杀进程(走 CC IPC control_request.subtype=interrupt)
|
|
53
|
-
"session:interrupt",
|
|
54
|
-
// 回滚到指定 user message,并撤销其后 CC 的文件编辑(走 CC IPC control_request.subtype=rewind_files)
|
|
55
|
-
"session:rewind",
|
|
56
|
-
// Rewind 预览:daemon 读 ~/.claude/file-history 快照 + 磁盘现状算真实 diff,不依赖 CC 进程
|
|
57
|
-
"session:rewind-diff",
|
|
58
|
-
// 打开 session 时一次性拿到"有真实 diff"的 user message id 集合,UI heuristic 据此过滤按钮显示
|
|
59
|
-
"session:rewindable-message-ids",
|
|
60
|
-
// 从指定 message uuid 处 fork 出新 transcript(截断 + 重写 sessionId/parentUuid + forkedFrom)
|
|
61
|
-
// daemon 只生成新 jsonl 文件并返回新 toolSessionId;UI 自行决定是否走 session:create 拉起 resume
|
|
62
|
-
"session:fork",
|
|
63
|
-
"session:new",
|
|
64
|
-
"session:resume",
|
|
65
|
-
"session:observe",
|
|
66
|
-
"session:events",
|
|
67
|
-
"session:subscribe",
|
|
68
|
-
"session:unsubscribe",
|
|
69
|
-
"session:pin",
|
|
70
|
-
// 清共享未读标记(SessionFile.unreadAt → null)+ 广播 session:info;幂等
|
|
71
|
-
"session:markRead",
|
|
72
|
-
"session:reorderPins",
|
|
73
|
-
// mirror peer sessions (2026-05-26): owner-only RPC,写/删本机 mirror SessionFile —
|
|
74
|
-
// mirror 是「**我**在朋友 daemon 上自己创建的 session」的本机持久化副本(不是朋友的会话),
|
|
75
|
-
// 方便 sidebar 跨设备聚合。daemon dumb 写删,**不广播任何 push 帧** (不发 session:info /
|
|
76
|
-
// session:deleted);UI 是写入唯一源,双写完成后通过 cache.setData('sessions', ...) 同步
|
|
77
|
-
// 本地 sidebar state。native session:* handler 完全不感知 mirror (UI 操作 mirror 不复用
|
|
78
|
-
// native 路径)。
|
|
79
|
-
"peerSession:upsert",
|
|
80
|
-
"peerSession:remove",
|
|
81
|
-
"permission:respond",
|
|
82
|
-
// AskUserQuestion 表单回写:UI 答完所有 question 后调用,daemon 把答案合并进 updated_input
|
|
83
|
-
// 写一条 control_response 到 CC stdin(详见 events.ts session:question JSDoc)
|
|
84
|
-
"session:answerQuestion",
|
|
85
|
-
// AskUserQuestion 用户跳过:daemon 向 CC 回 allow + answers={} 让 tool 走空答案路径,
|
|
86
|
-
// 同时广播 cleared 帧(无 answers)让所有客户端 UI 卡片转 Ended
|
|
87
|
-
"session:cancelQuestion",
|
|
88
|
-
"history:projects",
|
|
89
|
-
"history:list",
|
|
90
|
-
"history:read",
|
|
91
|
-
"history:subagents",
|
|
92
|
-
"history:subagent-read",
|
|
93
|
-
"history:recentDirs",
|
|
94
|
-
"workspace:list",
|
|
95
|
-
"workspace:read",
|
|
96
|
-
"shift:list",
|
|
97
|
-
// ---- shift-internal:* (cc 内 shift MCP server 管理 owner 排班,spec 2026-06-24-clawd-shift) ----
|
|
98
|
-
// 统一 RPC 鉴权(spec 2026-07-28)后经 /rpc + Bearer owner token 调;personaId 归因
|
|
99
|
-
// 从 body 来(env CLAWD_PERSONA_ID),handler 内 createdByPersona 自检防跨 persona 误操作。
|
|
100
|
-
"shift-internal:add",
|
|
101
|
-
"shift-internal:list",
|
|
102
|
-
"shift-internal:cancel",
|
|
103
|
-
"shift-internal:update",
|
|
104
|
-
"shift-internal:history",
|
|
105
|
-
"skills:list",
|
|
106
|
-
"agents:list",
|
|
107
|
-
"git:root",
|
|
108
|
-
"git:branch",
|
|
109
|
-
"git:branches",
|
|
110
|
-
"capabilities:get",
|
|
111
|
-
// ---- persona:* (persona 管理) ----
|
|
112
|
-
// persona:list 响应 shape 不分流(统一返 PersonaFile[]),但 daemon handler 按
|
|
113
|
-
// ConnectionContext 投影不同子集:
|
|
114
|
-
// owner ctx → 返全量 personas(含 private)
|
|
115
|
-
// guest ctx → persona.public === true ∧ assertGrant(ctx.grants, {persona,p.id}, 'read')
|
|
116
|
-
// method-grants.ts: persona:list 是 CAPABILITY_SCOPED;其它 persona:* 仍 ADMIN_ANY。
|
|
117
|
-
"persona:create",
|
|
118
|
-
"persona:list",
|
|
119
|
-
"persona:get",
|
|
120
|
-
"persona:update",
|
|
121
|
-
"persona:delete",
|
|
122
|
-
// ---- personaDispatch:* (dispatch 全家,spec 2026-07-28-unify-rpc-auth 统一登记) ----
|
|
123
|
-
// run:本地 MCP server 经 /rpc(Bearer owner token);跨设备 A 的 peer daemon 经 /rpc
|
|
124
|
-
//(Bearer connect token)。capability-scoped(handler 自检 persona.public + assertGrant(send))。
|
|
125
|
-
// complete / list:B / A 本机 MCP server 调(owner token → ADMIN_ANY)。
|
|
126
|
-
// get:跨设备轮询——A 端 daemon 凭 connect token 查 B 台账终态;handler 校验行归属。
|
|
127
|
-
"personaDispatch:run",
|
|
128
|
-
"personaDispatch:complete",
|
|
129
|
-
"personaDispatch:list",
|
|
130
|
-
"personaDispatch:get",
|
|
131
|
-
// ---- peerExec:run (跨设备 exec,spec 2026-07-16-cross-device-exec-mcp) ----
|
|
132
|
-
// A 侧本机 MCP server 经 /rpc(Bearer owner token)带 peerDeviceId → daemon forward;
|
|
133
|
-
// B 侧对端经 /rpc(Bearer connect token)无 peerDeviceId → 本地 spawn。METHOD_GRANT_MAP
|
|
134
|
-
// 设 public,handler 内判 remoteAccessAllowed(跟 inbox:postMessage 同款)。
|
|
135
|
-
"peerExec:run",
|
|
136
|
-
// ---- session:pty 双向透传(仅 CLAWD_CC_MODE=tui 才生效,对应 session:pty push 帧的上行) ----
|
|
137
|
-
// session:pty:input — UI 把用户键盘字节(base64 UTF-8)发给 daemon,daemon 直写 pty stdin。
|
|
138
|
-
// 高频帧(每次按键 1 帧),不入 reducer / 不广播。response 是 fire-and-forget 风格 ack。
|
|
139
|
-
// session:pty:resize — UI 端 xterm 尺寸(cols/rows)变化时同步给 daemon 调 pty resize;
|
|
140
|
-
// 触发频率低(仅 window resize),response 也是 ack。
|
|
141
|
-
"session:pty:input",
|
|
142
|
-
"session:pty:resize",
|
|
143
|
-
// session:pty:snapshot — UI XtermPanel 重新挂载(切 session 回来 / 刷新)时主动拉一次当前
|
|
144
|
-
// 屏幕全量快照,再开始消费 incremental session:pty。daemon 调 manager.getPtyReplay(sessionId)
|
|
145
|
-
// 先 drain detector parse queue 再 serialize,保证 atSeq 与 buffer 内容严格对齐。
|
|
146
|
-
// response 字段:
|
|
147
|
-
// - data:当前屏幕 + scrollback 的 ANSI 字节串(base64-utf8),与 session:pty push 帧同格式
|
|
148
|
-
// - atSeq:此 snapshot 覆盖到的最后一帧 session:pty 的 seq(即 detector 已 parse 完成的最大 seq)
|
|
149
|
-
// UI 端 flush 时丢弃 pending 中 seq ≤ atSeq 的帧
|
|
150
|
-
// - popupKind:当前 detector 检测到的 popup 类型(null = 无 popup)
|
|
151
|
-
// session 不存在 / 非 tui / pty 已 exit 时 data=null, atSeq=0。
|
|
152
|
-
"session:pty:snapshot",
|
|
153
|
-
// ---- attachment.* file-sharing(详见 attachment-schemas.ts) ----
|
|
154
|
-
// 命名警告:这里的 `attachment.*` RPC 与 CC v2.x 上行 `type:"attachment"` 系统行
|
|
155
|
-
// (attachment-skills / attachment-deferred-tools / attachment_memories)是不同概念。
|
|
156
|
-
// 全部管理类 RPC dispatcher grant 限 owner(capability admin-only);
|
|
157
|
-
// 实际文件传输走 HTTP 路由(GET /files?p=&e=&s=,HMAC 签名自包含,不在白名单内)。
|
|
158
|
-
"attachment.signUrl",
|
|
159
|
-
"attachment.groupAdd",
|
|
160
|
-
"attachment.groupRemove",
|
|
161
|
-
"attachment.groupList",
|
|
162
|
-
// ---- inbox:* (capability platform Phase 3 跨用户通知 + Phase 4 DM) ----
|
|
163
|
-
// owner 接 guest 的 cross-principal 消息事件 + DM 双向私聊.
|
|
164
|
-
// inbox:list / markRead: admin-only (Phase 3); inbox:postMessage: DM 自带能力,
|
|
165
|
-
// 任何 principal (owner/guest) 可调 (Phase 4).
|
|
166
|
-
"inbox:list",
|
|
167
|
-
"inbox:markRead",
|
|
168
|
-
"inbox:postMessage",
|
|
169
|
-
// inbox:sendDm——persona 代发 DM 编排(inbox MCP server 经 /rpc + Bearer owner token 调)。
|
|
170
|
-
// sender/mode 由 handler 按 body.sessionId 反查 session scope 归因(业务逻辑非鉴权)。
|
|
171
|
-
"inbox:sendDm",
|
|
172
|
-
// ---- contact:* (联系人列表) ----
|
|
173
|
-
// 飞书统一身份 Phase 3 (决策 #14): received-capability:* 正名为 contact:*——Phase 2 后
|
|
174
|
-
// 联系人身份由中心 server introspect 背书,不再是"对方颁发的 capability"。
|
|
175
|
-
// 写入路径:device:connect 落 store + 自动反向(决策 #11);list / remove 作联系人列表读删。
|
|
176
|
-
"contact:list",
|
|
177
|
-
"contact:pin",
|
|
178
|
-
"contact:remove",
|
|
179
|
-
// ---- contact:setRemoteAccess (远程访问授权,spec 2026-07-16) ----
|
|
180
|
-
// owner UI 授权 contact 反向操作我的设备(跨设备 exec 开关 remoteAccessAllowed)。
|
|
181
|
-
// 详见 protocol/src/contact-remote-access.ts.
|
|
182
|
-
"contact:setRemoteAccess",
|
|
183
|
-
// ---- contact:handshake (双向确认建联握手, spec 2026-07-22) ----
|
|
184
|
-
// device:connect 临时连接调用;被调方同步落库+broadcast 后回 ok(携带身份载荷)。
|
|
185
|
-
// 替代旧 whoami+auto-reverse 组合;whoami 对 connect-token guest 已封(旧客户端拦截)。
|
|
186
|
-
"contact:handshake",
|
|
187
|
-
// ---- visitor:* (web 访客 · persona web 分享,spec 2026-06-24-persona-web-share-design) ----
|
|
188
|
-
// owner-only:列出登录访问过本机 public persona 的 web 访客(零安装、飞书登录、daemon 自签
|
|
189
|
-
// visitor token)。存储 ~/.clawd/visitors.json(VisitorStore),登录(exchange)即 upsert;
|
|
190
|
-
// 访客身份用 TTC unique_id,会话按 creatorPrincipalId='visitor-<id>' 进现有会话用户分组。
|
|
191
|
-
// 访客换 token 走 HTTP-only 公开路由 POST /share/exchange(非 WS method)。
|
|
192
|
-
"visitor:list",
|
|
193
|
-
// ---- whoami (v2 capability platform) ----
|
|
194
|
-
// 任何 authed connection 都能调;返回 owner 显示名 + 当前 capability wire 形态 +
|
|
195
|
-
// grants 对应的 persona 元数据 (id + displayName)。UI 端 AddRemotePersonaDialog
|
|
196
|
-
// 的 preview 一次性临时 client 用它判定身份和可用 persona。
|
|
197
|
-
"whoami",
|
|
198
|
-
"info",
|
|
199
|
-
"ping",
|
|
200
|
-
// ---- extension runtime (v1: local mode only, no host-bridge —
|
|
201
|
-
// see clawd/superpowers/specs/2026-05-27-clawd-extensions-v1-design.md) ----
|
|
202
|
-
"extension.list",
|
|
203
|
-
"extension.open",
|
|
204
|
-
"extension.close",
|
|
205
|
-
"extension.uninstall",
|
|
206
|
-
// ---- extension sharing v1 (spec 2026-05-28-clawd-extension-sharing-design) ----
|
|
207
|
-
// owner-side: 公开 / 撤回 / 查 publish 状态(owner-only ADMIN_ANY)
|
|
208
|
-
"extension.publish",
|
|
209
|
-
"extension.unpublish",
|
|
210
|
-
"extension.publish:status",
|
|
211
|
-
// cross-tunnel: guest 从 owner 拉 published list + bundle(CAPABILITY_SCOPED)
|
|
212
|
-
"extension.list-published",
|
|
213
|
-
"extension.fetchBundle",
|
|
214
|
-
// guest-self: guest 在自己 daemon 上做安装与更新(ADMIN_ANY,guest 是 owner of self daemon).
|
|
215
|
-
// 无 subscription 持久化:guest 端身份完全来自文件系统 + reconciled publishedExtensions.
|
|
216
|
-
"extension.install-from-channel",
|
|
217
|
-
"extension.update-from-channel",
|
|
218
|
-
// ---- auth:* 飞书统一身份 Phase 1 (spec 2026-06-01-feishu-identity-design) ----
|
|
219
|
-
// owner-only:daemon loopback 登录流程(auth:login:start 起 state → HTTP /auth/callback
|
|
220
|
-
// 回调落盘 → auth:login:done 事件)。中央字面量见 protocol/feishu-auth.ts FEISHU_AUTH_METHODS。
|
|
221
|
-
"auth:login:start",
|
|
222
|
-
"auth:getIdentity",
|
|
223
|
-
"auth:logout",
|
|
224
|
-
// ---- device:* 设备目录 + 连接(决策 #15:deviceId + 自包含 token) ----
|
|
225
|
-
// owner-only:公共设备目录 + audience 绑定设备的签名 token 连接(daemon 代理中心 server)。
|
|
226
|
-
// 中央字面量见 protocol/feishu-auth.ts DEVICE_METHODS。
|
|
227
|
-
"device:list",
|
|
228
|
-
"device:connect",
|
|
229
|
-
// ---- app-builder Project (spec 2026-06-01 picker → 2026-06-02 单栏默认 refactor) ----
|
|
230
|
-
// persona-app-builder Project 管理;schemas: ProjectMetadataSchema + 5 个 args/result 对。
|
|
231
|
-
// listProjects: readdir projects/,按目录读 .clawd-project.json
|
|
232
|
-
// createProject: 校验 personaId/未绑 + 校验名 + 从 6173-6182 段分配端口 + 写元数据 + 创建空目录
|
|
233
|
-
// + daemon 内部 mutate session.appBuilderProject + 起 dev server(单栏 refactor 后唯一绑定入口)
|
|
234
|
-
// deleteProject: 停 dev server + rm -rf 目录(绑定 session 由 session:delete 联动 / 不在这里删)
|
|
235
|
-
// updateProjectPort: 校验新端口段内 + 未被别的 project 占 + 重启 dev server
|
|
236
|
-
// setProdUrl: 发布上线后 assistant 调一次写入 .clawd-project.json.prodUrl(取代 prod marker)
|
|
237
|
-
"appBuilder:listProjects",
|
|
238
|
-
// getProject:按 sessionId 取单个绑定 project(含 status)。people/mirror 跨 daemon 场景:
|
|
239
|
-
// 本机 owner 在远端是 guest,listProjects 被 per-user 隔离拿不到别人的 project;getProject
|
|
240
|
-
// 按 session 可见性授权(ensureSessionAccess read)放行。本地也复用(省掉拉全量再 find)。
|
|
241
|
-
"appBuilder:getProject",
|
|
242
|
-
"appBuilder:createProject",
|
|
243
|
-
"appBuilder:deleteProject",
|
|
244
|
-
"appBuilder:updateProjectPort",
|
|
245
|
-
"appBuilder:setProdUrl",
|
|
246
|
-
// 单栏 refactor stage fix (spec 2026-06-02-app-builder-single-pane-default-design §5.6.2):
|
|
247
|
-
// createProject 时不再立即起 dev server(fresh 目录必崩)。assistant scaffold + pnpm install
|
|
248
|
-
// 完成后调 startDevServer 显式触发 supervisor spawn;中间用 reportStage 上报进度(scaffolding
|
|
249
|
-
// / installing 等),daemon broadcast appBuilder:project-updated 帧让 UI PreviewPane 切阶段。
|
|
250
|
-
"appBuilder:startDevServer",
|
|
251
|
-
"appBuilder:reportStage",
|
|
252
|
-
// 显式控制 fix (spec 2026-06-02-app-builder-explicit-dev-server-control):用户点"收起预览"按钮触发,
|
|
253
|
-
// 对称 startDevServer。砍掉了 setActiveSession(dev server 不再跟用户 focus 走),切 session 不动 dev server。
|
|
254
|
-
"appBuilder:stopDevServer",
|
|
255
|
-
// 发布上线脚手架化 (spec 2026-06-03-app-builder-publish-scaffold-design):
|
|
256
|
-
// publish:PreviewPane「发布上线」按钮 onClick 调本 RPC,daemon 内串行化 + spawn publish.sh +
|
|
257
|
-
// 广播阶段进度帧 (appBuilder:publish-progress / publish-failed)。同 project 已有 in-flight job
|
|
258
|
-
// 返回 already-publishing + 既有 jobId(UI 不报错继续订阅)。失败时 daemon 调 manager.send()
|
|
259
|
-
// 注入 user_text 到 chat,由 assistant 接管完成部署。
|
|
260
|
-
// dismissPublishJob:取消 in-flight publish(SIGTERM 子进程 + 清字段)或清掉 daemon 崩溃留下的
|
|
261
|
-
// 中断残骸 publishJob 字段。UI 端 [取消] / [interrupted 取消] 都走这个 RPC。
|
|
262
|
-
"appBuilder:publish",
|
|
263
|
-
"appBuilder:dismissPublishJob"
|
|
264
|
-
];
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// ../protocol/src/events.ts
|
|
269
|
-
var DAEMON_MODE_VALUES, SESSION_STATUS_VALUES, HISTORY_USER_META_VALUES, SKILL_SOURCE_VALUES, AGENT_SOURCE_VALUES, ASK_USER_QUESTION_TOOL_NAME;
|
|
270
|
-
var init_events = __esm({
|
|
271
|
-
"../protocol/src/events.ts"() {
|
|
272
|
-
"use strict";
|
|
273
|
-
DAEMON_MODE_VALUES = ["sdk", "tui"];
|
|
274
|
-
SESSION_STATUS_VALUES = [
|
|
275
|
-
"idle",
|
|
276
|
-
"running",
|
|
277
|
-
"running-idle",
|
|
278
|
-
"stopped",
|
|
279
|
-
"error",
|
|
280
|
-
"observing"
|
|
281
|
-
];
|
|
282
|
-
HISTORY_USER_META_VALUES = [
|
|
283
|
-
"task-notification",
|
|
284
|
-
"slash-command",
|
|
285
|
-
"local-command",
|
|
286
|
-
"system-reminder",
|
|
287
|
-
"skill-hint",
|
|
288
|
-
"meta-text",
|
|
289
|
-
"attachment-skills",
|
|
290
|
-
"attachment-deferred-tools"
|
|
291
|
-
];
|
|
292
|
-
SKILL_SOURCE_VALUES = ["builtin", "global", "project", "plugin"];
|
|
293
|
-
AGENT_SOURCE_VALUES = [
|
|
294
|
-
"builtin",
|
|
295
|
-
"global",
|
|
296
|
-
"project",
|
|
297
|
-
"policy",
|
|
298
|
-
"plugin"
|
|
299
|
-
];
|
|
300
|
-
ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
// ../protocol/src/errors.ts
|
|
305
|
-
var ERROR_CODES, ClawdError;
|
|
306
|
-
var init_errors = __esm({
|
|
307
|
-
"../protocol/src/errors.ts"() {
|
|
308
|
-
"use strict";
|
|
309
|
-
ERROR_CODES = {
|
|
310
|
-
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
311
|
-
SESSION_BUSY: "SESSION_BUSY",
|
|
312
|
-
INVALID_CWD: "INVALID_CWD",
|
|
313
|
-
INVALID_PATH: "INVALID_PATH",
|
|
314
|
-
TOOL_NOT_SUPPORTED: "TOOL_NOT_SUPPORTED",
|
|
315
|
-
CLAUDE_NOT_FOUND: "CLAUDE_NOT_FOUND",
|
|
316
|
-
SPAWN_FAILED: "SPAWN_FAILED",
|
|
317
|
-
INVALID_PERMISSION_MODE: "INVALID_PERMISSION_MODE",
|
|
318
|
-
METHOD_NOT_IMPLEMENTED: "METHOD_NOT_IMPLEMENTED",
|
|
319
|
-
METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED",
|
|
320
|
-
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
321
|
-
PERMISSION_REQUEST_STALE: "PERMISSION_REQUEST_STALE",
|
|
322
|
-
FILE_TOO_LARGE: "FILE_TOO_LARGE",
|
|
323
|
-
INTERNAL: "INTERNAL",
|
|
324
|
-
UNAUTHORIZED: "UNAUTHORIZED",
|
|
325
|
-
FORBIDDEN: "FORBIDDEN",
|
|
326
|
-
INVALID_PARAM: "INVALID_PARAM",
|
|
327
|
-
// 飞书统一身份(spec 2026-06-01 决策 #9):People/远程体系强制飞书登录。
|
|
328
|
-
// daemon 进程身份未激活为飞书 unionId 时,FEISHU_GATED_METHODS 内的 RPC 一律返回此错误;
|
|
329
|
-
// UI 据此显示登录引导(区别于 UNAUTHORIZED 的越权语义)。
|
|
330
|
-
FEISHU_LOGIN_REQUIRED: "FEISHU_LOGIN_REQUIRED",
|
|
331
|
-
// app-builder 单栏默认 refactor (spec 2026-06-02-app-builder-single-pane-default-design):
|
|
332
|
-
// appBuilder:createProject 加 personaId + session 未绑校验后抛的两个错码。
|
|
333
|
-
WRONG_PERSONA: "WRONG_PERSONA",
|
|
334
|
-
SESSION_ALREADY_BOUND: "SESSION_ALREADY_BOUND",
|
|
335
|
-
// 2026-07-02 unified people sidebar: contact:pin 时 deviceId 不在 store(可能被别处删了)
|
|
336
|
-
CONTACT_NOT_FOUND: "CONTACT_NOT_FOUND",
|
|
337
|
-
// 统一 RPC 鉴权(spec 2026-07-28):personaDispatch:get 查不到台账行,或 guest ctx
|
|
338
|
-
// 查非自己发起的行(越权与未知 id 同码,不泄露存在性)。A 端轮询遇此码立即判失败。
|
|
339
|
-
DISPATCH_NOT_FOUND: "DISPATCH_NOT_FOUND"
|
|
340
|
-
};
|
|
341
|
-
ClawdError = class extends Error {
|
|
342
|
-
constructor(code, message) {
|
|
343
|
-
super(message);
|
|
344
|
-
this.code = code;
|
|
345
|
-
this.name = "ClawdError";
|
|
346
|
-
}
|
|
347
|
-
code;
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
|
|
352
36
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
353
37
|
var util, objectUtil, ZodParsedType, getParsedType;
|
|
354
38
|
var init_util = __esm({
|
|
@@ -731,7 +415,7 @@ function getErrorMap() {
|
|
|
731
415
|
return overrideErrorMap;
|
|
732
416
|
}
|
|
733
417
|
var overrideErrorMap;
|
|
734
|
-
var
|
|
418
|
+
var init_errors = __esm({
|
|
735
419
|
"../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js"() {
|
|
736
420
|
"use strict";
|
|
737
421
|
init_en();
|
|
@@ -763,7 +447,7 @@ var makeIssue, EMPTY_PATH, ParseStatus, INVALID, DIRTY, OK, isAborted, isDirty,
|
|
|
763
447
|
var init_parseUtil = __esm({
|
|
764
448
|
"../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js"() {
|
|
765
449
|
"use strict";
|
|
766
|
-
|
|
450
|
+
init_errors();
|
|
767
451
|
init_en();
|
|
768
452
|
makeIssue = (params) => {
|
|
769
453
|
const { data, path: path75, errorMaps, issueData } = params;
|
|
@@ -1073,7 +757,7 @@ var init_types = __esm({
|
|
|
1073
757
|
"../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js"() {
|
|
1074
758
|
"use strict";
|
|
1075
759
|
init_ZodError();
|
|
1076
|
-
|
|
760
|
+
init_errors();
|
|
1077
761
|
init_errorUtil();
|
|
1078
762
|
init_parseUtil();
|
|
1079
763
|
init_util();
|
|
@@ -4447,7 +4131,7 @@ __export(external_exports, {
|
|
|
4447
4131
|
var init_external = __esm({
|
|
4448
4132
|
"../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js"() {
|
|
4449
4133
|
"use strict";
|
|
4450
|
-
|
|
4134
|
+
init_errors();
|
|
4451
4135
|
init_parseUtil();
|
|
4452
4136
|
init_typeAliases();
|
|
4453
4137
|
init_util();
|
|
@@ -4465,6 +4149,346 @@ var init_zod = __esm({
|
|
|
4465
4149
|
}
|
|
4466
4150
|
});
|
|
4467
4151
|
|
|
4152
|
+
// ../protocol/src/methods.ts
|
|
4153
|
+
var METHOD_NAMES, RPC_METHOD_STATUSES, RpcMethodStatusSchema, RpcMethodInfoSchema, MetaMethodsResultSchema;
|
|
4154
|
+
var init_methods = __esm({
|
|
4155
|
+
"../protocol/src/methods.ts"() {
|
|
4156
|
+
"use strict";
|
|
4157
|
+
init_zod();
|
|
4158
|
+
METHOD_NAMES = [
|
|
4159
|
+
"session:create",
|
|
4160
|
+
"session:list",
|
|
4161
|
+
"session:get",
|
|
4162
|
+
"session:update",
|
|
4163
|
+
"session:delete",
|
|
4164
|
+
"session:send",
|
|
4165
|
+
// per-turn sender 2026-07-08 spec §4.6:MCP servers (ticket / inbox ...) 走 HTTP RPC
|
|
4166
|
+
// /rpc/session:currentTurnSender(Bearer)拉当前 turn caller;WS handler 同名
|
|
4167
|
+
"session:currentTurnSender",
|
|
4168
|
+
"session:stop",
|
|
4169
|
+
// 温柔中断当前轮次,不杀进程(走 CC IPC control_request.subtype=interrupt)
|
|
4170
|
+
"session:interrupt",
|
|
4171
|
+
// 回滚到指定 user message,并撤销其后 CC 的文件编辑(走 CC IPC control_request.subtype=rewind_files)
|
|
4172
|
+
"session:rewind",
|
|
4173
|
+
// Rewind 预览:daemon 读 ~/.claude/file-history 快照 + 磁盘现状算真实 diff,不依赖 CC 进程
|
|
4174
|
+
"session:rewind-diff",
|
|
4175
|
+
// 打开 session 时一次性拿到"有真实 diff"的 user message id 集合,UI heuristic 据此过滤按钮显示
|
|
4176
|
+
"session:rewindable-message-ids",
|
|
4177
|
+
// 从指定 message uuid 处 fork 出新 transcript(截断 + 重写 sessionId/parentUuid + forkedFrom)
|
|
4178
|
+
// daemon 只生成新 jsonl 文件并返回新 toolSessionId;UI 自行决定是否走 session:create 拉起 resume
|
|
4179
|
+
"session:fork",
|
|
4180
|
+
"session:new",
|
|
4181
|
+
"session:resume",
|
|
4182
|
+
"session:observe",
|
|
4183
|
+
"session:events",
|
|
4184
|
+
"session:subscribe",
|
|
4185
|
+
"session:unsubscribe",
|
|
4186
|
+
"session:pin",
|
|
4187
|
+
// 清共享未读标记(SessionFile.unreadAt → null)+ 广播 session:info;幂等
|
|
4188
|
+
"session:markRead",
|
|
4189
|
+
"session:reorderPins",
|
|
4190
|
+
// mirror peer sessions (2026-05-26): owner-only RPC,写/删本机 mirror SessionFile —
|
|
4191
|
+
// mirror 是「**我**在朋友 daemon 上自己创建的 session」的本机持久化副本(不是朋友的会话),
|
|
4192
|
+
// 方便 sidebar 跨设备聚合。daemon dumb 写删,**不广播任何 push 帧** (不发 session:info /
|
|
4193
|
+
// session:deleted);UI 是写入唯一源,双写完成后通过 cache.setData('sessions', ...) 同步
|
|
4194
|
+
// 本地 sidebar state。native session:* handler 完全不感知 mirror (UI 操作 mirror 不复用
|
|
4195
|
+
// native 路径)。
|
|
4196
|
+
"peerSession:upsert",
|
|
4197
|
+
"peerSession:remove",
|
|
4198
|
+
"permission:respond",
|
|
4199
|
+
// AskUserQuestion 表单回写:UI 答完所有 question 后调用,daemon 把答案合并进 updated_input
|
|
4200
|
+
// 写一条 control_response 到 CC stdin(详见 events.ts session:question JSDoc)
|
|
4201
|
+
"session:answerQuestion",
|
|
4202
|
+
// AskUserQuestion 用户跳过:daemon 向 CC 回 allow + answers={} 让 tool 走空答案路径,
|
|
4203
|
+
// 同时广播 cleared 帧(无 answers)让所有客户端 UI 卡片转 Ended
|
|
4204
|
+
"session:cancelQuestion",
|
|
4205
|
+
"history:projects",
|
|
4206
|
+
"history:list",
|
|
4207
|
+
"history:read",
|
|
4208
|
+
"history:subagents",
|
|
4209
|
+
"history:subagent-read",
|
|
4210
|
+
"history:recentDirs",
|
|
4211
|
+
"workspace:list",
|
|
4212
|
+
"workspace:read",
|
|
4213
|
+
"shift:list",
|
|
4214
|
+
// ---- shift-internal:* (cc 内 shift MCP server 管理 owner 排班,spec 2026-06-24-clawd-shift) ----
|
|
4215
|
+
// 统一 RPC 鉴权(spec 2026-07-28)后经 /rpc + Bearer owner token 调;personaId 归因
|
|
4216
|
+
// 从 body 来(env CLAWD_PERSONA_ID),handler 内 createdByPersona 自检防跨 persona 误操作。
|
|
4217
|
+
"shift-internal:add",
|
|
4218
|
+
"shift-internal:list",
|
|
4219
|
+
"shift-internal:cancel",
|
|
4220
|
+
"shift-internal:update",
|
|
4221
|
+
"shift-internal:history",
|
|
4222
|
+
"skills:list",
|
|
4223
|
+
"agents:list",
|
|
4224
|
+
"git:root",
|
|
4225
|
+
"git:branch",
|
|
4226
|
+
"git:branches",
|
|
4227
|
+
"capabilities:get",
|
|
4228
|
+
// ---- persona:* (persona 管理) ----
|
|
4229
|
+
// persona:list 响应 shape 不分流(统一返 PersonaFile[]),但 daemon handler 按
|
|
4230
|
+
// ConnectionContext 投影不同子集:
|
|
4231
|
+
// owner ctx → 返全量 personas(含 private)
|
|
4232
|
+
// guest ctx → persona.public === true ∧ assertGrant(ctx.grants, {persona,p.id}, 'read')
|
|
4233
|
+
// method-grants.ts: persona:list 是 CAPABILITY_SCOPED;其它 persona:* 仍 ADMIN_ANY。
|
|
4234
|
+
"persona:create",
|
|
4235
|
+
"persona:list",
|
|
4236
|
+
"persona:get",
|
|
4237
|
+
"persona:update",
|
|
4238
|
+
"persona:delete",
|
|
4239
|
+
// ---- personaDispatch:* (dispatch 全家,spec 2026-07-28-unify-rpc-auth 统一登记) ----
|
|
4240
|
+
// run:本地 MCP server 经 /rpc(Bearer owner token);跨设备 A 的 peer daemon 经 /rpc
|
|
4241
|
+
//(Bearer connect token)。capability-scoped(handler 自检 persona.public + assertGrant(send))。
|
|
4242
|
+
// complete / list:B / A 本机 MCP server 调(owner token → ADMIN_ANY)。
|
|
4243
|
+
// get:跨设备轮询——A 端 daemon 凭 connect token 查 B 台账终态;handler 校验行归属。
|
|
4244
|
+
"personaDispatch:run",
|
|
4245
|
+
"personaDispatch:complete",
|
|
4246
|
+
"personaDispatch:list",
|
|
4247
|
+
"personaDispatch:get",
|
|
4248
|
+
// ---- peerExec:run (跨设备 exec,spec 2026-07-16-cross-device-exec-mcp) ----
|
|
4249
|
+
// A 侧本机 MCP server 经 /rpc(Bearer owner token)带 peerDeviceId → daemon forward;
|
|
4250
|
+
// B 侧对端经 /rpc(Bearer connect token)无 peerDeviceId → 本地 spawn。METHOD_GRANT_MAP
|
|
4251
|
+
// 设 public,handler 内判 remoteAccessAllowed(跟 inbox:postMessage 同款)。
|
|
4252
|
+
"peerExec:run",
|
|
4253
|
+
// ---- session:pty 双向透传(仅 CLAWD_CC_MODE=tui 才生效,对应 session:pty push 帧的上行) ----
|
|
4254
|
+
// session:pty:input — UI 把用户键盘字节(base64 UTF-8)发给 daemon,daemon 直写 pty stdin。
|
|
4255
|
+
// 高频帧(每次按键 1 帧),不入 reducer / 不广播。response 是 fire-and-forget 风格 ack。
|
|
4256
|
+
// session:pty:resize — UI 端 xterm 尺寸(cols/rows)变化时同步给 daemon 调 pty resize;
|
|
4257
|
+
// 触发频率低(仅 window resize),response 也是 ack。
|
|
4258
|
+
"session:pty:input",
|
|
4259
|
+
"session:pty:resize",
|
|
4260
|
+
// session:pty:snapshot — UI XtermPanel 重新挂载(切 session 回来 / 刷新)时主动拉一次当前
|
|
4261
|
+
// 屏幕全量快照,再开始消费 incremental session:pty。daemon 调 manager.getPtyReplay(sessionId)
|
|
4262
|
+
// 先 drain detector parse queue 再 serialize,保证 atSeq 与 buffer 内容严格对齐。
|
|
4263
|
+
// response 字段:
|
|
4264
|
+
// - data:当前屏幕 + scrollback 的 ANSI 字节串(base64-utf8),与 session:pty push 帧同格式
|
|
4265
|
+
// - atSeq:此 snapshot 覆盖到的最后一帧 session:pty 的 seq(即 detector 已 parse 完成的最大 seq)
|
|
4266
|
+
// UI 端 flush 时丢弃 pending 中 seq ≤ atSeq 的帧
|
|
4267
|
+
// - popupKind:当前 detector 检测到的 popup 类型(null = 无 popup)
|
|
4268
|
+
// session 不存在 / 非 tui / pty 已 exit 时 data=null, atSeq=0。
|
|
4269
|
+
"session:pty:snapshot",
|
|
4270
|
+
// ---- attachment.* file-sharing(详见 attachment-schemas.ts) ----
|
|
4271
|
+
// 命名警告:这里的 `attachment.*` RPC 与 CC v2.x 上行 `type:"attachment"` 系统行
|
|
4272
|
+
// (attachment-skills / attachment-deferred-tools / attachment_memories)是不同概念。
|
|
4273
|
+
// 全部管理类 RPC dispatcher grant 限 owner(capability admin-only);
|
|
4274
|
+
// 实际文件传输走 HTTP 路由(GET /files?p=&e=&s=,HMAC 签名自包含,不在白名单内)。
|
|
4275
|
+
"attachment.signUrl",
|
|
4276
|
+
"attachment.groupAdd",
|
|
4277
|
+
"attachment.groupRemove",
|
|
4278
|
+
"attachment.groupList",
|
|
4279
|
+
// ---- inbox:* (capability platform Phase 3 跨用户通知 + Phase 4 DM) ----
|
|
4280
|
+
// owner 接 guest 的 cross-principal 消息事件 + DM 双向私聊.
|
|
4281
|
+
// inbox:list / markRead: admin-only (Phase 3); inbox:postMessage: DM 自带能力,
|
|
4282
|
+
// 任何 principal (owner/guest) 可调 (Phase 4).
|
|
4283
|
+
"inbox:list",
|
|
4284
|
+
"inbox:markRead",
|
|
4285
|
+
"inbox:postMessage",
|
|
4286
|
+
// inbox:sendDm——persona 代发 DM 编排(inbox MCP server 经 /rpc + Bearer owner token 调)。
|
|
4287
|
+
// sender/mode 由 handler 按 body.sessionId 反查 session scope 归因(业务逻辑非鉴权)。
|
|
4288
|
+
"inbox:sendDm",
|
|
4289
|
+
// ---- contact:* (联系人列表) ----
|
|
4290
|
+
// 飞书统一身份 Phase 3 (决策 #14): received-capability:* 正名为 contact:*——Phase 2 后
|
|
4291
|
+
// 联系人身份由中心 server introspect 背书,不再是"对方颁发的 capability"。
|
|
4292
|
+
// 写入路径:device:connect 落 store + 自动反向(决策 #11);list / remove 作联系人列表读删。
|
|
4293
|
+
"contact:list",
|
|
4294
|
+
"contact:pin",
|
|
4295
|
+
"contact:remove",
|
|
4296
|
+
// ---- contact:setRemoteAccess (远程访问授权,spec 2026-07-16) ----
|
|
4297
|
+
// owner UI 授权 contact 反向操作我的设备(跨设备 exec 开关 remoteAccessAllowed)。
|
|
4298
|
+
// 详见 protocol/src/contact-remote-access.ts.
|
|
4299
|
+
"contact:setRemoteAccess",
|
|
4300
|
+
// ---- contact:handshake (双向确认建联握手, spec 2026-07-22) ----
|
|
4301
|
+
// device:connect 临时连接调用;被调方同步落库+broadcast 后回 ok(携带身份载荷)。
|
|
4302
|
+
// 替代旧 whoami+auto-reverse 组合;whoami 对 connect-token guest 已封(旧客户端拦截)。
|
|
4303
|
+
"contact:handshake",
|
|
4304
|
+
// ---- visitor:* (web 访客 · persona web 分享,spec 2026-06-24-persona-web-share-design) ----
|
|
4305
|
+
// owner-only:列出登录访问过本机 public persona 的 web 访客(零安装、飞书登录、daemon 自签
|
|
4306
|
+
// visitor token)。存储 ~/.clawd/visitors.json(VisitorStore),登录(exchange)即 upsert;
|
|
4307
|
+
// 访客身份用 TTC unique_id,会话按 creatorPrincipalId='visitor-<id>' 进现有会话用户分组。
|
|
4308
|
+
// 访客换 token 走 HTTP-only 公开路由 POST /share/exchange(非 WS method)。
|
|
4309
|
+
"visitor:list",
|
|
4310
|
+
// ---- whoami (v2 capability platform) ----
|
|
4311
|
+
// 任何 authed connection 都能调;返回 owner 显示名 + 当前 capability wire 形态 +
|
|
4312
|
+
// grants 对应的 persona 元数据 (id + displayName)。UI 端 AddRemotePersonaDialog
|
|
4313
|
+
// 的 preview 一次性临时 client 用它判定身份和可用 persona。
|
|
4314
|
+
"whoami",
|
|
4315
|
+
"info",
|
|
4316
|
+
"ping",
|
|
4317
|
+
// ---- meta:methods (RPC 自省) ----
|
|
4318
|
+
// 任何 authed connection 都能调(同 whoami):返回 METHOD_NAMES 全集 + **对本连接**
|
|
4319
|
+
// 的可调用性三态。agent 侧 clawd-rpc 的 list tool 是唯一消费方——统一鉴权删掉白名单后
|
|
4320
|
+
// agent 面前是 104 个 method,没有自省就只能靠试错。
|
|
4321
|
+
"meta:methods",
|
|
4322
|
+
// ---- extension runtime (v1: local mode only, no host-bridge —
|
|
4323
|
+
// see clawd/superpowers/specs/2026-05-27-clawd-extensions-v1-design.md) ----
|
|
4324
|
+
"extension.list",
|
|
4325
|
+
"extension.open",
|
|
4326
|
+
"extension.close",
|
|
4327
|
+
"extension.uninstall",
|
|
4328
|
+
// ---- extension sharing v1 (spec 2026-05-28-clawd-extension-sharing-design) ----
|
|
4329
|
+
// owner-side: 公开 / 撤回 / 查 publish 状态(owner-only ADMIN_ANY)
|
|
4330
|
+
"extension.publish",
|
|
4331
|
+
"extension.unpublish",
|
|
4332
|
+
"extension.publish:status",
|
|
4333
|
+
// cross-tunnel: guest 从 owner 拉 published list + bundle(CAPABILITY_SCOPED)
|
|
4334
|
+
"extension.list-published",
|
|
4335
|
+
"extension.fetchBundle",
|
|
4336
|
+
// guest-self: guest 在自己 daemon 上做安装与更新(ADMIN_ANY,guest 是 owner of self daemon).
|
|
4337
|
+
// 无 subscription 持久化:guest 端身份完全来自文件系统 + reconciled publishedExtensions.
|
|
4338
|
+
"extension.install-from-channel",
|
|
4339
|
+
"extension.update-from-channel",
|
|
4340
|
+
// ---- auth:* 飞书统一身份 Phase 1 (spec 2026-06-01-feishu-identity-design) ----
|
|
4341
|
+
// owner-only:daemon loopback 登录流程(auth:login:start 起 state → HTTP /auth/callback
|
|
4342
|
+
// 回调落盘 → auth:login:done 事件)。中央字面量见 protocol/feishu-auth.ts FEISHU_AUTH_METHODS。
|
|
4343
|
+
"auth:login:start",
|
|
4344
|
+
"auth:getIdentity",
|
|
4345
|
+
"auth:logout",
|
|
4346
|
+
// ---- device:* 设备目录 + 连接(决策 #15:deviceId + 自包含 token) ----
|
|
4347
|
+
// owner-only:公共设备目录 + audience 绑定设备的签名 token 连接(daemon 代理中心 server)。
|
|
4348
|
+
// 中央字面量见 protocol/feishu-auth.ts DEVICE_METHODS。
|
|
4349
|
+
"device:list",
|
|
4350
|
+
"device:connect",
|
|
4351
|
+
// ---- app-builder Project (spec 2026-06-01 picker → 2026-06-02 单栏默认 refactor) ----
|
|
4352
|
+
// persona-app-builder Project 管理;schemas: ProjectMetadataSchema + 5 个 args/result 对。
|
|
4353
|
+
// listProjects: readdir projects/,按目录读 .clawd-project.json
|
|
4354
|
+
// createProject: 校验 personaId/未绑 + 校验名 + 从 6173-6182 段分配端口 + 写元数据 + 创建空目录
|
|
4355
|
+
// + daemon 内部 mutate session.appBuilderProject + 起 dev server(单栏 refactor 后唯一绑定入口)
|
|
4356
|
+
// deleteProject: 停 dev server + rm -rf 目录(绑定 session 由 session:delete 联动 / 不在这里删)
|
|
4357
|
+
// updateProjectPort: 校验新端口段内 + 未被别的 project 占 + 重启 dev server
|
|
4358
|
+
// setProdUrl: 发布上线后 assistant 调一次写入 .clawd-project.json.prodUrl(取代 prod marker)
|
|
4359
|
+
"appBuilder:listProjects",
|
|
4360
|
+
// getProject:按 sessionId 取单个绑定 project(含 status)。people/mirror 跨 daemon 场景:
|
|
4361
|
+
// 本机 owner 在远端是 guest,listProjects 被 per-user 隔离拿不到别人的 project;getProject
|
|
4362
|
+
// 按 session 可见性授权(ensureSessionAccess read)放行。本地也复用(省掉拉全量再 find)。
|
|
4363
|
+
"appBuilder:getProject",
|
|
4364
|
+
"appBuilder:createProject",
|
|
4365
|
+
"appBuilder:deleteProject",
|
|
4366
|
+
"appBuilder:updateProjectPort",
|
|
4367
|
+
"appBuilder:setProdUrl",
|
|
4368
|
+
// 单栏 refactor stage fix (spec 2026-06-02-app-builder-single-pane-default-design §5.6.2):
|
|
4369
|
+
// createProject 时不再立即起 dev server(fresh 目录必崩)。assistant scaffold + pnpm install
|
|
4370
|
+
// 完成后调 startDevServer 显式触发 supervisor spawn;中间用 reportStage 上报进度(scaffolding
|
|
4371
|
+
// / installing 等),daemon broadcast appBuilder:project-updated 帧让 UI PreviewPane 切阶段。
|
|
4372
|
+
"appBuilder:startDevServer",
|
|
4373
|
+
"appBuilder:reportStage",
|
|
4374
|
+
// 显式控制 fix (spec 2026-06-02-app-builder-explicit-dev-server-control):用户点"收起预览"按钮触发,
|
|
4375
|
+
// 对称 startDevServer。砍掉了 setActiveSession(dev server 不再跟用户 focus 走),切 session 不动 dev server。
|
|
4376
|
+
"appBuilder:stopDevServer",
|
|
4377
|
+
// 发布上线脚手架化 (spec 2026-06-03-app-builder-publish-scaffold-design):
|
|
4378
|
+
// publish:PreviewPane「发布上线」按钮 onClick 调本 RPC,daemon 内串行化 + spawn publish.sh +
|
|
4379
|
+
// 广播阶段进度帧 (appBuilder:publish-progress / publish-failed)。同 project 已有 in-flight job
|
|
4380
|
+
// 返回 already-publishing + 既有 jobId(UI 不报错继续订阅)。失败时 daemon 调 manager.send()
|
|
4381
|
+
// 注入 user_text 到 chat,由 assistant 接管完成部署。
|
|
4382
|
+
// dismissPublishJob:取消 in-flight publish(SIGTERM 子进程 + 清字段)或清掉 daemon 崩溃留下的
|
|
4383
|
+
// 中断残骸 publishJob 字段。UI 端 [取消] / [interrupted 取消] 都走这个 RPC。
|
|
4384
|
+
"appBuilder:publish",
|
|
4385
|
+
"appBuilder:dismissPublishJob"
|
|
4386
|
+
];
|
|
4387
|
+
RPC_METHOD_STATUSES = ["allowed", "conditional", "denied"];
|
|
4388
|
+
RpcMethodStatusSchema = external_exports.enum(RPC_METHOD_STATUSES);
|
|
4389
|
+
RpcMethodInfoSchema = external_exports.object({
|
|
4390
|
+
/** canonical method 名,直接可作为 clawd-rpc call 的 method 参数 */
|
|
4391
|
+
name: external_exports.string().min(1),
|
|
4392
|
+
status: RpcMethodStatusSchema,
|
|
4393
|
+
/**
|
|
4394
|
+
* `denied` 必带:daemon error code(`UNAUTHORIZED` / `FEISHU_LOGIN_REQUIRED` /
|
|
4395
|
+
* `METHOD_NOT_IMPLEMENTED`)。`conditional` 必带:谁来做二次校验。
|
|
4396
|
+
* `allowed` 恒无。
|
|
4397
|
+
*/
|
|
4398
|
+
reason: external_exports.string().optional()
|
|
4399
|
+
});
|
|
4400
|
+
MetaMethodsResultSchema = external_exports.object({
|
|
4401
|
+
type: external_exports.literal("meta:methods"),
|
|
4402
|
+
/** METHOD_NAMES 全集,顺序与之一致 */
|
|
4403
|
+
methods: external_exports.array(RpcMethodInfoSchema)
|
|
4404
|
+
});
|
|
4405
|
+
}
|
|
4406
|
+
});
|
|
4407
|
+
|
|
4408
|
+
// ../protocol/src/events.ts
|
|
4409
|
+
var DAEMON_MODE_VALUES, SESSION_STATUS_VALUES, HISTORY_USER_META_VALUES, SKILL_SOURCE_VALUES, AGENT_SOURCE_VALUES, ASK_USER_QUESTION_TOOL_NAME;
|
|
4410
|
+
var init_events = __esm({
|
|
4411
|
+
"../protocol/src/events.ts"() {
|
|
4412
|
+
"use strict";
|
|
4413
|
+
DAEMON_MODE_VALUES = ["sdk", "tui"];
|
|
4414
|
+
SESSION_STATUS_VALUES = [
|
|
4415
|
+
"idle",
|
|
4416
|
+
"running",
|
|
4417
|
+
"running-idle",
|
|
4418
|
+
"stopped",
|
|
4419
|
+
"error",
|
|
4420
|
+
"observing"
|
|
4421
|
+
];
|
|
4422
|
+
HISTORY_USER_META_VALUES = [
|
|
4423
|
+
"task-notification",
|
|
4424
|
+
"slash-command",
|
|
4425
|
+
"local-command",
|
|
4426
|
+
"system-reminder",
|
|
4427
|
+
"skill-hint",
|
|
4428
|
+
"meta-text",
|
|
4429
|
+
"attachment-skills",
|
|
4430
|
+
"attachment-deferred-tools"
|
|
4431
|
+
];
|
|
4432
|
+
SKILL_SOURCE_VALUES = ["builtin", "global", "project", "plugin"];
|
|
4433
|
+
AGENT_SOURCE_VALUES = [
|
|
4434
|
+
"builtin",
|
|
4435
|
+
"global",
|
|
4436
|
+
"project",
|
|
4437
|
+
"policy",
|
|
4438
|
+
"plugin"
|
|
4439
|
+
];
|
|
4440
|
+
ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
|
|
4441
|
+
}
|
|
4442
|
+
});
|
|
4443
|
+
|
|
4444
|
+
// ../protocol/src/errors.ts
|
|
4445
|
+
var ERROR_CODES, ClawdError;
|
|
4446
|
+
var init_errors2 = __esm({
|
|
4447
|
+
"../protocol/src/errors.ts"() {
|
|
4448
|
+
"use strict";
|
|
4449
|
+
ERROR_CODES = {
|
|
4450
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
4451
|
+
SESSION_BUSY: "SESSION_BUSY",
|
|
4452
|
+
INVALID_CWD: "INVALID_CWD",
|
|
4453
|
+
INVALID_PATH: "INVALID_PATH",
|
|
4454
|
+
TOOL_NOT_SUPPORTED: "TOOL_NOT_SUPPORTED",
|
|
4455
|
+
CLAUDE_NOT_FOUND: "CLAUDE_NOT_FOUND",
|
|
4456
|
+
SPAWN_FAILED: "SPAWN_FAILED",
|
|
4457
|
+
INVALID_PERMISSION_MODE: "INVALID_PERMISSION_MODE",
|
|
4458
|
+
METHOD_NOT_IMPLEMENTED: "METHOD_NOT_IMPLEMENTED",
|
|
4459
|
+
METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED",
|
|
4460
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
4461
|
+
PERMISSION_REQUEST_STALE: "PERMISSION_REQUEST_STALE",
|
|
4462
|
+
FILE_TOO_LARGE: "FILE_TOO_LARGE",
|
|
4463
|
+
INTERNAL: "INTERNAL",
|
|
4464
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
4465
|
+
FORBIDDEN: "FORBIDDEN",
|
|
4466
|
+
INVALID_PARAM: "INVALID_PARAM",
|
|
4467
|
+
// 飞书统一身份(spec 2026-06-01 决策 #9):People/远程体系强制飞书登录。
|
|
4468
|
+
// daemon 进程身份未激活为飞书 unionId 时,FEISHU_GATED_METHODS 内的 RPC 一律返回此错误;
|
|
4469
|
+
// UI 据此显示登录引导(区别于 UNAUTHORIZED 的越权语义)。
|
|
4470
|
+
FEISHU_LOGIN_REQUIRED: "FEISHU_LOGIN_REQUIRED",
|
|
4471
|
+
// app-builder 单栏默认 refactor (spec 2026-06-02-app-builder-single-pane-default-design):
|
|
4472
|
+
// appBuilder:createProject 加 personaId + session 未绑校验后抛的两个错码。
|
|
4473
|
+
WRONG_PERSONA: "WRONG_PERSONA",
|
|
4474
|
+
SESSION_ALREADY_BOUND: "SESSION_ALREADY_BOUND",
|
|
4475
|
+
// 2026-07-02 unified people sidebar: contact:pin 时 deviceId 不在 store(可能被别处删了)
|
|
4476
|
+
CONTACT_NOT_FOUND: "CONTACT_NOT_FOUND",
|
|
4477
|
+
// 统一 RPC 鉴权(spec 2026-07-28):personaDispatch:get 查不到台账行,或 guest ctx
|
|
4478
|
+
// 查非自己发起的行(越权与未知 id 同码,不泄露存在性)。A 端轮询遇此码立即判失败。
|
|
4479
|
+
DISPATCH_NOT_FOUND: "DISPATCH_NOT_FOUND"
|
|
4480
|
+
};
|
|
4481
|
+
ClawdError = class extends Error {
|
|
4482
|
+
constructor(code, message) {
|
|
4483
|
+
super(message);
|
|
4484
|
+
this.code = code;
|
|
4485
|
+
this.name = "ClawdError";
|
|
4486
|
+
}
|
|
4487
|
+
code;
|
|
4488
|
+
};
|
|
4489
|
+
}
|
|
4490
|
+
});
|
|
4491
|
+
|
|
4468
4492
|
// ../protocol/src/attachment-schemas.ts
|
|
4469
4493
|
var TOKEN_ROLES, GROUP_FILE_SOURCES, GroupFileEntrySchema, AttachmentSignUrlArgs, AttachmentSignUrlResponseSchema, AttachmentGroupAddArgs, AttachmentGroupAddResponseSchema, AttachmentGroupRemoveArgs, AttachmentGroupRemoveResponseSchema, AttachmentGroupListArgs, AttachmentGroupListResponseSchema, AttachmentUploadResponseSchema;
|
|
4470
4494
|
var init_attachment_schemas = __esm({
|
|
@@ -6371,7 +6395,7 @@ var init_runtime = __esm({
|
|
|
6371
6395
|
"use strict";
|
|
6372
6396
|
init_methods();
|
|
6373
6397
|
init_events();
|
|
6374
|
-
|
|
6398
|
+
init_errors2();
|
|
6375
6399
|
init_schemas();
|
|
6376
6400
|
init_frames();
|
|
6377
6401
|
init_persona_schemas();
|
|
@@ -54785,7 +54809,7 @@ function buildHistoryHandlers(deps) {
|
|
|
54785
54809
|
};
|
|
54786
54810
|
const list = async (frame, _client, ctx) => {
|
|
54787
54811
|
const args = HistoryListArgs.parse(frame);
|
|
54788
|
-
assertGuestPath(ctx, path57.resolve(args.projectPath), personaRoot, "history:list");
|
|
54812
|
+
assertGuestPath(ctx, path57.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
54789
54813
|
const sessions = await history.listSessions(args);
|
|
54790
54814
|
return { response: { type: "history:list", sessions } };
|
|
54791
54815
|
};
|
|
@@ -55647,6 +55671,235 @@ function buildDeviceHandlers(deps) {
|
|
|
55647
55671
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
55648
55672
|
init_protocol();
|
|
55649
55673
|
|
|
55674
|
+
// src/handlers/method-grants.ts
|
|
55675
|
+
var ADMIN_ANY = {
|
|
55676
|
+
kind: "fixed",
|
|
55677
|
+
resource: { type: "*" },
|
|
55678
|
+
action: "admin"
|
|
55679
|
+
};
|
|
55680
|
+
var CAPABILITY_SCOPED = { kind: "capability-scoped" };
|
|
55681
|
+
var METHOD_GRANT_MAP = {
|
|
55682
|
+
// ---- public(meta-only,guest 也能调) ----
|
|
55683
|
+
"info": { kind: "public" },
|
|
55684
|
+
"ping": { kind: "public" },
|
|
55685
|
+
// v2 Phase 6: whoami 是身份反查,任何 authed connection (owner / guest) 都能调;
|
|
55686
|
+
// handler 内部按 ctx.principal.kind 决定返回 "合成 owner self capability" 还是
|
|
55687
|
+
// "查 capabilityManager 拿 caller 的 guest capability"。
|
|
55688
|
+
"whoami": { kind: "public" },
|
|
55689
|
+
// meta:methods 是自省,与 whoami 同族:任何 authed connection 都能问「我能调什么」。
|
|
55690
|
+
// 返回全集而非只返可调的——guest 看到 denied 条目才知道边界在哪,否则只能反复试错;
|
|
55691
|
+
// method 名本身不是秘密(protocol/src/methods.ts 就是公开源),泄漏面为零。
|
|
55692
|
+
"meta:methods": { kind: "public" },
|
|
55693
|
+
// ---- inbox: 双投 P2P IM ----
|
|
55694
|
+
// 三条都 'public' — 能连上 = 已通过本地验票. handler 内额外校验 guest 的
|
|
55695
|
+
// args.peerDeviceId 与 ctx.principal.id(=deviceId) 一致, 防 guest 越权操作别的 DM 桶.
|
|
55696
|
+
"inbox:list": { kind: "public" },
|
|
55697
|
+
"inbox:markRead": { kind: "public" },
|
|
55698
|
+
"inbox:postMessage": { kind: "public" },
|
|
55699
|
+
// ---- contact:* (联系人列表) ----
|
|
55700
|
+
// 飞书统一身份 Phase 3 (决策 #14): received-capability:* 正名 contact:*。
|
|
55701
|
+
// 写入路径在 device:connect / 自动反向;list / remove 作联系人读 / 删,owner-only。
|
|
55702
|
+
"contact:list": ADMIN_ANY,
|
|
55703
|
+
"contact:pin": ADMIN_ANY,
|
|
55704
|
+
"contact:remove": ADMIN_ANY,
|
|
55705
|
+
// contact:setRemoteAccess (owner UI 配远程访问授权):ADMIN_ANY
|
|
55706
|
+
// (对齐 inbox:postMessage 的"能连上=有 auth,业务在 handler 校"模式)
|
|
55707
|
+
"contact:setRemoteAccess": ADMIN_ANY,
|
|
55708
|
+
// contact:handshake: 能连上 = 已通过本地验票;handler 内校验 tokenKind==='connect'
|
|
55709
|
+
// (visitor / owner 不允许触发反向落库)。
|
|
55710
|
+
"contact:handshake": { kind: "public" },
|
|
55711
|
+
// ---- visitor:* (访客名单,owner-only) ----
|
|
55712
|
+
// owner 看完整访客名单(含没开会话的);guest 不可调(handler 内再 assertOwner 兜底)。
|
|
55713
|
+
"visitor:list": ADMIN_ANY,
|
|
55714
|
+
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
55715
|
+
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
55716
|
+
// owner 自动通过(ctx 自带 '*':'admin' grant 一切 match);guest 在被授权 persona 内可调。
|
|
55717
|
+
"session:create": CAPABILITY_SCOPED,
|
|
55718
|
+
"session:list": CAPABILITY_SCOPED,
|
|
55719
|
+
"session:get": CAPABILITY_SCOPED,
|
|
55720
|
+
"session:update": CAPABILITY_SCOPED,
|
|
55721
|
+
"session:delete": CAPABILITY_SCOPED,
|
|
55722
|
+
"session:send": CAPABILITY_SCOPED,
|
|
55723
|
+
// per-turn sender 2026-07-08 spec §4.6:dispatcher 层走 'public'(HTTP RPC path 需 dispatcher 放行);
|
|
55724
|
+
// WS path 的隐私边界(防 guest 猜 sid 枚举 owner feishuUnionId)由 handler 内 ensureSessionAccess
|
|
55725
|
+
// 显式兜底——见 handlers/session.ts:currentTurnSender。dispatcher 'public' ≠ handler 免检。
|
|
55726
|
+
"session:currentTurnSender": { kind: "public" },
|
|
55727
|
+
"session:stop": CAPABILITY_SCOPED,
|
|
55728
|
+
"session:interrupt": CAPABILITY_SCOPED,
|
|
55729
|
+
"session:rewind": CAPABILITY_SCOPED,
|
|
55730
|
+
"session:rewind-diff": CAPABILITY_SCOPED,
|
|
55731
|
+
"session:rewindable-message-ids": CAPABILITY_SCOPED,
|
|
55732
|
+
"session:fork": CAPABILITY_SCOPED,
|
|
55733
|
+
"session:new": CAPABILITY_SCOPED,
|
|
55734
|
+
"session:resume": CAPABILITY_SCOPED,
|
|
55735
|
+
"session:observe": CAPABILITY_SCOPED,
|
|
55736
|
+
"session:events": CAPABILITY_SCOPED,
|
|
55737
|
+
"session:subscribe": CAPABILITY_SCOPED,
|
|
55738
|
+
"session:unsubscribe": CAPABILITY_SCOPED,
|
|
55739
|
+
"session:pin": CAPABILITY_SCOPED,
|
|
55740
|
+
"session:markRead": CAPABILITY_SCOPED,
|
|
55741
|
+
"session:reorderPins": ADMIN_ANY,
|
|
55742
|
+
// owner 全局操作,无 personaId 维度
|
|
55743
|
+
// mirror peer sessions (2026-05-26):owner-only — guest 不应能写/删本机 mirror SessionFile
|
|
55744
|
+
// (会绕过 #739 隔离规则把伪造身份的 SessionFile 写进 default store)。handler 端内部 ctx
|
|
55745
|
+
// 校验,dispatcher 层一刀切 admin 也兜底。
|
|
55746
|
+
"peerSession:upsert": ADMIN_ANY,
|
|
55747
|
+
"peerSession:remove": ADMIN_ANY,
|
|
55748
|
+
"permission:respond": CAPABILITY_SCOPED,
|
|
55749
|
+
"session:answerQuestion": CAPABILITY_SCOPED,
|
|
55750
|
+
"session:cancelQuestion": CAPABILITY_SCOPED,
|
|
55751
|
+
// 2026-05-25 老板拍板:guest 用别人 daemon 的 chat 必须能读 history / workspace /
|
|
55752
|
+
// attachment / skills / agents / git 元信息,下沉到 capability-scoped;handler 内
|
|
55753
|
+
// 用 isGuestPathAllowed (persona-paths.ts) 限制路径必须在 personaRoot/<allowed-pid>/** 下,
|
|
55754
|
+
// 防止跨 persona 越权读 owner 私有文件。
|
|
55755
|
+
"history:projects": CAPABILITY_SCOPED,
|
|
55756
|
+
"history:list": CAPABILITY_SCOPED,
|
|
55757
|
+
// history:read 取一条 session 的 CC JSONL 历史。guest 进 persona VM 后必须能读自己
|
|
55758
|
+
// 创建的 session 历史(chat view 加载历史消息走这条),所以下沉到 capability-scoped;
|
|
55759
|
+
// handler 内按 ctx.principal.id === file.creatorPrincipalId 拦越权。
|
|
55760
|
+
"history:read": CAPABILITY_SCOPED,
|
|
55761
|
+
"history:subagents": CAPABILITY_SCOPED,
|
|
55762
|
+
"history:subagent-read": CAPABILITY_SCOPED,
|
|
55763
|
+
"history:recentDirs": CAPABILITY_SCOPED,
|
|
55764
|
+
"workspace:list": CAPABILITY_SCOPED,
|
|
55765
|
+
"workspace:read": CAPABILITY_SCOPED,
|
|
55766
|
+
// ---- shift:* (排班 mock,owner-only 读) ----
|
|
55767
|
+
// mock 阶段只 owner 用;接 guest 后再考虑分级
|
|
55768
|
+
"shift:list": ADMIN_ANY,
|
|
55769
|
+
// ---- shift-internal:* + inbox:sendDm + personaDispatch complete/list ----
|
|
55770
|
+
// 统一 RPC 鉴权(spec 2026-07-28):原 /api/rpc 白名单 method 收编。调用方 = 本机
|
|
55771
|
+
// MCP server 持 owner token → ADMIN_ANY 即「owner token 即可」;业务归因(sendDm 的
|
|
55772
|
+
// sender、shift 的 personaId)在 handler 内按 body 字段处理,与鉴权无关。
|
|
55773
|
+
"shift-internal:add": ADMIN_ANY,
|
|
55774
|
+
"shift-internal:list": ADMIN_ANY,
|
|
55775
|
+
"shift-internal:cancel": ADMIN_ANY,
|
|
55776
|
+
"shift-internal:update": ADMIN_ANY,
|
|
55777
|
+
"shift-internal:history": ADMIN_ANY,
|
|
55778
|
+
"inbox:sendDm": ADMIN_ANY,
|
|
55779
|
+
"personaDispatch:complete": ADMIN_ANY,
|
|
55780
|
+
"personaDispatch:list": ADMIN_ANY,
|
|
55781
|
+
// 跨设备轮询(spec §5):A 端 daemon 凭 connect token 查 outcome;handler 内校验
|
|
55782
|
+
// 台账行 sourceSessionId === ctx.principal.id,防 guest 查别人的 dispatch。
|
|
55783
|
+
"personaDispatch:get": CAPABILITY_SCOPED,
|
|
55784
|
+
"skills:list": CAPABILITY_SCOPED,
|
|
55785
|
+
"agents:list": CAPABILITY_SCOPED,
|
|
55786
|
+
"git:root": CAPABILITY_SCOPED,
|
|
55787
|
+
"git:branch": CAPABILITY_SCOPED,
|
|
55788
|
+
"git:branches": CAPABILITY_SCOPED,
|
|
55789
|
+
"capabilities:get": ADMIN_ANY,
|
|
55790
|
+
"persona:create": ADMIN_ANY,
|
|
55791
|
+
// persona:list / persona:get 下沉到 CAPABILITY_SCOPED:guest 调用合法
|
|
55792
|
+
// (list 用于 People 面板展开对方分享的 personas;get 用于 guest 视角下
|
|
55793
|
+
// PersonaDrawer 展示 persona 详情 readOnly),handler 端按 ctx + persona.public
|
|
55794
|
+
// + assertGrant 过滤,两者口径一致。
|
|
55795
|
+
// persona:update / persona:delete 保持 ADMIN_ANY:UI 端 guest viewerRole 下
|
|
55796
|
+
// 已干掉编辑入口,dispatcher 这层是双保险——非法 RPC 401 兜底。
|
|
55797
|
+
"persona:list": CAPABILITY_SCOPED,
|
|
55798
|
+
"persona:get": CAPABILITY_SCOPED,
|
|
55799
|
+
"persona:update": ADMIN_ANY,
|
|
55800
|
+
"persona:delete": ADMIN_ANY,
|
|
55801
|
+
// 跨设备 dispatch:A 的 peer daemon 凭 connect token 经 /rpc 调进来;dispatcher 放行,
|
|
55802
|
+
// run handler 内做 persona.public + assertGrant(send) 双重校验(guest grants 是 wildcard,
|
|
55803
|
+
// 单 assertGrant 不够)。本地 MCP server 经 /rpc + Bearer 进来,同过此表(owner 恒过)。
|
|
55804
|
+
"personaDispatch:run": CAPABILITY_SCOPED,
|
|
55805
|
+
// 跨设备 exec(spec 2026-07-16):public——"能连上=有 auth",业务在 handler 校
|
|
55806
|
+
// (ensureGuest + remoteAccessAllowed),跟 inbox:postMessage 同模式。
|
|
55807
|
+
"peerExec:run": { kind: "public" },
|
|
55808
|
+
// 2026-05-26 修 clawd people TUI 渲染 mix 串扰回归(参考 f1133ff0 原 owner 路径
|
|
55809
|
+
// snapshot/buffer/flush 修复):之前三件套 ADMIN_ANY 把 guest 拦在 dispatcher 401,
|
|
55810
|
+
// 导致 XtermPanel 重挂载拉 snapshot 在 guest 路径不生效,老的字节流断裂串扰回来。
|
|
55811
|
+
// 同一个 session 永远只有一个操作者(owner 不进 guest 创建的 session),并发字节流
|
|
55812
|
+
// 冲突不存在;guest 在 chat 模式下已能 session:send/interrupt,PTY 域不开放纯属
|
|
55813
|
+
// 历史遗留的不对称。handler 端通过 ensureSessionAccess 验权对齐其他 session:* RPC。
|
|
55814
|
+
"session:pty:input": CAPABILITY_SCOPED,
|
|
55815
|
+
"session:pty:resize": CAPABILITY_SCOPED,
|
|
55816
|
+
"session:pty:snapshot": CAPABILITY_SCOPED,
|
|
55817
|
+
// file-sharing attachment.* RPC:dispatcher 放行;handler 内按 sessionId 反查
|
|
55818
|
+
// session.ownerPersonaId + ctx.grants 跑 assertGrant,限制 guest 只能签 / 操作
|
|
55819
|
+
// 自己被授权 persona 下的 session 文件。HTTP Bearer 仍然只识别 owner,所以 guest
|
|
55820
|
+
// 拿到 signed URL 后还要 HTTP 端校验通过才能取到文件——这里 RPC 层 ACL 是第一道。
|
|
55821
|
+
"attachment.signUrl": CAPABILITY_SCOPED,
|
|
55822
|
+
"attachment.groupAdd": CAPABILITY_SCOPED,
|
|
55823
|
+
"attachment.groupRemove": CAPABILITY_SCOPED,
|
|
55824
|
+
"attachment.groupList": CAPABILITY_SCOPED,
|
|
55825
|
+
// ---- extension runtime(owner-only;handler 内再 assertOwner 兜底) ----
|
|
55826
|
+
"extension.list": ADMIN_ANY,
|
|
55827
|
+
"extension.open": ADMIN_ANY,
|
|
55828
|
+
"extension.close": ADMIN_ANY,
|
|
55829
|
+
"extension.uninstall": ADMIN_ANY,
|
|
55830
|
+
// ---- extension sharing v1(spec 2026-05-28-clawd-extension-sharing-design) ----
|
|
55831
|
+
// owner-side:owner 自己管理 publish 状态
|
|
55832
|
+
"extension.publish": ADMIN_ANY,
|
|
55833
|
+
"extension.unpublish": ADMIN_ANY,
|
|
55834
|
+
"extension.publish:status": ADMIN_ANY,
|
|
55835
|
+
// cross-tunnel:guest 从 owner 拉 published list + bundle
|
|
55836
|
+
"extension.list-published": CAPABILITY_SCOPED,
|
|
55837
|
+
"extension.fetchBundle": CAPABILITY_SCOPED,
|
|
55838
|
+
// guest-self:guest 在自己 daemon 上触发安装与更新(无持久化 subscription 概念)
|
|
55839
|
+
"extension.install-from-channel": ADMIN_ANY,
|
|
55840
|
+
"extension.update-from-channel": ADMIN_ANY,
|
|
55841
|
+
// ---- auth:* 飞书统一身份 Phase 1(owner-only) ----
|
|
55842
|
+
// 登录/登出/查身份都是 owner 本机操作,guest 不可调
|
|
55843
|
+
"auth:login:start": ADMIN_ANY,
|
|
55844
|
+
"auth:getIdentity": ADMIN_ANY,
|
|
55845
|
+
"auth:logout": ADMIN_ANY,
|
|
55846
|
+
// ---- device:* 设备目录 + 连接(决策 #15,owner-only) ----
|
|
55847
|
+
// 设备目录 / 连接都是 owner 本机操作(用 owner 的 ttcJwt 找中心 server),guest 不可调
|
|
55848
|
+
"device:list": ADMIN_ANY,
|
|
55849
|
+
"device:connect": ADMIN_ANY,
|
|
55850
|
+
// ---- app-builder Project picker(spec 2026-06-01-app-builder-project-picker-design) ----
|
|
55851
|
+
// owner-only:picker UI 给 owner 管理本机 build 中的 project(fs + 端口分配)。
|
|
55852
|
+
// 即使 persona-app-builder 是 PreinstalledPersona,project 管理也属本机 owner 行为,
|
|
55853
|
+
// 不暴露给 guest(远端接入者)。
|
|
55854
|
+
"appBuilder:listProjects": ADMIN_ANY,
|
|
55855
|
+
// getProject 走 capability-scoped(区别于其它 appBuilder 的 owner-only ADMIN_ANY):mirror/people
|
|
55856
|
+
// 的本机 owner 在远端是 guest,需能调 getProject 拿它 mirror 的 session 的 project。dispatcher
|
|
55857
|
+
// 放行后由 handler 内 canAccessSession(read) 按 session 可见性授权(防 guest 越权拿别人 project)。
|
|
55858
|
+
"appBuilder:getProject": CAPABILITY_SCOPED,
|
|
55859
|
+
"appBuilder:createProject": ADMIN_ANY,
|
|
55860
|
+
"appBuilder:deleteProject": ADMIN_ANY,
|
|
55861
|
+
"appBuilder:updateProjectPort": ADMIN_ANY,
|
|
55862
|
+
// people/mirror 协同写操作(spec 2026-06-04-people-mode-app-builder-write-and-push):以下 5 个写
|
|
55863
|
+
// method 走 CAPABILITY_SCOPED(不再 owner-only ADMIN_ANY),handler 内 ensureProjectWriteAccess
|
|
55864
|
+
// 按 session 可见性(canAccessSession 'send')授权——mirror 的本机 owner 在远端是 guest,能 mirror
|
|
55865
|
+
// 该 session 就能操作它绑定的 project(发布凭证是 persona 共享资产,老板决策"统一 session 授权")。
|
|
55866
|
+
"appBuilder:setProdUrl": CAPABILITY_SCOPED,
|
|
55867
|
+
"appBuilder:startDevServer": CAPABILITY_SCOPED,
|
|
55868
|
+
// reportStage 仍 owner-only:assistant 走 HTTP RPC 上报(不过 WS admin grant),UI 不调它。
|
|
55869
|
+
"appBuilder:reportStage": ADMIN_ANY,
|
|
55870
|
+
"appBuilder:stopDevServer": CAPABILITY_SCOPED,
|
|
55871
|
+
"appBuilder:publish": CAPABILITY_SCOPED,
|
|
55872
|
+
"appBuilder:dismissPublishJob": CAPABILITY_SCOPED
|
|
55873
|
+
};
|
|
55874
|
+
function computeGrant(method) {
|
|
55875
|
+
const rule = METHOD_GRANT_MAP[method];
|
|
55876
|
+
if (!rule) return { kind: "public" };
|
|
55877
|
+
if (rule.kind === "public") return { kind: "public" };
|
|
55878
|
+
if (rule.kind === "capability-scoped") return { kind: "public" };
|
|
55879
|
+
return { kind: "check", resource: rule.resource, action: rule.action };
|
|
55880
|
+
}
|
|
55881
|
+
function computeMethodAccess(args) {
|
|
55882
|
+
const { method, grants, feishuActive, isImplemented } = args;
|
|
55883
|
+
if (!isImplemented(method)) {
|
|
55884
|
+
return { name: method, status: "denied", reason: "METHOD_NOT_IMPLEMENTED" };
|
|
55885
|
+
}
|
|
55886
|
+
if (!feishuActive && FEISHU_GATED_METHODS.includes(method)) {
|
|
55887
|
+
return { name: method, status: "denied", reason: "FEISHU_LOGIN_REQUIRED" };
|
|
55888
|
+
}
|
|
55889
|
+
if (METHOD_GRANT_MAP[method]?.kind === "capability-scoped") {
|
|
55890
|
+
return {
|
|
55891
|
+
name: method,
|
|
55892
|
+
status: "conditional",
|
|
55893
|
+
reason: "handler checks your grants for the target resource"
|
|
55894
|
+
};
|
|
55895
|
+
}
|
|
55896
|
+
const verdict = computeGrant(method);
|
|
55897
|
+
if (verdict.kind === "check" && !assertGrant(grants, verdict.resource, verdict.action)) {
|
|
55898
|
+
return { name: method, status: "denied", reason: "UNAUTHORIZED" };
|
|
55899
|
+
}
|
|
55900
|
+
return { name: method, status: "allowed" };
|
|
55901
|
+
}
|
|
55902
|
+
|
|
55650
55903
|
// src/version.ts
|
|
55651
55904
|
var version = "0.2.6".length > 0 ? "0.2.6" : "dev";
|
|
55652
55905
|
|
|
@@ -55699,6 +55952,20 @@ function buildMetaHandlers(deps) {
|
|
|
55699
55952
|
ping
|
|
55700
55953
|
};
|
|
55701
55954
|
}
|
|
55955
|
+
function buildMetaMethodsHandler(deps) {
|
|
55956
|
+
return async (_frame, _client, ctx) => {
|
|
55957
|
+
const grants = ctx?.grants ?? [];
|
|
55958
|
+
const methods = METHOD_NAMES.map(
|
|
55959
|
+
(method) => computeMethodAccess({
|
|
55960
|
+
method,
|
|
55961
|
+
grants,
|
|
55962
|
+
feishuActive: deps.feishuActive(),
|
|
55963
|
+
isImplemented: deps.isImplemented
|
|
55964
|
+
})
|
|
55965
|
+
);
|
|
55966
|
+
return { response: { type: "meta:methods", methods } };
|
|
55967
|
+
};
|
|
55968
|
+
}
|
|
55702
55969
|
|
|
55703
55970
|
// src/handlers/persona.ts
|
|
55704
55971
|
init_protocol();
|
|
@@ -58024,7 +58291,7 @@ function ensureGuest(ctx) {
|
|
|
58024
58291
|
|
|
58025
58292
|
// src/handlers/index.ts
|
|
58026
58293
|
function buildMethodHandlers(deps) {
|
|
58027
|
-
|
|
58294
|
+
const handlers = {
|
|
58028
58295
|
...buildSessionHandlers({
|
|
58029
58296
|
...deps,
|
|
58030
58297
|
devServerLifecycle: deps.devServerLifecycle,
|
|
@@ -58123,6 +58390,11 @@ function buildMethodHandlers(deps) {
|
|
|
58123
58390
|
}),
|
|
58124
58391
|
...buildVisitorHandlers({ visitorStore: deps.visitorStore })
|
|
58125
58392
|
};
|
|
58393
|
+
handlers["meta:methods"] = buildMetaMethodsHandler({
|
|
58394
|
+
feishuActive: deps.feishuActive ?? (() => true),
|
|
58395
|
+
isImplemented: (m2) => Boolean((deps.getAllHandlers?.() ?? handlers)[m2])
|
|
58396
|
+
});
|
|
58397
|
+
return handlers;
|
|
58126
58398
|
}
|
|
58127
58399
|
|
|
58128
58400
|
// src/app-builder/dev-server-supervisor.ts
|
|
@@ -58381,217 +58653,6 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
58381
58653
|
|
|
58382
58654
|
// src/handlers/dispatch-rpc.ts
|
|
58383
58655
|
init_protocol();
|
|
58384
|
-
|
|
58385
|
-
// src/handlers/method-grants.ts
|
|
58386
|
-
var ADMIN_ANY = {
|
|
58387
|
-
kind: "fixed",
|
|
58388
|
-
resource: { type: "*" },
|
|
58389
|
-
action: "admin"
|
|
58390
|
-
};
|
|
58391
|
-
var CAPABILITY_SCOPED = { kind: "capability-scoped" };
|
|
58392
|
-
var METHOD_GRANT_MAP = {
|
|
58393
|
-
// ---- public(meta-only,guest 也能调) ----
|
|
58394
|
-
"info": { kind: "public" },
|
|
58395
|
-
"ping": { kind: "public" },
|
|
58396
|
-
// v2 Phase 6: whoami 是身份反查,任何 authed connection (owner / guest) 都能调;
|
|
58397
|
-
// handler 内部按 ctx.principal.kind 决定返回 "合成 owner self capability" 还是
|
|
58398
|
-
// "查 capabilityManager 拿 caller 的 guest capability"。
|
|
58399
|
-
"whoami": { kind: "public" },
|
|
58400
|
-
// ---- inbox: 双投 P2P IM ----
|
|
58401
|
-
// 三条都 'public' — 能连上 = 已通过本地验票. handler 内额外校验 guest 的
|
|
58402
|
-
// args.peerDeviceId 与 ctx.principal.id(=deviceId) 一致, 防 guest 越权操作别的 DM 桶.
|
|
58403
|
-
"inbox:list": { kind: "public" },
|
|
58404
|
-
"inbox:markRead": { kind: "public" },
|
|
58405
|
-
"inbox:postMessage": { kind: "public" },
|
|
58406
|
-
// ---- contact:* (联系人列表) ----
|
|
58407
|
-
// 飞书统一身份 Phase 3 (决策 #14): received-capability:* 正名 contact:*。
|
|
58408
|
-
// 写入路径在 device:connect / 自动反向;list / remove 作联系人读 / 删,owner-only。
|
|
58409
|
-
"contact:list": ADMIN_ANY,
|
|
58410
|
-
"contact:pin": ADMIN_ANY,
|
|
58411
|
-
"contact:remove": ADMIN_ANY,
|
|
58412
|
-
// contact:setRemoteAccess (owner UI 配远程访问授权):ADMIN_ANY
|
|
58413
|
-
// (对齐 inbox:postMessage 的"能连上=有 auth,业务在 handler 校"模式)
|
|
58414
|
-
"contact:setRemoteAccess": ADMIN_ANY,
|
|
58415
|
-
// contact:handshake: 能连上 = 已通过本地验票;handler 内校验 tokenKind==='connect'
|
|
58416
|
-
// (visitor / owner 不允许触发反向落库)。
|
|
58417
|
-
"contact:handshake": { kind: "public" },
|
|
58418
|
-
// ---- visitor:* (访客名单,owner-only) ----
|
|
58419
|
-
// owner 看完整访客名单(含没开会话的);guest 不可调(handler 内再 assertOwner 兜底)。
|
|
58420
|
-
"visitor:list": ADMIN_ANY,
|
|
58421
|
-
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
58422
|
-
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
58423
|
-
// owner 自动通过(ctx 自带 '*':'admin' grant 一切 match);guest 在被授权 persona 内可调。
|
|
58424
|
-
"session:create": CAPABILITY_SCOPED,
|
|
58425
|
-
"session:list": CAPABILITY_SCOPED,
|
|
58426
|
-
"session:get": CAPABILITY_SCOPED,
|
|
58427
|
-
"session:update": CAPABILITY_SCOPED,
|
|
58428
|
-
"session:delete": CAPABILITY_SCOPED,
|
|
58429
|
-
"session:send": CAPABILITY_SCOPED,
|
|
58430
|
-
// per-turn sender 2026-07-08 spec §4.6:dispatcher 层走 'public'(HTTP RPC path 需 dispatcher 放行);
|
|
58431
|
-
// WS path 的隐私边界(防 guest 猜 sid 枚举 owner feishuUnionId)由 handler 内 ensureSessionAccess
|
|
58432
|
-
// 显式兜底——见 handlers/session.ts:currentTurnSender。dispatcher 'public' ≠ handler 免检。
|
|
58433
|
-
"session:currentTurnSender": { kind: "public" },
|
|
58434
|
-
"session:stop": CAPABILITY_SCOPED,
|
|
58435
|
-
"session:interrupt": CAPABILITY_SCOPED,
|
|
58436
|
-
"session:rewind": CAPABILITY_SCOPED,
|
|
58437
|
-
"session:rewind-diff": CAPABILITY_SCOPED,
|
|
58438
|
-
"session:rewindable-message-ids": CAPABILITY_SCOPED,
|
|
58439
|
-
"session:fork": CAPABILITY_SCOPED,
|
|
58440
|
-
"session:new": CAPABILITY_SCOPED,
|
|
58441
|
-
"session:resume": CAPABILITY_SCOPED,
|
|
58442
|
-
"session:observe": CAPABILITY_SCOPED,
|
|
58443
|
-
"session:events": CAPABILITY_SCOPED,
|
|
58444
|
-
"session:subscribe": CAPABILITY_SCOPED,
|
|
58445
|
-
"session:unsubscribe": CAPABILITY_SCOPED,
|
|
58446
|
-
"session:pin": CAPABILITY_SCOPED,
|
|
58447
|
-
"session:markRead": CAPABILITY_SCOPED,
|
|
58448
|
-
"session:reorderPins": ADMIN_ANY,
|
|
58449
|
-
// owner 全局操作,无 personaId 维度
|
|
58450
|
-
// mirror peer sessions (2026-05-26):owner-only — guest 不应能写/删本机 mirror SessionFile
|
|
58451
|
-
// (会绕过 #739 隔离规则把伪造身份的 SessionFile 写进 default store)。handler 端内部 ctx
|
|
58452
|
-
// 校验,dispatcher 层一刀切 admin 也兜底。
|
|
58453
|
-
"peerSession:upsert": ADMIN_ANY,
|
|
58454
|
-
"peerSession:remove": ADMIN_ANY,
|
|
58455
|
-
"permission:respond": CAPABILITY_SCOPED,
|
|
58456
|
-
"session:answerQuestion": CAPABILITY_SCOPED,
|
|
58457
|
-
"session:cancelQuestion": CAPABILITY_SCOPED,
|
|
58458
|
-
// 2026-05-25 老板拍板:guest 用别人 daemon 的 chat 必须能读 history / workspace /
|
|
58459
|
-
// attachment / skills / agents / git 元信息,下沉到 capability-scoped;handler 内
|
|
58460
|
-
// 用 isGuestPathAllowed (persona-paths.ts) 限制路径必须在 personaRoot/<allowed-pid>/** 下,
|
|
58461
|
-
// 防止跨 persona 越权读 owner 私有文件。
|
|
58462
|
-
"history:projects": CAPABILITY_SCOPED,
|
|
58463
|
-
"history:list": CAPABILITY_SCOPED,
|
|
58464
|
-
// history:read 取一条 session 的 CC JSONL 历史。guest 进 persona VM 后必须能读自己
|
|
58465
|
-
// 创建的 session 历史(chat view 加载历史消息走这条),所以下沉到 capability-scoped;
|
|
58466
|
-
// handler 内按 ctx.principal.id === file.creatorPrincipalId 拦越权。
|
|
58467
|
-
"history:read": CAPABILITY_SCOPED,
|
|
58468
|
-
"history:subagents": CAPABILITY_SCOPED,
|
|
58469
|
-
"history:subagent-read": CAPABILITY_SCOPED,
|
|
58470
|
-
"history:recentDirs": CAPABILITY_SCOPED,
|
|
58471
|
-
"workspace:list": CAPABILITY_SCOPED,
|
|
58472
|
-
"workspace:read": CAPABILITY_SCOPED,
|
|
58473
|
-
// ---- shift:* (排班 mock,owner-only 读) ----
|
|
58474
|
-
// mock 阶段只 owner 用;接 guest 后再考虑分级
|
|
58475
|
-
"shift:list": ADMIN_ANY,
|
|
58476
|
-
// ---- shift-internal:* + inbox:sendDm + personaDispatch complete/list ----
|
|
58477
|
-
// 统一 RPC 鉴权(spec 2026-07-28):原 /api/rpc 白名单 method 收编。调用方 = 本机
|
|
58478
|
-
// MCP server 持 owner token → ADMIN_ANY 即「owner token 即可」;业务归因(sendDm 的
|
|
58479
|
-
// sender、shift 的 personaId)在 handler 内按 body 字段处理,与鉴权无关。
|
|
58480
|
-
"shift-internal:add": ADMIN_ANY,
|
|
58481
|
-
"shift-internal:list": ADMIN_ANY,
|
|
58482
|
-
"shift-internal:cancel": ADMIN_ANY,
|
|
58483
|
-
"shift-internal:update": ADMIN_ANY,
|
|
58484
|
-
"shift-internal:history": ADMIN_ANY,
|
|
58485
|
-
"inbox:sendDm": ADMIN_ANY,
|
|
58486
|
-
"personaDispatch:complete": ADMIN_ANY,
|
|
58487
|
-
"personaDispatch:list": ADMIN_ANY,
|
|
58488
|
-
// 跨设备轮询(spec §5):A 端 daemon 凭 connect token 查 outcome;handler 内校验
|
|
58489
|
-
// 台账行 sourceSessionId === ctx.principal.id,防 guest 查别人的 dispatch。
|
|
58490
|
-
"personaDispatch:get": CAPABILITY_SCOPED,
|
|
58491
|
-
"skills:list": CAPABILITY_SCOPED,
|
|
58492
|
-
"agents:list": CAPABILITY_SCOPED,
|
|
58493
|
-
"git:root": CAPABILITY_SCOPED,
|
|
58494
|
-
"git:branch": CAPABILITY_SCOPED,
|
|
58495
|
-
"git:branches": CAPABILITY_SCOPED,
|
|
58496
|
-
"capabilities:get": ADMIN_ANY,
|
|
58497
|
-
"persona:create": ADMIN_ANY,
|
|
58498
|
-
// persona:list / persona:get 下沉到 CAPABILITY_SCOPED:guest 调用合法
|
|
58499
|
-
// (list 用于 People 面板展开对方分享的 personas;get 用于 guest 视角下
|
|
58500
|
-
// PersonaDrawer 展示 persona 详情 readOnly),handler 端按 ctx + persona.public
|
|
58501
|
-
// + assertGrant 过滤,两者口径一致。
|
|
58502
|
-
// persona:update / persona:delete 保持 ADMIN_ANY:UI 端 guest viewerRole 下
|
|
58503
|
-
// 已干掉编辑入口,dispatcher 这层是双保险——非法 RPC 401 兜底。
|
|
58504
|
-
"persona:list": CAPABILITY_SCOPED,
|
|
58505
|
-
"persona:get": CAPABILITY_SCOPED,
|
|
58506
|
-
"persona:update": ADMIN_ANY,
|
|
58507
|
-
"persona:delete": ADMIN_ANY,
|
|
58508
|
-
// 跨设备 dispatch:A 的 peer daemon 凭 connect token 经 /rpc 调进来;dispatcher 放行,
|
|
58509
|
-
// run handler 内做 persona.public + assertGrant(send) 双重校验(guest grants 是 wildcard,
|
|
58510
|
-
// 单 assertGrant 不够)。本地 MCP server 经 /rpc + Bearer 进来,同过此表(owner 恒过)。
|
|
58511
|
-
"personaDispatch:run": CAPABILITY_SCOPED,
|
|
58512
|
-
// 跨设备 exec(spec 2026-07-16):public——"能连上=有 auth",业务在 handler 校
|
|
58513
|
-
// (ensureGuest + remoteAccessAllowed),跟 inbox:postMessage 同模式。
|
|
58514
|
-
"peerExec:run": { kind: "public" },
|
|
58515
|
-
// 2026-05-26 修 clawd people TUI 渲染 mix 串扰回归(参考 f1133ff0 原 owner 路径
|
|
58516
|
-
// snapshot/buffer/flush 修复):之前三件套 ADMIN_ANY 把 guest 拦在 dispatcher 401,
|
|
58517
|
-
// 导致 XtermPanel 重挂载拉 snapshot 在 guest 路径不生效,老的字节流断裂串扰回来。
|
|
58518
|
-
// 同一个 session 永远只有一个操作者(owner 不进 guest 创建的 session),并发字节流
|
|
58519
|
-
// 冲突不存在;guest 在 chat 模式下已能 session:send/interrupt,PTY 域不开放纯属
|
|
58520
|
-
// 历史遗留的不对称。handler 端通过 ensureSessionAccess 验权对齐其他 session:* RPC。
|
|
58521
|
-
"session:pty:input": CAPABILITY_SCOPED,
|
|
58522
|
-
"session:pty:resize": CAPABILITY_SCOPED,
|
|
58523
|
-
"session:pty:snapshot": CAPABILITY_SCOPED,
|
|
58524
|
-
// file-sharing attachment.* RPC:dispatcher 放行;handler 内按 sessionId 反查
|
|
58525
|
-
// session.ownerPersonaId + ctx.grants 跑 assertGrant,限制 guest 只能签 / 操作
|
|
58526
|
-
// 自己被授权 persona 下的 session 文件。HTTP Bearer 仍然只识别 owner,所以 guest
|
|
58527
|
-
// 拿到 signed URL 后还要 HTTP 端校验通过才能取到文件——这里 RPC 层 ACL 是第一道。
|
|
58528
|
-
"attachment.signUrl": CAPABILITY_SCOPED,
|
|
58529
|
-
"attachment.groupAdd": CAPABILITY_SCOPED,
|
|
58530
|
-
"attachment.groupRemove": CAPABILITY_SCOPED,
|
|
58531
|
-
"attachment.groupList": CAPABILITY_SCOPED,
|
|
58532
|
-
// ---- extension runtime(owner-only;handler 内再 assertOwner 兜底) ----
|
|
58533
|
-
"extension.list": ADMIN_ANY,
|
|
58534
|
-
"extension.open": ADMIN_ANY,
|
|
58535
|
-
"extension.close": ADMIN_ANY,
|
|
58536
|
-
"extension.uninstall": ADMIN_ANY,
|
|
58537
|
-
// ---- extension sharing v1(spec 2026-05-28-clawd-extension-sharing-design) ----
|
|
58538
|
-
// owner-side:owner 自己管理 publish 状态
|
|
58539
|
-
"extension.publish": ADMIN_ANY,
|
|
58540
|
-
"extension.unpublish": ADMIN_ANY,
|
|
58541
|
-
"extension.publish:status": ADMIN_ANY,
|
|
58542
|
-
// cross-tunnel:guest 从 owner 拉 published list + bundle
|
|
58543
|
-
"extension.list-published": CAPABILITY_SCOPED,
|
|
58544
|
-
"extension.fetchBundle": CAPABILITY_SCOPED,
|
|
58545
|
-
// guest-self:guest 在自己 daemon 上触发安装与更新(无持久化 subscription 概念)
|
|
58546
|
-
"extension.install-from-channel": ADMIN_ANY,
|
|
58547
|
-
"extension.update-from-channel": ADMIN_ANY,
|
|
58548
|
-
// ---- auth:* 飞书统一身份 Phase 1(owner-only) ----
|
|
58549
|
-
// 登录/登出/查身份都是 owner 本机操作,guest 不可调
|
|
58550
|
-
"auth:login:start": ADMIN_ANY,
|
|
58551
|
-
"auth:getIdentity": ADMIN_ANY,
|
|
58552
|
-
"auth:logout": ADMIN_ANY,
|
|
58553
|
-
// ---- device:* 设备目录 + 连接(决策 #15,owner-only) ----
|
|
58554
|
-
// 设备目录 / 连接都是 owner 本机操作(用 owner 的 ttcJwt 找中心 server),guest 不可调
|
|
58555
|
-
"device:list": ADMIN_ANY,
|
|
58556
|
-
"device:connect": ADMIN_ANY,
|
|
58557
|
-
// ---- app-builder Project picker(spec 2026-06-01-app-builder-project-picker-design) ----
|
|
58558
|
-
// owner-only:picker UI 给 owner 管理本机 build 中的 project(fs + 端口分配)。
|
|
58559
|
-
// 即使 persona-app-builder 是 PreinstalledPersona,project 管理也属本机 owner 行为,
|
|
58560
|
-
// 不暴露给 guest(远端接入者)。
|
|
58561
|
-
"appBuilder:listProjects": ADMIN_ANY,
|
|
58562
|
-
// getProject 走 capability-scoped(区别于其它 appBuilder 的 owner-only ADMIN_ANY):mirror/people
|
|
58563
|
-
// 的本机 owner 在远端是 guest,需能调 getProject 拿它 mirror 的 session 的 project。dispatcher
|
|
58564
|
-
// 放行后由 handler 内 canAccessSession(read) 按 session 可见性授权(防 guest 越权拿别人 project)。
|
|
58565
|
-
"appBuilder:getProject": CAPABILITY_SCOPED,
|
|
58566
|
-
"appBuilder:createProject": ADMIN_ANY,
|
|
58567
|
-
"appBuilder:deleteProject": ADMIN_ANY,
|
|
58568
|
-
"appBuilder:updateProjectPort": ADMIN_ANY,
|
|
58569
|
-
// people/mirror 协同写操作(spec 2026-06-04-people-mode-app-builder-write-and-push):以下 5 个写
|
|
58570
|
-
// method 走 CAPABILITY_SCOPED(不再 owner-only ADMIN_ANY),handler 内 ensureProjectWriteAccess
|
|
58571
|
-
// 按 session 可见性(canAccessSession 'send')授权——mirror 的本机 owner 在远端是 guest,能 mirror
|
|
58572
|
-
// 该 session 就能操作它绑定的 project(发布凭证是 persona 共享资产,老板决策"统一 session 授权")。
|
|
58573
|
-
"appBuilder:setProdUrl": CAPABILITY_SCOPED,
|
|
58574
|
-
"appBuilder:startDevServer": CAPABILITY_SCOPED,
|
|
58575
|
-
// reportStage 仍 owner-only:assistant 走 HTTP RPC 上报(不过 WS admin grant),UI 不调它。
|
|
58576
|
-
"appBuilder:reportStage": ADMIN_ANY,
|
|
58577
|
-
"appBuilder:stopDevServer": CAPABILITY_SCOPED,
|
|
58578
|
-
"appBuilder:publish": CAPABILITY_SCOPED,
|
|
58579
|
-
"appBuilder:dismissPublishJob": CAPABILITY_SCOPED
|
|
58580
|
-
};
|
|
58581
|
-
function computeGrantForFrame(method, frame) {
|
|
58582
|
-
const rule = METHOD_GRANT_MAP[method];
|
|
58583
|
-
if (!rule) return { kind: "public" };
|
|
58584
|
-
if (rule.kind === "public") return { kind: "public" };
|
|
58585
|
-
if (rule.kind === "capability-scoped") return { kind: "public" };
|
|
58586
|
-
if (rule.kind === "fixed") {
|
|
58587
|
-
return { kind: "check", resource: rule.resource, action: rule.action };
|
|
58588
|
-
}
|
|
58589
|
-
const picked = rule.pick(frame);
|
|
58590
|
-
if (!picked) return { kind: "public" };
|
|
58591
|
-
return { kind: "check", resource: picked.resource, action: picked.action };
|
|
58592
|
-
}
|
|
58593
|
-
|
|
58594
|
-
// src/handlers/dispatch-rpc.ts
|
|
58595
58656
|
async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
58596
58657
|
if (!METHOD_NAMES.includes(method)) {
|
|
58597
58658
|
throw new ClawdError(ERROR_CODES.METHOD_NOT_ALLOWED, `unknown method: ${method}`);
|
|
@@ -58604,7 +58665,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
58604
58665
|
`${method} requires feishu login (People/remote identity)`
|
|
58605
58666
|
);
|
|
58606
58667
|
}
|
|
58607
|
-
const verdict =
|
|
58668
|
+
const verdict = computeGrant(method);
|
|
58608
58669
|
if (verdict.kind === "check") {
|
|
58609
58670
|
const ok = assertGrant(ctx.grants, verdict.resource, verdict.action);
|
|
58610
58671
|
if (!ok) {
|
|
@@ -59562,6 +59623,10 @@ async function startDaemon(config) {
|
|
|
59562
59623
|
/* @__PURE__ */ new Set([...config.previewPorts ?? [], ...appBuilderPortRange])
|
|
59563
59624
|
);
|
|
59564
59625
|
const makeHandlers = () => buildMethodHandlers({
|
|
59626
|
+
// meta:methods 自省:飞书 gate getter + 最终 handler 表(下面还会 spread 进
|
|
59627
|
+
// dispatch / shift-internal 两组,只看 buildMethodHandlers 内部表会误报死方法)
|
|
59628
|
+
feishuActive: () => feishuActive,
|
|
59629
|
+
getAllHandlers: () => handlers,
|
|
59565
59630
|
manager,
|
|
59566
59631
|
workspace,
|
|
59567
59632
|
skills,
|