@clawos-dev/clawd 0.2.135-beta.279.732f6db → 0.2.135-beta.281.fb1ead2
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 -9
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -4508,6 +4508,9 @@ var init_persona_schemas = __esm({
|
|
|
4508
4508
|
// 8-key set defined UI-side in `lib/session-icons.ts`; protocol stays plain string
|
|
4509
4509
|
// for forward compatibility, consumer fallbacks to default when key not found.
|
|
4510
4510
|
iconKey: external_exports.string().optional(),
|
|
4511
|
+
// 绑定的 agent tool('claude' / 'codex');缺省消费侧按 'claude' 兜底。
|
|
4512
|
+
// 与 model 平行:persona 新建 session 的默认 tool,可平滑切换。
|
|
4513
|
+
tool: external_exports.string().optional(),
|
|
4511
4514
|
createdAt: external_exports.number(),
|
|
4512
4515
|
updatedAt: external_exports.number()
|
|
4513
4516
|
}).strict();
|
|
@@ -4558,6 +4561,7 @@ var init_persona_schemas = __esm({
|
|
|
4558
4561
|
label: external_exports.string().min(1),
|
|
4559
4562
|
personality: external_exports.string(),
|
|
4560
4563
|
model: external_exports.string().optional(),
|
|
4564
|
+
tool: external_exports.string().optional(),
|
|
4561
4565
|
public: external_exports.boolean().optional(),
|
|
4562
4566
|
iconKey: external_exports.string().optional()
|
|
4563
4567
|
}).strict();
|
|
@@ -4569,6 +4573,7 @@ var init_persona_schemas = __esm({
|
|
|
4569
4573
|
patch: external_exports.object({
|
|
4570
4574
|
label: external_exports.string().min(1).optional(),
|
|
4571
4575
|
model: external_exports.string().optional(),
|
|
4576
|
+
tool: external_exports.string().optional(),
|
|
4572
4577
|
personality: external_exports.string().optional(),
|
|
4573
4578
|
public: external_exports.boolean().optional(),
|
|
4574
4579
|
// pass `null` to clear; daemon strips the field from PersonaFile on null
|
|
@@ -31762,6 +31767,9 @@ function buildSpawnContext(state, deps) {
|
|
|
31762
31767
|
if (meta?.addDirs && meta.addDirs.length > 0) {
|
|
31763
31768
|
ctx.addDirs = meta.addDirs;
|
|
31764
31769
|
}
|
|
31770
|
+
if (meta?.networkAccess !== void 0) {
|
|
31771
|
+
ctx.networkAccess = meta.networkAccess;
|
|
31772
|
+
}
|
|
31765
31773
|
return ctx;
|
|
31766
31774
|
}
|
|
31767
31775
|
function sessionInfoFrame(file) {
|
|
@@ -33258,6 +33266,8 @@ var SessionManager = class {
|
|
|
33258
33266
|
const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
|
|
33259
33267
|
const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
|
|
33260
33268
|
subSessionMeta.extraSettings = JSON.stringify(settings);
|
|
33269
|
+
const domains = settings.sandbox?.network?.allowedDomains;
|
|
33270
|
+
subSessionMeta.networkAccess = Array.isArray(domains) && domains.length > 0;
|
|
33261
33271
|
}
|
|
33262
33272
|
const attachmentGroup = this.deps.attachmentGroup;
|
|
33263
33273
|
const runner = new SessionRunner(makeInitialState(file, subSessionMeta), {
|
|
@@ -34472,6 +34482,11 @@ var PersonaStore = class {
|
|
|
34472
34482
|
claudeMdPath(personaId) {
|
|
34473
34483
|
return path9.join(this.personaDir(personaId), "CLAUDE.md");
|
|
34474
34484
|
}
|
|
34485
|
+
// codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
|
|
34486
|
+
// 两份内容恒一致,persona 切 tool 零迁移。
|
|
34487
|
+
agentsMdPath(personaId) {
|
|
34488
|
+
return path9.join(this.personaDir(personaId), "AGENTS.md");
|
|
34489
|
+
}
|
|
34475
34490
|
/**
|
|
34476
34491
|
* persona 级 sandbox 模板落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
|
|
34477
34492
|
* source 自动发现扫不到(owner `--setting-sources user,project,local` 不会顺手带进来)。
|
|
@@ -34485,6 +34500,7 @@ var PersonaStore = class {
|
|
|
34485
34500
|
const dir = this.personaDir(persona.personaId);
|
|
34486
34501
|
fs7.mkdirSync(path9.join(dir, ".clawd"), { recursive: true });
|
|
34487
34502
|
this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
|
|
34503
|
+
this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
|
|
34488
34504
|
this.atomicWrite(
|
|
34489
34505
|
this.sandboxSettingsPath(persona.personaId),
|
|
34490
34506
|
JSON.stringify(buildGuestSettingsV1(), null, 2)
|
|
@@ -34493,6 +34509,21 @@ var PersonaStore = class {
|
|
|
34493
34509
|
}
|
|
34494
34510
|
writePersonality(personaId, personality) {
|
|
34495
34511
|
this.atomicWrite(this.claudeMdPath(personaId), personality);
|
|
34512
|
+
this.atomicWrite(this.agentsMdPath(personaId), personality);
|
|
34513
|
+
}
|
|
34514
|
+
/**
|
|
34515
|
+
* 历史 persona 补 AGENTS.md:人格双写镜像是 codex 适配后才加的,更早落盘的 persona 只有
|
|
34516
|
+
* CLAUDE.md。codex 原生读 cwd 的 AGENTS.md,缺失则切到 codex 后人格丢失。daemon 启动跑一次
|
|
34517
|
+
* migrate(见 seed.migrateAgentsMirror)。幂等:已有 AGENTS.md(含用户手改的)不覆盖;
|
|
34518
|
+
* 无 CLAUDE.md 不凭空造。返回是否实际补写。
|
|
34519
|
+
*/
|
|
34520
|
+
ensureAgentsMirror(personaId) {
|
|
34521
|
+
const claudeMd = this.claudeMdPath(personaId);
|
|
34522
|
+
const agentsMd = this.agentsMdPath(personaId);
|
|
34523
|
+
if (!fs7.existsSync(claudeMd)) return false;
|
|
34524
|
+
if (fs7.existsSync(agentsMd)) return false;
|
|
34525
|
+
this.atomicWrite(agentsMd, fs7.readFileSync(claudeMd, "utf8"));
|
|
34526
|
+
return true;
|
|
34496
34527
|
}
|
|
34497
34528
|
/**
|
|
34498
34529
|
* 覆盖式写 persona 级 sandbox 配置(seed 给有 profile 的 persona 写 base⊕profile;owner 之后可手编)。
|
|
@@ -34522,9 +34553,11 @@ var PersonaStore = class {
|
|
|
34522
34553
|
return fs7.existsSync(this.metaPath(personaId));
|
|
34523
34554
|
}
|
|
34524
34555
|
readPersonality(personaId) {
|
|
34525
|
-
const
|
|
34526
|
-
if (
|
|
34527
|
-
|
|
34556
|
+
const claudeMd = this.claudeMdPath(personaId);
|
|
34557
|
+
if (fs7.existsSync(claudeMd)) return fs7.readFileSync(claudeMd, "utf8");
|
|
34558
|
+
const agentsMd = this.agentsMdPath(personaId);
|
|
34559
|
+
if (fs7.existsSync(agentsMd)) return fs7.readFileSync(agentsMd, "utf8");
|
|
34560
|
+
return null;
|
|
34528
34561
|
}
|
|
34529
34562
|
/**
|
|
34530
34563
|
* 读 sandbox-settings.json 当前内容;文件不存在 / JSON 解析失败均返回 null。
|
|
@@ -34926,6 +34959,7 @@ var PersonaManager = class {
|
|
|
34926
34959
|
personaId,
|
|
34927
34960
|
label: args.label,
|
|
34928
34961
|
model: args.model,
|
|
34962
|
+
tool: args.tool,
|
|
34929
34963
|
public: args.public ?? false,
|
|
34930
34964
|
iconKey: args.iconKey,
|
|
34931
34965
|
createdAt: now,
|
|
@@ -35205,6 +35239,23 @@ function refreshDaemonManagedDirs(args) {
|
|
|
35205
35239
|
}
|
|
35206
35240
|
}
|
|
35207
35241
|
}
|
|
35242
|
+
function migrateAgentsMirror(args) {
|
|
35243
|
+
let mirrored = 0;
|
|
35244
|
+
for (const personaId of args.store.list()) {
|
|
35245
|
+
try {
|
|
35246
|
+
if (args.store.ensureAgentsMirror(personaId)) {
|
|
35247
|
+
mirrored++;
|
|
35248
|
+
args.logger.info("persona.agents-mirror.synced", { personaId });
|
|
35249
|
+
}
|
|
35250
|
+
} catch (err) {
|
|
35251
|
+
args.logger.warn("persona.agents-mirror.failed", {
|
|
35252
|
+
personaId,
|
|
35253
|
+
error: err instanceof Error ? err.message : String(err)
|
|
35254
|
+
});
|
|
35255
|
+
}
|
|
35256
|
+
}
|
|
35257
|
+
if (mirrored > 0) args.logger.info("persona.agents-mirror.done", { mirrored });
|
|
35258
|
+
}
|
|
35208
35259
|
|
|
35209
35260
|
// src/index.ts
|
|
35210
35261
|
init_claude();
|
|
@@ -35392,24 +35443,29 @@ function num(v2) {
|
|
|
35392
35443
|
|
|
35393
35444
|
// src/tools/codex-app-server-params.ts
|
|
35394
35445
|
function resolveSandbox(ctx) {
|
|
35395
|
-
if (ctx.personaMode === "guest")
|
|
35446
|
+
if (ctx.personaMode === "guest") return "workspace-write";
|
|
35396
35447
|
return "danger-full-access";
|
|
35397
35448
|
}
|
|
35398
35449
|
function resolveApprovalPolicy(ctx) {
|
|
35450
|
+
if (ctx.personaMode === "owner" || ctx.personaMode === "guest") return "never";
|
|
35399
35451
|
const m2 = ctx.permissionMode ?? "";
|
|
35400
35452
|
if (m2 === "untrusted" || m2 === "on-failure" || m2 === "on-request" || m2 === "never") return m2;
|
|
35401
35453
|
return "on-request";
|
|
35402
35454
|
}
|
|
35403
35455
|
function threadStartParams(ctx) {
|
|
35404
|
-
|
|
35456
|
+
const params = {
|
|
35405
35457
|
cwd: ctx.cwd,
|
|
35406
35458
|
sandbox: resolveSandbox(ctx),
|
|
35407
|
-
// persona 侧
|
|
35408
35459
|
approvalPolicy: resolveApprovalPolicy(ctx),
|
|
35409
|
-
// 会话设置侧
|
|
35410
35460
|
approvalsReviewer: "user",
|
|
35411
35461
|
...ctx.model ? { model: ctx.model } : {}
|
|
35412
35462
|
};
|
|
35463
|
+
if (ctx.personaMode === "guest") {
|
|
35464
|
+
params.config = {
|
|
35465
|
+
sandbox_workspace_write: { writable_roots: ctx.addDirs ?? [], network_access: ctx.networkAccess ?? false }
|
|
35466
|
+
};
|
|
35467
|
+
}
|
|
35468
|
+
return params;
|
|
35413
35469
|
}
|
|
35414
35470
|
var ATTACHMENT_RE2 = /\[attachment:(image|file):([^\]]+)\]/g;
|
|
35415
35471
|
var SKILL_RE = /\[skill:(.+?):(\/[^\]]+)\]/g;
|
|
@@ -35598,6 +35654,10 @@ var CODEX_CAPABILITIES = {
|
|
|
35598
35654
|
}
|
|
35599
35655
|
]
|
|
35600
35656
|
};
|
|
35657
|
+
function sanitizeCodexModel(model) {
|
|
35658
|
+
if (model === void 0) return void 0;
|
|
35659
|
+
return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
|
|
35660
|
+
}
|
|
35601
35661
|
async function probeCodex(env = process.env) {
|
|
35602
35662
|
if (env.CODEX_BIN && import_node_fs10.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
|
|
35603
35663
|
try {
|
|
@@ -35631,7 +35691,7 @@ var CodexAdapter = class {
|
|
|
35631
35691
|
return (CODEX_MODELS.find((m2) => m2.id === (modelId ?? "")) ?? CODEX_MODELS[0]).contextWindowSize;
|
|
35632
35692
|
}
|
|
35633
35693
|
createSession(ctx, sink) {
|
|
35634
|
-
return createCodexSession(ctx, sink, { logger: this.logger });
|
|
35694
|
+
return createCodexSession({ ...ctx, model: sanitizeCodexModel(ctx.model) }, sink, { logger: this.logger });
|
|
35635
35695
|
}
|
|
35636
35696
|
spawn(_ctx) {
|
|
35637
35697
|
throw new Error("CodexAdapter uses createSession, not spawn");
|
|
@@ -41051,15 +41111,17 @@ function buildSessionHandlers(deps) {
|
|
|
41051
41111
|
};
|
|
41052
41112
|
const create = async (frame, _client, ctx) => {
|
|
41053
41113
|
const args = SessionCreateArgs.parse(frame);
|
|
41114
|
+
let tool = args.tool;
|
|
41054
41115
|
if (args.ownerPersonaId) {
|
|
41055
41116
|
const persona = deps.personaRegistry.get(args.ownerPersonaId);
|
|
41056
41117
|
if (!persona) {
|
|
41057
41118
|
throw new Error(`persona not found: ${args.ownerPersonaId}`);
|
|
41058
41119
|
}
|
|
41120
|
+
tool = persona.tool ?? args.tool;
|
|
41059
41121
|
}
|
|
41060
41122
|
ensurePersonaAccess(ctx, args.ownerPersonaId, "send");
|
|
41061
41123
|
const creatorPrincipalId = ctx?.principal.id ?? ownerPrincipalId;
|
|
41062
|
-
const { response, broadcast } = manager.create(args, creatorPrincipalId);
|
|
41124
|
+
const { response, broadcast } = manager.create({ ...args, tool }, creatorPrincipalId);
|
|
41063
41125
|
return { response: { type: "session:info", ...response }, broadcast };
|
|
41064
41126
|
};
|
|
41065
41127
|
const list = async (_frame, _client, ctx) => {
|
|
@@ -45221,6 +45283,7 @@ async function startDaemon(config) {
|
|
|
45221
45283
|
} else {
|
|
45222
45284
|
logger.warn("persona.seed.skip", { reason: "defaults-root-not-found" });
|
|
45223
45285
|
}
|
|
45286
|
+
migrateAgentsMirror({ store: personaStore, logger });
|
|
45224
45287
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
45225
45288
|
const manager = new SessionManager({
|
|
45226
45289
|
store,
|
package/package.json
CHANGED