@highway1/core 0.1.53 → 0.1.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +5 -18
  2. package/src/discovery/agent-card-encoder.ts +0 -119
  3. package/src/discovery/agent-card-schema.ts +0 -87
  4. package/src/discovery/agent-card-types.ts +0 -99
  5. package/src/discovery/agent-card.ts +0 -190
  6. package/src/discovery/bootstrap.ts +0 -63
  7. package/src/discovery/capability-matcher.ts +0 -167
  8. package/src/discovery/dht.ts +0 -310
  9. package/src/discovery/index.ts +0 -3
  10. package/src/discovery/relay-index.ts +0 -98
  11. package/src/discovery/search-index.ts +0 -247
  12. package/src/discovery/semantic-search.ts +0 -218
  13. package/src/identity/did.ts +0 -48
  14. package/src/identity/document.ts +0 -77
  15. package/src/identity/index.ts +0 -4
  16. package/src/identity/keys.ts +0 -79
  17. package/src/identity/signer.ts +0 -55
  18. package/src/index.ts +0 -39
  19. package/src/messaging/codec.ts +0 -47
  20. package/src/messaging/defense.ts +0 -236
  21. package/src/messaging/envelope.ts +0 -107
  22. package/src/messaging/index.ts +0 -8
  23. package/src/messaging/queue.ts +0 -181
  24. package/src/messaging/rate-limiter.ts +0 -85
  25. package/src/messaging/router.ts +0 -209
  26. package/src/messaging/storage.ts +0 -281
  27. package/src/messaging/types.ts +0 -149
  28. package/src/transport/connection.ts +0 -77
  29. package/src/transport/index.ts +0 -2
  30. package/src/transport/node.ts +0 -154
  31. package/src/transport/relay-client.ts +0 -437
  32. package/src/transport/relay-types.ts +0 -196
  33. package/src/trust/endorsement.ts +0 -167
  34. package/src/trust/index.ts +0 -194
  35. package/src/trust/interaction-history.ts +0 -155
  36. package/src/trust/sybil-defense.ts +0 -232
  37. package/src/trust/trust-score.ts +0 -136
  38. package/src/utils/errors.ts +0 -38
  39. package/src/utils/logger.ts +0 -48
