@clawos-dev/clawd 0.2.403 → 0.2.405
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 +171 -17
- package/dist/dispatch/mcp-server.cjs +20 -2
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-vUOVp3oA.js → guest-8eSm7XS8.js} +130 -130
- package/dist/share-ui/assets/guest-b29slU5m.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-xzm4Oo0s.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -6863,7 +6863,8 @@ var init_topic = __esm({
|
|
|
6863
6863
|
TopicResultSchema = external_exports.object({ topic: TopicSchema });
|
|
6864
6864
|
TopicDeleteResultSchema = external_exports.object({
|
|
6865
6865
|
ok: external_exports.literal(true),
|
|
6866
|
-
removedMasterSessionId: external_exports.string().min(1).nullable()
|
|
6866
|
+
removedMasterSessionId: external_exports.string().min(1).nullable(),
|
|
6867
|
+
removedWorkerSessionIds: external_exports.array(external_exports.string().min(1))
|
|
6867
6868
|
});
|
|
6868
6869
|
}
|
|
6869
6870
|
});
|
|
@@ -7073,7 +7074,21 @@ var init_persona_schemas = __esm({
|
|
|
7073
7074
|
}).optional()
|
|
7074
7075
|
});
|
|
7075
7076
|
PersonaInfoResponseSchema = PersonaFileSchema.extend({
|
|
7077
|
+
// 人格 builtin 层:`<personaDir>/CLAUDE.md`(= AGENTS.md 镜像)。预装 persona 的这份是
|
|
7078
|
+
// daemon ship 的产品规格,每次 daemon 启动被覆盖回 bundle 版(personalityManaged 标记它)。
|
|
7076
7079
|
personality: external_exports.string().optional(),
|
|
7080
|
+
// 人格补充层:`<personaDir>/.clawd/personality.local.md`。**与 builtin 层同性质——都是这个
|
|
7081
|
+
// persona 的配置,只是所有权不同**:builtin 归 daemon、随版本更新覆盖;这一层归 persona 的
|
|
7082
|
+
// 主人,不在 DAEMON_MANAGED_PATHS 里,OTA / daemon 重启都不碰。两层叠加生效(人格上冲突时
|
|
7083
|
+
// 以补充层为准),经 SpawnContext.extraSystemPrompt 注入,claude / codex 两端同源,
|
|
7084
|
+
// **owner / guest 会话一律注入**(它是 persona 属性不是私人偏好,同 builtin 人格的待遇)。
|
|
7085
|
+
// 仅 'persona:get' 携带;'' = 没写补充(与 personality 同口径,不用 null)。
|
|
7086
|
+
personalityLocal: external_exports.string().optional(),
|
|
7087
|
+
// builtin 层是不是 daemon 托管:true = 预装 persona,CLAUDE.md 是产品规格、用户改了会被
|
|
7088
|
+
// 下次启动覆盖 → UI 渲染成只读,编辑落到 personalityLocal;false = 用户自建 persona,
|
|
7089
|
+
// 它的 CLAUDE.md daemon 不碰,照旧直接编辑。派生自 daemon 的预装名单,**只读不可回写**。
|
|
7090
|
+
// 仅 'persona:get' 携带。
|
|
7091
|
+
personalityManaged: external_exports.boolean().optional(),
|
|
7077
7092
|
// 仅 'persona:get' 携带;null = 文件不存在 / parse 失败;undefined = 不在该响应类型上
|
|
7078
7093
|
skills: external_exports.array(PersonaSkillSummarySchema).optional(),
|
|
7079
7094
|
// 仅 'persona:get' 携带;空数组 = 没启用任何插件 / settings.json 不存在;undefined = 不在该响应类型上
|
|
@@ -7105,6 +7120,9 @@ var init_persona_schemas = __esm({
|
|
|
7105
7120
|
effort: external_exports.string().optional(),
|
|
7106
7121
|
tool: external_exports.string().optional(),
|
|
7107
7122
|
personality: external_exports.string().optional(),
|
|
7123
|
+
// 人格补充层正文(见 PersonaInfoResponseSchema.personalityLocal)。与 personality 各写
|
|
7124
|
+
// 各层、互不影响;'' = 清空补充层。预装 persona 的编辑入口写的就是这个字段。
|
|
7125
|
+
personalityLocal: external_exports.string().optional(),
|
|
7108
7126
|
public: external_exports.boolean().optional(),
|
|
7109
7127
|
// pass `null` to clear; daemon strips the field from PersonaFile on null
|
|
7110
7128
|
iconKey: external_exports.string().nullable().optional()
|
|
@@ -8584,7 +8602,7 @@ var init_methods = __esm({
|
|
|
8584
8602
|
args: TopicRenameArgsSchema
|
|
8585
8603
|
},
|
|
8586
8604
|
"topic:delete": {
|
|
8587
|
-
summary: "\u5220\u8BDD\u9898\uFF1A\u8FDE\u5E26\u5220\u5B83\u7684 Master session\uFF081:1\uFF09\
|
|
8605
|
+
summary: "\u5220\u8BDD\u9898\uFF1A\u8FDE\u5E26\u5220\u8FD9\u4E2A\u8BDD\u9898\u540D\u4E0B\u7684\u5168\u90E8\u4F1A\u8BDD\u2014\u2014\u5B83\u7684 Master session\uFF081:1\uFF09+ \u5B83\u6D3E\u51FA\u53BB\u7684\u6BCF\u4E00\u6761 worker session\uFF1Bdispatch \u53F0\u8D26\u884C\u4FDD\u7559\u3002\u4F1A\u8BDD\u5DF2\u4E0D\u5728\u65F6\u8BDD\u9898\u7167\u5220\uFF0CMaster \u90A3\u6761\u56DE removedMasterSessionId: null\uFF0Cworker \u90A3\u4E9B\u4E0D\u8FDB removedWorkerSessionIds",
|
|
8588
8606
|
args: TopicDeleteArgsSchema
|
|
8589
8607
|
},
|
|
8590
8608
|
// ---- master:*(授权查表,Master 经 clawd-rpc 桥调)----
|
|
@@ -44979,6 +44997,24 @@ var FILE_LINK_HINT = `## \u8BA9\u7528\u6237\u53BB\u770B\u6587\u4EF6\u65F6\u7ED9\
|
|
|
44979
44997
|
\u8BF7\u7528\u6237\u67E5\u770B\u67D0\u4E2A\u6587\u4EF6\u65F6\uFF0C\u7528 markdown \u94FE\u63A5\u7ED9**\u7EDD\u5BF9\u8DEF\u5F84**\uFF1A\`[\u8BF4\u660E.md](/Users/xxx/project/\u8BF4\u660E.md)\`\u3002
|
|
44980
44998
|
\u53EA\u7ED9\u6587\u4EF6\u540D\u6216\u76F8\u5BF9\u8DEF\u5F84\u7528\u6237\u70B9\u4E0D\u5F00\u4E5F\u627E\u4E0D\u5230\u3002`;
|
|
44981
44999
|
|
|
45000
|
+
// src/persona/local-personality-prompt.ts
|
|
45001
|
+
var LOCAL_PERSONALITY_HEADER = `## \u4EBA\u683C\u8865\u5145\uFF08\u8FD9\u4E2A persona \u7684\u8865\u5145\u8BBE\u5B9A\uFF09
|
|
45002
|
+
|
|
45003
|
+
\u4EE5\u4E0B\u662F\u8FD9\u4E2A persona \u7684\u8865\u5145\u8BBE\u5B9A\uFF0C\u7531\u5B83\u7684\u4E3B\u4EBA\u7EF4\u62A4\uFF0C\u4E0E CLAUDE.md / AGENTS.md \u91CC\u90A3\u4EFD\u5185\u7F6E\u4EBA\u683C\u53E0\u52A0\u751F\u6548\u3002
|
|
45004
|
+
**\u53EA\u8986\u76D6\u4EBA\u683C**\u2014\u2014\u8DDF\u4EBA\u683C\u6709\u5173\u7684\u5730\u65B9\u4EE5\u672C\u6BB5\u4E3A\u51C6\uFF1B\u4E0A\u9762\u90A3\u4E9B\u7531 clawd \u6CE8\u5165\u7684\u64CD\u4F5C\u89C4\u5219\uFF08\u600E\u4E48\u59D4\u6D3E\u3001
|
|
45005
|
+
\u600E\u4E48\u5206\u4EAB\u6587\u4EF6\u3001\u600E\u4E48\u7ED9\u6587\u4EF6\u94FE\u63A5\u3001\u7528\u4E0D\u7528\u9009\u62E9\u5361\u7247\uFF09\u4E0D\u5728\u672C\u6BB5\u7684\u8986\u76D6\u8303\u56F4\u5185\uFF0C\u7167\u65E7\u6267\u884C\u3002
|
|
45006
|
+
|
|
45007
|
+
\u672C\u6BB5\u8DDF\u5185\u7F6E\u4EBA\u683C\u540C\u6027\u8D28\uFF0C\u662F\u8FD9\u4E2A persona \u914D\u7F6E\u7684\u4E00\u90E8\u5206\uFF1A**owner \u4F1A\u8BDD\u4E0E\u8BBF\u5BA2\uFF08guest\uFF09\u4F1A\u8BDD\u4E00\u5F8B\u90FD\u751F\u6548**\u3002
|
|
45008
|
+
\u8981\u5BF9\u4E0D\u540C\u5BF9\u8C61\u6709\u4E0D\u540C\u8868\u73B0\uFF0C\u7531\u5199\u7684\u4EBA\u5728\u6B63\u6587\u91CC\u663E\u5F0F\u5199\u660E\uFF08\u4F8B\u5982\u300C\u9762\u5BF9\u8BBF\u5BA2\u65F6\u4E0D\u8981\u8FD9\u6837\u79F0\u547C\u300D\uFF09\uFF1B\u6CA1\u5199\u660E\u7684
|
|
45009
|
+
\u5C31\u6309\u4E0A\u9762\u7684\u8FDE\u63A5\u8EAB\u4EFD\u81EA\u884C\u62FF\u634F\uFF0C\u522B\u628A\u5BF9\u7740\u4E3B\u4EBA\u8BF4\u7684\u8BDD\u539F\u6837\u5957\u5230\u8BBF\u5BA2\u5934\u4E0A\u3002`;
|
|
45010
|
+
function buildLocalPersonalityPrompt(body) {
|
|
45011
|
+
const trimmed = body?.trim();
|
|
45012
|
+
if (!trimmed) return null;
|
|
45013
|
+
return `${LOCAL_PERSONALITY_HEADER}
|
|
45014
|
+
|
|
45015
|
+
${trimmed}`;
|
|
45016
|
+
}
|
|
45017
|
+
|
|
44982
45018
|
// src/dispatch/system-prompt.ts
|
|
44983
45019
|
var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08dispatch\uFF09
|
|
44984
45020
|
|
|
@@ -45218,6 +45254,12 @@ function buildSpawnContext(state, deps) {
|
|
|
45218
45254
|
if (meta?.personaMode) {
|
|
45219
45255
|
ctx.extraSystemPrompt = (ctx.extraSystemPrompt ? ctx.extraSystemPrompt + "\n\n" : "") + FILE_LINK_HINT;
|
|
45220
45256
|
}
|
|
45257
|
+
if (personaId2) {
|
|
45258
|
+
const localSegment = buildLocalPersonalityPrompt(deps.readPersonalityLocal?.(personaId2));
|
|
45259
|
+
if (localSegment) {
|
|
45260
|
+
ctx.extraSystemPrompt = (ctx.extraSystemPrompt ? ctx.extraSystemPrompt + "\n\n" : "") + localSegment;
|
|
45261
|
+
}
|
|
45262
|
+
}
|
|
45221
45263
|
if (meta?.extraSettings) {
|
|
45222
45264
|
ctx.extraSettings = meta.extraSettings;
|
|
45223
45265
|
}
|
|
@@ -46083,6 +46125,9 @@ var SessionRunner = class {
|
|
|
46083
46125
|
// daemon 级 MCP server 列表闭包透传;见 reducer.buildSpawnContext 派生
|
|
46084
46126
|
// SpawnContext.mcpConfigs + 按 DISPATCH_MCP_ID 判断 dispatch 教学注入
|
|
46085
46127
|
getMcpConfigs: this.hooks.getMcpConfigs,
|
|
46128
|
+
// 人格补充层读闭包透传;reducer.buildSpawnContext 按 SessionFile.ownerPersonaId 查,
|
|
46129
|
+
// 有内容就作为最后一段追加进 extraSystemPrompt
|
|
46130
|
+
readPersonalityLocal: this.hooks.readPersonalityLocal,
|
|
46086
46131
|
lookupDispatchByBSessionId: this.hooks.lookupDispatchByBSessionId,
|
|
46087
46132
|
// ReadyGate v2:透传 mode 让 reducer send / ready-detected 分支决定走暂存队列还是直写
|
|
46088
46133
|
mode: this.hooks.mode,
|
|
@@ -46928,6 +46973,9 @@ var SessionManager = class {
|
|
|
46928
46973
|
// daemon 级 MCP server 列表闭包透传给 reducer,cc spawn 逐项加 --mcp-config flag;
|
|
46929
46974
|
// B session 的 CLAWD_DISPATCH_ID env 由下方 lookupDispatchByBSessionId 反查闭包负责。
|
|
46930
46975
|
getMcpConfigs: () => this.deps.mcpConfigs ?? [],
|
|
46976
|
+
// 人格补充层:只把 store 的这一个读方法窄化成闭包给 runner/reducer(不把整个 personaStore
|
|
46977
|
+
// 递下去——in-place mention 注入那次的教训,见上面那条注释)。缺 store = 不注补充段。
|
|
46978
|
+
readPersonalityLocal: this.deps.personaStore ? (id) => this.deps.personaStore?.readPersonalityLocal(id) ?? null : void 0,
|
|
46931
46979
|
lookupDispatchByBSessionId: this.deps.personaDispatchManager ? (bSid) => this.deps.personaDispatchManager?.lookupDispatchByBSessionId(bSid) : void 0,
|
|
46932
46980
|
// file-sharing (spec §6 PR 3):闭包 scope + sessionId,runner 只暴露 tool/relPath/cwd
|
|
46933
46981
|
onFileEdit: attachmentGroup ? (input) => attachmentGroup.onFileEdit({
|
|
@@ -49010,6 +49058,21 @@ var PersonaStore = class {
|
|
|
49010
49058
|
sandboxSettingsPath(personaId2) {
|
|
49011
49059
|
return path15.join(this.personaDir(personaId2), ".clawd", "sandbox-settings.json");
|
|
49012
49060
|
}
|
|
49061
|
+
/**
|
|
49062
|
+
* 人格补充层落盘路径 —— `<personaDir>/.clawd/personality.local.md`。
|
|
49063
|
+
*
|
|
49064
|
+
* 位置不是随手挑的,两条既有约定叠出来的:`.clawd/` 是 daemon 声明「不动」的 persona 私有区
|
|
49065
|
+
* (不在 seed.ts 的 DAEMON_MANAGED_PATHS 里),`.local` 是仓内已成立的「本机个人 override
|
|
49066
|
+
* 永不被 OTA 覆盖」后缀(见 seed.refreshDeployKit)。于是内置 persona 的 CLAUDE.md 继续被
|
|
49067
|
+
* refresh 覆盖成 bundle 新版、用户写的这层原样活着。
|
|
49068
|
+
*
|
|
49069
|
+
* 同 sandbox-settings.json 的理由:放 `.clawd/` 而非 persona 根目录,让 CC 的 project
|
|
49070
|
+
* setting source 自动发现扫不到——这层只经 SpawnContext.extraSystemPrompt 注入
|
|
49071
|
+
* (见 local-personality-prompt.ts),通道唯一,不会被当第二份 CLAUDE.md 重复加载。
|
|
49072
|
+
*/
|
|
49073
|
+
personalityLocalPath(personaId2) {
|
|
49074
|
+
return path15.join(this.personaDir(personaId2), ".clawd", "personality.local.md");
|
|
49075
|
+
}
|
|
49013
49076
|
write(persona, personality) {
|
|
49014
49077
|
const dir = this.personaDir(persona.personaId);
|
|
49015
49078
|
fs12.mkdirSync(path15.join(dir, ".clawd"), { recursive: true });
|
|
@@ -49022,6 +49085,25 @@ var PersonaStore = class {
|
|
|
49022
49085
|
this.atomicWrite(this.claudeMdPath(personaId2), personality);
|
|
49023
49086
|
this.atomicWrite(this.agentsMdPath(personaId2), personality);
|
|
49024
49087
|
}
|
|
49088
|
+
/** 读人格补充层正文;文件不存在返回 null(= 该 persona 没有补充,走内置人格)。 */
|
|
49089
|
+
readPersonalityLocal(personaId2) {
|
|
49090
|
+
const p2 = this.personalityLocalPath(personaId2);
|
|
49091
|
+
if (!fs12.existsSync(p2)) return null;
|
|
49092
|
+
return fs12.readFileSync(p2, "utf8");
|
|
49093
|
+
}
|
|
49094
|
+
/**
|
|
49095
|
+
* 写人格补充层。**纯空白 = 清空**:删文件而不是留个空文件——「有没有补充」的唯一判据
|
|
49096
|
+
* 是文件在不在,留空文件会让下游多一种要判空的状态。persona 目录还没建时自建 `.clawd/`。
|
|
49097
|
+
*/
|
|
49098
|
+
writePersonalityLocal(personaId2, body) {
|
|
49099
|
+
const p2 = this.personalityLocalPath(personaId2);
|
|
49100
|
+
if (!body.trim()) {
|
|
49101
|
+
fs12.rmSync(p2, { force: true });
|
|
49102
|
+
return;
|
|
49103
|
+
}
|
|
49104
|
+
fs12.mkdirSync(path15.dirname(p2), { recursive: true });
|
|
49105
|
+
this.atomicWrite(p2, body);
|
|
49106
|
+
}
|
|
49025
49107
|
/**
|
|
49026
49108
|
* 历史 persona 补 AGENTS.md:人格双写镜像是 codex 适配后才加的,更早落盘的 persona 只有
|
|
49027
49109
|
* CLAUDE.md。codex 原生读 cwd 的 AGENTS.md,缺失则切到 codex 后人格丢失。daemon 启动跑一次
|
|
@@ -49547,7 +49629,7 @@ var PersonaManager = class {
|
|
|
49547
49629
|
this.deps.registry.set(persona);
|
|
49548
49630
|
return persona;
|
|
49549
49631
|
}
|
|
49550
|
-
update(personaId2, patch,
|
|
49632
|
+
update(personaId2, patch, texts) {
|
|
49551
49633
|
const existing = this.deps.registry.get(personaId2);
|
|
49552
49634
|
if (!existing) throw new Error(`persona not found: ${personaId2}`);
|
|
49553
49635
|
const { iconKey: iconKeyPatch, ...restPatch } = patch;
|
|
@@ -49566,8 +49648,11 @@ var PersonaManager = class {
|
|
|
49566
49648
|
} else if (iconKeyPatch !== void 0) {
|
|
49567
49649
|
updated.iconKey = iconKeyPatch;
|
|
49568
49650
|
}
|
|
49569
|
-
if (personality !== void 0) {
|
|
49570
|
-
this.deps.store.writePersonality(personaId2, personality);
|
|
49651
|
+
if (texts?.personality !== void 0) {
|
|
49652
|
+
this.deps.store.writePersonality(personaId2, texts.personality);
|
|
49653
|
+
}
|
|
49654
|
+
if (texts?.personalityLocal !== void 0) {
|
|
49655
|
+
this.deps.store.writePersonalityLocal(personaId2, texts.personalityLocal);
|
|
49571
49656
|
}
|
|
49572
49657
|
this.deps.store.writeMeta(updated);
|
|
49573
49658
|
this.deps.registry.set(updated);
|
|
@@ -49577,6 +49662,10 @@ var PersonaManager = class {
|
|
|
49577
49662
|
readPersonality(personaId2) {
|
|
49578
49663
|
return this.deps.store.readPersonality(personaId2);
|
|
49579
49664
|
}
|
|
49665
|
+
/** 读人格补充层(`.clawd/personality.local.md`);没写过返回 null。供 persona:get 拼响应。 */
|
|
49666
|
+
readPersonalityLocal(personaId2) {
|
|
49667
|
+
return this.deps.store.readPersonalityLocal(personaId2);
|
|
49668
|
+
}
|
|
49580
49669
|
/** 扫 persona 私有 skills 目录;目录不存在返回空数组。供 persona:get handler 拼响应。 */
|
|
49581
49670
|
listSkills(personaId2) {
|
|
49582
49671
|
return listSkillsForDir(this.deps.store.skillsDir(personaId2), "project");
|
|
@@ -49936,6 +50025,34 @@ function refreshDaemonManagedDirs(args) {
|
|
|
49936
50025
|
}
|
|
49937
50026
|
}
|
|
49938
50027
|
}
|
|
50028
|
+
function isDaemonManagedPersonality(personaId2, entries = DEFAULT_PERSONAS) {
|
|
50029
|
+
return entries.some((e) => e.personaId === personaId2);
|
|
50030
|
+
}
|
|
50031
|
+
function migratePersonalityOverlay(args) {
|
|
50032
|
+
const entries = args.entries ?? DEFAULT_PERSONAS;
|
|
50033
|
+
for (const entry of entries) {
|
|
50034
|
+
const personaId2 = entry.personaId;
|
|
50035
|
+
try {
|
|
50036
|
+
if (fs14.existsSync(args.store.personalityLocalPath(personaId2))) continue;
|
|
50037
|
+
const bundleClaudeMd = path17.join(args.defaultsRoot, personaId2, "CLAUDE.md");
|
|
50038
|
+
if (!fs14.existsSync(bundleClaudeMd)) continue;
|
|
50039
|
+
const current = args.store.readPersonality(personaId2);
|
|
50040
|
+
if (current === null) continue;
|
|
50041
|
+
const bundle = fs14.readFileSync(bundleClaudeMd, "utf8");
|
|
50042
|
+
if (current === bundle) continue;
|
|
50043
|
+
if (!current.startsWith(bundle)) continue;
|
|
50044
|
+
const tail = current.slice(bundle.length).trim();
|
|
50045
|
+
if (!tail) continue;
|
|
50046
|
+
args.store.writePersonalityLocal(personaId2, tail);
|
|
50047
|
+
args.logger.info("persona.personality.overlay-migrated", { personaId: personaId2, chars: tail.length });
|
|
50048
|
+
} catch (err) {
|
|
50049
|
+
args.logger.warn("persona.personality.overlay-migrate.failed", {
|
|
50050
|
+
personaId: personaId2,
|
|
50051
|
+
error: err instanceof Error ? err.message : String(err)
|
|
50052
|
+
});
|
|
50053
|
+
}
|
|
50054
|
+
}
|
|
50055
|
+
}
|
|
49939
50056
|
function refreshSandboxSettings(args) {
|
|
49940
50057
|
const entries = args.entries ?? DEFAULT_PERSONAS;
|
|
49941
50058
|
for (const entry of entries) {
|
|
@@ -62188,7 +62305,7 @@ function computeMethodAccess(args) {
|
|
|
62188
62305
|
}
|
|
62189
62306
|
|
|
62190
62307
|
// src/version.ts
|
|
62191
|
-
var version = "0.2.
|
|
62308
|
+
var version = "0.2.405".length > 0 ? "0.2.405" : "dev";
|
|
62192
62309
|
|
|
62193
62310
|
// src/cli-probe/probe.ts
|
|
62194
62311
|
var fs66 = __toESM(require("fs"), 1);
|
|
@@ -62347,6 +62464,8 @@ function buildPersonaHandlers(deps) {
|
|
|
62347
62464
|
);
|
|
62348
62465
|
}
|
|
62349
62466
|
const personality = personaManager.readPersonality(args.personaId) ?? "";
|
|
62467
|
+
const personalityLocal = personaManager.readPersonalityLocal(args.personaId) ?? "";
|
|
62468
|
+
const personalityManaged = isDaemonManagedPersonality(args.personaId);
|
|
62350
62469
|
const skills = personaManager.listSkills(args.personaId);
|
|
62351
62470
|
const plugins = personaManager.listEnabledPlugins(args.personaId);
|
|
62352
62471
|
const sandboxSettings = personaManager.readSandboxSettings(args.personaId);
|
|
@@ -62355,6 +62474,8 @@ function buildPersonaHandlers(deps) {
|
|
|
62355
62474
|
type: "persona:info",
|
|
62356
62475
|
...persona,
|
|
62357
62476
|
personality,
|
|
62477
|
+
personalityLocal,
|
|
62478
|
+
personalityManaged,
|
|
62358
62479
|
skills,
|
|
62359
62480
|
plugins,
|
|
62360
62481
|
sandboxSettings
|
|
@@ -62364,8 +62485,8 @@ function buildPersonaHandlers(deps) {
|
|
|
62364
62485
|
const update = async (frame) => {
|
|
62365
62486
|
const { type: _type, requestId: _requestId, ...rest } = frame;
|
|
62366
62487
|
const args = parseArgs2(PersonaUpdateArgsSchema, frame, "persona:update");
|
|
62367
|
-
const { personality, ...metaPatch } = args.patch;
|
|
62368
|
-
const persona = personaManager.update(args.personaId, metaPatch, personality);
|
|
62488
|
+
const { personality, personalityLocal, ...metaPatch } = args.patch;
|
|
62489
|
+
const persona = personaManager.update(args.personaId, metaPatch, { personality, personalityLocal });
|
|
62369
62490
|
return { response: { type: "persona:info", ...persona } };
|
|
62370
62491
|
};
|
|
62371
62492
|
const del = async (frame) => {
|
|
@@ -64335,6 +64456,9 @@ function buildShiftHandlers(deps) {
|
|
|
64335
64456
|
|
|
64336
64457
|
// src/handlers/channel.ts
|
|
64337
64458
|
init_protocol();
|
|
64459
|
+
function withMaster(ids) {
|
|
64460
|
+
return ids.includes(MASTER_PERSONA_ID) ? ids : [MASTER_PERSONA_ID, ...ids];
|
|
64461
|
+
}
|
|
64338
64462
|
function buildChannelHandlers(deps) {
|
|
64339
64463
|
return {
|
|
64340
64464
|
"channel:list": async () => ({
|
|
@@ -64344,7 +64468,7 @@ function buildChannelHandlers(deps) {
|
|
|
64344
64468
|
const args = ChannelCreateArgsSchema.parse(frame);
|
|
64345
64469
|
const channel = deps.channelStore.create({
|
|
64346
64470
|
name: args.name,
|
|
64347
|
-
memberPersonaIds: args.memberPersonaIds,
|
|
64471
|
+
memberPersonaIds: withMaster(args.memberPersonaIds),
|
|
64348
64472
|
memberContactDeviceIds: args.memberContactDeviceIds
|
|
64349
64473
|
});
|
|
64350
64474
|
return { response: ChannelResultSchema.parse({ channel }) };
|
|
@@ -64353,7 +64477,8 @@ function buildChannelHandlers(deps) {
|
|
|
64353
64477
|
const args = ChannelUpdateArgsSchema.parse(frame);
|
|
64354
64478
|
const channel = deps.channelStore.update(args.channelId, {
|
|
64355
64479
|
...args.name !== void 0 ? { name: args.name } : {},
|
|
64356
|
-
|
|
64480
|
+
// 改名单同样过 withMaster:编辑路径把 Master 摘掉,效果跟建一个没 Master 的频道一样
|
|
64481
|
+
...args.memberPersonaIds !== void 0 ? { memberPersonaIds: withMaster(args.memberPersonaIds) } : {},
|
|
64357
64482
|
...args.memberContactDeviceIds !== void 0 ? { memberContactDeviceIds: args.memberContactDeviceIds } : {}
|
|
64358
64483
|
});
|
|
64359
64484
|
if (!channel) {
|
|
@@ -64419,6 +64544,16 @@ function buildTopicHandlers(deps) {
|
|
|
64419
64544
|
}
|
|
64420
64545
|
return joinLines(records, t.lineMeta);
|
|
64421
64546
|
};
|
|
64547
|
+
const workerSessionIdsOf = (masterSessionId) => {
|
|
64548
|
+
const ids = /* @__PURE__ */ new Set();
|
|
64549
|
+
for (const r of deps.dispatchStore.list({ sourceSessionId: masterSessionId })) {
|
|
64550
|
+
if (typeof r.workerSessionId === "string" && r.workerSessionId) {
|
|
64551
|
+
ids.add(r.workerSessionId);
|
|
64552
|
+
}
|
|
64553
|
+
}
|
|
64554
|
+
ids.delete(masterSessionId);
|
|
64555
|
+
return [...ids];
|
|
64556
|
+
};
|
|
64422
64557
|
return {
|
|
64423
64558
|
"topic:list": async (frame) => {
|
|
64424
64559
|
const { channelId } = TopicListArgsSchema.parse(frame);
|
|
@@ -64555,14 +64690,30 @@ function buildTopicHandlers(deps) {
|
|
|
64555
64690
|
"topic:delete": async (frame) => {
|
|
64556
64691
|
const { topicId } = TopicDeleteArgsSchema.parse(frame);
|
|
64557
64692
|
const topic = mustGet(topicId);
|
|
64558
|
-
const { removed, broadcast } = deps.
|
|
64693
|
+
const { removed, broadcast } = deps.deleteSession(topic.masterSessionId);
|
|
64694
|
+
const removedWorkerSessionIds = [];
|
|
64695
|
+
const allBroadcast = [...broadcast];
|
|
64696
|
+
for (const sessionId of workerSessionIdsOf(topic.masterSessionId)) {
|
|
64697
|
+
try {
|
|
64698
|
+
const w2 = deps.deleteSession(sessionId);
|
|
64699
|
+
allBroadcast.push(...w2.broadcast);
|
|
64700
|
+
if (w2.removed) removedWorkerSessionIds.push(sessionId);
|
|
64701
|
+
} catch (err) {
|
|
64702
|
+
deps.logger?.warn("topic.delete.worker-failed", {
|
|
64703
|
+
topicId,
|
|
64704
|
+
sessionId,
|
|
64705
|
+
error: err instanceof Error ? err.message : String(err)
|
|
64706
|
+
});
|
|
64707
|
+
}
|
|
64708
|
+
}
|
|
64559
64709
|
deps.topicStore.remove(topicId);
|
|
64560
64710
|
return {
|
|
64561
64711
|
response: TopicDeleteResultSchema.parse({
|
|
64562
64712
|
ok: true,
|
|
64563
|
-
removedMasterSessionId: removed ? topic.masterSessionId : null
|
|
64713
|
+
removedMasterSessionId: removed ? topic.masterSessionId : null,
|
|
64714
|
+
removedWorkerSessionIds
|
|
64564
64715
|
}),
|
|
64565
|
-
broadcast
|
|
64716
|
+
broadcast: allBroadcast
|
|
64566
64717
|
};
|
|
64567
64718
|
}
|
|
64568
64719
|
};
|
|
@@ -65208,7 +65359,8 @@ function buildMethodHandlers(deps) {
|
|
|
65208
65359
|
channelStore: deps.channelStore,
|
|
65209
65360
|
dispatchStore: deps.dispatchStore,
|
|
65210
65361
|
createMasterSession: deps.createMasterSession,
|
|
65211
|
-
|
|
65362
|
+
deleteSession: deps.deleteSession,
|
|
65363
|
+
logger: deps.logger
|
|
65212
65364
|
}),
|
|
65213
65365
|
...buildShiftHandlers({
|
|
65214
65366
|
shiftStore: deps.shiftStore,
|
|
@@ -66124,6 +66276,7 @@ async function startDaemon(config) {
|
|
|
66124
66276
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
66125
66277
|
if (defaultsRoot) {
|
|
66126
66278
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
66279
|
+
migratePersonalityOverlay({ store: personaStore, defaultsRoot, logger });
|
|
66127
66280
|
refreshDaemonManagedDirs({ store: personaStore, defaultsRoot, logger });
|
|
66128
66281
|
} else {
|
|
66129
66282
|
logger.warn("persona.seed.skip", { reason: "defaults-root-not-found" });
|
|
@@ -66695,9 +66848,10 @@ async function startDaemon(config) {
|
|
|
66695
66848
|
}
|
|
66696
66849
|
return { sessionId, file: response };
|
|
66697
66850
|
},
|
|
66698
|
-
//
|
|
66699
|
-
//
|
|
66700
|
-
|
|
66851
|
+
// 删话题连带删这个话题名下的全部会话(Master + 它派出去的 worker),逐条走这里。
|
|
66852
|
+
// 会话已经不在本机了不算失败——话题仍要删得掉,所以 SESSION_NOT_FOUND 吞掉并回
|
|
66853
|
+
// removed:false,其余错误照抛(别把真故障说成成功)。
|
|
66854
|
+
deleteSession: (sessionId) => {
|
|
66701
66855
|
try {
|
|
66702
66856
|
const { broadcast } = manager.delete({ sessionId });
|
|
66703
66857
|
return { removed: true, broadcast };
|
|
@@ -22051,7 +22051,8 @@ var TopicAcceptResultSchema = external_exports.object({
|
|
|
22051
22051
|
var TopicResultSchema = external_exports.object({ topic: TopicSchema });
|
|
22052
22052
|
var TopicDeleteResultSchema = external_exports.object({
|
|
22053
22053
|
ok: external_exports.literal(true),
|
|
22054
|
-
removedMasterSessionId: external_exports.string().min(1).nullable()
|
|
22054
|
+
removedMasterSessionId: external_exports.string().min(1).nullable(),
|
|
22055
|
+
removedWorkerSessionIds: external_exports.array(external_exports.string().min(1))
|
|
22055
22056
|
});
|
|
22056
22057
|
|
|
22057
22058
|
// ../protocol/src/master.ts
|
|
@@ -22226,7 +22227,21 @@ var PersonaSandboxSettingsSchema = external_exports.object({
|
|
|
22226
22227
|
}).optional()
|
|
22227
22228
|
});
|
|
22228
22229
|
var PersonaInfoResponseSchema = PersonaFileSchema.extend({
|
|
22230
|
+
// 人格 builtin 层:`<personaDir>/CLAUDE.md`(= AGENTS.md 镜像)。预装 persona 的这份是
|
|
22231
|
+
// daemon ship 的产品规格,每次 daemon 启动被覆盖回 bundle 版(personalityManaged 标记它)。
|
|
22229
22232
|
personality: external_exports.string().optional(),
|
|
22233
|
+
// 人格补充层:`<personaDir>/.clawd/personality.local.md`。**与 builtin 层同性质——都是这个
|
|
22234
|
+
// persona 的配置,只是所有权不同**:builtin 归 daemon、随版本更新覆盖;这一层归 persona 的
|
|
22235
|
+
// 主人,不在 DAEMON_MANAGED_PATHS 里,OTA / daemon 重启都不碰。两层叠加生效(人格上冲突时
|
|
22236
|
+
// 以补充层为准),经 SpawnContext.extraSystemPrompt 注入,claude / codex 两端同源,
|
|
22237
|
+
// **owner / guest 会话一律注入**(它是 persona 属性不是私人偏好,同 builtin 人格的待遇)。
|
|
22238
|
+
// 仅 'persona:get' 携带;'' = 没写补充(与 personality 同口径,不用 null)。
|
|
22239
|
+
personalityLocal: external_exports.string().optional(),
|
|
22240
|
+
// builtin 层是不是 daemon 托管:true = 预装 persona,CLAUDE.md 是产品规格、用户改了会被
|
|
22241
|
+
// 下次启动覆盖 → UI 渲染成只读,编辑落到 personalityLocal;false = 用户自建 persona,
|
|
22242
|
+
// 它的 CLAUDE.md daemon 不碰,照旧直接编辑。派生自 daemon 的预装名单,**只读不可回写**。
|
|
22243
|
+
// 仅 'persona:get' 携带。
|
|
22244
|
+
personalityManaged: external_exports.boolean().optional(),
|
|
22230
22245
|
// 仅 'persona:get' 携带;null = 文件不存在 / parse 失败;undefined = 不在该响应类型上
|
|
22231
22246
|
skills: external_exports.array(PersonaSkillSummarySchema).optional(),
|
|
22232
22247
|
// 仅 'persona:get' 携带;空数组 = 没启用任何插件 / settings.json 不存在;undefined = 不在该响应类型上
|
|
@@ -22258,6 +22273,9 @@ var PersonaUpdateArgsSchema = external_exports.object({
|
|
|
22258
22273
|
effort: external_exports.string().optional(),
|
|
22259
22274
|
tool: external_exports.string().optional(),
|
|
22260
22275
|
personality: external_exports.string().optional(),
|
|
22276
|
+
// 人格补充层正文(见 PersonaInfoResponseSchema.personalityLocal)。与 personality 各写
|
|
22277
|
+
// 各层、互不影响;'' = 清空补充层。预装 persona 的编辑入口写的就是这个字段。
|
|
22278
|
+
personalityLocal: external_exports.string().optional(),
|
|
22261
22279
|
public: external_exports.boolean().optional(),
|
|
22262
22280
|
// pass `null` to clear; daemon strips the field from PersonaFile on null
|
|
22263
22281
|
iconKey: external_exports.string().nullable().optional()
|
|
@@ -23644,7 +23662,7 @@ var METHOD_DOCS = {
|
|
|
23644
23662
|
args: TopicRenameArgsSchema
|
|
23645
23663
|
},
|
|
23646
23664
|
"topic:delete": {
|
|
23647
|
-
summary: "\u5220\u8BDD\u9898\uFF1A\u8FDE\u5E26\u5220\u5B83\u7684 Master session\uFF081:1\uFF09\
|
|
23665
|
+
summary: "\u5220\u8BDD\u9898\uFF1A\u8FDE\u5E26\u5220\u8FD9\u4E2A\u8BDD\u9898\u540D\u4E0B\u7684\u5168\u90E8\u4F1A\u8BDD\u2014\u2014\u5B83\u7684 Master session\uFF081:1\uFF09+ \u5B83\u6D3E\u51FA\u53BB\u7684\u6BCF\u4E00\u6761 worker session\uFF1Bdispatch \u53F0\u8D26\u884C\u4FDD\u7559\u3002\u4F1A\u8BDD\u5DF2\u4E0D\u5728\u65F6\u8BDD\u9898\u7167\u5220\uFF0CMaster \u90A3\u6761\u56DE removedMasterSessionId: null\uFF0Cworker \u90A3\u4E9B\u4E0D\u8FDB removedWorkerSessionIds",
|
|
23648
23666
|
args: TopicDeleteArgsSchema
|
|
23649
23667
|
},
|
|
23650
23668
|
// ---- master:*(授权查表,Master 经 clawd-rpc 桥调)----
|