@clawos-dev/clawd 0.2.355 → 0.2.356

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +38 -25
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -5924,12 +5924,13 @@ var init_capability = __esm({
5924
5924
  });
5925
5925
 
5926
5926
  // ../protocol/src/contact-handshake.ts
5927
- var ContactHandshakeArgsSchema, ContactHandshakeOkSchema;
5927
+ var PEER_LOGIN_EXPIRED_ERROR_MARKER, ContactHandshakeArgsSchema, ContactHandshakeOkSchema;
5928
5928
  var init_contact_handshake = __esm({
5929
5929
  "../protocol/src/contact-handshake.ts"() {
5930
5930
  "use strict";
5931
5931
  init_zod();
5932
5932
  init_capability();
5933
+ PEER_LOGIN_EXPIRED_ERROR_MARKER = "PEER_LOGIN_EXPIRED";
5933
5934
  ContactHandshakeArgsSchema = external_exports.object({
5934
5935
  selfUrl: external_exports.string().min(1)
5935
5936
  });
@@ -59777,7 +59778,7 @@ function upsertPeerContact(args) {
59777
59778
  provider: args.provider,
59778
59779
  displayName: args.displayName,
59779
59780
  remoteUrl: args.selfUrl,
59780
- connectToken: "",
59781
+ connectToken: args.connectToken,
59781
59782
  grants,
59782
59783
  addedAt: now(),
59783
59784
  pinnedAt: existing?.pinnedAt ?? null,
@@ -59787,17 +59788,6 @@ function upsertPeerContact(args) {
59787
59788
  args.broadcast({ type: "contact:added", contact: base });
59788
59789
  return base;
59789
59790
  }
59790
- async function backfillConnectToken(args) {
59791
- try {
59792
- const token = await args.exchangeToken(args.contact.deviceId);
59793
- if (!token) return;
59794
- const upgraded = { ...args.contact, connectToken: token };
59795
- args.store.upsert(upgraded);
59796
- args.broadcast({ type: "contact:added", contact: upgraded });
59797
- } catch {
59798
- return;
59799
- }
59800
- }
59801
59791
 
59802
59792
  // src/handlers/contact.ts
59803
59793
  function ensureOwner(ctx) {
@@ -59865,7 +59855,22 @@ function buildContactHandlers(deps) {
59865
59855
  );
59866
59856
  }
59867
59857
  const args = parseArgs2(ContactHandshakeArgsSchema, frame, "contact:handshake");
59868
- const contact = upsertPeerContact({
59858
+ let token;
59859
+ try {
59860
+ token = await deps.exchangeToken(ctx.principal.id);
59861
+ } catch (e) {
59862
+ throw new ClawdError(
59863
+ ERROR_CODES.INTERNAL,
59864
+ `TOKEN_EXCHANGE_FAILED: \u6362\u7968\u5931\u8D25\uFF08${e.message}\uFF09\uFF0C\u7A0D\u540E\u91CD\u8BD5`
59865
+ );
59866
+ }
59867
+ if (!token) {
59868
+ throw new ClawdError(
59869
+ ERROR_CODES.VALIDATION_ERROR,
59870
+ `${PEER_LOGIN_EXPIRED_ERROR_MARKER}: \u672C\u673A\u767B\u5F55\u6001\u7F3A\u5931\u6216\u5DF2\u8FC7\u671F\uFF0C\u65E0\u6CD5\u5B8C\u6210\u5EFA\u8054`
59871
+ );
59872
+ }
59873
+ upsertPeerContact({
59869
59874
  store: deps.store,
59870
59875
  broadcast: deps.broadcast,
59871
59876
  deviceId: ctx.principal.id,
@@ -59873,14 +59878,9 @@ function buildContactHandlers(deps) {
59873
59878
  provider: ctx.provider ?? "",
59874
59879
  displayName: ctx.principal.displayName ?? ctx.principal.id,
59875
59880
  selfUrl: args.selfUrl,
59881
+ connectToken: token,
59876
59882
  now: deps.now
59877
59883
  });
59878
- void backfillConnectToken({
59879
- store: deps.store,
59880
- broadcast: deps.broadcast,
59881
- contact,
59882
- exchangeToken: deps.exchangeToken
59883
- });
59884
59884
  const identity = deps.getOwnerIdentity();
59885
59885
  return {
59886
59886
  response: {
@@ -60113,6 +60113,12 @@ function buildDeviceHandlers(deps) {
60113
60113
  "REVERSE_UNSUPPORTED: \u5BF9\u65B9 clawd \u7248\u672C\u8FC7\u65E7\uFF0C\u8BF7\u8BA9\u5BF9\u65B9\u5347\u7EA7\u540E\u91CD\u8BD5"
60114
60114
  );
60115
60115
  }
60116
+ if (msg.includes(PEER_LOGIN_EXPIRED_ERROR_MARKER)) {
60117
+ throw new ClawdError(
60118
+ ERROR_CODES.VALIDATION_ERROR,
60119
+ `${PEER_LOGIN_EXPIRED_ERROR_MARKER}: \u5BF9\u65B9\u8BBE\u5907\u767B\u5F55\u5DF2\u8FC7\u671F\u6216\u672A\u767B\u5F55\uFF0C\u8BF7\u5BF9\u65B9\u5728 clawd \u91CD\u65B0\u767B\u5F55\u540E\u518D\u8BD5`
60120
+ );
60121
+ }
60116
60122
  throw e;
60117
60123
  }
60118
60124
  const existing = deps.store.get(args.deviceId) ?? void 0;
@@ -60429,7 +60435,7 @@ function computeMethodAccess(args) {
60429
60435
  }
60430
60436
 
60431
60437
  // src/version.ts
60432
- var version = "0.2.355".length > 0 ? "0.2.355" : "dev";
60438
+ var version = "0.2.356".length > 0 ? "0.2.356" : "dev";
60433
60439
 
60434
60440
  // src/cli-probe/probe.ts
60435
60441
  var fs60 = __toESM(require("fs"), 1);
@@ -64613,8 +64619,10 @@ async function startDaemon(config) {
64613
64619
  inboxStore,
64614
64620
  // 联系人列表 store(device:connect 出站 / contact:handshake 入站落同一 store)
64615
64621
  contactStore,
64616
- // contact:handshake 换票回填(spec 2026-07-22):用 owner 当前 jwt 换 aud=对方设备 的票。
64617
- // 现读 ownerIdentityStore(热切换后用新身份);失败 / 未登录 null 保持空票。
64622
+ // contact:handshake 换票(spec 2026-07-22;2026-08-17 起硬失败,不再是回填):
64623
+ // owner 当前 jwt aud=对方设备 的票,现读 ownerIdentityStore(热切换后用新身份)。
64624
+ // 契约(ContactHandlerDeps.exchangeToken):null = 本机登录问题(未登录 / JWT 过期),
64625
+ // 其他失败原样抛给 handler——两种都会让握手硬失败,只是给对端的错误文案不同。
64618
64626
  exchangeToken: async (targetDeviceId) => {
64619
64627
  const record = ownerIdentityStore.read();
64620
64628
  if (!record) return null;
@@ -64624,7 +64632,11 @@ async function startDaemon(config) {
64624
64632
  jwt: record.ttcToken,
64625
64633
  provider: record.identity.provider,
64626
64634
  deviceId: targetDeviceId,
64627
- selfDeviceId: authFile.deviceId
64635
+ selfDeviceId: authFile.deviceId,
64636
+ // 换票在握手关键路径上(硬失败),对端 connect-remote RPC_TIMEOUT_MS=5s:
64637
+ // 必须在其内失败/成功,否则对端先超时不落库、本机后换票成功落库 → 反向半连,
64638
+ // 破坏「两侧都不落库」不变量。4s 留 1s 余量给 ws 往返
64639
+ timeoutMs: 4e3
64628
64640
  });
64629
64641
  return r.token;
64630
64642
  } catch (e) {
@@ -64632,7 +64644,8 @@ async function startDaemon(config) {
64632
64644
  targetDeviceId,
64633
64645
  err: e.message
64634
64646
  });
64635
- return null;
64647
+ if (e instanceof CentralClientError && e.code === "UNAUTHORIZED") return null;
64648
+ throw e;
64636
64649
  }
64637
64650
  },
64638
64651
  // inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.355",
3
+ "version": "0.2.356",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",