@clawos-dev/clawd 0.2.275 → 0.2.277

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 CHANGED
@@ -6651,6 +6651,11 @@ var init_persona_schemas = __esm({
6651
6651
  sandboxSettings: PersonaSandboxSettingsSchema.nullable().optional()
6652
6652
  });
6653
6653
  PersonaCreateArgsSchema = external_exports.object({
6654
+ // persona 身份。daemon 拼成 personaId = `persona-<slug>`——前缀由 daemon 拥有,调用方只给后半段,
6655
+ // 「所有 persona id 带该前缀」的约定由构造保证。与 label(显示名,可中文、可随时改)是两个概念:
6656
+ // 曾经只有 label、id 从 label 推,导致中文 label 被剥空后一律降级成 persona-persona。
6657
+ // 正则即安全边界——该值直接落进 ~/.clawd/personas/<id>/,此处排除 . / 空格后路径穿越无从构造。
6658
+ slug: external_exports.string().regex(/^[a-z0-9]+(-[a-z0-9]+)*$/).max(32),
6654
6659
  label: external_exports.string().min(1),
6655
6660
  personality: external_exports.string(),
6656
6661
  model: external_exports.string().optional(),
@@ -7981,7 +7986,7 @@ var init_methods = __esm({
7981
7986
  args: CapabilitiesGetArgs
7982
7987
  },
7983
7988
  "persona:create": {
7984
- summary: "\u65B0\u5EFA persona\uFF08\u5199 PersonaFile + CLAUDE.md \u9AA8\u67B6\uFF09\u3002owner-only",
7989
+ summary: "\u65B0\u5EFA persona\uFF08\u5199 PersonaFile + CLAUDE.md \u9AA8\u67B6\uFF09\u3002owner-only\u3002slug \u53EA\u6536\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u4E0E\u5355\u8FDE\u5B57\u7B26\uFF08^[a-z0-9]+(-[a-z0-9]+)*$\uFF0C\u226432\uFF09\uFF0Cdaemon \u62FC\u6210 personaId=persona-<slug>\uFF1B\u8BE5 id \u5DF2\u5B58\u5728\u5219\u62A5\u9519\uFF0C\u4E0D\u81EA\u52A8\u6539\u540D\u3002label \u662F\u663E\u793A\u540D\uFF0C\u4E0D\u53C2\u4E0E id \u63A8\u5BFC\uFF0C\u53EF\u7528\u4E2D\u6587",
7985
7990
  args: PersonaCreateArgsSchema
7986
7991
  },
7987
7992
  "persona:list": {
@@ -47622,9 +47627,6 @@ var PersonaRegistry = class {
47622
47627
  }
47623
47628
  };
47624
47629
 
47625
- // src/persona/manager.ts
47626
- var import_node_crypto3 = __toESM(require("crypto"), 1);
47627
-
47628
47630
  // src/skills/scanner.ts
47629
47631
  var import_node_fs10 = __toESM(require("fs"), 1);
47630
47632
  var import_node_os6 = __toESM(require("os"), 1);
@@ -47904,8 +47906,19 @@ var PersonaManager = class {
47904
47906
  this.deps = deps;
47905
47907
  }
47906
47908
  deps;
47909
+ /**
47910
+ * slug 是 persona 的身份,label 只是显示名——两者刻意分开:id 落进文件路径 /
47911
+ * 分享链接且创建后不可改,label 可中文、可随时改。此前 id 从 label 推导,
47912
+ * 非 ascii 被剥空后一律 fallback 成 `persona-persona`。
47913
+ *
47914
+ * 撞名直接抛错而非改名:id 由调用方显式指定,静默换成带后缀的 id 等于把
47915
+ * 用户的选择偷偷改掉。字符集校验在 PersonaCreateArgsSchema(路径穿越边界)。
47916
+ */
47907
47917
  create(args) {
47908
- const personaId2 = this.generatePersonaId(args.label);
47918
+ const personaId2 = `persona-${args.slug}`;
47919
+ if (this.deps.store.has(personaId2)) {
47920
+ throw new Error(`personaId already exists: ${personaId2}`);
47921
+ }
47909
47922
  const now = Date.now();
47910
47923
  const persona = {
47911
47924
  personaId: personaId2,
@@ -47971,21 +47984,6 @@ var PersonaManager = class {
47971
47984
  this.deps.store.remove(personaId2);
47972
47985
  this.deps.registry.remove(personaId2);
47973
47986
  }
47974
- /**
47975
- * label 转 4-16 char slug。优先用 `persona-<slug>`;若 slug 已被占用,追加 4 char
47976
- * base64url 随机后缀直到不撞为止(最多 5 次,理论冲突 ≈ 2^-24,留个 panic 上限)。
47977
- */
47978
- generatePersonaId(label) {
47979
- const slug = label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 16) || "persona";
47980
- const base = `persona-${slug}`;
47981
- if (!this.deps.store.has(base)) return base;
47982
- for (let i = 0; i < 5; i++) {
47983
- const rand = import_node_crypto3.default.randomBytes(3).toString("base64url").slice(0, 4);
47984
- const candidate = `${base}-${rand}`;
47985
- if (!this.deps.store.has(candidate)) return candidate;
47986
- }
47987
- throw new Error(`failed to generate unique personaId for label=${label}`);
47988
- }
47989
47987
  };
47990
47988
 
47991
47989
  // src/persona/seed.ts
@@ -48545,7 +48543,7 @@ function tryLoadShareUi(logger) {
48545
48543
  }
48546
48544
 
48547
48545
  // src/visitor/visitor-token.ts
48548
- var import_node_crypto4 = __toESM(require("crypto"), 1);
48546
+ var import_node_crypto3 = __toESM(require("crypto"), 1);
48549
48547
 
48550
48548
  // ../protocol/src/index.ts
48551
48549
  init_runtime();
@@ -48553,7 +48551,7 @@ init_runtime();
48553
48551
  // src/visitor/visitor-token.ts
48554
48552
  var DOMAIN_PREFIX = "clawd-visitor-v1|";
48555
48553
  function hmac(secret, body) {
48556
- return import_node_crypto4.default.createHmac("sha256", secret).update(`${DOMAIN_PREFIX}${body}`).digest("base64url");
48554
+ return import_node_crypto3.default.createHmac("sha256", secret).update(`${DOMAIN_PREFIX}${body}`).digest("base64url");
48557
48555
  }
48558
48556
  function signVisitorToken(secret, payload) {
48559
48557
  const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
@@ -48566,7 +48564,7 @@ function verifyVisitorToken(secret, token, now) {
48566
48564
  const sig = token.slice(dot + 1);
48567
48565
  const expected = hmac(secret, body);
48568
48566
  if (sig.length !== expected.length) return { ok: false, reason: "BAD_SIGNATURE" };
48569
- if (!import_node_crypto4.default.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
48567
+ if (!import_node_crypto3.default.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
48570
48568
  return { ok: false, reason: "BAD_SIGNATURE" };
48571
48569
  }
48572
48570
  let payload;
@@ -49268,7 +49266,7 @@ var CodexAdapter = class {
49268
49266
  };
49269
49267
 
49270
49268
  // src/tools/claude-tui.ts
49271
- var import_node_crypto5 = require("crypto");
49269
+ var import_node_crypto4 = require("crypto");
49272
49270
  var import_node_fs19 = __toESM(require("fs"), 1);
49273
49271
  var import_node_os7 = __toESM(require("os"), 1);
49274
49272
  var import_node_path17 = __toESM(require("path"), 1);
@@ -50156,7 +50154,7 @@ function observeScreenIdle(surface, opts) {
50156
50154
  };
50157
50155
  }
50158
50156
  function shortHash(s) {
50159
- return (0, import_node_crypto5.createHash)("sha1").update(s).digest("hex").slice(0, 8);
50157
+ return (0, import_node_crypto4.createHash)("sha1").update(s).digest("hex").slice(0, 8);
50160
50158
  }
50161
50159
  function firstLineDiff(prev, next) {
50162
50160
  const p2 = prev.split("\n");
@@ -50870,7 +50868,7 @@ function resolveSourceJsonlPath(sourceFile, home) {
50870
50868
  // src/shift/store.ts
50871
50869
  var import_promises2 = __toESM(require("fs/promises"), 1);
50872
50870
  var import_node_path26 = __toESM(require("path"), 1);
50873
- var import_node_crypto6 = require("crypto");
50871
+ var import_node_crypto5 = require("crypto");
50874
50872
 
50875
50873
  // src/shift/schedule.ts
50876
50874
  var import_cron_parser = __toESM(require_dist(), 1);
@@ -50974,7 +50972,7 @@ function createShiftStore(deps) {
50974
50972
  const shift = {
50975
50973
  ...input,
50976
50974
  schedule,
50977
- id: (0, import_node_crypto6.randomUUID)(),
50975
+ id: (0, import_node_crypto5.randomUUID)(),
50978
50976
  createdAtMs: now,
50979
50977
  updatedAtMs: now,
50980
50978
  state: { nextRunAtMs },
@@ -53678,7 +53676,7 @@ var ContactStore = class {
53678
53676
  };
53679
53677
 
53680
53678
  // src/contact/connect-remote.ts
53681
- var crypto5 = __toESM(require("crypto"), 1);
53679
+ var crypto4 = __toESM(require("crypto"), 1);
53682
53680
  init_protocol();
53683
53681
  var HANDSHAKE_TIMEOUT_MS = 5e3;
53684
53682
  var RPC_TIMEOUT_MS = 5e3;
@@ -53733,7 +53731,7 @@ async function connectRemote(args) {
53733
53731
  ws.once("close", onClose);
53734
53732
  });
53735
53733
  function call(method, payload) {
53736
- const requestId = crypto5.randomUUID();
53734
+ const requestId = crypto4.randomUUID();
53737
53735
  return new Promise((resolve6, reject) => {
53738
53736
  const onMessage = (raw) => {
53739
53737
  let f;
@@ -53990,7 +53988,7 @@ function lookupMime(filePathOrName) {
53990
53988
  }
53991
53989
 
53992
53990
  // src/attachment/sign-url.ts
53993
- var import_node_crypto7 = __toESM(require("crypto"), 1);
53991
+ var import_node_crypto6 = __toESM(require("crypto"), 1);
53994
53992
  var HMAC_ALGO = "sha256";
53995
53993
  function base64urlEncode(buf) {
53996
53994
  const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
@@ -54008,7 +54006,7 @@ function decodeAbsPathFromUrl(encoded) {
54008
54006
  var DOMAIN_PREFIX2 = "clawd-attach-v1|";
54009
54007
  function computeSig(secret, absPath, e) {
54010
54008
  const msg = e === null ? `${DOMAIN_PREFIX2}${absPath}` : `${DOMAIN_PREFIX2}${absPath}|${e}`;
54011
- return import_node_crypto7.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
54009
+ return import_node_crypto6.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
54012
54010
  }
54013
54011
  function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
54014
54012
  const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
@@ -54043,7 +54041,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
54043
54041
  if (provided.length !== expected.length) {
54044
54042
  return { ok: false, code: "BAD_SIG" };
54045
54043
  }
54046
- if (!import_node_crypto7.default.timingSafeEqual(provided, expected)) {
54044
+ if (!import_node_crypto6.default.timingSafeEqual(provided, expected)) {
54047
54045
  return { ok: false, code: "BAD_SIG" };
54048
54046
  }
54049
54047
  if (e !== null && now() / 1e3 > e) {
@@ -54055,7 +54053,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
54055
54053
  // src/attachment/upload.ts
54056
54054
  var import_node_fs30 = __toESM(require("fs"), 1);
54057
54055
  var import_node_path33 = __toESM(require("path"), 1);
54058
- var import_node_crypto8 = __toESM(require("crypto"), 1);
54056
+ var import_node_crypto7 = __toESM(require("crypto"), 1);
54059
54057
  var import_promises3 = require("stream/promises");
54060
54058
  var UploadError = class extends Error {
54061
54059
  constructor(code, message) {
@@ -54079,11 +54077,11 @@ async function writeUploadedAttachment(args) {
54079
54077
  } catch (err) {
54080
54078
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
54081
54079
  }
54082
- const hasher = import_node_crypto8.default.createHash("sha256");
54080
+ const hasher = import_node_crypto7.default.createHash("sha256");
54083
54081
  let actualSize = 0;
54084
54082
  const tmpPath = import_node_path33.default.join(
54085
54083
  attachmentsRoot,
54086
- `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
54084
+ `.upload-${process.pid}-${Date.now()}-${import_node_crypto7.default.randomBytes(4).toString("hex")}`
54087
54085
  );
54088
54086
  try {
54089
54087
  await (0, import_promises3.pipeline)(
@@ -54873,7 +54871,7 @@ function runAttachmentGc(args) {
54873
54871
  // src/attachment/group.ts
54874
54872
  var import_node_fs33 = __toESM(require("fs"), 1);
54875
54873
  var import_node_path37 = __toESM(require("path"), 1);
54876
- var import_node_crypto9 = __toESM(require("crypto"), 1);
54874
+ var import_node_crypto8 = __toESM(require("crypto"), 1);
54877
54875
  init_protocol();
54878
54876
  var GroupFileStore = class {
54879
54877
  dataDir;
@@ -54962,7 +54960,7 @@ var GroupFileStore = class {
54962
54960
  entries[idx] = next;
54963
54961
  } else {
54964
54962
  next = {
54965
- id: `gf-${import_node_crypto9.default.randomBytes(6).toString("base64url")}`,
54963
+ id: `gf-${import_node_crypto8.default.randomBytes(6).toString("base64url")}`,
54966
54964
  relPath: input.relPath,
54967
54965
  from: input.from,
54968
54966
  label: input.label,
@@ -55080,7 +55078,7 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
55080
55078
  // src/tunnel/tunnel-manager.ts
55081
55079
  var import_node_fs38 = __toESM(require("fs"), 1);
55082
55080
  var import_node_path42 = __toESM(require("path"), 1);
55083
- var import_node_crypto10 = __toESM(require("crypto"), 1);
55081
+ var import_node_crypto9 = __toESM(require("crypto"), 1);
55084
55082
  var import_node_child_process10 = require("child_process");
55085
55083
 
55086
55084
  // src/tunnel/tunnel-store.ts
@@ -55579,7 +55577,7 @@ var TunnelManager = class {
55579
55577
  override: this.deps.frpcBinaryOverride ?? void 0
55580
55578
  });
55581
55579
  const tomlPath = import_node_path42.default.join(this.deps.dataDir, "frpc.toml");
55582
- const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
55580
+ const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto9.default.randomBytes(3).toString("hex")}`;
55583
55581
  const toml = buildFrpcToml({
55584
55582
  serverAddr: t.frpsHost,
55585
55583
  serverPort: t.frpsPort,
@@ -55680,7 +55678,7 @@ async function waitForFrpcReady(proc, timeoutMs) {
55680
55678
  // src/tunnel/device-key.ts
55681
55679
  var import_node_os14 = __toESM(require("os"), 1);
55682
55680
  var import_node_path43 = __toESM(require("path"), 1);
55683
- var import_node_crypto11 = __toESM(require("crypto"), 1);
55681
+ var import_node_crypto10 = __toESM(require("crypto"), 1);
55684
55682
  var DERIVE_SALT = "clawd-tunnel-device-v1";
55685
55683
  function deriveStableDeviceKey(opts = {}) {
55686
55684
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
@@ -55690,13 +55688,13 @@ function deriveStableDeviceKey(opts = {}) {
55690
55688
  const normalizedDataDir = opts.dataDir ? import_node_path43.default.resolve(opts.dataDir) : null;
55691
55689
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
55692
55690
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
55693
- return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
55691
+ return import_node_crypto10.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
55694
55692
  }
55695
55693
 
55696
55694
  // src/auth-store.ts
55697
55695
  var import_node_fs39 = __toESM(require("fs"), 1);
55698
55696
  var import_node_path44 = __toESM(require("path"), 1);
55699
- var import_node_crypto12 = __toESM(require("crypto"), 1);
55697
+ var import_node_crypto11 = __toESM(require("crypto"), 1);
55700
55698
  var AUTH_FILE_NAME = "auth.json";
55701
55699
  function authFilePath(dataDir) {
55702
55700
  return import_node_path44.default.join(dataDir, AUTH_FILE_NAME);
@@ -55724,10 +55722,10 @@ function loadOrCreateAuthFile(opts) {
55724
55722
  return next;
55725
55723
  }
55726
55724
  function defaultGenerateToken() {
55727
- return import_node_crypto12.default.randomBytes(32).toString("base64url");
55725
+ return import_node_crypto11.default.randomBytes(32).toString("base64url");
55728
55726
  }
55729
55727
  function defaultGenerateOwnerPrincipalId() {
55730
- return `owner-${import_node_crypto12.default.randomUUID()}`;
55728
+ return `owner-${import_node_crypto11.default.randomUUID()}`;
55731
55729
  }
55732
55730
  function readAuthFile(file) {
55733
55731
  try {
@@ -55849,7 +55847,7 @@ var OwnerIdentityStore = class {
55849
55847
  };
55850
55848
 
55851
55849
  // src/feishu-auth/login-flow.ts
55852
- var import_node_crypto13 = __toESM(require("crypto"), 1);
55850
+ var import_node_crypto12 = __toESM(require("crypto"), 1);
55853
55851
  var STATE_TTL_MS = 5 * 60 * 1e3;
55854
55852
  var LoginFlow = class {
55855
55853
  constructor(deps) {
@@ -55858,7 +55856,7 @@ var LoginFlow = class {
55858
55856
  deps;
55859
55857
  pendingStates = /* @__PURE__ */ new Map();
55860
55858
  start() {
55861
- const state = import_node_crypto13.default.randomBytes(16).toString("base64url");
55859
+ const state = import_node_crypto12.default.randomBytes(16).toString("base64url");
55862
55860
  const now = (this.deps.now ?? Date.now)();
55863
55861
  this.pendingStates.set(state, now);
55864
55862
  this.gcExpired(now);
@@ -56124,7 +56122,7 @@ async function upsertDeviceBinding(opts) {
56124
56122
  }
56125
56123
 
56126
56124
  // src/feishu-auth/verify-token.ts
56127
- var crypto13 = __toESM(require("crypto"), 1);
56125
+ var crypto12 = __toESM(require("crypto"), 1);
56128
56126
  var CONNECT_TOKEN_PREFIX = "clawdtk1";
56129
56127
  function verifyConnectToken(args) {
56130
56128
  const now = args.nowSeconds ?? Math.floor(Date.now() / 1e3);
@@ -56136,7 +56134,7 @@ function verifyConnectToken(args) {
56136
56134
  const data = `${prefix}.${payloadB64}`;
56137
56135
  let signatureValid = false;
56138
56136
  try {
56139
- signatureValid = crypto13.verify(
56137
+ signatureValid = crypto12.verify(
56140
56138
  null,
56141
56139
  Buffer.from(data, "utf8"),
56142
56140
  args.publicKeyPem,
@@ -57931,7 +57929,7 @@ function computeMethodAccess(args) {
57931
57929
  }
57932
57930
 
57933
57931
  // src/version.ts
57934
- var version = "0.2.275".length > 0 ? "0.2.275" : "dev";
57932
+ var version = "0.2.277".length > 0 ? "0.2.277" : "dev";
57935
57933
 
57936
57934
  // src/cli-probe/probe.ts
57937
57935
  var fs54 = __toESM(require("fs"), 1);
@@ -58312,7 +58310,7 @@ init_protocol();
58312
58310
  // src/extension/bundle-zip.ts
58313
58311
  var import_promises6 = __toESM(require("fs/promises"), 1);
58314
58312
  var import_node_path50 = __toESM(require("path"), 1);
58315
- var import_node_crypto14 = __toESM(require("crypto"), 1);
58313
+ var import_node_crypto13 = __toESM(require("crypto"), 1);
58316
58314
  var import_jszip2 = __toESM(require_lib3(), 1);
58317
58315
  async function bundleExtensionDir(dir) {
58318
58316
  const entries = await listFilesSorted(dir);
@@ -58327,7 +58325,7 @@ async function bundleExtensionDir(dir) {
58327
58325
  compression: "DEFLATE",
58328
58326
  compressionOptions: { level: 6 }
58329
58327
  });
58330
- const sha256 = import_node_crypto14.default.createHash("sha256").update(buffer).digest("hex");
58328
+ const sha256 = import_node_crypto13.default.createHash("sha256").update(buffer).digest("hex");
58331
58329
  return { buffer, sha256 };
58332
58330
  }
58333
58331
  var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
@@ -58395,7 +58393,7 @@ function computePublishCheck(args) {
58395
58393
  var import_promises7 = __toESM(require("fs/promises"), 1);
58396
58394
  var import_node_path52 = __toESM(require("path"), 1);
58397
58395
  var import_node_os19 = __toESM(require("os"), 1);
58398
- var import_node_crypto15 = __toESM(require("crypto"), 1);
58396
+ var import_node_crypto14 = __toESM(require("crypto"), 1);
58399
58397
  var import_jszip3 = __toESM(require_lib3(), 1);
58400
58398
 
58401
58399
  // src/extension/paths.ts
@@ -58424,7 +58422,7 @@ var InstallError = class extends Error {
58424
58422
  };
58425
58423
  async function installFromChannel(args, deps) {
58426
58424
  const { channelRef, snapshotHash, bundleZip } = args;
58427
- const computed = import_node_crypto15.default.createHash("sha256").update(bundleZip).digest("hex");
58425
+ const computed = import_node_crypto14.default.createHash("sha256").update(bundleZip).digest("hex");
58428
58426
  if (computed !== snapshotHash) {
58429
58427
  throw new InstallError(
58430
58428
  "HASH_MISMATCH",
@@ -58516,7 +58514,7 @@ async function installFromChannel(args, deps) {
58516
58514
  var import_promises8 = __toESM(require("fs/promises"), 1);
58517
58515
  var import_node_path53 = __toESM(require("path"), 1);
58518
58516
  var import_node_os20 = __toESM(require("os"), 1);
58519
- var import_node_crypto16 = __toESM(require("crypto"), 1);
58517
+ var import_node_crypto15 = __toESM(require("crypto"), 1);
58520
58518
  var import_jszip4 = __toESM(require_lib3(), 1);
58521
58519
  var UpdateError = class extends Error {
58522
58520
  constructor(code, message) {
@@ -58554,7 +58552,7 @@ async function updateFromChannel(args, deps) {
58554
58552
  if (e instanceof UpdateError) throw e;
58555
58553
  throw e;
58556
58554
  }
58557
- const computed = import_node_crypto16.default.createHash("sha256").update(bundleZip).digest("hex");
58555
+ const computed = import_node_crypto15.default.createHash("sha256").update(bundleZip).digest("hex");
58558
58556
  if (computed !== snapshotHash) {
58559
58557
  throw new UpdateError(
58560
58558
  "HASH_MISMATCH",
@@ -59220,7 +59218,7 @@ function listPidsOnPort(port) {
59220
59218
  }
59221
59219
 
59222
59220
  // src/app-builder/publish-registry.ts
59223
- var import_node_crypto17 = require("crypto");
59221
+ var import_node_crypto16 = require("crypto");
59224
59222
  var PublishJobRegistry = class {
59225
59223
  jobs = /* @__PURE__ */ new Map();
59226
59224
  has(name) {
@@ -59237,7 +59235,7 @@ var PublishJobRegistry = class {
59237
59235
  if (this.jobs.has(args.name)) {
59238
59236
  throw new Error(`already publishing: ${args.name}`);
59239
59237
  }
59240
- const jobId = args.jobId ?? `job-${(0, import_node_crypto17.randomUUID)()}`;
59238
+ const jobId = args.jobId ?? `job-${(0, import_node_crypto16.randomUUID)()}`;
59241
59239
  this.jobs.set(args.name, {
59242
59240
  jobId,
59243
59241
  name: args.name,
@@ -60180,7 +60178,7 @@ async function uninstall(deps) {
60180
60178
  }
60181
60179
 
60182
60180
  // src/handlers/index.ts
60183
- var import_node_crypto18 = require("crypto");
60181
+ var import_node_crypto17 = require("crypto");
60184
60182
 
60185
60183
  // src/handlers/peer-exec.ts
60186
60184
  init_protocol();
@@ -60335,7 +60333,7 @@ function buildMethodHandlers(deps) {
60335
60333
  const c = deps.contactStore.get(deviceId);
60336
60334
  return c ? { deviceId: c.deviceId, remoteUrl: c.remoteUrl, connectToken: c.connectToken } : null;
60337
60335
  },
60338
- genId: () => (0, import_node_crypto18.randomUUID)(),
60336
+ genId: () => (0, import_node_crypto17.randomUUID)(),
60339
60337
  now: () => Date.now(),
60340
60338
  forwardInboxPostToPeer,
60341
60339
  logger: deps.logger
@@ -21852,6 +21852,11 @@ var PersonaInfoResponseSchema = PersonaFileSchema.extend({
21852
21852
  sandboxSettings: PersonaSandboxSettingsSchema.nullable().optional()
21853
21853
  });
21854
21854
  var PersonaCreateArgsSchema = external_exports.object({
21855
+ // persona 身份。daemon 拼成 personaId = `persona-<slug>`——前缀由 daemon 拥有,调用方只给后半段,
21856
+ // 「所有 persona id 带该前缀」的约定由构造保证。与 label(显示名,可中文、可随时改)是两个概念:
21857
+ // 曾经只有 label、id 从 label 推,导致中文 label 被剥空后一律降级成 persona-persona。
21858
+ // 正则即安全边界——该值直接落进 ~/.clawd/personas/<id>/,此处排除 . / 空格后路径穿越无从构造。
21859
+ slug: external_exports.string().regex(/^[a-z0-9]+(-[a-z0-9]+)*$/).max(32),
21855
21860
  label: external_exports.string().min(1),
21856
21861
  personality: external_exports.string(),
21857
21862
  model: external_exports.string().optional(),
@@ -23095,7 +23100,7 @@ var METHOD_DOCS = {
23095
23100
  args: CapabilitiesGetArgs
23096
23101
  },
23097
23102
  "persona:create": {
23098
- summary: "\u65B0\u5EFA persona\uFF08\u5199 PersonaFile + CLAUDE.md \u9AA8\u67B6\uFF09\u3002owner-only",
23103
+ summary: "\u65B0\u5EFA persona\uFF08\u5199 PersonaFile + CLAUDE.md \u9AA8\u67B6\uFF09\u3002owner-only\u3002slug \u53EA\u6536\u5C0F\u5199\u5B57\u6BCD\u6570\u5B57\u4E0E\u5355\u8FDE\u5B57\u7B26\uFF08^[a-z0-9]+(-[a-z0-9]+)*$\uFF0C\u226432\uFF09\uFF0Cdaemon \u62FC\u6210 personaId=persona-<slug>\uFF1B\u8BE5 id \u5DF2\u5B58\u5728\u5219\u62A5\u9519\uFF0C\u4E0D\u81EA\u52A8\u6539\u540D\u3002label \u662F\u663E\u793A\u540D\uFF0C\u4E0D\u53C2\u4E0E id \u63A8\u5BFC\uFF0C\u53EF\u7528\u4E2D\u6587",
23099
23104
  args: PersonaCreateArgsSchema
23100
23105
  },
23101
23106
  "persona:list": {