@highway1/core 0.1.62 → 0.1.76

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/index.js CHANGED
@@ -3,8 +3,6 @@ import { base58btc } from 'multiformats/bases/base58';
3
3
  import { WebSocket } from 'ws';
4
4
  import { encode, decode } from 'cbor-x';
5
5
  import Ajv from 'ajv';
6
- import lunr from 'lunr';
7
- import Fuse from 'fuse.js';
8
6
  import { Level } from 'level';
9
7
  import { sha256 } from '@noble/hashes/sha256';
10
8
  import { bytesToHex } from '@noble/hashes/utils';
@@ -146,6 +144,112 @@ async function verifyMessage(signedMessage, expectedPublicKey) {
146
144
  }
147
145
  }
148
146
 
147
+ // src/identity/aliases.ts
148
+ function validateAliasName(alias) {
149
+ if (!alias || alias.length === 0) {
150
+ return { valid: false, error: "Alias cannot be empty" };
151
+ }
152
+ if (alias.length > 32) {
153
+ return { valid: false, error: "Alias must be 32 characters or less" };
154
+ }
155
+ if (alias.startsWith("did:")) {
156
+ return { valid: false, error: 'Alias cannot start with "did:" (reserved for DID prefix)' };
157
+ }
158
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(alias)) {
159
+ return { valid: false, error: "Alias must be lowercase alphanumeric with hyphens, starting with alphanumeric" };
160
+ }
161
+ return { valid: true };
162
+ }
163
+ function resolveDid(input, aliases) {
164
+ if (!input) {
165
+ return void 0;
166
+ }
167
+ if (input.startsWith("did:")) {
168
+ return input;
169
+ }
170
+ const did = aliases[input];
171
+ if (did) {
172
+ return did;
173
+ }
174
+ return void 0;
175
+ }
176
+ function reverseAlias(did, aliases) {
177
+ for (const [alias, aliasDid] of Object.entries(aliases)) {
178
+ if (aliasDid === did) {
179
+ return alias;
180
+ }
181
+ }
182
+ return void 0;
183
+ }
184
+ function formatDidWithAlias(did, aliases) {
185
+ const alias = reverseAlias(did, aliases);
186
+ return alias || did;
187
+ }
188
+ function formatDidWithAliasDetailed(did, aliases, truncate = false) {
189
+ const alias = reverseAlias(did, aliases);
190
+ if (alias) {
191
+ if (truncate && did.length > 40) {
192
+ const truncated = did.substring(0, 20) + "..." + did.substring(did.length - 10);
193
+ return `${alias} (${truncated})`;
194
+ }
195
+ return `${alias} (${did})`;
196
+ }
197
+ if (truncate && did.length > 40) {
198
+ return did.substring(0, 20) + "..." + did.substring(did.length - 10);
199
+ }
200
+ return did;
201
+ }
202
+
203
+ // src/identity/document.ts
204
+ function createDIDDocument(publicKey, services) {
205
+ const did = deriveDID(publicKey);
206
+ const keyId = `${did}#key-1`;
207
+ const publicKeyMultibase = `z${Buffer.from(publicKey).toString("hex")}`;
208
+ return {
209
+ "@context": [
210
+ "https://www.w3.org/ns/did/v1",
211
+ "https://w3id.org/security/suites/ed25519-2020/v1"
212
+ ],
213
+ id: did,
214
+ verificationMethod: [
215
+ {
216
+ id: keyId,
217
+ type: "Ed25519VerificationKey2020",
218
+ controller: did,
219
+ publicKeyMultibase
220
+ }
221
+ ],
222
+ authentication: [keyId],
223
+ assertionMethod: [keyId],
224
+ service: services
225
+ };
226
+ }
227
+ function validateDIDDocument(doc) {
228
+ if (typeof doc !== "object" || doc === null) {
229
+ return false;
230
+ }
231
+ const d = doc;
232
+ return Array.isArray(d["@context"]) && typeof d.id === "string" && d.id.startsWith("did:clawiverse:") && Array.isArray(d.verificationMethod) && d.verificationMethod.length > 0 && Array.isArray(d.authentication) && Array.isArray(d.assertionMethod);
233
+ }
234
+
235
+ // src/identity/index.ts
236
+ async function generateAnonymousIdentity() {
237
+ const keyPair = await generateKeyPair();
238
+ const exported = exportKeyPair(keyPair);
239
+ const did = deriveDID(keyPair.publicKey);
240
+ const didSuffix = did.split(":").pop().slice(-8);
241
+ return {
242
+ did,
243
+ publicKey: exported.publicKey,
244
+ privateKey: exported.privateKey,
245
+ agentCard: {
246
+ name: `Agent-${didSuffix}`,
247
+ description: `Anonymous agent ${didSuffix}`,
248
+ capabilities: []
249
+ }
250
+ };
251
+ }
252
+
149
253
  // src/utils/logger.ts
150
254
  var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
151
255
  LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
@@ -198,8 +302,9 @@ var DEFAULT_RECONNECT = {
198
302
  stableAfterMs: 6e4
199
303
  };
200
304
  function createRelayClient(config) {
201
- const { relayUrls, did, keyPair, card } = config;
305
+ const { relayUrls, did, keyPair } = config;
202
306
  const reconnectConfig = { ...DEFAULT_RECONNECT, ...config.reconnect };
307
+ let currentCard = config.card;
203
308
  const connections = relayUrls.map((url) => ({
204
309
  url,
205
310
  ws: null,
@@ -228,13 +333,13 @@ function createRelayClient(config) {
228
333
  logger.info("WebSocket connected", { url: conn.url });
229
334
  try {
230
335
  const timestamp = Date.now();
231
- const helloData = encode({ did, card, timestamp });
336
+ const helloData = encode({ did, card: currentCard, timestamp });
232
337
  const signature = await sign(helloData, keyPair.privateKey);
233
338
  const hello = {
234
339
  type: "HELLO",
235
340
  protocolVersion: 1,
236
341
  did,
237
- card,
342
+ card: currentCard,
238
343
  timestamp,
239
344
  signature
240
345
  };
@@ -445,7 +550,7 @@ function createRelayClient(config) {
445
550
  ws.off("message", handler);
446
551
  resolve(msg.agents);
447
552
  }
448
- } catch (err) {
553
+ } catch {
449
554
  }
450
555
  };
451
556
  ws.on("message", handler);
@@ -470,13 +575,49 @@ function createRelayClient(config) {
470
575
  ws.off("message", handler);
471
576
  resolve(msg.card);
472
577
  }
473
- } catch (err) {
578
+ } catch {
474
579
  }
475
580
  };
476
581
  ws.on("message", handler);
477
582
  ws.send(encode({ type: "FETCH_CARD", did: did2 }));
478
583
  });
479
584
  },
585
+ async queryTrust(target, domain, since, cursor) {
586
+ const conn = getConnectedConnection();
587
+ const ws = conn?.ws;
588
+ if (!conn || !ws) {
589
+ throw new TransportError("No connected relay");
590
+ }
591
+ return new Promise((resolve, reject) => {
592
+ const timeout = setTimeout(() => {
593
+ reject(new TransportError("Trust query timeout"));
594
+ }, 1e4);
595
+ const handler = (data) => {
596
+ try {
597
+ const msg = decode(data);
598
+ if (msg.type === "TRUST_RESULT" && msg.target === target) {
599
+ clearTimeout(timeout);
600
+ ws.off("message", handler);
601
+ resolve(msg);
602
+ }
603
+ } catch {
604
+ }
605
+ };
606
+ ws.on("message", handler);
607
+ ws.send(encode({ type: "TRUST_QUERY", target, domain, since, cursor }));
608
+ });
609
+ },
610
+ async publishCard(card) {
611
+ if (card) {
612
+ currentCard = card;
613
+ }
614
+ await sendToRelay({ type: "PUBLISH_CARD", card });
615
+ logger.debug("Sent PUBLISH_CARD");
616
+ },
617
+ async unpublishCard() {
618
+ await sendToRelay({ type: "UNPUBLISH_CARD" });
619
+ logger.debug("Sent UNPUBLISH_CARD");
620
+ },
480
621
  onDeliver(handler) {
481
622
  deliveryHandler = handler;
482
623
  },
@@ -818,490 +959,63 @@ function createRelayIndexOperations(client) {
818
959
  }
819
960
  };
820
961
  }
821
- var logger3 = createLogger("search-index");
822
- var SearchIndex = class {
823
- cards = /* @__PURE__ */ new Map();
824
- lunrIndex;
825
- fuse;
826
- needsRebuild = false;
827
- /**
828
- * Add or update an Agent Card in the index
829
- */
830
- indexAgentCard(card) {
831
- this.cards.set(card.did, card);
832
- this.needsRebuild = true;
833
- logger3.debug("Indexed Agent Card", { did: card.did, capabilities: card.capabilities.length });
834
- }
835
- /**
836
- * Remove an Agent Card from the index
837
- */
838
- removeAgentCard(did) {
839
- this.cards.delete(did);
840
- this.needsRebuild = true;
841
- logger3.debug("Removed Agent Card from index", { did });
842
- }
843
- /**
844
- * Search for agents matching a query
845
- */
846
- search(query) {
847
- if (this.needsRebuild) {
848
- this.rebuild();
849
- }
850
- let results = [];
851
- if (query.text && this.lunrIndex) {
852
- results = this.searchByText(query.text);
853
- } else if (query.capability && this.fuse) {
854
- results = this.searchByCapability(query.capability);
855
- } else {
856
- results = Array.from(this.cards.values()).map((card) => ({
857
- card,
858
- score: 1
859
- }));
860
- }
861
- if (query.filters) {
862
- results = this.applyFilters(results, query.filters);
863
- }
864
- results.sort((a, b) => b.score - a.score);
865
- if (query.limit) {
866
- results = results.slice(0, query.limit);
867
- }
868
- logger3.debug("Search completed", { query, results: results.length });
869
- return results;
870
- }
871
- /**
872
- * Get all indexed cards
873
- */
874
- getAllCards() {
875
- return Array.from(this.cards.values());
876
- }
877
- /**
878
- * Clear the index
879
- */
880
- clear() {
881
- this.cards.clear();
882
- this.lunrIndex = void 0;
883
- this.fuse = void 0;
884
- this.needsRebuild = false;
885
- logger3.info("Search index cleared");
886
- }
887
- /**
888
- * Get index size
889
- */
890
- size() {
891
- return this.cards.size;
892
- }
893
- /**
894
- * Rebuild search indexes
895
- */
896
- rebuild() {
897
- logger3.info("Rebuilding search indexes", { cards: this.cards.size });
898
- const cards = Array.from(this.cards.values());
899
- this.lunrIndex = lunr(function() {
900
- this.ref("did");
901
- this.field("name", { boost: 10 });
902
- this.field("description", { boost: 5 });
903
- this.field("capabilities");
904
- for (const card of cards) {
905
- this.add({
906
- did: card.did,
907
- name: card.name,
908
- description: card.description,
909
- capabilities: card.capabilities.map((cap) => `${cap.name} ${cap.description}`).join(" ")
910
- });
911
- }
912
- });
913
- this.fuse = new Fuse(Array.from(this.cards.values()), {
914
- keys: [
915
- { name: "name", weight: 0.3 },
916
- { name: "description", weight: 0.2 },
917
- { name: "capabilities.name", weight: 0.3 },
918
- { name: "capabilities.description", weight: 0.2 }
919
- ],
920
- threshold: 0.4,
921
- includeScore: true
922
- });
923
- this.needsRebuild = false;
924
- logger3.info("Search indexes rebuilt");
925
- }
926
- /**
927
- * Search by text using Lunr
928
- */
929
- searchByText(text) {
930
- if (!this.lunrIndex) return [];
931
- const lunrResults = this.lunrIndex.search(text);
932
- return lunrResults.map((result) => ({
933
- card: this.cards.get(result.ref),
934
- score: result.score
935
- }));
936
- }
937
- /**
938
- * Search by capability using Fuse
939
- */
940
- searchByCapability(capability) {
941
- if (!this.fuse) return [];
942
- const fuseResults = this.fuse.search(capability);
943
- return fuseResults.map((result) => ({
944
- card: result.item,
945
- score: 1 - (result.score || 0)
946
- // Fuse score is distance, convert to similarity
947
- }));
948
- }
949
- /**
950
- * Apply filters to search results
951
- */
952
- applyFilters(results, filters) {
953
- return results.filter((result) => {
954
- const { card } = result;
955
- if (filters.minTrustScore !== void 0 && card.trust) {
956
- const overallTrust = card.trust.interactionScore * 0.4 + Math.min(card.trust.endorsements / 10, 1) * 0.2 + card.trust.completionRate * 0.2 + card.trust.uptime * 0.2;
957
- if (overallTrust < filters.minTrustScore) {
958
- return false;
959
- }
960
- }
961
- if (filters.language) {
962
- const hasLanguage = card.capabilities.some(
963
- (cap) => {
964
- const metadata = cap.metadata;
965
- if (!metadata) return false;
966
- return metadata.language === filters.language || Array.isArray(metadata.languages) && metadata.languages.includes(filters.language);
967
- }
968
- );
969
- if (!hasLanguage) return false;
970
- }
971
- if (filters.tags && filters.tags.length > 0) {
972
- const cardTags = Array.isArray(card.metadata?.tags) ? card.metadata.tags : [];
973
- const hasAllTags = filters.tags.every((tag) => cardTags.includes(tag));
974
- if (!hasAllTags) return false;
975
- }
976
- return true;
977
- });
978
- }
979
- };
980
962
 
