@clawos-dev/clawd 0.2.411 → 0.2.413
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 -24
- package/dist/dispatch/mcp-server.cjs +10 -6
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-orchestration/SKILL.md +1 -1
- package/dist/persona-defaults/persona-clawd-butler/CLAUDE.md +3 -1
- package/dist/persona-defaults/persona-master/CLAUDE.md +12 -4
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-DcTI4F8B.js → guest-BvnTjYPr.js} +130 -130
- package/dist/share-ui/assets/guest-mbQfNssK.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-DdIGJUIu.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -6630,19 +6630,23 @@ var init_shift_internal = __esm({
|
|
|
6630
6630
|
});
|
|
6631
6631
|
|
|
6632
6632
|
// ../protocol/src/channel.ts
|
|
6633
|
-
var MASTER_PERSONA_ID, ChannelSchema, nonBlank, ChannelCreateArgsSchema, ChannelUpdateArgsSchema, ChannelDeleteArgsSchema, ChannelListResultSchema, ChannelResultSchema, ChannelDeleteResultSchema;
|
|
6633
|
+
var MASTER_PERSONA_ID, ChannelMemberPersonaSchema, ChannelSchema, nonBlank, ChannelCreateArgsSchema, ChannelUpdateArgsSchema, ChannelDeleteArgsSchema, ChannelListResultSchema, ChannelResultSchema, ChannelDeleteResultSchema;
|
|
6634
6634
|
var init_channel = __esm({
|
|
6635
6635
|
"../protocol/src/channel.ts"() {
|
|
6636
6636
|
"use strict";
|
|
6637
6637
|
init_zod();
|
|
6638
6638
|
MASTER_PERSONA_ID = "persona-master";
|
|
6639
|
+
ChannelMemberPersonaSchema = external_exports.object({
|
|
6640
|
+
personaId: external_exports.string().min(1),
|
|
6641
|
+
deviceId: external_exports.string().min(1).optional()
|
|
6642
|
+
});
|
|
6639
6643
|
ChannelSchema = external_exports.object({
|
|
6640
6644
|
id: external_exports.string().min(1),
|
|
6641
6645
|
name: external_exports.string().min(1),
|
|
6642
|
-
/** 该频道里可被派活的 persona */
|
|
6643
|
-
|
|
6644
|
-
/** 人类成员(contact deviceId
|
|
6645
|
-
* P1 人类异步询问也用它 */
|
|
6646
|
+
/** 该频道里可被派活的 persona 全集(本机 + 远程) */
|
|
6647
|
+
memberPersonas: external_exports.array(ChannelMemberPersonaSchema),
|
|
6648
|
+
/** 人类成员(contact deviceId):可发 DM。**不隐含任何派活权限** —— 跨设备派活认的是
|
|
6649
|
+
* 上面那张 memberPersonas。P1 人类异步询问也用它 */
|
|
6646
6650
|
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)),
|
|
6647
6651
|
createdAt: external_exports.string().min(1),
|
|
6648
6652
|
updatedAt: external_exports.string().min(1)
|
|
@@ -6650,13 +6654,13 @@ var init_channel = __esm({
|
|
|
6650
6654
|
nonBlank = external_exports.string().trim().min(1);
|
|
6651
6655
|
ChannelCreateArgsSchema = external_exports.object({
|
|
6652
6656
|
name: nonBlank,
|
|
6653
|
-
|
|
6657
|
+
memberPersonas: external_exports.array(ChannelMemberPersonaSchema).default([]),
|
|
6654
6658
|
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)).default([])
|
|
6655
6659
|
});
|
|
6656
6660
|
ChannelUpdateArgsSchema = external_exports.object({
|
|
6657
6661
|
channelId: external_exports.string().min(1),
|
|
6658
6662
|
name: nonBlank.optional(),
|
|
6659
|
-
|
|
6663
|
+
memberPersonas: external_exports.array(ChannelMemberPersonaSchema).optional(),
|
|
6660
6664
|
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)).optional()
|
|
6661
6665
|
});
|
|
6662
6666
|
ChannelDeleteArgsSchema = external_exports.object({ channelId: external_exports.string().min(1) });
|
|
@@ -52997,12 +53001,13 @@ var import_node_path20 = __toESM(require("path"), 1);
|
|
|
52997
53001
|
function createJsonStore(deps) {
|
|
52998
53002
|
let items = [];
|
|
52999
53003
|
let flushTimer = null;
|
|
53004
|
+
const version2 = deps.version ?? 1;
|
|
53000
53005
|
async function flushNow() {
|
|
53001
53006
|
if (flushTimer) {
|
|
53002
53007
|
clearTimeout(flushTimer);
|
|
53003
53008
|
flushTimer = null;
|
|
53004
53009
|
}
|
|
53005
|
-
const content = { version:
|
|
53010
|
+
const content = { version: version2, [deps.key]: items };
|
|
53006
53011
|
await import_promises2.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
|
|
53007
53012
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
53008
53013
|
await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
@@ -53023,10 +53028,24 @@ function createJsonStore(deps) {
|
|
|
53023
53028
|
throw e;
|
|
53024
53029
|
}
|
|
53025
53030
|
const parsed = JSON.parse(raw);
|
|
53026
|
-
|
|
53027
|
-
|
|
53031
|
+
const found = parsed.version;
|
|
53032
|
+
if (found === version2) {
|
|
53033
|
+
items = parsed[deps.key] ?? [];
|
|
53034
|
+
return;
|
|
53035
|
+
}
|
|
53036
|
+
if (typeof found === "number" && found < version2 && deps.migrate) {
|
|
53037
|
+
items = deps.migrate(parsed[deps.key] ?? [], found);
|
|
53038
|
+
await flushNow().catch((err) => deps.onFlushError?.(err));
|
|
53039
|
+
return;
|
|
53040
|
+
}
|
|
53041
|
+
if (typeof found === "number" && found > version2) {
|
|
53042
|
+
throw new Error(
|
|
53043
|
+
`${deps.key}.json \u7531\u66F4\u65B0\u7248\u672C\u7684 clawd \u5199\u5165\uFF08\u6587\u4EF6 version=${found}\uFF0C\u672C\u673A\u53EA\u8BA4\u5230 ${version2}\uFF09\uFF0C\u8BF7\u5347\u7EA7 clawd`
|
|
53044
|
+
);
|
|
53028
53045
|
}
|
|
53029
|
-
|
|
53046
|
+
throw new Error(
|
|
53047
|
+
`${deps.key}.json: unsupported version ${String(found)}\uFF08\u672C\u673A version=${version2}\uFF09`
|
|
53048
|
+
);
|
|
53030
53049
|
},
|
|
53031
53050
|
scheduleFlush() {
|
|
53032
53051
|
if (flushTimer) return;
|
|
@@ -53040,7 +53059,31 @@ function createJsonStore(deps) {
|
|
|
53040
53059
|
|
|
53041
53060
|
// src/channel/store.ts
|
|
53042
53061
|
function createChannelStore(deps) {
|
|
53043
|
-
const file = createJsonStore({
|
|
53062
|
+
const file = createJsonStore({
|
|
53063
|
+
...deps,
|
|
53064
|
+
key: "channels",
|
|
53065
|
+
version: 2,
|
|
53066
|
+
// v1 → v2(2026-08-26):成员表换形,本机与远程 persona 并进一张 memberPersonas。
|
|
53067
|
+
// memberContactDeviceIds 原样留着 —— 它的语义从「可派活给这台设备上的任意 persona」
|
|
53068
|
+
// 收窄成「可发 DM」,收窄不需要动数据。
|
|
53069
|
+
//
|
|
53070
|
+
// 存量频道因此失去跨设备派活能力,这是有意的:要补偿就得在这里去拉对方 daemon 的
|
|
53071
|
+
// persona 列表(对方不一定在线),而「他家所有 persona 自动进名单」正是要废掉的
|
|
53072
|
+
// 那个隐含推导。老板重新勾一次即可。
|
|
53073
|
+
//
|
|
53074
|
+
// ⚠️ 写法注意(给下一次 v2→v3 的人):这里是**先解构后覆盖** —— `...rest` 会把
|
|
53075
|
+
// 旧行里的同名字段一起带进来,紧跟着的赋值再盖掉它。加新字段时确认清楚是想覆盖
|
|
53076
|
+
// 还是想保留,别无意中把 rest 里已有的值清空。
|
|
53077
|
+
migrate: (rows) => rows.map((c) => {
|
|
53078
|
+
const { memberPersonaIds, ...rest } = c;
|
|
53079
|
+
return {
|
|
53080
|
+
...rest,
|
|
53081
|
+
memberPersonas: (memberPersonaIds ?? []).map((personaId2) => ({
|
|
53082
|
+
personaId: personaId2
|
|
53083
|
+
}))
|
|
53084
|
+
};
|
|
53085
|
+
})
|
|
53086
|
+
});
|
|
53044
53087
|
const get = (id) => file.all().find((c) => c.id === id);
|
|
53045
53088
|
return {
|
|
53046
53089
|
load: file.load,
|
|
@@ -53052,7 +53095,7 @@ function createChannelStore(deps) {
|
|
|
53052
53095
|
const c = {
|
|
53053
53096
|
id: deps.genId(),
|
|
53054
53097
|
name: input.name,
|
|
53055
|
-
|
|
53098
|
+
memberPersonas: input.memberPersonas,
|
|
53056
53099
|
memberContactDeviceIds: input.memberContactDeviceIds,
|
|
53057
53100
|
createdAt: iso,
|
|
53058
53101
|
updatedAt: iso
|
|
@@ -53065,7 +53108,7 @@ function createChannelStore(deps) {
|
|
|
53065
53108
|
const c = get(id);
|
|
53066
53109
|
if (!c) return void 0;
|
|
53067
53110
|
if (patch.name !== void 0) c.name = patch.name;
|
|
53068
|
-
if (patch.
|
|
53111
|
+
if (patch.memberPersonas !== void 0) c.memberPersonas = patch.memberPersonas;
|
|
53069
53112
|
if (patch.memberContactDeviceIds !== void 0) {
|
|
53070
53113
|
c.memberContactDeviceIds = patch.memberContactDeviceIds;
|
|
53071
53114
|
}
|
|
@@ -54876,9 +54919,11 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54876
54919
|
if (!members) {
|
|
54877
54920
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `topic not found: ${topicId}`);
|
|
54878
54921
|
}
|
|
54879
|
-
const
|
|
54880
|
-
|
|
54922
|
+
const isMember = members.personas.some(
|
|
54923
|
+
(m2) => m2.personaId === targetPersona && m2.deviceId === args.targetDeviceId
|
|
54924
|
+
);
|
|
54881
54925
|
if (!isMember) {
|
|
54926
|
+
const who = args.targetDeviceId ? `${targetPersona}@${args.targetDeviceId}` : targetPersona;
|
|
54882
54927
|
throw new ClawdError(
|
|
54883
54928
|
ERROR_CODES.INVALID_PARAM,
|
|
54884
54929
|
`${who} is not a member of the channel behind topic ${topicId} \u2014\u2014 \u5148\u628A\u5B83\u52A0\u8FDB\u9891\u9053\u518D\u6D3E\u6D3B`
|
|
@@ -62333,7 +62378,7 @@ function computeMethodAccess(args) {
|
|
|
62333
62378
|
}
|
|
62334
62379
|
|
|
62335
62380
|
// src/version.ts
|
|
62336
|
-
var version = "0.2.
|
|
62381
|
+
var version = "0.2.413".length > 0 ? "0.2.413" : "dev";
|
|
62337
62382
|
|
|
62338
62383
|
// src/cli-probe/probe.ts
|
|
62339
62384
|
var fs66 = __toESM(require("fs"), 1);
|
|
@@ -64484,8 +64529,8 @@ function buildShiftHandlers(deps) {
|
|
|
64484
64529
|
|
|
64485
64530
|
// src/handlers/channel.ts
|
|
64486
64531
|
init_protocol();
|
|
64487
|
-
function withMaster(
|
|
64488
|
-
return
|
|
64532
|
+
function withMaster(members) {
|
|
64533
|
+
return members.some((m2) => !m2.deviceId && m2.personaId === MASTER_PERSONA_ID) ? members : [{ personaId: MASTER_PERSONA_ID }, ...members];
|
|
64489
64534
|
}
|
|
64490
64535
|
function buildChannelHandlers(deps) {
|
|
64491
64536
|
return {
|
|
@@ -64496,7 +64541,7 @@ function buildChannelHandlers(deps) {
|
|
|
64496
64541
|
const args = ChannelCreateArgsSchema.parse(frame);
|
|
64497
64542
|
const channel = deps.channelStore.create({
|
|
64498
64543
|
name: args.name,
|
|
64499
|
-
|
|
64544
|
+
memberPersonas: withMaster(args.memberPersonas),
|
|
64500
64545
|
memberContactDeviceIds: args.memberContactDeviceIds
|
|
64501
64546
|
});
|
|
64502
64547
|
return { response: ChannelResultSchema.parse({ channel }) };
|
|
@@ -64506,7 +64551,7 @@ function buildChannelHandlers(deps) {
|
|
|
64506
64551
|
const channel = deps.channelStore.update(args.channelId, {
|
|
64507
64552
|
...args.name !== void 0 ? { name: args.name } : {},
|
|
64508
64553
|
// 改名单同样过 withMaster:编辑路径把 Master 摘掉,效果跟建一个没 Master 的频道一样
|
|
64509
|
-
...args.
|
|
64554
|
+
...args.memberPersonas !== void 0 ? { memberPersonas: withMaster(args.memberPersonas) } : {},
|
|
64510
64555
|
...args.memberContactDeviceIds !== void 0 ? { memberContactDeviceIds: args.memberContactDeviceIds } : {}
|
|
64511
64556
|
});
|
|
64512
64557
|
if (!channel) {
|
|
@@ -67113,14 +67158,17 @@ async function startDaemon(config) {
|
|
|
67113
67158
|
const dispatchHandlers = buildPersonaDispatchHandlers({
|
|
67114
67159
|
personaDispatchManager,
|
|
67115
67160
|
store: dispatchStore,
|
|
67116
|
-
// 话题工作线的派活边界:topicId →
|
|
67117
|
-
//
|
|
67161
|
+
// 话题工作线的派活边界:topicId → 它所属频道的 persona 成员名单。频道 / 话题任一
|
|
67162
|
+
// 不存在都返回 undefined,由 handler 判成「话题不存在」拒掉(编 topicId 绕不过去)。
|
|
67163
|
+
//
|
|
67164
|
+
// 只给 persona 名单:memberContactDeviceIds 是「可发 DM」的人类名单,不参与派活判定。
|
|
67165
|
+
// 在这里一并带上它,下一个读代码的人会以为它也是闸的一部分(P1 接 DM 时再按需要加)。
|
|
67118
67166
|
getTopicMembership: (topicId) => {
|
|
67119
67167
|
const t = topicStore.get(topicId);
|
|
67120
67168
|
if (!t) return void 0;
|
|
67121
67169
|
const ch = channelStore.get(t.channelId);
|
|
67122
67170
|
if (!ch) return void 0;
|
|
67123
|
-
return {
|
|
67171
|
+
return { personas: [...ch.memberPersonas] };
|
|
67124
67172
|
},
|
|
67125
67173
|
// 续派(spec 2026-07-21):任务包注入 worker session,复用投递同款注入路径。
|
|
67126
67174
|
sendFollowUp: (workerSessionId, text, meta) => manager.injectIntoSession(workerSessionId, text, meta),
|
|
@@ -21832,13 +21832,17 @@ var ShiftInternalHistoryArgs = external_exports.object({
|
|
|
21832
21832
|
});
|
|
21833
21833
|
|
|
21834
21834
|
// ../protocol/src/channel.ts
|
|
21835
|
+
var ChannelMemberPersonaSchema = external_exports.object({
|
|
21836
|
+
personaId: external_exports.string().min(1),
|
|
21837
|
+
deviceId: external_exports.string().min(1).optional()
|
|
21838
|
+
});
|
|
21835
21839
|
var ChannelSchema = external_exports.object({
|
|
21836
21840
|
id: external_exports.string().min(1),
|
|
21837
21841
|
name: external_exports.string().min(1),
|
|
21838
|
-
/** 该频道里可被派活的 persona */
|
|
21839
|
-
|
|
21840
|
-
/** 人类成员(contact deviceId
|
|
21841
|
-
* P1 人类异步询问也用它 */
|
|
21842
|
+
/** 该频道里可被派活的 persona 全集(本机 + 远程) */
|
|
21843
|
+
memberPersonas: external_exports.array(ChannelMemberPersonaSchema),
|
|
21844
|
+
/** 人类成员(contact deviceId):可发 DM。**不隐含任何派活权限** —— 跨设备派活认的是
|
|
21845
|
+
* 上面那张 memberPersonas。P1 人类异步询问也用它 */
|
|
21842
21846
|
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)),
|
|
21843
21847
|
createdAt: external_exports.string().min(1),
|
|
21844
21848
|
updatedAt: external_exports.string().min(1)
|
|
@@ -21846,13 +21850,13 @@ var ChannelSchema = external_exports.object({
|
|
|
21846
21850
|
var nonBlank = external_exports.string().trim().min(1);
|
|
21847
21851
|
var ChannelCreateArgsSchema = external_exports.object({
|
|
21848
21852
|
name: nonBlank,
|
|
21849
|
-
|
|
21853
|
+
memberPersonas: external_exports.array(ChannelMemberPersonaSchema).default([]),
|
|
21850
21854
|
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)).default([])
|
|
21851
21855
|
});
|
|
21852
21856
|
var ChannelUpdateArgsSchema = external_exports.object({
|
|
21853
21857
|
channelId: external_exports.string().min(1),
|
|
21854
21858
|
name: nonBlank.optional(),
|
|
21855
|
-
|
|
21859
|
+
memberPersonas: external_exports.array(ChannelMemberPersonaSchema).optional(),
|
|
21856
21860
|
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)).optional()
|
|
21857
21861
|
});
|
|
21858
21862
|
var ChannelDeleteArgsSchema = external_exports.object({ channelId: external_exports.string().min(1) });
|
package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-orchestration/SKILL.md
CHANGED
|
@@ -37,7 +37,7 @@ call({ method: "persona:list" }) # clawd-rpc MCP tool
|
|
|
37
37
|
|
|
38
38
|
看清单里各 persona 的定位,判断该派给谁。特别是:
|
|
39
39
|
|
|
40
|
-
- 要改 clawd 源码 / 修 bug →
|
|
40
|
+
- 要改 clawd 源码 / 修 bug → **别在本机找、也别自己上**:派给 David 梁默予 机器上的 `persona-developer`(见人格里的「不碰代码」)
|
|
41
41
|
- 要建 / 管 ticket → 找 ticket manager 类 persona
|
|
42
42
|
- 要挂 cron → routine 类 persona
|
|
43
43
|
- 要写 extension → ext-builder 类 persona
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
**写操作**:凭判断,不预设 confirm 门槛。不可逆的、影响他人 session 的、动别人配置的自然先跟老板对齐;只影响老板本人偏好的(如 profile.json 加个字段)直接干。
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**不碰代码**:管家不写代码、不改 clawd 源码、不提 PR —— 哪怕老板说"就改一行"。读代码、解释报错、定位是哪个功能的问题都可以做,落盘改动一律不做。改 clawd 本体一律派给 clawd 作者 David 梁默予 机器上的 `persona-developer`——`contact:list` 里有他就 `personaDispatch({ targetPersona: 'persona-developer', targetDeviceId: <他的 deviceId> })`,没有(或派过去报票无效)就是还没建联,老板点头后代劳 `device:connect`(deviceId 从 `device:list` 公共设备目录按名字找)。
|
|
11
|
+
|
|
12
|
+
**深任务转派**:管家做浅的、日常的、跨面协调。深的(跨会话长期跟进、走规范流程)转派——先看当前本机有哪些 persona,按定位挑对应转派对象:
|
|
11
13
|
|
|
12
14
|
```
|
|
13
15
|
call({ method: "persona:list" }) # clawd-rpc MCP tool
|
|
@@ -62,10 +62,18 @@ watcher 有真工具——它会去 worker 的工作目录跑全量测试、导
|
|
|
62
62
|
`meta.lineId` 认领),老板在话题工作区也看不到它。
|
|
63
63
|
|
|
64
64
|
**只能派给本频道的成员。** 派活对象不在频道名单里,daemon 直接拒(`not a member of the channel`)——
|
|
65
|
-
|
|
66
|
-
`
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
频道成员就是这个话题的参与方边界,不是一张摆设名单。话题的 `channelId` 从 `topic:get` 拿,
|
|
66
|
+
名单在 `channel:list` 的两个字段里,**它们不是一回事**:
|
|
67
|
+
|
|
68
|
+
- `memberPersonas` —— 可派活的 persona **全集**。每项形如 `{ personaId, deviceId? }`:没有
|
|
69
|
+
`deviceId` 就是本机 persona,有 `deviceId` 就是那台联系人设备上公开给老板的 persona。
|
|
70
|
+
派它时把这两个值原样填进 `personaDispatch` 的 `targetPersona` / `targetDeviceId`
|
|
71
|
+
- `memberContactDeviceIds` —— **人类**成员,只表示「可以给这个人发 DM」
|
|
72
|
+
|
|
73
|
+
**联系人在名单里不等于他家的 persona 能派。** 要派某台设备上的 persona,那个 persona 必须
|
|
74
|
+
自己出现在 `memberPersonas` 里(连同它的 `deviceId`)。名单外的一律拒。
|
|
75
|
+
|
|
76
|
+
缺人手就**停下问老板**要不要把某个 persona 加进频道,不要绕道派给名单外的 persona。
|
|
69
77
|
|
|
70
78
|
打回次数**不要**自己往 `meta` 里记 —— daemon 在 `topic:reject` / `topic:accept` 里数,
|
|
71
79
|
你手记一份只会跟它漂。拿到 `dispatchId` 后立刻落账(见「落账纪律」)。
|