@awebai/claude-channel 1.3.2 → 1.4.0

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aweb-channel",
3
3
  "description": "aweb agent coordination channel — receive mail, chat, tasks, and control signals from your agent team in real time.",
4
- "version": "1.3.2",
4
+ "version": "1.4.0",
5
5
  "author": {
6
6
  "name": "awebai"
7
7
  },
package/dist/index.js CHANGED
@@ -25460,6 +25460,7 @@ function canonicalJSON(env) {
25460
25460
  ["type", env.type]
25461
25461
  ];
25462
25462
  if (env.from_stable_id) fields.push(["from_stable_id", env.from_stable_id]);
25463
+ if (env.conversation_id) fields.push(["conversation_id", env.conversation_id]);
25463
25464
  if (env.message_id) fields.push(["message_id", env.message_id]);
25464
25465
  if (env.to_stable_id) fields.push(["to_stable_id", env.to_stable_id]);
25465
25466
  fields.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
@@ -25572,6 +25573,20 @@ async function verifySignedPayload(signedPayload, signatureB64, fromDID, signing
25572
25573
  );
25573
25574
  return valid ? "verified" : "failed";
25574
25575
  }
25576
+ function signedPayloadConversationStatus(signedPayload, conversationID) {
25577
+ const expected = (conversationID || "").trim();
25578
+ if (!expected) return "verified";
25579
+ try {
25580
+ const payload = JSON.parse(signedPayload);
25581
+ if (payload.conversation_id === expected) return "verified";
25582
+ if (payload.conversation_id === void 0 || payload.conversation_id === "") {
25583
+ return "verified_legacy";
25584
+ }
25585
+ return "failed";
25586
+ } catch {
25587
+ return "failed";
25588
+ }
25589
+ }
25575
25590
 
25576
25591
  // src/api/mail.ts