981
- // src/discovery/capability-matcher.ts
982
- var CapabilityMatcher = class {
983
- /**
984
- * Match a query against a capability
985
- * Returns a score between 0 and 1
986
- */
987
- match(query, capability) {
988
- let score = 0;
989
- let weights = 0;
990
- if (query.capability && capability.id === query.capability) {
991
- return 1;
992
- }
993
- if (query.capability) {
994
- const nameScore = this.fuzzyMatch(query.capability, capability.name);
995
- score += nameScore * 0.4;
996
- weights += 0.4;
997
- }
998
- if (query.text) {
999
- const keywords = this.extractKeywords(query.text);
1000
- const keywordScore = this.matchKeywords(keywords, capability);
1001
- score += keywordScore * 0.4;
1002
- weights += 0.4;
1003
- }
1004
- if (query.capability && capability["@type"]) {
1005
- const typeScore = this.matchesType(query.capability, capability["@type"]) ? 0.6 : 0;
1006
- score += typeScore * 0.2;
1007
- weights += 0.2;
1008
- }
1009
- return weights > 0 ? score / weights : 0;
1010
- }
1011
- /**
1012
- * Extract keywords from natural language text
1013
- */
1014
- extractKeywords(text) {
1015
- const stopWords = /* @__PURE__ */ new Set([
1016
- "a",
1017
- "an",
1018
- "the",
1019
- "is",
1020
- "are",
1021
- "was",
1022
- "were",
1023
- "be",
1024
- "been",
1025
- "to",
1026
- "from",
1027
- "in",
1028
- "on",
1029
- "at",
1030
- "by",
1031
- "for",
1032
- "with",
1033
- "about",
1034
- "can",
1035
- "could",
1036
- "should",
1037
- "would",
1038
- "will",
1039
- "do",
1040
- "does",
1041
- "did",
1042
- "i",
1043
- "you",
1044
- "he",
1045
- "she",
1046
- "it",
1047
- "we",
1048
- "they",
1049
- "me",
1050
- "him",
1051
- "her"
1052
- ]);
1053
- return text.toLowerCase().split(/\W+/).filter((word) => word.length > 2 && !stopWords.has(word));
1054
- }
1055
- /**
1056
- * Match keywords against capability
1057
- */
1058
- matchKeywords(keywords, capability) {
1059
- if (keywords.length === 0) return 0;
1060
- const capText = `${capability.name} ${capability.description}`.toLowerCase();
1061
- const matches = keywords.filter((keyword) => capText.includes(keyword));
1062
- return matches.length / keywords.length;
1063
- }
1064
- /**
1065
- * Check if query matches capability type hierarchy
1066
- */
1067
- matchesType(query, type) {
1068
- const queryLower = query.toLowerCase();
1069
- const typeLower = type.toLowerCase();
1070
- if (typeLower.includes(queryLower)) return true;
1071
- const typeMap = {
1072
- translate: ["translation", "translationservice"],
1073
- review: ["codereview", "reviewservice"],
1074
- analyze: ["analysis", "dataanalysis"],
1075
- generate: ["generation", "textgeneration", "imagegeneration"],
1076
- search: ["searchservice", "query"],
1077
- compute: ["computation", "computationservice"],
1078
- store: ["storage", "storageservice"],
1079
- message: ["messaging", "messagingservice"],
1080
- auth: ["authentication", "authenticationservice"]
1081
- };
1082
- for (const [key, values] of Object.entries(typeMap)) {
1083
- if (queryLower.includes(key) && values.some((v) => typeLower.includes(v))) {
1084
- return true;
1085
- }
1086
- }
1087
- return false;
1088
- }
1089
- /**
1090
- * Fuzzy string matching using Levenshtein distance
1091
- */
1092
- fuzzyMatch(query, target) {
1093
- const queryLower = query.toLowerCase();
1094
- const targetLower = target.toLowerCase();
1095
- if (queryLower === targetLower) return 1;
1096
- if (targetLower.includes(queryLower)) return 0.8;
1097
- if (queryLower.includes(targetLower)) return 0.7;
1098
- const distance = this.levenshteinDistance(queryLower, targetLower);
1099
- const maxLen = Math.max(queryLower.length, targetLower.length);
1100
- const similarity = 1 - distance / maxLen;
1101
- return similarity > 0.5 ? similarity * 0.6 : 0;
1102
- }
1103
- /**
1104
- * Calculate Levenshtein distance between two strings
1105
- */
1106
- levenshteinDistance(a, b) {
1107
- const matrix = [];
1108
- for (let i = 0; i <= b.length; i++) {
1109
- matrix[i] = [i];
1110
- }
1111
- for (let j = 0; j <= a.length; j++) {
1112
- matrix[0][j] = j;
1113
- }
1114
- for (let i = 1; i <= b.length; i++) {
1115
- for (let j = 1; j <= a.length; j++) {
1116
- if (b.charAt(i - 1) === a.charAt(j - 1)) {
1117
- matrix[i][j] = matrix[i - 1][j - 1];
1118
- } else {
1119
- matrix[i][j] = Math.min(
1120
- matrix[i - 1][j - 1] + 1,
1121
- // substitution
1122
- matrix[i][j - 1] + 1,
1123
- // insertion
1124
- matrix[i - 1][j] + 1
1125
- // deletion
1126
- );
1127
- }
1128
- }
1129
- }
1130
- return matrix[b.length][a.length];
1131
- }
1132
- };
1133
-
1134
- // src/discovery/semantic-search.ts
1135
- var logger4 = createLogger("semantic-search");
1136
- var SemanticSearchEngine = class {
1137
- constructor(dht) {
1138
- this.dht = dht;
1139
- this.index = new SearchIndex();
1140
- this.matcher = new CapabilityMatcher();
1141
- }
1142
- index;
1143
- matcher;
1144
- /**
1145
- * Main search interface
1146
- * Local-first with network fallback
1147
- */
1148
- async search(query) {
1149
- logger4.info("Searching for agents", { query });
1150
- const localResults = this.index.search(query);
1151
- logger4.debug("Local search results", { count: localResults.length });
1152
- const limit = query.limit || 10;
1153
- if (localResults.length < limit && this.dht) {
1154
- logger4.debug("Insufficient local results, querying network");
1155
- const networkResults = await this.searchNetwork(query);
1156
- return this.mergeResults(localResults, networkResults, limit);
1157
- }
1158
- return localResults.map((r) => r.card);
963
+ // src/messaging/envelope.ts
964
+ function normalizeEnvelopeType(type) {
965
+ if (type === "message" || type === "notification" || type === "request") {
966
+ return "message";
1159
967
  }
1160
- /**
1161
- * Index an Agent Card for local search
1162
- */
1163
- indexAgentCard(card) {
1164
- this.index.indexAgentCard(card);
968
+ if (type === "reply" || type === "response") {
969
+ return "reply";
1165
970
  }
1166
- /**
1167
- * Remove an Agent Card from local index
1168
- */
1169
- removeAgentCard(did) {
1170
- this.index.removeAgentCard(did);
1171
- }
1172
- /**
1173
- * Get all indexed cards
1174
- */
1175
- getAllIndexedCards() {
1176
- return this.index.getAllCards();
971
+ return void 0;
972
+ }
973
+ function normalizeEnvelope(msg) {
974
+ if (typeof msg !== "object" || msg === null) {
975
+ return void 0;
1177
976
  }
1178
- /**
1179
- * Clear local index
1180
- */
1181
- clearIndex() {
1182
- this.index.clear();
977
+ const envelope = msg;
978
+ const normalizedType = envelope.type ? normalizeEnvelopeType(envelope.type) : void 0;
979
+ if (typeof envelope.id !== "string" || typeof envelope.from !== "string" || !envelope.from.startsWith("did:clawiverse:") || typeof envelope.to !== "string" || !envelope.to.startsWith("did:clawiverse:") || !normalizedType || typeof envelope.protocol !== "string" || envelope.payload === void 0 || typeof envelope.timestamp !== "number" || typeof envelope.signature !== "string") {
980
+ return void 0;
1183
981
  }
1184
- /**
1185
- * Get index size
1186
- */
1187
- getIndexSize() {
1188
- return this.index.size();
982
+ if (normalizedType === "reply" && typeof envelope.replyTo !== "string") {
983
+ return void 0;
1189
984
  }
1190
- /**
1191
- * Search network via DHT
1192
- */
1193
- async searchNetwork(query) {
1194
- if (!this.dht) {
1195
- return [];
1196
- }
1197
- try {
1198
- const capability = query.capability || this.extractPrimaryCapability(query.text);
1199
- if (!capability) {
1200
- logger4.debug("No capability extracted from query, skipping network search");
1201
- return [];
1202
- }
1203
- const cards = await this.dht.queryByCapability(capability);
1204
- logger4.debug("Network search results", { count: cards.length });
1205
- return cards.map((card) => {
1206
- const score = this.scoreCard(card, query);
1207
- return { card, score };
1208
- });
1209
- } catch (error) {
1210
- logger4.error("Network search failed", { error });
1211
- return [];
1212
- }
985
+ if (normalizedType === "message" && envelope.replyTo !== void 0) {
986
+ return void 0;
1213
987
  }
1214
- /**
1215
- * Merge local and network results, removing duplicates
1216
- */
1217
- mergeResults(local, network, limit) {
1218
- const seen = /* @__PURE__ */ new Set();
1219
- const merged = [];
1220
- for (const result of local) {
1221
- if (!seen.has(result.card.did)) {
1222
- seen.add(result.card.did);
1223
- merged.push(result);
1224
- }
1225
- }
1226
- for (const result of network) {
1227
- if (!seen.has(result.card.did)) {
1228
- seen.add(result.card.did);
1229
- merged.push(result);
1230
- this.index.indexAgentCard(result.card);
1231
- }
1232
- }
1233
- merged.sort((a, b) => b.score - a.score);
1234
- return merged.slice(0, limit).map((r) => r.card);
988
+ return {
989
+ id: envelope.id,
990
+ from: envelope.from,
991
+ to: envelope.to,
992
+ type: normalizedType,
993
+ protocol: envelope.protocol,
994
+ payload: envelope.payload,
995
+ timestamp: envelope.timestamp,
996
+ signature: envelope.signature,
997
+ replyTo: normalizedType === "reply" ? envelope.replyTo : void 0,
998
+ threadId: typeof envelope.threadId === "string" ? envelope.threadId : void 0
999
+ };
1000
+ }
1001
+ function createEnvelope(from, to, type, protocol, payload, replyTo, threadId) {
1002
+ const normalizedType = normalizeEnvelopeType(type);
1003
+ if (!normalizedType) {
1004
+ throw new MessagingError(`Invalid message type: ${type}`);
1235
1005
  }
1236
- /**
1237
- * Score a card against a query
1238
- */
1239
- scoreCard(card, query) {
1240
- let totalScore = 0;
1241
- let count = 0;
1242
- for (const capability of card.capabilities) {
1243
- const score = this.matcher.match(query, capability);
1244
- if (score > 0) {
1245
- totalScore += score;
1246
- count++;
1247
- }
1248
- }
1249
- const avgScore = count > 0 ? totalScore / count : 0;
1250
- if (card.trust) {
1251
- const trustBoost = card.trust.interactionScore * 0.2;
1252
- return Math.min(avgScore + trustBoost, 1);
1253
- }
1254
- return avgScore;
1255
- }
1256
- /**
1257
- * Extract primary capability from natural language text
1258
- */
1259
- extractPrimaryCapability(text) {
1260
- if (!text) return void 0;
1261
- const keywords = this.matcher.extractKeywords(text);
1262
- const capabilityKeywords = [
1263
- "translate",
1264
- "translation",
1265
- "review",
1266
- "code",
1267
- "analyze",
1268
- "analysis",
1269
- "generate",
1270
- "generation",
1271
- "search",
1272
- "query",
1273
- "compute",
1274
- "calculation",
1275
- "store",
1276
- "storage",
1277
- "message",
1278
- "messaging",
1279
- "auth",
1280
- "authentication"
1281
- ];
1282
- for (const keyword of keywords) {
1283
- if (capabilityKeywords.includes(keyword)) {
1284
- return keyword;
1285
- }
1286
- }
1287
- return keywords[0];
1006
+ if (normalizedType === "reply" && !replyTo) {
1007
+ throw new MessagingError("Reply envelopes must include replyTo");
1288
1008
  }
1289
- };
1290
- function createSemanticSearch(dht) {
1291
- return new SemanticSearchEngine(dht);
1292
- }
1293
-
1294
- // src/messaging/envelope.ts
1295
- function createEnvelope(from, to, type, protocol, payload, replyTo) {
1296
1009
  return {
1297
1010
  id: generateMessageId(),
1298
1011
  from,
1299
1012
  to,
1300
- type,
1013
+ type: normalizedType,
1301
1014
  protocol,
1302
1015
  payload,
1303
1016
  timestamp: Date.now(),
1304
- replyTo
1017
+ ...normalizedType === "reply" ? { replyTo } : {},
1018
+ ...threadId ? { threadId } : {}
1305
1019
  };
1306
1020
  }
1307
1021
  async function signEnvelope(envelope, signFn) {
@@ -1319,7 +1033,11 @@ async function signEnvelope(envelope, signFn) {
1319
1033
  }
1320
1034
  async function verifyEnvelope(envelope, verifyFn) {
1321
1035
  try {
1322
- const { signature, ...envelopeWithoutSig } = envelope;
1036
+ const normalized = normalizeEnvelope(envelope);
1037
+ if (!normalized) {
1038
+ return false;
1039
+ }
1040
+ const { signature, ...envelopeWithoutSig } = normalized;
1323
1041
  const envelopeJson = JSON.stringify(envelopeWithoutSig);
1324
1042
  const envelopeBytes = new TextEncoder().encode(envelopeJson);
1325
1043
  const signatureBytes = Buffer.from(signature, "hex");
@@ -1329,15 +1047,15 @@ async function verifyEnvelope(envelope, verifyFn) {
1329
1047
  }
1330
1048
  }
1331
1049
  function validateEnvelope(msg) {
1332
- if (typeof msg !== "object" || msg === null) {
1333
- return false;
1334
- }
1335
- const m = msg;
1336
- return typeof m.id === "string" && typeof m.from === "string" && m.from.startsWith("did:clawiverse:") && typeof m.to === "string" && m.to.startsWith("did:clawiverse:") && (m.type === "request" || m.type === "response" || m.type === "notification") && typeof m.protocol === "string" && m.payload !== void 0 && typeof m.timestamp === "number" && typeof m.signature === "string";
1050
+ const normalized = normalizeEnvelope(msg);
1051
+ return normalized !== void 0;
1337
1052
  }
1338
1053
  function generateMessageId() {
1339
1054
  return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
1340
1055
  }
1056
+ function generateThreadId() {
1057
+ return `thread_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
1058
+ }
1341
1059
  function encodeMessage(envelope) {
1342
1060
  try {
1343
1061
  return encode(envelope);
@@ -1347,8 +1065,16 @@ function encodeMessage(envelope) {
1347
1065
  }
1348
1066
  function decodeMessage(data) {
1349
1067
  try {
1350
- return decode(data);
1068
+ const decoded = decode(data);
1069
+ const normalized = normalizeEnvelope(decoded);
1070
+ if (!normalized) {
1071
+ throw new MessagingError("Decoded message envelope is invalid");
1072
+ }
1073
+ return normalized;
1351
1074
  } catch (error) {
1075
+ if (error instanceof MessagingError) {
1076
+ throw error;
1077
+ }
1352
1078
  throw new MessagingError("Failed to decode message", error);
1353
1079
  }
1354
1080
  }
@@ -1361,30 +1087,37 @@ function encodeMessageJSON(envelope) {
1361
1087
  }
1362
1088
  function decodeMessageJSON(json) {
1363
1089
  try {
1364
- return JSON.parse(json);
1090
+ const decoded = JSON.parse(json);
1091
+ const normalized = normalizeEnvelope(decoded);
1092
+ if (!normalized) {
1093
+ throw new MessagingError("Decoded JSON envelope is invalid");
1094
+ }
1095
+ return normalized;
1365
1096
  } catch (error) {
1097
+ if (error instanceof MessagingError) {
1098
+ throw error;
1099
+ }
1366
1100
  throw new MessagingError("Failed to decode message from JSON", error);
1367
1101
  }
1368
1102
  }
1369
1103
 
1370
1104
  // src/messaging/router.ts
1371
- var logger5 = createLogger("router");
1105
+ var logger3 = createLogger("router");
1372
1106
  function createMessageRouter(relayClient, verifyFn) {
1373
1107
  const handlers = /* @__PURE__ */ new Map();
1374
1108
  let catchAllHandler;
1375
- const pendingRequests = /* @__PURE__ */ new Map();
1376
1109
  return {
1377
1110
  registerHandler: (protocol, handler) => {
1378
1111
  handlers.set(protocol, handler);
1379
- logger5.info("Registered message handler", { protocol });
1112
+ logger3.info("Registered message handler", { protocol });
1380
1113
  },
1381
1114
  unregisterHandler: (protocol) => {
1382
1115
  handlers.delete(protocol);
1383
- logger5.info("Unregistered message handler", { protocol });
1116
+ logger3.info("Unregistered message handler", { protocol });
1384
1117
  },
1385
1118
  registerCatchAllHandler: (handler) => {
1386
1119
  catchAllHandler = handler;
1387
- logger5.info("Registered catch-all message handler");
1120
+ logger3.info("Registered catch-all message handler");
1388
1121
  },
1389
1122
  sendMessage: async (envelope) => {
1390
1123
  try {
@@ -1393,25 +1126,13 @@ function createMessageRouter(relayClient, verifyFn) {
1393
1126
  }
1394
1127
  const encoded = encodeMessage(envelope);
1395
1128
  await relayClient.sendEnvelope(envelope.to, encoded);
1396
- logger5.info("Message sent via relay", {
1129
+ logger3.info("Message sent via relay", {
1397
1130
  id: envelope.id,
1398
1131
  from: envelope.from,
1399
1132
  to: envelope.to,
1400
- protocol: envelope.protocol
1133
+ protocol: envelope.protocol,
1134
+ type: envelope.type
1401
1135
  });
1402
- if (envelope.type === "request") {
1403
- logger5.debug("Waiting for response to request", { id: envelope.id });
1404
- const RESPONSE_TIMEOUT = 3e4;
1405
- return new Promise((resolve) => {
1406
- const timeout = setTimeout(() => {
1407
- pendingRequests.delete(envelope.id);
1408
- logger5.warn("Response timeout", { id: envelope.id, timeout: RESPONSE_TIMEOUT });
1409
- resolve(void 0);
1410
- }, RESPONSE_TIMEOUT);
1411
- pendingRequests.set(envelope.id, { resolve, timeout });
1412
- });
1413
- }
1414
- return void 0;
1415
1136
  } catch (error) {
1416
1137
  if (error instanceof MessagingError) throw error;
1417
1138
  throw new MessagingError("Failed to send message", error);
@@ -1422,7 +1143,7 @@ function createMessageRouter(relayClient, verifyFn) {
1422
1143
  try {
1423
1144
  const envelope = decodeMessage(deliverMsg.envelope);
1424
1145
  if (!validateEnvelope(envelope)) {
1425
- logger5.warn("Received invalid message envelope");
1146
+ logger3.warn("Received invalid message envelope");
1426
1147
  return;
1427
1148
  }
1428
1149
  const isValidSignature = await verifyEnvelope(envelope, async (signature, data) => {
@@ -1430,7 +1151,7 @@ function createMessageRouter(relayClient, verifyFn) {
1430
1151
  return verify(signature, data, senderPublicKey);
1431
1152
  });
1432
1153
  if (!isValidSignature) {
1433
- logger5.warn("Received message with invalid signature", {
1154
+ logger3.warn("Received message with invalid signature", {
1434
1155
  id: envelope.id,
1435
1156
  from: envelope.from
1436
1157
  });
@@ -1442,77 +1163,59 @@ function createMessageRouter(relayClient, verifyFn) {
1442
1163
  const signatureBytes = Buffer.from(signature, "hex");
1443
1164
  const hookValid = await verifyFn(signatureBytes, dataBytes);
1444
1165
  if (!hookValid) {
1445
- logger5.warn("Message rejected by custom verifier", {
1166
+ logger3.warn("Message rejected by custom verifier", {
1446
1167
  id: envelope.id,
1447
1168
  from: envelope.from
1448
1169
  });
1449
1170
  return;
1450
1171
  }
1451
1172
  } catch (error) {
1452
- logger5.warn("Custom verification hook failed", {
1173
+ logger3.warn("Custom verification hook failed", {
1453
1174
  id: envelope.id,
1454
1175
  from: envelope.from,
1455
1176
  error: error.message
1456
1177
  });
1457
1178
  return;
1458
1179
  }
1459
- logger5.info("Received message", {
1180
+ logger3.info("Received message", {
1460
1181
  id: envelope.id,
1461
1182
  from: envelope.from,
1462
1183
  to: envelope.to,
1463
1184
  protocol: envelope.protocol,
1464
1185
  type: envelope.type
1465
1186
  });
1466
- if (envelope.type === "response" && envelope.replyTo) {
1467
- const pending = pendingRequests.get(envelope.replyTo);
1468
- if (pending) {
1469
- clearTimeout(pending.timeout);
1470
- pendingRequests.delete(envelope.replyTo);
1471
- pending.resolve(envelope);
1472
- logger5.info("Matched response to pending request", {
1473
- requestId: envelope.replyTo,
1474
- responseId: envelope.id
1475
- });
1476
- return;
1477
- }
1478
- }
1479
1187
  const handler = handlers.get(envelope.protocol);
1480
1188
  let response = void 0;
1481
1189
  if (handler) {
1482
1190
  response = await handler(envelope);
1483
1191
  } else if (catchAllHandler) {
1484
- logger5.debug("Using catch-all handler for protocol", { protocol: envelope.protocol });
1192
+ logger3.debug("Using catch-all handler for protocol", { protocol: envelope.protocol });
1485
1193
  response = await catchAllHandler(envelope);
1486
1194
  } else {
1487
- logger5.warn("No handler for protocol", { protocol: envelope.protocol });
1195
+ logger3.warn("No handler for protocol", { protocol: envelope.protocol });
1488
1196
  }
1489
1197
  if (response) {
1490
1198
  const encoded = encodeMessage(response);
1491
1199
  await relayClient.sendEnvelope(response.to, encoded);
1492
- logger5.info("Sent response back to sender", {
1200
+ logger3.info("Sent reply back to sender", {
1493
1201
  responseId: response.id,
1494
1202
  replyTo: response.replyTo
1495
1203
  });
1496
1204
  }
1497
1205
  } catch (error) {
1498
- logger5.error("Error handling incoming message", error);
1206
+ logger3.error("Error handling incoming message", error);
1499
1207
  }
1500
1208
  });
1501
- logger5.info("Message router started");
1209
+ logger3.info("Message router started");
1502
1210
  },
1503
1211
  stop: async () => {
1504
- for (const [, pending] of pendingRequests.entries()) {
1505
- clearTimeout(pending.timeout);
1506
- pending.resolve(void 0);
1507
- }
1508
- pendingRequests.clear();
1509
1212
  handlers.clear();
1510
1213
  catchAllHandler = void 0;
1511
- logger5.info("Message router stopped");
1214
+ logger3.info("Message router stopped");
1512
1215
  }
1513
1216
  };
1514
1217
  }
1515
- var logger6 = createLogger("message-storage");
1218
+ var logger4 = createLogger("message-storage");
1516
1219
  var MessageStorage = class {
1517
1220
  db;
1518
1221
  ready = false;
@@ -1522,22 +1225,28 @@ var MessageStorage = class {
1522
1225
  async open() {
1523
1226
  await this.db.open();
1524
1227
  this.ready = true;
1525
- logger6.info("Message storage opened");
1228
+ logger4.info("Message storage opened");
1526
1229
  }
1527
1230
  async close() {
1528
1231
  if (this.ready) {
1529
1232
  await this.db.close();
1530
1233
  this.ready = false;
1531
- logger6.info("Message storage closed");
1234
+ logger4.info("Message storage closed");
1532
1235
  }
1533
1236
  }
1534
1237
  // ─── Message Operations ───────────────────────────────────────────────────
1535
1238
  async putMessage(msg) {
1536
- const ts = String(msg.receivedAt ?? msg.sentAt ?? Date.now()).padStart(16, "0");
1537
- const key = `msg:${msg.direction}:${ts}:${msg.envelope.id}`;
1538
- await this.db.put(key, msg);
1539
- const idxKey = `idx:from:${msg.envelope.from}:${ts}:${msg.envelope.id}`;
1239
+ const normalized = this.requireStoredMessage(msg);
1240
+ const ts = String(normalized.receivedAt ?? normalized.sentAt ?? Date.now()).padStart(16, "0");
1241
+ const key = `msg:${normalized.direction}:${ts}:${normalized.envelope.id}`;
1242
+ await this.db.put(key, normalized);
1243
+ const idxKey = `idx:from:${normalized.envelope.from}:${ts}:${normalized.envelope.id}`;
1540
1244
  await this.db.put(idxKey, "1");
1245
+ if (normalized.envelope.threadId) {
1246
+ const threadIdxKey = `idx:thread:${normalized.envelope.threadId}:${ts}:${normalized.envelope.id}`;
1247
+ await this.db.put(threadIdxKey, "1");
1248
+ await this.updateSessionMeta(normalized);
1249
+ }
1541
1250
  }
1542
1251
  async getMessage(id) {
1543
1252
  for (const direction of ["inbound", "outbound"]) {
@@ -1547,7 +1256,9 @@ var MessageStorage = class {
1547
1256
  lte: prefix + "\xFF",
1548
1257
  valueEncoding: "json"
1549
1258
  })) {
1550
- if (value.envelope.id === id) return value;
1259
+ if (value.envelope.id !== id) continue;
1260
+ const normalized = this.normalizeStoredMessage(value);
1261
+ if (normalized) return normalized;
1551
1262
  }
1552
1263
  }
1553
1264
  return null;
@@ -1583,13 +1294,14 @@ var MessageStorage = class {
1583
1294
  // newest first
1584
1295
  valueEncoding: "json"
1585
1296
  })) {
1586
- if (!this.matchesFilter(value, filter)) continue;
1297
+ const normalized = this.normalizeStoredMessage(value);
1298
+ if (!normalized || !this.matchesFilter(normalized, filter)) continue;
1587
1299
  total++;
1588
1300
  if (skipped < offset) {
1589
1301
  skipped++;
1590
1302
  continue;
1591
1303
  }
1592
- if (results.length < limit) results.push(value);
1304
+ if (results.length < limit) results.push(normalized);
1593
1305
  }
1594
1306
  return {
1595
1307
  messages: results,
@@ -1611,6 +1323,10 @@ var MessageStorage = class {
1611
1323
  if (!protos.includes(msg.envelope.protocol)) return false;
1612
1324
  }
1613
1325
  if (filter.type && msg.envelope.type !== filter.type) return false;
1326
+ if (filter.replyTo) {
1327
+ const replyIds = Array.isArray(filter.replyTo) ? filter.replyTo : [filter.replyTo];
1328
+ if (!msg.envelope.replyTo || !replyIds.includes(msg.envelope.replyTo)) return false;
1329
+ }
1614
1330
  if (filter.unreadOnly && msg.readAt != null) return false;
1615
1331
  if (filter.status) {
1616
1332
  const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
@@ -1621,6 +1337,7 @@ var MessageStorage = class {
1621
1337
  if (age > filter.maxAge) return false;
1622
1338
  }
1623
1339
  if (filter.minTrustScore != null && (msg.trustScore ?? 0) < filter.minTrustScore) return false;
1340
+ if (filter.threadId && msg.envelope.threadId !== filter.threadId) return false;
1624
1341
  return true;
1625
1342
  }
1626
1343
  async countMessages(direction, filter = {}) {
@@ -1631,10 +1348,29 @@ var MessageStorage = class {
1631
1348
  lte: prefix + "\xFF",
1632
1349
  valueEncoding: "json"
1633
1350
  })) {
1634
- if (this.matchesFilter(value, filter)) count++;
1351
+ const normalized = this.normalizeStoredMessage(value);
1352
+ if (normalized && this.matchesFilter(normalized, filter)) count++;
1635
1353
  }
1636
1354
  return count;
1637
1355
  }
1356
+ normalizeStoredMessage(msg) {
1357
+ const envelope = normalizeEnvelope(msg.envelope);
1358
+ if (!envelope) {
1359
+ logger4.warn("Skipping invalid stored message envelope", { id: msg.envelope?.id });
1360
+ return null;
1361
+ }
1362
+ return {
1363
+ ...msg,
1364
+ envelope
1365
+ };
1366
+ }
1367
+ requireStoredMessage(msg) {
1368
+ const normalized = this.normalizeStoredMessage(msg);
1369
+ if (!normalized) {
1370
+ throw new Error(`Invalid stored message envelope: ${msg.envelope?.id ?? "unknown"}`);
1371
+ }
1372
+ return normalized;
1373
+ }
1638
1374
  // ─── Blocklist ────────────────────────────────────────────────────────────
1639
1375
  async putBlock(entry) {
1640
1376
  await this.db.put(`block:${entry.did}`, entry);
@@ -1737,10 +1473,160 @@ var MessageStorage = class {
1737
1473
  }
1738
1474
  await this.db.batch(toDelete.map((key) => ({ type: "del", key })));
1739
1475
  }
1476
+ // ─── Session Management (CVP-0014) ────────────────────────────────────────
1477
+ async updateSessionMeta(msg) {
1478
+ if (!msg.envelope.threadId) return;
1479
+ const sessionKey = `session:${msg.envelope.threadId}`;
1480
+ let session;
1481
+ try {
1482
+ session = await this.db.get(sessionKey);
1483
+ } catch {
1484
+ const peerDid = msg.direction === "inbound" ? msg.envelope.from : msg.envelope.to;
1485
+ const text = typeof msg.envelope.payload === "object" && msg.envelope.payload !== null ? msg.envelope.payload.text ?? msg.envelope.payload.message ?? "" : String(msg.envelope.payload ?? "");
1486
+ const title = text ? String(text).slice(0, 50) : void 0;
1487
+ session = {
1488
+ threadId: msg.envelope.threadId,
1489
+ peerDid,
1490
+ startedAt: msg.receivedAt ?? msg.sentAt ?? Date.now(),
1491
+ lastMessageAt: msg.receivedAt ?? msg.sentAt ?? Date.now(),
1492
+ messageCount: 1,
1493
+ title
1494
+ };
1495
+ await this.db.put(sessionKey, session);
1496
+ return;
1497
+ }
1498
+ session.lastMessageAt = msg.receivedAt ?? msg.sentAt ?? Date.now();
1499
+ session.messageCount = (session.messageCount ?? 0) + 1;
1500
+ await this.db.put(sessionKey, session);
1501
+ }
1502
+ async getSession(threadId) {
1503
+ try {
1504
+ return await this.db.get(`session:${threadId}`);
1505
+ } catch {
1506
+ return null;
1507
+ }
1508
+ }
1509
+ async listSessions(peerDid, limit = 50, includeArchived = false) {
1510
+ const results = [];
1511
+ for await (const [, value] of this.db.iterator({
1512
+ gte: "session:",
1513
+ lte: "session:\xFF",
1514
+ reverse: true,
1515
+ // newest first
1516
+ valueEncoding: "json"
1517
+ })) {
1518
+ if (peerDid && value.peerDid !== peerDid) continue;
1519
+ if (!includeArchived && value.archived) continue;
1520
+ results.push(value);
1521
+ if (results.length >= limit) break;
1522
+ }
1523
+ return results;
1524
+ }
1525
+ async archiveSession(threadId) {
1526
+ const session = await this.getSession(threadId);
1527
+ if (!session) {
1528
+ throw new Error(`Session not found: ${threadId}`);
1529
+ }
1530
+ session.archived = true;
1531
+ session.archivedAt = Date.now();
1532
+ await this.db.put(`session:${threadId}`, session);
1533
+ }
1534
+ async unarchiveSession(threadId) {
1535
+ const session = await this.getSession(threadId);
1536
+ if (!session) {
1537
+ throw new Error(`Session not found: ${threadId}`);
1538
+ }
1539
+ session.archived = false;
1540
+ delete session.archivedAt;
1541
+ await this.db.put(`session:${threadId}`, session);
1542
+ }
1543
+ async listArchivedSessions(peerDid, limit = 50) {
1544
+ const results = [];
1545
+ for await (const [, value] of this.db.iterator({
1546
+ gte: "session:",
1547
+ lte: "session:\xFF",
1548
+ reverse: true,
1549
+ // newest first
1550
+ valueEncoding: "json"
1551
+ })) {
1552
+ if (!value.archived) continue;
1553
+ if (peerDid && value.peerDid !== peerDid) continue;
1554
+ results.push(value);
1555
+ if (results.length >= limit) break;
1556
+ }
1557
+ return results;
1558
+ }
1559
+ async searchSessions(query, limit = 50) {
1560
+ const results = [];
1561
+ const lowerQuery = query.toLowerCase();
1562
+ for await (const [, value] of this.db.iterator({
1563
+ gte: "session:",
1564
+ lte: "session:\xFF",
1565
+ reverse: true,
1566
+ // newest first
1567
+ valueEncoding: "json"
1568
+ })) {
1569
+ if (value.title && value.title.toLowerCase().includes(lowerQuery)) {
1570
+ results.push(value);
1571
+ if (results.length >= limit) break;
1572
+ continue;
1573
+ }
1574
+ if (value.peerDid && value.peerDid.toLowerCase().includes(lowerQuery)) {
1575
+ results.push(value);
1576
+ if (results.length >= limit) break;
1577
+ continue;
1578
+ }
1579
+ const messages = await this.queryMessagesByThread(value.threadId, { limit: 100 });
1580
+ for (const msg of messages.messages) {
1581
+ const payload = msg.envelope.payload;
1582
+ const text = payload?.text || payload?.message || "";
1583
+ if (text && String(text).toLowerCase().includes(lowerQuery)) {
1584
+ results.push(value);
1585
+ if (results.length >= limit) break;
1586
+ break;
1587
+ }
1588
+ }
1589
+ if (results.length >= limit) break;
1590
+ }
1591
+ return results;
1592
+ }
1593
+ async queryMessagesByThread(threadId, pagination = {}) {
1594
+ const { limit = 50, offset = 0 } = pagination;
1595
+ const prefix = `idx:thread:${threadId}:`;
1596
+ const results = [];
1597
+ let total = 0;
1598
+ let skipped = 0;
1599
+ const messageIds = [];
1600
+ for await (const [key] of this.db.iterator({
1601
+ gte: prefix,
1602
+ lte: prefix + "\xFF",
1603
+ reverse: false
1604
+ // chronological order
1605
+ })) {
1606
+ const parts = key.split(":");
1607
+ const msgId = parts[parts.length - 1];
1608
+ messageIds.push(msgId);
1609
+ }
1610
+ for (const msgId of messageIds) {
1611
+ const msg = await this.getMessage(msgId);
1612
+ if (!msg) continue;
1613
+ total++;
1614
+ if (skipped < offset) {
1615
+ skipped++;
1616
+ continue;
1617
+ }
1618
+ if (results.length < limit) results.push(msg);
1619
+ }
1620
+ return {
1621
+ messages: results,
1622
+ total,
1623
+ hasMore: total > offset + results.length
1624
+ };
1625
+ }
1740
1626
  };
1741
1627
 
1742
1628
  // src/messaging/queue.ts
1743
- var logger7 = createLogger("message-queue");
1629
+ var logger5 = createLogger("message-queue");
1744
1630
  var MessageQueue = class {
1745
1631
  storage;
1746
1632
  subscriptions = /* @__PURE__ */ new Map();
@@ -1753,12 +1639,12 @@ var MessageQueue = class {
1753
1639
  }
1754
1640
  async start() {
1755
1641
  await this.storage.open();
1756
- logger7.info("Message queue started");
1642
+ logger5.info("Message queue started");
1757
1643
  }
1758
1644
  async stop() {
1759
1645
  await this.storage.close();
1760
1646
  this.subscriptions.clear();
1761
- logger7.info("Message queue stopped");
1647
+ logger5.info("Message queue stopped");
1762
1648
  }
1763
1649
  // ─── Inbox ────────────────────────────────────────────────────────────────
1764
1650
  async getInbox(filter = {}, pagination = {}) {
@@ -1781,16 +1667,17 @@ var MessageQueue = class {
1781
1667
  await this.storage.updateMessage(id, { status: "pending", error: void 0 });
1782
1668
  }
1783
1669
  // ─── Enqueue ──────────────────────────────────────────────────────────────
1784
- async enqueueInbound(envelope, trustScore) {
1670
+ async enqueueInbound(envelope, trustScore, trustStatus) {
1785
1671
  const msg = {
1786
1672
  envelope,
1787
1673
  direction: "inbound",
1788
1674
  status: "pending",
1789
1675
  receivedAt: Date.now(),
1790
- trustScore
1676
+ trustScore,
1677
+ trustStatus
1791
1678
  };
1792
1679
  await this.storage.putMessage(msg);
1793
- logger7.debug("Enqueued inbound message", { id: envelope.id, from: envelope.from });
1680
+ logger5.debug("Enqueued inbound message", { id: envelope.id, from: envelope.from });
1794
1681
  this.notifySubscribers(msg);
1795
1682
  return msg;
1796
1683
  }
@@ -1802,7 +1689,7 @@ var MessageQueue = class {
1802
1689
  sentAt: Date.now()
1803
1690
  };
1804
1691
  await this.storage.putMessage(msg);
1805
- logger7.debug("Enqueued outbound message", { id: envelope.id, to: envelope.to });
1692
+ logger5.debug("Enqueued outbound message", { id: envelope.id, to: envelope.to });
1806
1693
  return msg;
1807
1694
  }
1808
1695
  async markOutboundDelivered(id) {
@@ -1815,18 +1702,18 @@ var MessageQueue = class {
1815
1702
  subscribe(filter, callback) {
1816
1703
  const id = `sub_${++this.subCounter}`;
1817
1704
  this.subscriptions.set(id, { id, filter, callback });
1818
- logger7.debug("Subscription added", { id });
1705
+ logger5.debug("Subscription added", { id });
1819
1706
  return id;
1820
1707
  }
1821
1708
  unsubscribe(subscriptionId) {
1822
1709
  this.subscriptions.delete(subscriptionId);
1823
- logger7.debug("Subscription removed", { id: subscriptionId });
1710
+ logger5.debug("Subscription removed", { id: subscriptionId });
1824
1711
  }
1825
1712
  notifySubscribers(msg) {
1826
1713
  for (const sub of this.subscriptions.values()) {
1827
1714
  if (this.matchesSubscriptionFilter(msg, sub.filter)) {
1828
1715
  Promise.resolve(sub.callback(msg)).catch((err) => {
1829
- logger7.warn("Subscription callback error", { id: sub.id, error: err.message });
1716
+ logger5.warn("Subscription callback error", { id: sub.id, error: err.message });
1830
1717
  });
1831
1718
  }
1832
1719
  }
@@ -1841,6 +1728,11 @@ var MessageQueue = class {
1841
1728
  if (!protos.includes(msg.envelope.protocol)) return false;
1842
1729
  }
1843
1730
  if (filter.type && msg.envelope.type !== filter.type) return false;
1731
+ if (filter.replyTo) {
1732
+ const replyIds = Array.isArray(filter.replyTo) ? filter.replyTo : [filter.replyTo];
1733
+ if (!msg.envelope.replyTo || !replyIds.includes(msg.envelope.replyTo)) return false;
1734
+ }
1735
+ if (filter.threadId && msg.envelope.threadId !== filter.threadId) return false;
1844
1736
  return true;
1845
1737
  }
1846
1738
  // ─── Stats ────────────────────────────────────────────────────────────────
@@ -1925,12 +1817,11 @@ function getTierConfig(trustScore, tiers) {
1925
1817
  }
1926
1818
 
1927
1819
  // src/messaging/defense.ts
1928
- var logger8 = createLogger("defense");
1820
+ var logger6 = createLogger("defense");
1929
1821
  var DefenseMiddleware = class {
1930
1822
  trust;
1931
1823
  storage;
1932
1824
  minTrustScore;
1933
- autoBlockThreshold;
1934
1825
  tiers;
1935
1826
  seenTtlMs;
1936
1827
  // In-memory LRU-style seen cache (backed by LevelDB for persistence)
@@ -1943,7 +1834,6 @@ var DefenseMiddleware = class {
1943
1834
  this.trust = config.trustSystem;
1944
1835
  this.storage = config.storage;
1945
1836
  this.minTrustScore = config.minTrustScore ?? 0;
1946
- this.autoBlockThreshold = config.autoBlockThreshold ?? 0.1;
1947
1837
  this.tiers = config.rateLimitTiers ?? DEFAULT_RATE_LIMIT_TIERS;
1948
1838
  this.seenTtlMs = config.seenTtlMs ?? 60 * 60 * 1e3;
1949
1839
  }
@@ -1956,36 +1846,47 @@ var DefenseMiddleware = class {
1956
1846
  const did = envelope.from;
1957
1847
  if (await this.isAllowed(did)) {
1958
1848
  this.markAsSeen(envelope.id);
1959
- return { allowed: true };
1849
+ return { allowed: true, trustStatus: "allowed" };
1960
1850
  }
1961
1851
  if (await this.isBlocked(did)) {
1962
- logger8.debug("Message rejected: blocked", { id: envelope.id, from: did });
1852
+ logger6.debug("Message rejected: blocked", { id: envelope.id, from: did });
1963
1853
  return { allowed: false, reason: "blocked" };
1964
1854
  }
1855
+ if (this.trust.isRateLimited(did)) {
1856
+ logger6.debug("Message rejected: sybil rate limited", { id: envelope.id, from: did });
1857
+ return { allowed: false, reason: "rate_limited" };
1858
+ }
1965
1859
  if (this.hasSeen(envelope.id)) {
1966
- logger8.debug("Message rejected: duplicate", { id: envelope.id });
1860
+ logger6.debug("Message rejected: duplicate", { id: envelope.id });
1967
1861
  return { allowed: false, reason: "duplicate" };
1968
1862
  }
1969
1863
  let trustScore = 0;
1864
+ let trustStatus = "unknown";
1970
1865
  try {
1971
1866
  const score = await this.trust.getTrustScore(did);
1972
1867
  trustScore = score.interactionScore;
1973
- const hasHistory = (score.totalInteractions ?? 0) >= 5;
1974
- if (hasHistory && trustScore < this.autoBlockThreshold && trustScore > 0) {
1975
- logger8.warn("Auto-blocking low-trust agent", { did, trustScore });
1976
- await this.blockAgent(did, `Auto-blocked: trust score ${trustScore.toFixed(2)} below threshold`);
1868
+ trustStatus = score.status;
1869
+ const totalInteractions = score.totalInteractions ?? 0;
1870
+ const recentFailureRate = 1 - (score.recentSuccessRate ?? 1);
1871
+ if (totalInteractions >= 10 && recentFailureRate > 0.5) {
1872
+ logger6.warn("Suspicious agent detected", { did, recentFailureRate: recentFailureRate.toFixed(2), totalInteractions });
1873
+ trustScore = 0;
1874
+ }
1875
+ if (totalInteractions >= 20 && recentFailureRate > 0.7) {
1876
+ logger6.warn("Auto-blocking high-failure-rate agent", { did, recentFailureRate: recentFailureRate.toFixed(2), totalInteractions });
1877
+ await this.blockAgent(did, `Auto-blocked: ${(recentFailureRate * 100).toFixed(0)}% failure rate over last 20 interactions`);
1977
1878
  return { allowed: false, reason: "blocked" };
1978
1879
  }
1979
1880
  if (trustScore < this.minTrustScore) {
1980
- logger8.debug("Message rejected: trust too low", { id: envelope.id, trustScore });
1881
+ logger6.debug("Message rejected: trust too low", { id: envelope.id, trustScore });
1981
1882
  return { allowed: false, reason: "trust_too_low", trustScore };
1982
1883
  }
1983
1884
  } catch (err) {
1984
- logger8.warn("Trust score lookup failed, using 0", { did, error: err.message });
1885
+ logger6.warn("Trust score lookup failed, using 0", { did, error: err.message });
1985
1886
  }
1986
1887
  const rateLimitResult = await this.checkRateLimit(did, trustScore);
1987
1888
  if (!rateLimitResult.allowed) {
1988
- logger8.debug("Message rejected: rate limited", {
1889
+ logger6.debug("Message rejected: rate limited", {
1989
1890
  id: envelope.id,
1990
1891
  from: did,
1991
1892
  resetTime: rateLimitResult.resetTime
@@ -1998,16 +1899,16 @@ var DefenseMiddleware = class {
1998
1899
  };
1999
1900
  }
2000
1901
  this.markAsSeen(envelope.id);
2001
- return { allowed: true, trustScore, remainingTokens: rateLimitResult.remaining };
1902
+ return { allowed: true, trustScore, trustStatus, remainingTokens: rateLimitResult.remaining };
2002
1903
  }
2003
1904
  // ─── Blocklist ────────────────────────────────────────────────────────────
2004
1905
  async blockAgent(did, reason, blockedBy = "local") {
2005
1906
  await this.storage.putBlock({ did, reason, blockedAt: Date.now(), blockedBy });
2006
- logger8.info("Agent blocked", { did, reason });
1907
+ logger6.info("Agent blocked", { did, reason });
2007
1908
  }
2008
1909
  async unblockAgent(did) {
2009
1910
  await this.storage.deleteBlock(did);
2010
- logger8.info("Agent unblocked", { did });
1911
+ logger6.info("Agent unblocked", { did });
2011
1912
  }
2012
1913
  async isBlocked(did) {
2013
1914
  return await this.storage.getBlock(did) !== null;
@@ -2015,11 +1916,11 @@ var DefenseMiddleware = class {
2015
1916
  // ─── Allowlist ────────────────────────────────────────────────────────────
2016
1917
  async allowAgent(did, note) {
2017
1918
  await this.storage.putAllow({ did, addedAt: Date.now(), note });
2018
- logger8.info("Agent allowlisted", { did });
1919
+ logger6.info("Agent allowlisted", { did });
2019
1920
  }
2020
1921
  async removeFromAllowlist(did) {
2021
1922
  await this.storage.deleteAllow(did);
2022
- logger8.info("Agent removed from allowlist", { did });
1923
+ logger6.info("Agent removed from allowlist", { did });
2023
1924
  }
2024
1925
  async isAllowed(did) {
2025
1926
  return await this.storage.getAllow(did) !== null;
@@ -2088,41 +1989,51 @@ var DefenseMiddleware = class {
2088
1989
  // src/trust/trust-score.ts
2089
1990
  var TrustMetrics = class {
2090
1991
  /**
2091
- * Calculate trust score from interaction history
1992
+ * Calculate trust score from interaction history.
1993
+ * @param endorsementScore - Average endorsement score (0-1), not count
2092
1994
  */
2093
- calculateScore(stats, endorsements, uptime) {
2094
- const volumeWeight = Math.min(stats.totalInteractions / 100, 1);
2095
- const interactionScore = stats.successRate * volumeWeight;
2096
- const completionRate = stats.successRate;
1995
+ calculateScore(stats, endorsementScore, uptime) {
1996
+ const maturityWeight = Math.min(stats.totalInteractions / 50, 1);
1997
+ const interactionScore = stats.successRate * maturityWeight;
1998
+ const status = this.deriveStatus(stats);
2097
1999
  return {
2098
2000
  interactionScore,
2099
- endorsements,
2100
- completionRate,
2001
+ endorsements: 0,
2002
+ // kept for backwards compat
2003
+ endorsementScore,
2004
+ completionRate: stats.successRate,
2101
2005
  responseTime: stats.avgResponseTime,
2102
2006
  uptime,
2103
2007
  lastUpdated: Date.now(),
2104
- totalInteractions: stats.totalInteractions
2008
+ totalInteractions: stats.totalInteractions,
2009
+ recentSuccessRate: stats.recentSuccessRate,
2010
+ status
2105
2011
  };
2106
2012
  }
2013
+ deriveStatus(stats) {
2014
+ if (stats.totalInteractions === 0) return "unknown";
2015
+ const recentFailureRate = 1 - stats.recentSuccessRate;
2016
+ if (stats.totalInteractions >= 10 && recentFailureRate > 0.5) return "suspicious";
2017
+ return "known";
2018
+ }
2107
2019
  /**
2108
2020
  * Calculate overall trust level (0-1)
2021
+ * @param score - TrustScore
2022
+ * @param endorsementScore - Average endorsement score (0-1)
2109
2023
  */
2110
2024
  calculateOverallTrust(score) {
2111
2025
  const weights = {
2112
- interaction: 0.4,
2113
- endorsement: 0.2,
2114
- completion: 0.2,
2115
- uptime: 0.2
2026
+ interaction: 0.6,
2027
+ endorsement: 0.4
2116
2028
  };
2117
- const endorsementScore = Math.min(score.endorsements / 10, 1);
2118
- return score.interactionScore * weights.interaction + endorsementScore * weights.endorsement + score.completionRate * weights.completion + score.uptime * weights.uptime;
2029
+ return score.interactionScore * weights.interaction + score.endorsementScore * weights.endorsement;
2119
2030
  }
2120
2031
  /**
2121
2032
  * Get trust level category
2122
2033
  */
2123
2034
  getTrustLevel(score) {
2124
2035
  const overall = this.calculateOverallTrust(score);
2125
- if (score.interactionScore === 0) return "new";
2036
+ if (score.totalInteractions === 0) return "new";
2126
2037
  if (overall < 0.3) return "low";
2127
2038
  if (overall < 0.6) return "medium";
2128
2039
  if (overall < 0.8) return "high";
@@ -2134,12 +2045,8 @@ var TrustMetrics = class {
2134
2045
  shouldRateLimit(score, agentAge) {
2135
2046
  const overall = this.calculateOverallTrust(score);
2136
2047
  const ONE_DAY = 24 * 60 * 60 * 1e3;
2137
- if (agentAge < ONE_DAY && overall < 0.3) {
2138
- return true;
2139
- }
2140
- if (overall < 0.1) {
2141
- return true;
2142
- }
2048
+ if (agentAge < ONE_DAY && overall < 0.3) return true;
2049
+ if (overall < 0.1) return true;
2143
2050
  return false;
2144
2051
  }
2145
2052
  };
@@ -2147,14 +2054,17 @@ function createDefaultTrustScore() {
2147
2054
  return {
2148
2055
  interactionScore: 0,
2149
2056
  endorsements: 0,
2057
+ endorsementScore: 0,
2150
2058
  completionRate: 0,
2151
2059
  responseTime: 0,
2152
2060
  uptime: 0,
2153
2061
  lastUpdated: Date.now(),
2154
- totalInteractions: 0
2062
+ totalInteractions: 0,
2063
+ recentSuccessRate: 1,
2064
+ status: "unknown"
2155
2065
  };
2156
2066
  }
2157
- var logger9 = createLogger("interaction-history");
2067
+ var logger7 = createLogger("interaction-history");
2158
2068
  var InteractionHistory = class {
2159
2069
  db;
2160
2070
  constructor(dbPath) {
@@ -2165,14 +2075,14 @@ var InteractionHistory = class {
2165
2075
  */
2166
2076
  async open() {
2167
2077
  await this.db.open();
2168
- logger9.info("Interaction history database opened", { path: this.db.location });
2078
+ logger7.info("Interaction history database opened", { path: this.db.location });
2169
2079
  }
2170
2080
  /**
2171
2081
  * Close database connection
2172
2082
  */
2173
2083
  async close() {
2174
2084
  await this.db.close();
2175
- logger9.info("Interaction history database closed");
2085
+ logger7.info("Interaction history database closed");
2176
2086
  }
2177
2087
  /**
2178
2088
  * Record an interaction
@@ -2180,7 +2090,7 @@ var InteractionHistory = class {
2180
2090
  async record(interaction) {
2181
2091
  const key = `interaction:${interaction.agentDid}:${interaction.timestamp}`;
2182
2092
  await this.db.put(key, interaction);
2183
- logger9.debug("Recorded interaction", { agentDid: interaction.agentDid, type: interaction.type });
2093
+ logger7.debug("Recorded interaction", { agentDid: interaction.agentDid, type: interaction.type });
2184
2094
  }
2185
2095
  /**
2186
2096
  * Get interaction history for an agent
@@ -2199,7 +2109,7 @@ var InteractionHistory = class {
2199
2109
  interactions.push(value);
2200
2110
  }
2201
2111
  } catch (error) {
2202
- logger9.error("Failed to get interaction history", { agentDid, error });
2112
+ logger7.error("Failed to get interaction history", { agentDid, error });
2203
2113
  }
2204
2114
  return interactions;
2205
2115
  }
@@ -2212,15 +2122,21 @@ var InteractionHistory = class {
2212
2122
  return {
2213
2123
  totalInteractions: 0,
2214
2124
  successRate: 0,
2125
+ recentSuccessRate: 1,
2126
+ // No history → assume good (don't penalize new agents)
2215
2127
  avgResponseTime: 0,
2216
2128
  lastInteraction: 0
2217
2129
  };
2218
2130
  }
2219
2131
  const successCount = history.filter((i) => i.success).length;
2220
2132
  const totalResponseTime = history.reduce((sum, i) => sum + i.responseTime, 0);
2133
+ const recent = history.slice(0, 20);
2134
+ const recentSuccessCount = recent.filter((i) => i.success).length;
2135
+ const recentSuccessRate = recentSuccessCount / recent.length;
2221
2136
  return {
2222
2137
  totalInteractions: history.length,
2223
2138
  successRate: successCount / history.length,
2139
+ recentSuccessRate,
2224
2140
  avgResponseTime: totalResponseTime / history.length,
2225
2141
  lastInteraction: history[0].timestamp
2226
2142
  };
@@ -2238,7 +2154,7 @@ var InteractionHistory = class {
2238
2154
  }
2239
2155
  }
2240
2156
  } catch (error) {
2241
- logger9.error("Failed to get all agents", { error });
2157
+ logger7.error("Failed to get all agents", { error });
2242
2158
  }
2243
2159
  return Array.from(agents);
2244
2160
  }
@@ -2255,7 +2171,7 @@ var InteractionHistory = class {
2255
2171
  keysToDelete.push(key);
2256
2172
  }
2257
2173
  await this.db.batch(keysToDelete.map((key) => ({ type: "del", key })));
2258
- logger9.info("Deleted interaction history", { agentDid, count: keysToDelete.length });
2174
+ logger7.info("Deleted interaction history", { agentDid, count: keysToDelete.length });
2259
2175
  }
2260
2176
  /**
2261
2177
  * Clean up old interactions (older than 90 days)
@@ -2270,21 +2186,65 @@ var InteractionHistory = class {
2270
2186
  }
2271
2187
  if (keysToDelete.length > 0) {
2272
2188
  await this.db.batch(keysToDelete.map((key) => ({ type: "del", key })));
2273
- logger9.info("Cleaned up old interactions", { count: keysToDelete.length });
2189
+ logger7.info("Cleaned up old interactions", { count: keysToDelete.length });
2274
2190
  }
2275
2191
  return keysToDelete.length;
2276
2192
  }
2277
2193
  };
2278
2194
 
2279
2195
  // src/trust/endorsement.ts
2280
- var logger10 = createLogger("endorsement");
2196
+ var logger8 = createLogger("endorsement");
2197
+ var FAST_DOMAINS = ["translation", "transcription", "data-entry", "moderation"];
2198
+ var SLOW_DOMAINS = ["research", "architecture", "security-audit", "legal-review"];
2199
+ function getDefaultExpiration(domain) {
2200
+ if (!domain) return 180;
2201
+ if (FAST_DOMAINS.includes(domain)) return 90;
2202
+ if (SLOW_DOMAINS.includes(domain)) return 365;
2203
+ return 180;
2204
+ }
2205
+ function validateDomain(domain) {
2206
+ const pattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;
2207
+ return pattern.test(domain) && domain.length <= 64;
2208
+ }
2281
2209
  var EndorsementManager = class {
2282
2210
  constructor(db, getPublicKey) {
2283
2211
  this.db = db;
2284
2212
  this.getPublicKey = getPublicKey;
2285
2213
  }
2286
2214
  /**
2287
- * Create an endorsement
2215
+ * Create an endorsement (v2)
2216
+ */
2217
+ async endorseV2(fromDid, toDid, score, reason, signFn, domain, expires) {
2218
+ if (score < 0 || score > 1) {
2219
+ throw new Error("Score must be between 0 and 1");
2220
+ }
2221
+ if (domain && !validateDomain(domain)) {
2222
+ throw new Error("Invalid domain format. Must match ^[a-z0-9]+(-[a-z0-9]+)*$ and be <= 64 chars");
2223
+ }
2224
+ const timestamp = Date.now();
2225
+ const defaultExpires = timestamp + getDefaultExpiration(domain) * 24 * 60 * 60 * 1e3;
2226
+ const endorsement = {
2227
+ version: 2,
2228
+ from: fromDid,
2229
+ to: toDid,
2230
+ score,
2231
+ domain,
2232
+ reason,
2233
+ timestamp,
2234
+ expires: expires || defaultExpires
2235
+ };
2236
+ const data = new TextEncoder().encode(JSON.stringify(endorsement));
2237
+ const signatureBytes = await signFn(data);
2238
+ const signature = Buffer.from(signatureBytes).toString("hex");
2239
+ const signedEndorsement = {
2240
+ ...endorsement,
2241
+ signature
2242
+ };
2243
+ logger8.info("Created endorsement v2", { from: fromDid, to: toDid, score, domain });
2244
+ return signedEndorsement;
2245
+ }
2246
+ /**
2247
+ * Create an endorsement (v1 - legacy)
2288
2248
  */
2289
2249
  async endorse(fromDid, toDid, score, reason, signFn) {
2290
2250
  if (score < 0 || score > 1) {
@@ -2304,11 +2264,26 @@ var EndorsementManager = class {
2304
2264
  ...endorsement,
2305
2265
  signature
2306
2266
  };
2307
- logger10.info("Created endorsement", { from: fromDid, to: toDid, score });
2267
+ logger8.info("Created endorsement", { from: fromDid, to: toDid, score });
2308
2268
  return signedEndorsement;
2309
2269
  }
2310
2270
  /**
2311
- * Verify endorsement signature
2271
+ * Verify endorsement signature (v2)
2272
+ */
2273
+ async verifyV2(endorsement, verifyFn) {
2274
+ try {
2275
+ const { signature, ...endorsementWithoutSig } = endorsement;
2276
+ const data = new TextEncoder().encode(JSON.stringify(endorsementWithoutSig));
2277
+ const signatureBytes = Buffer.from(signature, "hex");
2278
+ const publicKey = await this.getPublicKey(endorsement.from);
2279
+ return await verifyFn(signatureBytes, data, publicKey);
2280
+ } catch (error) {
2281
+ logger8.error("Failed to verify endorsement v2", { error });
2282
+ return false;
2283
+ }
2284
+ }
2285
+ /**
2286
+ * Verify endorsement signature (v1)
2312
2287
  */
2313
2288
  async verify(endorsement, verifyFn) {
2314
2289
  try {
@@ -2318,17 +2293,36 @@ var EndorsementManager = class {
2318
2293
  const publicKey = await this.getPublicKey(endorsement.from);
2319
2294
  return await verifyFn(signatureBytes, data, publicKey);
2320
2295
  } catch (error) {
2321
- logger10.error("Failed to verify endorsement", { error });
2296
+ logger8.error("Failed to verify endorsement", { error });
2322
2297
  return false;
2323
2298
  }
2324
2299
  }
2300
+ /**
2301
+ * Upgrade v1 endorsement to v2
2302
+ */
2303
+ upgradeEndorsement(e) {
2304
+ return {
2305
+ version: 2,
2306
+ from: e.from,
2307
+ to: e.to,
2308
+ score: e.score,
2309
+ domain: void 0,
2310
+ // v1 endorsements are domain-agnostic
2311
+ reason: e.reason,
2312
+ timestamp: e.timestamp,
2313
+ expires: e.timestamp + 90 * 24 * 60 * 60 * 1e3,
2314
+ // 90-day default
2315
+ signature: e.signature
2316
+ // v1 signature remains valid
2317
+ };
2318
+ }
2325
2319
  /**
2326
2320
  * Publish endorsement to local database
2327
2321
  */
2328
2322
  async publish(endorsement) {
2329
2323
  const key = `endorsement:${endorsement.to}:${endorsement.from}`;
2330
2324
  await this.db.put(key, endorsement);
2331
- logger10.info("Published endorsement", { from: endorsement.from, to: endorsement.to });
2325
+ logger8.info("Published endorsement", { from: endorsement.from, to: endorsement.to });
2332
2326
  }
2333
2327
  /**
2334
2328
  * Get all endorsements for an agent
@@ -2344,7 +2338,7 @@ var EndorsementManager = class {
2344
2338
  endorsements.push(value);
2345
2339
  }
2346
2340
  } catch (error) {
2347
- logger10.error("Failed to get endorsements", { agentDid, error });
2341
+ logger8.error("Failed to get endorsements", { agentDid, error });
2348
2342
  }
2349
2343
  return endorsements;
2350
2344
  }
@@ -2360,7 +2354,7 @@ var EndorsementManager = class {
2360
2354
  }
2361
2355
  }
2362
2356
  } catch (error) {
2363
- logger10.error("Failed to get endorsements by agent", { fromDid, error });
2357
+ logger8.error("Failed to get endorsements by agent", { fromDid, error });
2364
2358
  }
2365
2359
  return endorsements;
2366
2360
  }
@@ -2381,10 +2375,29 @@ var EndorsementManager = class {
2381
2375
  async deleteEndorsement(fromDid, toDid) {
2382
2376
  const key = `endorsement:${toDid}:${fromDid}`;
2383
2377
  await this.db.del(key);
2384
- logger10.info("Deleted endorsement", { from: fromDid, to: toDid });
2378
+ logger8.info("Deleted endorsement", { from: fromDid, to: toDid });
2379
+ }
2380
+ /**
2381
+ * Publish endorsement to relay (CVP-0017)
2382
+ */
2383
+ async publishToRelay(relay, endorsement) {
2384
+ logger8.info("Publishing endorsement to relay", { from: endorsement.from, to: endorsement.to });
2385
+ return await relay.publishEndorsement(endorsement);
2386
+ }
2387
+ /**
2388
+ * Query endorsements from relay (CVP-0017)
2389
+ */
2390
+ async queryFromRelay(relay, target, domain, since) {
2391
+ logger8.info("Querying endorsements from relay", { target, domain });
2392
+ const result = await relay.queryTrust(target, domain, since);
2393
+ return {
2394
+ endorsements: result.endorsements,
2395
+ total: result.endorsementCount ?? result.endorsements.length,
2396
+ averageScore: result.averageScore ?? (result.endorsements.length > 0 ? result.endorsements.reduce((sum, e) => sum + e.score, 0) / result.endorsements.length : 0)
2397
+ };
2385
2398
  }
2386
2399
  };
2387
- var logger11 = createLogger("sybil-defense");
2400
+ var logger9 = createLogger("sybil-defense");
2388
2401
  var SybilDefense = class {
2389
2402
  rateLimits = /* @__PURE__ */ new Map();
2390
2403
  peerFirstSeen = /* @__PURE__ */ new Map();
@@ -2414,7 +2427,7 @@ var SybilDefense = class {
2414
2427
  verifyChallenge(solution) {
2415
2428
  const { challenge, solution: solutionNonce } = solution;
2416
2429
  if (Date.now() - challenge.timestamp > 60 * 60 * 1e3) {
2417
- logger11.warn("Challenge expired", { did: challenge.did });
2430
+ logger9.warn("Challenge expired", { did: challenge.did });
2418
2431
  return false;
2419
2432
  }
2420
2433
  const data = `${challenge.did}:${challenge.nonce}:${solutionNonce}`;
@@ -2422,9 +2435,9 @@ var SybilDefense = class {
2422
2435
  const leadingZeros = this.countLeadingZeroBits(hash);
2423
2436
  const valid = leadingZeros >= challenge.difficulty;
2424
2437
  if (valid) {
2425
- logger11.info("Challenge verified", { did: challenge.did, leadingZeros });
2438
+ logger9.info("Challenge verified", { did: challenge.did, leadingZeros });
2426
2439
  } else {
2427
- logger11.warn("Challenge failed", { did: challenge.did, leadingZeros, required: challenge.difficulty });
2440
+ logger9.warn("Challenge failed", { did: challenge.did, leadingZeros, required: challenge.difficulty });
2428
2441
  }
2429
2442
  return valid;
2430
2443
  }
@@ -2464,7 +2477,7 @@ var SybilDefense = class {
2464
2477
  record.requests = record.requests.filter(
2465
2478
  (t) => now - t < this.RATE_LIMIT_WINDOW
2466
2479
  );
2467
- logger11.debug("Recorded request", { did, count: record.requests.length });
2480
+ logger9.debug("Recorded request", { did, count: record.requests.length });
2468
2481
  }
2469
2482
  /**
2470
2483
  * Get peer trust level based on age
@@ -2489,7 +2502,7 @@ var SybilDefense = class {
2489
2502
  recordPeerSeen(peerId) {
2490
2503
  if (!this.peerFirstSeen.has(peerId)) {
2491
2504
  this.peerFirstSeen.set(peerId, Date.now());
2492
- logger11.debug("Recorded new peer", { peerId });
2505
+ logger9.debug("Recorded new peer", { peerId });
2493
2506
  }
2494
2507
  }
2495
2508
  /**
@@ -2503,7 +2516,7 @@ var SybilDefense = class {
2503
2516
  this.rateLimits.delete(did);
2504
2517
  }
2505
2518
  }
2506
- logger11.info("Cleaned up Sybil defense records", {
2519
+ logger9.info("Cleaned up Sybil defense records", {
2507
2520
  rateLimits: this.rateLimits.size,
2508
2521
  peers: this.peerFirstSeen.size
2509
2522
  });
@@ -2536,7 +2549,342 @@ var SybilDefense = class {
2536
2549
  return count;
2537
2550
  }
2538
2551
  };
2539
- var logger12 = createLogger("trust-system");
2552
+
2553
+ // src/trust/trust-computer.ts
2554
+ var logger10 = createLogger("trust-computer");
2555
+ var DEFAULT_CONFIG = {
2556
+ seedPeers: [],
2557
+ maxRecursionDepth: 3,
2558
+ decayHalfLife: {
2559
+ default: 90,
2560
+ translation: 30,
2561
+ transcription: 30,
2562
+ "data-entry": 30,
2563
+ moderation: 30,
2564
+ research: 180,
2565
+ architecture: 180,
2566
+ "security-audit": 180,
2567
+ "legal-review": 180
2568
+ },
2569
+ localInteractionWeight: 0.6,
2570
+ networkEndorsementWeight: 0.4
2571
+ };
2572
+ var TrustComputer = class {
2573
+ config;
2574
+ cache = /* @__PURE__ */ new Map();
2575
+ CACHE_TTL = 5 * 60 * 1e3;
2576
+ // 5 minutes
2577
+ // Cached SCC results: endorser DID → penalty factor (1.0 = no penalty, 0.1 = collusion)
2578
+ sccPenaltyCache = /* @__PURE__ */ new Map();
2579
+ sccCacheExpiresAt = 0;
2580
+ SCC_CACHE_TTL = 5 * 60 * 1e3;
2581
+ // 5 minutes
2582
+ // Endorsements by target DID, used for recursive weight lookup
2583
+ endorsementsByTarget = /* @__PURE__ */ new Map();
2584
+ constructor(config = {}) {
2585
+ this.config = {
2586
+ ...DEFAULT_CONFIG,
2587
+ ...config,
2588
+ decayHalfLife: {
2589
+ ...DEFAULT_CONFIG.decayHalfLife,
2590
+ ...config.decayHalfLife
2591
+ }
2592
+ };
2593
+ if (this.config.maxRecursionDepth > 6) {
2594
+ logger10.warn("Max recursion depth capped at 6", { requested: this.config.maxRecursionDepth });
2595
+ this.config.maxRecursionDepth = 6;
2596
+ }
2597
+ }
2598
+ /**
2599
+ * Compute trust score for a target DID.
2600
+ * allEndorsements: flat list of all endorsements known to the caller (used for recursive weight lookup).
2601
+ */
2602
+ compute(target, endorsements, localInteractionScore = 0, localInteractionCount = 0, domain, allEndorsements) {
2603
+ const cached = this.cache.get(this.getCacheKey(target, domain));
2604
+ if (cached && cached.expiresAt > Date.now()) {
2605
+ logger10.debug("Trust score cache hit", { target, domain });
2606
+ return cached.result;
2607
+ }
2608
+ if (allEndorsements && allEndorsements.length > 0) {
2609
+ this.endorsementsByTarget.clear();
2610
+ for (const e of allEndorsements) {
2611
+ if (!this.endorsementsByTarget.has(e.to)) {
2612
+ this.endorsementsByTarget.set(e.to, []);
2613
+ }
2614
+ this.endorsementsByTarget.get(e.to).push(e);
2615
+ }
2616
+ }
2617
+ const allEnds = allEndorsements ?? endorsements;
2618
+ if (Date.now() > this.sccCacheExpiresAt) {
2619
+ this.rebuildSccPenaltyCache(allEnds);
2620
+ }
2621
+ const filteredEndorsements = this.filterByDomain(endorsements, domain);
2622
+ const networkScore = this.computeNetworkTrust(target, filteredEndorsements, domain);
2623
+ const alpha = Math.min(localInteractionCount / 20, 0.8);
2624
+ const score = alpha * localInteractionScore + (1 - alpha) * networkScore;
2625
+ const collusionDetected = this.detectCollusion(target, allEnds);
2626
+ const result = {
2627
+ score,
2628
+ localScore: localInteractionScore,
2629
+ networkScore,
2630
+ endorsementCount: filteredEndorsements.length,
2631
+ collusionDetected,
2632
+ computedAt: Date.now()
2633
+ };
2634
+ this.cache.set(this.getCacheKey(target, domain), {
2635
+ result,
2636
+ expiresAt: Date.now() + this.CACHE_TTL
2637
+ });
2638
+ logger10.debug("Computed trust score", { target, domain, score, networkScore, collusionDetected });
2639
+ return result;
2640
+ }
2641
+ /**
2642
+ * Compute network trust score using EigenTrust-lite
2643
+ */
2644
+ computeNetworkTrust(target, endorsements, domain, depth = 0, visited = /* @__PURE__ */ new Set()) {
2645
+ if (endorsements.length === 0) {
2646
+ return 0;
2647
+ }
2648
+ if (depth >= this.config.maxRecursionDepth) {
2649
+ return 0.1;
2650
+ }
2651
+ if (visited.has(target)) {
2652
+ return 0.1;
2653
+ }
2654
+ visited.add(target);
2655
+ const now = Date.now();
2656
+ let weightedSum = 0;
2657
+ let totalWeight = 0;
2658
+ for (const endorsement of endorsements) {
2659
+ if (endorsement.expires && endorsement.expires < now) {
2660
+ continue;
2661
+ }
2662
+ const endorserWeight = this.getEndorserWeight(
2663
+ endorsement.from,
2664
+ domain,
2665
+ depth + 1,
2666
+ visited
2667
+ );
2668
+ const timeDecay = this.computeTimeDecay(endorsement, domain);
2669
+ const collusionPenalty = this.getCollusionPenalty(endorsement.from);
2670
+ const baseWeight = endorserWeight * collusionPenalty;
2671
+ weightedSum += endorsement.score * timeDecay * baseWeight;
2672
+ totalWeight += baseWeight;
2673
+ }
2674
+ return totalWeight > 0 ? weightedSum / totalWeight : 0;
2675
+ }
2676
+ /**
2677
+ * Get endorser weight (recursive EigenTrust-lite).
2678
+ * Uses endorsementsByTarget populated by compute() for local graph traversal.
2679
+ */
2680
+ getEndorserWeight(endorser, domain, depth, visited) {
2681
+ if (this.config.seedPeers.includes(endorser)) {
2682
+ return 1;
2683
+ }
2684
+ if (depth >= this.config.maxRecursionDepth) {
2685
+ return 0.1;
2686
+ }
2687
+ if (visited.has(endorser)) {
2688
+ return 0.1;
2689
+ }
2690
+ const endorserEndorsements = this.endorsementsByTarget.get(endorser);
2691
+ if (!endorserEndorsements || endorserEndorsements.length === 0) {
2692
+ return 0.1;
2693
+ }
2694
+ const endorserScore = this.computeNetworkTrust(
2695
+ endorser,
2696
+ this.filterByDomain(endorserEndorsements, domain),
2697
+ domain,
2698
+ depth,
2699
+ new Set(visited)
2700
+ // copy so sibling branches don't share state
2701
+ );
2702
+ return 0.1 + endorserScore * 0.9;
2703
+ }
2704
+ /**
2705
+ * Compute time decay for an endorsement
2706
+ */
2707
+ computeTimeDecay(endorsement, domain) {
2708
+ const age = Date.now() - endorsement.timestamp;
2709
+ const ageDays = age / (24 * 60 * 60 * 1e3);
2710
+ const halfLife = this.getDecayHalfLife(endorsement.domain || domain);
2711
+ return Math.exp(-ageDays / halfLife);
2712
+ }
2713
+ /**
2714
+ * Get decay half-life for a domain
2715
+ */
2716
+ getDecayHalfLife(domain) {
2717
+ if (!domain) {
2718
+ return this.config.decayHalfLife.default || 90;
2719
+ }
2720
+ if (FAST_DOMAINS.includes(domain)) {
2721
+ return this.config.decayHalfLife[domain] || 30;
2722
+ }
2723
+ if (SLOW_DOMAINS.includes(domain)) {
2724
+ return this.config.decayHalfLife[domain] || 180;
2725
+ }
2726
+ return this.config.decayHalfLife[domain] || this.config.decayHalfLife.default || 90;
2727
+ }
2728
+ /**
2729
+ * Detect collusion using Tarjan's SCC algorithm
2730
+ */
2731
+ detectCollusion(target, endorsements) {
2732
+ const graph = this.buildGraph(endorsements);
2733
+ const sccs = this.findSCCs(graph);
2734
+ for (const scc of sccs) {
2735
+ if (scc.nodes.includes(target) && scc.nodes.length > 3) {
2736
+ const ratio = scc.externalEdges / (scc.internalEdges || 1);
2737
+ if (ratio < 0.2) {
2738
+ logger10.warn("Collusion detected", {
2739
+ target,
2740
+ sccSize: scc.nodes.length,
2741
+ ratio
2742
+ });
2743
+ return true;
2744
+ }
2745
+ }
2746
+ }
2747
+ return false;
2748
+ }
2749
+ /**
2750
+ * Build endorsement graph
2751
+ */
2752
+ buildGraph(endorsements) {
2753
+ const graph = /* @__PURE__ */ new Map();
2754
+ for (const endorsement of endorsements) {
2755
+ if (!graph.has(endorsement.from)) {
2756
+ graph.set(endorsement.from, { did: endorsement.from, endorsements: [] });
2757
+ }
2758
+ if (!graph.has(endorsement.to)) {
2759
+ graph.set(endorsement.to, { did: endorsement.to, endorsements: [] });
2760
+ }
2761
+ graph.get(endorsement.from).endorsements.push(endorsement);
2762
+ }
2763
+ return graph;
2764
+ }
2765
+ /**
2766
+ * Find strongly connected components using Tarjan's algorithm
2767
+ */
2768
+ findSCCs(graph) {
2769
+ const sccs = [];
2770
+ const stack = [];
2771
+ let index = 0;
2772
+ const strongConnect = (node) => {
2773
+ node.index = index;
2774
+ node.lowlink = index;
2775
+ index++;
2776
+ stack.push(node.did);
2777
+ node.onStack = true;
2778
+ for (const endorsement of node.endorsements) {
2779
+ const successor = graph.get(endorsement.to);
2780
+ if (!successor) continue;
2781
+ if (successor.index === void 0) {
2782
+ strongConnect(successor);
2783
+ node.lowlink = Math.min(node.lowlink, successor.lowlink);
2784
+ } else if (successor.onStack) {
2785
+ node.lowlink = Math.min(node.lowlink, successor.index);
2786
+ }
2787
+ }
2788
+ if (node.lowlink === node.index) {
2789
+ const sccNodes = [];
2790
+ let w;
2791
+ do {
2792
+ w = stack.pop();
2793
+ graph.get(w).onStack = false;
2794
+ sccNodes.push(w);
2795
+ } while (w !== node.did);
2796
+ if (sccNodes.length > 1) {
2797
+ let internalEdges = 0;
2798
+ let externalEdges = 0;
2799
+ for (const did of sccNodes) {
2800
+ const n = graph.get(did);
2801
+ for (const endorsement of n.endorsements) {
2802
+ if (sccNodes.includes(endorsement.to)) {
2803
+ internalEdges++;
2804
+ } else {
2805
+ externalEdges++;
2806
+ }
2807
+ }
2808
+ }
2809
+ sccs.push({ nodes: sccNodes, internalEdges, externalEdges });
2810
+ }
2811
+ }
2812
+ };
2813
+ for (const node of graph.values()) {
2814
+ if (node.index === void 0) {
2815
+ strongConnect(node);
2816
+ }
2817
+ }
2818
+ return sccs;
2819
+ }
2820
+ /**
2821
+ * Rebuild the SCC penalty cache from a full endorsement graph.
2822
+ * Called lazily when the cache is stale.
2823
+ */
2824
+ rebuildSccPenaltyCache(endorsements) {
2825
+ this.sccPenaltyCache.clear();
2826
+ const graph = this.buildGraph(endorsements);
2827
+ const sccs = this.findSCCs(graph);
2828
+ for (const scc of sccs) {
2829
+ if (scc.nodes.length > 3) {
2830
+ const ratio = scc.externalEdges / (scc.internalEdges || 1);
2831
+ if (ratio < 0.2) {
2832
+ for (const did of scc.nodes) {
2833
+ this.sccPenaltyCache.set(did, 0.1);
2834
+ }
2835
+ }
2836
+ }
2837
+ }
2838
+ this.sccCacheExpiresAt = Date.now() + this.SCC_CACHE_TTL;
2839
+ }
2840
+ /**
2841
+ * Get collusion penalty for an endorser.
2842
+ * Returns 0.1 if the endorser is in a detected collusion cluster, 1.0 otherwise.
2843
+ */
2844
+ getCollusionPenalty(endorser) {
2845
+ return this.sccPenaltyCache.get(endorser) ?? 1;
2846
+ }
2847
+ /**
2848
+ * Filter endorsements by domain
2849
+ */
2850
+ filterByDomain(endorsements, domain) {
2851
+ if (!domain) {
2852
+ return endorsements;
2853
+ }
2854
+ return endorsements.filter(
2855
+ (e) => e.domain === domain || e.domain === void 0 || e.domain === "*"
2856
+ );
2857
+ }
2858
+ /**
2859
+ * Get cache key
2860
+ */
2861
+ getCacheKey(target, domain) {
2862
+ return `${target}:${domain || "*"}`;
2863
+ }
2864
+ /**
2865
+ * Clear cache
2866
+ */
2867
+ clearCache() {
2868
+ this.cache.clear();
2869
+ logger10.debug("Trust score cache cleared");
2870
+ }
2871
+ /**
2872
+ * Update configuration
2873
+ */
2874
+ updateConfig(config) {
2875
+ this.config = {
2876
+ ...this.config,
2877
+ ...config,
2878
+ decayHalfLife: {
2879
+ ...this.config.decayHalfLife,
2880
+ ...config.decayHalfLife
2881
+ }
2882
+ };
2883
+ this.clearCache();
2884
+ logger10.info("Trust config updated", { config });
2885
+ }
2886
+ };
2887
+ var logger11 = createLogger("trust-system");
2540
2888
  var TrustSystem = class {
2541
2889
  metrics;
2542
2890
  history;
@@ -2545,6 +2893,8 @@ var TrustSystem = class {
2545
2893
  trustCache = /* @__PURE__ */ new Map();
2546
2894
  CACHE_TTL = 5 * 60 * 1e3;
2547
2895
  // 5 minutes
2896
+ // Uptime tracking: DID → { firstSeen, totalOnlineMs, lastOnlineAt }
2897
+ uptimeTracker = /* @__PURE__ */ new Map();
2548
2898
  constructor(config) {
2549
2899
  this.metrics = new TrustMetrics();
2550
2900
  this.history = new InteractionHistory(`${config.dbPath}/interactions`);
@@ -2559,14 +2909,14 @@ var TrustSystem = class {
2559
2909
  */
2560
2910
  async start() {
2561
2911
  await this.history.open();
2562
- logger12.info("Trust system started");
2912
+ logger11.info("Trust system started");
2563
2913
  }
2564
2914
  /**
2565
2915
  * Shutdown the trust system
2566
2916
  */
2567
2917
  async stop() {
2568
2918
  await this.history.close();
2569
- logger12.info("Trust system stopped");
2919
+ logger11.info("Trust system stopped");
2570
2920
  }
2571
2921
  /**
2572
2922
  * Record an interaction
@@ -2576,6 +2926,42 @@ var TrustSystem = class {
2576
2926
  this.sybilDefense.recordRequest(interaction.agentDid);
2577
2927
  this.trustCache.delete(interaction.agentDid);
2578
2928
  }
2929
+ /**
2930
+ * Record agent coming online (for uptime tracking)
2931
+ */
2932
+ recordOnline(agentDid) {
2933
+ const now = Date.now();
2934
+ const existing = this.uptimeTracker.get(agentDid);
2935
+ if (existing) {
2936
+ existing.lastOnlineAt = now;
2937
+ } else {
2938
+ this.uptimeTracker.set(agentDid, { firstSeen: now, totalOnlineMs: 0, lastOnlineAt: now });
2939
+ }
2940
+ }
2941
+ /**
2942
+ * Record agent going offline (for uptime tracking)
2943
+ */
2944
+ recordOffline(agentDid) {
2945
+ const now = Date.now();
2946
+ const entry = this.uptimeTracker.get(agentDid);
2947
+ if (entry && entry.lastOnlineAt > 0) {
2948
+ entry.totalOnlineMs += now - entry.lastOnlineAt;
2949
+ entry.lastOnlineAt = 0;
2950
+ }
2951
+ }
2952
+ /**
2953
+ * Get uptime ratio for an agent (0.0 - 1.0)
2954
+ * Based on time since first seen vs total online time.
2955
+ */
2956
+ getUptime(agentDid) {
2957
+ const entry = this.uptimeTracker.get(agentDid);
2958
+ if (!entry) return 1;
2959
+ const now = Date.now();
2960
+ const totalMs = now - entry.firstSeen;
2961
+ if (totalMs < 6e4) return 1;
2962
+ const onlineMs = entry.totalOnlineMs + (entry.lastOnlineAt > 0 ? now - entry.lastOnlineAt : 0);
2963
+ return Math.min(1, onlineMs / totalMs);
2964
+ }
2579
2965
  /**
2580
2966
  * Get trust score for an agent
2581
2967
  */
@@ -2586,8 +2972,9 @@ var TrustSystem = class {
2586
2972
  }
2587
2973
  const stats = await this.history.getStats(agentDid);
2588
2974
  const endorsementList = await this.endorsements.getEndorsements(agentDid);
2589
- const uptime = 1;
2590
- const score = this.metrics.calculateScore(stats, endorsementList.length, uptime);
2975
+ const uptime = this.getUptime(agentDid);
2976
+ const endorsementScore = endorsementList.length > 0 ? endorsementList.reduce((sum, e) => sum + e.score, 0) / endorsementList.length : 0;
2977
+ const score = this.metrics.calculateScore(stats, endorsementScore, uptime);
2591
2978
  this.trustCache.set(agentDid, { score, timestamp: Date.now() });
2592
2979
  return score;
2593
2980
  }
@@ -2655,13 +3042,13 @@ var TrustSystem = class {
2655
3042
  await this.history.cleanup();
2656
3043
  this.sybilDefense.cleanup();
2657
3044
  this.trustCache.clear();
2658
- logger12.info("Trust system cleanup completed");
3045
+ logger11.info("Trust system cleanup completed");
2659
3046
  }
2660
3047
  };
2661
3048
  function createTrustSystem(config) {
2662
3049
  return new TrustSystem(config);
2663
3050
  }
2664
3051
 
2665
- export { CLAWIVERSE_CONTEXT, CapabilityMatcher, CapabilityTypes, ClawiverseError, DEFAULT_RATE_LIMIT_TIERS, DefenseMiddleware, DiscoveryError, EndorsementManager, IdentityError, InteractionHistory, LogLevel, Logger, MessageQueue, MessageStorage, MessagingError, ParameterTypes, RELAY_PROTOCOL_VERSION, SCHEMA_ORG_CONTEXT, SearchIndex, SemanticSearchEngine, SybilDefense, TokenBucket, TransportError, TrustMetrics, TrustSystem, clawiverseContext, createAgentCard, createDefaultTrustScore, createEnvelope, createLegacyAgentCard, createLogger, createMessageRouter, createRelayClient, createRelayIndexOperations, createSemanticSearch, createTrustSystem, decodeAgentCard, decodeFromCBOR, decodeFromJSON, decodeMessage, decodeMessageJSON, deriveDID, downgradeToLegacyCard, encodeForDHT, encodeForWeb, encodeMessage, encodeMessageJSON, exportKeyPair, extractPublicKey, generateKeyPair, getAgentCardContext, getEncodedSize, getTierConfig, importKeyPair, isLegacyCard, isValidContext, matchesCapability, sign, signAgentCard, signEnvelope, signMessage, upgradeLegacyCard, validateAgentCard, validateDID, validateEnvelope, verify, verifyAgentCard, verifyEnvelope, verifyMessage };
3052
+ export { CLAWIVERSE_CONTEXT, CapabilityTypes, ClawiverseError, DEFAULT_RATE_LIMIT_TIERS, DefenseMiddleware, DiscoveryError, EndorsementManager, FAST_DOMAINS, IdentityError, InteractionHistory, LogLevel, Logger, MessageQueue, MessageStorage, MessagingError, ParameterTypes, RELAY_PROTOCOL_VERSION, SCHEMA_ORG_CONTEXT, SLOW_DOMAINS, SybilDefense, TokenBucket, TransportError, TrustComputer, TrustMetrics, TrustSystem, clawiverseContext, createAgentCard, createDIDDocument, createDefaultTrustScore, createEnvelope, createLegacyAgentCard, createLogger, createMessageRouter, createRelayClient, createRelayIndexOperations, createTrustSystem, decodeAgentCard, decodeFromCBOR, decodeFromJSON, decodeMessage, decodeMessageJSON, deriveDID, downgradeToLegacyCard, encodeForDHT, encodeForWeb, encodeMessage, encodeMessageJSON, exportKeyPair, extractPublicKey, formatDidWithAlias, formatDidWithAliasDetailed, generateAnonymousIdentity, generateKeyPair, generateThreadId, getAgentCardContext, getDefaultExpiration, getEncodedSize, getTierConfig, importKeyPair, isLegacyCard, isValidContext, matchesCapability, normalizeEnvelope, normalizeEnvelopeType, resolveDid, reverseAlias, sign, signAgentCard, signEnvelope, signMessage, upgradeLegacyCard, validateAgentCard, validateAliasName, validateDID, validateDIDDocument, validateDomain, validateEnvelope, verify, verifyAgentCard, verifyEnvelope, verifyMessage };
2666
3053
  //# sourceMappingURL=index.js.map
2667
3054
  //# sourceMappingURL=index.js.map