@clawos-dev/clawd 0.2.187-beta.372.beee855 → 0.2.187-beta.373.fba4299

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
@@ -157,7 +157,8 @@ var init_methods = __esm({
157
157
  // 写入路径:device:connect 落 store + 自动反向(决策 #11);list / remove 作联系人列表读删。
158
158
  "contact:list",
159
159
  "contact:remove",
160
- // ---- visitor:* (web 访客 · persona web 分享,spec 2026-06-24-persona-web-share-design) ----
160
+ "contact:set-note",
161
+ // ---- visitor:*(web 访客 · persona web 分享,spec 2026-06-24-persona-web-share-design) ----
161
162
  // owner-only:列出登录访问过本机 public persona 的 web 访客(零安装、飞书登录、daemon 自签
162
163
  // visitor token)。存储 ~/.clawd/visitors.json(VisitorStore),登录(exchange)即 upsert;
163
164
  // 访客身份用 TTC unique_id,会话按 creatorPrincipalId='visitor-<id>' 进现有会话用户分组。
@@ -5630,7 +5631,7 @@ var init_inbox = __esm({
5630
5631
  });
5631
5632
 
5632
5633
  // ../protocol/src/contact.ts
5633
- var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema;
5634
+ var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema, ContactSetNoteArgsSchema, ContactSetNoteOkSchema;
5634
5635
  var init_contact = __esm({
5635
5636
  "../protocol/src/contact.ts"() {
5636
5637
  "use strict";
@@ -5659,7 +5660,12 @@ var init_contact = __esm({
5659
5660
  // 不用 .min(1):自动反向路径合法地存空串,禁止填假 token 占位(不造假数据)。
5660
5661
  connectToken: external_exports.string(),
5661
5662
  grants: external_exports.array(GrantSchema),
5662
- addedAt: external_exports.number().int().nonnegative()
5663
+ addedAt: external_exports.number().int().nonnegative(),
5664
+ /**
5665
+ * 本机私有备注(≤20 字):owner 给该联系人加的标注,只存本机、不分享给对方。
5666
+ * optional——老 contacts.json 记录无此字段,禁止必填(否则 strict parse 失败 orphan 全部联系人)。
5667
+ */
5668
+ note: external_exports.string().max(20).optional()
5663
5669
  }).strict();
5664
5670
  ContactWireSchema = ContactSchema;
5665
5671
  ContactRemoveArgsSchema = external_exports.object({
@@ -5681,6 +5687,15 @@ var init_contact = __esm({
5681
5687
  type: external_exports.literal("contact:removed"),
5682
5688
  deviceId: external_exports.string().min(1)
5683
5689
  }).strict();
5690
+ ContactSetNoteArgsSchema = external_exports.object({
5691
+ deviceId: external_exports.string().min(1),
5692
+ note: external_exports.string().max(20)
5693
+ }).strict();
5694
+ ContactSetNoteOkSchema = external_exports.object({
5695
+ type: external_exports.literal("contact:set-note:ok"),
5696
+ deviceId: external_exports.string().min(1),
5697
+ note: external_exports.string().max(20)
5698
+ }).strict();
5684
5699
  }
5685
5700
  });
5686
5701
 
@@ -48858,24 +48873,8 @@ var SessionObserver = class {
48858
48873
  return import_node_path21.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
48859
48874
  }
48860
48875
  start(args) {
48876
+ this.stop(args.sessionId);
48861
48877
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
48862
- const existing = this.watches.get(args.sessionId);
48863
- if (existing && existing.filePath === filePath) {
48864
- this.opts.logger?.info("observer.start no-op", {
48865
- sessionId: args.sessionId,
48866
- filePath,
48867
- reason: "already-watching-same-file"
48868
- });
48869
- return { filePath };
48870
- }
48871
- if (existing) {
48872
- this.stop(args.sessionId, "file-changed");
48873
- }
48874
- this.opts.logger?.info("observer.start", {
48875
- sessionId: args.sessionId,
48876
- filePath,
48877
- reason: existing ? "file-changed" : "first-attach"
48878
- });
48879
48878
  let size = 0;
48880
48879
  try {
48881
48880
  size = import_node_fs23.default.statSync(filePath).size;
@@ -49022,7 +49021,7 @@ var SessionObserver = class {
49022
49021
  isObserving(sessionId) {
49023
49022
  return this.watches.has(sessionId);
49024
49023
  }
49025
- stop(sessionId, reason = "session-delete") {
49024
+ stop(sessionId) {
49026
49025
  const w2 = this.watches.get(sessionId);
49027
49026
  if (!w2) return false;
49028
49027
  try {
@@ -49033,11 +49032,6 @@ var SessionObserver = class {
49033
49032
  this.watches.delete(sessionId);
49034
49033
  this.metaObserver?.stop(sessionId);
49035
49034
  this.opts.onStatus?.(sessionId, "stopped");
49036
- this.opts.logger?.info("observer.stop", {
49037
- sessionId,
49038
- filePath: w2.filePath,
49039
- reason
49040
- });
49041
49035
  return true;
49042
49036
  }
49043
49037
  stopAll() {
@@ -50195,6 +50189,21 @@ var ContactStore = class {
50195
50189
  this.contacts.set(contact.deviceId, contact);
50196
50190
  this.flush();
50197
50191
  }
50192
+ /**
50193
+ * 设/改/清空单台设备的本机私有备注(决策:本机私有标注,只存本机不分享)。
50194
+ * 命中返回更新后的 contact 并 flush;note 空串则删除 note 字段(保持 contacts.json 干净);
50195
+ * 未命中返回 null(不写盘)。
50196
+ */
50197
+ setNote(deviceId, note) {
50198
+ const existing = this.contacts.get(deviceId);
50199
+ if (!existing) return null;
50200
+ const next = { ...existing };
50201
+ if (note) next.note = note;
50202
+ else delete next.note;
50203
+ this.contacts.set(deviceId, next);
50204
+ this.flush();
50205
+ return next;
50206
+ }
50198
50207
  /** 删单台设备(contact:remove 语义,决策 #16):删该 deviceId 一条,返回是否删到 */
50199
50208
  removeByDeviceId(deviceId) {
50200
50209
  const existed = this.contacts.delete(deviceId);
@@ -53030,7 +53039,7 @@ function buildSessionHandlers(deps) {
53030
53039
  const newSession = async (frame, _client, ctx) => {
53031
53040
  const args = SessionIdArgs.parse(frame);
53032
53041
  ensureSessionAccess(ctx, args.sessionId, "send");
53033
- observer.stop(args.sessionId, "session-delete");
53042
+ observer.stop(args.sessionId);
53034
53043
  const { response, broadcast } = manager.newSession(args);
53035
53044
  return { response: { type: "session:info", ...response }, broadcast };
53036
53045
  };
@@ -53781,9 +53790,30 @@ function buildContactHandlers(deps) {
53781
53790
  }
53782
53791
  };
53783
53792
  };
53793
+ const setNote = async (frame, _client, ctx) => {
53794
+ ensureOwner(ctx);
53795
+ const { type: _t, requestId: _r, ...rest } = frame;
53796
+ const args = ContactSetNoteArgsSchema.parse(rest);
53797
+ const updated = deps.store.setNote(args.deviceId, args.note);
53798
+ if (!updated) {
53799
+ throw new ClawdError(
53800
+ ERROR_CODES.INVALID_PARAM,
53801
+ `INVALID_PARAM: contact ${args.deviceId} \u4E0D\u5B58\u5728`
53802
+ );
53803
+ }
53804
+ deps.broadcast({ type: "contact:added", contact: updated });
53805
+ return {
53806
+ response: {
53807
+ type: "contact:set-note:ok",
53808
+ deviceId: args.deviceId,
53809
+ note: args.note
53810
+ }
53811
+ };
53812
+ };
53784
53813
  return {
53785
53814
  "contact:list": list,
53786
- "contact:remove": remove
53815
+ "contact:remove": remove,
53816
+ "contact:set-note": setNote
53787
53817
  };
53788
53818
  }
53789
53819
 
@@ -56574,6 +56604,7 @@ var METHOD_GRANT_MAP = {
56574
56604
  // 写入路径在 device:connect / 自动反向;list / remove 作联系人读 / 删,owner-only。
56575
56605
  "contact:list": ADMIN_ANY,
56576
56606
  "contact:remove": ADMIN_ANY,
56607
+ "contact:set-note": ADMIN_ANY,
56577
56608
  // ---- visitor:* (访客名单,owner-only) ----
56578
56609
  // owner 看完整访客名单(含没开会话的);guest 不可调(handler 内再 assertOwner 兜底)。
56579
56610
  "visitor:list": ADMIN_ANY,
@@ -57482,9 +57513,7 @@ async function startDaemon(config) {
57482
57513
  // daemon 内部转译,UI 看到的始终是 events 流里的 synth uuid(详见 manager 注释)
57483
57514
  onUserMessageObserved: (sessionId, realUuid, text) => {
57484
57515
  manager.recordRealUserUuid({ sessionId, realUuid, text });
57485
- },
57486
- // 永久取证 log:observer.start / start no-op / stop(spec 2026-06-26-observer-restart-fix §3.3)
57487
- logger
57516
+ }
57488
57517
  });
57489
57518
  manager.attachObserver(observer);
57490
57519
  const claudeAdapter = config.mode === "tui" ? new ClaudeTuiAdapter({