@awebai/claude-channel 1.4.3 → 1.4.5
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/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +58 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22437,7 +22437,9 @@ async function* streamAgentEvents(client, signal) {
|
|
|
22437
22437
|
} catch (err2) {
|
|
22438
22438
|
if (signal.aborted)
|
|
22439
22439
|
return;
|
|
22440
|
-
|
|
22440
|
+
if (!isExpectedStreamTermination(err2)) {
|
|
22441
|
+
console.error(`[aw-channel] events stream parse failed: ${err2}`);
|
|
22442
|
+
}
|
|
22441
22443
|
await sleep(1e3, signal);
|
|
22442
22444
|
} finally {
|
|
22443
22445
|
resp.body?.cancel().catch(() => {
|
|
@@ -22523,6 +22525,13 @@ function parseAgentEvent(eventName, data) {
|
|
|
22523
22525
|
return { type: eventName };
|
|
22524
22526
|
}
|
|
22525
22527
|
}
|
|
22528
|
+
function isExpectedStreamTermination(err2) {
|
|
22529
|
+
if (!(err2 instanceof Error))
|
|
22530
|
+
return false;
|
|
22531
|
+
const name = err2.name.toLowerCase();
|
|
22532
|
+
const message = err2.message.toLowerCase();
|
|
22533
|
+
return name === "aborterror" || message === "terminated";
|
|
22534
|
+
}
|
|
22526
22535
|
function sleep(ms, signal) {
|
|
22527
22536
|
return new Promise((resolve) => {
|
|
22528
22537
|
if (signal.aborted) {
|
|
@@ -22879,6 +22888,9 @@ function hydrateAddressesFromSignedPayload(msg) {
|
|
|
22879
22888
|
} catch {
|
|
22880
22889
|
}
|
|
22881
22890
|
}
|
|
22891
|
+
async function ackMessage(client, messageId) {
|
|
22892
|
+
await client.post(`/v1/messages/${encodeURIComponent(messageId)}/ack`);
|
|
22893
|
+
}
|
|
22882
22894
|
async function verifyInboxMessage(msg) {
|
|
22883
22895
|
if (msg.signed_payload && msg.signature && msg.from_did) {
|
|
22884
22896
|
const status2 = await verifySignedPayload(msg.signed_payload, msg.signature, msg.from_did, msg.signing_key_id || "");
|
|
@@ -22954,6 +22966,9 @@ function hydrateAddressesFromSignedPayload2(msg) {
|
|
|
22954
22966
|
} catch {
|
|
22955
22967
|
}
|
|
22956
22968
|
}
|
|
22969
|
+
async function markRead(client, sessionId, upToMessageId) {
|
|
22970
|
+
await client.post(`/v1/chat/sessions/${encodeURIComponent(sessionId)}/read`, { up_to_message_id: upToMessageId });
|
|
22971
|
+
}
|
|
22957
22972
|
async function verifyChatMessage(msg) {
|
|
22958
22973
|
if (msg.signed_payload && msg.signature && msg.from_did) {
|
|
22959
22974
|
const status2 = await verifySignedPayload(msg.signed_payload, msg.signature, msg.from_did, msg.signing_key_id || "");
|
|
@@ -25749,9 +25764,9 @@ import { mkdir, open, rename, rm } from "node:fs/promises";
|
|
|
25749
25764
|
var PinStore = class _PinStore {
|
|
25750
25765
|
pins = /* @__PURE__ */ new Map();
|
|
25751
25766
|
addresses = /* @__PURE__ */ new Map();
|
|
25752
|
-
/** Check whether a DID matches the stored pin for
|
|
25753
|
-
checkPin(address, did,
|
|
25754
|
-
if (
|
|
25767
|
+
/** Check whether a DID matches the stored pin for a global address. */
|
|
25768
|
+
checkPin(address, did, identityScope) {
|
|
25769
|
+
if (identityScope === "local")
|
|
25755
25770
|
return "skipped";
|
|
25756
25771
|
const pinnedDID = this.addresses.get(address);
|
|
25757
25772
|
if (pinnedDID === void 0)
|
|
@@ -25947,7 +25962,7 @@ var RegistryResolver = class {
|
|
|
25947
25962
|
address: `${split2.domain}/${split2.name}`,
|
|
25948
25963
|
controllerDid: authority.controllerDid,
|
|
25949
25964
|
custody: "self",
|
|
25950
|
-
|
|
25965
|
+
identityScope: "global"
|
|
25951
25966
|
};
|
|
25952
25967
|
}
|
|
25953
25968
|
async discoverRegistry(domain2) {
|
|
@@ -26338,6 +26353,17 @@ function escapeJSON2(s) {
|
|
|
26338
26353
|
// ../channel-core/dist/identity/trust.js
|
|
26339
26354
|
etc.sha512Sync = (...m) => sha512(etc.concatBytes(...m));
|
|
26340
26355
|
var ANNOUNCEMENT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
26356
|
+
function normalizeIdentityScope(identityScope, legacyLifetime, defaultScope) {
|
|
26357
|
+
const normalizedScope = (identityScope || "").trim().toLowerCase();
|
|
26358
|
+
if (normalizedScope === "global" || normalizedScope === "local")
|
|
26359
|
+
return normalizedScope;
|
|
26360
|
+
const normalizedLegacy = (legacyLifetime || "").trim().toLowerCase();
|
|
26361
|
+
if (normalizedLegacy === "persistent")
|
|
26362
|
+
return "global";
|
|
26363
|
+
if (normalizedLegacy === "ephemeral")
|
|
26364
|
+
return "local";
|
|
26365
|
+
return defaultScope;
|
|
26366
|
+
}
|
|
26341
26367
|
var SenderTrustManager = class {
|
|
26342
26368
|
client;
|
|
26343
26369
|
registry;
|
|
@@ -26377,6 +26403,11 @@ var SenderTrustManager = class {
|
|
|
26377
26403
|
if (!recipientDID || !selfDID) {
|
|
26378
26404
|
return status;
|
|
26379
26405
|
}
|
|
26406
|
+
if (recipientDID.startsWith("did:aw:")) {
|
|
26407
|
+
if (recipientStableID)
|
|
26408
|
+
return status;
|
|
26409
|
+
return selfStableID ? "identity_mismatch" : status;
|
|
26410
|
+
}
|
|
26380
26411
|
return recipientDID === selfDID ? status : "identity_mismatch";
|
|
26381
26412
|
}
|
|
26382
26413
|
async checkStableIdentityRegistry(status, trustAddress, fromDID, fromStableID) {
|
|
@@ -26399,7 +26430,7 @@ var SenderTrustManager = class {
|
|
|
26399
26430
|
if (!status || status !== "verified" && status !== "verified_custodial" || !fromDID || !trustAddress || !meta3.resolved) {
|
|
26400
26431
|
return { status, stored: false };
|
|
26401
26432
|
}
|
|
26402
|
-
if (meta3.
|
|
26433
|
+
if (meta3.identityScope === "local") {
|
|
26403
26434
|
let removed = store.removeAddress(trustAddress);
|
|
26404
26435
|
if (rawAddress && rawAddress !== trustAddress) {
|
|
26405
26436
|
removed = store.removeAddress(rawAddress) || removed;
|
|
@@ -26426,7 +26457,7 @@ var SenderTrustManager = class {
|
|
|
26426
26457
|
}
|
|
26427
26458
|
}
|
|
26428
26459
|
}
|
|
26429
|
-
const pinResult = store.checkPin(trustAddress, pinKey, meta3.
|
|
26460
|
+
const pinResult = store.checkPin(trustAddress, pinKey, meta3.identityScope);
|
|
26430
26461
|
switch (pinResult) {
|
|
26431
26462
|
case "new":
|
|
26432
26463
|
store.storePin(pinKey, trustAddress, "", "");
|
|
@@ -26552,7 +26583,7 @@ var SenderTrustManager = class {
|
|
|
26552
26583
|
const rawAddress = address.trim();
|
|
26553
26584
|
const trustAddress = this.canonicalTrustAddress(rawAddress);
|
|
26554
26585
|
if (!trustAddress) {
|
|
26555
|
-
return {
|
|
26586
|
+
return { identityScope: "global", custody: "self", resolved: false };
|
|
26556
26587
|
}
|
|
26557
26588
|
const cached2 = this.metaCache.get(trustAddress);
|
|
26558
26589
|
if (cached2)
|
|
@@ -26560,7 +26591,7 @@ var SenderTrustManager = class {
|
|
|
26560
26591
|
try {
|
|
26561
26592
|
const identity = await this.resolveIdentity(rawAddress);
|
|
26562
26593
|
const meta3 = {
|
|
26563
|
-
|
|
26594
|
+
identityScope: identity.identityScope,
|
|
26564
26595
|
custody: identity.custody || "self",
|
|
26565
26596
|
controllerDid: identity.controllerDid,
|
|
26566
26597
|
resolved: true
|
|
@@ -26568,7 +26599,7 @@ var SenderTrustManager = class {
|
|
|
26568
26599
|
this.metaCache.set(trustAddress, meta3);
|
|
26569
26600
|
return meta3;
|
|
26570
26601
|
} catch {
|
|
26571
|
-
return {
|
|
26602
|
+
return { identityScope: "global", custody: "self", resolved: false };
|
|
26572
26603
|
}
|
|
26573
26604
|
}
|
|
26574
26605
|
async resolveIdentity(address) {
|
|
@@ -26588,7 +26619,7 @@ var SenderTrustManager = class {
|
|
|
26588
26619
|
stableID: response.did_aw,
|
|
26589
26620
|
address: response.address || `${this.teamID}/${trimmed}`,
|
|
26590
26621
|
custody: "self",
|
|
26591
|
-
|
|
26622
|
+
identityScope: normalizeIdentityScope(response.identity_scope, response.lifetime, "local")
|
|
26592
26623
|
};
|
|
26593
26624
|
}
|
|
26594
26625
|
};
|
|
@@ -26659,9 +26690,11 @@ function escapeJSON3(s) {
|
|
|
26659
26690
|
}
|
|
26660
26691
|
|
|
26661
26692
|
// ../channel-core/dist/channel.js
|
|
26662
|
-
import { join as join2 } from "node:path";
|
|
26693
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
26663
26694
|
import { homedir } from "node:os";
|
|
26664
26695
|
var DEFAULT_PIN_STORE_PATH = join2(homedir(), ".config", "aw", "known_agents.yaml");
|
|
26696
|
+
var DEFAULT_DELIVERY_STORE_PATH = join2(homedir(), ".config", "aw", "channel-delivered-ids.json");
|
|
26697
|
+
var DELIVERED_IDS_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
26665
26698
|
|
|
26666
26699
|
// src/index.ts
|
|
26667
26700
|
var PIN_STORE_PATH = join3(homedir2(), ".config", "aw", "known_agents.yaml");
|
|
@@ -26719,7 +26752,7 @@ async function main() {
|
|
|
26719
26752
|
},
|
|
26720
26753
|
instructions: `Events from the aweb channel are coordination messages from other agents in your team. Use the aw CLI to respond, not MCP tools.
|
|
26721
26754
|
|
|
26722
|
-
Mail events (type="mail") are async. Read them and act if needed.
|
|
26755
|
+
Mail events (type="mail") are async. Read them and act if needed. Confirmed channel delivery marks the source message handled so reconnects do not replay stale mail. Reply with: aw mail reply <message_id> --body "<reply>".
|
|
26723
26756
|
|
|
26724
26757
|
Chat events (type="chat") may have sender_waiting="true", meaning the sender is blocked waiting for your reply. Respond promptly with: aw chat send-and-wait <from> "<reply>"
|
|
26725
26758
|
If you need more time, send a status update the same way.
|
|
@@ -26777,7 +26810,10 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
|
|
|
26777
26810
|
if (isSelfSender(msg.from_alias, msg.from_address, msg.from_stable_id, msg.from_did, self)) continue;
|
|
26778
26811
|
const conversationID = msg.conversation_id || event.conversation_id;
|
|
26779
26812
|
const key = dispatchKey("mail", conversationID, msg.message_id);
|
|
26780
|
-
if (dispatched.has(key))
|
|
26813
|
+
if (dispatched.has(key)) {
|
|
26814
|
+
if (!msg.read_at) await ackMessage(client, msg.message_id);
|
|
26815
|
+
continue;
|
|
26816
|
+
}
|
|
26781
26817
|
dispatched.add(key);
|
|
26782
26818
|
const from = senderDisplayAddress(msg.from_alias, msg.from_address);
|
|
26783
26819
|
const tofu = await trust.normalizeTrust(
|
|
@@ -26807,6 +26843,7 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
|
|
|
26807
26843
|
method: "notifications/claude/channel",
|
|
26808
26844
|
params: { content: msg.body, meta: meta3 }
|
|
26809
26845
|
});
|
|
26846
|
+
await ackMessage(client, msg.message_id);
|
|
26810
26847
|
}
|
|
26811
26848
|
if (pinsDirty) await pinStore.save(PIN_STORE_PATH);
|
|
26812
26849
|
break;
|
|
@@ -26815,11 +26852,15 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
|
|
|
26815
26852
|
if (!event.session_id) break;
|
|
26816
26853
|
const messages = await fetchHistory(client, event.session_id, true, CHAT_FETCH_LIMIT, event.message_id);
|
|
26817
26854
|
let pinsDirty = false;
|
|
26855
|
+
let lastMessageId;
|
|
26818
26856
|
for (const msg of messages) {
|
|
26819
26857
|
if (isSelfSender(msg.from_agent, msg.from_address, msg.from_stable_id, msg.from_did, self)) continue;
|
|
26820
26858
|
const conversationID = msg.conversation_id || event.conversation_id || event.session_id;
|
|
26821
26859
|
const key = dispatchKey("chat", conversationID, msg.message_id);
|
|
26822
|
-
if (dispatched.has(key))
|
|
26860
|
+
if (dispatched.has(key)) {
|
|
26861
|
+
lastMessageId = msg.message_id;
|
|
26862
|
+
continue;
|
|
26863
|
+
}
|
|
26823
26864
|
dispatched.add(key);
|
|
26824
26865
|
const from = senderDisplayAddress(msg.from_agent, msg.from_address);
|
|
26825
26866
|
const tofu = await trust.normalizeTrust(
|
|
@@ -26850,7 +26891,9 @@ async function dispatchEvent(mcp, client, pinStore, trust, self, dispatched, eve
|
|
|
26850
26891
|
method: "notifications/claude/channel",
|
|
26851
26892
|
params: { content: msg.body, meta: meta3 }
|
|
26852
26893
|
});
|
|
26894
|
+
lastMessageId = msg.message_id;
|
|
26853
26895
|
}
|
|
26896
|
+
if (lastMessageId) await markRead(client, event.session_id, lastMessageId);
|
|
26854
26897
|
if (pinsDirty) await pinStore.save(PIN_STORE_PATH);
|
|
26855
26898
|
break;
|
|
26856
26899
|
}
|