@clawos-dev/clawd 0.2.221-beta.432.4424967 → 0.2.221-beta.433.d7a6891
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 +72 -320
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-B5ChN9T3.css +32 -0
- package/dist/share-ui/assets/{guest-ZjGuFfc2.js → guest-BA1GIgmA.js} +119 -119
- package/dist/share-ui/guest.html +2 -2
- package/dist/ticket/mcp-server.cjs +33 -76
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-CuXP1xCR.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -45,9 +45,6 @@ var init_methods = __esm({
|
|
|
45
45
|
"session:update",
|
|
46
46
|
"session:delete",
|
|
47
47
|
"session:send",
|
|
48
|
-
// per-turn sender 2026-07-08 spec §4.6:MCP servers (ticket / inbox ...) 走 HTTP RPC
|
|
49
|
-
// /api/rpc/session.currentTurnSender 拉当前 turn caller;WS handler 同名(loopback path 复用)
|
|
50
|
-
"session:currentTurnSender",
|
|
51
48
|
"session:stop",
|
|
52
49
|
// 温柔中断当前轮次,不杀进程(走 CC IPC control_request.subtype=interrupt)
|
|
53
50
|
"session:interrupt",
|
|
@@ -4523,59 +4520,6 @@ var init_attachment_schemas = __esm({
|
|
|
4523
4520
|
}
|
|
4524
4521
|
});
|
|
4525
4522
|
|
|
4526
|
-
// ../protocol/src/principal.ts
|
|
4527
|
-
function makeOwnerPrincipal(id, displayName, feishuUnionId) {
|
|
4528
|
-
return PrincipalSchema.parse({
|
|
4529
|
-
id,
|
|
4530
|
-
kind: "owner",
|
|
4531
|
-
displayName,
|
|
4532
|
-
...feishuUnionId ? { feishuUnionId } : {}
|
|
4533
|
-
});
|
|
4534
|
-
}
|
|
4535
|
-
function principalToSender(p2) {
|
|
4536
|
-
return {
|
|
4537
|
-
did: p2.id,
|
|
4538
|
-
displayName: p2.displayName,
|
|
4539
|
-
principal: p2.kind,
|
|
4540
|
-
...p2.feishuUnionId ? { feishuUnionId: p2.feishuUnionId } : {}
|
|
4541
|
-
};
|
|
4542
|
-
}
|
|
4543
|
-
function makeGuestSender(did, displayName, feishuUnionId) {
|
|
4544
|
-
return SenderInfoSchema.parse({
|
|
4545
|
-
did,
|
|
4546
|
-
displayName,
|
|
4547
|
-
principal: "guest",
|
|
4548
|
-
...feishuUnionId ? { feishuUnionId } : {}
|
|
4549
|
-
});
|
|
4550
|
-
}
|
|
4551
|
-
var PrincipalKindSchema, PrincipalSchema, SenderInfoSchema;
|
|
4552
|
-
var init_principal = __esm({
|
|
4553
|
-
"../protocol/src/principal.ts"() {
|
|
4554
|
-
"use strict";
|
|
4555
|
-
init_zod();
|
|
4556
|
-
PrincipalKindSchema = external_exports.enum(["owner", "guest"]);
|
|
4557
|
-
PrincipalSchema = external_exports.object({
|
|
4558
|
-
id: external_exports.string().min(1),
|
|
4559
|
-
kind: PrincipalKindSchema,
|
|
4560
|
-
displayName: external_exports.string(),
|
|
4561
|
-
/**
|
|
4562
|
-
* 飞书 union_id。owner: 本机 daemon 已飞书登录时透传自 owner-identity.json;未登录 undefined。
|
|
4563
|
-
* guest: v1 保持 undefined(connect token 当前不携带 unionId;未来若签名 payload 加字段可透传)。
|
|
4564
|
-
* 消费方(如 ticket MCP / 未来别的飞书身份挂钩场景)按 undefined 决定是否降级;本层不做 fallback。
|
|
4565
|
-
*/
|
|
4566
|
-
feishuUnionId: external_exports.string().optional()
|
|
4567
|
-
}).strict();
|
|
4568
|
-
SenderInfoSchema = external_exports.object({
|
|
4569
|
-
/** = principal.id = deviceId(决策 #16)。稳定路由 id */
|
|
4570
|
-
did: external_exports.string().min(1),
|
|
4571
|
-
displayName: external_exports.string(),
|
|
4572
|
-
/** owner 未登录 / guest 无飞书身份时缺省。消费方各自决定是否降级 */
|
|
4573
|
-
feishuUnionId: external_exports.string().optional(),
|
|
4574
|
-
principal: PrincipalKindSchema
|
|
4575
|
-
}).strict();
|
|
4576
|
-
}
|
|
4577
|
-
});
|
|
4578
|
-
|
|
4579
4523
|
// ../protocol/src/persona-schemas.ts
|
|
4580
4524
|
var PersonaFileSchema, PersonaSkillSummarySchema, PersonaPluginSummarySchema, PersonaSandboxSettingsSchema, PersonaInfoResponseSchema, PersonaCreateArgsSchema, PersonaIdArgsSchema, PersonaUpdateArgsSchema, CodexSandboxSettingsSchema;
|
|
4581
4525
|
var init_persona_schemas = __esm({
|
|
@@ -4684,7 +4628,6 @@ var init_schemas = __esm({
|
|
|
4684
4628
|
init_zod();
|
|
4685
4629
|
init_events();
|
|
4686
4630
|
init_attachment_schemas();
|
|
4687
|
-
init_principal();
|
|
4688
4631
|
init_persona_schemas();
|
|
4689
4632
|
SessionStatusSchema = external_exports.enum(SESSION_STATUS_VALUES);
|
|
4690
4633
|
UsageSchema = external_exports.object({
|
|
@@ -4951,18 +4894,13 @@ var init_schemas = __esm({
|
|
|
4951
4894
|
// 真实用户输入:daemon 通过 --replay-user-messages 拿到 stdin 回显,区分于 assistant text。
|
|
4952
4895
|
// meta 非空表示是 CC 注入的系统消息(task-notification / slash-command / system-reminder 等),
|
|
4953
4896
|
// UI 据此走低视觉权重渲染或子 agent 通知卡。
|
|
4954
|
-
//
|
|
4955
|
-
// sender(2026-07-08 spec §4.1):daemon 'send' 命令 synth 的 user_text 携带发起人 SenderInfo;
|
|
4956
|
-
// observer 回灌路径(cc jsonl)永远不带 —— cc 自己写盘不知道 daemon 层身份。
|
|
4957
|
-
// UI 端 sender 缺省 → 不渲染 displayName label;有 → 气泡下方渲染。
|
|
4958
4897
|
external_exports.object({
|
|
4959
4898
|
...ParsedEventBase,
|
|
4960
4899
|
kind: external_exports.literal("user_text"),
|
|
4961
4900
|
text: external_exports.string(),
|
|
4962
4901
|
meta: HistoryUserMetaSchema.optional(),
|
|
4963
4902
|
taskId: external_exports.string().optional(),
|
|
4964
|
-
parentToolUseId: external_exports.string().optional()
|
|
4965
|
-
sender: SenderInfoSchema.optional()
|
|
4903
|
+
parentToolUseId: external_exports.string().optional()
|
|
4966
4904
|
}),
|
|
4967
4905
|
external_exports.object({
|
|
4968
4906
|
...ParsedEventBase,
|
|
@@ -5571,6 +5509,24 @@ var init_persona_mode = __esm({
|
|
|
5571
5509
|
}
|
|
5572
5510
|
});
|
|
5573
5511
|
|
|
5512
|
+
// ../protocol/src/principal.ts
|
|
5513
|
+
function makeOwnerPrincipal(id, displayName) {
|
|
5514
|
+
return PrincipalSchema.parse({ id, kind: "owner", displayName });
|
|
5515
|
+
}
|
|
5516
|
+
var PrincipalKindSchema, PrincipalSchema;
|
|
5517
|
+
var init_principal = __esm({
|
|
5518
|
+
"../protocol/src/principal.ts"() {
|
|
5519
|
+
"use strict";
|
|
5520
|
+
init_zod();
|
|
5521
|
+
PrincipalKindSchema = external_exports.enum(["owner", "guest"]);
|
|
5522
|
+
PrincipalSchema = external_exports.object({
|
|
5523
|
+
id: external_exports.string().min(1),
|
|
5524
|
+
kind: PrincipalKindSchema,
|
|
5525
|
+
displayName: external_exports.string()
|
|
5526
|
+
}).strict();
|
|
5527
|
+
}
|
|
5528
|
+
});
|
|
5529
|
+
|
|
5574
5530
|
// ../protocol/src/capability.ts
|
|
5575
5531
|
function stripSecretHash(cap) {
|
|
5576
5532
|
const { secretHash: _hash, ...wire } = cap;
|
|
@@ -41695,47 +41651,6 @@ function escapeAttr(v2) {
|
|
|
41695
41651
|
return v2.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
41696
41652
|
}
|
|
41697
41653
|
|
|
41698
|
-
// src/shift/end-frame-handler.ts
|
|
41699
|
-
function makeEndFrameHandler(sessionId, onEnd) {
|
|
41700
|
-
return (frame) => {
|
|
41701
|
-
if (!frame || typeof frame !== "object") return;
|
|
41702
|
-
const f = frame;
|
|
41703
|
-
if (f.type !== "session:status") return;
|
|
41704
|
-
if (f.sessionId !== sessionId) return;
|
|
41705
|
-
if (f.status === "running-idle") {
|
|
41706
|
-
onEnd({ kind: "idle" });
|
|
41707
|
-
return;
|
|
41708
|
-
}
|
|
41709
|
-
if (f.status === "stopped") {
|
|
41710
|
-
onEnd({ kind: "stopped" });
|
|
41711
|
-
return;
|
|
41712
|
-
}
|
|
41713
|
-
if (f.status === "error") {
|
|
41714
|
-
onEnd({ kind: "error", message: f.message ?? "cc proc error" });
|
|
41715
|
-
return;
|
|
41716
|
-
}
|
|
41717
|
-
};
|
|
41718
|
-
}
|
|
41719
|
-
|
|
41720
|
-
// src/shift/end-dispatcher.ts
|
|
41721
|
-
function dispatchShiftEnd(info, settle, killImpl) {
|
|
41722
|
-
if (info.kind === "idle") {
|
|
41723
|
-
settle({ ok: true });
|
|
41724
|
-
killImpl();
|
|
41725
|
-
return;
|
|
41726
|
-
}
|
|
41727
|
-
if (info.kind === "stopped") {
|
|
41728
|
-
settle({ error: "cc exited before turn completed" });
|
|
41729
|
-
return;
|
|
41730
|
-
}
|
|
41731
|
-
if (info.kind === "error") {
|
|
41732
|
-
settle({ error: info.message });
|
|
41733
|
-
return;
|
|
41734
|
-
}
|
|
41735
|
-
const _exhaustive = info;
|
|
41736
|
-
throw new Error(`dispatchShiftEnd: unhandled kind ${JSON.stringify(_exhaustive)}`);
|
|
41737
|
-
}
|
|
41738
|
-
|
|
41739
41654
|
// src/session/runner.ts
|
|
41740
41655
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
41741
41656
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
@@ -41902,9 +41817,7 @@ function cloneState(s) {
|
|
|
41902
41817
|
// ReadyGate v2:readyForSend 是基础类型直接复制;pendingSend 必须浅拷贝防止
|
|
41903
41818
|
// reduce 内 push/shift 在调用方原 state 上副作用(reducer 纯函数契约)
|
|
41904
41819
|
readyForSend: s.readyForSend,
|
|
41905
|
-
pendingSend: s.pendingSend.slice()
|
|
41906
|
-
// per-turn sender (spec §4.3):SenderInfo 只在 case 'send' 覆盖,其它 kind 直接复用引用
|
|
41907
|
-
currentTurnSender: s.currentTurnSender
|
|
41820
|
+
pendingSend: s.pendingSend.slice()
|
|
41908
41821
|
};
|
|
41909
41822
|
}
|
|
41910
41823
|
var IDLE_KILL_DELAY_MS = 6e5;
|
|
@@ -41969,7 +41882,8 @@ function buildSpawnContext(state, deps) {
|
|
|
41969
41882
|
const personaId = file.ownerPersonaId;
|
|
41970
41883
|
if (personaId) env.CLAWD_PERSONA_ID = personaId;
|
|
41971
41884
|
const dispatchMcpConfigPath2 = deps.getDispatchMcpConfigPath?.() ?? null;
|
|
41972
|
-
const
|
|
41885
|
+
const ticketMcpConfigPathRaw = deps.getTicketMcpConfigPath?.() ?? null;
|
|
41886
|
+
const ticketMcpConfigPath2 = ticketMcpConfigPathRaw && file.ownerPersonaId === "persona-ticket-manager" ? ticketMcpConfigPathRaw : null;
|
|
41973
41887
|
const shiftMcpConfigPath2 = deps.getShiftMcpConfigPath?.() ?? null;
|
|
41974
41888
|
const inboxMcpConfigPath2 = deps.getInboxMcpConfigPath?.() ?? null;
|
|
41975
41889
|
const ctx = {
|
|
@@ -42243,12 +42157,10 @@ function applyCommand(state, command, deps) {
|
|
|
42243
42157
|
}
|
|
42244
42158
|
});
|
|
42245
42159
|
}
|
|
42246
|
-
next.currentTurnSender = command.senderPrincipal;
|
|
42247
42160
|
const userEvent = {
|
|
42248
42161
|
kind: "user_text",
|
|
42249
42162
|
text: command.text,
|
|
42250
|
-
uuid: deps.genUuid?.()
|
|
42251
|
-
sender: command.senderPrincipal
|
|
42163
|
+
uuid: deps.genUuid?.()
|
|
42252
42164
|
};
|
|
42253
42165
|
const pushed = pushEventToBuffer(next, userEvent, deps);
|
|
42254
42166
|
effects.push(...pushed.effects);
|
|
@@ -42796,7 +42708,7 @@ var SessionRunner = class {
|
|
|
42796
42708
|
getDispatchMcpConfigPath: this.hooks.getDispatchMcpConfigPath,
|
|
42797
42709
|
getShiftMcpConfigPath: this.hooks.getShiftMcpConfigPath,
|
|
42798
42710
|
getInboxMcpConfigPath: this.hooks.getInboxMcpConfigPath,
|
|
42799
|
-
// Ticket MCP:透传 ticket.mcp.json
|
|
42711
|
+
// Ticket MCP:透传 ticket.mcp.json 路径闭包(reducer 内做 persona-ticket-manager gating)
|
|
42800
42712
|
getTicketMcpConfigPath: this.hooks.getTicketMcpConfigPath,
|
|
42801
42713
|
lookupDispatchByBSessionId: this.hooks.lookupDispatchByBSessionId,
|
|
42802
42714
|
// ReadyGate v2:透传 mode 让 reducer send / ready-detected 分支决定走暂存队列还是直写
|
|
@@ -43315,9 +43227,7 @@ function makeInitialState(file, subSessionMeta) {
|
|
|
43315
43227
|
// ReadyGate v2:默认值兼容 SDK happy path(直写 stdin,不走队列)。
|
|
43316
43228
|
// TUI 模式由 reducer send 分支按 deps.mode='tui' 主动翻 readyForSend=false
|
|
43317
43229
|
readyForSend: true,
|
|
43318
|
-
pendingSend: []
|
|
43319
|
-
// per-turn sender 2026-07-08 spec §4.3:初始 null;case 'send' 首次覆盖
|
|
43320
|
-
currentTurnSender: null
|
|
43230
|
+
pendingSend: []
|
|
43321
43231
|
};
|
|
43322
43232
|
}
|
|
43323
43233
|
var SessionManager = class {
|
|
@@ -43990,7 +43900,7 @@ var SessionManager = class {
|
|
|
43990
43900
|
]
|
|
43991
43901
|
};
|
|
43992
43902
|
}
|
|
43993
|
-
send(args
|
|
43903
|
+
send(args) {
|
|
43994
43904
|
const existing = this.getFile(args.sessionId);
|
|
43995
43905
|
let runner = this.runners.get(args.sessionId);
|
|
43996
43906
|
if (!runner) {
|
|
@@ -43998,22 +43908,10 @@ var SessionManager = class {
|
|
|
43998
43908
|
this.runners.set(args.sessionId, runner);
|
|
43999
43909
|
}
|
|
44000
43910
|
const { broadcast } = this.withCollector(() => {
|
|
44001
|
-
runner.input({
|
|
44002
|
-
kind: "command",
|
|
44003
|
-
command: { kind: "send", text: args.text, senderPrincipal }
|
|
44004
|
-
});
|
|
43911
|
+
runner.input({ kind: "command", command: { kind: "send", text: args.text } });
|
|
44005
43912
|
});
|
|
44006
43913
|
return { response: { ok: true }, broadcast };
|
|
44007
43914
|
}
|
|
44008
|
-
/**
|
|
44009
|
-
* 只读拿 SessionState;session 不存在返 null(不 throw)。
|
|
44010
|
-
* handlers/session.ts:currentTurnSender 用(loopback HTTP RPC 绝对不能因不存在的 sid 崩)。
|
|
44011
|
-
* 2026-07-08 spec §4.6。
|
|
44012
|
-
*/
|
|
44013
|
-
tryGetState(sessionId) {
|
|
44014
|
-
const runner = this.runners.get(sessionId);
|
|
44015
|
-
return runner?.getState() ?? null;
|
|
44016
|
-
}
|
|
44017
43915
|
// 等子进程真退出再 ack。reducer 推 SIGKILL effect(见 reducer.ts),内核立即回收子进程,
|
|
44018
43916
|
// proc.on('exit') 几乎瞬时触发;waitUntilStopped 的 3s 超时只在子进程已是 zombie 或
|
|
44019
43917
|
// 极端 OS 异常时才会用上。这样修掉了"前端 sessionStop 还没等 CC 退就去删 worktree
|
|
@@ -44413,10 +44311,7 @@ var SessionManager = class {
|
|
|
44413
44311
|
}
|
|
44414
44312
|
const runner = this.ensureRunnerForScope(file, args.scope);
|
|
44415
44313
|
const { broadcast } = this.withCollector(() => {
|
|
44416
|
-
runner.input({
|
|
44417
|
-
kind: "command",
|
|
44418
|
-
command: { kind: "send", text: args.text, senderPrincipal: args.senderPrincipal }
|
|
44419
|
-
});
|
|
44314
|
+
runner.input({ kind: "command", command: { kind: "send", text: args.text } });
|
|
44420
44315
|
});
|
|
44421
44316
|
return { response: { ok: true }, broadcast };
|
|
44422
44317
|
}
|
|
@@ -44560,27 +44455,7 @@ var SessionManager = class {
|
|
|
44560
44455
|
sourceJsonlPath: args.sourceJsonlPath,
|
|
44561
44456
|
dispatchId: args.dispatchId
|
|
44562
44457
|
});
|
|
44563
|
-
|
|
44564
|
-
if (args.guestPrincipalId) {
|
|
44565
|
-
dispatchSender = makeGuestSender(args.guestPrincipalId, args.guestDisplayName ?? args.guestPrincipalId);
|
|
44566
|
-
} else {
|
|
44567
|
-
if (!this.deps.ownerPrincipalId) {
|
|
44568
|
-
throw new Error(
|
|
44569
|
-
"createDispatchedSession requires ManagerDeps.ownerPrincipalId to build owner sender"
|
|
44570
|
-
);
|
|
44571
|
-
}
|
|
44572
|
-
dispatchSender = principalToSender(
|
|
44573
|
-
makeOwnerPrincipal(
|
|
44574
|
-
this.deps.ownerPrincipalId,
|
|
44575
|
-
this.deps.ownerDisplayName ?? "Owner",
|
|
44576
|
-
this.deps.ownerFeishuUnionId
|
|
44577
|
-
)
|
|
44578
|
-
);
|
|
44579
|
-
}
|
|
44580
|
-
runner.input({
|
|
44581
|
-
kind: "command",
|
|
44582
|
-
command: { kind: "send", text: taskPack, senderPrincipal: dispatchSender }
|
|
44583
|
-
});
|
|
44458
|
+
runner.input({ kind: "command", command: { kind: "send", text: taskPack } });
|
|
44584
44459
|
this.deps.logger?.info("dispatch.createDispatchedSession.task-pack-sent", {
|
|
44585
44460
|
dispatchId: args.dispatchId,
|
|
44586
44461
|
bSessionId: sessionId
|
|
@@ -44595,9 +44470,8 @@ var SessionManager = class {
|
|
|
44595
44470
|
* 跟 createDispatchedSession 的差异:
|
|
44596
44471
|
* - 不带 dispatchId / source / task pack;prompt 直接当第一条 user message
|
|
44597
44472
|
* - 不调 personaDispatchManager.registerBSession
|
|
44598
|
-
* - 多返一个 ended Promise,监听 session:status
|
|
44599
|
-
*
|
|
44600
|
-
* - turn-idle 到达即视为业务完成 → settle {ok:true} + fire-and-forget kill cc
|
|
44473
|
+
* - 多返一个 ended Promise,监听 session:status (stopped/error) 帧通过现有
|
|
44474
|
+
* subscribe() 入口(白名单已含 session:status)
|
|
44601
44475
|
* - kill 通过 runner.input({command:{kind:'stop'}}) 触发 SIGKILL → proc-exit
|
|
44602
44476
|
*/
|
|
44603
44477
|
createShiftSession(args) {
|
|
@@ -44641,32 +44515,18 @@ var SessionManager = class {
|
|
|
44641
44515
|
unsubscribe();
|
|
44642
44516
|
resolveEnded(info);
|
|
44643
44517
|
};
|
|
44644
|
-
|
|
44645
|
-
|
|
44646
|
-
|
|
44647
|
-
|
|
44648
|
-
|
|
44649
|
-
|
|
44650
|
-
|
|
44651
|
-
|
|
44652
|
-
|
|
44653
|
-
|
|
44654
|
-
})
|
|
44655
|
-
);
|
|
44518
|
+
unsubscribe = this.subscribe(sessionId, scope, (frame) => {
|
|
44519
|
+
if (frame.type !== "session:status") return;
|
|
44520
|
+
const f = frame;
|
|
44521
|
+
if (f.sessionId !== sessionId) return;
|
|
44522
|
+
if (f.status === "stopped") {
|
|
44523
|
+
settle({ exitCode: f.exitCode ?? null });
|
|
44524
|
+
} else if (f.status === "error") {
|
|
44525
|
+
settle({ exitCode: null, error: f.message ?? "cc proc error" });
|
|
44526
|
+
}
|
|
44527
|
+
});
|
|
44656
44528
|
const runner = this.ensureRunnerForScope(file, scope);
|
|
44657
44529
|
this.deps.logger?.info("shift.createShiftSession.runner-ready", { sessionId });
|
|
44658
|
-
if (!this.deps.ownerPrincipalId) {
|
|
44659
|
-
throw new Error(
|
|
44660
|
-
"createShiftSession requires ManagerDeps.ownerPrincipalId to build owner sender"
|
|
44661
|
-
);
|
|
44662
|
-
}
|
|
44663
|
-
const shiftSender = principalToSender(
|
|
44664
|
-
makeOwnerPrincipal(
|
|
44665
|
-
this.deps.ownerPrincipalId,
|
|
44666
|
-
this.deps.ownerDisplayName ?? "Owner",
|
|
44667
|
-
this.deps.ownerFeishuUnionId
|
|
44668
|
-
)
|
|
44669
|
-
);
|
|
44670
44530
|
runner.input({
|
|
44671
44531
|
kind: "command",
|
|
44672
44532
|
command: {
|
|
@@ -44674,11 +44534,15 @@ var SessionManager = class {
|
|
|
44674
44534
|
text: wrapShiftFirePrompt({
|
|
44675
44535
|
prompt: args.prompt,
|
|
44676
44536
|
targetPersona: args.targetPersona
|
|
44677
|
-
})
|
|
44678
|
-
senderPrincipal: shiftSender
|
|
44537
|
+
})
|
|
44679
44538
|
}
|
|
44680
44539
|
});
|
|
44681
|
-
|
|
44540
|
+
const kill = () => {
|
|
44541
|
+
const r = this.runners.get(sessionId);
|
|
44542
|
+
if (!r) return;
|
|
44543
|
+
r.input({ kind: "command", command: { kind: "stop" } });
|
|
44544
|
+
};
|
|
44545
|
+
return { sessionId, ended, kill };
|
|
44682
44546
|
}
|
|
44683
44547
|
/**
|
|
44684
44548
|
* 老板插话:把 'inject-owner-text' input 喂给对应 runner,
|
|
@@ -48188,7 +48052,7 @@ function ticketMcpConfigPath(dataDir) {
|
|
|
48188
48052
|
function writeTicketMcpConfig(args) {
|
|
48189
48053
|
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
48190
48054
|
const content = {
|
|
48191
|
-
_comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002ticket-mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\uFF0CHTTP client \u8C03 clawos api /api/tickets/*\u3002env \u542B api url\u3001\u5199\u6B7B API key\
|
|
48055
|
+
_comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002ticket-mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\uFF0CHTTP client \u8C03 clawos api /api/tickets/*\u3002env \u542B api url\u3001\u5199\u6B7B API key\u3001caller did/name/scene\uFF1BCLAWD_TICKET_LOG \u6307 server \u5199\u65E5\u5FD7\u7684 append \u6587\u4EF6\u8DEF\u5F84\u3002cc \u573A\u666F scene \u56FA\u5B9A persona\u3002",
|
|
48192
48056
|
mcpServers: {
|
|
48193
48057
|
"clawd-ticket": {
|
|
48194
48058
|
type: "stdio",
|
|
@@ -48197,6 +48061,8 @@ function writeTicketMcpConfig(args) {
|
|
|
48197
48061
|
env: {
|
|
48198
48062
|
CLAWD_TICKET_API_URL: args.apiBaseUrl,
|
|
48199
48063
|
CLAWD_TICKET_API_KEY: args.apiKey,
|
|
48064
|
+
CLAWD_TICKET_DID: args.did,
|
|
48065
|
+
CLAWD_TICKET_NAME: args.name,
|
|
48200
48066
|
CLAWD_TICKET_SCENE: "persona",
|
|
48201
48067
|
...args.logPath ? { CLAWD_TICKET_LOG: args.logPath } : {}
|
|
48202
48068
|
}
|
|
@@ -48581,11 +48447,15 @@ function createShiftSpawnFn(deps) {
|
|
|
48581
48447
|
void created.ended.then((info) => {
|
|
48582
48448
|
clearTimeout(timer);
|
|
48583
48449
|
if (settled) return;
|
|
48584
|
-
if (
|
|
48450
|
+
if (info.error) {
|
|
48451
|
+
settle({ kind: "error", error: info.error });
|
|
48452
|
+
return;
|
|
48453
|
+
}
|
|
48454
|
+
if (info.exitCode === 0) {
|
|
48585
48455
|
settle({ kind: "ok" });
|
|
48586
48456
|
return;
|
|
48587
48457
|
}
|
|
48588
|
-
settle({ kind: "error", error: info.
|
|
48458
|
+
settle({ kind: "error", error: `cc exited with code ${info.exitCode}` });
|
|
48589
48459
|
});
|
|
48590
48460
|
return { sessionId: created.sessionId, ended };
|
|
48591
48461
|
};
|
|
@@ -50307,12 +50177,7 @@ var EXPOSED_RPC_METHODS = [
|
|
|
50307
50177
|
"attachment.groupAdd",
|
|
50308
50178
|
"attachment.signUrl",
|
|
50309
50179
|
// persona 受控发 P2P IM DM(sender 由 session scope 推,driver 分级授权见 handlers/inbox.ts)
|
|
50310
|
-
"inbox.sendDm"
|
|
50311
|
-
// per-turn sender 2026-07-08 spec §4.1:MCP servers (ticket / inbox / ...) 每 tool call
|
|
50312
|
-
// 查当前 turn caller —— cc 长驻 + owner/guest 交替驱动同一 session 时不能靠启动时 env
|
|
50313
|
-
// 写死身份,必须运行时 fetch。header X-Clawd-Session-Id 作 session 定位,handler 内查
|
|
50314
|
-
// manager.tryGetState(sid).currentTurnSender 返 SenderInfo | null。
|
|
50315
|
-
"session.currentTurnSender"
|
|
50180
|
+
"inbox.sendDm"
|
|
50316
50181
|
];
|
|
50317
50182
|
async function handleRpcRequest(input) {
|
|
50318
50183
|
const { method, body, sessionId, dispatcher } = input;
|
|
@@ -50497,9 +50362,9 @@ function constantTimeEqual2(a, b2) {
|
|
|
50497
50362
|
}
|
|
50498
50363
|
|
|
50499
50364
|
// src/transport/connection-context.ts
|
|
50500
|
-
function ownerContext(ownerPrincipalId, displayName
|
|
50365
|
+
function ownerContext(ownerPrincipalId, displayName) {
|
|
50501
50366
|
return {
|
|
50502
|
-
principal: makeOwnerPrincipal(ownerPrincipalId, displayName
|
|
50367
|
+
principal: makeOwnerPrincipal(ownerPrincipalId, displayName),
|
|
50503
50368
|
grants: [{ resource: { type: "*" }, actions: ["admin"] }]
|
|
50504
50369
|
};
|
|
50505
50370
|
}
|
|
@@ -50528,10 +50393,7 @@ function visitorGuestContext(p2) {
|
|
|
50528
50393
|
async function authenticate(token, deps) {
|
|
50529
50394
|
if (!token) return { ok: false, code: "NO_TOKEN" };
|
|
50530
50395
|
if (deps.isOwnerToken(token)) {
|
|
50531
|
-
return {
|
|
50532
|
-
ok: true,
|
|
50533
|
-
context: ownerContext(deps.ownerPrincipalId, deps.ownerDisplayName, deps.ownerFeishuUnionId)
|
|
50534
|
-
};
|
|
50396
|
+
return { ok: true, context: ownerContext(deps.ownerPrincipalId, deps.ownerDisplayName) };
|
|
50535
50397
|
}
|
|
50536
50398
|
if (deps.verifyVisitorToken) {
|
|
50537
50399
|
const vr = deps.verifyVisitorToken(token);
|
|
@@ -54330,22 +54192,6 @@ var LoginFlow = class {
|
|
|
54330
54192
|
} catch (err) {
|
|
54331
54193
|
return { ok: false, reason: `user_info failed: ${err.message}` };
|
|
54332
54194
|
}
|
|
54333
|
-
if (!identity.unionId) {
|
|
54334
|
-
return { ok: false, reason: "union_id missing from TTC user_info" };
|
|
54335
|
-
}
|
|
54336
|
-
try {
|
|
54337
|
-
await this.deps.upsertBinding({
|
|
54338
|
-
deviceId: this.deps.getDeviceId(),
|
|
54339
|
-
unionId: identity.unionId,
|
|
54340
|
-
displayName: identity.displayName,
|
|
54341
|
-
avatarUrl: identity.avatarUrl ?? null
|
|
54342
|
-
});
|
|
54343
|
-
} catch (err) {
|
|
54344
|
-
return {
|
|
54345
|
-
ok: false,
|
|
54346
|
-
reason: `device_binding upsert failed: ${err.message}`
|
|
54347
|
-
};
|
|
54348
|
-
}
|
|
54349
54195
|
const expiresAtNum = params.expiresAt ? Number.parseInt(params.expiresAt, 10) : NaN;
|
|
54350
54196
|
this.deps.store.write({
|
|
54351
54197
|
identity,
|
|
@@ -54514,58 +54360,6 @@ async function centralListDevices(opts) {
|
|
|
54514
54360
|
return out;
|
|
54515
54361
|
}
|
|
54516
54362
|
|
|
54517
|
-
// src/feishu-auth/device-binding-client.ts
|
|
54518
|
-
var DeviceBindingClientError = class extends Error {
|
|
54519
|
-
constructor(code, message, cause) {
|
|
54520
|
-
super(message);
|
|
54521
|
-
this.code = code;
|
|
54522
|
-
this.cause = cause;
|
|
54523
|
-
this.name = "DeviceBindingClientError";
|
|
54524
|
-
}
|
|
54525
|
-
code;
|
|
54526
|
-
cause;
|
|
54527
|
-
};
|
|
54528
|
-
var DEFAULT_TIMEOUT_MS4 = 8e3;
|
|
54529
|
-
async function upsertDeviceBinding(opts) {
|
|
54530
|
-
const doFetch = opts.fetchImpl ?? fetch;
|
|
54531
|
-
const ac = new AbortController();
|
|
54532
|
-
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4);
|
|
54533
|
-
const body = { unionId: opts.unionId };
|
|
54534
|
-
if (opts.avatarUrl != null) body.avatarUrl = opts.avatarUrl;
|
|
54535
|
-
let res;
|
|
54536
|
-
try {
|
|
54537
|
-
res = await doFetch(`${opts.apiUrl}/api/device-bindings/self`, {
|
|
54538
|
-
method: "PUT",
|
|
54539
|
-
signal: ac.signal,
|
|
54540
|
-
headers: {
|
|
54541
|
-
authorization: `Bearer ${opts.apiKey}`,
|
|
54542
|
-
"x-did": encodeURIComponent(opts.deviceId),
|
|
54543
|
-
"x-name": encodeURIComponent(opts.displayName),
|
|
54544
|
-
"x-scene": "daemon",
|
|
54545
|
-
"content-type": "application/json"
|
|
54546
|
-
},
|
|
54547
|
-
body: JSON.stringify(body)
|
|
54548
|
-
});
|
|
54549
|
-
} catch (err) {
|
|
54550
|
-
clearTimeout(timer);
|
|
54551
|
-
throw new DeviceBindingClientError(
|
|
54552
|
-
"NETWORK",
|
|
54553
|
-
`network error: ${err.message}`,
|
|
54554
|
-
err
|
|
54555
|
-
);
|
|
54556
|
-
} finally {
|
|
54557
|
-
clearTimeout(timer);
|
|
54558
|
-
}
|
|
54559
|
-
if (!res.ok) {
|
|
54560
|
-
let detail = "";
|
|
54561
|
-
try {
|
|
54562
|
-
detail = JSON.stringify(await res.json());
|
|
54563
|
-
} catch {
|
|
54564
|
-
}
|
|
54565
|
-
throw new DeviceBindingClientError("API_ERROR", `HTTP ${res.status}: ${detail}`);
|
|
54566
|
-
}
|
|
54567
|
-
}
|
|
54568
|
-
|
|
54569
54363
|
// src/feishu-auth/verify-token.ts
|
|
54570
54364
|
var crypto14 = __toESM(require("crypto"), 1);
|
|
54571
54365
|
var CONNECT_TOKEN_PREFIX = "clawdtk1";
|
|
@@ -54824,25 +54618,9 @@ function buildSessionHandlers(deps) {
|
|
|
54824
54618
|
const send = async (frame, _client, ctx) => {
|
|
54825
54619
|
const args = SessionSendArgs.parse(frame);
|
|
54826
54620
|
ensureSessionAccess(ctx, args.sessionId, "send");
|
|
54827
|
-
const
|
|
54828
|
-
makeOwnerPrincipal(ownerPrincipalId, deps.ownerDisplayName, deps.ownerFeishuUnionId)
|
|
54829
|
-
);
|
|
54830
|
-
const { broadcast } = manager.send(args, sender);
|
|
54621
|
+
const { broadcast } = manager.send(args);
|
|
54831
54622
|
return { response: { type: "session:send", ok: true }, broadcast };
|
|
54832
54623
|
};
|
|
54833
|
-
const currentTurnSender = async (frame, _client, ctx) => {
|
|
54834
|
-
const sid = typeof frame === "object" && frame != null && "sessionId" in frame ? String(frame.sessionId) : "";
|
|
54835
|
-
if (!sid) {
|
|
54836
|
-
return { response: { type: "session:currentTurnSender", sender: null } };
|
|
54837
|
-
}
|
|
54838
|
-
if (ctx && "principal" in ctx) {
|
|
54839
|
-
ensureSessionAccess(ctx, sid, "read");
|
|
54840
|
-
}
|
|
54841
|
-
const state = manager.tryGetState(sid);
|
|
54842
|
-
return {
|
|
54843
|
-
response: { type: "session:currentTurnSender", sender: state?.currentTurnSender ?? null }
|
|
54844
|
-
};
|
|
54845
|
-
};
|
|
54846
54624
|
const stop = async (frame, _client, ctx) => {
|
|
54847
54625
|
const args = SessionIdArgs.parse(frame);
|
|
54848
54626
|
ensureSessionAccess(ctx, args.sessionId, "send");
|
|
@@ -55045,7 +54823,6 @@ function buildSessionHandlers(deps) {
|
|
|
55045
54823
|
"session:update": update,
|
|
55046
54824
|
"session:delete": del,
|
|
55047
54825
|
"session:send": send,
|
|
55048
|
-
"session:currentTurnSender": currentTurnSender,
|
|
55049
54826
|
"session:stop": stop,
|
|
55050
54827
|
"session:interrupt": interrupt,
|
|
55051
54828
|
"session:rewind": rewind,
|
|
@@ -58114,14 +57891,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
58114
57891
|
broadcastProjectUpdated(f);
|
|
58115
57892
|
},
|
|
58116
57893
|
injectUserText: async (sessionId, text) => {
|
|
58117
|
-
const
|
|
58118
|
-
makeOwnerPrincipal(
|
|
58119
|
-
deps.ownerPrincipalId,
|
|
58120
|
-
deps.ownerDisplayName ?? "Owner",
|
|
58121
|
-
deps.ownerFeishuUnionId
|
|
58122
|
-
)
|
|
58123
|
-
);
|
|
58124
|
-
const { broadcast } = sessionManager.send({ sessionId, text }, ownerSender);
|
|
57894
|
+
const { broadcast } = sessionManager.send({ sessionId, text });
|
|
58125
57895
|
for (const entry of broadcast) {
|
|
58126
57896
|
deps.broadcastSessionFrame(entry.frame, entry.target);
|
|
58127
57897
|
}
|
|
@@ -58420,9 +58190,6 @@ function buildMethodHandlers(deps) {
|
|
|
58420
58190
|
usersRoot: deps.usersRoot,
|
|
58421
58191
|
devServerLifecycle: deps.devServerLifecycle,
|
|
58422
58192
|
sessionManager: deps.manager,
|
|
58423
|
-
ownerPrincipalId: deps.ownerPrincipalId,
|
|
58424
|
-
ownerDisplayName: deps.ownerDisplayName,
|
|
58425
|
-
ownerFeishuUnionId: deps.ownerFeishuUnionId,
|
|
58426
58193
|
getTunnelUrl: deps.getTunnelUrl,
|
|
58427
58194
|
broadcastProjectUpdated: deps.broadcastProjectUpdated,
|
|
58428
58195
|
logger: deps.logger,
|
|
@@ -58751,10 +58518,6 @@ var METHOD_GRANT_MAP = {
|
|
|
58751
58518
|
"session:update": CAPABILITY_SCOPED,
|
|
58752
58519
|
"session:delete": CAPABILITY_SCOPED,
|
|
58753
58520
|
"session:send": CAPABILITY_SCOPED,
|
|
58754
|
-
// per-turn sender 2026-07-08 spec §4.6:dispatcher 层走 'public'(HTTP RPC path 需 dispatcher 放行);
|
|
58755
|
-
// WS path 的隐私边界(防 guest 猜 sid 枚举 owner feishuUnionId)由 handler 内 ensureSessionAccess
|
|
58756
|
-
// 显式兜底——见 handlers/session.ts:currentTurnSender。dispatcher 'public' ≠ handler 免检。
|
|
58757
|
-
"session:currentTurnSender": { kind: "public" },
|
|
58758
58521
|
"session:stop": CAPABILITY_SCOPED,
|
|
58759
58522
|
"session:interrupt": CAPABILITY_SCOPED,
|
|
58760
58523
|
"session:rewind": CAPABILITY_SCOPED,
|
|
@@ -59327,7 +59090,6 @@ async function startDaemon(config) {
|
|
|
59327
59090
|
let ownerId = feishuIdentity?.identity.ownerId ?? "";
|
|
59328
59091
|
let ownerProvider = feishuIdentity?.identity.provider ?? "";
|
|
59329
59092
|
let ownerDisplayName = feishuIdentity?.identity.displayName ?? loadOwnerDisplayName(config.dataDir);
|
|
59330
|
-
let ownerFeishuUnionId = feishuIdentity?.identity.unionId;
|
|
59331
59093
|
const authMode = resolvedAuthToken == null ? "none" : "first-message";
|
|
59332
59094
|
const inboxStore = new InboxStore(config.dataDir);
|
|
59333
59095
|
const inboxManager = new InboxManager(inboxStore, (_peerDeviceId, frame) => {
|
|
@@ -59340,7 +59102,6 @@ async function startDaemon(config) {
|
|
|
59340
59102
|
isOwnerToken: (x) => resolvedAuthToken != null && constantTimeEqual(x, resolvedAuthToken),
|
|
59341
59103
|
ownerPrincipalId,
|
|
59342
59104
|
ownerDisplayName,
|
|
59343
|
-
ownerFeishuUnionId,
|
|
59344
59105
|
// persona web 分享:访客 visitor token = daemon 自签 HMAC(无 aud),独立于飞书 connect token
|
|
59345
59106
|
// 基建——secret 恒存在(auth-store backfill),故无条件注入。验签 ok → guest ctx(persona wildcard)。
|
|
59346
59107
|
verifyVisitorToken: (t) => {
|
|
@@ -59424,7 +59185,7 @@ async function startDaemon(config) {
|
|
|
59424
59185
|
return result;
|
|
59425
59186
|
},
|
|
59426
59187
|
onAuthed: (h, ctx) => wsServer?.attachClientContext(h.id, ctx),
|
|
59427
|
-
buildOwnerContext: () => ownerContext(ownerPrincipalId, ownerDisplayName
|
|
59188
|
+
buildOwnerContext: () => ownerContext(ownerPrincipalId, ownerDisplayName),
|
|
59428
59189
|
closeConnection: (h, code, reason) => wsServer?.closeClient(h.id, code, reason),
|
|
59429
59190
|
sendOk: (h, payload) => wsServer?.sendToClient(h.id, payload)
|
|
59430
59191
|
}) : null;
|
|
@@ -59496,14 +59257,18 @@ async function startDaemon(config) {
|
|
|
59496
59257
|
import_node_path64.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
59497
59258
|
];
|
|
59498
59259
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
59260
|
+
const ticketCallerDid = feishuIdentity?.identity.unionId ?? "";
|
|
59261
|
+
const ticketCallerName = feishuIdentity?.identity.displayName ?? "";
|
|
59499
59262
|
let ticketMcpConfigPath2;
|
|
59500
|
-
if (ticketServerScriptPath) {
|
|
59263
|
+
if (ticketServerScriptPath && ticketCallerDid) {
|
|
59501
59264
|
const ticketLogPath = import_node_path64.default.join(config.dataDir, "ticket-mcp-server.log");
|
|
59502
59265
|
ticketMcpConfigPath2 = writeTicketMcpConfig({
|
|
59503
59266
|
dataDir: config.dataDir,
|
|
59504
59267
|
serverScriptPath: ticketServerScriptPath,
|
|
59505
59268
|
apiBaseUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
59506
59269
|
apiKey: resolveClawdTicketsApiKey(),
|
|
59270
|
+
did: ticketCallerDid,
|
|
59271
|
+
name: ticketCallerName,
|
|
59507
59272
|
logPath: ticketLogPath
|
|
59508
59273
|
});
|
|
59509
59274
|
logger.info("ticket.mcp.json written", {
|
|
@@ -59513,7 +59278,7 @@ async function startDaemon(config) {
|
|
|
59513
59278
|
});
|
|
59514
59279
|
} else {
|
|
59515
59280
|
logger.warn("ticket-mcp skipped", {
|
|
59516
|
-
reason: "ticket-mcp-server.cjs not found (need build)"
|
|
59281
|
+
reason: !ticketCallerDid ? "caller did missing (login required)" : "ticket-mcp-server.cjs not found (need build)"
|
|
59517
59282
|
});
|
|
59518
59283
|
}
|
|
59519
59284
|
const shiftServerCandidates = [
|
|
@@ -59592,7 +59357,6 @@ async function startDaemon(config) {
|
|
|
59592
59357
|
personaStore,
|
|
59593
59358
|
ownerDisplayName,
|
|
59594
59359
|
ownerPrincipalId,
|
|
59595
|
-
ownerFeishuUnionId,
|
|
59596
59360
|
contactStore,
|
|
59597
59361
|
mode: config.mode,
|
|
59598
59362
|
// 单栏 refactor (spec 2026-06-02 §5.1):cc 子进程 env CLAWD_DAEMON_URL 闭包来源。
|
|
@@ -59765,16 +59529,7 @@ async function startDaemon(config) {
|
|
|
59765
59529
|
store: ownerIdentityStore,
|
|
59766
59530
|
fetchUserInfo: (ttcToken) => fetchTtcUserInfo({ apiBase: TTC_HOSTS.api, token: ttcToken }),
|
|
59767
59531
|
ttcAuthBase: TTC_HOSTS.auth,
|
|
59768
|
-
getCallbackUrl: () => `http://127.0.0.1:${config.port}/auth/callback
|
|
59769
|
-
// device_bindings upsert(did ↔ 飞书 unionId 映射):
|
|
59770
|
-
// deviceId 从 auth.json 稳定读;apiUrl 走同一份 clawosApi;apiKey 复用 CLAWD_TICKETS_API_KEY。
|
|
59771
|
-
// 失败即登录失败(fail-hard,login-flow.spec §upsert 失败)。
|
|
59772
|
-
getDeviceId: () => authFile.deviceId,
|
|
59773
|
-
upsertBinding: (opts) => upsertDeviceBinding({
|
|
59774
|
-
apiUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
59775
|
-
apiKey: resolveClawdTicketsApiKey(),
|
|
59776
|
-
...opts
|
|
59777
|
-
})
|
|
59532
|
+
getCallbackUrl: () => `http://127.0.0.1:${config.port}/auth/callback`
|
|
59778
59533
|
});
|
|
59779
59534
|
const visitorStore = createVisitorStore({ dir: config.dataDir });
|
|
59780
59535
|
const exchangeVisitorToken = buildVisitorLogin({
|
|
@@ -59855,8 +59610,6 @@ async function startDaemon(config) {
|
|
|
59855
59610
|
ownerDisplayName,
|
|
59856
59611
|
// 决策 #16: whoami owner.id = 本机 deviceId(路由主键)+ ownerId/provider 归属人
|
|
59857
59612
|
ownerPrincipalId,
|
|
59858
|
-
// per-turn sender §4.6:send handler 无 ctx 兜底 + AppBuilder publish injectUserText 需要
|
|
59859
|
-
ownerFeishuUnionId,
|
|
59860
59613
|
ownerId,
|
|
59861
59614
|
ownerProvider,
|
|
59862
59615
|
personaStore,
|
|
@@ -60140,7 +59893,6 @@ async function startDaemon(config) {
|
|
|
60140
59893
|
ownerId = result.identity.ownerId;
|
|
60141
59894
|
ownerProvider = result.identity.provider;
|
|
60142
59895
|
ownerDisplayName = result.identity.displayName;
|
|
60143
|
-
ownerFeishuUnionId = result.identity.unionId;
|
|
60144
59896
|
handlers = makeHandlers();
|
|
60145
59897
|
wsServer?.broadcastToOwners({ type: "auth:login:done", identity: result.identity });
|
|
60146
59898
|
setImmediate(() => wsServer?.closeAllClients());
|
|
@@ -60279,7 +60031,7 @@ async function startDaemon(config) {
|
|
|
60279
60031
|
wss.onFrame(async (client, frame) => {
|
|
60280
60032
|
const type = frame.type;
|
|
60281
60033
|
const requestId = typeof frame.requestId === "string" ? frame.requestId : void 0;
|
|
60282
|
-
const ctx = wsServer.getClientContext(client.id) ?? ownerContext(ownerPrincipalId, ownerDisplayName
|
|
60034
|
+
const ctx = wsServer.getClientContext(client.id) ?? ownerContext(ownerPrincipalId, ownerDisplayName);
|
|
60283
60035
|
const result = await dispatchRpc(type, frame, client, ctx, {
|
|
60284
60036
|
handlers,
|
|
60285
60037
|
feishuActive: () => feishuActive
|