25577
25592
  async function fetchInbox(client, unreadOnly = true, limit = 50, messageID) {
@@ -25595,6 +25610,9 @@ function hydrateAddressesFromSignedPayload(msg) {
25595
25610
  if (typeof payload.from_did === "string" && payload.from_did.trim()) {
25596
25611
  msg.from_did = payload.from_did;
25597
25612
  }
25613
+ if (typeof payload.from === "string" && payload.from.trim()) {
25614
+ msg.signed_from = payload.from;
25615
+ }
25598
25616
  if (typeof payload.to_did === "string" && payload.to_did.trim()) {
25599
25617
  msg.to_did = payload.to_did;
25600
25618
  }
@@ -25604,11 +25622,8 @@ function hydrateAddressesFromSignedPayload(msg) {
25604
25622
  if (!msg.to_stable_id && typeof payload.to_stable_id === "string") {
25605
25623
  msg.to_stable_id = payload.to_stable_id;
25606
25624
  }
25607
- if (!msg.from_address && typeof payload.from === "string") {
25608
- msg.from_address = payload.from;
25609
- }
25610
- if (!msg.to_address && typeof payload.to === "string") {
25611
- msg.to_address = payload.to;
25625
+ if (!msg.conversation_id && typeof payload.conversation_id === "string") {
25626
+ msg.conversation_id = payload.conversation_id;
25612
25627
  }
25613
25628
  } catch {
25614
25629
  }
@@ -25618,12 +25633,14 @@ async function ackMessage(client, messageId) {
25618
25633
  }
25619
25634
  async function verifyInboxMessage(msg) {
25620
25635
  if (msg.signed_payload && msg.signature && msg.from_did) {
25621
- return verifySignedPayload(
25636
+ const status2 = await verifySignedPayload(
25622
25637
  msg.signed_payload,
25623
25638
  msg.signature,
25624
25639
  msg.from_did,
25625
25640
  msg.signing_key_id || ""
25626
25641
  );
25642
+ if (status2 !== "verified") return status2;
25643
+ return signedPayloadConversationStatus(msg.signed_payload, msg.conversation_id);
25627
25644
  }
25628
25645
  const from = msg.from_address || msg.from_alias;
25629
25646
  const to = msg.to_address || msg.to_alias || "";
@@ -25639,10 +25656,16 @@ async function verifyInboxMessage(msg) {
25639
25656
  from_stable_id: msg.from_stable_id,
25640
25657
  to_stable_id: msg.to_stable_id,
25641
25658
  message_id: msg.message_id,
25659
+ conversation_id: msg.conversation_id,
25642
25660
  signature: msg.signature,
25643
25661
  signing_key_id: msg.signing_key_id
25644
25662
  };
25645
- return verifyMessage(env);
25663
+ const status = await verifyMessage(env);
25664
+ if (status === "failed" && msg.conversation_id) {
25665
+ const legacyStatus = await verifyMessage({ ...env, conversation_id: void 0 });
25666
+ return legacyStatus === "verified" ? "verified_legacy" : legacyStatus;
25667
+ }
25668
+ return status;
25646
25669
  }
25647
25670
 
25648
25671
  // src/api/chat.ts
@@ -25667,6 +25690,9 @@ function hydrateAddressesFromSignedPayload2(msg) {
25667
25690
  if (typeof payload.from_did === "string" && payload.from_did.trim()) {
25668
25691
  msg.from_did = payload.from_did;
25669
25692
  }
25693
+ if (typeof payload.from === "string" && payload.from.trim()) {
25694
+ msg.signed_from = payload.from;
25695
+ }
25670
25696
  if (typeof payload.to_did === "string" && payload.to_did.trim()) {
25671
25697
  msg.to_did = payload.to_did;
25672
25698
  }
@@ -25676,11 +25702,8 @@ function hydrateAddressesFromSignedPayload2(msg) {
25676
25702
  if (!msg.to_stable_id && typeof payload.to_stable_id === "string") {
25677
25703
  msg.to_stable_id = payload.to_stable_id;
25678
25704
  }
25679
- if (!msg.from_address && typeof payload.from === "string") {
25680
- msg.from_address = payload.from;
25681
- }
25682
- if (!msg.to_address && typeof payload.to === "string") {
25683
- msg.to_address = payload.to;
25705
+ if (!msg.conversation_id && typeof payload.conversation_id === "string") {
25706
+ msg.conversation_id = payload.conversation_id;
25684
25707
  }
25685
25708
  } catch {
25686
25709
  }
@@ -25693,12 +25716,14 @@ async function markRead(client, sessionId, upToMessageId) {
25693
25716
  }
25694
25717
  async function verifyChatMessage(msg) {
25695
25718
  if (msg.signed_payload && msg.signature && msg.from_did) {
25696
- return verifySignedPayload(
25719
+ const status2 = await verifySignedPayload(
25697
25720
  msg.signed_payload,
25698
25721
  msg.signature,
25699
25722
  msg.from_did,
25700
25723
  msg.signing_key_id || ""
25701
25724
  );
25725
+ if (status2 !== "verified") return status2;
25726
+ return signedPayloadConversationStatus(msg.signed_payload, msg.conversation_id);
25702
25727
  }
25703
25728
  const from = msg.from_address || msg.from_agent;
25704
25729
  const env = {
@@ -25713,10 +25738,16 @@ async function verifyChatMessage(msg) {
25713
25738
  from_stable_id: msg.from_stable_id,
25714
25739
  to_stable_id: msg.to_stable_id,
25715
25740
  message_id: msg.message_id,
25741
+ conversation_id: msg.conversation_id,
25716
25742
  signature: msg.signature,
25717
25743
  signing_key_id: msg.signing_key_id
25718
25744
  };
25719
- return verifyMessage(env);
25745
+ const status = await verifyMessage(env);
25746
+ if (status === "failed" && msg.conversation_id) {
25747
+ const legacyStatus = await verifyMessage({ ...env, conversation_id: void 0 });
25748
+ return legacyStatus === "verified" ? "verified_legacy" : legacyStatus;
25749
+ }
25750
+ return status;
25720
25751
  }
25721
25752
 
25722
25753
  // src/identity/pinstore.ts
@@ -26314,19 +26345,21 @@ function escapeJSON2(s) {
26314
26345
  etc.sha512Sync = (...m) => sha512(etc.concatBytes(...m));
26315
26346
  var ANNOUNCEMENT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
26316
26347
  var SenderTrustManager = class {
26317
- constructor(client, registry2, teamID, selfDid) {
26348
+ constructor(client, registry2, teamID, selfDid, selfStableID = "") {
26318
26349
  this.client = client;
26319
26350
  this.registry = registry2;
26320
26351
  this.teamID = teamID;
26321
26352
  this.selfDid = selfDid;
26353
+ this.selfStableID = selfStableID;
26322
26354
  }
26323
26355
  client;
26324
26356
  registry;
26325
26357
  teamID;
26326
26358
  selfDid;
26359
+ selfStableID;
26327
26360
  metaCache = /* @__PURE__ */ new Map();
26328
- async normalizeTrust(store, verificationStatus, rawAddress, fromDID, fromStableID, toDID, rotationAnnouncement, replacementAnnouncement, verificationAddress) {
26329
- let status = this.checkRecipientBinding(verificationStatus, toDID);
26361
+ async normalizeTrust(store, verificationStatus, rawAddress, fromDID, fromStableID, toDID, toStableID, rotationAnnouncement, replacementAnnouncement, verificationAddress) {
26362
+ let status = this.checkRecipientBinding(verificationStatus, toDID, toStableID);
26330
26363
  if (!status || !rawAddress.trim()) {
26331
26364
  return { status, stored: false };
26332
26365
  }
@@ -26352,11 +26385,21 @@ var SenderTrustManager = class {
26352
26385
  registryCheck.confirmedCurrentKey
26353
26386
  );
26354
26387
  }
26355
- checkRecipientBinding(status, toDID) {
26356
- if (status !== "verified" || !toDID || !this.selfDid) {
26388
+ checkRecipientBinding(status, toDID, toStableID) {
26389
+ if (status !== "verified") {
26357
26390
  return status;
26358
26391
  }
26359
- return toDID === this.selfDid ? status : "identity_mismatch";
26392
+ const selfStableID = this.selfStableID.trim();
26393
+ const recipientStableID = (toStableID || "").trim();
26394
+ if (selfStableID && recipientStableID) {
26395
+ return recipientStableID.toLowerCase() === selfStableID.toLowerCase() ? status : "identity_mismatch";
26396
+ }
26397
+ const selfDID = this.selfDid.trim();
26398
+ const recipientDID = (toDID || "").trim();
26399
+ if (!recipientDID || !selfDID) {
26400
+ return status;
26401
+ }
26402
+ return recipientDID === selfDID ? status : "identity_mismatch";
26360
26403
  }
26361
26404
  async checkStableIdentityRegistry(status, trustAddress, fromDID, fromStableID) {
26362
26405
  if (status !== "verified" || !fromDID || !fromStableID?.startsWith("did:aw:")) {
@@ -26671,6 +26714,10 @@ function pruneDispatched(dispatched) {
26671
26714
  removed++;
26672
26715
  }
26673
26716
  }
26717
+ function dispatchKey(channel, conversationID, messageID) {
26718
+ const conversation = (conversationID || "").trim();
26719
+ return `${channel}:${conversation}:${messageID}`;
26720
+ }
26674
26721
  async function main() {
26675
26722
  const workdir = process.cwd();
26676
26723
  const config2 = await resolveConfig(workdir);
@@ -26683,13 +26730,14 @@ async function main() {
26683
26730
  });
26684
26731
  const pinStore = await loadPinStore();
26685
26732
  const registry2 = new RegistryResolver(fetch, void 0, void 0, {
26686
- fallbackRegistryURL: resolveRegistryFallbackURL(config2.baseURL, config2.registryURL)
26733
+ fallbackRegistryURL: resolveRegistryFallbackURL(config2.registryURL)
26687
26734
  });
26688
26735
  const trust = new SenderTrustManager(
26689
26736
  client,
26690
26737
  registry2,
26691
26738
  config2.teamID,
26692
- config2.did
26739
+ config2.did,
26740
+ config2.stableID
26693
26741
  );
26694
26742
  const mcp = new Server(
26695
26743
  { name: "aweb", version: "0.1.0" },
@@ -26726,10 +26774,13 @@ Control events (type="control") are operational signals. On "pause", stop curren
26726
26774
  abort.signal
26727
26775
  );
26728
26776
  }
26729
- function resolveRegistryFallbackURL(baseURL, identityRegistryURL = "") {
26777
+ function resolveRegistryFallbackURL(identityRegistryURL = "") {
26730
26778
  const envRegistryURL = (process.env.AWID_REGISTRY_URL || "").trim();
26731
26779
  if (envRegistryURL) {
26732
- return envRegistryURL.toLowerCase() === "local" ? baseURL : envRegistryURL;
26780
+ if (envRegistryURL.toLowerCase() === "local") {
26781
+ throw new Error("AWID_REGISTRY_URL=local is not supported; set AWID_REGISTRY_URL=https://api.awid.ai");
26782
+ }
26783
+ return envRegistryURL;
26733
26784
  }
26734
26785
  const configuredRegistryURL = identityRegistryURL.trim();
26735
26786
  return configuredRegistryURL || void 0;
@@ -26752,8 +26803,10 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
26752
26803
  let pinsDirty = false;
26753
26804
  for (const msg of messages) {
26754
26805
  if (isSelfSender(msg.from_alias, msg.from_address, msg.from_stable_id, msg.from_did, self)) continue;
26755
- if (dispatched.has(msg.message_id)) continue;
26756
- dispatched.add(msg.message_id);
26806
+ const conversationID = msg.conversation_id || event.conversation_id;
26807
+ const key = dispatchKey("mail", conversationID, msg.message_id);
26808
+ if (dispatched.has(key)) continue;
26809
+ dispatched.add(key);
26757
26810
  const from = senderDisplayAddress(msg.from_alias, msg.from_address);
26758
26811
  const tofu = await trust.normalizeTrust(
26759
26812
  pinStore,
@@ -26762,9 +26815,10 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
26762
26815
  msg.from_did,
26763
26816
  msg.from_stable_id,
26764
26817
  msg.to_did,
26818
+ msg.to_stable_id,
26765
26819
  msg.rotation_announcement,
26766
26820
  msg.replacement_announcement,
26767
- msg.from_address || msg.from_alias || ""
26821
+ msg.signed_from || msg.from_address || msg.from_alias || ""
26768
26822
  );
26769
26823
  msg.verification_status = tofu.status;
26770
26824
  if (tofu.stored) pinsDirty = true;
@@ -26773,6 +26827,7 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
26773
26827
  from,
26774
26828
  message_id: msg.message_id
26775
26829
  };
26830
+ if (conversationID) meta3.conversation_id = conversationID;
26776
26831
  if (msg.subject) meta3.subject = msg.subject;
26777
26832
  if (msg.priority && msg.priority !== "normal") meta3.priority = msg.priority;
26778
26833
  if (msg.verification_status) meta3.verified = String(msg.verification_status === "verified" || msg.verification_status === "verified_custodial");
@@ -26794,8 +26849,10 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
26794
26849
  let lastMessageId;
26795
26850
  for (const msg of messages) {
26796
26851
  if (isSelfSender(msg.from_agent, msg.from_address, msg.from_stable_id, msg.from_did, self)) continue;
26797
- if (dispatched.has(msg.message_id)) continue;
26798
- dispatched.add(msg.message_id);
26852
+ const conversationID = msg.conversation_id || event.conversation_id || event.session_id;
26853
+ const key = dispatchKey("chat", conversationID, msg.message_id);
26854
+ if (dispatched.has(key)) continue;
26855
+ dispatched.add(key);
26799
26856
  const from = senderDisplayAddress(msg.from_agent, msg.from_address);
26800
26857
  const tofu = await trust.normalizeTrust(
26801
26858
  pinStore,
@@ -26804,9 +26861,10 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
26804
26861
  msg.from_did,
26805
26862
  msg.from_stable_id,
26806
26863
  msg.to_did,
26864
+ msg.to_stable_id,
26807
26865
  msg.rotation_announcement,
26808
26866
  msg.replacement_announcement,
26809
- msg.from_address || msg.from_agent || ""
26867
+ msg.signed_from || msg.from_address || msg.from_agent || ""
26810
26868
  );
26811
26869
  msg.verification_status = tofu.status;
26812
26870
  if (tofu.stored) pinsDirty = true;
@@ -26816,6 +26874,7 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
26816
26874
  session_id: event.session_id,
26817
26875
  message_id: msg.message_id
26818
26876
  };
26877
+ if (conversationID) meta3.conversation_id = conversationID;
26819
26878
  if (event.sender_waiting) meta3.sender_waiting = "true";
26820
26879
  if (msg.sender_leaving) meta3.sender_leaving = "true";
26821
26880
  if (msg.verification_status) meta3.verified = String(msg.verification_status === "verified" || msg.verification_status === "verified_custodial");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awebai/claude-channel",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "bin": "./dist/index.js",