@clawos-dev/clawd 0.2.262 → 0.2.264
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 +1795 -1548
- package/dist/dispatch/mcp-server.cjs +2001 -1491
- package/dist/rpc-tool/mcp-server.cjs +14 -4
- package/dist/share-ui/assets/{guest-DyvZnRwD.js → guest-7QpiTI6y.js} +126 -126
- package/dist/share-ui/guest.html +1 -1
- package/package.json +4 -3
package/dist/cli.cjs
CHANGED
|
@@ -4149,346 +4149,6 @@ var init_zod = __esm({
|
|
|
4149
4149
|
}
|
|
4150
4150
|
});
|
|
4151
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
|
-
|
|
4492
4152
|
// ../protocol/src/attachment-schemas.ts
|
|
4493
4153
|
var TOKEN_ROLES, GROUP_FILE_SOURCES, GroupFileEntrySchema, AttachmentSignUrlArgs, AttachmentSignUrlResponseSchema, AttachmentGroupAddArgs, AttachmentGroupAddResponseSchema, AttachmentGroupRemoveArgs, AttachmentGroupRemoveResponseSchema, AttachmentGroupListArgs, AttachmentGroupListResponseSchema, AttachmentUploadResponseSchema;
|
|
4494
4154
|
var init_attachment_schemas = __esm({
|
|
@@ -4573,56 +4233,733 @@ var init_attachment_schemas = __esm({
|
|
|
4573
4233
|
}
|
|
4574
4234
|
});
|
|
4575
4235
|
|
|
4576
|
-
// ../protocol/src/
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
kind: "owner",
|
|
4581
|
-
displayName,
|
|
4582
|
-
...feishuUnionId ? { feishuUnionId } : {}
|
|
4583
|
-
});
|
|
4584
|
-
}
|
|
4585
|
-
function principalToSender(p2) {
|
|
4586
|
-
return {
|
|
4587
|
-
did: p2.id,
|
|
4588
|
-
displayName: p2.displayName,
|
|
4589
|
-
principal: p2.kind,
|
|
4590
|
-
...p2.feishuUnionId ? { feishuUnionId: p2.feishuUnionId } : {}
|
|
4591
|
-
};
|
|
4592
|
-
}
|
|
4593
|
-
function makeGuestSender(did, displayName, feishuUnionId) {
|
|
4594
|
-
return SenderInfoSchema.parse({
|
|
4595
|
-
did,
|
|
4596
|
-
displayName,
|
|
4597
|
-
principal: "guest",
|
|
4598
|
-
...feishuUnionId ? { feishuUnionId } : {}
|
|
4599
|
-
});
|
|
4600
|
-
}
|
|
4601
|
-
var PrincipalKindSchema, PrincipalSchema, SenderInfoSchema;
|
|
4602
|
-
var init_principal = __esm({
|
|
4603
|
-
"../protocol/src/principal.ts"() {
|
|
4236
|
+
// ../protocol/src/capability.ts
|
|
4237
|
+
var ResourceSchema, ActionSchema, GrantSchema, CapabilitySchema, CapabilityWireSchema, WhoamiResponseSchema, PERSONAL_CAP_GRANTS;
|
|
4238
|
+
var init_capability = __esm({
|
|
4239
|
+
"../protocol/src/capability.ts"() {
|
|
4604
4240
|
"use strict";
|
|
4605
4241
|
init_zod();
|
|
4606
|
-
|
|
4607
|
-
|
|
4242
|
+
ResourceSchema = external_exports.discriminatedUnion("type", [
|
|
4243
|
+
external_exports.object({ type: external_exports.literal("persona"), id: external_exports.string().min(1) }).strict(),
|
|
4244
|
+
external_exports.object({ type: external_exports.literal("chat"), id: external_exports.string().min(1) }).strict(),
|
|
4245
|
+
external_exports.object({ type: external_exports.literal("*") }).strict()
|
|
4246
|
+
]);
|
|
4247
|
+
ActionSchema = external_exports.enum(["read", "send", "admin"]);
|
|
4248
|
+
GrantSchema = external_exports.object({
|
|
4249
|
+
resource: ResourceSchema,
|
|
4250
|
+
actions: external_exports.array(ActionSchema).min(1)
|
|
4251
|
+
}).strict();
|
|
4252
|
+
CapabilitySchema = external_exports.object({
|
|
4608
4253
|
id: external_exports.string().min(1),
|
|
4609
|
-
|
|
4254
|
+
// sha256(token) hex 64
|
|
4255
|
+
secretHash: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
4610
4256
|
displayName: external_exports.string(),
|
|
4257
|
+
// 空数组合法 = 纯访客(只能 DM)
|
|
4258
|
+
grants: external_exports.array(GrantSchema),
|
|
4259
|
+
issuedAt: external_exports.number().int().nonnegative(),
|
|
4260
|
+
expiresAt: external_exports.number().int().positive().optional(),
|
|
4261
|
+
maxUses: external_exports.number().int().positive().optional(),
|
|
4262
|
+
usedCount: external_exports.number().int().nonnegative(),
|
|
4611
4263
|
/**
|
|
4612
|
-
*
|
|
4613
|
-
*
|
|
4614
|
-
* 消费方(如 ticket MCP / 未来别的飞书身份挂钩场景)按 undefined 决定是否降级;本层不做 fallback。
|
|
4264
|
+
* guest 在 auth 帧捎带 selfPrincipalId 时由 AuthGate.authenticate 回写;
|
|
4265
|
+
* 未被消费的 cap 此字段缺失。
|
|
4615
4266
|
*/
|
|
4616
|
-
|
|
4267
|
+
peerOwnerId: external_exports.string().min(1).optional(),
|
|
4268
|
+
/** 首次 client hello 时间戳(与 peerOwnerId 同步写入) */
|
|
4269
|
+
firstUsedByPeerAt: external_exports.number().int().positive().optional(),
|
|
4270
|
+
/**
|
|
4271
|
+
* 对方 daemon owner 的 displayName,guest auth 帧 selfDisplayName 触发
|
|
4272
|
+
* recordPeerHello 时同步回写。视角 B (2026-05-23) UI 派生联系人列表用此字段
|
|
4273
|
+
* 显示对方名字(避免 fallback 到我颁 cap 时填的 displayName)。
|
|
4274
|
+
*/
|
|
4275
|
+
peerDisplayName: external_exports.string().optional()
|
|
4617
4276
|
}).strict();
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4277
|
+
CapabilityWireSchema = CapabilitySchema.omit({ secretHash: true });
|
|
4278
|
+
WhoamiResponseSchema = external_exports.object({
|
|
4279
|
+
type: external_exports.literal("whoami:ok"),
|
|
4280
|
+
owner: external_exports.object({
|
|
4281
|
+
id: external_exports.string(),
|
|
4282
|
+
kind: external_exports.enum(["owner", "guest"]),
|
|
4283
|
+
displayName: external_exports.string(),
|
|
4284
|
+
/** 归属人 id(决策 #16:TTC unique_id 等,落 contact.ownerId) */
|
|
4285
|
+
ownerId: external_exports.string(),
|
|
4286
|
+
/** 身份来源(决策 #16:'ttc'/'google',落 contact.provider) */
|
|
4287
|
+
provider: external_exports.string()
|
|
4288
|
+
}).strict(),
|
|
4289
|
+
capability: CapabilityWireSchema,
|
|
4290
|
+
grantedPersonas: external_exports.array(
|
|
4291
|
+
external_exports.object({
|
|
4292
|
+
id: external_exports.string().min(1),
|
|
4293
|
+
displayName: external_exports.string()
|
|
4294
|
+
}).strict()
|
|
4295
|
+
)
|
|
4296
|
+
}).strict();
|
|
4297
|
+
PERSONAL_CAP_GRANTS = Object.freeze([
|
|
4298
|
+
Object.freeze({
|
|
4299
|
+
resource: Object.freeze({ type: "persona", id: "*" }),
|
|
4300
|
+
actions: Object.freeze(["read", "send"])
|
|
4301
|
+
})
|
|
4302
|
+
]);
|
|
4303
|
+
}
|
|
4304
|
+
});
|
|
4305
|
+
|
|
4306
|
+
// ../protocol/src/contact-handshake.ts
|
|
4307
|
+
var ContactHandshakeArgsSchema, ContactHandshakeOkSchema;
|
|
4308
|
+
var init_contact_handshake = __esm({
|
|
4309
|
+
"../protocol/src/contact-handshake.ts"() {
|
|
4310
|
+
"use strict";
|
|
4311
|
+
init_zod();
|
|
4312
|
+
init_capability();
|
|
4313
|
+
ContactHandshakeArgsSchema = external_exports.object({
|
|
4314
|
+
selfUrl: external_exports.string().min(1)
|
|
4315
|
+
});
|
|
4316
|
+
ContactHandshakeOkSchema = external_exports.object({
|
|
4317
|
+
type: external_exports.literal("contact:handshake:ok"),
|
|
4318
|
+
owner: external_exports.object({
|
|
4319
|
+
/** 被调方 deviceId(路由主键;调用方落 Contact 的主键用自己请求的 args.deviceId,此值供校验/展示) */
|
|
4320
|
+
id: external_exports.string(),
|
|
4321
|
+
/** 归属人(落 Contact.ownerId / provider,显示分组用) */
|
|
4322
|
+
ownerId: external_exports.string(),
|
|
4323
|
+
provider: external_exports.string(),
|
|
4324
|
+
displayName: external_exports.string()
|
|
4325
|
+
}),
|
|
4326
|
+
/** 被调方授调用方的 grants(落 Contact.grants) */
|
|
4327
|
+
grants: external_exports.array(GrantSchema)
|
|
4328
|
+
});
|
|
4329
|
+
}
|
|
4330
|
+
});
|
|
4331
|
+
|
|
4332
|
+
// ../protocol/src/contact-remote-access.ts
|
|
4333
|
+
var ContactSetRemoteAccessArgsSchema, ContactSetRemoteAccessOkSchema, ContactRemoteAccessUpdatedFrameSchema;
|
|
4334
|
+
var init_contact_remote_access = __esm({
|
|
4335
|
+
"../protocol/src/contact-remote-access.ts"() {
|
|
4336
|
+
"use strict";
|
|
4337
|
+
init_zod();
|
|
4338
|
+
ContactSetRemoteAccessArgsSchema = external_exports.object({
|
|
4339
|
+
deviceId: external_exports.string().min(1),
|
|
4340
|
+
remoteAccessAllowed: external_exports.boolean()
|
|
4341
|
+
}).strict();
|
|
4342
|
+
ContactSetRemoteAccessOkSchema = external_exports.object({
|
|
4343
|
+
type: external_exports.literal("contact:setRemoteAccess:ok"),
|
|
4344
|
+
deviceId: external_exports.string().min(1),
|
|
4345
|
+
remoteAccessAllowed: external_exports.boolean()
|
|
4346
|
+
}).strict();
|
|
4347
|
+
ContactRemoteAccessUpdatedFrameSchema = external_exports.object({
|
|
4348
|
+
type: external_exports.literal("contact:remote-access-updated"),
|
|
4349
|
+
deviceId: external_exports.string().min(1),
|
|
4350
|
+
remoteAccessAllowed: external_exports.boolean()
|
|
4351
|
+
}).strict();
|
|
4352
|
+
}
|
|
4353
|
+
});
|
|
4354
|
+
|
|
4355
|
+
// ../protocol/src/contact.ts
|
|
4356
|
+
var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema, ContactPinArgsSchema, ContactPinOkSchema, ContactPinnedFrameSchema;
|
|
4357
|
+
var init_contact = __esm({
|
|
4358
|
+
"../protocol/src/contact.ts"() {
|
|
4359
|
+
"use strict";
|
|
4360
|
+
init_zod();
|
|
4361
|
+
init_capability();
|
|
4362
|
+
ContactSchema = external_exports.object({
|
|
4363
|
+
/**
|
|
4364
|
+
* 对方设备标识(主键):对方 daemon 自己生成并持久化的标识(auth.json deviceId,
|
|
4365
|
+
* 如 dev-<uuid>),provider 无关。同 deviceId 重复 upsert 覆盖。
|
|
4366
|
+
*/
|
|
4367
|
+
deviceId: external_exports.string().min(1),
|
|
4368
|
+
/**
|
|
4369
|
+
* 归属人 id(决策 #16):TTC unique_id 等,由 connect token subOwner 签名背书。
|
|
4370
|
+
* 与 provider 一起唯一标识一个人。DM 不再按它路由(路由用 deviceId),仅显示/分组用。
|
|
4371
|
+
*/
|
|
4372
|
+
ownerId: external_exports.string().min(1),
|
|
4373
|
+
/** 身份来源(决策 #16):'ttc'(飞书/手机/邮箱登入 TTC)| 'google' | ...,token 背书 */
|
|
4374
|
+
provider: external_exports.string().min(1),
|
|
4375
|
+
/** 联系人显示名 */
|
|
4621
4376
|
displayName: external_exports.string(),
|
|
4622
|
-
/**
|
|
4623
|
-
|
|
4624
|
-
|
|
4377
|
+
/** 该设备可达的 ws/tunnel 地址 */
|
|
4378
|
+
remoteUrl: external_exports.string().min(1),
|
|
4379
|
+
// 自动反向建立联系人(spec 决策 #11):被连接方本地验票成功后自动落 A 为
|
|
4380
|
+
// 联系人,但它不持有 A 颁发的 token(A 从未给它换票)→ connectToken 为空串。
|
|
4381
|
+
// device:connect 出站路径仍存中心 server 签发的真实 connect token(断线重连复用)。
|
|
4382
|
+
// 不用 .min(1):自动反向路径合法地存空串,禁止填假 token 占位(不造假数据)。
|
|
4383
|
+
connectToken: external_exports.string(),
|
|
4384
|
+
grants: external_exports.array(GrantSchema),
|
|
4385
|
+
addedAt: external_exports.number().int().nonnegative(),
|
|
4386
|
+
/**
|
|
4387
|
+
* pin 时间戳(ms,Date.now() 语义);null = 未 pin。sidebar 顶部固定区渲染由此驱动。
|
|
4388
|
+
* 老 contacts.json 缺此字段 → zod default 补 null(无破坏性升级;不 orphan)。
|
|
4389
|
+
* 对齐 SessionFile.pinnedAt 语义(daemon 侧持久化,contact:pin RPC 更新 → contact:pinned push)。
|
|
4390
|
+
*/
|
|
4391
|
+
pinnedAt: external_exports.number().int().nullable().default(null),
|
|
4392
|
+
/**
|
|
4393
|
+
* 远程访问授权(spec 2026-07-16)。owner 视角:允许该 contact 反向操作我的设备——
|
|
4394
|
+
* 跨设备 exec 的总开关(peerExec:run handler 运行时判它)。default=false,owner 显式开。
|
|
4395
|
+
* 授权粒度 per-people (per-contact):借用别人 persona 本来就带信任对方本人的前提。
|
|
4396
|
+
*/
|
|
4397
|
+
remoteAccessAllowed: external_exports.boolean().default(false)
|
|
4398
|
+
}).strict();
|
|
4399
|
+
ContactWireSchema = ContactSchema;
|
|
4400
|
+
ContactRemoveArgsSchema = external_exports.object({
|
|
4401
|
+
deviceId: external_exports.string().min(1)
|
|
4402
|
+
}).strict();
|
|
4403
|
+
ContactRemoveOkSchema = external_exports.object({
|
|
4404
|
+
type: external_exports.literal("contact:remove:ok"),
|
|
4405
|
+
deviceId: external_exports.string().min(1)
|
|
4406
|
+
}).strict();
|
|
4407
|
+
ContactListOkSchema = external_exports.object({
|
|
4408
|
+
type: external_exports.literal("contact:list:ok"),
|
|
4409
|
+
contacts: external_exports.array(ContactWireSchema)
|
|
4410
|
+
}).strict();
|
|
4411
|
+
ContactAddedFrameSchema = external_exports.object({
|
|
4412
|
+
type: external_exports.literal("contact:added"),
|
|
4413
|
+
contact: ContactWireSchema
|
|
4414
|
+
}).strict();
|
|
4415
|
+
ContactRemovedFrameSchema = external_exports.object({
|
|
4416
|
+
type: external_exports.literal("contact:removed"),
|
|
4417
|
+
deviceId: external_exports.string().min(1)
|
|
4418
|
+
}).strict();
|
|
4419
|
+
ContactPinArgsSchema = external_exports.object({
|
|
4420
|
+
deviceId: external_exports.string().min(1),
|
|
4421
|
+
pinned: external_exports.boolean()
|
|
4422
|
+
}).strict();
|
|
4423
|
+
ContactPinOkSchema = external_exports.object({
|
|
4424
|
+
type: external_exports.literal("contact:pin:ok"),
|
|
4425
|
+
deviceId: external_exports.string().min(1),
|
|
4426
|
+
pinnedAt: external_exports.number().int().nullable()
|
|
4427
|
+
}).strict();
|
|
4428
|
+
ContactPinnedFrameSchema = external_exports.object({
|
|
4429
|
+
type: external_exports.literal("contact:pinned"),
|
|
4430
|
+
deviceId: external_exports.string().min(1),
|
|
4431
|
+
pinnedAt: external_exports.number().int().nullable()
|
|
4432
|
+
}).strict();
|
|
4433
|
+
}
|
|
4434
|
+
});
|
|
4435
|
+
|
|
4436
|
+
// ../protocol/src/feishu-auth.ts
|
|
4437
|
+
var FEISHU_GATED_METHODS, DeviceEntrySchema, DeviceListResponseSchema, DeviceConnectArgsSchema, DeviceConnectResponseSchema, FeishuIdentitySchema, AuthLoginStartResponseSchema, AuthGetIdentityResponseSchema, AuthLogoutResponseSchema, AuthLoginDoneEventSchema, AuthLoginFailedEventSchema;
|
|
4438
|
+
var init_feishu_auth = __esm({
|
|
4439
|
+
"../protocol/src/feishu-auth.ts"() {
|
|
4440
|
+
"use strict";
|
|
4441
|
+
init_zod();
|
|
4442
|
+
FEISHU_GATED_METHODS = [
|
|
4443
|
+
// 联系人列表(device:connect 落同一 store;list 读 / remove 删)
|
|
4444
|
+
"contact:list",
|
|
4445
|
+
"contact:remove",
|
|
4446
|
+
// DM / 跨用户通知
|
|
4447
|
+
"inbox:list",
|
|
4448
|
+
"inbox:markRead",
|
|
4449
|
+
"inbox:postMessage",
|
|
4450
|
+
// mirror peer sessions(远端会话镜像)
|
|
4451
|
+
"peerSession:upsert",
|
|
4452
|
+
"peerSession:remove",
|
|
4453
|
+
// 设备目录 + 连接(决策 #15:daemon 代理中心 server,需要 owner 的 ttcJwt)
|
|
4454
|
+
"device:list",
|
|
4455
|
+
"device:connect"
|
|
4456
|
+
];
|
|
4457
|
+
DeviceEntrySchema = external_exports.object({
|
|
4458
|
+
/**
|
|
4459
|
+
* 设备标识(决策 #15:daemon 本地生成的 dev-<uuid>,与人的身份 unionId 无关)。
|
|
4460
|
+
* 中心 server clawd_devices 注册表仅作服务发现(url 下发 + 目录),不在安全路径上。
|
|
4461
|
+
*/
|
|
4462
|
+
deviceId: external_exports.string().min(1),
|
|
4463
|
+
/** 显示名 */
|
|
4464
|
+
name: external_exports.string().min(1),
|
|
4465
|
+
/** ws/tunnel 地址 */
|
|
4466
|
+
url: external_exports.string().min(1)
|
|
4467
|
+
});
|
|
4468
|
+
DeviceListResponseSchema = external_exports.object({
|
|
4469
|
+
type: external_exports.literal("device:list:ok"),
|
|
4470
|
+
devices: external_exports.array(DeviceEntrySchema)
|
|
4471
|
+
});
|
|
4472
|
+
DeviceConnectArgsSchema = external_exports.object({
|
|
4473
|
+
/** 目标设备的 deviceId(对方 daemon 生成的 dev-<uuid>) */
|
|
4474
|
+
deviceId: external_exports.string().min(1),
|
|
4475
|
+
/**
|
|
4476
|
+
* 目标设备的 ws/tunnel 地址(可选):
|
|
4477
|
+
* - 公开目录点击:带 url(device:list 已下发,省一次 server 查询)
|
|
4478
|
+
* - 凭 deviceId 连接:缺省 url → daemon exchange 时由中心 server 下发该设备上报的 url
|
|
4479
|
+
* - 注册表不在安全路径上:知道对方 url 时显式传入即可连接(不依赖中心 server 服务发现)
|
|
4480
|
+
*/
|
|
4481
|
+
url: external_exports.string().min(1).optional(),
|
|
4482
|
+
/** 显示名(公共设备来自目录;缺省时连上后用 whoami 回填) */
|
|
4483
|
+
name: external_exports.string().optional()
|
|
4484
|
+
});
|
|
4485
|
+
DeviceConnectResponseSchema = external_exports.object({
|
|
4486
|
+
type: external_exports.literal("device:connect:ok"),
|
|
4487
|
+
/** 连接的目标设备标识(= 请求 args.deviceId) */
|
|
4488
|
+
deviceId: external_exports.string(),
|
|
4489
|
+
name: external_exports.string(),
|
|
4490
|
+
url: external_exports.string()
|
|
4491
|
+
});
|
|
4492
|
+
FeishuIdentitySchema = external_exports.object({
|
|
4493
|
+
/** 归属人 id(决策 #16:TTC unique_id,取代飞书 union_id;跨登录方式稳定) */
|
|
4494
|
+
ownerId: external_exports.string().min(1),
|
|
4495
|
+
/** 身份来源:'ttc'(飞书/手机/邮箱登入 TTC)| 'google' | ...(决策 #16,拓展用) */
|
|
4496
|
+
provider: external_exports.string().min(1),
|
|
4497
|
+
/** 显示名。TTC user_info 接口 data.name */
|
|
4498
|
+
displayName: external_exports.string().min(1),
|
|
4499
|
+
/** TTC user_info 接口 data.avatar_url,可缺省 */
|
|
4500
|
+
avatarUrl: external_exports.string().optional(),
|
|
4501
|
+
/** TTC user_info 接口 data.union_id(飞书 union_id;dataclaw 可信入口 X-User-UnionId 用),可缺省 */
|
|
4502
|
+
unionId: external_exports.string().optional()
|
|
4503
|
+
});
|
|
4504
|
+
AuthLoginStartResponseSchema = external_exports.object({
|
|
4505
|
+
type: external_exports.literal("auth:login:start:ok"),
|
|
4506
|
+
/** 完整 TTC 授权页 URL(含 callback_url + state + auto=1),UI 直接 window.open */
|
|
4507
|
+
authUrl: external_exports.string().min(1),
|
|
4508
|
+
/** 防 CSRF 的一次性 nonce;回调时 daemon 校验 */
|
|
4509
|
+
state: external_exports.string().min(1)
|
|
4510
|
+
});
|
|
4511
|
+
AuthGetIdentityResponseSchema = external_exports.object({
|
|
4512
|
+
type: external_exports.literal("auth:getIdentity:ok"),
|
|
4513
|
+
/** null = 未登录 */
|
|
4514
|
+
identity: FeishuIdentitySchema.nullable(),
|
|
4515
|
+
/**
|
|
4516
|
+
* 本机设备标识(决策 #15:daemon 生成并持久化在 auth.json,如 dev-<uuid>)。
|
|
4517
|
+
* 设备属性,与登录态无关、登录登出不变。UI"我的设备标识"用它拼
|
|
4518
|
+
* clawos://device/<deviceId>(替代旧的 unionId——不再向外暴露人的身份标识)。
|
|
4519
|
+
*/
|
|
4520
|
+
deviceId: external_exports.string().min(1)
|
|
4521
|
+
});
|
|
4522
|
+
AuthLogoutResponseSchema = external_exports.object({
|
|
4523
|
+
type: external_exports.literal("auth:logout:ok")
|
|
4524
|
+
});
|
|
4525
|
+
AuthLoginDoneEventSchema = external_exports.object({
|
|
4526
|
+
type: external_exports.literal("auth:login:done"),
|
|
4527
|
+
identity: FeishuIdentitySchema
|
|
4528
|
+
});
|
|
4529
|
+
AuthLoginFailedEventSchema = external_exports.object({
|
|
4530
|
+
type: external_exports.literal("auth:login:failed"),
|
|
4531
|
+
reason: external_exports.string()
|
|
4532
|
+
});
|
|
4533
|
+
}
|
|
4534
|
+
});
|
|
4535
|
+
|
|
4536
|
+
// ../protocol/src/dispatch.ts
|
|
4537
|
+
var DispatchOutcomeSchema, DispatchRunArgsSchema, DispatchCompleteArgsSchema, DISPATCH_STATUSES, DispatchStatusSchema, DispatchRecordSchema, DispatchListArgsSchema, DispatchListResultSchema, DispatchGetArgsSchema, DispatchGetOkSchema;
|
|
4538
|
+
var init_dispatch = __esm({
|
|
4539
|
+
"../protocol/src/dispatch.ts"() {
|
|
4540
|
+
"use strict";
|
|
4541
|
+
init_zod();
|
|
4542
|
+
DispatchOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
4543
|
+
external_exports.object({
|
|
4544
|
+
kind: external_exports.literal("success"),
|
|
4545
|
+
text: external_exports.string(),
|
|
4546
|
+
filePaths: external_exports.array(external_exports.string()).optional()
|
|
4547
|
+
}),
|
|
4548
|
+
external_exports.object({
|
|
4549
|
+
kind: external_exports.literal("failure"),
|
|
4550
|
+
reason: external_exports.string()
|
|
4551
|
+
})
|
|
4552
|
+
]);
|
|
4553
|
+
DispatchRunArgsSchema = external_exports.object({
|
|
4554
|
+
// 新开必填;续派(dispatchId 非空)时可省略——targetPersonaId 从台账行取。
|
|
4555
|
+
targetPersona: external_exports.string().min(1).optional(),
|
|
4556
|
+
// 续派(spec 2026-07-21,单 dispatchId 语义:一件事一行一 id):非空 = 把 prompt
|
|
4557
|
+
// 作为新 turn 打进该 dispatch 的原 worker session 接着干(台账行复位 running)。
|
|
4558
|
+
// 省略 = 新开一件事,daemon 铸新 id。
|
|
4559
|
+
dispatchId: external_exports.string().min(1).optional(),
|
|
4560
|
+
prompt: external_exports.string(),
|
|
4561
|
+
// 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
|
|
4562
|
+
// 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
|
|
4563
|
+
targetDeviceId: external_exports.string().min(1).optional(),
|
|
4564
|
+
// 可选:override B session 使用的 claude 模型。缺省 = 用 persona 默认。
|
|
4565
|
+
// 合法值集与 claude adapter capabilities.models[].id 一致(见 daemon
|
|
4566
|
+
// tools/claude.ts CLAUDE_MODEL_IDS);handler 层做二次校验,非法值 fail-fast。
|
|
4567
|
+
// protocol 层保持 string 便于未来跨 tool 扩展(届时 union 收合法字面量)。
|
|
4568
|
+
model: external_exports.string().min(1).optional(),
|
|
4569
|
+
// 可选:给新 worker session 起 label(写入 SessionFile.label,sidebar 显示)。
|
|
4570
|
+
// 仅在**新开 dispatch**(dispatchId 缺席)时生效;续派(dispatchId 非空)
|
|
4571
|
+
// 时 daemon 层静默丢弃(避免半途改 label 造成 sidebar 抖动)。
|
|
4572
|
+
// 上限 60 字符——sidebar 显示 tolerance,卡在 dispatch 入口即可。
|
|
4573
|
+
// 协议层不硬拒 sessionLabel + dispatchId 同传,保留 forward-compat。
|
|
4574
|
+
sessionLabel: external_exports.string().min(1).max(60).optional()
|
|
4575
|
+
}).refine((v2) => v2.targetPersona !== void 0 || v2.dispatchId !== void 0, {
|
|
4576
|
+
message: "either targetPersona (new dispatch) or dispatchId (follow-up) is required"
|
|
4577
|
+
}).refine((v2) => !(v2.dispatchId !== void 0 && v2.targetDeviceId !== void 0), {
|
|
4578
|
+
message: "cross-device dispatch cannot be continued (dispatchId + targetDeviceId are mutually exclusive)"
|
|
4579
|
+
});
|
|
4580
|
+
DispatchCompleteArgsSchema = external_exports.object({
|
|
4581
|
+
dispatchId: external_exports.string().min(1),
|
|
4582
|
+
outcome: DispatchOutcomeSchema
|
|
4583
|
+
});
|
|
4584
|
+
DISPATCH_STATUSES = ["running", "completed", "failed"];
|
|
4585
|
+
DispatchStatusSchema = external_exports.enum(DISPATCH_STATUSES);
|
|
4586
|
+
DispatchRecordSchema = external_exports.object({
|
|
4587
|
+
dispatchId: external_exports.string().min(1),
|
|
4588
|
+
sourceSessionId: external_exports.string().min(1),
|
|
4589
|
+
sourcePersonaId: external_exports.string().min(1).optional(),
|
|
4590
|
+
targetPersonaId: external_exports.string().min(1),
|
|
4591
|
+
/** B 的 sessionId;registerBSession 后回填 */
|
|
4592
|
+
workerSessionId: external_exports.string().min(1).optional(),
|
|
4593
|
+
/** 任务摘要;截断(≤500 字符)在 daemon store.add 处保证 */
|
|
4594
|
+
taskText: external_exports.string(),
|
|
4595
|
+
status: DispatchStatusSchema,
|
|
4596
|
+
outcome: DispatchOutcomeSchema.optional(),
|
|
4597
|
+
/** 上层消费者语义(如司礼监的口谕/验收状态),daemon 不解释 */
|
|
4598
|
+
meta: external_exports.record(external_exports.unknown()).optional(),
|
|
4599
|
+
createdAt: external_exports.string().min(1),
|
|
4600
|
+
completedAt: external_exports.string().min(1).optional(),
|
|
4601
|
+
/** 结果注入 source session 成功时戳,兼当投递 dedup 标记 */
|
|
4602
|
+
deliveredAt: external_exports.string().min(1).optional()
|
|
4603
|
+
});
|
|
4604
|
+
DispatchListArgsSchema = external_exports.object({
|
|
4605
|
+
sourceSessionId: external_exports.string().min(1).optional()
|
|
4606
|
+
});
|
|
4607
|
+
DispatchListResultSchema = external_exports.object({
|
|
4608
|
+
records: external_exports.array(DispatchRecordSchema)
|
|
4609
|
+
});
|
|
4610
|
+
DispatchGetArgsSchema = external_exports.object({
|
|
4611
|
+
dispatchId: external_exports.string().min(1)
|
|
4612
|
+
});
|
|
4613
|
+
DispatchGetOkSchema = external_exports.object({
|
|
4614
|
+
type: external_exports.literal("personaDispatch:get:ok"),
|
|
4615
|
+
status: DispatchStatusSchema,
|
|
4616
|
+
outcome: DispatchOutcomeSchema.optional()
|
|
4617
|
+
});
|
|
4618
|
+
}
|
|
4619
|
+
});
|
|
4620
|
+
|
|
4621
|
+
// ../protocol/src/extension.ts
|
|
4622
|
+
function isAllowedHostedUrl(raw) {
|
|
4623
|
+
let u;
|
|
4624
|
+
try {
|
|
4625
|
+
u = new URL(raw);
|
|
4626
|
+
} catch {
|
|
4627
|
+
return false;
|
|
4628
|
+
}
|
|
4629
|
+
if (u.protocol === "https:") return true;
|
|
4630
|
+
if (u.protocol === "http:" && LOCALHOST_HOSTS.has(u.hostname)) return true;
|
|
4631
|
+
return false;
|
|
4632
|
+
}
|
|
4633
|
+
function manifestMode(m2) {
|
|
4634
|
+
return m2.entry?.url ? "hosted" : "local";
|
|
4635
|
+
}
|
|
4636
|
+
function ownerNamespace(ownerPrincipalId) {
|
|
4637
|
+
let h = 2166136261;
|
|
4638
|
+
for (let i = 0; i < ownerPrincipalId.length; i++) {
|
|
4639
|
+
h ^= ownerPrincipalId.charCodeAt(i);
|
|
4640
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
4641
|
+
}
|
|
4642
|
+
return (h >>> 0).toString(16).padStart(8, "0");
|
|
4643
|
+
}
|
|
4644
|
+
function namespacedExtId(slug, ownerPrincipalId) {
|
|
4645
|
+
return `${slug}-${ownerNamespace(ownerPrincipalId)}`;
|
|
4646
|
+
}
|
|
4647
|
+
function validateSimpleSemver(v2) {
|
|
4648
|
+
if (typeof v2 !== "string") {
|
|
4649
|
+
return { ok: false, reason: "version must be a string" };
|
|
4650
|
+
}
|
|
4651
|
+
const parts = v2.split(".");
|
|
4652
|
+
if (parts.length !== 3) {
|
|
4653
|
+
return { ok: false, reason: `"${v2}" \u2014 only MAJOR.MINOR.PATCH allowed` };
|
|
4654
|
+
}
|
|
4655
|
+
for (const p2 of parts) {
|
|
4656
|
+
if (!/^\d+$/.test(p2)) {
|
|
4657
|
+
return { ok: false, reason: `"${v2}" \u2014 only numeric segments allowed` };
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
return { ok: true };
|
|
4661
|
+
}
|
|
4662
|
+
function compareSimpleSemver(a, b2) {
|
|
4663
|
+
const pa = parseOrThrow(a);
|
|
4664
|
+
const pb = parseOrThrow(b2);
|
|
4665
|
+
for (let i = 0; i < 3; i++) {
|
|
4666
|
+
if (pa[i] < pb[i]) return -1;
|
|
4667
|
+
if (pa[i] > pb[i]) return 1;
|
|
4668
|
+
}
|
|
4669
|
+
return 0;
|
|
4670
|
+
}
|
|
4671
|
+
function parseOrThrow(v2) {
|
|
4672
|
+
const r = validateSimpleSemver(v2);
|
|
4673
|
+
if (!r.ok) throw new Error(r.reason);
|
|
4674
|
+
const [a, b2, c] = v2.split(".").map((p2) => parseInt(p2, 10));
|
|
4675
|
+
return [a, b2, c];
|
|
4676
|
+
}
|
|
4677
|
+
var EXT_ID_REGEX, ExtensionStateSchema, LOCALHOST_HOSTS, ExtensionManifestSchema, ExtensionTargetSchema, ExtensionRecordSchema, PublishedSnapshotSchema, ChannelRefSchema, SourceRefSchema, PublishedExtensionRecordSchema, PublishCheckSchema, PublishStatusResultSchema, ExtensionPublishArgs, ExtensionIdArgs, ExtensionFetchBundleArgs, ExtensionFromChannelArgs;
|
|
4678
|
+
var init_extension = __esm({
|
|
4679
|
+
"../protocol/src/extension.ts"() {
|
|
4680
|
+
"use strict";
|
|
4681
|
+
init_zod();
|
|
4682
|
+
EXT_ID_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
4683
|
+
ExtensionStateSchema = external_exports.enum([
|
|
4684
|
+
"stopped",
|
|
4685
|
+
"starting",
|
|
4686
|
+
"running",
|
|
4687
|
+
"crashed",
|
|
4688
|
+
"invalid"
|
|
4689
|
+
]);
|
|
4690
|
+
LOCALHOST_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
4691
|
+
ExtensionManifestSchema = external_exports.object({
|
|
4692
|
+
id: external_exports.string().regex(EXT_ID_REGEX),
|
|
4693
|
+
name: external_exports.string().min(1),
|
|
4694
|
+
version: external_exports.string().min(1),
|
|
4695
|
+
apiVersion: external_exports.literal("1"),
|
|
4696
|
+
runtime: external_exports.object({ startCommand: external_exports.string().min(1) }).passthrough().optional(),
|
|
4697
|
+
entry: external_exports.object({
|
|
4698
|
+
url: external_exports.string().url().refine(isAllowedHostedUrl, {
|
|
4699
|
+
message: "INVALID_URL_SCHEME: only https or http://localhost is allowed"
|
|
4700
|
+
})
|
|
4701
|
+
}).strict().optional()
|
|
4702
|
+
}).passthrough().superRefine((m2, ctx) => {
|
|
4703
|
+
const hasRuntime = !!m2.runtime;
|
|
4704
|
+
const hasUrl = !!m2.entry?.url;
|
|
4705
|
+
if (hasRuntime && hasUrl) {
|
|
4706
|
+
ctx.addIssue({
|
|
4707
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4708
|
+
message: "INVALID_MANIFEST: entry.url and runtime cannot coexist"
|
|
4709
|
+
});
|
|
4710
|
+
}
|
|
4711
|
+
if (!hasRuntime && !hasUrl) {
|
|
4712
|
+
ctx.addIssue({
|
|
4713
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4714
|
+
message: "INVALID_MANIFEST: must have either entry.url or runtime"
|
|
4715
|
+
});
|
|
4716
|
+
}
|
|
4717
|
+
});
|
|
4718
|
+
ExtensionTargetSchema = external_exports.discriminatedUnion("kind", [
|
|
4719
|
+
external_exports.object({ kind: external_exports.literal("local"), port: external_exports.number().int().min(1).max(65535) }),
|
|
4720
|
+
external_exports.object({ kind: external_exports.literal("hosted"), url: external_exports.string().url() })
|
|
4721
|
+
]);
|
|
4722
|
+
ExtensionRecordSchema = external_exports.discriminatedUnion("state", [
|
|
4723
|
+
external_exports.object({
|
|
4724
|
+
extId: external_exports.string(),
|
|
4725
|
+
manifest: ExtensionManifestSchema,
|
|
4726
|
+
state: external_exports.literal("stopped")
|
|
4727
|
+
}),
|
|
4728
|
+
external_exports.object({
|
|
4729
|
+
extId: external_exports.string(),
|
|
4730
|
+
manifest: ExtensionManifestSchema,
|
|
4731
|
+
state: external_exports.literal("starting")
|
|
4732
|
+
}),
|
|
4733
|
+
external_exports.object({
|
|
4734
|
+
extId: external_exports.string(),
|
|
4735
|
+
manifest: ExtensionManifestSchema,
|
|
4736
|
+
state: external_exports.literal("running"),
|
|
4737
|
+
target: ExtensionTargetSchema
|
|
4738
|
+
}),
|
|
4739
|
+
external_exports.object({
|
|
4740
|
+
extId: external_exports.string(),
|
|
4741
|
+
manifest: ExtensionManifestSchema,
|
|
4742
|
+
state: external_exports.literal("crashed")
|
|
4743
|
+
}),
|
|
4744
|
+
external_exports.object({
|
|
4745
|
+
extId: external_exports.string(),
|
|
4746
|
+
manifest: external_exports.unknown().nullable(),
|
|
4747
|
+
state: external_exports.literal("invalid"),
|
|
4748
|
+
invalidReason: external_exports.string().min(1)
|
|
4749
|
+
})
|
|
4750
|
+
]);
|
|
4751
|
+
PublishedSnapshotSchema = external_exports.object({
|
|
4752
|
+
snapshotHash: external_exports.string().min(1),
|
|
4753
|
+
version: external_exports.string().min(1),
|
|
4754
|
+
publishedAt: external_exports.number()
|
|
4755
|
+
});
|
|
4756
|
+
ChannelRefSchema = external_exports.discriminatedUnion("kind", [
|
|
4757
|
+
external_exports.object({
|
|
4758
|
+
kind: external_exports.literal("p2p-tunnel"),
|
|
4759
|
+
ownerPrincipalId: external_exports.string().min(1),
|
|
4760
|
+
extId: external_exports.string().min(1)
|
|
4761
|
+
})
|
|
4762
|
+
]);
|
|
4763
|
+
SourceRefSchema = external_exports.discriminatedUnion("kind", [
|
|
4764
|
+
external_exports.object({
|
|
4765
|
+
kind: external_exports.literal("p2p-tunnel"),
|
|
4766
|
+
ownerPrincipalId: external_exports.string().min(1),
|
|
4767
|
+
extId: external_exports.string().min(1),
|
|
4768
|
+
snapshotHash: external_exports.string().min(1)
|
|
4769
|
+
})
|
|
4770
|
+
]);
|
|
4771
|
+
PublishedExtensionRecordSchema = external_exports.object({
|
|
4772
|
+
extId: external_exports.string().min(1),
|
|
4773
|
+
name: external_exports.string().min(1),
|
|
4774
|
+
version: external_exports.string().min(1),
|
|
4775
|
+
contentHash: external_exports.string().min(1),
|
|
4776
|
+
publishedAt: external_exports.number()
|
|
4777
|
+
});
|
|
4778
|
+
PublishCheckSchema = external_exports.discriminatedUnion("kind", [
|
|
4779
|
+
external_exports.object({ kind: external_exports.literal("clean") }),
|
|
4780
|
+
external_exports.object({
|
|
4781
|
+
kind: external_exports.literal("ready-new-version"),
|
|
4782
|
+
fromVersion: external_exports.string().min(1),
|
|
4783
|
+
toVersion: external_exports.string().min(1)
|
|
4784
|
+
}),
|
|
4785
|
+
external_exports.object({
|
|
4786
|
+
kind: external_exports.literal("error-same-hash"),
|
|
4787
|
+
version: external_exports.string().min(1)
|
|
4788
|
+
}),
|
|
4789
|
+
external_exports.object({
|
|
4790
|
+
kind: external_exports.literal("error-version-not-bumped"),
|
|
4791
|
+
localVersion: external_exports.string().min(1),
|
|
4792
|
+
publishedVersion: external_exports.string().min(1)
|
|
4793
|
+
}),
|
|
4794
|
+
external_exports.object({
|
|
4795
|
+
kind: external_exports.literal("error-version-regression"),
|
|
4796
|
+
localVersion: external_exports.string().min(1),
|
|
4797
|
+
publishedVersion: external_exports.string().min(1)
|
|
4798
|
+
})
|
|
4799
|
+
]);
|
|
4800
|
+
PublishStatusResultSchema = external_exports.object({
|
|
4801
|
+
localManifest: external_exports.object({
|
|
4802
|
+
name: external_exports.string().min(1),
|
|
4803
|
+
version: external_exports.string().min(1),
|
|
4804
|
+
contentHash: external_exports.string().min(1)
|
|
4805
|
+
}),
|
|
4806
|
+
publishState: external_exports.discriminatedUnion("kind", [
|
|
4807
|
+
external_exports.object({ kind: external_exports.literal("unpublished") }),
|
|
4808
|
+
external_exports.object({
|
|
4809
|
+
kind: external_exports.literal("published"),
|
|
4810
|
+
version: external_exports.string().min(1),
|
|
4811
|
+
contentHash: external_exports.string().min(1),
|
|
4812
|
+
publishedAt: external_exports.number()
|
|
4813
|
+
})
|
|
4814
|
+
]),
|
|
4815
|
+
check: PublishCheckSchema
|
|
4816
|
+
});
|
|
4817
|
+
ExtensionPublishArgs = external_exports.object({
|
|
4818
|
+
extId: external_exports.string().min(1),
|
|
4819
|
+
/**
|
|
4820
|
+
* 可选版本号:给了就在 publish-check 之前重写 manifest.json 的 version。
|
|
4821
|
+
* nullish 而非 optional —— 改造前的 pickOptionalString 显式把 null 当「没给」处理,
|
|
4822
|
+
* 换成纯 optional 会让 `newVersion: null` 从「不 bump」变成 INVALID_PARAM。
|
|
4823
|
+
*/
|
|
4824
|
+
newVersion: external_exports.string().min(1).nullish()
|
|
4825
|
+
});
|
|
4826
|
+
ExtensionIdArgs = external_exports.object({
|
|
4827
|
+
extId: external_exports.string().min(1)
|
|
4828
|
+
});
|
|
4829
|
+
ExtensionFetchBundleArgs = external_exports.object({
|
|
4830
|
+
extId: external_exports.string().min(1),
|
|
4831
|
+
snapshotHash: external_exports.string().min(1)
|
|
4832
|
+
});
|
|
4833
|
+
ExtensionFromChannelArgs = external_exports.object({
|
|
4834
|
+
channelRef: ChannelRefSchema,
|
|
4835
|
+
snapshotHash: external_exports.string().min(1),
|
|
4836
|
+
zipBase64: external_exports.string().min(1)
|
|
4837
|
+
});
|
|
4838
|
+
}
|
|
4839
|
+
});
|
|
4840
|
+
|
|
4841
|
+
// ../protocol/src/inbox.ts
|
|
4842
|
+
var InboxMessageSchema, InboxPostMessageArgsSchema, InboxListArgsSchema, InboxMarkReadArgsSchema, InboxSendDmArgsSchema;
|
|
4843
|
+
var init_inbox = __esm({
|
|
4844
|
+
"../protocol/src/inbox.ts"() {
|
|
4845
|
+
"use strict";
|
|
4846
|
+
init_zod();
|
|
4847
|
+
InboxMessageSchema = external_exports.object({
|
|
4848
|
+
id: external_exports.string().min(1),
|
|
4849
|
+
peerDeviceId: external_exports.string().min(1),
|
|
4850
|
+
senderDeviceId: external_exports.string().min(1),
|
|
4851
|
+
text: external_exports.string().min(1),
|
|
4852
|
+
createdAt: external_exports.number().int().nonnegative(),
|
|
4853
|
+
readBy: external_exports.record(external_exports.string().min(1), external_exports.number().int().positive()).default({}),
|
|
4854
|
+
// persona 代发署名(B 版设计):非空 = 该消息由某 persona 代发,非真人手打。
|
|
4855
|
+
// 缺省 = 真人。routing 身份仍看 senderDeviceId;origin 只用于末端 UI 渲染来源。
|
|
4856
|
+
origin: external_exports.object({ kind: external_exports.literal("persona"), personaId: external_exports.string().min(1) }).optional()
|
|
4625
4857
|
}).strict();
|
|
4858
|
+
InboxPostMessageArgsSchema = external_exports.object({
|
|
4859
|
+
peerDeviceId: external_exports.string().min(1).optional(),
|
|
4860
|
+
id: external_exports.string().min(1),
|
|
4861
|
+
text: external_exports.string().min(1),
|
|
4862
|
+
createdAt: external_exports.number().int().nonnegative(),
|
|
4863
|
+
// persona 代发署名(跨 daemon forward 时随远程腿透传;真人发缺省)。
|
|
4864
|
+
origin: external_exports.object({ kind: external_exports.literal("persona"), personaId: external_exports.string().min(1) }).optional()
|
|
4865
|
+
}).strict();
|
|
4866
|
+
InboxListArgsSchema = external_exports.object({
|
|
4867
|
+
peerDeviceId: external_exports.string().min(1),
|
|
4868
|
+
sinceCreatedAt: external_exports.number().int().nonnegative().optional()
|
|
4869
|
+
}).strict();
|
|
4870
|
+
InboxMarkReadArgsSchema = external_exports.object({
|
|
4871
|
+
peerDeviceId: external_exports.string().min(1),
|
|
4872
|
+
upToCreatedAt: external_exports.number().int().nonnegative()
|
|
4873
|
+
}).strict();
|
|
4874
|
+
InboxSendDmArgsSchema = external_exports.object({
|
|
4875
|
+
peerDeviceId: external_exports.string().min(1).optional(),
|
|
4876
|
+
text: external_exports.string().min(1)
|
|
4877
|
+
});
|
|
4878
|
+
}
|
|
4879
|
+
});
|
|
4880
|
+
|
|
4881
|
+
// ../protocol/src/peer-exec.ts
|
|
4882
|
+
var PeerExecRunArgsSchema, PeerExecRunOkSchema;
|
|
4883
|
+
var init_peer_exec = __esm({
|
|
4884
|
+
"../protocol/src/peer-exec.ts"() {
|
|
4885
|
+
"use strict";
|
|
4886
|
+
init_zod();
|
|
4887
|
+
PeerExecRunArgsSchema = external_exports.object({
|
|
4888
|
+
/** A 侧发起时带:目标设备 deviceId。peer-forward 转发前 strip 掉,B 侧本地执行时无此字段。 */
|
|
4889
|
+
peerDeviceId: external_exports.string().min(1).optional(),
|
|
4890
|
+
/** 交给对端 `bash -c` 的命令;cc 自拼完整路径(一发一收,无跨命令会话状态)。 */
|
|
4891
|
+
command: external_exports.string().min(1),
|
|
4892
|
+
/** 超时上限(ms);缺省用 handler 默认 30_000,clamp 300_000。 */
|
|
4893
|
+
timeoutMs: external_exports.number().int().positive().optional()
|
|
4894
|
+
}).strict();
|
|
4895
|
+
PeerExecRunOkSchema = external_exports.object({
|
|
4896
|
+
type: external_exports.literal("peerExec:run:ok"),
|
|
4897
|
+
stdout: external_exports.string(),
|
|
4898
|
+
stderr: external_exports.string(),
|
|
4899
|
+
/** 进程退出码;被超时 kill 时 null。 */
|
|
4900
|
+
exitCode: external_exports.number().int().nullable(),
|
|
4901
|
+
timedOut: external_exports.boolean(),
|
|
4902
|
+
stdoutTruncated: external_exports.boolean(),
|
|
4903
|
+
stderrTruncated: external_exports.boolean()
|
|
4904
|
+
}).strict();
|
|
4905
|
+
}
|
|
4906
|
+
});
|
|
4907
|
+
|
|
4908
|
+
// ../protocol/src/shift-internal.ts
|
|
4909
|
+
var ShiftScheduleSchema, personaId, ShiftInternalAddArgs, ShiftInternalListArgs, ShiftInternalCancelArgs, ShiftPatchSchema, ShiftInternalUpdateArgs, ShiftInternalHistoryArgs;
|
|
4910
|
+
var init_shift_internal = __esm({
|
|
4911
|
+
"../protocol/src/shift-internal.ts"() {
|
|
4912
|
+
"use strict";
|
|
4913
|
+
init_zod();
|
|
4914
|
+
ShiftScheduleSchema = external_exports.discriminatedUnion("kind", [
|
|
4915
|
+
/** ISO-8601 时间点;时区随字符串自带 */
|
|
4916
|
+
external_exports.object({ kind: external_exports.literal("at"), at: external_exports.string().min(1) }),
|
|
4917
|
+
/** 固定间隔;anchorMs 缺省 = 从登记时刻起算 */
|
|
4918
|
+
external_exports.object({
|
|
4919
|
+
kind: external_exports.literal("every"),
|
|
4920
|
+
everyMs: external_exports.number().int().positive(),
|
|
4921
|
+
anchorMs: external_exports.number().int().nonnegative().optional()
|
|
4922
|
+
}),
|
|
4923
|
+
/** 5 字段 cron 表达式;tz 缺省 = 系统本地时区 */
|
|
4924
|
+
external_exports.object({ kind: external_exports.literal("cron"), expr: external_exports.string().min(1), tz: external_exports.string().min(1).optional() })
|
|
4925
|
+
]);
|
|
4926
|
+
personaId = external_exports.string().trim().min(1);
|
|
4927
|
+
ShiftInternalAddArgs = external_exports.object({
|
|
4928
|
+
personaId,
|
|
4929
|
+
name: external_exports.string().min(1),
|
|
4930
|
+
schedule: ShiftScheduleSchema,
|
|
4931
|
+
prompt: external_exports.string().min(1),
|
|
4932
|
+
/** 缺省 = 派给调用方自己 */
|
|
4933
|
+
targetPersona: external_exports.string().min(1).optional(),
|
|
4934
|
+
timeoutMs: external_exports.number().int().positive().optional()
|
|
4935
|
+
});
|
|
4936
|
+
ShiftInternalListArgs = external_exports.object({
|
|
4937
|
+
personaId,
|
|
4938
|
+
/** 缺省 true —— 只列本 persona 建的 */
|
|
4939
|
+
onlyMine: external_exports.boolean().optional()
|
|
4940
|
+
});
|
|
4941
|
+
ShiftInternalCancelArgs = external_exports.object({
|
|
4942
|
+
personaId,
|
|
4943
|
+
shiftId: external_exports.string().min(1)
|
|
4944
|
+
});
|
|
4945
|
+
ShiftPatchSchema = external_exports.object({
|
|
4946
|
+
name: external_exports.string().min(1).optional(),
|
|
4947
|
+
schedule: ShiftScheduleSchema.optional(),
|
|
4948
|
+
prompt: external_exports.string().min(1).optional(),
|
|
4949
|
+
targetPersona: external_exports.string().min(1).optional(),
|
|
4950
|
+
timeoutMs: external_exports.number().int().positive().optional(),
|
|
4951
|
+
enabled: external_exports.boolean().optional()
|
|
4952
|
+
});
|
|
4953
|
+
ShiftInternalUpdateArgs = external_exports.object({
|
|
4954
|
+
personaId,
|
|
4955
|
+
shiftId: external_exports.string().min(1),
|
|
4956
|
+
patch: ShiftPatchSchema
|
|
4957
|
+
});
|
|
4958
|
+
ShiftInternalHistoryArgs = external_exports.object({
|
|
4959
|
+
personaId,
|
|
4960
|
+
shiftId: external_exports.string().min(1),
|
|
4961
|
+
limit: external_exports.number().int().positive().optional()
|
|
4962
|
+
});
|
|
4626
4963
|
}
|
|
4627
4964
|
});
|
|
4628
4965
|
|
|
@@ -4726,8 +5063,97 @@ var init_persona_schemas = __esm({
|
|
|
4726
5063
|
}
|
|
4727
5064
|
});
|
|
4728
5065
|
|
|
5066
|
+
// ../protocol/src/events.ts
|
|
5067
|
+
var DAEMON_MODE_VALUES, SESSION_STATUS_VALUES, HISTORY_USER_META_VALUES, SKILL_SOURCE_VALUES, AGENT_SOURCE_VALUES, ASK_USER_QUESTION_TOOL_NAME;
|
|
5068
|
+
var init_events = __esm({
|
|
5069
|
+
"../protocol/src/events.ts"() {
|
|
5070
|
+
"use strict";
|
|
5071
|
+
DAEMON_MODE_VALUES = ["sdk", "tui"];
|
|
5072
|
+
SESSION_STATUS_VALUES = [
|
|
5073
|
+
"idle",
|
|
5074
|
+
"running",
|
|
5075
|
+
"running-idle",
|
|
5076
|
+
"stopped",
|
|
5077
|
+
"error",
|
|
5078
|
+
"observing"
|
|
5079
|
+
];
|
|
5080
|
+
HISTORY_USER_META_VALUES = [
|
|
5081
|
+
"task-notification",
|
|
5082
|
+
"slash-command",
|
|
5083
|
+
"local-command",
|
|
5084
|
+
"system-reminder",
|
|
5085
|
+
"skill-hint",
|
|
5086
|
+
"meta-text",
|
|
5087
|
+
"attachment-skills",
|
|
5088
|
+
"attachment-deferred-tools"
|
|
5089
|
+
];
|
|
5090
|
+
SKILL_SOURCE_VALUES = ["builtin", "global", "project", "plugin"];
|
|
5091
|
+
AGENT_SOURCE_VALUES = [
|
|
5092
|
+
"builtin",
|
|
5093
|
+
"global",
|
|
5094
|
+
"project",
|
|
5095
|
+
"policy",
|
|
5096
|
+
"plugin"
|
|
5097
|
+
];
|
|
5098
|
+
ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
|
|
5099
|
+
}
|
|
5100
|
+
});
|
|
5101
|
+
|
|
5102
|
+
// ../protocol/src/principal.ts
|
|
5103
|
+
function makeOwnerPrincipal(id, displayName, feishuUnionId) {
|
|
5104
|
+
return PrincipalSchema.parse({
|
|
5105
|
+
id,
|
|
5106
|
+
kind: "owner",
|
|
5107
|
+
displayName,
|
|
5108
|
+
...feishuUnionId ? { feishuUnionId } : {}
|
|
5109
|
+
});
|
|
5110
|
+
}
|
|
5111
|
+
function principalToSender(p2) {
|
|
5112
|
+
return {
|
|
5113
|
+
did: p2.id,
|
|
5114
|
+
displayName: p2.displayName,
|
|
5115
|
+
principal: p2.kind,
|
|
5116
|
+
...p2.feishuUnionId ? { feishuUnionId: p2.feishuUnionId } : {}
|
|
5117
|
+
};
|
|
5118
|
+
}
|
|
5119
|
+
function makeGuestSender(did, displayName, feishuUnionId) {
|
|
5120
|
+
return SenderInfoSchema.parse({
|
|
5121
|
+
did,
|
|
5122
|
+
displayName,
|
|
5123
|
+
principal: "guest",
|
|
5124
|
+
...feishuUnionId ? { feishuUnionId } : {}
|
|
5125
|
+
});
|
|
5126
|
+
}
|
|
5127
|
+
var PrincipalKindSchema, PrincipalSchema, SenderInfoSchema;
|
|
5128
|
+
var init_principal = __esm({
|
|
5129
|
+
"../protocol/src/principal.ts"() {
|
|
5130
|
+
"use strict";
|
|
5131
|
+
init_zod();
|
|
5132
|
+
PrincipalKindSchema = external_exports.enum(["owner", "guest"]);
|
|
5133
|
+
PrincipalSchema = external_exports.object({
|
|
5134
|
+
id: external_exports.string().min(1),
|
|
5135
|
+
kind: PrincipalKindSchema,
|
|
5136
|
+
displayName: external_exports.string(),
|
|
5137
|
+
/**
|
|
5138
|
+
* 飞书 union_id。owner: 本机 daemon 已飞书登录时透传自 owner-identity.json;未登录 undefined。
|
|
5139
|
+
* guest: v1 保持 undefined(connect token 当前不携带 unionId;未来若签名 payload 加字段可透传)。
|
|
5140
|
+
* 消费方(如 ticket MCP / 未来别的飞书身份挂钩场景)按 undefined 决定是否降级;本层不做 fallback。
|
|
5141
|
+
*/
|
|
5142
|
+
feishuUnionId: external_exports.string().optional()
|
|
5143
|
+
}).strict();
|
|
5144
|
+
SenderInfoSchema = external_exports.object({
|
|
5145
|
+
/** = principal.id = deviceId(决策 #16)。稳定路由 id */
|
|
5146
|
+
did: external_exports.string().min(1),
|
|
5147
|
+
displayName: external_exports.string(),
|
|
5148
|
+
/** owner 未登录 / guest 无飞书身份时缺省。消费方各自决定是否降级 */
|
|
5149
|
+
feishuUnionId: external_exports.string().optional(),
|
|
5150
|
+
principal: PrincipalKindSchema
|
|
5151
|
+
}).strict();
|
|
5152
|
+
}
|
|
5153
|
+
});
|
|
5154
|
+
|
|
4729
5155
|
// ../protocol/src/schemas.ts
|
|
4730
|
-
var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
|
|
5156
|
+
var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionInterruptArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
|
|
4731
5157
|
var init_schemas = __esm({
|
|
4732
5158
|
"../protocol/src/schemas.ts"() {
|
|
4733
5159
|
"use strict";
|
|
@@ -5214,6 +5640,7 @@ var init_schemas = __esm({
|
|
|
5214
5640
|
sessionId: external_exports.string().min(1),
|
|
5215
5641
|
text: external_exports.string()
|
|
5216
5642
|
});
|
|
5643
|
+
SessionInterruptArgs = SessionIdArgs;
|
|
5217
5644
|
SessionRewindArgs = external_exports.object({
|
|
5218
5645
|
sessionId: external_exports.string().min(1),
|
|
5219
5646
|
userMessageId: external_exports.string().min(1),
|
|
@@ -5344,7 +5771,12 @@ var init_schemas = __esm({
|
|
|
5344
5771
|
AgentsListResponseSchema = external_exports.object({
|
|
5345
5772
|
agents: external_exports.array(AgentEntrySchema)
|
|
5346
5773
|
});
|
|
5347
|
-
|
|
5774
|
+
SessionCurrentTurnSenderArgs = external_exports.object({
|
|
5775
|
+
// 刻意不加 .min(1):空串是被依赖的软路径(handler 见空即返 sender:null,
|
|
5776
|
+
// session-current-turn-sender.spec 有用例守着)。加了 min 会把它变成硬报错。
|
|
5777
|
+
sessionId: external_exports.string().optional()
|
|
5778
|
+
});
|
|
5779
|
+
SessionSubscribeArgs = external_exports.object({ sessionId: external_exports.string().min(1).optional() });
|
|
5348
5780
|
SessionPinArgs = external_exports.object({
|
|
5349
5781
|
sessionId: external_exports.string().min(1),
|
|
5350
5782
|
pinned: external_exports.boolean()
|
|
@@ -5583,7 +6015,9 @@ var init_schemas = __esm({
|
|
|
5583
6015
|
CreateProjectArgsSchema = external_exports.object({
|
|
5584
6016
|
/** 必填:caller session,daemon 自动绑过去(spec 2026-06-02 §3 invariant 1 Session ↔ 1 Project) */
|
|
5585
6017
|
sessionId: external_exports.string().min(1),
|
|
5586
|
-
|
|
6018
|
+
// .min(1):改造前手写校验是 `!f.name` 明确拒空串;空 name 会让 projectDir('')
|
|
6019
|
+
// 落到 projects 根目录,scaffold 往根上铺模板。
|
|
6020
|
+
name: external_exports.string().min(1)
|
|
5587
6021
|
}).strict();
|
|
5588
6022
|
CreateProjectResultSchema = external_exports.object({
|
|
5589
6023
|
project: ProjectMetadataSchema
|
|
@@ -5650,690 +6084,564 @@ var init_schemas = __esm({
|
|
|
5650
6084
|
name: external_exports.string().regex(projectNameRegex)
|
|
5651
6085
|
});
|
|
5652
6086
|
DismissPublishJobResultSchema = external_exports.object({
|
|
5653
|
-
ok: external_exports.literal(true)
|
|
5654
|
-
}).strict();
|
|
5655
|
-
AppBuilderPublishProgressEventSchema = external_exports.object({
|
|
5656
|
-
type: external_exports.literal("appBuilder:publish-progress"),
|
|
5657
|
-
name: external_exports.string().regex(projectNameRegex),
|
|
5658
|
-
jobId: external_exports.string().min(1),
|
|
5659
|
-
stage: external_exports.enum(["build", "deploy", "verify"]),
|
|
5660
|
-
status: external_exports.enum(["started", "completed"])
|
|
5661
|
-
}).strict();
|
|
5662
|
-
AppBuilderPublishFailedEventSchema = external_exports.object({
|
|
5663
|
-
type: external_exports.literal("appBuilder:publish-failed"),
|
|
5664
|
-
name: external_exports.string().regex(projectNameRegex),
|
|
5665
|
-
jobId: external_exports.string().min(1),
|
|
5666
|
-
stage: external_exports.enum(["build", "deploy", "verify", "unknown"]),
|
|
5667
|
-
errorSummary: external_exports.string()
|
|
5668
|
-
}).strict();
|
|
5669
|
-
}
|
|
5670
|
-
});
|
|
5671
|
-
|
|
5672
|
-
// ../protocol/src/frames.ts
|
|
5673
|
-
var PROTOCOL_VERSION, DISPATCH_MCP_ID;
|
|
5674
|
-
var init_frames = __esm({
|
|
5675
|
-
"../protocol/src/frames.ts"() {
|
|
5676
|
-
"use strict";
|
|
5677
|
-
PROTOCOL_VERSION = 1;
|
|
5678
|
-
DISPATCH_MCP_ID = "dispatch";
|
|
5679
|
-
}
|
|
5680
|
-
});
|
|
5681
|
-
|
|
5682
|
-
// ../protocol/src/persona-mode.ts
|
|
5683
|
-
var init_persona_mode = __esm({
|
|
5684
|
-
"../protocol/src/persona-mode.ts"() {
|
|
5685
|
-
"use strict";
|
|
5686
|
-
}
|
|
5687
|
-
});
|
|
5688
|
-
|
|
5689
|
-
// ../protocol/src/capability.ts
|
|
5690
|
-
var ResourceSchema, ActionSchema, GrantSchema, CapabilitySchema, CapabilityWireSchema, WhoamiResponseSchema, PERSONAL_CAP_GRANTS;
|
|
5691
|
-
var init_capability = __esm({
|
|
5692
|
-
"../protocol/src/capability.ts"() {
|
|
5693
|
-
"use strict";
|
|
5694
|
-
init_zod();
|
|
5695
|
-
ResourceSchema = external_exports.discriminatedUnion("type", [
|
|
5696
|
-
external_exports.object({ type: external_exports.literal("persona"), id: external_exports.string().min(1) }).strict(),
|
|
5697
|
-
external_exports.object({ type: external_exports.literal("chat"), id: external_exports.string().min(1) }).strict(),
|
|
5698
|
-
external_exports.object({ type: external_exports.literal("*") }).strict()
|
|
5699
|
-
]);
|
|
5700
|
-
ActionSchema = external_exports.enum(["read", "send", "admin"]);
|
|
5701
|
-
GrantSchema = external_exports.object({
|
|
5702
|
-
resource: ResourceSchema,
|
|
5703
|
-
actions: external_exports.array(ActionSchema).min(1)
|
|
5704
|
-
}).strict();
|
|
5705
|
-
CapabilitySchema = external_exports.object({
|
|
5706
|
-
id: external_exports.string().min(1),
|
|
5707
|
-
// sha256(token) hex 64
|
|
5708
|
-
secretHash: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
5709
|
-
displayName: external_exports.string(),
|
|
5710
|
-
// 空数组合法 = 纯访客(只能 DM)
|
|
5711
|
-
grants: external_exports.array(GrantSchema),
|
|
5712
|
-
issuedAt: external_exports.number().int().nonnegative(),
|
|
5713
|
-
expiresAt: external_exports.number().int().positive().optional(),
|
|
5714
|
-
maxUses: external_exports.number().int().positive().optional(),
|
|
5715
|
-
usedCount: external_exports.number().int().nonnegative(),
|
|
5716
|
-
/**
|
|
5717
|
-
* guest 在 auth 帧捎带 selfPrincipalId 时由 AuthGate.authenticate 回写;
|
|
5718
|
-
* 未被消费的 cap 此字段缺失。
|
|
5719
|
-
*/
|
|
5720
|
-
peerOwnerId: external_exports.string().min(1).optional(),
|
|
5721
|
-
/** 首次 client hello 时间戳(与 peerOwnerId 同步写入) */
|
|
5722
|
-
firstUsedByPeerAt: external_exports.number().int().positive().optional(),
|
|
5723
|
-
/**
|
|
5724
|
-
* 对方 daemon owner 的 displayName,guest auth 帧 selfDisplayName 触发
|
|
5725
|
-
* recordPeerHello 时同步回写。视角 B (2026-05-23) UI 派生联系人列表用此字段
|
|
5726
|
-
* 显示对方名字(避免 fallback 到我颁 cap 时填的 displayName)。
|
|
5727
|
-
*/
|
|
5728
|
-
peerDisplayName: external_exports.string().optional()
|
|
5729
|
-
}).strict();
|
|
5730
|
-
CapabilityWireSchema = CapabilitySchema.omit({ secretHash: true });
|
|
5731
|
-
WhoamiResponseSchema = external_exports.object({
|
|
5732
|
-
type: external_exports.literal("whoami:ok"),
|
|
5733
|
-
owner: external_exports.object({
|
|
5734
|
-
id: external_exports.string(),
|
|
5735
|
-
kind: external_exports.enum(["owner", "guest"]),
|
|
5736
|
-
displayName: external_exports.string(),
|
|
5737
|
-
/** 归属人 id(决策 #16:TTC unique_id 等,落 contact.ownerId) */
|
|
5738
|
-
ownerId: external_exports.string(),
|
|
5739
|
-
/** 身份来源(决策 #16:'ttc'/'google',落 contact.provider) */
|
|
5740
|
-
provider: external_exports.string()
|
|
5741
|
-
}).strict(),
|
|
5742
|
-
capability: CapabilityWireSchema,
|
|
5743
|
-
grantedPersonas: external_exports.array(
|
|
5744
|
-
external_exports.object({
|
|
5745
|
-
id: external_exports.string().min(1),
|
|
5746
|
-
displayName: external_exports.string()
|
|
5747
|
-
}).strict()
|
|
5748
|
-
)
|
|
5749
|
-
}).strict();
|
|
5750
|
-
PERSONAL_CAP_GRANTS = Object.freeze([
|
|
5751
|
-
Object.freeze({
|
|
5752
|
-
resource: Object.freeze({ type: "persona", id: "*" }),
|
|
5753
|
-
actions: Object.freeze(["read", "send"])
|
|
5754
|
-
})
|
|
5755
|
-
]);
|
|
5756
|
-
}
|
|
5757
|
-
});
|
|
5758
|
-
|
|
5759
|
-
// ../protocol/src/inbox.ts
|
|
5760
|
-
var InboxMessageSchema, InboxPostMessageArgsSchema, InboxListArgsSchema, InboxMarkReadArgsSchema, InboxSendDmArgsSchema;
|
|
5761
|
-
var init_inbox = __esm({
|
|
5762
|
-
"../protocol/src/inbox.ts"() {
|
|
5763
|
-
"use strict";
|
|
5764
|
-
init_zod();
|
|
5765
|
-
InboxMessageSchema = external_exports.object({
|
|
5766
|
-
id: external_exports.string().min(1),
|
|
5767
|
-
peerDeviceId: external_exports.string().min(1),
|
|
5768
|
-
senderDeviceId: external_exports.string().min(1),
|
|
5769
|
-
text: external_exports.string().min(1),
|
|
5770
|
-
createdAt: external_exports.number().int().nonnegative(),
|
|
5771
|
-
readBy: external_exports.record(external_exports.string().min(1), external_exports.number().int().positive()).default({}),
|
|
5772
|
-
// persona 代发署名(B 版设计):非空 = 该消息由某 persona 代发,非真人手打。
|
|
5773
|
-
// 缺省 = 真人。routing 身份仍看 senderDeviceId;origin 只用于末端 UI 渲染来源。
|
|
5774
|
-
origin: external_exports.object({ kind: external_exports.literal("persona"), personaId: external_exports.string().min(1) }).optional()
|
|
5775
|
-
}).strict();
|
|
5776
|
-
InboxPostMessageArgsSchema = external_exports.object({
|
|
5777
|
-
peerDeviceId: external_exports.string().min(1).optional(),
|
|
5778
|
-
id: external_exports.string().min(1),
|
|
5779
|
-
text: external_exports.string().min(1),
|
|
5780
|
-
createdAt: external_exports.number().int().nonnegative(),
|
|
5781
|
-
// persona 代发署名(跨 daemon forward 时随远程腿透传;真人发缺省)。
|
|
5782
|
-
origin: external_exports.object({ kind: external_exports.literal("persona"), personaId: external_exports.string().min(1) }).optional()
|
|
5783
|
-
}).strict();
|
|
5784
|
-
InboxListArgsSchema = external_exports.object({
|
|
5785
|
-
peerDeviceId: external_exports.string().min(1),
|
|
5786
|
-
sinceCreatedAt: external_exports.number().int().nonnegative().optional()
|
|
5787
|
-
}).strict();
|
|
5788
|
-
InboxMarkReadArgsSchema = external_exports.object({
|
|
5789
|
-
peerDeviceId: external_exports.string().min(1),
|
|
5790
|
-
upToCreatedAt: external_exports.number().int().nonnegative()
|
|
5791
|
-
}).strict();
|
|
5792
|
-
InboxSendDmArgsSchema = external_exports.object({
|
|
5793
|
-
peerDeviceId: external_exports.string().min(1).optional(),
|
|
5794
|
-
text: external_exports.string().min(1)
|
|
5795
|
-
});
|
|
5796
|
-
}
|
|
5797
|
-
});
|
|
5798
|
-
|
|
5799
|
-
// ../protocol/src/contact.ts
|
|
5800
|
-
var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema, ContactPinArgsSchema, ContactPinOkSchema, ContactPinnedFrameSchema;
|
|
5801
|
-
var init_contact = __esm({
|
|
5802
|
-
"../protocol/src/contact.ts"() {
|
|
5803
|
-
"use strict";
|
|
5804
|
-
init_zod();
|
|
5805
|
-
init_capability();
|
|
5806
|
-
ContactSchema = external_exports.object({
|
|
5807
|
-
/**
|
|
5808
|
-
* 对方设备标识(主键):对方 daemon 自己生成并持久化的标识(auth.json deviceId,
|
|
5809
|
-
* 如 dev-<uuid>),provider 无关。同 deviceId 重复 upsert 覆盖。
|
|
5810
|
-
*/
|
|
5811
|
-
deviceId: external_exports.string().min(1),
|
|
5812
|
-
/**
|
|
5813
|
-
* 归属人 id(决策 #16):TTC unique_id 等,由 connect token subOwner 签名背书。
|
|
5814
|
-
* 与 provider 一起唯一标识一个人。DM 不再按它路由(路由用 deviceId),仅显示/分组用。
|
|
5815
|
-
*/
|
|
5816
|
-
ownerId: external_exports.string().min(1),
|
|
5817
|
-
/** 身份来源(决策 #16):'ttc'(飞书/手机/邮箱登入 TTC)| 'google' | ...,token 背书 */
|
|
5818
|
-
provider: external_exports.string().min(1),
|
|
5819
|
-
/** 联系人显示名 */
|
|
5820
|
-
displayName: external_exports.string(),
|
|
5821
|
-
/** 该设备可达的 ws/tunnel 地址 */
|
|
5822
|
-
remoteUrl: external_exports.string().min(1),
|
|
5823
|
-
// 自动反向建立联系人(spec 决策 #11):被连接方本地验票成功后自动落 A 为
|
|
5824
|
-
// 联系人,但它不持有 A 颁发的 token(A 从未给它换票)→ connectToken 为空串。
|
|
5825
|
-
// device:connect 出站路径仍存中心 server 签发的真实 connect token(断线重连复用)。
|
|
5826
|
-
// 不用 .min(1):自动反向路径合法地存空串,禁止填假 token 占位(不造假数据)。
|
|
5827
|
-
connectToken: external_exports.string(),
|
|
5828
|
-
grants: external_exports.array(GrantSchema),
|
|
5829
|
-
addedAt: external_exports.number().int().nonnegative(),
|
|
5830
|
-
/**
|
|
5831
|
-
* pin 时间戳(ms,Date.now() 语义);null = 未 pin。sidebar 顶部固定区渲染由此驱动。
|
|
5832
|
-
* 老 contacts.json 缺此字段 → zod default 补 null(无破坏性升级;不 orphan)。
|
|
5833
|
-
* 对齐 SessionFile.pinnedAt 语义(daemon 侧持久化,contact:pin RPC 更新 → contact:pinned push)。
|
|
5834
|
-
*/
|
|
5835
|
-
pinnedAt: external_exports.number().int().nullable().default(null),
|
|
5836
|
-
/**
|
|
5837
|
-
* 远程访问授权(spec 2026-07-16)。owner 视角:允许该 contact 反向操作我的设备——
|
|
5838
|
-
* 跨设备 exec 的总开关(peerExec:run handler 运行时判它)。default=false,owner 显式开。
|
|
5839
|
-
* 授权粒度 per-people (per-contact):借用别人 persona 本来就带信任对方本人的前提。
|
|
5840
|
-
*/
|
|
5841
|
-
remoteAccessAllowed: external_exports.boolean().default(false)
|
|
5842
|
-
}).strict();
|
|
5843
|
-
ContactWireSchema = ContactSchema;
|
|
5844
|
-
ContactRemoveArgsSchema = external_exports.object({
|
|
5845
|
-
deviceId: external_exports.string().min(1)
|
|
5846
|
-
}).strict();
|
|
5847
|
-
ContactRemoveOkSchema = external_exports.object({
|
|
5848
|
-
type: external_exports.literal("contact:remove:ok"),
|
|
5849
|
-
deviceId: external_exports.string().min(1)
|
|
5850
|
-
}).strict();
|
|
5851
|
-
ContactListOkSchema = external_exports.object({
|
|
5852
|
-
type: external_exports.literal("contact:list:ok"),
|
|
5853
|
-
contacts: external_exports.array(ContactWireSchema)
|
|
5854
|
-
}).strict();
|
|
5855
|
-
ContactAddedFrameSchema = external_exports.object({
|
|
5856
|
-
type: external_exports.literal("contact:added"),
|
|
5857
|
-
contact: ContactWireSchema
|
|
5858
|
-
}).strict();
|
|
5859
|
-
ContactRemovedFrameSchema = external_exports.object({
|
|
5860
|
-
type: external_exports.literal("contact:removed"),
|
|
5861
|
-
deviceId: external_exports.string().min(1)
|
|
5862
|
-
}).strict();
|
|
5863
|
-
ContactPinArgsSchema = external_exports.object({
|
|
5864
|
-
deviceId: external_exports.string().min(1),
|
|
5865
|
-
pinned: external_exports.boolean()
|
|
5866
|
-
}).strict();
|
|
5867
|
-
ContactPinOkSchema = external_exports.object({
|
|
5868
|
-
type: external_exports.literal("contact:pin:ok"),
|
|
5869
|
-
deviceId: external_exports.string().min(1),
|
|
5870
|
-
pinnedAt: external_exports.number().int().nullable()
|
|
5871
|
-
}).strict();
|
|
5872
|
-
ContactPinnedFrameSchema = external_exports.object({
|
|
5873
|
-
type: external_exports.literal("contact:pinned"),
|
|
5874
|
-
deviceId: external_exports.string().min(1),
|
|
5875
|
-
pinnedAt: external_exports.number().int().nullable()
|
|
5876
|
-
}).strict();
|
|
5877
|
-
}
|
|
5878
|
-
});
|
|
5879
|
-
|
|
5880
|
-
// ../protocol/src/contact-handshake.ts
|
|
5881
|
-
var ContactHandshakeArgsSchema, ContactHandshakeOkSchema;
|
|
5882
|
-
var init_contact_handshake = __esm({
|
|
5883
|
-
"../protocol/src/contact-handshake.ts"() {
|
|
5884
|
-
"use strict";
|
|
5885
|
-
init_zod();
|
|
5886
|
-
init_capability();
|
|
5887
|
-
ContactHandshakeArgsSchema = external_exports.object({
|
|
5888
|
-
selfUrl: external_exports.string().min(1)
|
|
5889
|
-
});
|
|
5890
|
-
ContactHandshakeOkSchema = external_exports.object({
|
|
5891
|
-
type: external_exports.literal("contact:handshake:ok"),
|
|
5892
|
-
owner: external_exports.object({
|
|
5893
|
-
/** 被调方 deviceId(路由主键;调用方落 Contact 的主键用自己请求的 args.deviceId,此值供校验/展示) */
|
|
5894
|
-
id: external_exports.string(),
|
|
5895
|
-
/** 归属人(落 Contact.ownerId / provider,显示分组用) */
|
|
5896
|
-
ownerId: external_exports.string(),
|
|
5897
|
-
provider: external_exports.string(),
|
|
5898
|
-
displayName: external_exports.string()
|
|
5899
|
-
}),
|
|
5900
|
-
/** 被调方授调用方的 grants(落 Contact.grants) */
|
|
5901
|
-
grants: external_exports.array(GrantSchema)
|
|
5902
|
-
});
|
|
5903
|
-
}
|
|
5904
|
-
});
|
|
5905
|
-
|
|
5906
|
-
// ../protocol/src/contact-remote-access.ts
|
|
5907
|
-
var ContactSetRemoteAccessArgsSchema, ContactSetRemoteAccessOkSchema, ContactRemoteAccessUpdatedFrameSchema;
|
|
5908
|
-
var init_contact_remote_access = __esm({
|
|
5909
|
-
"../protocol/src/contact-remote-access.ts"() {
|
|
5910
|
-
"use strict";
|
|
5911
|
-
init_zod();
|
|
5912
|
-
ContactSetRemoteAccessArgsSchema = external_exports.object({
|
|
5913
|
-
deviceId: external_exports.string().min(1),
|
|
5914
|
-
remoteAccessAllowed: external_exports.boolean()
|
|
5915
|
-
}).strict();
|
|
5916
|
-
ContactSetRemoteAccessOkSchema = external_exports.object({
|
|
5917
|
-
type: external_exports.literal("contact:setRemoteAccess:ok"),
|
|
5918
|
-
deviceId: external_exports.string().min(1),
|
|
5919
|
-
remoteAccessAllowed: external_exports.boolean()
|
|
5920
|
-
}).strict();
|
|
5921
|
-
ContactRemoteAccessUpdatedFrameSchema = external_exports.object({
|
|
5922
|
-
type: external_exports.literal("contact:remote-access-updated"),
|
|
5923
|
-
deviceId: external_exports.string().min(1),
|
|
5924
|
-
remoteAccessAllowed: external_exports.boolean()
|
|
5925
|
-
}).strict();
|
|
5926
|
-
}
|
|
5927
|
-
});
|
|
5928
|
-
|
|
5929
|
-
// ../protocol/src/peer-exec.ts
|
|
5930
|
-
var PeerExecRunArgsSchema, PeerExecRunOkSchema;
|
|
5931
|
-
var init_peer_exec = __esm({
|
|
5932
|
-
"../protocol/src/peer-exec.ts"() {
|
|
5933
|
-
"use strict";
|
|
5934
|
-
init_zod();
|
|
5935
|
-
PeerExecRunArgsSchema = external_exports.object({
|
|
5936
|
-
/** A 侧发起时带:目标设备 deviceId。peer-forward 转发前 strip 掉,B 侧本地执行时无此字段。 */
|
|
5937
|
-
peerDeviceId: external_exports.string().min(1).optional(),
|
|
5938
|
-
/** 交给对端 `bash -c` 的命令;cc 自拼完整路径(一发一收,无跨命令会话状态)。 */
|
|
5939
|
-
command: external_exports.string().min(1),
|
|
5940
|
-
/** 超时上限(ms);缺省用 handler 默认 30_000,clamp 300_000。 */
|
|
5941
|
-
timeoutMs: external_exports.number().int().positive().optional()
|
|
5942
|
-
}).strict();
|
|
5943
|
-
PeerExecRunOkSchema = external_exports.object({
|
|
5944
|
-
type: external_exports.literal("peerExec:run:ok"),
|
|
5945
|
-
stdout: external_exports.string(),
|
|
5946
|
-
stderr: external_exports.string(),
|
|
5947
|
-
/** 进程退出码;被超时 kill 时 null。 */
|
|
5948
|
-
exitCode: external_exports.number().int().nullable(),
|
|
5949
|
-
timedOut: external_exports.boolean(),
|
|
5950
|
-
stdoutTruncated: external_exports.boolean(),
|
|
5951
|
-
stderrTruncated: external_exports.boolean()
|
|
5952
|
-
}).strict();
|
|
5953
|
-
}
|
|
5954
|
-
});
|
|
5955
|
-
|
|
5956
|
-
// ../protocol/src/extension.ts
|
|
5957
|
-
function isAllowedHostedUrl(raw) {
|
|
5958
|
-
let u;
|
|
5959
|
-
try {
|
|
5960
|
-
u = new URL(raw);
|
|
5961
|
-
} catch {
|
|
5962
|
-
return false;
|
|
5963
|
-
}
|
|
5964
|
-
if (u.protocol === "https:") return true;
|
|
5965
|
-
if (u.protocol === "http:" && LOCALHOST_HOSTS.has(u.hostname)) return true;
|
|
5966
|
-
return false;
|
|
5967
|
-
}
|
|
5968
|
-
function manifestMode(m2) {
|
|
5969
|
-
return m2.entry?.url ? "hosted" : "local";
|
|
5970
|
-
}
|
|
5971
|
-
function ownerNamespace(ownerPrincipalId) {
|
|
5972
|
-
let h = 2166136261;
|
|
5973
|
-
for (let i = 0; i < ownerPrincipalId.length; i++) {
|
|
5974
|
-
h ^= ownerPrincipalId.charCodeAt(i);
|
|
5975
|
-
h = Math.imul(h, 16777619) >>> 0;
|
|
5976
|
-
}
|
|
5977
|
-
return (h >>> 0).toString(16).padStart(8, "0");
|
|
5978
|
-
}
|
|
5979
|
-
function namespacedExtId(slug, ownerPrincipalId) {
|
|
5980
|
-
return `${slug}-${ownerNamespace(ownerPrincipalId)}`;
|
|
5981
|
-
}
|
|
5982
|
-
function validateSimpleSemver(v2) {
|
|
5983
|
-
if (typeof v2 !== "string") {
|
|
5984
|
-
return { ok: false, reason: "version must be a string" };
|
|
5985
|
-
}
|
|
5986
|
-
const parts = v2.split(".");
|
|
5987
|
-
if (parts.length !== 3) {
|
|
5988
|
-
return { ok: false, reason: `"${v2}" \u2014 only MAJOR.MINOR.PATCH allowed` };
|
|
5989
|
-
}
|
|
5990
|
-
for (const p2 of parts) {
|
|
5991
|
-
if (!/^\d+$/.test(p2)) {
|
|
5992
|
-
return { ok: false, reason: `"${v2}" \u2014 only numeric segments allowed` };
|
|
5993
|
-
}
|
|
5994
|
-
}
|
|
5995
|
-
return { ok: true };
|
|
5996
|
-
}
|
|
5997
|
-
function compareSimpleSemver(a, b2) {
|
|
5998
|
-
const pa = parseOrThrow(a);
|
|
5999
|
-
const pb = parseOrThrow(b2);
|
|
6000
|
-
for (let i = 0; i < 3; i++) {
|
|
6001
|
-
if (pa[i] < pb[i]) return -1;
|
|
6002
|
-
if (pa[i] > pb[i]) return 1;
|
|
6003
|
-
}
|
|
6004
|
-
return 0;
|
|
6005
|
-
}
|
|
6006
|
-
function parseOrThrow(v2) {
|
|
6007
|
-
const r = validateSimpleSemver(v2);
|
|
6008
|
-
if (!r.ok) throw new Error(r.reason);
|
|
6009
|
-
const [a, b2, c] = v2.split(".").map((p2) => parseInt(p2, 10));
|
|
6010
|
-
return [a, b2, c];
|
|
6011
|
-
}
|
|
6012
|
-
var EXT_ID_REGEX, ExtensionStateSchema, LOCALHOST_HOSTS, ExtensionManifestSchema, ExtensionTargetSchema, ExtensionRecordSchema, PublishedSnapshotSchema, ChannelRefSchema, SourceRefSchema, PublishedExtensionRecordSchema, PublishCheckSchema, PublishStatusResultSchema;
|
|
6013
|
-
var init_extension = __esm({
|
|
6014
|
-
"../protocol/src/extension.ts"() {
|
|
6015
|
-
"use strict";
|
|
6016
|
-
init_zod();
|
|
6017
|
-
EXT_ID_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
6018
|
-
ExtensionStateSchema = external_exports.enum([
|
|
6019
|
-
"stopped",
|
|
6020
|
-
"starting",
|
|
6021
|
-
"running",
|
|
6022
|
-
"crashed",
|
|
6023
|
-
"invalid"
|
|
6024
|
-
]);
|
|
6025
|
-
LOCALHOST_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
6026
|
-
ExtensionManifestSchema = external_exports.object({
|
|
6027
|
-
id: external_exports.string().regex(EXT_ID_REGEX),
|
|
6028
|
-
name: external_exports.string().min(1),
|
|
6029
|
-
version: external_exports.string().min(1),
|
|
6030
|
-
apiVersion: external_exports.literal("1"),
|
|
6031
|
-
runtime: external_exports.object({ startCommand: external_exports.string().min(1) }).passthrough().optional(),
|
|
6032
|
-
entry: external_exports.object({
|
|
6033
|
-
url: external_exports.string().url().refine(isAllowedHostedUrl, {
|
|
6034
|
-
message: "INVALID_URL_SCHEME: only https or http://localhost is allowed"
|
|
6035
|
-
})
|
|
6036
|
-
}).strict().optional()
|
|
6037
|
-
}).passthrough().superRefine((m2, ctx) => {
|
|
6038
|
-
const hasRuntime = !!m2.runtime;
|
|
6039
|
-
const hasUrl = !!m2.entry?.url;
|
|
6040
|
-
if (hasRuntime && hasUrl) {
|
|
6041
|
-
ctx.addIssue({
|
|
6042
|
-
code: external_exports.ZodIssueCode.custom,
|
|
6043
|
-
message: "INVALID_MANIFEST: entry.url and runtime cannot coexist"
|
|
6044
|
-
});
|
|
6045
|
-
}
|
|
6046
|
-
if (!hasRuntime && !hasUrl) {
|
|
6047
|
-
ctx.addIssue({
|
|
6048
|
-
code: external_exports.ZodIssueCode.custom,
|
|
6049
|
-
message: "INVALID_MANIFEST: must have either entry.url or runtime"
|
|
6050
|
-
});
|
|
6051
|
-
}
|
|
6052
|
-
});
|
|
6053
|
-
ExtensionTargetSchema = external_exports.discriminatedUnion("kind", [
|
|
6054
|
-
external_exports.object({ kind: external_exports.literal("local"), port: external_exports.number().int().min(1).max(65535) }),
|
|
6055
|
-
external_exports.object({ kind: external_exports.literal("hosted"), url: external_exports.string().url() })
|
|
6056
|
-
]);
|
|
6057
|
-
ExtensionRecordSchema = external_exports.discriminatedUnion("state", [
|
|
6058
|
-
external_exports.object({
|
|
6059
|
-
extId: external_exports.string(),
|
|
6060
|
-
manifest: ExtensionManifestSchema,
|
|
6061
|
-
state: external_exports.literal("stopped")
|
|
6062
|
-
}),
|
|
6063
|
-
external_exports.object({
|
|
6064
|
-
extId: external_exports.string(),
|
|
6065
|
-
manifest: ExtensionManifestSchema,
|
|
6066
|
-
state: external_exports.literal("starting")
|
|
6067
|
-
}),
|
|
6068
|
-
external_exports.object({
|
|
6069
|
-
extId: external_exports.string(),
|
|
6070
|
-
manifest: ExtensionManifestSchema,
|
|
6071
|
-
state: external_exports.literal("running"),
|
|
6072
|
-
target: ExtensionTargetSchema
|
|
6073
|
-
}),
|
|
6074
|
-
external_exports.object({
|
|
6075
|
-
extId: external_exports.string(),
|
|
6076
|
-
manifest: ExtensionManifestSchema,
|
|
6077
|
-
state: external_exports.literal("crashed")
|
|
6078
|
-
}),
|
|
6079
|
-
external_exports.object({
|
|
6080
|
-
extId: external_exports.string(),
|
|
6081
|
-
manifest: external_exports.unknown().nullable(),
|
|
6082
|
-
state: external_exports.literal("invalid"),
|
|
6083
|
-
invalidReason: external_exports.string().min(1)
|
|
6084
|
-
})
|
|
6085
|
-
]);
|
|
6086
|
-
PublishedSnapshotSchema = external_exports.object({
|
|
6087
|
-
snapshotHash: external_exports.string().min(1),
|
|
6088
|
-
version: external_exports.string().min(1),
|
|
6089
|
-
publishedAt: external_exports.number()
|
|
6090
|
-
});
|
|
6091
|
-
ChannelRefSchema = external_exports.discriminatedUnion("kind", [
|
|
6092
|
-
external_exports.object({
|
|
6093
|
-
kind: external_exports.literal("p2p-tunnel"),
|
|
6094
|
-
ownerPrincipalId: external_exports.string().min(1),
|
|
6095
|
-
extId: external_exports.string().min(1)
|
|
6096
|
-
})
|
|
6097
|
-
]);
|
|
6098
|
-
SourceRefSchema = external_exports.discriminatedUnion("kind", [
|
|
6099
|
-
external_exports.object({
|
|
6100
|
-
kind: external_exports.literal("p2p-tunnel"),
|
|
6101
|
-
ownerPrincipalId: external_exports.string().min(1),
|
|
6102
|
-
extId: external_exports.string().min(1),
|
|
6103
|
-
snapshotHash: external_exports.string().min(1)
|
|
6104
|
-
})
|
|
6105
|
-
]);
|
|
6106
|
-
PublishedExtensionRecordSchema = external_exports.object({
|
|
6107
|
-
extId: external_exports.string().min(1),
|
|
6108
|
-
name: external_exports.string().min(1),
|
|
6109
|
-
version: external_exports.string().min(1),
|
|
6110
|
-
contentHash: external_exports.string().min(1),
|
|
6111
|
-
publishedAt: external_exports.number()
|
|
6112
|
-
});
|
|
6113
|
-
PublishCheckSchema = external_exports.discriminatedUnion("kind", [
|
|
6114
|
-
external_exports.object({ kind: external_exports.literal("clean") }),
|
|
6115
|
-
external_exports.object({
|
|
6116
|
-
kind: external_exports.literal("ready-new-version"),
|
|
6117
|
-
fromVersion: external_exports.string().min(1),
|
|
6118
|
-
toVersion: external_exports.string().min(1)
|
|
6119
|
-
}),
|
|
6120
|
-
external_exports.object({
|
|
6121
|
-
kind: external_exports.literal("error-same-hash"),
|
|
6122
|
-
version: external_exports.string().min(1)
|
|
6123
|
-
}),
|
|
6124
|
-
external_exports.object({
|
|
6125
|
-
kind: external_exports.literal("error-version-not-bumped"),
|
|
6126
|
-
localVersion: external_exports.string().min(1),
|
|
6127
|
-
publishedVersion: external_exports.string().min(1)
|
|
6128
|
-
}),
|
|
6129
|
-
external_exports.object({
|
|
6130
|
-
kind: external_exports.literal("error-version-regression"),
|
|
6131
|
-
localVersion: external_exports.string().min(1),
|
|
6132
|
-
publishedVersion: external_exports.string().min(1)
|
|
6133
|
-
})
|
|
6134
|
-
]);
|
|
6135
|
-
PublishStatusResultSchema = external_exports.object({
|
|
6136
|
-
localManifest: external_exports.object({
|
|
6137
|
-
name: external_exports.string().min(1),
|
|
6138
|
-
version: external_exports.string().min(1),
|
|
6139
|
-
contentHash: external_exports.string().min(1)
|
|
6140
|
-
}),
|
|
6141
|
-
publishState: external_exports.discriminatedUnion("kind", [
|
|
6142
|
-
external_exports.object({ kind: external_exports.literal("unpublished") }),
|
|
6143
|
-
external_exports.object({
|
|
6144
|
-
kind: external_exports.literal("published"),
|
|
6145
|
-
version: external_exports.string().min(1),
|
|
6146
|
-
contentHash: external_exports.string().min(1),
|
|
6147
|
-
publishedAt: external_exports.number()
|
|
6148
|
-
})
|
|
6149
|
-
]),
|
|
6150
|
-
check: PublishCheckSchema
|
|
6151
|
-
});
|
|
6087
|
+
ok: external_exports.literal(true)
|
|
6088
|
+
}).strict();
|
|
6089
|
+
AppBuilderPublishProgressEventSchema = external_exports.object({
|
|
6090
|
+
type: external_exports.literal("appBuilder:publish-progress"),
|
|
6091
|
+
name: external_exports.string().regex(projectNameRegex),
|
|
6092
|
+
jobId: external_exports.string().min(1),
|
|
6093
|
+
stage: external_exports.enum(["build", "deploy", "verify"]),
|
|
6094
|
+
status: external_exports.enum(["started", "completed"])
|
|
6095
|
+
}).strict();
|
|
6096
|
+
AppBuilderPublishFailedEventSchema = external_exports.object({
|
|
6097
|
+
type: external_exports.literal("appBuilder:publish-failed"),
|
|
6098
|
+
name: external_exports.string().regex(projectNameRegex),
|
|
6099
|
+
jobId: external_exports.string().min(1),
|
|
6100
|
+
stage: external_exports.enum(["build", "deploy", "verify", "unknown"]),
|
|
6101
|
+
errorSummary: external_exports.string()
|
|
6102
|
+
}).strict();
|
|
6152
6103
|
}
|
|
6153
6104
|
});
|
|
6154
6105
|
|
|
6155
|
-
// ../protocol/src/
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6106
|
+
// ../protocol/src/methods.ts
|
|
6107
|
+
function methodArgFields(method) {
|
|
6108
|
+
let schema = METHOD_DOCS[method].args;
|
|
6109
|
+
if (!schema) return null;
|
|
6110
|
+
for (let i = 0; i < 5 && schema && !schema.shape; i += 1) {
|
|
6111
|
+
schema = schema._def?.schema;
|
|
6112
|
+
}
|
|
6113
|
+
const shape = schema?.shape;
|
|
6114
|
+
if (!shape) return null;
|
|
6115
|
+
return Object.entries(shape).map(([name, def]) => ({ name, required: !def.isOptional() }));
|
|
6116
|
+
}
|
|
6117
|
+
var NO_ARGS, METHOD_DOCS, METHOD_NAMES, RPC_METHOD_STATUSES, RpcMethodStatusSchema, RpcMethodInfoSchema, MetaMethodsResultSchema;
|
|
6118
|
+
var init_methods = __esm({
|
|
6119
|
+
"../protocol/src/methods.ts"() {
|
|
6159
6120
|
"use strict";
|
|
6160
6121
|
init_zod();
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6122
|
+
init_attachment_schemas();
|
|
6123
|
+
init_contact_handshake();
|
|
6124
|
+
init_contact_remote_access();
|
|
6125
|
+
init_contact();
|
|
6126
|
+
init_feishu_auth();
|
|
6127
|
+
init_dispatch();
|
|
6128
|
+
init_extension();
|
|
6129
|
+
init_inbox();
|
|
6130
|
+
init_peer_exec();
|
|
6131
|
+
init_shift_internal();
|
|
6132
|
+
init_persona_schemas();
|
|
6133
|
+
init_schemas();
|
|
6134
|
+
NO_ARGS = external_exports.object({});
|
|
6135
|
+
METHOD_DOCS = {
|
|
6136
|
+
"session:create": {
|
|
6137
|
+
summary: "\u65B0\u5EFA\u4F1A\u8BDD\u5E76\u62C9\u8D77 tool \u8FDB\u7A0B\uFF08claude / codex\uFF09\u3002**cwd \u4E0E ownerPersonaId \u81F3\u5C11\u4F20\u4E00\u4E2A**\uFF08\u5E26 ownerPersonaId \u65F6 cwd \u7531 daemon \u6D3E\u751F\uFF09\u2014\u2014\u8FD9\u6761\u4E92\u65A5\u7EA6\u675F\u662F schema \u7684 refine\uFF0C\u53CD\u5C04\u4E0D\u51FA\u6765",
|
|
6138
|
+
args: SessionCreateArgs
|
|
6139
|
+
},
|
|
6140
|
+
"session:list": {
|
|
6141
|
+
summary: "\u5217\u51FA\u5F53\u524D\u8EAB\u4EFD\u53EF\u89C1\u7684\u4F1A\u8BDD\uFF08owner \u5168\u91CF\uFF1Bguest \u9650\u88AB\u6388\u6743 persona\uFF09",
|
|
6142
|
+
args: SessionListArgs
|
|
6143
|
+
},
|
|
6144
|
+
"session:get": {
|
|
6145
|
+
summary: "\u53D6\u5355\u4E2A\u4F1A\u8BDD\u7684\u5B8C\u6574 SessionFile\uFF08\u5143\u6570\u636E + \u72B6\u6001\uFF09",
|
|
6146
|
+
args: SessionIdArgs
|
|
6147
|
+
},
|
|
6148
|
+
"session:update": {
|
|
6149
|
+
summary: "\u6539\u4F1A\u8BDD\u5143\u6570\u636E\uFF0C\u4E0D\u5F71\u54CD\u8FDB\u7A0B\u3002patch \u5141\u8BB8\u7684\u952E\uFF1Alabel / model / permissionMode / effort / cwd / iconKey\u2014\u2014**\u4F20\u522B\u7684\u952E\u4F1A\u88AB\u9759\u9ED8\u4E22\u5F03**\uFF08zod strip\uFF09\uFF0Chandler \u7167\u6837\u8FD4 ok",
|
|
6150
|
+
args: SessionUpdateArgs
|
|
6151
|
+
},
|
|
6152
|
+
"session:delete": {
|
|
6153
|
+
summary: "\u5220\u4F1A\u8BDD\uFF1A\u505C\u8FDB\u7A0B + \u5220 SessionFile\uFF0C\u5E76\u8054\u52A8\u6E05\u7406\u7ED1\u5B9A\u7684 app-builder project",
|
|
6154
|
+
args: SessionIdArgs
|
|
6155
|
+
},
|
|
6156
|
+
"session:send": {
|
|
6157
|
+
summary: "\u5411\u4F1A\u8BDD\u53D1\u4E00\u6761\u7528\u6237\u6D88\u606F\uFF08\u89E6\u53D1\u65B0\u4E00\u8F6E turn\uFF09",
|
|
6158
|
+
args: SessionSendArgs
|
|
6159
|
+
},
|
|
6160
|
+
"session:currentTurnSender": {
|
|
6161
|
+
summary: "\u67E5\u5F53\u524D turn \u7684\u9A71\u52A8\u8005\uFF08owner / guest \u7684 SenderInfo\uFF09\u3002\u7701\u7565 sessionId \u6216\u4F20\u7A7A\u4E32 \u2192 \u76F4\u63A5\u8FD4 sender:null\uFF0C\u4E0D\u62A5\u9519",
|
|
6162
|
+
args: SessionCurrentTurnSenderArgs
|
|
6163
|
+
},
|
|
6164
|
+
"session:stop": {
|
|
6165
|
+
summary: "\u505C\u6389\u4F1A\u8BDD\u7684 tool \u8FDB\u7A0B\uFF08\u6740\u8FDB\u7A0B\uFF0C\u4F1A\u8BDD\u672C\u8EAB\u4FDD\u7559\uFF09",
|
|
6166
|
+
args: SessionIdArgs
|
|
6167
|
+
},
|
|
6168
|
+
"session:interrupt": {
|
|
6169
|
+
summary: "\u6E29\u67D4\u4E2D\u65AD\u5F53\u524D\u8F6E\u6B21\uFF0C\u4E0D\u6740\u8FDB\u7A0B\uFF08\u8D70 CC IPC control_request.subtype=interrupt\uFF09",
|
|
6170
|
+
args: SessionInterruptArgs
|
|
6171
|
+
},
|
|
6172
|
+
"session:rewind": {
|
|
6173
|
+
summary: "\u56DE\u6EDA\u5230\u6307\u5B9A user message\uFF0C\u5E76\u64A4\u9500\u5176\u540E CC \u505A\u7684\u6587\u4EF6\u7F16\u8F91",
|
|
6174
|
+
args: SessionRewindArgs
|
|
6175
|
+
},
|
|
6176
|
+
"session:rewind-diff": {
|
|
6177
|
+
summary: "\u56DE\u6EDA\u9884\u89C8\uFF1A\u8BFB ~/.claude/file-history \u5FEB\u7167 + \u78C1\u76D8\u73B0\u72B6\u7B97\u771F\u5B9E diff\uFF0C\u4E0D\u4F9D\u8D56 CC \u8FDB\u7A0B",
|
|
6178
|
+
args: SessionRewindDiffArgs
|
|
6179
|
+
},
|
|
6180
|
+
"session:rewindable-message-ids": {
|
|
6181
|
+
summary: "\u4E00\u6B21\u6027\u62FF\u5230\u300C\u6709\u771F\u5B9E diff\u300D\u7684 user message id \u96C6\u5408\uFF0CUI \u636E\u6B64\u51B3\u5B9A\u54EA\u4E9B\u6D88\u606F\u663E\u793A\u56DE\u6EDA\u6309\u94AE",
|
|
6182
|
+
args: SessionRewindableMessageIdsArgs
|
|
6183
|
+
},
|
|
6184
|
+
"session:fork": {
|
|
6185
|
+
summary: "\u4ECE\u6307\u5B9A message \u5904 fork \u51FA\u65B0 transcript\uFF08\u622A\u65AD + \u91CD\u5199 sessionId/parentUuid\uFF09\uFF0C\u8FD4\u56DE\u65B0 toolSessionId\uFF1B\u4E0D\u81EA\u52A8\u62C9\u8D77\u8FDB\u7A0B",
|
|
6186
|
+
args: SessionForkArgs
|
|
6187
|
+
},
|
|
6188
|
+
"session:new": {
|
|
6189
|
+
summary: "\u5728**\u5DF2\u6709**\u4F1A\u8BDD\u4E0A\u6E05\u7A7A\u4E0A\u4E0B\u6587\u5F00\u65B0\u4E00\u8F6E\uFF0C\u76F8\u5F53\u4E8E CC \u7684 /clear\uFF08\u4E0D\u662F\u5EFA\u65B0\u4F1A\u8BDD\u2014\u2014\u5EFA\u65B0\u4F1A\u8BDD\u7528 session:create\uFF09",
|
|
6190
|
+
args: SessionIdArgs
|
|
6191
|
+
},
|
|
6192
|
+
"session:resume": {
|
|
6193
|
+
summary: "\u628A\u4F1A\u8BDD\u6062\u590D\u5230\u6307\u5B9A\u7684 tool \u4F1A\u8BDD\uFF08CC transcript\uFF09\u4E0A\u7EE7\u7EED",
|
|
6194
|
+
args: SessionResumeArgs
|
|
6195
|
+
},
|
|
6196
|
+
"session:observe": {
|
|
6197
|
+
summary: "\u6302 observer \u76D1\u542C\u8BE5\u4F1A\u8BDD\u7684 CC jsonl\uFF0C\u628A daemon \u4E4B\u5916\u542F\u52A8\u7684 CC \u6D3B\u52A8\u56DE\u704C\u8FDB\u6765\uFF08\u591A\u7AEF\u5171\u4EAB / \u63A5\u7BA1\u5916\u90E8\u4F1A\u8BDD\uFF09\u3002\u4EC5 claude \u652F\u6301",
|
|
6198
|
+
args: SessionObserveArgs
|
|
6199
|
+
},
|
|
6200
|
+
"session:events": {
|
|
6201
|
+
summary: "\u62C9\u53D6\u4F1A\u8BDD\u7684\u5386\u53F2\u4E8B\u4EF6\uFF08\u6309 seq \u589E\u91CF\uFF09\uFF0C\u7528\u4E8E\u65AD\u7EBF\u91CD\u8FDE\u8865\u5E27",
|
|
6202
|
+
args: SessionEventsArgs
|
|
6203
|
+
},
|
|
6204
|
+
"session:subscribe": {
|
|
6205
|
+
summary: "\u8BA2\u9605\u8BE5\u4F1A\u8BDD\u7684 push \u5E27\uFF08\u672C\u8FDE\u63A5\u751F\u6548\uFF0CrefCount \u8BA1\u6570\uFF09\u3002**\u7701\u7565 sessionId = \u4E0D\u5EFA\u7ACB\u4EFB\u4F55\u8BA2\u9605**\uFF0C\u4F46\u7167\u6837\u8FD4 subscribed \u2014\u2014 \u4E0D\u662F\u300C\u8BA2\u9605\u5168\u90E8\u300D",
|
|
6206
|
+
args: SessionSubscribeArgs
|
|
6207
|
+
},
|
|
6208
|
+
"session:unsubscribe": {
|
|
6209
|
+
summary: "\u53D6\u6D88\u8BA2\u9605\u8BE5\u4F1A\u8BDD\u7684 push \u5E27\u3002\u7701\u7565 sessionId \u65F6\u4E0D\u53D6\u6D88\u4EFB\u4F55\u8BA2\u9605\uFF0C\u7167\u6837\u8FD4 ok",
|
|
6210
|
+
args: SessionSubscribeArgs
|
|
6211
|
+
},
|
|
6212
|
+
"session:pin": {
|
|
6213
|
+
summary: "\u7F6E\u9876 / \u53D6\u6D88\u7F6E\u9876\u4F1A\u8BDD",
|
|
6214
|
+
args: SessionPinArgs
|
|
6215
|
+
},
|
|
6216
|
+
"session:markRead": {
|
|
6217
|
+
summary: "\u6E05\u6389\u4F1A\u8BDD\u7684\u5171\u4EAB\u672A\u8BFB\u6807\u8BB0\u5E76\u5E7F\u64AD session:info\uFF1B\u5E42\u7B49",
|
|
6218
|
+
args: SessionIdArgs
|
|
6219
|
+
},
|
|
6220
|
+
"session:reorderPins": {
|
|
6221
|
+
summary: "\u6574\u4F53\u91CD\u5199\u6240\u6709\u7F6E\u9876\u4F1A\u8BDD\u7684\u6392\u5E8F\uFF08sidebar \u62D6\u62FD\u5B8C\u6210\u65F6\u8C03\uFF09",
|
|
6222
|
+
args: SessionReorderPinsArgs
|
|
6223
|
+
},
|
|
6224
|
+
"peerSession:upsert": {
|
|
6225
|
+
summary: "\u5199\u5165 / \u66F4\u65B0\u4E00\u6761 mirror SessionFile \u2014\u2014 \u300C\u6211\u5728\u670B\u53CB daemon \u4E0A\u521B\u5EFA\u7684\u4F1A\u8BDD\u300D\u5728\u672C\u673A\u7684\u526F\u672C\uFF0C\u4EC5\u4F9B sidebar \u8DE8\u8BBE\u5907\u805A\u5408\uFF1Bdaemon \u53EA dumb \u5199\uFF0C\u4E0D\u5E7F\u64AD\u4EFB\u4F55 push \u5E27",
|
|
6226
|
+
args: PeerSessionUpsertArgs
|
|
6227
|
+
},
|
|
6228
|
+
"peerSession:remove": {
|
|
6229
|
+
summary: "\u5220\u9664\u4E00\u6761 mirror SessionFile\uFF08\u540C\u6837\u4E0D\u5E7F\u64AD\uFF09",
|
|
6230
|
+
args: PeerSessionRemoveArgs
|
|
6231
|
+
},
|
|
6232
|
+
"permission:respond": {
|
|
6233
|
+
summary: "\u56DE\u5E94 CC \u7684\u6743\u9650\u8BF7\u6C42\uFF08\u5141\u8BB8 / \u62D2\u7EDD / \u8BB0\u4F4F\u89C4\u5219\uFF09",
|
|
6234
|
+
args: PermissionRespondArgs
|
|
6235
|
+
},
|
|
6236
|
+
"session:answerQuestion": {
|
|
6237
|
+
summary: "\u56DE\u586B AskUserQuestion \u8868\u5355\u7B54\u6848\uFF0Cdaemon \u5408\u5E76\u8FDB updated_input \u5199 control_response \u7ED9 CC",
|
|
6238
|
+
args: AnswerQuestionArgs
|
|
6239
|
+
},
|
|
6240
|
+
"session:cancelQuestion": {
|
|
6241
|
+
summary: "\u7528\u6237\u8DF3\u8FC7 AskUserQuestion\uFF1Adaemon \u56DE allow + \u7A7A\u7B54\u6848\u8BA9 tool \u8D70\u7A7A\u8DEF\u5F84\uFF0C\u5E76\u5E7F\u64AD cleared \u5E27",
|
|
6242
|
+
args: CancelQuestionArgs
|
|
6243
|
+
},
|
|
6244
|
+
"history:projects": {
|
|
6245
|
+
summary: "\u5217\u51FA CC \u5386\u53F2\u91CC\u7684\u5168\u90E8\u9879\u76EE\uFF08\u6309 projectPath \u805A\u5408\uFF09\uFF1Bguest \u53EA\u770B\u5230\u81EA\u5DF1\u88AB\u6388\u6743 persona \u5B50\u6811\u4E0B\u7684",
|
|
6246
|
+
args: NO_ARGS
|
|
6247
|
+
},
|
|
6248
|
+
"history:list": {
|
|
6249
|
+
summary: "\u5217\u51FA\u67D0\u4E2A\u9879\u76EE\u4E0B\u7684\u5386\u53F2\u4F1A\u8BDD",
|
|
6250
|
+
args: HistoryListArgs
|
|
6251
|
+
},
|
|
6252
|
+
"history:read": {
|
|
6253
|
+
summary: "\u8BFB\u4E00\u6761\u5386\u53F2\u4F1A\u8BDD\u7684\u5B8C\u6574\u6D88\u606F\uFF08\u89E3\u6790 CC jsonl\uFF09",
|
|
6254
|
+
args: HistoryReadArgs
|
|
6255
|
+
},
|
|
6256
|
+
"history:subagents": {
|
|
6257
|
+
summary: "\u5217\u51FA\u67D0\u6B21\u4F1A\u8BDD\u91CC\u7684 subagent \u8FD0\u884C\u8BB0\u5F55",
|
|
6258
|
+
args: HistorySubagentsArgs
|
|
6259
|
+
},
|
|
6260
|
+
"history:subagent-read": {
|
|
6261
|
+
summary: "\u8BFB\u4E00\u6761 subagent \u7684\u5B8C\u6574\u8BB0\u5F55",
|
|
6262
|
+
args: HistorySubagentReadArgs
|
|
6263
|
+
},
|
|
6264
|
+
"history:recentDirs": {
|
|
6265
|
+
summary: "\u6700\u8FD1\u7528\u8FC7\u7684\u5DE5\u4F5C\u76EE\u5F55\u5217\u8868\uFF08\u6309 cwd \u53BB\u91CD\u3001\u53D6\u6700\u65B0 updatedAt\uFF09\u3002\u65E0\u53C2\u6570",
|
|
6266
|
+
args: NO_ARGS
|
|
6267
|
+
},
|
|
6268
|
+
"workspace:list": {
|
|
6269
|
+
summary: "\u5217\u76EE\u5F55\u5185\u5BB9\uFF08\u6587\u4EF6\u6D4F\u89C8\uFF09\uFF1Bguest \u88AB\u9650\u5236\u5728\u88AB\u6388\u6743 persona \u5B50\u6811\u5185",
|
|
6270
|
+
args: WorkspaceListArgs
|
|
6271
|
+
},
|
|
6272
|
+
"workspace:read": {
|
|
6273
|
+
summary: "\u8BFB\u6587\u4EF6\u5185\u5BB9\uFF1Bguest \u8DEF\u5F84\u8FB9\u754C\u4E0E workspace:list \u540C",
|
|
6274
|
+
args: WorkspaceReadArgs
|
|
6275
|
+
},
|
|
6276
|
+
"shift:list": {
|
|
6277
|
+
summary: "\u5217\u51FA owner \u7684\u5168\u90E8 shift\uFF08\u6392\u73ED\uFF09\uFF0C\u7ED9 UI \u65E5\u5386\u6E32\u67D3\u7528\uFF1Bowner-only",
|
|
6278
|
+
args: NO_ARGS
|
|
6279
|
+
},
|
|
6280
|
+
"shift-internal:add": {
|
|
6281
|
+
summary: "\u6392\u4E00\u4E2A shift\uFF08\u5230\u70B9\u81EA\u52A8\u62C9\u8D77 persona \u5E72\u6D3B\uFF09\u3002\u7701\u7565 targetPersona = \u6D3E\u7ED9\u8C03\u7528\u65B9\u81EA\u5DF1",
|
|
6282
|
+
args: ShiftInternalAddArgs
|
|
6283
|
+
},
|
|
6284
|
+
"shift-internal:list": {
|
|
6285
|
+
summary: "\u5217 shift\u3002\u7701\u7565 onlyMine \u9ED8\u8BA4 true \u2014\u2014 \u53EA\u5217\u672C persona \u5EFA\u7684",
|
|
6286
|
+
args: ShiftInternalListArgs
|
|
6287
|
+
},
|
|
6288
|
+
"shift-internal:cancel": {
|
|
6289
|
+
summary: "\u53D6\u6D88 shift\uFF08\u4EC5\u521B\u5EFA\u5B83\u7684 persona \u53EF\u64CD\u4F5C\uFF09",
|
|
6290
|
+
args: ShiftInternalCancelArgs
|
|
6291
|
+
},
|
|
6292
|
+
"shift-internal:update": {
|
|
6293
|
+
summary: "\u4FEE\u6539 shift \u5B57\u6BB5\uFF08\u4EC5\u521B\u5EFA\u8005\uFF09\u3002patch \u5141\u8BB8\u7684\u952E\uFF1Aname / schedule / prompt / targetPersona / timeoutMs / enabled\uFF1Bschedule \u53D8\u4E86 store \u81EA\u52A8\u91CD\u7B97 nextRunAtMs",
|
|
6294
|
+
args: ShiftInternalUpdateArgs
|
|
6295
|
+
},
|
|
6296
|
+
"shift-internal:history": {
|
|
6297
|
+
summary: "\u67E5 shift \u7684\u6267\u884C\u5386\u53F2\uFF08\u4EC5\u521B\u5EFA\u8005\uFF09",
|
|
6298
|
+
args: ShiftInternalHistoryArgs
|
|
6299
|
+
},
|
|
6300
|
+
"skills:list": {
|
|
6301
|
+
summary: "\u626B\u63CF\u5E76\u5217\u51FA\u8BE5\u76EE\u5F55\u53EF\u7528\u7684 skill",
|
|
6302
|
+
args: SkillsListArgs
|
|
6303
|
+
},
|
|
6304
|
+
"agents:list": {
|
|
6305
|
+
summary: "\u626B\u63CF\u5E76\u5217\u51FA\u8BE5\u76EE\u5F55\u53EF\u7528\u7684 subagent \u5B9A\u4E49",
|
|
6306
|
+
args: AgentsListArgs
|
|
6307
|
+
},
|
|
6308
|
+
"git:root": {
|
|
6309
|
+
summary: "\u53D6\u8BE5\u8DEF\u5F84\u6240\u5C5E git \u4ED3\u5E93\u7684\u6839\u76EE\u5F55\uFF08\u4E0D\u5728\u4ED3\u5E93\u91CC\u8FD4 null\uFF09",
|
|
6310
|
+
args: GitRootArgs
|
|
6311
|
+
},
|
|
6312
|
+
"git:branch": {
|
|
6313
|
+
summary: "\u53D6\u5F53\u524D\u5206\u652F\u540D",
|
|
6314
|
+
args: GitBranchArgs
|
|
6315
|
+
},
|
|
6316
|
+
"git:branches": {
|
|
6317
|
+
summary: "\u5217\u51FA\u672C\u5730\u5206\u652F",
|
|
6318
|
+
args: GitBranchesArgs
|
|
6319
|
+
},
|
|
6320
|
+
"capabilities:get": {
|
|
6321
|
+
summary: "\u53D6\u67D0\u4E2A tool \u7684\u80FD\u529B\u96C6\uFF1A\u53EF\u7528\u6A21\u578B\u5217\u8868 / permissionModes / configSchema",
|
|
6322
|
+
args: CapabilitiesGetArgs
|
|
6323
|
+
},
|
|
6324
|
+
"persona:create": {
|
|
6325
|
+
summary: "\u65B0\u5EFA persona\uFF08\u5199 PersonaFile + CLAUDE.md \u9AA8\u67B6\uFF09\u3002owner-only",
|
|
6326
|
+
args: PersonaCreateArgsSchema
|
|
6327
|
+
},
|
|
6328
|
+
"persona:list": {
|
|
6329
|
+
summary: "\u5217\u51FA persona \u5143\u6570\u636E\uFF08\u4E0D\u542B CLAUDE.md \u6B63\u6587\uFF09\u3002owner \u8FD4\u5168\u91CF\u542B private\uFF1Bguest \u53EA\u8FD4 public \u4E14\u88AB\u6388\u6743\u7684",
|
|
6330
|
+
args: NO_ARGS
|
|
6331
|
+
},
|
|
6332
|
+
"persona:get": {
|
|
6333
|
+
summary: "\u53D6\u5355\u4E2A persona \u8BE6\u60C5\uFF0C**\u542B personality\uFF08CLAUDE.md \u6B63\u6587\uFF09**\u2014\u2014\u552F\u4E00\u643A\u5E26\u6B63\u6587\u7684 method",
|
|
6334
|
+
args: PersonaIdArgsSchema
|
|
6335
|
+
},
|
|
6336
|
+
"persona:update": {
|
|
6337
|
+
summary: "\u6539 persona\uFF08label / model / public / CLAUDE.md \u7B49\uFF09\u3002owner-only",
|
|
6338
|
+
args: PersonaUpdateArgsSchema
|
|
6339
|
+
},
|
|
6340
|
+
"persona:delete": {
|
|
6341
|
+
summary: "\u5220 persona\u3002owner-only",
|
|
6342
|
+
args: PersonaIdArgsSchema
|
|
6343
|
+
},
|
|
6344
|
+
"personaDispatch:run": {
|
|
6345
|
+
summary: "\u628A\u4EFB\u52A1\u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08\u53EF\u8DE8\u8BBE\u5907\uFF09\uFF0C\u5F02\u6B65\u79D2\u56DE { dispatchId }\u3002targetPersona \u4E0E dispatchId **\u81F3\u5C11\u7ED9\u4E00\u4E2A**\uFF08\u524D\u8005\u65B0\u5F00\u3001\u540E\u8005\u7EED\u6D3E\uFF09\uFF1BdispatchId \u4E0E targetDeviceId **\u4E92\u65A5**",
|
|
6346
|
+
args: DispatchRunArgsSchema
|
|
6347
|
+
},
|
|
6348
|
+
"personaDispatch:complete": {
|
|
6349
|
+
summary: '\u88AB\u59D4\u6D3E\u65B9\u56DE\u62A5\u7ED3\u679C\uFF1A\u5199\u53F0\u8D26\u5E76\u628A\u7ED3\u679C\u6295\u9012\u56DE\u53D1\u8D77\u65B9\u4F1A\u8BDD\u3002outcome \u662F { kind:"success", text, filePaths? } \u6216 { kind:"failure", reason } \u4E8C\u9009\u4E00',
|
|
6350
|
+
args: DispatchCompleteArgsSchema
|
|
6351
|
+
},
|
|
6352
|
+
"personaDispatch:list": {
|
|
6353
|
+
summary: "\u67E5 dispatch \u53F0\u8D26\uFF08\u72B6\u6001 / \u7ED3\u679C / \u65F6\u95F4\u6233\uFF09\u3002\u7701\u7565 sourceSessionId = \u8FD4\u5168\u91CF",
|
|
6354
|
+
args: DispatchListArgsSchema
|
|
6355
|
+
},
|
|
6356
|
+
"personaDispatch:get": {
|
|
6357
|
+
summary: "\u67E5\u5355\u6761 dispatch \u53F0\u8D26\u7EC8\u6001\uFF1B\u8DE8\u8BBE\u5907\u65F6 A \u7AEF\u51ED connect token \u8F6E\u8BE2 B \u7AEF\u7528",
|
|
6358
|
+
args: DispatchGetArgsSchema
|
|
6359
|
+
},
|
|
6360
|
+
"peerExec:run": {
|
|
6361
|
+
summary: "\u5728\u8054\u7CFB\u4EBA\u8BBE\u5907\u4E0A\u8DD1\u4E00\u6761 bash \u547D\u4EE4\uFF08\u4E00\u53D1\u4E00\u6536\uFF0C\u65E0\u8DE8\u547D\u4EE4\u4F1A\u8BDD\u72B6\u6001\uFF09\u3002**\u672C\u673A\u53D1\u8D77\u5FC5\u586B peerDeviceId**\u2014\u2014\u7701\u7565\u4EC5\u7528\u4E8E\u5BF9\u7AEF guest \u53CD\u5411\u5165\u53E3\uFF0Cowner ctx \u7701\u7565\u4F1A\u88AB\u62D2\uFF1B\u9700\u5BF9\u65B9\u5F00\u4E86 remoteAccess",
|
|
6362
|
+
args: PeerExecRunArgsSchema
|
|
6363
|
+
},
|
|
6364
|
+
"session:pty:input": {
|
|
6365
|
+
summary: "\u628A\u7528\u6237\u952E\u76D8\u5B57\u8282\u5199\u8FDB pty stdin\uFF08\u4EC5 CLAWD_CC_MODE=tui\uFF09\u3002\u9AD8\u9891\u5E27\uFF0C\u4E0D\u5165 reducer\u3002body: { sessionId, data\uFF08base64-utf8\uFF09 }"
|
|
6366
|
+
},
|
|
6367
|
+
"session:pty:resize": {
|
|
6368
|
+
summary: "\u540C\u6B65\u7EC8\u7AEF\u5C3A\u5BF8\u7ED9 pty\uFF08\u4EC5 tui \u6A21\u5F0F\uFF09\u3002body: { sessionId, cols, rows }"
|
|
6369
|
+
},
|
|
6370
|
+
"session:pty:snapshot": {
|
|
6371
|
+
summary: "\u62C9\u5F53\u524D pty \u5C4F\u5E55\u5168\u91CF\u5FEB\u7167\uFF08\u5207\u56DE\u4F1A\u8BDD / \u5237\u65B0\u65F6\u7528\uFF09\uFF0C\u8FD4\u56DE { data, atSeq, popupKind }\uFF1B\u975E tui \u6216\u5DF2\u9000\u51FA\u65F6 data=null\u3002body: { sessionId }"
|
|
6372
|
+
},
|
|
6373
|
+
"attachment.signUrl": {
|
|
6374
|
+
summary: "\u7ED9\u5DF2\u5165\u7FA4\u7684\u6587\u4EF6\u7B7E\u53D1 HMAC \u4E0B\u8F7D URL\uFF08\u8DE8\u8BBE\u5907\u53EF\u76F4\u63A5\u6253\u5F00\uFF09",
|
|
6375
|
+
args: AttachmentSignUrlArgs
|
|
6376
|
+
},
|
|
6377
|
+
"attachment.groupAdd": {
|
|
6378
|
+
summary: "\u628A\u6587\u4EF6\u767B\u8BB0\u8FDB\u672C\u4F1A\u8BDD\u7684\u5171\u4EAB\u6E05\u5355\uFF08\u7B7E URL \u524D\u5FC5\u987B\u5148\u5165\u7FA4\uFF09",
|
|
6379
|
+
args: AttachmentGroupAddArgs
|
|
6380
|
+
},
|
|
6381
|
+
"attachment.groupRemove": {
|
|
6382
|
+
summary: "\u628A\u6587\u4EF6\u79FB\u51FA\u5171\u4EAB\u6E05\u5355",
|
|
6383
|
+
args: AttachmentGroupRemoveArgs
|
|
6384
|
+
},
|
|
6385
|
+
"attachment.groupList": {
|
|
6386
|
+
summary: "\u5217\u51FA\u672C\u4F1A\u8BDD\u5171\u4EAB\u6E05\u5355\u91CC\u7684\u6587\u4EF6",
|
|
6387
|
+
args: AttachmentGroupListArgs
|
|
6388
|
+
},
|
|
6389
|
+
"inbox:list": {
|
|
6390
|
+
summary: "\u62C9\u67D0\u4E2A peer \u7684 DM / \u901A\u77E5\u961F\u5217",
|
|
6391
|
+
args: InboxListArgsSchema
|
|
6392
|
+
},
|
|
6393
|
+
"inbox:markRead": {
|
|
6394
|
+
summary: "\u628A\u67D0 peer \u961F\u5217\u6807\u8BB0\u4E3A\u5DF2\u8BFB\u5230\u67D0\u65F6\u95F4\u70B9",
|
|
6395
|
+
args: InboxMarkReadArgsSchema
|
|
6396
|
+
},
|
|
6397
|
+
"inbox:postMessage": {
|
|
6398
|
+
summary: "\u6295\u9012\u4E00\u6761 P2P IM \u6D88\u606F\uFF08\u53CC\u6295\uFF1A\u672C\u673A\u843D\u5E93 + \u8F6C\u53D1\u5BF9\u7AEF\uFF09\u3002**owner \u8C03\u7528\u5FC5\u586B peerDeviceId**\uFF0C\u4EC5 guest \u53EF\u7701\uFF08\u4ECE ctx \u63A8\uFF09",
|
|
6399
|
+
args: InboxPostMessageArgsSchema
|
|
6400
|
+
},
|
|
6401
|
+
"inbox:sendDm": {
|
|
6402
|
+
summary: "\u4EE5\u5F53\u524D\u4F1A\u8BDD\u7684\u8EAB\u4EFD\u53D1\u4E00\u6761 DM\uFF08\u53D1\u4FE1\u4EBA\u7531 session scope \u5F52\u56E0\uFF0C\u4E0D\u53EF\u4F2A\u9020\uFF09\u3002**owner \u9A71\u52A8\u7684\u4F1A\u8BDD\u5FC5\u586B peerDeviceId**\uFF0Cguest \u9A71\u52A8\u7684\u53EF\u7701",
|
|
6403
|
+
args: InboxSendDmArgsSchema
|
|
6404
|
+
},
|
|
6405
|
+
"contact:list": {
|
|
6406
|
+
summary: "\u5217\u51FA\u8054\u7CFB\u4EBA\uFF08\u5DF2\u5EFA\u8054\u7684\u8BBE\u5907\uFF09\u3002owner-only",
|
|
6407
|
+
args: NO_ARGS
|
|
6408
|
+
},
|
|
6409
|
+
"contact:pin": {
|
|
6410
|
+
summary: "\u7F6E\u9876 / \u53D6\u6D88\u7F6E\u9876\u8054\u7CFB\u4EBA",
|
|
6411
|
+
args: ContactPinArgsSchema
|
|
6412
|
+
},
|
|
6413
|
+
"contact:remove": {
|
|
6414
|
+
summary: "\u5220\u9664\u8054\u7CFB\u4EBA\u5E76\u6E05\u6389\u5BF9\u5E94\u7684 inbox \u961F\u5217",
|
|
6415
|
+
args: ContactRemoveArgsSchema
|
|
6416
|
+
},
|
|
6417
|
+
"contact:setRemoteAccess": {
|
|
6418
|
+
summary: "\u5F00\u5173\u67D0\u8054\u7CFB\u4EBA\u7684\u8FDC\u7A0B\u8BBF\u95EE\u6388\u6743\uFF08\u63A7\u5236\u5B83\u80FD\u5426\u53CD\u5411 peerExec \u6211\u7684\u8BBE\u5907\uFF09",
|
|
6419
|
+
args: ContactSetRemoteAccessArgsSchema
|
|
6420
|
+
},
|
|
6421
|
+
"contact:handshake": {
|
|
6422
|
+
summary: "\u53CC\u5411\u786E\u8BA4\u5EFA\u8054\u63E1\u624B\uFF1A\u8FDE\u63A5\u65B9\u81EA\u62A5 selfUrl\uFF0C\u88AB\u8FDE\u65B9\u843D\u5E93 + \u5E7F\u64AD\u540E\u56DE\u8EAB\u4EFD\u8F7D\u8377\u3002\u7531 device:connect \u7684\u4E34\u65F6\u8FDE\u63A5\u8C03\u7528",
|
|
6423
|
+
args: ContactHandshakeArgsSchema
|
|
6424
|
+
},
|
|
6425
|
+
"visitor:list": {
|
|
6426
|
+
summary: "\u5217\u51FA\u767B\u5F55\u8BBF\u95EE\u8FC7\u672C\u673A public persona \u7684 web \u8BBF\u5BA2\u3002owner-only",
|
|
6427
|
+
args: NO_ARGS
|
|
6428
|
+
},
|
|
6429
|
+
"whoami": {
|
|
6430
|
+
summary: "\u8FD4\u56DE\u672C\u8FDE\u63A5\u7684\u8EAB\u4EFD\uFF1Aowner \u663E\u793A\u540D + capability wire \u5F62\u6001 + \u88AB\u6388\u6743\u7684 persona \u5217\u8868\u3002\u4EFB\u4F55 authed \u8FDE\u63A5\u53EF\u8C03",
|
|
6431
|
+
args: NO_ARGS
|
|
6432
|
+
},
|
|
6433
|
+
"info": {
|
|
6434
|
+
summary: "daemon \u8FD0\u884C\u65F6\u4FE1\u606F\uFF1A\u7248\u672C / \u534F\u8BAE\u7248\u672C / \u4E3B\u673A / \u53EF\u7528 tool / \u5728\u8DD1\u7684\u4F1A\u8BDD / tunnel URL \u7B49",
|
|
6435
|
+
args: NO_ARGS
|
|
6436
|
+
},
|
|
6437
|
+
"ping": {
|
|
6438
|
+
summary: "\u5B58\u6D3B\u63A2\u6D4B\uFF0C\u56DE pong",
|
|
6439
|
+
args: NO_ARGS
|
|
6440
|
+
},
|
|
6441
|
+
"meta:methods": {
|
|
6442
|
+
summary: "RPC \u81EA\u7701\uFF1A\u8FD4\u56DE METHOD_NAMES \u5168\u96C6 + **\u5BF9\u672C\u8FDE\u63A5**\u7684\u53EF\u8C03\u7528\u6027\u4E09\u6001\uFF08allowed / conditional / denied\uFF09+ \u6BCF\u6761\u7684\u8BF4\u660E\u3002agent \u4FA7 clawd-rpc \u7684 list tool \u662F\u552F\u4E00\u6D88\u8D39\u65B9",
|
|
6443
|
+
args: NO_ARGS
|
|
6444
|
+
},
|
|
6445
|
+
"extension.list": {
|
|
6446
|
+
summary: "\u5217\u51FA\u5DF2\u5B89\u88C5\u7684 extension",
|
|
6447
|
+
args: NO_ARGS
|
|
6448
|
+
},
|
|
6449
|
+
"extension.open": {
|
|
6450
|
+
summary: "\u62C9\u8D77\u67D0\u4E2A extension\uFF08local-spawn \u8D77\u8FDB\u7A0B\u5E76\u7B49 healthz\uFF09",
|
|
6451
|
+
args: ExtensionIdArgs
|
|
6452
|
+
},
|
|
6453
|
+
"extension.close": {
|
|
6454
|
+
summary: "\u5173\u6389\u67D0\u4E2A\u6B63\u5728\u8DD1\u7684 extension",
|
|
6455
|
+
args: ExtensionIdArgs
|
|
6456
|
+
},
|
|
6457
|
+
"extension.uninstall": {
|
|
6458
|
+
summary: "\u5378\u8F7D extension\uFF08\u5220\u5B89\u88C5\u76EE\u5F55\uFF09",
|
|
6459
|
+
args: ExtensionIdArgs
|
|
6460
|
+
},
|
|
6461
|
+
"extension.publish": {
|
|
6462
|
+
summary: "\u628A\u672C\u673A extension \u516C\u5F00\u5230\u5206\u4EAB\u9891\u9053\uFF0C\u4F9B\u8054\u7CFB\u4EBA\u62C9\u53D6\u3002owner-only",
|
|
6463
|
+
args: ExtensionPublishArgs
|
|
6464
|
+
},
|
|
6465
|
+
"extension.unpublish": {
|
|
6466
|
+
summary: "\u64A4\u56DE\u5DF2\u516C\u5F00\u7684 extension\u3002owner-only",
|
|
6467
|
+
args: ExtensionIdArgs
|
|
6468
|
+
},
|
|
6469
|
+
"extension.publish:status": {
|
|
6470
|
+
summary: "\u67E5\u67D0\u4E2A extension \u7684\u516C\u5F00\u72B6\u6001\u3002owner-only",
|
|
6471
|
+
args: ExtensionIdArgs
|
|
6472
|
+
},
|
|
6473
|
+
"extension.list-published": {
|
|
6474
|
+
summary: "\uFF08\u8DE8\u8BBE\u5907\uFF09\u4ECE\u5BF9\u7AEF owner \u62C9\u5B83\u516C\u5F00\u7684 extension \u6E05\u5355",
|
|
6475
|
+
args: NO_ARGS
|
|
6476
|
+
},
|
|
6477
|
+
"extension.fetchBundle": {
|
|
6478
|
+
summary: "\uFF08\u8DE8\u8BBE\u5907\uFF09\u4ECE\u5BF9\u7AEF owner \u4E0B\u8F7D extension bundle \u5B57\u8282\u3002extId \u5FC5\u4F20\u4F46\u4E0D\u53C2\u4E0E\u7D22\u5F15\u2014\u2014\u771F\u6B63\u7684\u952E\u662F snapshotHash\uFF08publish \u90A3\u523B\u51BB\u7ED3\u7684\u90A3\u4EFD\uFF0C\u4E0E owner \u5DE5\u4F5C\u76EE\u5F55\u540E\u7EED\u53D8\u5316\u89E3\u8026\uFF09",
|
|
6479
|
+
args: ExtensionFetchBundleArgs
|
|
6480
|
+
},
|
|
6481
|
+
"extension.install-from-channel": {
|
|
6482
|
+
summary: "\u5728\u81EA\u5DF1 daemon \u4E0A\u4ECE\u5206\u4EAB\u9891\u9053\u5B89\u88C5 extension",
|
|
6483
|
+
args: ExtensionFromChannelArgs
|
|
6484
|
+
},
|
|
6485
|
+
"extension.update-from-channel": {
|
|
6486
|
+
summary: "\u5728\u81EA\u5DF1 daemon \u4E0A\u628A\u5DF2\u88C5 extension \u66F4\u65B0\u5230\u9891\u9053\u6700\u65B0\u7248",
|
|
6487
|
+
args: ExtensionFromChannelArgs
|
|
6488
|
+
},
|
|
6489
|
+
"auth:login:start": {
|
|
6490
|
+
summary: "\u8D77\u98DE\u4E66\u767B\u5F55\u6D41\u7A0B\uFF1A\u751F\u6210 state \u5E76\u8FD4\u56DE\u6388\u6743 URL\uFF0C\u56DE\u8C03\u8D70 HTTP /auth/callback \u843D\u76D8\u3002owner-only",
|
|
6491
|
+
args: NO_ARGS
|
|
6492
|
+
},
|
|
6493
|
+
"auth:getIdentity": {
|
|
6494
|
+
summary: "\u53D6\u672C\u673A owner \u7684\u98DE\u4E66\u8EAB\u4EFD\uFF08ownerId / provider / displayName / unionId\uFF09+ **\u672C\u673A deviceId**\uFF08\u8BBE\u5907\u5C5E\u6027\uFF0C\u4E0E\u767B\u5F55\u6001\u65E0\u5173\uFF1Bdevice:connect / contact:* / inbox:* \u7684\u4E3B\u952E\u90FD\u662F\u5B83\uFF09\uFF1B\u7EDD\u4E0D\u8FD4\u56DE ttcToken",
|
|
6495
|
+
args: NO_ARGS
|
|
6496
|
+
},
|
|
6497
|
+
"auth:logout": {
|
|
6498
|
+
summary: "\u767B\u51FA\u98DE\u4E66\u8EAB\u4EFD\uFF08\u6E05 owner-identity \u843D\u76D8\uFF09\u3002owner-only",
|
|
6499
|
+
args: NO_ARGS
|
|
6500
|
+
},
|
|
6501
|
+
"device:list": {
|
|
6502
|
+
summary: "\u5217\u51FA\u516C\u5171\u8BBE\u5907\u76EE\u5F55\u91CC\u53EF\u8FDE\u63A5\u7684\u8BBE\u5907\uFF08daemon \u4EE3\u7406\u4E2D\u5FC3 server\uFF09\u3002owner-only",
|
|
6503
|
+
args: NO_ARGS
|
|
6504
|
+
},
|
|
6505
|
+
"device:connect": {
|
|
6506
|
+
summary: "\u8FDE\u63A5\u76EE\u6807\u8BBE\u5907\uFF1A\u6362 aud \u7ED1\u5B9A\u7684\u7B7E\u540D token \u5E76\u8D70 contact:handshake \u5EFA\u8054\u3002owner-only",
|
|
6507
|
+
args: DeviceConnectArgsSchema
|
|
6508
|
+
},
|
|
6509
|
+
"appBuilder:listProjects": {
|
|
6510
|
+
summary: "\u5217\u51FA app-builder project\uFF08\u542B dev server \u72B6\u6001\uFF09",
|
|
6511
|
+
args: ListProjectsArgsSchema
|
|
6512
|
+
},
|
|
6513
|
+
"appBuilder:getProject": {
|
|
6514
|
+
summary: "\u6309 sessionId \u53D6\u5355\u4E2A\u7ED1\u5B9A\u7684 project\uFF08\u542B status\uFF09",
|
|
6515
|
+
args: GetProjectArgsSchema
|
|
6516
|
+
},
|
|
6517
|
+
"appBuilder:createProject": {
|
|
6518
|
+
summary: "\u7ED9\u4F1A\u8BDD\u7ED1\u5B9A\u65B0 project\uFF1A\u6821\u9A8C\u540D + \u4ECE 6173-6182 \u6BB5\u5206\u914D\u7AEF\u53E3 + \u5EFA\u76EE\u5F55\u5199\u5143\u6570\u636E",
|
|
6519
|
+
args: CreateProjectArgsSchema
|
|
6520
|
+
},
|
|
6521
|
+
"appBuilder:deleteProject": {
|
|
6522
|
+
summary: "\u505C dev server + \u5220 project \u76EE\u5F55\uFF08\u7ED1\u5B9A\u7684\u4F1A\u8BDD\u4E0D\u5728\u8FD9\u91CC\u5220\uFF09",
|
|
6523
|
+
args: DeleteProjectArgsSchema
|
|
6524
|
+
},
|
|
6525
|
+
"appBuilder:updateProjectPort": {
|
|
6526
|
+
summary: "\u6539 dev server \u7AEF\u53E3\uFF08\u6821\u9A8C\u6BB5\u5185 + \u4E0D\u649E\u8F66\uFF09\u5E76\u91CD\u542F",
|
|
6527
|
+
args: UpdateProjectPortArgsSchema
|
|
6528
|
+
},
|
|
6529
|
+
"appBuilder:setProdUrl": {
|
|
6530
|
+
summary: "\u53D1\u5E03\u4E0A\u7EBF\u540E\u56DE\u586B\u7EBF\u4E0A\u5730\u5740\u5230 .clawd-project.json",
|
|
6531
|
+
args: SetProdUrlArgsSchema
|
|
6532
|
+
},
|
|
6533
|
+
"appBuilder:startDevServer": {
|
|
6534
|
+
summary: "scaffold + \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210\u540E\u663E\u5F0F\u62C9\u8D77 dev server\uFF08createProject \u4E0D\u518D\u81EA\u52A8\u8D77\uFF09",
|
|
6535
|
+
args: StartDevServerArgsSchema
|
|
6536
|
+
},
|
|
6537
|
+
"appBuilder:reportStage": {
|
|
6538
|
+
summary: "\u4E0A\u62A5\u811A\u624B\u67B6\u9636\u6BB5\uFF08scaffolding / installing / failed \u7B49\uFF09\uFF0Cdaemon \u5E7F\u64AD\u5E27\u8BA9 UI \u5207 PreviewPane",
|
|
6539
|
+
args: ReportStageArgsSchema
|
|
6540
|
+
},
|
|
6541
|
+
"appBuilder:stopDevServer": {
|
|
6542
|
+
summary: "\u6536\u8D77\u9884\u89C8\uFF1A\u505C\u6389 dev server\uFF08\u5BF9\u79F0 startDevServer\uFF09",
|
|
6543
|
+
args: StopDevServerArgsSchema
|
|
6544
|
+
},
|
|
6545
|
+
"appBuilder:publish": {
|
|
6546
|
+
summary: "\u53D1\u5E03\u4E0A\u7EBF\uFF1A\u4E32\u884C\u5316 spawn publish.sh \u5E76\u5E7F\u64AD\u9636\u6BB5\u8FDB\u5EA6\u5E27\uFF1B\u540C project \u5DF2\u6709 in-flight job \u65F6\u8FD4\u56DE already-publishing",
|
|
6547
|
+
args: PublishArgsSchema
|
|
6548
|
+
},
|
|
6549
|
+
"appBuilder:dismissPublishJob": {
|
|
6550
|
+
summary: "\u53D6\u6D88 in-flight publish\uFF08SIGTERM \u5B50\u8FDB\u7A0B\uFF09\u6216\u6E05\u6389 daemon \u5D29\u6E83\u7559\u4E0B\u7684\u6B8B\u9AB8 publishJob \u5B57\u6BB5",
|
|
6551
|
+
args: DismissPublishJobArgsSchema
|
|
6552
|
+
}
|
|
6553
|
+
};
|
|
6554
|
+
METHOD_NAMES = Object.keys(METHOD_DOCS);
|
|
6555
|
+
RPC_METHOD_STATUSES = ["allowed", "conditional", "denied"];
|
|
6556
|
+
RpcMethodStatusSchema = external_exports.enum(RPC_METHOD_STATUSES);
|
|
6557
|
+
RpcMethodInfoSchema = external_exports.object({
|
|
6558
|
+
/** canonical method 名,直接可作为 clawd-rpc call 的 method 参数 */
|
|
6183
6559
|
name: external_exports.string().min(1),
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
DeviceListResponseSchema = external_exports.object({
|
|
6188
|
-
type: external_exports.literal("device:list:ok"),
|
|
6189
|
-
devices: external_exports.array(DeviceEntrySchema)
|
|
6190
|
-
});
|
|
6191
|
-
DeviceConnectArgsSchema = external_exports.object({
|
|
6192
|
-
/** 目标设备的 deviceId(对方 daemon 生成的 dev-<uuid>) */
|
|
6193
|
-
deviceId: external_exports.string().min(1),
|
|
6560
|
+
status: RpcMethodStatusSchema,
|
|
6561
|
+
/** 该 method 干什么,取自 {@link METHOD_DOCS} 的 summary */
|
|
6562
|
+
description: external_exports.string().min(1),
|
|
6194
6563
|
/**
|
|
6195
|
-
*
|
|
6196
|
-
*
|
|
6197
|
-
* - 凭 deviceId 连接:缺省 url → daemon exchange 时由中心 server 下发该设备上报的 url
|
|
6198
|
-
* - 注册表不在安全路径上:知道对方 url 时显式传入即可连接(不依赖中心 server 服务发现)
|
|
6564
|
+
* 参数字段,从 {@link METHOD_DOCS} 的 args schema **反射**得来(不手写)。
|
|
6565
|
+
* `null` = 该 method 还没有中央 zod schema(欠账,见 RpcMethodDoc),调用方需自行试探。
|
|
6199
6566
|
*/
|
|
6200
|
-
|
|
6201
|
-
/** 显示名(公共设备来自目录;缺省时连上后用 whoami 回填) */
|
|
6202
|
-
name: external_exports.string().optional()
|
|
6203
|
-
});
|
|
6204
|
-
DeviceConnectResponseSchema = external_exports.object({
|
|
6205
|
-
type: external_exports.literal("device:connect:ok"),
|
|
6206
|
-
/** 连接的目标设备标识(= 请求 args.deviceId) */
|
|
6207
|
-
deviceId: external_exports.string(),
|
|
6208
|
-
name: external_exports.string(),
|
|
6209
|
-
url: external_exports.string()
|
|
6210
|
-
});
|
|
6211
|
-
FeishuIdentitySchema = external_exports.object({
|
|
6212
|
-
/** 归属人 id(决策 #16:TTC unique_id,取代飞书 union_id;跨登录方式稳定) */
|
|
6213
|
-
ownerId: external_exports.string().min(1),
|
|
6214
|
-
/** 身份来源:'ttc'(飞书/手机/邮箱登入 TTC)| 'google' | ...(决策 #16,拓展用) */
|
|
6215
|
-
provider: external_exports.string().min(1),
|
|
6216
|
-
/** 显示名。TTC user_info 接口 data.name */
|
|
6217
|
-
displayName: external_exports.string().min(1),
|
|
6218
|
-
/** TTC user_info 接口 data.avatar_url,可缺省 */
|
|
6219
|
-
avatarUrl: external_exports.string().optional(),
|
|
6220
|
-
/** TTC user_info 接口 data.union_id(飞书 union_id;dataclaw 可信入口 X-User-UnionId 用),可缺省 */
|
|
6221
|
-
unionId: external_exports.string().optional()
|
|
6222
|
-
});
|
|
6223
|
-
AuthLoginStartResponseSchema = external_exports.object({
|
|
6224
|
-
type: external_exports.literal("auth:login:start:ok"),
|
|
6225
|
-
/** 完整 TTC 授权页 URL(含 callback_url + state + auto=1),UI 直接 window.open */
|
|
6226
|
-
authUrl: external_exports.string().min(1),
|
|
6227
|
-
/** 防 CSRF 的一次性 nonce;回调时 daemon 校验 */
|
|
6228
|
-
state: external_exports.string().min(1)
|
|
6229
|
-
});
|
|
6230
|
-
AuthGetIdentityResponseSchema = external_exports.object({
|
|
6231
|
-
type: external_exports.literal("auth:getIdentity:ok"),
|
|
6232
|
-
/** null = 未登录 */
|
|
6233
|
-
identity: FeishuIdentitySchema.nullable(),
|
|
6567
|
+
args: external_exports.array(external_exports.object({ name: external_exports.string(), required: external_exports.boolean() })).nullable(),
|
|
6234
6568
|
/**
|
|
6235
|
-
*
|
|
6236
|
-
*
|
|
6237
|
-
*
|
|
6569
|
+
* `denied` 必带:daemon error code(`UNAUTHORIZED` / `FEISHU_LOGIN_REQUIRED` /
|
|
6570
|
+
* `METHOD_NOT_IMPLEMENTED`)。`conditional` 必带:谁来做二次校验。
|
|
6571
|
+
* `allowed` 恒无。
|
|
6238
6572
|
*/
|
|
6239
|
-
|
|
6240
|
-
});
|
|
6241
|
-
AuthLogoutResponseSchema = external_exports.object({
|
|
6242
|
-
type: external_exports.literal("auth:logout:ok")
|
|
6243
|
-
});
|
|
6244
|
-
AuthLoginDoneEventSchema = external_exports.object({
|
|
6245
|
-
type: external_exports.literal("auth:login:done"),
|
|
6246
|
-
identity: FeishuIdentitySchema
|
|
6573
|
+
reason: external_exports.string().optional()
|
|
6247
6574
|
});
|
|
6248
|
-
|
|
6249
|
-
type: external_exports.literal("
|
|
6250
|
-
|
|
6575
|
+
MetaMethodsResultSchema = external_exports.object({
|
|
6576
|
+
type: external_exports.literal("meta:methods"),
|
|
6577
|
+
/** METHOD_NAMES 全集,顺序与之一致 */
|
|
6578
|
+
methods: external_exports.array(RpcMethodInfoSchema)
|
|
6251
6579
|
});
|
|
6252
6580
|
}
|
|
6253
6581
|
});
|
|
6254
6582
|
|
|
6255
|
-
// ../protocol/src/
|
|
6256
|
-
var
|
|
6257
|
-
var
|
|
6258
|
-
"../protocol/src/
|
|
6583
|
+
// ../protocol/src/errors.ts
|
|
6584
|
+
var ERROR_CODES, ClawdError;
|
|
6585
|
+
var init_errors2 = __esm({
|
|
6586
|
+
"../protocol/src/errors.ts"() {
|
|
6587
|
+
"use strict";
|
|
6588
|
+
ERROR_CODES = {
|
|
6589
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
6590
|
+
SESSION_BUSY: "SESSION_BUSY",
|
|
6591
|
+
INVALID_CWD: "INVALID_CWD",
|
|
6592
|
+
INVALID_PATH: "INVALID_PATH",
|
|
6593
|
+
TOOL_NOT_SUPPORTED: "TOOL_NOT_SUPPORTED",
|
|
6594
|
+
CLAUDE_NOT_FOUND: "CLAUDE_NOT_FOUND",
|
|
6595
|
+
SPAWN_FAILED: "SPAWN_FAILED",
|
|
6596
|
+
INVALID_PERMISSION_MODE: "INVALID_PERMISSION_MODE",
|
|
6597
|
+
METHOD_NOT_IMPLEMENTED: "METHOD_NOT_IMPLEMENTED",
|
|
6598
|
+
METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED",
|
|
6599
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
6600
|
+
PERMISSION_REQUEST_STALE: "PERMISSION_REQUEST_STALE",
|
|
6601
|
+
FILE_TOO_LARGE: "FILE_TOO_LARGE",
|
|
6602
|
+
INTERNAL: "INTERNAL",
|
|
6603
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
6604
|
+
FORBIDDEN: "FORBIDDEN",
|
|
6605
|
+
INVALID_PARAM: "INVALID_PARAM",
|
|
6606
|
+
// 飞书统一身份(spec 2026-06-01 决策 #9):People/远程体系强制飞书登录。
|
|
6607
|
+
// daemon 进程身份未激活为飞书 unionId 时,FEISHU_GATED_METHODS 内的 RPC 一律返回此错误;
|
|
6608
|
+
// UI 据此显示登录引导(区别于 UNAUTHORIZED 的越权语义)。
|
|
6609
|
+
FEISHU_LOGIN_REQUIRED: "FEISHU_LOGIN_REQUIRED",
|
|
6610
|
+
// app-builder 单栏默认 refactor (spec 2026-06-02-app-builder-single-pane-default-design):
|
|
6611
|
+
// appBuilder:createProject 加 personaId + session 未绑校验后抛的两个错码。
|
|
6612
|
+
WRONG_PERSONA: "WRONG_PERSONA",
|
|
6613
|
+
SESSION_ALREADY_BOUND: "SESSION_ALREADY_BOUND",
|
|
6614
|
+
// 2026-07-02 unified people sidebar: contact:pin 时 deviceId 不在 store(可能被别处删了)
|
|
6615
|
+
CONTACT_NOT_FOUND: "CONTACT_NOT_FOUND",
|
|
6616
|
+
// 统一 RPC 鉴权(spec 2026-07-28):personaDispatch:get 查不到台账行,或 guest ctx
|
|
6617
|
+
// 查非自己发起的行(越权与未知 id 同码,不泄露存在性)。A 端轮询遇此码立即判失败。
|
|
6618
|
+
DISPATCH_NOT_FOUND: "DISPATCH_NOT_FOUND"
|
|
6619
|
+
};
|
|
6620
|
+
ClawdError = class extends Error {
|
|
6621
|
+
constructor(code, message) {
|
|
6622
|
+
super(message);
|
|
6623
|
+
this.code = code;
|
|
6624
|
+
this.name = "ClawdError";
|
|
6625
|
+
}
|
|
6626
|
+
code;
|
|
6627
|
+
};
|
|
6628
|
+
}
|
|
6629
|
+
});
|
|
6630
|
+
|
|
6631
|
+
// ../protocol/src/frames.ts
|
|
6632
|
+
var PROTOCOL_VERSION, DISPATCH_MCP_ID;
|
|
6633
|
+
var init_frames = __esm({
|
|
6634
|
+
"../protocol/src/frames.ts"() {
|
|
6635
|
+
"use strict";
|
|
6636
|
+
PROTOCOL_VERSION = 1;
|
|
6637
|
+
DISPATCH_MCP_ID = "dispatch";
|
|
6638
|
+
}
|
|
6639
|
+
});
|
|
6640
|
+
|
|
6641
|
+
// ../protocol/src/persona-mode.ts
|
|
6642
|
+
var init_persona_mode = __esm({
|
|
6643
|
+
"../protocol/src/persona-mode.ts"() {
|
|
6259
6644
|
"use strict";
|
|
6260
|
-
init_zod();
|
|
6261
|
-
DispatchOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
6262
|
-
external_exports.object({
|
|
6263
|
-
kind: external_exports.literal("success"),
|
|
6264
|
-
text: external_exports.string(),
|
|
6265
|
-
filePaths: external_exports.array(external_exports.string()).optional()
|
|
6266
|
-
}),
|
|
6267
|
-
external_exports.object({
|
|
6268
|
-
kind: external_exports.literal("failure"),
|
|
6269
|
-
reason: external_exports.string()
|
|
6270
|
-
})
|
|
6271
|
-
]);
|
|
6272
|
-
DispatchRunArgsSchema = external_exports.object({
|
|
6273
|
-
// 新开必填;续派(dispatchId 非空)时可省略——targetPersonaId 从台账行取。
|
|
6274
|
-
targetPersona: external_exports.string().min(1).optional(),
|
|
6275
|
-
// 续派(spec 2026-07-21,单 dispatchId 语义:一件事一行一 id):非空 = 把 prompt
|
|
6276
|
-
// 作为新 turn 打进该 dispatch 的原 worker session 接着干(台账行复位 running)。
|
|
6277
|
-
// 省略 = 新开一件事,daemon 铸新 id。
|
|
6278
|
-
dispatchId: external_exports.string().min(1).optional(),
|
|
6279
|
-
prompt: external_exports.string(),
|
|
6280
|
-
// 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
|
|
6281
|
-
// 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
|
|
6282
|
-
targetDeviceId: external_exports.string().min(1).optional(),
|
|
6283
|
-
// 可选:override B session 使用的 claude 模型。缺省 = 用 persona 默认。
|
|
6284
|
-
// 合法值集与 claude adapter capabilities.models[].id 一致(见 daemon
|
|
6285
|
-
// tools/claude.ts CLAUDE_MODEL_IDS);handler 层做二次校验,非法值 fail-fast。
|
|
6286
|
-
// protocol 层保持 string 便于未来跨 tool 扩展(届时 union 收合法字面量)。
|
|
6287
|
-
model: external_exports.string().min(1).optional(),
|
|
6288
|
-
// 可选:给新 worker session 起 label(写入 SessionFile.label,sidebar 显示)。
|
|
6289
|
-
// 仅在**新开 dispatch**(dispatchId 缺席)时生效;续派(dispatchId 非空)
|
|
6290
|
-
// 时 daemon 层静默丢弃(避免半途改 label 造成 sidebar 抖动)。
|
|
6291
|
-
// 上限 60 字符——sidebar 显示 tolerance,卡在 dispatch 入口即可。
|
|
6292
|
-
// 协议层不硬拒 sessionLabel + dispatchId 同传,保留 forward-compat。
|
|
6293
|
-
sessionLabel: external_exports.string().min(1).max(60).optional()
|
|
6294
|
-
}).refine((v2) => v2.targetPersona !== void 0 || v2.dispatchId !== void 0, {
|
|
6295
|
-
message: "either targetPersona (new dispatch) or dispatchId (follow-up) is required"
|
|
6296
|
-
}).refine((v2) => !(v2.dispatchId !== void 0 && v2.targetDeviceId !== void 0), {
|
|
6297
|
-
message: "cross-device dispatch cannot be continued (dispatchId + targetDeviceId are mutually exclusive)"
|
|
6298
|
-
});
|
|
6299
|
-
DispatchCompleteArgsSchema = external_exports.object({
|
|
6300
|
-
dispatchId: external_exports.string().min(1),
|
|
6301
|
-
outcome: DispatchOutcomeSchema
|
|
6302
|
-
});
|
|
6303
|
-
DISPATCH_STATUSES = ["running", "completed", "failed"];
|
|
6304
|
-
DispatchStatusSchema = external_exports.enum(DISPATCH_STATUSES);
|
|
6305
|
-
DispatchRecordSchema = external_exports.object({
|
|
6306
|
-
dispatchId: external_exports.string().min(1),
|
|
6307
|
-
sourceSessionId: external_exports.string().min(1),
|
|
6308
|
-
sourcePersonaId: external_exports.string().min(1).optional(),
|
|
6309
|
-
targetPersonaId: external_exports.string().min(1),
|
|
6310
|
-
/** B 的 sessionId;registerBSession 后回填 */
|
|
6311
|
-
workerSessionId: external_exports.string().min(1).optional(),
|
|
6312
|
-
/** 任务摘要;截断(≤500 字符)在 daemon store.add 处保证 */
|
|
6313
|
-
taskText: external_exports.string(),
|
|
6314
|
-
status: DispatchStatusSchema,
|
|
6315
|
-
outcome: DispatchOutcomeSchema.optional(),
|
|
6316
|
-
/** 上层消费者语义(如司礼监的口谕/验收状态),daemon 不解释 */
|
|
6317
|
-
meta: external_exports.record(external_exports.unknown()).optional(),
|
|
6318
|
-
createdAt: external_exports.string().min(1),
|
|
6319
|
-
completedAt: external_exports.string().min(1).optional(),
|
|
6320
|
-
/** 结果注入 source session 成功时戳,兼当投递 dedup 标记 */
|
|
6321
|
-
deliveredAt: external_exports.string().min(1).optional()
|
|
6322
|
-
});
|
|
6323
|
-
DispatchListArgsSchema = external_exports.object({
|
|
6324
|
-
sourceSessionId: external_exports.string().min(1).optional()
|
|
6325
|
-
});
|
|
6326
|
-
DispatchListResultSchema = external_exports.object({
|
|
6327
|
-
records: external_exports.array(DispatchRecordSchema)
|
|
6328
|
-
});
|
|
6329
|
-
DispatchGetArgsSchema = external_exports.object({
|
|
6330
|
-
dispatchId: external_exports.string().min(1)
|
|
6331
|
-
});
|
|
6332
|
-
DispatchGetOkSchema = external_exports.object({
|
|
6333
|
-
type: external_exports.literal("personaDispatch:get:ok"),
|
|
6334
|
-
status: DispatchStatusSchema,
|
|
6335
|
-
outcome: DispatchOutcomeSchema.optional()
|
|
6336
|
-
});
|
|
6337
6645
|
}
|
|
6338
6646
|
});
|
|
6339
6647
|
|
|
@@ -6413,6 +6721,7 @@ var init_runtime = __esm({
|
|
|
6413
6721
|
init_dispatch();
|
|
6414
6722
|
init_log();
|
|
6415
6723
|
init_visitor_schemas();
|
|
6724
|
+
init_shift_internal();
|
|
6416
6725
|
}
|
|
6417
6726
|
});
|
|
6418
6727
|
|
|
@@ -41624,21 +41933,21 @@ var SessionStoreFactory = class {
|
|
|
41624
41933
|
bareRoot() {
|
|
41625
41934
|
return path5.join(this.dataDir, "sessions");
|
|
41626
41935
|
}
|
|
41627
|
-
vmOwnerRoot(
|
|
41936
|
+
vmOwnerRoot(personaId2) {
|
|
41628
41937
|
return path5.join(
|
|
41629
41938
|
this.dataDir,
|
|
41630
41939
|
"personas",
|
|
41631
|
-
safeFileName(
|
|
41940
|
+
safeFileName(personaId2),
|
|
41632
41941
|
".clawd",
|
|
41633
41942
|
"sessions",
|
|
41634
41943
|
"owner"
|
|
41635
41944
|
);
|
|
41636
41945
|
}
|
|
41637
|
-
vmGuestRoot(
|
|
41946
|
+
vmGuestRoot(personaId2, capId) {
|
|
41638
41947
|
return path5.join(
|
|
41639
41948
|
this.dataDir,
|
|
41640
41949
|
"personas",
|
|
41641
|
-
safeFileName(
|
|
41950
|
+
safeFileName(personaId2),
|
|
41642
41951
|
".clawd",
|
|
41643
41952
|
"sessions",
|
|
41644
41953
|
"guests",
|
|
@@ -41652,19 +41961,19 @@ var SessionStoreFactory = class {
|
|
|
41652
41961
|
}
|
|
41653
41962
|
return this.bareStore;
|
|
41654
41963
|
}
|
|
41655
|
-
forVmOwner(
|
|
41656
|
-
const key =
|
|
41964
|
+
forVmOwner(personaId2) {
|
|
41965
|
+
const key = personaId2;
|
|
41657
41966
|
const cached = this.vmOwnerStores.get(key);
|
|
41658
41967
|
if (cached) return cached;
|
|
41659
|
-
const st = new SessionStore({ root: this.vmOwnerRoot(
|
|
41968
|
+
const st = new SessionStore({ root: this.vmOwnerRoot(personaId2) });
|
|
41660
41969
|
this.vmOwnerStores.set(key, st);
|
|
41661
41970
|
return st;
|
|
41662
41971
|
}
|
|
41663
|
-
forVmGuest(
|
|
41664
|
-
const key = `${
|
|
41972
|
+
forVmGuest(personaId2, capId) {
|
|
41973
|
+
const key = `${personaId2}::${capId}`;
|
|
41665
41974
|
const cached = this.vmGuestStores.get(key);
|
|
41666
41975
|
if (cached) return cached;
|
|
41667
|
-
const st = new SessionStore({ root: this.vmGuestRoot(
|
|
41976
|
+
const st = new SessionStore({ root: this.vmGuestRoot(personaId2, capId) });
|
|
41668
41977
|
this.vmGuestStores.set(key, st);
|
|
41669
41978
|
return st;
|
|
41670
41979
|
}
|
|
@@ -42146,8 +42455,8 @@ function buildSpawnContext(state, deps) {
|
|
|
42146
42455
|
if (clawosApi) env.CLAWOS_API = clawosApi;
|
|
42147
42456
|
const dispatchId = deps.lookupDispatchByBSessionId?.(file.sessionId);
|
|
42148
42457
|
if (dispatchId) env.CLAWD_DISPATCH_ID = dispatchId;
|
|
42149
|
-
const
|
|
42150
|
-
if (
|
|
42458
|
+
const personaId2 = file.ownerPersonaId;
|
|
42459
|
+
if (personaId2) env.CLAWD_PERSONA_ID = personaId2;
|
|
42151
42460
|
const mcpConfigs = deps.getMcpConfigs?.() ?? [];
|
|
42152
42461
|
const ctx = {
|
|
42153
42462
|
cwd: file.cwd,
|
|
@@ -42162,7 +42471,7 @@ function buildSpawnContext(state, deps) {
|
|
|
42162
42471
|
...mcpConfigs.length > 0 ? { mcpConfigs } : {},
|
|
42163
42472
|
// shift v1:把 SessionFile.ownerPersonaId 透传到 SpawnContext;buildSpawnArgs 等下游
|
|
42164
42473
|
// 不直接读这个字段(只读 env),但保留显式字段方便 daemon 内部诊断/日志。
|
|
42165
|
-
personaId
|
|
42474
|
+
personaId: personaId2
|
|
42166
42475
|
};
|
|
42167
42476
|
const meta = state.subSessionMeta;
|
|
42168
42477
|
if (meta?.personaMode) {
|
|
@@ -43456,14 +43765,14 @@ When done, call the \`personaDispatchComplete\` tool from the \`clawd-dispatch\`
|
|
|
43456
43765
|
dispatchId for this task: ${args.dispatchId}`;
|
|
43457
43766
|
}
|
|
43458
43767
|
function derivePersonaSpawnCwd(file, personaRoot) {
|
|
43459
|
-
const
|
|
43460
|
-
if (!
|
|
43768
|
+
const personaId2 = file.ownerPersonaId;
|
|
43769
|
+
if (!personaId2) return file.cwd;
|
|
43461
43770
|
if (!personaRoot) {
|
|
43462
43771
|
throw new Error(
|
|
43463
|
-
`derivePersonaSpawnCwd: personaRoot missing for owner session ${file.sessionId} (ownerPersonaId=${
|
|
43772
|
+
`derivePersonaSpawnCwd: personaRoot missing for owner session ${file.sessionId} (ownerPersonaId=${personaId2})`
|
|
43464
43773
|
);
|
|
43465
43774
|
}
|
|
43466
|
-
return import_node_path9.default.join(personaRoot, safeFileName(
|
|
43775
|
+
return import_node_path9.default.join(personaRoot, safeFileName(personaId2));
|
|
43467
43776
|
}
|
|
43468
43777
|
function makeInitialState(file, subSessionMeta) {
|
|
43469
43778
|
return {
|
|
@@ -43613,12 +43922,12 @@ var SessionManager = class {
|
|
|
43613
43922
|
// 扫某 persona 下 guests/ 子目录, 拿所有 capId.
|
|
43614
43923
|
// 路径: <dataDir>/personas/<pid>/.clawd/sessions/guests/<capId>/
|
|
43615
43924
|
// 只在 storeFactory 注入 (新布局) 下生效, 老布局无 guest 目录.
|
|
43616
|
-
listGuestCapIdsForPersona(
|
|
43925
|
+
listGuestCapIdsForPersona(personaId2) {
|
|
43617
43926
|
if (!this.deps.dataDir || !this.deps.storeFactory) return [];
|
|
43618
43927
|
const root = import_node_path9.default.join(
|
|
43619
43928
|
this.deps.dataDir,
|
|
43620
43929
|
"personas",
|
|
43621
|
-
|
|
43930
|
+
personaId2,
|
|
43622
43931
|
".clawd",
|
|
43623
43932
|
"sessions",
|
|
43624
43933
|
"guests"
|
|
@@ -43650,12 +43959,12 @@ var SessionManager = class {
|
|
|
43650
43959
|
if (runner) return runner.getState().file;
|
|
43651
43960
|
const dflt = this.deps.store.read(sessionId);
|
|
43652
43961
|
if (dflt) return dflt;
|
|
43653
|
-
for (const
|
|
43654
|
-
const ownerStore = this.storeFor({ kind: "persona", personaId, mode: "owner" });
|
|
43962
|
+
for (const personaId2 of this.listPersonaIdsOnDisk()) {
|
|
43963
|
+
const ownerStore = this.storeFor({ kind: "persona", personaId: personaId2, mode: "owner" });
|
|
43655
43964
|
const found = ownerStore.read(sessionId);
|
|
43656
43965
|
if (found) return found;
|
|
43657
|
-
for (const capId of this.listGuestCapIdsForPersona(
|
|
43658
|
-
const guestStore = this.storeFor({ kind: "persona", personaId, mode: "guest", capId });
|
|
43966
|
+
for (const capId of this.listGuestCapIdsForPersona(personaId2)) {
|
|
43967
|
+
const guestStore = this.storeFor({ kind: "persona", personaId: personaId2, mode: "guest", capId });
|
|
43659
43968
|
const g2 = guestStore.read(sessionId);
|
|
43660
43969
|
if (g2) return g2;
|
|
43661
43970
|
}
|
|
@@ -43684,11 +43993,11 @@ var SessionManager = class {
|
|
|
43684
43993
|
listAllOwned() {
|
|
43685
43994
|
const out = [];
|
|
43686
43995
|
out.push(...this.deps.store.list());
|
|
43687
|
-
for (const
|
|
43688
|
-
const ownerStore = this.storeFor({ kind: "persona", personaId, mode: "owner" });
|
|
43996
|
+
for (const personaId2 of this.listPersonaIdsOnDisk()) {
|
|
43997
|
+
const ownerStore = this.storeFor({ kind: "persona", personaId: personaId2, mode: "owner" });
|
|
43689
43998
|
out.push(...ownerStore.list());
|
|
43690
|
-
for (const capId of this.listGuestCapIdsForPersona(
|
|
43691
|
-
const guestStore = this.storeFor({ kind: "persona", personaId, mode: "guest", capId });
|
|
43999
|
+
for (const capId of this.listGuestCapIdsForPersona(personaId2)) {
|
|
44000
|
+
const guestStore = this.storeFor({ kind: "persona", personaId: personaId2, mode: "guest", capId });
|
|
43692
44001
|
out.push(...guestStore.list());
|
|
43693
44002
|
}
|
|
43694
44003
|
}
|
|
@@ -43716,11 +44025,11 @@ var SessionManager = class {
|
|
|
43716
44025
|
// 删除 owned SessionFile(default / persona owner / persona guest),与 findOwnedSession 对称扫盘.
|
|
43717
44026
|
deleteOwned(sessionId) {
|
|
43718
44027
|
if (this.deps.store.delete(sessionId)) return true;
|
|
43719
|
-
for (const
|
|
43720
|
-
const ownerStore = this.storeFor({ kind: "persona", personaId, mode: "owner" });
|
|
44028
|
+
for (const personaId2 of this.listPersonaIdsOnDisk()) {
|
|
44029
|
+
const ownerStore = this.storeFor({ kind: "persona", personaId: personaId2, mode: "owner" });
|
|
43721
44030
|
if (ownerStore.delete(sessionId)) return true;
|
|
43722
|
-
for (const capId of this.listGuestCapIdsForPersona(
|
|
43723
|
-
const guestStore = this.storeFor({ kind: "persona", personaId, mode: "guest", capId });
|
|
44031
|
+
for (const capId of this.listGuestCapIdsForPersona(personaId2)) {
|
|
44032
|
+
const guestStore = this.storeFor({ kind: "persona", personaId: personaId2, mode: "guest", capId });
|
|
43724
44033
|
if (guestStore.delete(sessionId)) return true;
|
|
43725
44034
|
}
|
|
43726
44035
|
}
|
|
@@ -45418,19 +45727,19 @@ var PersonaStore = class {
|
|
|
45418
45727
|
fs10.mkdirSync(root, { recursive: true });
|
|
45419
45728
|
}
|
|
45420
45729
|
root;
|
|
45421
|
-
personaDir(
|
|
45422
|
-
return path12.join(this.root, safeFileName(
|
|
45730
|
+
personaDir(personaId2) {
|
|
45731
|
+
return path12.join(this.root, safeFileName(personaId2));
|
|
45423
45732
|
}
|
|
45424
|
-
metaPath(
|
|
45425
|
-
return path12.join(this.personaDir(
|
|
45733
|
+
metaPath(personaId2) {
|
|
45734
|
+
return path12.join(this.personaDir(personaId2), ".clawd", "persona.json");
|
|
45426
45735
|
}
|
|
45427
|
-
claudeMdPath(
|
|
45428
|
-
return path12.join(this.personaDir(
|
|
45736
|
+
claudeMdPath(personaId2) {
|
|
45737
|
+
return path12.join(this.personaDir(personaId2), "CLAUDE.md");
|
|
45429
45738
|
}
|
|
45430
45739
|
// codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
|
|
45431
45740
|
// 两份内容恒一致,persona 切 tool 零迁移。
|
|
45432
|
-
agentsMdPath(
|
|
45433
|
-
return path12.join(this.personaDir(
|
|
45741
|
+
agentsMdPath(personaId2) {
|
|
45742
|
+
return path12.join(this.personaDir(personaId2), "AGENTS.md");
|
|
45434
45743
|
}
|
|
45435
45744
|
/**
|
|
45436
45745
|
* persona 级 sandbox base 落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
|
|
@@ -45438,8 +45747,8 @@ var PersonaStore = class {
|
|
|
45438
45747
|
* 这份是 guest 沙箱的 **base 真源**(manager compose 读它当 base);guest 实际加载的是 manager
|
|
45439
45748
|
* spawn 前 per-guest 动态拼到各自 session 目录的那份(base + 强制底座 + 本 guest userWorkDir carve)。
|
|
45440
45749
|
*/
|
|
45441
|
-
sandboxSettingsPath(
|
|
45442
|
-
return path12.join(this.personaDir(
|
|
45750
|
+
sandboxSettingsPath(personaId2) {
|
|
45751
|
+
return path12.join(this.personaDir(personaId2), ".clawd", "sandbox-settings.json");
|
|
45443
45752
|
}
|
|
45444
45753
|
write(persona, personality) {
|
|
45445
45754
|
const dir = this.personaDir(persona.personaId);
|
|
@@ -45449,9 +45758,9 @@ var PersonaStore = class {
|
|
|
45449
45758
|
this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
|
|
45450
45759
|
this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
|
|
45451
45760
|
}
|
|
45452
|
-
writePersonality(
|
|
45453
|
-
this.atomicWrite(this.claudeMdPath(
|
|
45454
|
-
this.atomicWrite(this.agentsMdPath(
|
|
45761
|
+
writePersonality(personaId2, personality) {
|
|
45762
|
+
this.atomicWrite(this.claudeMdPath(personaId2), personality);
|
|
45763
|
+
this.atomicWrite(this.agentsMdPath(personaId2), personality);
|
|
45455
45764
|
}
|
|
45456
45765
|
/**
|
|
45457
45766
|
* 历史 persona 补 AGENTS.md:人格双写镜像是 codex 适配后才加的,更早落盘的 persona 只有
|
|
@@ -45459,9 +45768,9 @@ var PersonaStore = class {
|
|
|
45459
45768
|
* migrate(见 seed.migrateAgentsMirror)。幂等:已有 AGENTS.md(含用户手改的)不覆盖;
|
|
45460
45769
|
* 无 CLAUDE.md 不凭空造。返回是否实际补写。
|
|
45461
45770
|
*/
|
|
45462
|
-
ensureAgentsMirror(
|
|
45463
|
-
const claudeMd = this.claudeMdPath(
|
|
45464
|
-
const agentsMd = this.agentsMdPath(
|
|
45771
|
+
ensureAgentsMirror(personaId2) {
|
|
45772
|
+
const claudeMd = this.claudeMdPath(personaId2);
|
|
45773
|
+
const agentsMd = this.agentsMdPath(personaId2);
|
|
45465
45774
|
if (!fs10.existsSync(claudeMd)) return false;
|
|
45466
45775
|
if (fs10.existsSync(agentsMd)) return false;
|
|
45467
45776
|
this.atomicWrite(agentsMd, fs10.readFileSync(claudeMd, "utf8"));
|
|
@@ -45474,25 +45783,25 @@ var PersonaStore = class {
|
|
|
45474
45783
|
* 写入时强制注入本 persona 的 Edit-deny('~/<persona>/**' 按实际 persona dir 算)+ 剥掉历史相对 'Edit(./**)',
|
|
45475
45784
|
* 让落盘 base 就是 source of truth(compose 不再运行时替换 permission deny)。
|
|
45476
45785
|
*/
|
|
45477
|
-
writeSandboxSettings(
|
|
45786
|
+
writeSandboxSettings(personaId2, settings) {
|
|
45478
45787
|
this.atomicWrite(
|
|
45479
|
-
this.sandboxSettingsPath(
|
|
45480
|
-
JSON.stringify(this.injectPersonaEditDeny(
|
|
45788
|
+
this.sandboxSettingsPath(personaId2),
|
|
45789
|
+
JSON.stringify(this.injectPersonaEditDeny(personaId2, settings), null, 2)
|
|
45481
45790
|
);
|
|
45482
45791
|
}
|
|
45483
45792
|
/** 把 persona Edit-deny(绝对 '~/<persona>/**')并进 settings.permissions.deny,剥掉历史相对 'Edit(./**)'。 */
|
|
45484
|
-
injectPersonaEditDeny(
|
|
45793
|
+
injectPersonaEditDeny(personaId2, settings) {
|
|
45485
45794
|
const s = settings;
|
|
45486
|
-
const rule = personaEditDeny(this.personaDir(
|
|
45795
|
+
const rule = personaEditDeny(this.personaDir(personaId2));
|
|
45487
45796
|
const prev = (s.permissions?.deny ?? []).filter((r) => r !== "Edit(./**)" && r !== rule);
|
|
45488
45797
|
return { ...s, permissions: { ...s.permissions ?? {}, deny: [...prev, rule] } };
|
|
45489
45798
|
}
|
|
45490
|
-
codexSandboxSettingsPath(
|
|
45491
|
-
return path12.join(this.personaDir(
|
|
45799
|
+
codexSandboxSettingsPath(personaId2) {
|
|
45800
|
+
return path12.join(this.personaDir(personaId2), ".clawd", "codex-sandbox.json");
|
|
45492
45801
|
}
|
|
45493
45802
|
/** 读 codex-sandbox.json;不存在/损坏 → null。 */
|
|
45494
|
-
readCodexSandboxSettings(
|
|
45495
|
-
const p2 = this.codexSandboxSettingsPath(
|
|
45803
|
+
readCodexSandboxSettings(personaId2) {
|
|
45804
|
+
const p2 = this.codexSandboxSettingsPath(personaId2);
|
|
45496
45805
|
if (!fs10.existsSync(p2)) return null;
|
|
45497
45806
|
try {
|
|
45498
45807
|
return CodexSandboxSettingsSchema.parse(JSON.parse(fs10.readFileSync(p2, "utf8")));
|
|
@@ -45501,16 +45810,16 @@ var PersonaStore = class {
|
|
|
45501
45810
|
}
|
|
45502
45811
|
}
|
|
45503
45812
|
/** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
|
|
45504
|
-
writeCodexSandboxSettings(
|
|
45505
|
-
const dir = path12.join(this.personaDir(
|
|
45813
|
+
writeCodexSandboxSettings(personaId2, settings) {
|
|
45814
|
+
const dir = path12.join(this.personaDir(personaId2), ".clawd");
|
|
45506
45815
|
fs10.mkdirSync(dir, { recursive: true });
|
|
45507
|
-
this.atomicWrite(this.codexSandboxSettingsPath(
|
|
45816
|
+
this.atomicWrite(this.codexSandboxSettingsPath(personaId2), JSON.stringify(settings, null, 2));
|
|
45508
45817
|
}
|
|
45509
45818
|
writeMeta(persona) {
|
|
45510
45819
|
this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
|
|
45511
45820
|
}
|
|
45512
|
-
read(
|
|
45513
|
-
const p2 = this.metaPath(
|
|
45821
|
+
read(personaId2) {
|
|
45822
|
+
const p2 = this.metaPath(personaId2);
|
|
45514
45823
|
if (!fs10.existsSync(p2)) return null;
|
|
45515
45824
|
const raw = JSON.parse(fs10.readFileSync(p2, "utf8"));
|
|
45516
45825
|
if (raw && typeof raw === "object" && "tokenMap" in raw) {
|
|
@@ -45519,13 +45828,13 @@ var PersonaStore = class {
|
|
|
45519
45828
|
}
|
|
45520
45829
|
return PersonaFileSchema.parse(raw);
|
|
45521
45830
|
}
|
|
45522
|
-
has(
|
|
45523
|
-
return fs10.existsSync(this.metaPath(
|
|
45831
|
+
has(personaId2) {
|
|
45832
|
+
return fs10.existsSync(this.metaPath(personaId2));
|
|
45524
45833
|
}
|
|
45525
|
-
readPersonality(
|
|
45526
|
-
const claudeMd = this.claudeMdPath(
|
|
45834
|
+
readPersonality(personaId2) {
|
|
45835
|
+
const claudeMd = this.claudeMdPath(personaId2);
|
|
45527
45836
|
if (fs10.existsSync(claudeMd)) return fs10.readFileSync(claudeMd, "utf8");
|
|
45528
|
-
const agentsMd = this.agentsMdPath(
|
|
45837
|
+
const agentsMd = this.agentsMdPath(personaId2);
|
|
45529
45838
|
if (fs10.existsSync(agentsMd)) return fs10.readFileSync(agentsMd, "utf8");
|
|
45530
45839
|
return null;
|
|
45531
45840
|
}
|
|
@@ -45533,8 +45842,8 @@ var PersonaStore = class {
|
|
|
45533
45842
|
* 读 sandbox-settings.json 当前内容;文件不存在 / JSON 解析失败均返回 null。
|
|
45534
45843
|
* owner 手改文件可能写出非法形状,daemon 不强校验,UI 拿到 null → 显示空状态。
|
|
45535
45844
|
*/
|
|
45536
|
-
readSandboxSettings(
|
|
45537
|
-
const p2 = this.sandboxSettingsPath(
|
|
45845
|
+
readSandboxSettings(personaId2) {
|
|
45846
|
+
const p2 = this.sandboxSettingsPath(personaId2);
|
|
45538
45847
|
if (!fs10.existsSync(p2)) return null;
|
|
45539
45848
|
try {
|
|
45540
45849
|
return JSON.parse(fs10.readFileSync(p2, "utf8"));
|
|
@@ -45543,15 +45852,15 @@ var PersonaStore = class {
|
|
|
45543
45852
|
}
|
|
45544
45853
|
}
|
|
45545
45854
|
/** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
|
|
45546
|
-
skillsDir(
|
|
45547
|
-
return path12.join(this.personaDir(
|
|
45855
|
+
skillsDir(personaId2) {
|
|
45856
|
+
return path12.join(this.personaDir(personaId2), ".claude", "skills");
|
|
45548
45857
|
}
|
|
45549
45858
|
/**
|
|
45550
45859
|
* Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
|
|
45551
45860
|
* 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
|
|
45552
45861
|
*/
|
|
45553
|
-
claudeSettingsPath(
|
|
45554
|
-
return path12.join(this.personaDir(
|
|
45862
|
+
claudeSettingsPath(personaId2) {
|
|
45863
|
+
return path12.join(this.personaDir(personaId2), ".claude", "settings.json");
|
|
45555
45864
|
}
|
|
45556
45865
|
/**
|
|
45557
45866
|
* 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
|
|
@@ -45564,8 +45873,8 @@ var PersonaStore = class {
|
|
|
45564
45873
|
* - 单 value 非 boolean → 跳过该 entry
|
|
45565
45874
|
* 其他错误(fs 权限等)原样抛出,由上层 handler 转 ws error 帧。
|
|
45566
45875
|
*/
|
|
45567
|
-
readEnabledPlugins(
|
|
45568
|
-
const p2 = this.claudeSettingsPath(
|
|
45876
|
+
readEnabledPlugins(personaId2) {
|
|
45877
|
+
const p2 = this.claudeSettingsPath(personaId2);
|
|
45569
45878
|
if (!fs10.existsSync(p2)) return [];
|
|
45570
45879
|
let raw;
|
|
45571
45880
|
try {
|
|
@@ -45588,12 +45897,12 @@ var PersonaStore = class {
|
|
|
45588
45897
|
return fs10.existsSync(path12.join(this.root, name, ".clawd", "persona.json"));
|
|
45589
45898
|
});
|
|
45590
45899
|
}
|
|
45591
|
-
remove(
|
|
45592
|
-
const dir = this.personaDir(
|
|
45900
|
+
remove(personaId2) {
|
|
45901
|
+
const dir = this.personaDir(personaId2);
|
|
45593
45902
|
if (fs10.existsSync(dir)) fs10.rmSync(dir, { recursive: true, force: true });
|
|
45594
45903
|
}
|
|
45595
|
-
personaDirPath(
|
|
45596
|
-
return this.personaDir(
|
|
45904
|
+
personaDirPath(personaId2) {
|
|
45905
|
+
return this.personaDir(personaId2);
|
|
45597
45906
|
}
|
|
45598
45907
|
atomicWrite(file, content) {
|
|
45599
45908
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
@@ -45625,15 +45934,15 @@ var PersonaRegistry = class {
|
|
|
45625
45934
|
}
|
|
45626
45935
|
}
|
|
45627
45936
|
}
|
|
45628
|
-
get(
|
|
45629
|
-
return this.cache.get(
|
|
45937
|
+
get(personaId2) {
|
|
45938
|
+
return this.cache.get(personaId2);
|
|
45630
45939
|
}
|
|
45631
45940
|
/** PersonaManager 写盘后同步 cache;不主动写盘 */
|
|
45632
45941
|
set(file) {
|
|
45633
45942
|
this.cache.set(file.personaId, file);
|
|
45634
45943
|
}
|
|
45635
|
-
remove(
|
|
45636
|
-
this.cache.delete(
|
|
45944
|
+
remove(personaId2) {
|
|
45945
|
+
this.cache.delete(personaId2);
|
|
45637
45946
|
}
|
|
45638
45947
|
list() {
|
|
45639
45948
|
return Array.from(this.cache.values());
|
|
@@ -45923,10 +46232,10 @@ var PersonaManager = class {
|
|
|
45923
46232
|
}
|
|
45924
46233
|
deps;
|
|
45925
46234
|
create(args) {
|
|
45926
|
-
const
|
|
46235
|
+
const personaId2 = this.generatePersonaId(args.label);
|
|
45927
46236
|
const now = Date.now();
|
|
45928
46237
|
const persona = {
|
|
45929
|
-
personaId,
|
|
46238
|
+
personaId: personaId2,
|
|
45930
46239
|
label: args.label,
|
|
45931
46240
|
model: args.model,
|
|
45932
46241
|
tool: args.tool,
|
|
@@ -45939,9 +46248,9 @@ var PersonaManager = class {
|
|
|
45939
46248
|
this.deps.registry.set(persona);
|
|
45940
46249
|
return persona;
|
|
45941
46250
|
}
|
|
45942
|
-
update(
|
|
45943
|
-
const existing = this.deps.registry.get(
|
|
45944
|
-
if (!existing) throw new Error(`persona not found: ${
|
|
46251
|
+
update(personaId2, patch, personality) {
|
|
46252
|
+
const existing = this.deps.registry.get(personaId2);
|
|
46253
|
+
if (!existing) throw new Error(`persona not found: ${personaId2}`);
|
|
45945
46254
|
const { iconKey: iconKeyPatch, ...restPatch } = patch;
|
|
45946
46255
|
const updated = {
|
|
45947
46256
|
...existing,
|
|
@@ -45954,30 +46263,30 @@ var PersonaManager = class {
|
|
|
45954
46263
|
updated.iconKey = iconKeyPatch;
|
|
45955
46264
|
}
|
|
45956
46265
|
if (personality !== void 0) {
|
|
45957
|
-
this.deps.store.writePersonality(
|
|
46266
|
+
this.deps.store.writePersonality(personaId2, personality);
|
|
45958
46267
|
}
|
|
45959
46268
|
this.deps.store.writeMeta(updated);
|
|
45960
46269
|
this.deps.registry.set(updated);
|
|
45961
46270
|
return updated;
|
|
45962
46271
|
}
|
|
45963
46272
|
/** 读取 CLAUDE.md 内容;persona 目录或文件不存在时返回 null。透传给 handler 拼响应。 */
|
|
45964
|
-
readPersonality(
|
|
45965
|
-
return this.deps.store.readPersonality(
|
|
46273
|
+
readPersonality(personaId2) {
|
|
46274
|
+
return this.deps.store.readPersonality(personaId2);
|
|
45966
46275
|
}
|
|
45967
46276
|
/** 扫 persona 私有 skills 目录;目录不存在返回空数组。供 persona:get handler 拼响应。 */
|
|
45968
|
-
listSkills(
|
|
45969
|
-
return listSkillsForDir(this.deps.store.skillsDir(
|
|
46277
|
+
listSkills(personaId2) {
|
|
46278
|
+
return listSkillsForDir(this.deps.store.skillsDir(personaId2), "project");
|
|
45970
46279
|
}
|
|
45971
46280
|
/**
|
|
45972
46281
|
* 读取 persona `.claude/settings.json` 中已启用的插件列表(value === true 的 key)。
|
|
45973
46282
|
* 文件不存在 / 解析失败 / 字段缺失 → 空数组。供 persona:get handler 拼响应。
|
|
45974
46283
|
*/
|
|
45975
|
-
listEnabledPlugins(
|
|
45976
|
-
return this.deps.store.readEnabledPlugins(
|
|
46284
|
+
listEnabledPlugins(personaId2) {
|
|
46285
|
+
return this.deps.store.readEnabledPlugins(personaId2);
|
|
45977
46286
|
}
|
|
45978
46287
|
/** 读 sandbox-settings.json;不存在 / 损坏返回 null。供 persona:get handler 拼响应。 */
|
|
45979
|
-
readSandboxSettings(
|
|
45980
|
-
return this.deps.store.readSandboxSettings(
|
|
46288
|
+
readSandboxSettings(personaId2) {
|
|
46289
|
+
return this.deps.store.readSandboxSettings(personaId2);
|
|
45981
46290
|
}
|
|
45982
46291
|
/**
|
|
45983
46292
|
* 删除 persona。
|
|
@@ -45985,9 +46294,9 @@ var PersonaManager = class {
|
|
|
45985
46294
|
* (含 .clawd/sessions/owner/ 和 .clawd/sessions/guests/<capId>/),rmSync
|
|
45986
46295
|
* recursive force 一锅清。
|
|
45987
46296
|
*/
|
|
45988
|
-
delete(
|
|
45989
|
-
this.deps.store.remove(
|
|
45990
|
-
this.deps.registry.remove(
|
|
46297
|
+
delete(personaId2) {
|
|
46298
|
+
this.deps.store.remove(personaId2);
|
|
46299
|
+
this.deps.registry.remove(personaId2);
|
|
45991
46300
|
}
|
|
45992
46301
|
/**
|
|
45993
46302
|
* label 转 4-16 char slug。优先用 `persona-<slug>`;若 slug 已被占用,追加 4 char
|
|
@@ -46317,15 +46626,15 @@ function refreshSandboxSettings(args) {
|
|
|
46317
46626
|
}
|
|
46318
46627
|
function migrateAgentsMirror(args) {
|
|
46319
46628
|
let mirrored = 0;
|
|
46320
|
-
for (const
|
|
46629
|
+
for (const personaId2 of args.store.list()) {
|
|
46321
46630
|
try {
|
|
46322
|
-
if (args.store.ensureAgentsMirror(
|
|
46631
|
+
if (args.store.ensureAgentsMirror(personaId2)) {
|
|
46323
46632
|
mirrored++;
|
|
46324
|
-
args.logger.info("persona.agents-mirror.synced", { personaId });
|
|
46633
|
+
args.logger.info("persona.agents-mirror.synced", { personaId: personaId2 });
|
|
46325
46634
|
}
|
|
46326
46635
|
} catch (err) {
|
|
46327
46636
|
args.logger.warn("persona.agents-mirror.failed", {
|
|
46328
|
-
personaId,
|
|
46637
|
+
personaId: personaId2,
|
|
46329
46638
|
error: err instanceof Error ? err.message : String(err)
|
|
46330
46639
|
});
|
|
46331
46640
|
}
|
|
@@ -46335,15 +46644,15 @@ function migrateAgentsMirror(args) {
|
|
|
46335
46644
|
function migrateCodexSandbox(args) {
|
|
46336
46645
|
const entries = args.entries ?? DEFAULT_PERSONAS;
|
|
46337
46646
|
let n = 0;
|
|
46338
|
-
for (const
|
|
46339
|
-
if (args.store.readCodexSandboxSettings(
|
|
46647
|
+
for (const personaId2 of args.store.list()) {
|
|
46648
|
+
if (args.store.readCodexSandboxSettings(personaId2)) continue;
|
|
46340
46649
|
try {
|
|
46341
|
-
const def = entries.find((e) => e.personaId ===
|
|
46342
|
-
args.store.writeCodexSandboxSettings(
|
|
46650
|
+
const def = entries.find((e) => e.personaId === personaId2)?.codexSandbox ?? { writableRoots: [], denyRead: [], network: false };
|
|
46651
|
+
args.store.writeCodexSandboxSettings(personaId2, def);
|
|
46343
46652
|
n++;
|
|
46344
|
-
args.logger.info("persona.codex-sandbox.synced", { personaId });
|
|
46653
|
+
args.logger.info("persona.codex-sandbox.synced", { personaId: personaId2 });
|
|
46345
46654
|
} catch (err) {
|
|
46346
|
-
args.logger.warn("persona.codex-sandbox.failed", { personaId, error: err instanceof Error ? err.message : String(err) });
|
|
46655
|
+
args.logger.warn("persona.codex-sandbox.failed", { personaId: personaId2, error: err instanceof Error ? err.message : String(err) });
|
|
46347
46656
|
}
|
|
46348
46657
|
}
|
|
46349
46658
|
if (n > 0) args.logger.info("persona.codex-sandbox.done", { migrated: n });
|
|
@@ -49193,16 +49502,17 @@ function createShiftSpawnFn(deps) {
|
|
|
49193
49502
|
};
|
|
49194
49503
|
}
|
|
49195
49504
|
|
|
49196
|
-
// src/handlers/
|
|
49197
|
-
|
|
49198
|
-
|
|
49199
|
-
|
|
49200
|
-
|
|
49201
|
-
|
|
49202
|
-
|
|
49203
|
-
}
|
|
49204
|
-
return raw;
|
|
49505
|
+
// src/handlers/types.ts
|
|
49506
|
+
init_protocol();
|
|
49507
|
+
function parseArgs2(schema, frame, what, code = ERROR_CODES.VALIDATION_ERROR) {
|
|
49508
|
+
const effective = typeof schema.strip === "function" ? schema.strip() : schema;
|
|
49509
|
+
const r = effective.safeParse(frame);
|
|
49510
|
+
if (!r.success) throw new ClawdError(code, `${what}: ${r.error.message}`);
|
|
49511
|
+
return r.data;
|
|
49205
49512
|
}
|
|
49513
|
+
|
|
49514
|
+
// src/handlers/shift-internal.ts
|
|
49515
|
+
init_protocol();
|
|
49206
49516
|
function validateSchedule(schedule) {
|
|
49207
49517
|
const next = computeNextRunAtMs(schedule, Date.now());
|
|
49208
49518
|
if (next === null) {
|
|
@@ -49213,10 +49523,9 @@ function validateSchedule(schedule) {
|
|
|
49213
49523
|
}
|
|
49214
49524
|
function buildShiftInternalHandlers(deps) {
|
|
49215
49525
|
const add = async (frame) => {
|
|
49216
|
-
const persona = readPersonaId(frame);
|
|
49217
49526
|
const callerSessionId = typeof frame.sessionId === "string" ? frame.sessionId : void 0;
|
|
49218
|
-
const
|
|
49219
|
-
const
|
|
49527
|
+
const args = parseArgs2(ShiftInternalAddArgs, frame, "shift-internal:add");
|
|
49528
|
+
const persona = args.personaId;
|
|
49220
49529
|
validateSchedule(args.schedule);
|
|
49221
49530
|
const shift = deps.store.add({
|
|
49222
49531
|
ownerId: deps.ownerIdProvider(),
|
|
@@ -49234,17 +49543,15 @@ function buildShiftInternalHandlers(deps) {
|
|
|
49234
49543
|
};
|
|
49235
49544
|
};
|
|
49236
49545
|
const list = async (frame) => {
|
|
49237
|
-
const
|
|
49238
|
-
const
|
|
49239
|
-
const args = rest;
|
|
49546
|
+
const args = parseArgs2(ShiftInternalListArgs, frame, "shift-internal:list");
|
|
49547
|
+
const persona = args.personaId;
|
|
49240
49548
|
const onlyMine = args.onlyMine !== false;
|
|
49241
49549
|
const filter = onlyMine ? { ownerId: deps.ownerIdProvider(), createdByPersona: persona } : { ownerId: deps.ownerIdProvider() };
|
|
49242
49550
|
return { response: { shifts: deps.store.list(filter) } };
|
|
49243
49551
|
};
|
|
49244
49552
|
const cancel = async (frame) => {
|
|
49245
|
-
const
|
|
49246
|
-
const
|
|
49247
|
-
const args = rest;
|
|
49553
|
+
const args = parseArgs2(ShiftInternalCancelArgs, frame, "shift-internal:cancel");
|
|
49554
|
+
const persona = args.personaId;
|
|
49248
49555
|
const shift = deps.store.get(args.shiftId);
|
|
49249
49556
|
if (!shift) {
|
|
49250
49557
|
throw new Error(`shift-internal:cancel: shift not found: ${args.shiftId}`);
|
|
@@ -49258,9 +49565,8 @@ function buildShiftInternalHandlers(deps) {
|
|
|
49258
49565
|
return { response: { ok: true } };
|
|
49259
49566
|
};
|
|
49260
49567
|
const update = async (frame) => {
|
|
49261
|
-
const
|
|
49262
|
-
const
|
|
49263
|
-
const args = rest;
|
|
49568
|
+
const args = parseArgs2(ShiftInternalUpdateArgs, frame, "shift-internal:update");
|
|
49569
|
+
const persona = args.personaId;
|
|
49264
49570
|
const shift = deps.store.get(args.shiftId);
|
|
49265
49571
|
if (!shift) {
|
|
49266
49572
|
throw new Error(`shift-internal:update: shift not found: ${args.shiftId}`);
|
|
@@ -49280,9 +49586,8 @@ function buildShiftInternalHandlers(deps) {
|
|
|
49280
49586
|
};
|
|
49281
49587
|
};
|
|
49282
49588
|
const history = async (frame) => {
|
|
49283
|
-
const
|
|
49284
|
-
const
|
|
49285
|
-
const args = rest;
|
|
49589
|
+
const args = parseArgs2(ShiftInternalHistoryArgs, frame, "shift-internal:history");
|
|
49590
|
+
const persona = args.personaId;
|
|
49286
49591
|
const shift = deps.store.get(args.shiftId);
|
|
49287
49592
|
if (!shift) {
|
|
49288
49593
|
throw new Error(`shift-internal:history: shift not found: ${args.shiftId}`);
|
|
@@ -49338,9 +49643,9 @@ function canAccessSession(ctx, sessionId, action, deps) {
|
|
|
49338
49643
|
if (!file) return true;
|
|
49339
49644
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, action);
|
|
49340
49645
|
}
|
|
49341
|
-
function canAccessPersona(grants,
|
|
49342
|
-
if (!
|
|
49343
|
-
const resource = { type: "persona", id:
|
|
49646
|
+
function canAccessPersona(grants, personaId2, action) {
|
|
49647
|
+
if (!personaId2) return false;
|
|
49648
|
+
const resource = { type: "persona", id: personaId2 };
|
|
49344
49649
|
return assertGrant(grants, resource, action);
|
|
49345
49650
|
}
|
|
49346
49651
|
|
|
@@ -50685,7 +50990,7 @@ function listRegistered() {
|
|
|
50685
50990
|
|
|
50686
50991
|
// ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
50687
50992
|
var import_stream = __toESM(require_stream(), 1);
|
|
50688
|
-
var
|
|
50993
|
+
var import_extension2 = __toESM(require_extension(), 1);
|
|
50689
50994
|
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
50690
50995
|
var import_receiver = __toESM(require_receiver(), 1);
|
|
50691
50996
|
var import_sender = __toESM(require_sender(), 1);
|
|
@@ -54287,14 +54592,14 @@ function buildSessionHandlers(deps) {
|
|
|
54287
54592
|
);
|
|
54288
54593
|
}
|
|
54289
54594
|
};
|
|
54290
|
-
const ensurePersonaAccess = (ctx,
|
|
54595
|
+
const ensurePersonaAccess = (ctx, personaId2, action) => {
|
|
54291
54596
|
if (!ctx) return;
|
|
54292
54597
|
if (ctx.principal.kind === "owner") return;
|
|
54293
|
-
const ok = canAccessPersona(ctx.grants,
|
|
54598
|
+
const ok = canAccessPersona(ctx.grants, personaId2, action);
|
|
54294
54599
|
if (!ok) {
|
|
54295
54600
|
throw new ClawdError(
|
|
54296
54601
|
ERROR_CODES.UNAUTHORIZED,
|
|
54297
|
-
`principal ${ctx.principal.kind}:${ctx.principal.id} cannot ${action} on persona:${
|
|
54602
|
+
`principal ${ctx.principal.kind}:${ctx.principal.id} cannot ${action} on persona:${personaId2 ?? "<none>"}`
|
|
54298
54603
|
);
|
|
54299
54604
|
}
|
|
54300
54605
|
};
|
|
@@ -54399,13 +54704,17 @@ function buildSessionHandlers(deps) {
|
|
|
54399
54704
|
const args = SessionSendArgs.parse(frame);
|
|
54400
54705
|
ensureSessionAccess(ctx, args.sessionId, "send");
|
|
54401
54706
|
const sender = ctx ? principalToSender(ctx.principal) : principalToSender(
|
|
54402
|
-
makeOwnerPrincipal(
|
|
54707
|
+
makeOwnerPrincipal(
|
|
54708
|
+
ownerPrincipalId,
|
|
54709
|
+
deps.getOwnerIdentity().displayName,
|
|
54710
|
+
deps.getOwnerIdentity().feishuUnionId
|
|
54711
|
+
)
|
|
54403
54712
|
);
|
|
54404
54713
|
const { broadcast } = manager.send(args, sender);
|
|
54405
54714
|
return { response: { type: "session:send", ok: true }, broadcast };
|
|
54406
54715
|
};
|
|
54407
54716
|
const currentTurnSender = async (frame, _client, ctx) => {
|
|
54408
|
-
const sid =
|
|
54717
|
+
const sid = SessionCurrentTurnSenderArgs.parse(frame).sessionId ?? "";
|
|
54409
54718
|
if (!sid) {
|
|
54410
54719
|
return { response: { type: "session:currentTurnSender", sender: null } };
|
|
54411
54720
|
}
|
|
@@ -54510,19 +54819,20 @@ function buildSessionHandlers(deps) {
|
|
|
54510
54819
|
return { response: { type: "session:events", ...response } };
|
|
54511
54820
|
};
|
|
54512
54821
|
const subscribe = async (frame, client, ctx) => {
|
|
54513
|
-
|
|
54514
|
-
|
|
54515
|
-
|
|
54822
|
+
const args = SessionSubscribeArgs.parse(frame);
|
|
54823
|
+
if (args.sessionId !== void 0) {
|
|
54824
|
+
ensureSessionAccess(ctx, args.sessionId, "read");
|
|
54825
|
+
addSubscription(client, args.sessionId);
|
|
54516
54826
|
}
|
|
54517
54827
|
return {
|
|
54518
|
-
response: { type: "subscribed", sessionId:
|
|
54828
|
+
response: { type: "subscribed", sessionId: args.sessionId }
|
|
54519
54829
|
};
|
|
54520
54830
|
};
|
|
54521
54831
|
const unsubscribe = async (frame, client) => {
|
|
54522
|
-
|
|
54523
|
-
|
|
54832
|
+
const args = SessionSubscribeArgs.parse(frame);
|
|
54833
|
+
if (args.sessionId !== void 0) removeSubscription(client, args.sessionId);
|
|
54524
54834
|
return {
|
|
54525
|
-
response: { type: "unsubscribed", sessionId:
|
|
54835
|
+
response: { type: "unsubscribed", sessionId: args.sessionId }
|
|
54526
54836
|
};
|
|
54527
54837
|
};
|
|
54528
54838
|
const pin = async (frame, _client, ctx) => {
|
|
@@ -54721,11 +55031,11 @@ function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userW
|
|
|
54721
55031
|
if (!target.startsWith(root + sep3)) return false;
|
|
54722
55032
|
const rel = path56.relative(root, target);
|
|
54723
55033
|
if (!rel || rel.startsWith("..")) return false;
|
|
54724
|
-
const
|
|
54725
|
-
if (!
|
|
55034
|
+
const personaId2 = rel.split(path56.sep)[0];
|
|
55035
|
+
if (!personaId2) return false;
|
|
54726
55036
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
54727
55037
|
if (allowed === "*") return true;
|
|
54728
|
-
return allowed.has(
|
|
55038
|
+
return allowed.has(personaId2);
|
|
54729
55039
|
}
|
|
54730
55040
|
function personaIdFromPath(absPath, personaRoot) {
|
|
54731
55041
|
const root = path56.resolve(personaRoot);
|
|
@@ -54743,9 +55053,9 @@ function isPathWithin(dir, absPath) {
|
|
|
54743
55053
|
const sep3 = d.endsWith(path56.sep) ? "" : path56.sep;
|
|
54744
55054
|
return t === d || t.startsWith(d + sep3);
|
|
54745
55055
|
}
|
|
54746
|
-
function isPathInGuestBoundary(personaRoot,
|
|
55056
|
+
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
54747
55057
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
54748
|
-
return personaIdFromPath(path56.resolve(absPath), personaRoot) ===
|
|
55058
|
+
return personaIdFromPath(path56.resolve(absPath), personaRoot) === personaId2;
|
|
54749
55059
|
}
|
|
54750
55060
|
|
|
54751
55061
|
// src/handlers/history.ts
|
|
@@ -54878,9 +55188,9 @@ var path58 = __toESM(require("path"), 1);
|
|
|
54878
55188
|
var os16 = __toESM(require("os"), 1);
|
|
54879
55189
|
init_protocol();
|
|
54880
55190
|
init_protocol();
|
|
54881
|
-
function buildEnabledPluginNames(personaManager,
|
|
55191
|
+
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
54882
55192
|
const out = /* @__PURE__ */ new Set();
|
|
54883
|
-
for (const p2 of personaManager.listEnabledPlugins(
|
|
55193
|
+
for (const p2 of personaManager.listEnabledPlugins(personaId2)) {
|
|
54884
55194
|
const name = p2.id.includes("@") ? p2.id.slice(0, p2.id.indexOf("@")) : p2.id;
|
|
54885
55195
|
if (name) out.add(name);
|
|
54886
55196
|
}
|
|
@@ -54935,8 +55245,8 @@ function buildWorkspaceHandlers(deps) {
|
|
|
54935
55245
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
54936
55246
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
54937
55247
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
54938
|
-
const
|
|
54939
|
-
const enabled =
|
|
55248
|
+
const personaId2 = personaIdFromPath(cwdAbs, personaRoot);
|
|
55249
|
+
const enabled = personaId2 ? buildEnabledPluginNames(personaManager, personaId2) : /* @__PURE__ */ new Set();
|
|
54940
55250
|
return { response: { type: "skills:list", skills: filterGuestSkills(list2, enabled) } };
|
|
54941
55251
|
}
|
|
54942
55252
|
return { response: { type: "skills:list", skills: list2 } };
|
|
@@ -54950,8 +55260,8 @@ function buildWorkspaceHandlers(deps) {
|
|
|
54950
55260
|
}
|
|
54951
55261
|
const list2 = agents.list(args);
|
|
54952
55262
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
54953
|
-
const
|
|
54954
|
-
const enabled =
|
|
55263
|
+
const personaId2 = personaIdFromPath(cwdAbs, personaRoot);
|
|
55264
|
+
const enabled = personaId2 ? buildEnabledPluginNames(personaManager, personaId2) : /* @__PURE__ */ new Set();
|
|
54955
55265
|
return { response: { type: "agents:list", agents: filterGuestAgents(list2, enabled) } };
|
|
54956
55266
|
}
|
|
54957
55267
|
return { response: { type: "agents:list", agents: list2 } };
|
|
@@ -55124,8 +55434,7 @@ function resolvePeerDeviceId(ctx, argsPeerDeviceId) {
|
|
|
55124
55434
|
function buildInboxHandlers(deps) {
|
|
55125
55435
|
const { manager } = deps;
|
|
55126
55436
|
const postMessage = async (frame, _client, ctx) => {
|
|
55127
|
-
const
|
|
55128
|
-
const args = InboxPostMessageArgsSchema.parse(rest);
|
|
55437
|
+
const args = parseArgs2(InboxPostMessageArgsSchema, frame, "inbox:postMessage");
|
|
55129
55438
|
if (!ctx) {
|
|
55130
55439
|
throw new ClawdError(ERROR_CODES.INTERNAL, "inbox:postMessage: missing ConnectionContext");
|
|
55131
55440
|
}
|
|
@@ -55143,8 +55452,7 @@ function buildInboxHandlers(deps) {
|
|
|
55143
55452
|
};
|
|
55144
55453
|
};
|
|
55145
55454
|
const list = async (frame, _client, ctx) => {
|
|
55146
|
-
const
|
|
55147
|
-
const args = InboxListArgsSchema.parse(rest);
|
|
55455
|
+
const args = parseArgs2(InboxListArgsSchema, frame, "inbox:list");
|
|
55148
55456
|
if (!ctx) {
|
|
55149
55457
|
throw new ClawdError(ERROR_CODES.INTERNAL, "inbox:list: missing ConnectionContext");
|
|
55150
55458
|
}
|
|
@@ -55155,8 +55463,7 @@ function buildInboxHandlers(deps) {
|
|
|
55155
55463
|
};
|
|
55156
55464
|
};
|
|
55157
55465
|
const markRead = async (frame, _client, ctx) => {
|
|
55158
|
-
const
|
|
55159
|
-
const args = InboxMarkReadArgsSchema.parse(rest);
|
|
55466
|
+
const args = parseArgs2(InboxMarkReadArgsSchema, frame, "inbox:markRead");
|
|
55160
55467
|
if (!ctx) {
|
|
55161
55468
|
throw new ClawdError(ERROR_CODES.INTERNAL, "inbox:markRead: missing ConnectionContext");
|
|
55162
55469
|
}
|
|
@@ -55178,7 +55485,7 @@ function buildInboxHandlers(deps) {
|
|
|
55178
55485
|
const sendDm = async (frame) => {
|
|
55179
55486
|
const { type: _t, requestId: _r, ...rest } = frame;
|
|
55180
55487
|
const sessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
|
|
55181
|
-
const args = InboxSendDmArgsSchema
|
|
55488
|
+
const args = parseArgs2(InboxSendDmArgsSchema, frame, "inbox:sendDm");
|
|
55182
55489
|
const d = deps.sendDmDeps;
|
|
55183
55490
|
if (!d) throw new ClawdError(ERROR_CODES.INTERNAL, "inbox:sendDm not wired");
|
|
55184
55491
|
if (!sessionId) {
|
|
@@ -55339,8 +55646,7 @@ function buildContactHandlers(deps) {
|
|
|
55339
55646
|
};
|
|
55340
55647
|
const pin = async (frame, _client, ctx) => {
|
|
55341
55648
|
ensureOwner(ctx);
|
|
55342
|
-
const
|
|
55343
|
-
const args = ContactPinArgsSchema.parse(rest);
|
|
55649
|
+
const args = parseArgs2(ContactPinArgsSchema, frame, "contact:pin");
|
|
55344
55650
|
const pinnedAt = args.pinned ? deps.now() : null;
|
|
55345
55651
|
const hit = deps.store.setPin(args.deviceId, pinnedAt);
|
|
55346
55652
|
if (!hit) {
|
|
@@ -55364,8 +55670,7 @@ function buildContactHandlers(deps) {
|
|
|
55364
55670
|
};
|
|
55365
55671
|
const remove = async (frame, _client, ctx) => {
|
|
55366
55672
|
ensureOwner(ctx);
|
|
55367
|
-
const
|
|
55368
|
-
const args = ContactRemoveArgsSchema.parse(rest);
|
|
55673
|
+
const args = parseArgs2(ContactRemoveArgsSchema, frame, "contact:remove");
|
|
55369
55674
|
deps.store.removeByDeviceId(args.deviceId);
|
|
55370
55675
|
deps.broadcast({
|
|
55371
55676
|
type: "contact:removed",
|
|
@@ -55385,8 +55690,7 @@ function buildContactHandlers(deps) {
|
|
|
55385
55690
|
"contact:handshake \u4EC5\u63A5\u53D7 connect-token \u8FDE\u63A5\uFF08\u8BBE\u5907\u4E92\u8FDE\u63E1\u624B\u4E13\u7528\uFF09"
|
|
55386
55691
|
);
|
|
55387
55692
|
}
|
|
55388
|
-
const
|
|
55389
|
-
const args = ContactHandshakeArgsSchema.parse(rest);
|
|
55693
|
+
const args = parseArgs2(ContactHandshakeArgsSchema, frame, "contact:handshake");
|
|
55390
55694
|
const contact = upsertPeerContact({
|
|
55391
55695
|
store: deps.store,
|
|
55392
55696
|
broadcast: deps.broadcast,
|
|
@@ -55403,14 +55707,15 @@ function buildContactHandlers(deps) {
|
|
|
55403
55707
|
contact,
|
|
55404
55708
|
exchangeToken: deps.exchangeToken
|
|
55405
55709
|
});
|
|
55710
|
+
const identity = deps.getOwnerIdentity();
|
|
55406
55711
|
return {
|
|
55407
55712
|
response: {
|
|
55408
55713
|
type: "contact:handshake:ok",
|
|
55409
55714
|
owner: {
|
|
55410
55715
|
id: deps.ownerPrincipalId,
|
|
55411
|
-
ownerId:
|
|
55412
|
-
provider:
|
|
55413
|
-
displayName:
|
|
55716
|
+
ownerId: identity.ownerId,
|
|
55717
|
+
provider: identity.provider,
|
|
55718
|
+
displayName: identity.displayName
|
|
55414
55719
|
},
|
|
55415
55720
|
grants: ctx.grants
|
|
55416
55721
|
}
|
|
@@ -55437,8 +55742,7 @@ function ensureOwner2(ctx) {
|
|
|
55437
55742
|
function buildContactRemoteAccessHandlers(deps) {
|
|
55438
55743
|
const setRemoteAccess = async (frame, _client, ctx) => {
|
|
55439
55744
|
ensureOwner2(ctx);
|
|
55440
|
-
const
|
|
55441
|
-
const args = ContactSetRemoteAccessArgsSchema.parse(rest);
|
|
55745
|
+
const args = parseArgs2(ContactSetRemoteAccessArgsSchema, frame, "contact:setRemoteAccess");
|
|
55442
55746
|
const hit = deps.store.setRemoteAccess(args.deviceId, {
|
|
55443
55747
|
remoteAccessAllowed: args.remoteAccessAllowed
|
|
55444
55748
|
});
|
|
@@ -55473,6 +55777,7 @@ function buildWhoamiHandler(deps) {
|
|
|
55473
55777
|
if (!ctx) {
|
|
55474
55778
|
throw new ClawdError(ERROR_CODES.INTERNAL, "whoami: missing ConnectionContext");
|
|
55475
55779
|
}
|
|
55780
|
+
const identity = deps.getOwnerIdentity();
|
|
55476
55781
|
if (ctx.tokenKind === "connect") {
|
|
55477
55782
|
return {
|
|
55478
55783
|
response: {
|
|
@@ -55482,15 +55787,15 @@ function buildWhoamiHandler(deps) {
|
|
|
55482
55787
|
};
|
|
55483
55788
|
}
|
|
55484
55789
|
const owner = {
|
|
55485
|
-
...makeOwnerPrincipal(deps.ownerPrincipalId,
|
|
55486
|
-
ownerId:
|
|
55487
|
-
provider:
|
|
55790
|
+
...makeOwnerPrincipal(deps.ownerPrincipalId, identity.displayName),
|
|
55791
|
+
ownerId: identity.ownerId,
|
|
55792
|
+
provider: identity.provider
|
|
55488
55793
|
};
|
|
55489
55794
|
let capability;
|
|
55490
55795
|
if (ctx.principal.kind === "owner") {
|
|
55491
55796
|
capability = {
|
|
55492
55797
|
id: deps.ownerPrincipalId,
|
|
55493
|
-
displayName:
|
|
55798
|
+
displayName: identity.displayName,
|
|
55494
55799
|
grants: ctx.grants,
|
|
55495
55800
|
issuedAt: 0,
|
|
55496
55801
|
usedCount: 0
|
|
@@ -55880,24 +56185,28 @@ function computeGrant(method) {
|
|
|
55880
56185
|
}
|
|
55881
56186
|
function computeMethodAccess(args) {
|
|
55882
56187
|
const { method, grants, feishuActive, isImplemented } = args;
|
|
56188
|
+
const description = METHOD_DOCS[method].summary;
|
|
56189
|
+
const argFields = methodArgFields(method);
|
|
55883
56190
|
if (!isImplemented(method)) {
|
|
55884
|
-
return { name: method, status: "denied", reason: "METHOD_NOT_IMPLEMENTED" };
|
|
56191
|
+
return { name: method, description, args: argFields, status: "denied", reason: "METHOD_NOT_IMPLEMENTED" };
|
|
55885
56192
|
}
|
|
55886
56193
|
if (!feishuActive && FEISHU_GATED_METHODS.includes(method)) {
|
|
55887
|
-
return { name: method, status: "denied", reason: "FEISHU_LOGIN_REQUIRED" };
|
|
56194
|
+
return { name: method, description, args: argFields, status: "denied", reason: "FEISHU_LOGIN_REQUIRED" };
|
|
55888
56195
|
}
|
|
55889
56196
|
if (METHOD_GRANT_MAP[method]?.kind === "capability-scoped") {
|
|
55890
56197
|
return {
|
|
55891
56198
|
name: method,
|
|
56199
|
+
description,
|
|
56200
|
+
args: argFields,
|
|
55892
56201
|
status: "conditional",
|
|
55893
56202
|
reason: "handler checks your grants for the target resource"
|
|
55894
56203
|
};
|
|
55895
56204
|
}
|
|
55896
56205
|
const verdict = computeGrant(method);
|
|
55897
56206
|
if (verdict.kind === "check" && !assertGrant(grants, verdict.resource, verdict.action)) {
|
|
55898
|
-
return { name: method, status: "denied", reason: "UNAUTHORIZED" };
|
|
56207
|
+
return { name: method, description, args: argFields, status: "denied", reason: "UNAUTHORIZED" };
|
|
55899
56208
|
}
|
|
55900
|
-
return { name: method, status: "allowed" };
|
|
56209
|
+
return { name: method, description, args: argFields, status: "allowed" };
|
|
55901
56210
|
}
|
|
55902
56211
|
|
|
55903
56212
|
// src/version.ts
|
|
@@ -55973,7 +56282,7 @@ function buildPersonaHandlers(deps) {
|
|
|
55973
56282
|
const { personaManager, personaRegistry } = deps;
|
|
55974
56283
|
const create = async (frame) => {
|
|
55975
56284
|
const { type: _type, requestId: _requestId, ...rest } = frame;
|
|
55976
|
-
const args = PersonaCreateArgsSchema
|
|
56285
|
+
const args = parseArgs2(PersonaCreateArgsSchema, frame, "persona:create");
|
|
55977
56286
|
const persona = personaManager.create(args);
|
|
55978
56287
|
return { response: { type: "persona:info", ...persona } };
|
|
55979
56288
|
};
|
|
@@ -55989,7 +56298,7 @@ function buildPersonaHandlers(deps) {
|
|
|
55989
56298
|
};
|
|
55990
56299
|
};
|
|
55991
56300
|
const get = async (frame, _client, ctx) => {
|
|
55992
|
-
const args = PersonaIdArgsSchema
|
|
56301
|
+
const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:get");
|
|
55993
56302
|
const persona = personaRegistry.get(args.personaId) ?? null;
|
|
55994
56303
|
if (!persona) {
|
|
55995
56304
|
return { response: { type: "persona:info", persona: null } };
|
|
@@ -56018,13 +56327,13 @@ function buildPersonaHandlers(deps) {
|
|
|
56018
56327
|
};
|
|
56019
56328
|
const update = async (frame) => {
|
|
56020
56329
|
const { type: _type, requestId: _requestId, ...rest } = frame;
|
|
56021
|
-
const args = PersonaUpdateArgsSchema
|
|
56330
|
+
const args = parseArgs2(PersonaUpdateArgsSchema, frame, "persona:update");
|
|
56022
56331
|
const { personality, ...metaPatch } = args.patch;
|
|
56023
56332
|
const persona = personaManager.update(args.personaId, metaPatch, personality);
|
|
56024
56333
|
return { response: { type: "persona:info", ...persona } };
|
|
56025
56334
|
};
|
|
56026
56335
|
const del = async (frame) => {
|
|
56027
|
-
const args = PersonaIdArgsSchema
|
|
56336
|
+
const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:get");
|
|
56028
56337
|
personaManager.delete(args.personaId);
|
|
56029
56338
|
return {
|
|
56030
56339
|
response: { type: "persona:deleted", personaId: args.personaId }
|
|
@@ -56582,32 +56891,6 @@ async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
|
56582
56891
|
}
|
|
56583
56892
|
|
|
56584
56893
|
// src/handlers/extension.ts
|
|
56585
|
-
function pickChannelRef(frame) {
|
|
56586
|
-
const ref = frame.channelRef;
|
|
56587
|
-
const parsed = ChannelRefSchema.safeParse(ref);
|
|
56588
|
-
if (!parsed.success) {
|
|
56589
|
-
throw new ClawdError(
|
|
56590
|
-
ERROR_CODES.INVALID_PARAM,
|
|
56591
|
-
`channelRef invalid: ${parsed.error.issues.map((i) => i.message).join("; ")}`
|
|
56592
|
-
);
|
|
56593
|
-
}
|
|
56594
|
-
return parsed.data;
|
|
56595
|
-
}
|
|
56596
|
-
function pickStringField(frame, name) {
|
|
56597
|
-
const v2 = frame[name];
|
|
56598
|
-
if (typeof v2 !== "string" || v2.length === 0) {
|
|
56599
|
-
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `${name} required`);
|
|
56600
|
-
}
|
|
56601
|
-
return v2;
|
|
56602
|
-
}
|
|
56603
|
-
function pickOptionalString(frame, name) {
|
|
56604
|
-
const v2 = frame[name];
|
|
56605
|
-
if (v2 === void 0 || v2 === null) return null;
|
|
56606
|
-
if (typeof v2 !== "string") {
|
|
56607
|
-
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `${name} must be string`);
|
|
56608
|
-
}
|
|
56609
|
-
return v2;
|
|
56610
|
-
}
|
|
56611
56894
|
async function rewriteManifestVersion(root, extId, newVersion, previousPublishedVersion) {
|
|
56612
56895
|
const v2 = validateSimpleSemver(newVersion);
|
|
56613
56896
|
if (!v2.ok) {
|
|
@@ -56665,13 +56948,6 @@ function assertOwner(ctx) {
|
|
|
56665
56948
|
throw new ClawdError(ERROR_CODES.FORBIDDEN, "owner only");
|
|
56666
56949
|
}
|
|
56667
56950
|
}
|
|
56668
|
-
function pickExtId(frame) {
|
|
56669
|
-
const extId = frame.extId;
|
|
56670
|
-
if (typeof extId !== "string") {
|
|
56671
|
-
throw new ClawdError(ERROR_CODES.INVALID_PARAM, "extId required");
|
|
56672
|
-
}
|
|
56673
|
-
return extId;
|
|
56674
|
-
}
|
|
56675
56951
|
function composeState(rec3, running, crashed, getPort) {
|
|
56676
56952
|
if (rec3.state === "invalid") return rec3;
|
|
56677
56953
|
if (manifestMode(rec3.manifest) === "hosted") {
|
|
@@ -56705,19 +56981,19 @@ function buildExtensionHandlers(deps) {
|
|
|
56705
56981
|
};
|
|
56706
56982
|
const open = async (frame, _client, ctx) => {
|
|
56707
56983
|
assertOwner(ctx);
|
|
56708
|
-
const extId =
|
|
56984
|
+
const { extId } = parseArgs2(ExtensionIdArgs, frame, "extension", ERROR_CODES.INVALID_PARAM);
|
|
56709
56985
|
const target = await deps.runtime.open(extId);
|
|
56710
56986
|
return { response: target };
|
|
56711
56987
|
};
|
|
56712
56988
|
const close = async (frame, _client, ctx) => {
|
|
56713
56989
|
assertOwner(ctx);
|
|
56714
|
-
const extId =
|
|
56990
|
+
const { extId } = parseArgs2(ExtensionIdArgs, frame, "extension", ERROR_CODES.INVALID_PARAM);
|
|
56715
56991
|
await deps.runtime.close(extId);
|
|
56716
56992
|
return { response: { ok: true } };
|
|
56717
56993
|
};
|
|
56718
56994
|
const uninstall2 = async (frame, _client, ctx) => {
|
|
56719
56995
|
assertOwner(ctx);
|
|
56720
|
-
const extId =
|
|
56996
|
+
const { extId } = parseArgs2(ExtensionIdArgs, frame, "extension", ERROR_CODES.INVALID_PARAM);
|
|
56721
56997
|
await deps.uninstall({ root: deps.root, extId, runtime: deps.runtime });
|
|
56722
56998
|
return { response: { ok: true } };
|
|
56723
56999
|
};
|
|
@@ -56728,9 +57004,8 @@ function buildExtensionHandlers(deps) {
|
|
|
56728
57004
|
}
|
|
56729
57005
|
const publish = async (frame, _client, ctx) => {
|
|
56730
57006
|
assertOwner(ctx);
|
|
56731
|
-
const extId =
|
|
56732
|
-
|
|
56733
|
-
if (newVersion !== null) {
|
|
57007
|
+
const { extId, newVersion } = parseArgs2(ExtensionPublishArgs, frame, "publish", ERROR_CODES.INVALID_PARAM);
|
|
57008
|
+
if (newVersion != null) {
|
|
56734
57009
|
await rewriteManifestVersion(deps.root, extId, newVersion, deps.publishedChannelStore.get(extId)?.version);
|
|
56735
57010
|
}
|
|
56736
57011
|
const { manifest, contentHash, buffer } = await buildSnapshotMeta(extId);
|
|
@@ -56774,7 +57049,7 @@ function buildExtensionHandlers(deps) {
|
|
|
56774
57049
|
};
|
|
56775
57050
|
const unpublish = async (frame, _client, ctx) => {
|
|
56776
57051
|
assertOwner(ctx);
|
|
56777
|
-
const extId =
|
|
57052
|
+
const { extId } = parseArgs2(ExtensionIdArgs, frame, "extension", ERROR_CODES.INVALID_PARAM);
|
|
56778
57053
|
const head = deps.publishedChannelStore.get(extId);
|
|
56779
57054
|
await deps.publishedChannelStore.delete(extId);
|
|
56780
57055
|
if (head) {
|
|
@@ -56784,7 +57059,7 @@ function buildExtensionHandlers(deps) {
|
|
|
56784
57059
|
};
|
|
56785
57060
|
const publishStatus = async (frame, _client, ctx) => {
|
|
56786
57061
|
assertOwner(ctx);
|
|
56787
|
-
const extId =
|
|
57062
|
+
const { extId } = parseArgs2(ExtensionIdArgs, frame, "extension", ERROR_CODES.INVALID_PARAM);
|
|
56788
57063
|
const { manifest, contentHash } = await buildSnapshotMeta(extId);
|
|
56789
57064
|
const head = deps.publishedChannelStore.get(extId);
|
|
56790
57065
|
const check = computePublishCheck({
|
|
@@ -56833,8 +57108,7 @@ function buildExtensionHandlers(deps) {
|
|
|
56833
57108
|
if (!ctx || ctx.principal.kind !== "guest") {
|
|
56834
57109
|
throw new ClawdError(ERROR_CODES.FORBIDDEN, "guest only");
|
|
56835
57110
|
}
|
|
56836
|
-
|
|
56837
|
-
const expectedHash = pickStringField(frame, "snapshotHash");
|
|
57111
|
+
const { snapshotHash: expectedHash } = parseArgs2(ExtensionFetchBundleArgs, frame, "fetchBundle", ERROR_CODES.INVALID_PARAM);
|
|
56838
57112
|
const cached = await deps.bundleCache.read(expectedHash);
|
|
56839
57113
|
if (cached === null) {
|
|
56840
57114
|
throw new ClawdError(
|
|
@@ -56846,9 +57120,7 @@ function buildExtensionHandlers(deps) {
|
|
|
56846
57120
|
};
|
|
56847
57121
|
const installFromChannelHandler = async (frame, _client, ctx) => {
|
|
56848
57122
|
assertOwner(ctx);
|
|
56849
|
-
const channelRef =
|
|
56850
|
-
const snapshotHash = pickStringField(frame, "snapshotHash");
|
|
56851
|
-
const zipBase64 = pickStringField(frame, "zipBase64");
|
|
57123
|
+
const { channelRef, snapshotHash, zipBase64 } = parseArgs2(ExtensionFromChannelArgs, frame, "fromChannel", ERROR_CODES.INVALID_PARAM);
|
|
56852
57124
|
const bundleZip = Buffer.from(zipBase64, "base64");
|
|
56853
57125
|
try {
|
|
56854
57126
|
const { extId, installedVersion } = await installFromChannel(
|
|
@@ -56868,9 +57140,7 @@ function buildExtensionHandlers(deps) {
|
|
|
56868
57140
|
};
|
|
56869
57141
|
const updateFromChannelHandler = async (frame, _client, ctx) => {
|
|
56870
57142
|
assertOwner(ctx);
|
|
56871
|
-
const channelRef =
|
|
56872
|
-
const snapshotHash = pickStringField(frame, "snapshotHash");
|
|
56873
|
-
const zipBase64 = pickStringField(frame, "zipBase64");
|
|
57143
|
+
const { channelRef, snapshotHash, zipBase64 } = parseArgs2(ExtensionFromChannelArgs, frame, "fromChannel", ERROR_CODES.INVALID_PARAM);
|
|
56874
57144
|
const bundleZip = Buffer.from(zipBase64, "base64");
|
|
56875
57145
|
try {
|
|
56876
57146
|
const result = await updateFromChannel(
|
|
@@ -57635,10 +57905,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57635
57905
|
return { response: { projects: metas.map(toProjectWithStatus) } };
|
|
57636
57906
|
};
|
|
57637
57907
|
const getProject = async (frame, _client, ctx) => {
|
|
57638
|
-
const f = frame;
|
|
57639
|
-
if (typeof f.sessionId !== "string" || !f.sessionId) {
|
|
57640
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "getProject: sessionId required");
|
|
57641
|
-
}
|
|
57908
|
+
const f = parseArgs2(GetProjectArgsSchema, frame, "getProject");
|
|
57642
57909
|
if (ctx && !canAccessSession(ctx, f.sessionId, "read", {
|
|
57643
57910
|
readSession: (sid) => sessionManager.findOwnedSession(sid) ?? null
|
|
57644
57911
|
})) {
|
|
@@ -57653,13 +57920,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57653
57920
|
return { response: { project: meta ? toProjectWithStatus(meta) : null } };
|
|
57654
57921
|
};
|
|
57655
57922
|
const createProject = async (frame, _client, ctx) => {
|
|
57656
|
-
const f = frame;
|
|
57657
|
-
if (typeof f.sessionId !== "string" || !f.sessionId) {
|
|
57658
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "createProject: sessionId required");
|
|
57659
|
-
}
|
|
57660
|
-
if (typeof f.name !== "string" || !f.name) {
|
|
57661
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "createProject: name required");
|
|
57662
|
-
}
|
|
57923
|
+
const f = parseArgs2(CreateProjectArgsSchema, frame, "createProject");
|
|
57663
57924
|
const session = sessionManager.findOwnedSession(f.sessionId);
|
|
57664
57925
|
if (!session) {
|
|
57665
57926
|
throw new ClawdError(ERROR_CODES.SESSION_NOT_FOUND, `session ${f.sessionId} not found`);
|
|
@@ -57713,8 +57974,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57713
57974
|
return { response: { project, projectDir: userStore.projectDir(project.name) }, broadcast };
|
|
57714
57975
|
};
|
|
57715
57976
|
const deleteProject = async (frame, _client, ctx) => {
|
|
57716
|
-
const name = frame
|
|
57717
|
-
if (typeof name !== "string") throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "deleteProject: name required");
|
|
57977
|
+
const { name } = parseArgs2(DeleteProjectArgsSchema, frame, "deleteProject");
|
|
57718
57978
|
const userStore = resolveStore({ ctx, projectName: name });
|
|
57719
57979
|
await devServerLifecycle.stopForProject(name);
|
|
57720
57980
|
await userStore.delete(name);
|
|
@@ -57722,9 +57982,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57722
57982
|
return { response: {} };
|
|
57723
57983
|
};
|
|
57724
57984
|
const updateProjectPort = async (frame, _client, ctx) => {
|
|
57725
|
-
const f = frame;
|
|
57726
|
-
if (typeof f.name !== "string") throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "updateProjectPort: name required");
|
|
57727
|
-
if (typeof f.newPort !== "number") throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "updateProjectPort: newPort required");
|
|
57985
|
+
const f = parseArgs2(UpdateProjectPortArgsSchema, frame, "updateProjectPort");
|
|
57728
57986
|
const userStore = resolveStore({ ctx, projectName: f.name });
|
|
57729
57987
|
await devServerLifecycle.stopForProject(f.name);
|
|
57730
57988
|
const project = await userStore.updatePort(f.name, f.newPort);
|
|
@@ -57732,9 +57990,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57732
57990
|
return { response: { project } };
|
|
57733
57991
|
};
|
|
57734
57992
|
const setProdUrl = async (frame, _client, ctx) => {
|
|
57735
|
-
const f = frame;
|
|
57736
|
-
if (typeof f.name !== "string") throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "setProdUrl: name required");
|
|
57737
|
-
if (typeof f.url !== "string") throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "setProdUrl: url required");
|
|
57993
|
+
const f = parseArgs2(SetProdUrlArgsSchema, frame, "setProdUrl");
|
|
57738
57994
|
ensureProjectWriteAccess(ctx, { projectName: f.name });
|
|
57739
57995
|
const userStore = resolveStore({ ctx, projectName: f.name });
|
|
57740
57996
|
const project = await userStore.setProdUrl(f.name, f.url);
|
|
@@ -57743,10 +57999,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57743
57999
|
return { response: { project } };
|
|
57744
58000
|
};
|
|
57745
58001
|
const startDevServer = async (frame, _client, ctx) => {
|
|
57746
|
-
const f = frame;
|
|
57747
|
-
if (typeof f.sessionId !== "string" || !f.sessionId) {
|
|
57748
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "startDevServer: sessionId required");
|
|
57749
|
-
}
|
|
58002
|
+
const f = parseArgs2(StartDevServerArgsSchema, frame, "startDevServer");
|
|
57750
58003
|
const force = f.force === true;
|
|
57751
58004
|
ensureProjectWriteAccess(ctx, { sessionId: f.sessionId });
|
|
57752
58005
|
const session = sessionManager.findOwnedSession(f.sessionId);
|
|
@@ -57805,13 +58058,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57805
58058
|
return { response: { project: meta } };
|
|
57806
58059
|
};
|
|
57807
58060
|
const reportStage = async (frame, _client, ctx) => {
|
|
57808
|
-
const f = frame;
|
|
57809
|
-
if (typeof f.sessionId !== "string" || !f.sessionId) {
|
|
57810
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "reportStage: sessionId required");
|
|
57811
|
-
}
|
|
57812
|
-
if (typeof f.stage !== "string") {
|
|
57813
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "reportStage: stage required");
|
|
57814
|
-
}
|
|
58061
|
+
const f = parseArgs2(ReportStageArgsSchema, frame, "reportStage");
|
|
57815
58062
|
if (!ASSISTANT_REPORTABLE_STAGES.includes(f.stage)) {
|
|
57816
58063
|
throw new ClawdError(
|
|
57817
58064
|
ERROR_CODES.VALIDATION_ERROR,
|
|
@@ -57839,10 +58086,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57839
58086
|
return { response: { ok: true } };
|
|
57840
58087
|
};
|
|
57841
58088
|
const stopDevServer = async (frame, _client, ctx) => {
|
|
57842
|
-
const f = frame;
|
|
57843
|
-
if (typeof f.sessionId !== "string" || !f.sessionId) {
|
|
57844
|
-
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "stopDevServer: sessionId required");
|
|
57845
|
-
}
|
|
58089
|
+
const f = parseArgs2(StopDevServerArgsSchema, frame, "stopDevServer");
|
|
57846
58090
|
ensureProjectWriteAccess(ctx, { sessionId: f.sessionId });
|
|
57847
58091
|
const session = sessionManager.findOwnedSession(f.sessionId);
|
|
57848
58092
|
if (!session) {
|
|
@@ -57936,8 +58180,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57936
58180
|
const ownerSender = principalToSender(
|
|
57937
58181
|
makeOwnerPrincipal(
|
|
57938
58182
|
deps.ownerPrincipalId,
|
|
57939
|
-
deps.
|
|
57940
|
-
deps.
|
|
58183
|
+
deps.getOwnerIdentity().displayName || "Owner",
|
|
58184
|
+
deps.getOwnerIdentity().feishuUnionId
|
|
57941
58185
|
)
|
|
57942
58186
|
);
|
|
57943
58187
|
const { broadcast } = sessionManager.send({ sessionId, text }, ownerSender);
|
|
@@ -58330,9 +58574,7 @@ function buildMethodHandlers(deps) {
|
|
|
58330
58574
|
broadcast: deps.broadcastToOwners,
|
|
58331
58575
|
now: () => Date.now(),
|
|
58332
58576
|
ownerPrincipalId: deps.ownerPrincipalId,
|
|
58333
|
-
|
|
58334
|
-
ownerId: deps.ownerId,
|
|
58335
|
-
ownerProvider: deps.ownerProvider,
|
|
58577
|
+
getOwnerIdentity: deps.getOwnerIdentity,
|
|
58336
58578
|
exchangeToken: deps.exchangeToken
|
|
58337
58579
|
}),
|
|
58338
58580
|
...buildContactRemoteAccessHandlers({
|
|
@@ -58346,10 +58588,8 @@ function buildMethodHandlers(deps) {
|
|
|
58346
58588
|
forwardToPeer: (a) => forwardPeerExecToPeer(a)
|
|
58347
58589
|
}),
|
|
58348
58590
|
whoami: buildWhoamiHandler({
|
|
58349
|
-
ownerDisplayName: deps.ownerDisplayName,
|
|
58350
58591
|
ownerPrincipalId: deps.ownerPrincipalId,
|
|
58351
|
-
|
|
58352
|
-
ownerProvider: deps.ownerProvider,
|
|
58592
|
+
getOwnerIdentity: deps.getOwnerIdentity,
|
|
58353
58593
|
personaStore: deps.personaStore
|
|
58354
58594
|
}),
|
|
58355
58595
|
...buildFeishuAuthHandlers(deps.feishuAuth),
|
|
@@ -58370,8 +58610,7 @@ function buildMethodHandlers(deps) {
|
|
|
58370
58610
|
devServerLifecycle: deps.devServerLifecycle,
|
|
58371
58611
|
sessionManager: deps.manager,
|
|
58372
58612
|
ownerPrincipalId: deps.ownerPrincipalId,
|
|
58373
|
-
|
|
58374
|
-
ownerFeishuUnionId: deps.ownerFeishuUnionId,
|
|
58613
|
+
getOwnerIdentity: deps.getOwnerIdentity,
|
|
58375
58614
|
getTunnelUrl: deps.getTunnelUrl,
|
|
58376
58615
|
broadcastProjectUpdated: deps.broadcastProjectUpdated,
|
|
58377
58616
|
logger: deps.logger,
|
|
@@ -58652,6 +58891,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
58652
58891
|
};
|
|
58653
58892
|
|
|
58654
58893
|
// src/handlers/dispatch-rpc.ts
|
|
58894
|
+
init_zod();
|
|
58655
58895
|
init_protocol();
|
|
58656
58896
|
async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
58657
58897
|
if (!METHOD_NAMES.includes(method)) {
|
|
@@ -58675,7 +58915,14 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
58675
58915
|
);
|
|
58676
58916
|
}
|
|
58677
58917
|
}
|
|
58678
|
-
|
|
58918
|
+
try {
|
|
58919
|
+
return await handler(frame, client, ctx);
|
|
58920
|
+
} catch (err) {
|
|
58921
|
+
if (err instanceof ZodError) {
|
|
58922
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, err.message);
|
|
58923
|
+
}
|
|
58924
|
+
throw err;
|
|
58925
|
+
}
|
|
58679
58926
|
}
|
|
58680
58927
|
|
|
58681
58928
|
// src/extension/runtime.ts
|
|
@@ -59111,7 +59358,6 @@ async function startDaemon(config) {
|
|
|
59111
59358
|
isOwnerToken: (x) => resolvedAuthToken != null && constantTimeEqual(x, resolvedAuthToken),
|
|
59112
59359
|
ownerPrincipalId,
|
|
59113
59360
|
ownerDisplayName,
|
|
59114
|
-
ownerFeishuUnionId,
|
|
59115
59361
|
// persona web 分享:访客 visitor token = daemon 自签 HMAC(无 aud),独立于飞书 connect token
|
|
59116
59362
|
// 基建——secret 恒存在(auth-store backfill),故无条件注入。验签 ok → guest ctx(persona wildcard)。
|
|
59117
59363
|
verifyVisitorToken: (t) => {
|
|
@@ -59383,7 +59629,7 @@ async function startDaemon(config) {
|
|
|
59383
59629
|
personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
|
|
59384
59630
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
59385
59631
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
59386
|
-
getPersonaTool: (
|
|
59632
|
+
getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool,
|
|
59387
59633
|
usersRoot,
|
|
59388
59634
|
personaStore,
|
|
59389
59635
|
ownerDisplayName,
|
|
@@ -59622,217 +59868,219 @@ async function startDaemon(config) {
|
|
|
59622
59868
|
const effectivePreviewPorts = Array.from(
|
|
59623
59869
|
/* @__PURE__ */ new Set([...config.previewPorts ?? [], ...appBuilderPortRange])
|
|
59624
59870
|
);
|
|
59625
|
-
const
|
|
59626
|
-
|
|
59627
|
-
|
|
59628
|
-
|
|
59629
|
-
|
|
59630
|
-
|
|
59631
|
-
|
|
59632
|
-
|
|
59633
|
-
|
|
59634
|
-
|
|
59635
|
-
|
|
59636
|
-
|
|
59637
|
-
|
|
59638
|
-
|
|
59639
|
-
|
|
59640
|
-
|
|
59641
|
-
|
|
59642
|
-
|
|
59643
|
-
|
|
59644
|
-
|
|
59645
|
-
|
|
59646
|
-
|
|
59647
|
-
|
|
59648
|
-
|
|
59649
|
-
|
|
59650
|
-
|
|
59651
|
-
|
|
59652
|
-
|
|
59653
|
-
|
|
59654
|
-
|
|
59655
|
-
|
|
59656
|
-
|
|
59657
|
-
|
|
59658
|
-
// session,attachment 整套 RPC 对 persona session 都会报 "session not found"。
|
|
59659
|
-
// 详见 fix(daemon) #703:file-sharing v1 预存 wiring bug,#701 把 desktop 默认 --tunnel
|
|
59660
|
-
// 后首次让 desktop 用户用上 file-sharing 才被暴露。
|
|
59661
|
-
attachment: {
|
|
59662
|
-
groupFileStore,
|
|
59663
|
-
sessionStore: { read: (sid) => manager.findOwnedSession(sid) },
|
|
59871
|
+
const getOwnerIdentity = () => ({
|
|
59872
|
+
displayName: ownerDisplayName,
|
|
59873
|
+
ownerId,
|
|
59874
|
+
provider: ownerProvider,
|
|
59875
|
+
feishuUnionId: ownerFeishuUnionId
|
|
59876
|
+
});
|
|
59877
|
+
const handlers = {
|
|
59878
|
+
...buildMethodHandlers({
|
|
59879
|
+
// meta:methods 自省:飞书 gate getter + 最终 handler 表(下面还会 spread 进
|
|
59880
|
+
// dispatch / shift-internal 两组,只看 buildMethodHandlers 内部表会误报死方法)
|
|
59881
|
+
feishuActive: () => feishuActive,
|
|
59882
|
+
getAllHandlers: () => handlers,
|
|
59883
|
+
manager,
|
|
59884
|
+
workspace,
|
|
59885
|
+
skills,
|
|
59886
|
+
agents,
|
|
59887
|
+
// skills:list 按 tool 路由:codex → app-server skills/list;缺省 claude → SkillsScanner(同步包成 Promise)。
|
|
59888
|
+
getSkillsForTool: (tool, cwd) => tool === "codex" ? listCodexSkills(cwd) : Promise.resolve(skills.list({ cwd })),
|
|
59889
|
+
history,
|
|
59890
|
+
// history:read 按 session.tool 路由:codex → adapter.historyReader(CodexHistoryReader);缺省 claude。
|
|
59891
|
+
getHistoryReader: (tool) => getAdapter(tool).historyReader ?? history,
|
|
59892
|
+
observer,
|
|
59893
|
+
getAdapter,
|
|
59894
|
+
store,
|
|
59895
|
+
personaManager,
|
|
59896
|
+
personaRegistry,
|
|
59897
|
+
getTunnelUrl: () => currentTunnelUrl,
|
|
59898
|
+
// ready / info 帧的 mode = daemon CC spawn 模式('sdk' | 'tui')。UI 据此挂 XtermPanel +
|
|
59899
|
+
// 订阅 session:pty / session:control;业务帧名两种 mode 完全一致,UI 业务订阅代码不变
|
|
59900
|
+
mode: config.mode,
|
|
59901
|
+
// file-sharing (spec §8):ready / info 帧把 httpBaseUrl + httpToken 下发给 UI。
|
|
59902
|
+
// PR 2 阶段 httpToken 复用 owner WS token;noAuth 模式下为 null(UI 看到无 httpToken
|
|
59903
|
+
// 时禁用文件 GET/POST,保持 1.0 行为兼容)。
|
|
59664
59904
|
getHttpBaseUrl,
|
|
59665
|
-
|
|
59666
|
-
|
|
59667
|
-
//
|
|
59668
|
-
//
|
|
59669
|
-
getSessionScope
|
|
59670
|
-
//
|
|
59905
|
+
httpToken: resolvedAuthToken,
|
|
59906
|
+
// file-sharing attachment.* RPC。signUrl 用 owner token 做 HMAC secret;group RPC
|
|
59907
|
+
// 根据 sessionId 反查 scope 写盘。
|
|
59908
|
+
//
|
|
59909
|
+
// sessionStore / getSessionScope 都走 manager 的跨 scope 公开 API(findOwnedSession /
|
|
59910
|
+
// findOwnedSessionScope)—— 否则 default-only SessionStore 找不到 persona owner-mode
|
|
59911
|
+
// session,attachment 整套 RPC 对 persona session 都会报 "session not found"。
|
|
59912
|
+
// 详见 fix(daemon) #703:file-sharing v1 预存 wiring bug,#701 把 desktop 默认 --tunnel
|
|
59913
|
+
// 后首次让 desktop 用户用上 file-sharing 才被暴露。
|
|
59914
|
+
attachment: {
|
|
59915
|
+
groupFileStore,
|
|
59916
|
+
sessionStore: { read: (sid) => manager.findOwnedSession(sid) },
|
|
59917
|
+
getHttpBaseUrl,
|
|
59918
|
+
// HMAC sign secret = auth.json 唯一 token(authFile 恒非空,startDaemon 开头加载)。
|
|
59919
|
+
getSignSecret: () => authFile.token,
|
|
59920
|
+
// group RPC + sign 都用:根据 sessionId 反查 scope。owner-mode persona session 走
|
|
59921
|
+
// 'persona/<pid>/owner',default 走 'default'。
|
|
59922
|
+
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
59923
|
+
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
59924
|
+
personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
|
|
59925
|
+
usersRoot
|
|
59926
|
+
},
|
|
59927
|
+
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
59671
59928
|
personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
|
|
59672
|
-
|
|
59673
|
-
|
|
59674
|
-
|
|
59675
|
-
|
|
59676
|
-
|
|
59677
|
-
|
|
59678
|
-
|
|
59679
|
-
|
|
59680
|
-
|
|
59681
|
-
|
|
59682
|
-
|
|
59683
|
-
|
|
59684
|
-
|
|
59685
|
-
|
|
59686
|
-
|
|
59687
|
-
|
|
59688
|
-
// cascade 接 store (list 统计 deletedInboxEvents).
|
|
59689
|
-
inboxManager,
|
|
59690
|
-
inboxStore,
|
|
59691
|
-
// 联系人列表 store(device:connect 出站 / contact:handshake 入站落同一 store)
|
|
59692
|
-
contactStore,
|
|
59693
|
-
// contact:handshake 换票回填(spec 2026-07-22):用 owner 当前 jwt 换 aud=对方设备 的票。
|
|
59694
|
-
// 现读 ownerIdentityStore(热切换后用新身份);失败 / 未登录 → null → 保持空票。
|
|
59695
|
-
exchangeToken: async (targetDeviceId) => {
|
|
59696
|
-
const record = ownerIdentityStore.read();
|
|
59697
|
-
if (!record) return null;
|
|
59698
|
-
try {
|
|
59699
|
-
const r = await centralExchange({
|
|
59700
|
-
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
59701
|
-
jwt: record.ttcToken,
|
|
59702
|
-
provider: record.identity.provider,
|
|
59703
|
-
deviceId: targetDeviceId,
|
|
59704
|
-
selfDeviceId: authFile.deviceId
|
|
59705
|
-
});
|
|
59706
|
-
return r.token;
|
|
59707
|
-
} catch (e) {
|
|
59708
|
-
logger.warn("contact:handshake exchange token failed", {
|
|
59709
|
-
targetDeviceId,
|
|
59710
|
-
err: e.message
|
|
59711
|
-
});
|
|
59712
|
-
return null;
|
|
59713
|
-
}
|
|
59714
|
-
},
|
|
59715
|
-
// inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
|
|
59716
|
-
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
59717
|
-
// contact:removed broadcast;复用 capability:tokenIssued 同款通路
|
|
59718
|
-
broadcastToOwners: (frame) => wsServer?.broadcastToOwners(frame),
|
|
59719
|
-
// extension runtime (v1: local-mode only). Instance owned by daemon top
|
|
59720
|
-
// level so stopAll() runs in the shutdown hook below.
|
|
59721
|
-
extensionRuntime,
|
|
59722
|
-
// extension sharing v1 — owner-side published-channels store.
|
|
59723
|
-
publishedChannelStore,
|
|
59724
|
-
bundleCache,
|
|
59725
|
-
// 飞书统一身份 Phase 1:登录 RPC handlers(auth:login:start / getIdentity / logout)
|
|
59726
|
-
// deviceId(决策 #15):getIdentity 返回给 UI 拼"我的设备标识"
|
|
59727
|
-
feishuAuth: {
|
|
59728
|
-
loginFlow,
|
|
59729
|
-
ownerIdentityStore,
|
|
59730
|
-
deviceId: authFile.deviceId,
|
|
59731
|
-
serverKeyStore,
|
|
59732
|
-
// 退出登录:登录(feishuLogin.handleLoginCallback)在进程内设置的身份状态的对称逆操作。
|
|
59733
|
-
// 核心是 feishuActive 翻 false——否则 dispatcher 飞书 gate(下方 feishuActive 判定,每帧
|
|
59734
|
-
// 现读 let binding)退登后仍放行 gated 方法。一并把归属人重置回未登录初值 + 重建 handlers
|
|
59735
|
-
// (deps 持 ownerId/displayName 值快照,whoami/出站自报身份用),与登录置位三件套对称。
|
|
59736
|
-
// 不踢连:踢连是登录热切换换身份 ctx 的需要;退登只是降级,gate 每帧现读即时生效,
|
|
59737
|
-
// 既有连接继续用,避免改动连接生命周期 / wire 契约。
|
|
59738
|
-
onLogout: () => {
|
|
59739
|
-
feishuActive = false;
|
|
59740
|
-
ownerId = "";
|
|
59741
|
-
ownerProvider = "";
|
|
59742
|
-
ownerDisplayName = loadOwnerDisplayName(config.dataDir);
|
|
59743
|
-
handlers = makeHandlers();
|
|
59744
|
-
}
|
|
59745
|
-
},
|
|
59746
|
-
// 设备目录 + 连接(决策 #15:daemon 代理中心 server)。
|
|
59747
|
-
// exchange/listDevices 包掉 owner ttcJwt(每次现读 store——热切换后立即用新身份);
|
|
59748
|
-
// dispatcher 的 FEISHU_GATED_METHODS gate 已保证未登录时这些 RPC 到不了 handler,
|
|
59749
|
-
// 这里的 FEISHU_LOGIN_REQUIRED 抛错只是防御纵深。
|
|
59750
|
-
feishuDevice: {
|
|
59751
|
-
store: contactStore,
|
|
59752
|
-
exchange: async (deviceId) => {
|
|
59929
|
+
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
59930
|
+
usersRoot,
|
|
59931
|
+
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
59932
|
+
getOwnerIdentity,
|
|
59933
|
+
// 决策 #16: whoami owner.id = 本机 deviceId(路由主键,const,热切换不变)
|
|
59934
|
+
ownerPrincipalId,
|
|
59935
|
+
personaStore,
|
|
59936
|
+
// capability platform v3 inbox: handler 接 manager (post/list/markRead),
|
|
59937
|
+
// cascade 接 store (list 统计 deletedInboxEvents).
|
|
59938
|
+
inboxManager,
|
|
59939
|
+
inboxStore,
|
|
59940
|
+
// 联系人列表 store(device:connect 出站 / contact:handshake 入站落同一 store)
|
|
59941
|
+
contactStore,
|
|
59942
|
+
// contact:handshake 换票回填(spec 2026-07-22):用 owner 当前 jwt 换 aud=对方设备 的票。
|
|
59943
|
+
// 现读 ownerIdentityStore(热切换后用新身份);失败 / 未登录 → null → 保持空票。
|
|
59944
|
+
exchangeToken: async (targetDeviceId) => {
|
|
59753
59945
|
const record = ownerIdentityStore.read();
|
|
59754
|
-
if (!record)
|
|
59755
|
-
|
|
59756
|
-
|
|
59757
|
-
|
|
59758
|
-
|
|
59759
|
-
|
|
59760
|
-
|
|
59761
|
-
|
|
59762
|
-
|
|
59763
|
-
|
|
59946
|
+
if (!record) return null;
|
|
59947
|
+
try {
|
|
59948
|
+
const r = await centralExchange({
|
|
59949
|
+
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
59950
|
+
jwt: record.ttcToken,
|
|
59951
|
+
provider: record.identity.provider,
|
|
59952
|
+
deviceId: targetDeviceId,
|
|
59953
|
+
selfDeviceId: authFile.deviceId
|
|
59954
|
+
});
|
|
59955
|
+
return r.token;
|
|
59956
|
+
} catch (e) {
|
|
59957
|
+
logger.warn("contact:handshake exchange token failed", {
|
|
59958
|
+
targetDeviceId,
|
|
59959
|
+
err: e.message
|
|
59960
|
+
});
|
|
59961
|
+
return null;
|
|
59962
|
+
}
|
|
59764
59963
|
},
|
|
59765
|
-
|
|
59766
|
-
|
|
59767
|
-
|
|
59768
|
-
|
|
59964
|
+
// inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
|
|
59965
|
+
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
59966
|
+
// contact:removed broadcast;复用 capability:tokenIssued 同款通路
|
|
59967
|
+
broadcastToOwners: (frame) => wsServer?.broadcastToOwners(frame),
|
|
59968
|
+
// extension runtime (v1: local-mode only). Instance owned by daemon top
|
|
59969
|
+
// level so stopAll() runs in the shutdown hook below.
|
|
59970
|
+
extensionRuntime,
|
|
59971
|
+
// extension sharing v1 — owner-side published-channels store.
|
|
59972
|
+
publishedChannelStore,
|
|
59973
|
+
bundleCache,
|
|
59974
|
+
// 飞书统一身份 Phase 1:登录 RPC handlers(auth:login:start / getIdentity / logout)
|
|
59975
|
+
// deviceId(决策 #15):getIdentity 返回给 UI 拼"我的设备标识"
|
|
59976
|
+
feishuAuth: {
|
|
59977
|
+
loginFlow,
|
|
59978
|
+
ownerIdentityStore,
|
|
59979
|
+
deviceId: authFile.deviceId,
|
|
59980
|
+
serverKeyStore,
|
|
59981
|
+
// 退出登录:登录(feishuLogin.handleLoginCallback)在进程内设置的身份状态的对称逆操作。
|
|
59982
|
+
// 核心是 feishuActive 翻 false——否则 dispatcher 飞书 gate(下方 feishuActive 判定,每帧
|
|
59983
|
+
// 现读 let binding)退登后仍放行 gated 方法。一并把归属人重置回未登录初值 + 重建 handlers
|
|
59984
|
+
// (deps 持 ownerId/displayName 值快照,whoami/出站自报身份用),与登录置位三件套对称。
|
|
59985
|
+
// 不踢连:踢连是登录热切换换身份 ctx 的需要;退登只是降级,gate 每帧现读即时生效,
|
|
59986
|
+
// 既有连接继续用,避免改动连接生命周期 / wire 契约。
|
|
59987
|
+
onLogout: () => {
|
|
59988
|
+
feishuActive = false;
|
|
59989
|
+
ownerId = "";
|
|
59990
|
+
ownerProvider = "";
|
|
59991
|
+
ownerDisplayName = loadOwnerDisplayName(config.dataDir);
|
|
59769
59992
|
}
|
|
59770
|
-
return centralListDevices({
|
|
59771
|
-
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
59772
|
-
ttcJwt: record.ttcToken,
|
|
59773
|
-
provider: record.identity.provider
|
|
59774
|
-
});
|
|
59775
59993
|
},
|
|
59776
|
-
|
|
59777
|
-
|
|
59778
|
-
//
|
|
59779
|
-
//
|
|
59780
|
-
|
|
59781
|
-
|
|
59782
|
-
|
|
59783
|
-
|
|
59784
|
-
|
|
59785
|
-
|
|
59786
|
-
|
|
59787
|
-
|
|
59788
|
-
|
|
59789
|
-
|
|
59790
|
-
|
|
59791
|
-
|
|
59792
|
-
|
|
59793
|
-
|
|
59794
|
-
|
|
59795
|
-
|
|
59796
|
-
|
|
59797
|
-
|
|
59798
|
-
|
|
59799
|
-
|
|
59800
|
-
|
|
59801
|
-
|
|
59802
|
-
|
|
59803
|
-
|
|
59804
|
-
|
|
59805
|
-
|
|
59806
|
-
|
|
59807
|
-
|
|
59808
|
-
|
|
59809
|
-
|
|
59810
|
-
|
|
59811
|
-
|
|
59812
|
-
|
|
59813
|
-
|
|
59814
|
-
|
|
59815
|
-
|
|
59816
|
-
|
|
59817
|
-
|
|
59818
|
-
|
|
59819
|
-
|
|
59820
|
-
|
|
59821
|
-
|
|
59822
|
-
|
|
59823
|
-
|
|
59824
|
-
|
|
59825
|
-
|
|
59826
|
-
|
|
59827
|
-
|
|
59828
|
-
|
|
59829
|
-
|
|
59830
|
-
|
|
59831
|
-
|
|
59832
|
-
|
|
59833
|
-
|
|
59834
|
-
|
|
59835
|
-
|
|
59994
|
+
// 设备目录 + 连接(决策 #15:daemon 代理中心 server)。
|
|
59995
|
+
// exchange/listDevices 包掉 owner ttcJwt(每次现读 store——热切换后立即用新身份);
|
|
59996
|
+
// dispatcher 的 FEISHU_GATED_METHODS gate 已保证未登录时这些 RPC 到不了 handler,
|
|
59997
|
+
// 这里的 FEISHU_LOGIN_REQUIRED 抛错只是防御纵深。
|
|
59998
|
+
feishuDevice: {
|
|
59999
|
+
store: contactStore,
|
|
60000
|
+
exchange: async (deviceId) => {
|
|
60001
|
+
const record = ownerIdentityStore.read();
|
|
60002
|
+
if (!record) {
|
|
60003
|
+
throw new ClawdError(ERROR_CODES.FEISHU_LOGIN_REQUIRED, "device:connect requires feishu login");
|
|
60004
|
+
}
|
|
60005
|
+
return centralExchange({
|
|
60006
|
+
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
60007
|
+
jwt: record.ttcToken,
|
|
60008
|
+
provider: record.identity.provider,
|
|
60009
|
+
deviceId,
|
|
60010
|
+
selfDeviceId: authFile.deviceId
|
|
60011
|
+
});
|
|
60012
|
+
},
|
|
60013
|
+
listDevices: async () => {
|
|
60014
|
+
const record = ownerIdentityStore.read();
|
|
60015
|
+
if (!record) {
|
|
60016
|
+
throw new ClawdError(ERROR_CODES.FEISHU_LOGIN_REQUIRED, "device:list requires feishu login");
|
|
60017
|
+
}
|
|
60018
|
+
return centralListDevices({
|
|
60019
|
+
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
60020
|
+
ttcJwt: record.ttcToken,
|
|
60021
|
+
provider: record.identity.provider
|
|
60022
|
+
});
|
|
60023
|
+
},
|
|
60024
|
+
connectRemote,
|
|
60025
|
+
broadcast: (frame) => wsServer?.broadcastToOwners(frame),
|
|
60026
|
+
// 自动反向(spec 决策 #11):本机可达地址 = tunnel URL(公网),出站连接时
|
|
60027
|
+
// 透传让对方反向加我为联系人。无 tunnel(仅本机 ws)→ null,对方不自动反向(不造假数据)。
|
|
60028
|
+
// 决策 #16:身份不自报——本机 deviceId/ownerId/provider 由 exchange 签进 token 背书。
|
|
60029
|
+
selfUrl: () => currentTunnelUrl
|
|
60030
|
+
},
|
|
60031
|
+
// app-builder
|
|
60032
|
+
appBuilderStore,
|
|
60033
|
+
getProjectStore,
|
|
60034
|
+
devServerLifecycle: devServerSupervisor,
|
|
60035
|
+
// 单栏 refactor §5.6.2 stage fix:appBuilder:project-updated 帧通过 wsServer broadcast。
|
|
60036
|
+
// 推给所有 owner 连接(picker 可能没订阅特定 session,全局 broadcast 最稳)。
|
|
60037
|
+
// people/mirror(spec 2026-06-04-people-mode-app-builder-write-and-push):额外推给订阅该 project
|
|
60038
|
+
// 绑定 session 的 client(mirror guest 经 session:observe 订阅),让远端协同者也看到 stage / 发布进度。
|
|
60039
|
+
// 同一帧 owner 也走 project-updated 复用给 publish-progress/failed(app-builder.ts 内 broadcast 闭包):
|
|
60040
|
+
// name 在 event.project.name(project-updated)或 event.name(publish 帧)。owner 双栏会同时命中
|
|
60041
|
+
// owner-broadcast + session-broadcast,但 UI patch 幂等(同 project 覆盖)无害。
|
|
60042
|
+
broadcastProjectUpdated: (event) => {
|
|
60043
|
+
const ev = event;
|
|
60044
|
+
wsServer?.broadcastToOwners(ev);
|
|
60045
|
+
const projectName = event.project?.name ?? event.name;
|
|
60046
|
+
const boundSid = projectName ? manager.findOwnedSessionByAppBuilderProject(projectName)?.sessionId : void 0;
|
|
60047
|
+
if (boundSid) wsServer?.broadcastToSession(boundSid, ev);
|
|
60048
|
+
},
|
|
60049
|
+
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
60050
|
+
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
60051
|
+
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
60052
|
+
appBuilderPersonaRoot: import_node_path62.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
60053
|
+
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
60054
|
+
deployKitRoot: import_node_path62.default.join(config.dataDir, "deploy-kit"),
|
|
60055
|
+
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
60056
|
+
resolvePersonaRoot: (personaId2) => import_node_path62.default.join(config.dataDir, "personas", personaId2),
|
|
60057
|
+
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
60058
|
+
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
60059
|
+
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
60060
|
+
broadcastSessionFrame: (frame, target) => {
|
|
60061
|
+
if (target === "all") {
|
|
60062
|
+
transport?.broadcastAll(frame);
|
|
60063
|
+
return;
|
|
60064
|
+
}
|
|
60065
|
+
const sid = frame.sessionId;
|
|
60066
|
+
if (!sid) return;
|
|
60067
|
+
if (target === "first-subscriber") {
|
|
60068
|
+
const handle = transport?.firstSubscriber(sid);
|
|
60069
|
+
if (handle) handle.send(frame);
|
|
60070
|
+
return;
|
|
60071
|
+
}
|
|
60072
|
+
transport?.broadcastToSession(sid, frame);
|
|
60073
|
+
},
|
|
60074
|
+
logger,
|
|
60075
|
+
// shift v1:shift:list 桥接 handler 透传 ShiftStore 单例(同实例也喂给
|
|
60076
|
+
// shift-internal:* MCP loopback handler)。owner 过滤用 ownerPrincipalId(跨
|
|
60077
|
+
// daemon 稳定身份),跟我们 ShiftStore boot 时用的 provider 一致。
|
|
60078
|
+
shiftStore,
|
|
60079
|
+
shiftOwnerIdProvider: () => ownerPrincipalId,
|
|
60080
|
+
// persona web 分享:visitor:list owner RPC 读访客名单(同 exchange upsert 的实例)
|
|
60081
|
+
visitorStore
|
|
60082
|
+
})
|
|
60083
|
+
};
|
|
59836
60084
|
const dispatchHandlers = buildPersonaDispatchHandlers({
|
|
59837
60085
|
personaDispatchManager,
|
|
59838
60086
|
store: dispatchStore,
|
|
@@ -59899,16 +60147,16 @@ async function startDaemon(config) {
|
|
|
59899
60147
|
});
|
|
59900
60148
|
},
|
|
59901
60149
|
// B 角色:判断 targetPersona 是否 public(跨设备授权边界,private 拒)。
|
|
59902
|
-
getPersonaPublic: (
|
|
60150
|
+
getPersonaPublic: (personaId2) => personaRegistry.get(personaId2)?.public ?? false,
|
|
59903
60151
|
// model 校验按 target persona 绑定 tool 选表(claude / codex 模型集不同)
|
|
59904
|
-
getPersonaTool: (
|
|
60152
|
+
getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool
|
|
59905
60153
|
});
|
|
59906
|
-
handlers
|
|
60154
|
+
Object.assign(handlers, dispatchHandlers);
|
|
59907
60155
|
const shiftHandlers = buildShiftInternalHandlers({
|
|
59908
60156
|
store: shiftStore,
|
|
59909
60157
|
ownerIdProvider: () => ownerPrincipalId
|
|
59910
60158
|
});
|
|
59911
|
-
handlers
|
|
60159
|
+
Object.assign(handlers, shiftHandlers);
|
|
59912
60160
|
const shiftSpawnFn = createShiftSpawnFn({ sessionManager: manager });
|
|
59913
60161
|
const shiftScheduler = createShiftScheduler({
|
|
59914
60162
|
store: shiftStore,
|
|
@@ -59987,7 +60235,6 @@ async function startDaemon(config) {
|
|
|
59987
60235
|
ownerProvider = result.identity.provider;
|
|
59988
60236
|
ownerDisplayName = result.identity.displayName;
|
|
59989
60237
|
ownerFeishuUnionId = result.identity.unionId;
|
|
59990
|
-
handlers = makeHandlers();
|
|
59991
60238
|
wsServer?.broadcastToOwners({ type: "auth:login:done", identity: result.identity });
|
|
59992
60239
|
setImmediate(() => wsServer?.closeAllClients());
|
|
59993
60240
|
void reportDevice();
|