@clawos-dev/clawd 0.2.193 → 0.2.194-beta.391.a419f09

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
@@ -156,6 +156,7 @@ var init_methods = __esm({
156
156
  // 联系人身份由中心 server introspect 背书,不再是"对方颁发的 capability"。
157
157
  // 写入路径:device:connect 落 store + 自动反向(决策 #11);list / remove 作联系人列表读删。
158
158
  "contact:list",
159
+ "contact:pin",
159
160
  "contact:remove",
160
161
  // ---- visitor:* (web 访客 · persona web 分享,spec 2026-06-24-persona-web-share-design) ----
161
162
  // owner-only:列出登录访问过本机 public persona 的 web 访客(零安装、飞书登录、daemon 自签
@@ -304,7 +305,9 @@ var init_errors = __esm({
304
305
  // app-builder 单栏默认 refactor (spec 2026-06-02-app-builder-single-pane-default-design):
305
306
  // appBuilder:createProject 加 personaId + session 未绑校验后抛的两个错码。
306
307
  WRONG_PERSONA: "WRONG_PERSONA",
307
- SESSION_ALREADY_BOUND: "SESSION_ALREADY_BOUND"
308
+ SESSION_ALREADY_BOUND: "SESSION_ALREADY_BOUND",
309
+ // 2026-07-02 unified people sidebar: contact:pin 时 deviceId 不在 store(可能被别处删了)
310
+ CONTACT_NOT_FOUND: "CONTACT_NOT_FOUND"
308
311
  };
309
312
  ClawdError = class extends Error {
310
313
  constructor(code, message) {
@@ -5640,7 +5643,7 @@ var init_inbox = __esm({
5640
5643
  });
5641
5644
 
5642
5645
  // ../protocol/src/contact.ts
5643
- var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema;
5646
+ var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema, ContactPinArgsSchema, ContactPinOkSchema, ContactPinnedFrameSchema;
5644
5647
  var init_contact = __esm({
5645
5648
  "../protocol/src/contact.ts"() {
5646
5649
  "use strict";
@@ -5669,7 +5672,13 @@ var init_contact = __esm({
5669
5672
  // 不用 .min(1):自动反向路径合法地存空串,禁止填假 token 占位(不造假数据)。
5670
5673
  connectToken: external_exports.string(),
5671
5674
  grants: external_exports.array(GrantSchema),
5672
- addedAt: external_exports.number().int().nonnegative()
5675
+ addedAt: external_exports.number().int().nonnegative(),
5676
+ /**
5677
+ * pin 时间戳(ms,Date.now() 语义);null = 未 pin。sidebar 顶部固定区渲染由此驱动。
5678
+ * 老 contacts.json 缺此字段 → zod default 补 null(无破坏性升级;不 orphan)。
5679
+ * 对齐 SessionFile.pinnedAt 语义(daemon 侧持久化,contact:pin RPC 更新 → contact:pinned push)。
5680
+ */
5681
+ pinnedAt: external_exports.number().int().nullable().default(null)
5673
5682
  }).strict();
5674
5683
  ContactWireSchema = ContactSchema;
5675
5684
  ContactRemoveArgsSchema = external_exports.object({
@@ -5691,6 +5700,20 @@ var init_contact = __esm({
5691
5700
  type: external_exports.literal("contact:removed"),
5692
5701
  deviceId: external_exports.string().min(1)
5693
5702
  }).strict();
5703
+ ContactPinArgsSchema = external_exports.object({
5704
+ deviceId: external_exports.string().min(1),
5705
+ pinned: external_exports.boolean()
5706
+ }).strict();
5707
+ ContactPinOkSchema = external_exports.object({
5708
+ type: external_exports.literal("contact:pin:ok"),
5709
+ deviceId: external_exports.string().min(1),
5710
+ pinnedAt: external_exports.number().int().nullable()
5711
+ }).strict();
5712
+ ContactPinnedFrameSchema = external_exports.object({
5713
+ type: external_exports.literal("contact:pinned"),
5714
+ deviceId: external_exports.string().min(1),
5715
+ pinnedAt: external_exports.number().int().nullable()
5716
+ }).strict();
5694
5717
  }
5695
5718
  });
5696
5719
 
@@ -50314,6 +50337,18 @@ var ContactStore = class {
50314
50337
  if (existed) this.flush();
50315
50338
  return existed;
50316
50339
  }
50340
+ /**
50341
+ * 更新单条 contact 的 pinnedAt(对齐 session:pin pattern,2026-07-02 unified people sidebar)。
50342
+ * @param pinnedAt null = 未 pin;number = pin 时间戳(daemon 侧 Date.now())
50343
+ * @returns 是否命中:deviceId 不存在返 false,调用方按需 error/broadcast;命中即 flush。
50344
+ */
50345
+ setPin(deviceId, pinnedAt) {
50346
+ const existing = this.contacts.get(deviceId);
50347
+ if (!existing) return false;
50348
+ this.contacts.set(deviceId, { ...existing, pinnedAt });
50349
+ this.flush();
50350
+ return true;
50351
+ }
50317
50352
  flush() {
50318
50353
  const file = path30.join(this.dataDir, FILE_NAME);
50319
50354
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
@@ -50460,7 +50495,8 @@ async function autoReverseContact(args) {
50460
50495
  remoteUrl: args.selfUrl,
50461
50496
  connectToken: "",
50462
50497
  grants,
50463
- addedAt: now()
50498
+ addedAt: now(),
50499
+ pinnedAt: null
50464
50500
  };
50465
50501
  args.store.upsert(base);
50466
50502
  args.broadcast({ type: "contact:added", contact: base });
@@ -53975,6 +54011,31 @@ function buildContactHandlers(deps) {
53975
54011
  }
53976
54012
  };
53977
54013
  };
54014
+ const pin = async (frame, _client, ctx) => {
54015
+ ensureOwner(ctx);
54016
+ const { type: _t, requestId: _r, ...rest } = frame;
54017
+ const args = ContactPinArgsSchema.parse(rest);
54018
+ const pinnedAt = args.pinned ? deps.now() : null;
54019
+ const hit = deps.store.setPin(args.deviceId, pinnedAt);
54020
+ if (!hit) {
54021
+ throw new ClawdError(
54022
+ ERROR_CODES.CONTACT_NOT_FOUND,
54023
+ `CONTACT_NOT_FOUND: contact ${args.deviceId} not in store`
54024
+ );
54025
+ }
54026
+ deps.broadcast({
54027
+ type: "contact:pinned",
54028
+ deviceId: args.deviceId,
54029
+ pinnedAt
54030
+ });
54031
+ return {
54032
+ response: {
54033
+ type: "contact:pin:ok",
54034
+ deviceId: args.deviceId,
54035
+ pinnedAt
54036
+ }
54037
+ };
54038
+ };
53978
54039
  const remove = async (frame, _client, ctx) => {
53979
54040
  ensureOwner(ctx);
53980
54041
  const { type: _t, requestId: _r, ...rest } = frame;
@@ -53993,6 +54054,7 @@ function buildContactHandlers(deps) {
53993
54054
  };
53994
54055
  return {
53995
54056
  "contact:list": list,
54057
+ "contact:pin": pin,
53996
54058
  "contact:remove": remove
53997
54059
  };
53998
54060
  }
@@ -54149,7 +54211,8 @@ function buildDeviceHandlers(deps) {
54149
54211
  // 过期后对方拒 TOKEN_EXPIRED → 重新 device:connect 换新票)
54150
54212
  connectToken: exchanged.token,
54151
54213
  grants: wh.grants,
54152
- addedAt: now()
54214
+ addedAt: now(),
54215
+ pinnedAt: null
54153
54216
  };
54154
54217
  deps.store.upsert(contact);
54155
54218
  deps.broadcast({ type: "contact:added", contact });
@@ -56461,7 +56524,8 @@ function buildMethodHandlers(deps) {
56461
56524
  }),
56462
56525
  ...buildContactHandlers({
56463
56526
  store: deps.contactStore,
56464
- broadcast: deps.broadcastToOwners
56527
+ broadcast: deps.broadcastToOwners,
56528
+ now: () => Date.now()
56465
56529
  }),
56466
56530
  whoami: buildWhoamiHandler({
56467
56531
  ownerDisplayName: deps.ownerDisplayName,
@@ -56796,6 +56860,7 @@ var METHOD_GRANT_MAP = {
56796
56860
  // 飞书统一身份 Phase 3 (决策 #14): received-capability:* 正名 contact:*。
56797
56861
  // 写入路径在 device:connect / 自动反向;list / remove 作联系人读 / 删,owner-only。
56798
56862
  "contact:list": ADMIN_ANY,
56863
+ "contact:pin": ADMIN_ANY,
56799
56864
  "contact:remove": ADMIN_ANY,
56800
56865
  // ---- visitor:* (访客名单,owner-only) ----
56801
56866
  // owner 看完整访客名单(含没开会话的);guest 不可调(handler 内再 assertOwner 兜底)。