@@ -1,247 +0,0 @@
1
- /**
2
- * Search Index for Agent Discovery
3
- *
4
- * Maintains a local index of discovered agents for fast semantic search
5
- */
6
-
7
- import lunr from 'lunr';
8
- import Fuse from 'fuse.js';
9
- import type { AgentCard } from './agent-card-types.js';
10
- import { createLogger } from '../utils/logger.js';
11
-
12
- const logger = createLogger('search-index');
13
-
14
- /**
15
- * Semantic Query Interface
16
- */
17
- export interface SemanticQuery {
18
- text?: string; // Natural language: "translate Japanese"
19
- capability?: string; // Structured: "translate"
20
- filters?: {
21
- language?: string;
22
- minTrustScore?: number;
23
- maxCost?: number;
24
- tags?: string[];
25
- };
26
- limit?: number;
27
- }
28
-
29
- /**
30
- * Search Result with Score
31
- */
32
- export interface SearchResult {
33
- card: AgentCard;
34
- score: number;
35
- }
36
-
37
- /**
38
- * Search Index Implementation
39
- */
40
- export class SearchIndex {
41
- private cards = new Map<string, AgentCard>();
42
- private lunrIndex?: lunr.Index;
43
- private fuse?: Fuse<AgentCard>;
44
- private needsRebuild = false;
45
-
46
- /**
47
- * Add or update an Agent Card in the index
48
- */
49
- indexAgentCard(card: AgentCard): void {
50
- this.cards.set(card.did, card);
51
- this.needsRebuild = true;
52
- logger.debug('Indexed Agent Card', { did: card.did, capabilities: card.capabilities.length });
53
- }
54
-
55
- /**
56
- * Remove an Agent Card from the index
57
- */
58
- removeAgentCard(did: string): void {
59
- this.cards.delete(did);
60
- this.needsRebuild = true;
61
- logger.debug('Removed Agent Card from index', { did });
62
- }
63
-
64
- /**
65
- * Search for agents matching a query
66
- */
67
- search(query: SemanticQuery): SearchResult[] {
68
- if (this.needsRebuild) {
69
- this.rebuild();
70
- }
71
-
72
- let results: SearchResult[] = [];
73
-
74
- // Text search using Lunr
75
- if (query.text && this.lunrIndex) {
76
- results = this.searchByText(query.text);
77
- }
78
- // Capability search using Fuse
79
- else if (query.capability && this.fuse) {
80
- results = this.searchByCapability(query.capability);
81
- }
82
- // No query - return all
83
- else {
84
- results = Array.from(this.cards.values()).map(card => ({
85
- card,
86
- score: 1.0,
87
- }));
88
- }
89
-
90
- // Apply filters
91
- if (query.filters) {
92
- results = this.applyFilters(results, query.filters);
93
- }
94
-
95
- // Sort by score (descending)
96
- results.sort((a, b) => b.score - a.score);
97
-
98
- // Apply limit
99
- if (query.limit) {
100
- results = results.slice(0, query.limit);
101
- }
102
-
103
- logger.debug('Search completed', { query, results: results.length });
104
- return results;
105
- }
106
-
107
- /**
108
- * Get all indexed cards
109
- */
110
- getAllCards(): AgentCard[] {
111
- return Array.from(this.cards.values());
112
- }
113
-
114
- /**
115
- * Clear the index
116
- */
117
- clear(): void {
118
- this.cards.clear();
119
- this.lunrIndex = undefined;
120
- this.fuse = undefined;
121
- this.needsRebuild = false;
122
- logger.info('Search index cleared');
123
- }
124
-
125
- /**
126
- * Get index size
127
- */
128
- size(): number {
129
- return this.cards.size;
130
- }
131
-
132
- /**
133
- * Rebuild search indexes
134
- */
135
- private rebuild(): void {
136
- logger.info('Rebuilding search indexes', { cards: this.cards.size });
137
-
138
- const cards = Array.from(this.cards.values());
139
-
140
- // Build Lunr index for full-text search
141
- this.lunrIndex = lunr(function (this: lunr.Builder) {
142
- this.ref('did');
143
- this.field('name', { boost: 10 });
144
- this.field('description', { boost: 5 });
145
- this.field('capabilities');
146
-
147
- for (const card of cards) {
148
- this.add({
149
- did: card.did,
150
- name: card.name,
151
- description: card.description,
152
- capabilities: card.capabilities
153
- .map((cap: any) => `${cap.name} ${cap.description}`)
154
- .join(' '),
155
- });
156
- }
157
- });
158
-
159
- // Build Fuse index for fuzzy matching
160
- this.fuse = new Fuse(Array.from(this.cards.values()), {
161
- keys: [
162
- { name: 'name', weight: 0.3 },
163
- { name: 'description', weight: 0.2 },
164
- { name: 'capabilities.name', weight: 0.3 },
165
- { name: 'capabilities.description', weight: 0.2 },
166
- ],
167
- threshold: 0.4,
168
- includeScore: true,
169
- });
170
-
171
- this.needsRebuild = false;
172
- logger.info('Search indexes rebuilt');
173
- }
174
-
175
- /**
176
- * Search by text using Lunr
177
- */
178
- private searchByText(text: string): SearchResult[] {
179
- if (!this.lunrIndex) return [];
180
-
181
- const lunrResults = this.lunrIndex.search(text);
182
- return lunrResults.map(result => ({
183
- card: this.cards.get(result.ref)!,
184
- score: result.score,
185
- }));
186
- }
187
-
188
- /**
189
- * Search by capability using Fuse
190
- */
191
- private searchByCapability(capability: string): SearchResult[] {
192
- if (!this.fuse) return [];
193
-
194
- const fuseResults = this.fuse.search(capability);
195
- return fuseResults.map(result => ({
196
- card: result.item,
197
- score: 1 - (result.score || 0), // Fuse score is distance, convert to similarity
198
- }));
199
- }
200
-
201
- /**
202
- * Apply filters to search results
203
- */
204
- private applyFilters(
205
- results: SearchResult[],
206
- filters: NonNullable<SemanticQuery['filters']>
207
- ): SearchResult[] {
208
- return results.filter(result => {
209
- const { card } = result;
210
-
211
- // Trust score filter
212
- if (filters.minTrustScore !== undefined && card.trust) {
213
- const overallTrust =
214
- card.trust.interactionScore * 0.4 +
215
- Math.min(card.trust.endorsements / 10, 1) * 0.2 +
216
- card.trust.completionRate * 0.2 +
217
- card.trust.uptime * 0.2;
218
-
219
- if (overallTrust < filters.minTrustScore) {
220
- return false;
221
- }
222
- }
223
-
224
- // Language filter (check capability metadata)
225
- if (filters.language) {
226
- const hasLanguage = card.capabilities.some(
227
- cap => {
228
- const metadata = cap.metadata as Record<string, any> | undefined;
229
- if (!metadata) return false;
230
- return metadata.language === filters.language ||
231
- (Array.isArray(metadata.languages) && metadata.languages.includes(filters.language));
232
- }
233
- );
234
- if (!hasLanguage) return false;
235
- }
236
-
237
- // Tags filter
238
- if (filters.tags && filters.tags.length > 0) {
239
- const cardTags = Array.isArray(card.metadata?.tags) ? (card.metadata.tags as string[]) : [];
240
- const hasAllTags = filters.tags.every(tag => cardTags.includes(tag));
241
- if (!hasAllTags) return false;
242
- }
243
-
244
- return true;
245
- });
246
- }
247
- }
@@ -1,218 +0,0 @@
1
- /**
2
- * Semantic Search Engine
3
- *
4
- * Provides intelligent agent discovery through semantic search
5
- * with local-first strategy and network fallback
6
- */
7
-
8
- import type { AgentCard } from './agent-card-types.js';
9
- import { SearchIndex } from './search-index.js';
10
- import type { SemanticQuery, SearchResult } from './search-index.js';
11
- import { CapabilityMatcher } from './capability-matcher.js';
12
- import type { DHTOperations } from './dht.js';
13
- import { createLogger } from '../utils/logger.js';
14
-
15
- const logger = createLogger('semantic-search');
16
-
17
- /**
18
- * Semantic Search Engine
19
- */
20
- export class SemanticSearchEngine {
21
- private index: SearchIndex;
22
- private matcher: CapabilityMatcher;
23
-
24
- constructor(private dht?: DHTOperations) {
25
- this.index = new SearchIndex();
26
- this.matcher = new CapabilityMatcher();
27
- }
28
-
29
- /**
30
- * Main search interface
31
- * Local-first with network fallback
32
- */
33
- async search(query: SemanticQuery): Promise<AgentCard[]> {
34
- logger.info('Searching for agents', { query });
35
-
36
- // 1. Search local index
37
- const localResults = this.index.search(query);
38
- logger.debug('Local search results', { count: localResults.length });
39
-
40
- // 2. If insufficient results, query network
41
- const limit = query.limit || 10;
42
- if (localResults.length < limit && this.dht) {
43
- logger.debug('Insufficient local results, querying network');
44
- const networkResults = await this.searchNetwork(query);
45
- return this.mergeResults(localResults, networkResults, limit);
46
- }
47
-
48
- return localResults.map(r => r.card);
49
- }
50
-
51
- /**
52
- * Index an Agent Card for local search
53
- */
54
- indexAgentCard(card: AgentCard): void {
55
- this.index.indexAgentCard(card);
56
- }
57
-
58
- /**
59
- * Remove an Agent Card from local index
60
- */
61
- removeAgentCard(did: string): void {
62
- this.index.removeAgentCard(did);
63
- }
64
-
65
- /**
66
- * Get all indexed cards
67
- */
68
- getAllIndexedCards(): AgentCard[] {
69
- return this.index.getAllCards();
70
- }
71
-
72
- /**
73
- * Clear local index
74
- */
75
- clearIndex(): void {
76
- this.index.clear();
77
- }
78
-
79
- /**
80
- * Get index size
81
- */
82
- getIndexSize(): number {
83
- return this.index.size();
84
- }
85
-
86
- /**
87
- * Search network via DHT
88
- */
89
- private async searchNetwork(query: SemanticQuery): Promise<SearchResult[]> {
90
- if (!this.dht) {
91
- return [];
92
- }
93
-
94
- try {
95
- // For now, use capability-based DHT query
96
- // In future, implement distributed semantic search overlay
97
- const capability = query.capability || this.extractPrimaryCapability(query.text);
98
-
99
- if (!capability) {
100
- logger.debug('No capability extracted from query, skipping network search');
101
- return [];
102
- }
103
-
104
- const cards = await this.dht.queryByCapability(capability);
105
- logger.debug('Network search results', { count: cards.length });
106
-
107
- // Score network results
108
- return cards.map(card => {
109
- const score = this.scoreCard(card, query);
110
- return { card, score };
111
- });
112
- } catch (error) {
113
- logger.error('Network search failed', { error });
114
- return [];
115
- }
116
- }
117
-
118
- /**
119
- * Merge local and network results, removing duplicates
120
- */
121
- private mergeResults(
122
- local: SearchResult[],
123
- network: SearchResult[],
124
- limit: number
125
- ): AgentCard[] {
126
- const seen = new Set<string>();
127
- const merged: SearchResult[] = [];
128
-
129
- // Add local results first (they're already scored and sorted)
130
- for (const result of local) {
131
- if (!seen.has(result.card.did)) {
132
- seen.add(result.card.did);
133
- merged.push(result);
134
- }
135
- }
136
-
137
- // Add network results
138
- for (const result of network) {
139
- if (!seen.has(result.card.did)) {
140
- seen.add(result.card.did);
141
- merged.push(result);
142
-
143
- // Also index for future searches
144
- this.index.indexAgentCard(result.card);
145
- }
146
- }
147
-
148
- // Sort by score and apply limit
149
- merged.sort((a, b) => b.score - a.score);
150
- return merged.slice(0, limit).map(r => r.card);
151
- }
152
-
153
- /**
154
- * Score a card against a query
155
- */
156
- private scoreCard(card: AgentCard, query: SemanticQuery): number {
157
- let totalScore = 0;
158
- let count = 0;
159
-
160
- for (const capability of card.capabilities) {
161
- const score = this.matcher.match(query, capability);
162
- if (score > 0) {
163
- totalScore += score;
164
- count++;
165
- }
166
- }
167
-
168
- // Average score across matching capabilities
169
- const avgScore = count > 0 ? totalScore / count : 0;
170
-
171
- // Boost by trust score if available
172
- if (card.trust) {
173
- const trustBoost = card.trust.interactionScore * 0.2;
174
- return Math.min(avgScore + trustBoost, 1.0);
175
- }
176
-
177
- return avgScore;
178
- }
179
-
180
- /**
181
- * Extract primary capability from natural language text
182
- */
183
- private extractPrimaryCapability(text?: string): string | undefined {
184
- if (!text) return undefined;
185
-
186
- const keywords = this.matcher.extractKeywords(text);
187
-
188
- // Common capability keywords
189
- const capabilityKeywords = [
190
- 'translate', 'translation',
191
- 'review', 'code',
192
- 'analyze', 'analysis',
193
- 'generate', 'generation',
194
- 'search', 'query',
195
- 'compute', 'calculation',
196
- 'store', 'storage',
197
- 'message', 'messaging',
198
- 'auth', 'authentication',
199
- ];
200
-
201
- // Find first matching keyword
202
- for (const keyword of keywords) {
203
- if (capabilityKeywords.includes(keyword)) {
204
- return keyword;
205
- }
206
- }
207
-
208
- // Return first keyword as fallback
209
- return keywords[0];
210
- }
211
- }
212
-
213
- /**
214
- * Create a semantic search engine
215
- */
216
- export function createSemanticSearch(dht?: DHTOperations): SemanticSearchEngine {
217
- return new SemanticSearchEngine(dht);
218
- }
@@ -1,48 +0,0 @@
1
- import { base58btc } from 'multiformats/bases/base58';
2
- import { IdentityError } from '../utils/errors.js';
3
-
4
- /**
5
- * Derive a did:clawiverse DID from a public key
6
- * Format: did:clawiverse:<base58btc-encoded-pubkey>
7
- */
8
- export function deriveDID(publicKey: Uint8Array): string {
9
- try {
10
- const encoded = base58btc.encode(publicKey);
11
- return `did:clawiverse:${encoded}`;
12
- } catch (error) {
13
- throw new IdentityError('Failed to derive DID', error);
14
- }
15
- }
16
-
17
- /**
18
- * Extract public key from a did:clawiverse DID
19
- */
20
- export function extractPublicKey(did: string): Uint8Array {
21
- if (!did.startsWith('did:clawiverse:')) {
22
- throw new IdentityError('Invalid DID format: must start with did:clawiverse:');
23
- }
24
-
25
- try {
26
- const encoded = did.replace('did:clawiverse:', '');
27
- return base58btc.decode(encoded);
28
- } catch (error) {
29
- throw new IdentityError('Failed to extract public key from DID', error);
30
- }
31
- }
32
-
33
- /**
34
- * Validate a did:clawiverse DID format
35
- */
36
- export function validateDID(did: string): boolean {
37
- if (!did.startsWith('did:clawiverse:')) {
38
- return false;
39
- }
40
-
41
- try {
42
- const encoded = did.replace('did:clawiverse:', '');
43
- base58btc.decode(encoded);
44
- return true;
45
- } catch {
46
- return false;
47
- }
48
- }
@@ -1,77 +0,0 @@
1
- import { deriveDID } from './did.js';
2
-
3
- export interface DIDDocument {
4
- '@context': string[];
5
- id: string;
6
- verificationMethod: VerificationMethod[];
7
- authentication: string[];
8
- assertionMethod: string[];
9
- keyAgreement?: string[];
10
- service?: ServiceEndpoint[];
11
- }
12
-
13
- export interface VerificationMethod {
14
- id: string;
15
- type: string;
16
- controller: string;
17
- publicKeyMultibase: string;
18
- }
19
-
20
- export interface ServiceEndpoint {
21
- id: string;
22
- type: string;
23
- serviceEndpoint: string;
24
- }
25
-
26
- /**
27
- * Create a DID Document for a did:clawiverse identity
28
- */
29
- export function createDIDDocument(
30
- publicKey: Uint8Array,
31
- services?: ServiceEndpoint[]
32
- ): DIDDocument {
33
- const did = deriveDID(publicKey);
34
- const keyId = `${did}#key-1`;
35
- // Use base58btc encoding for multibase format
36
- const publicKeyMultibase = `z${Buffer.from(publicKey).toString('hex')}`;
37
-
38
- return {
39
- '@context': [
40
- 'https://www.w3.org/ns/did/v1',
41
- 'https://w3id.org/security/suites/ed25519-2020/v1',
42
- ],
43
- id: did,
44
- verificationMethod: [
45
- {
46
- id: keyId,
47
- type: 'Ed25519VerificationKey2020',
48
- controller: did,
49
- publicKeyMultibase,
50
- },
51
- ],
52
- authentication: [keyId],
53
- assertionMethod: [keyId],
54
- service: services,
55
- };
56
- }
57
-
58
- /**
59
- * Validate a DID Document structure
60
- */
61
- export function validateDIDDocument(doc: unknown): doc is DIDDocument {
62
- if (typeof doc !== 'object' || doc === null) {
63
- return false;
64
- }
65
-
66
- const d = doc as Partial<DIDDocument>;
67
-
68
- return (
69
- Array.isArray(d['@context']) &&
70
- typeof d.id === 'string' &&
71
- d.id.startsWith('did:clawiverse:') &&
72
- Array.isArray(d.verificationMethod) &&
73
- d.verificationMethod.length > 0 &&
74
- Array.isArray(d.authentication) &&
75
- Array.isArray(d.assertionMethod)
76
- );
77
- }
@@ -1,4 +0,0 @@
1
- export * from './keys.js';
2
- export * from './did.js';
3
- export * from './document.js';
4
- export * from './signer.js';
@@ -1,79 +0,0 @@
1
- import * as ed25519 from '@noble/ed25519';
2
- import { IdentityError } from '../utils/errors.js';
3
-
4
- export interface KeyPair {
5
- publicKey: Uint8Array;
6
- privateKey: Uint8Array;
7
- }
8
-
9
- /**
10
- * Generate a new Ed25519 key pair
11
- */
12
- export async function generateKeyPair(): Promise<KeyPair> {
13
- try {
14
- const privateKey = ed25519.utils.randomPrivateKey();
15
- const publicKey = await ed25519.getPublicKeyAsync(privateKey);
16
-
17
- return {
18
- publicKey,
19
- privateKey,
20
- };
21
- } catch (error) {
22
- throw new IdentityError('Failed to generate key pair', error);
23
- }
24
- }
25
-
26
- /**
27
- * Sign a message with a private key
28
- */
29
- export async function sign(
30
- message: Uint8Array,
31
- privateKey: Uint8Array
32
- ): Promise<Uint8Array> {
33
- try {
34
- return await ed25519.signAsync(message, privateKey);
35
- } catch (error) {
36
- throw new IdentityError('Failed to sign message', error);
37
- }
38
- }
39
-
40
- /**
41
- * Verify a signature
42
- */
43
- export async function verify(
44
- signature: Uint8Array,
45
- message: Uint8Array,
46
- publicKey: Uint8Array
47
- ): Promise<boolean> {
48
- try {
49
- return await ed25519.verifyAsync(signature, message, publicKey);
50
- } catch (error) {
51
- throw new IdentityError('Failed to verify signature', error);
52
- }
53
- }
54
-
55
- /**
56
- * Export key pair to JSON format
57
- */
58
- export function exportKeyPair(keyPair: KeyPair): {
59
- publicKey: string;
60
- privateKey: string;
61
- } {
62
- return {
63
- publicKey: Buffer.from(keyPair.publicKey).toString('hex'),
64
- privateKey: Buffer.from(keyPair.privateKey).toString('hex'),
65
- };
66
- }
67
-
68
- /**
69
- * Import key pair from JSON format
70
- */
71
- export function importKeyPair(exported: {
72
- publicKey: string;
73
- privateKey: string;
74
- }): KeyPair {
75
- return {
76
- publicKey: new Uint8Array(Buffer.from(exported.publicKey, 'hex')),
77
- privateKey: new Uint8Array(Buffer.from(exported.privateKey, 'hex')),
78
- };
79
- }