@claude-flow/cli 3.0.0-alpha.81 → 3.0.0-alpha.83

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 (67) hide show
  1. package/dist/src/commands/claims.d.ts.map +1 -1
  2. package/dist/src/commands/claims.js +92 -7
  3. package/dist/src/commands/claims.js.map +1 -1
  4. package/dist/src/commands/embeddings.d.ts.map +1 -1
  5. package/dist/src/commands/embeddings.js +99 -5
  6. package/dist/src/commands/embeddings.js.map +1 -1
  7. package/dist/src/commands/index.d.ts.map +1 -1
  8. package/dist/src/commands/index.js +2 -0
  9. package/dist/src/commands/index.js.map +1 -1
  10. package/dist/src/commands/neural.d.ts.map +1 -1
  11. package/dist/src/commands/neural.js +68 -16
  12. package/dist/src/commands/neural.js.map +1 -1
  13. package/dist/src/commands/performance.d.ts.map +1 -1
  14. package/dist/src/commands/performance.js +155 -9
  15. package/dist/src/commands/performance.js.map +1 -1
  16. package/dist/src/commands/security.d.ts.map +1 -1
  17. package/dist/src/commands/security.js +199 -31
  18. package/dist/src/commands/security.js.map +1 -1
  19. package/dist/src/commands/update.d.ts +8 -0
  20. package/dist/src/commands/update.d.ts.map +1 -0
  21. package/dist/src/commands/update.js +276 -0
  22. package/dist/src/commands/update.js.map +1 -0
  23. package/dist/src/index.d.ts +5 -0
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +28 -0
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/transfer/storage/gcs.d.ts +82 -0
  28. package/dist/src/transfer/storage/gcs.d.ts.map +1 -0
  29. package/dist/src/transfer/storage/gcs.js +230 -0
  30. package/dist/src/transfer/storage/gcs.js.map +1 -0
  31. package/dist/src/transfer/storage/index.d.ts +6 -0
  32. package/dist/src/transfer/storage/index.d.ts.map +1 -0
  33. package/dist/src/transfer/storage/index.js +6 -0
  34. package/dist/src/transfer/storage/index.js.map +1 -0
  35. package/dist/src/transfer/store/discovery.d.ts +9 -9
  36. package/dist/src/transfer/store/discovery.d.ts.map +1 -1
  37. package/dist/src/transfer/store/discovery.js +197 -91
  38. package/dist/src/transfer/store/discovery.js.map +1 -1
  39. package/dist/src/transfer/store/download.d.ts +6 -6
  40. package/dist/src/transfer/store/download.d.ts.map +1 -1
  41. package/dist/src/transfer/store/download.js +104 -65
  42. package/dist/src/transfer/store/download.js.map +1 -1
  43. package/dist/src/transfer/store/publish.d.ts.map +1 -1
  44. package/dist/src/transfer/store/publish.js +57 -25
  45. package/dist/src/transfer/store/publish.js.map +1 -1
  46. package/dist/src/update/checker.d.ts +34 -0
  47. package/dist/src/update/checker.d.ts.map +1 -0
  48. package/dist/src/update/checker.js +190 -0
  49. package/dist/src/update/checker.js.map +1 -0
  50. package/dist/src/update/executor.d.ts +32 -0
  51. package/dist/src/update/executor.d.ts.map +1 -0
  52. package/dist/src/update/executor.js +181 -0
  53. package/dist/src/update/executor.js.map +1 -0
  54. package/dist/src/update/index.d.ts +33 -0
  55. package/dist/src/update/index.d.ts.map +1 -0
  56. package/dist/src/update/index.js +64 -0
  57. package/dist/src/update/index.js.map +1 -0
  58. package/dist/src/update/rate-limiter.d.ts +20 -0
  59. package/dist/src/update/rate-limiter.d.ts.map +1 -0
  60. package/dist/src/update/rate-limiter.js +96 -0
  61. package/dist/src/update/rate-limiter.js.map +1 -0
  62. package/dist/src/update/validator.d.ts +17 -0
  63. package/dist/src/update/validator.d.ts.map +1 -0
  64. package/dist/src/update/validator.js +123 -0
  65. package/dist/src/update/validator.js.map +1 -0
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +1 -1
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Google Cloud Storage Backend
3
+ * Real storage implementation using gcloud CLI or GCS APIs
4
+ *
5
+ * @module @claude-flow/cli/transfer/storage/gcs
6
+ * @version 3.0.0
7
+ */
8
+ import * as crypto from 'crypto';
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import { execSync } from 'child_process';
12
+ /**
13
+ * Get GCS configuration from environment
14
+ */
15
+ export function getGCSConfig() {
16
+ const bucket = process.env.GCS_BUCKET || process.env.GOOGLE_CLOUD_BUCKET;
17
+ if (!bucket)
18
+ return null;
19
+ return {
20
+ bucket,
21
+ projectId: process.env.GCS_PROJECT_ID || process.env.GOOGLE_CLOUD_PROJECT,
22
+ keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS,
23
+ prefix: process.env.GCS_PREFIX || 'claude-flow-patterns',
24
+ };
25
+ }
26
+ /**
27
+ * Check if gcloud CLI is available
28
+ */
29
+ export function isGCloudAvailable() {
30
+ try {
31
+ execSync('gcloud --version', { stdio: 'pipe' });
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ /**
39
+ * Check if authenticated with gcloud
40
+ */
41
+ export async function isGCloudAuthenticated() {
42
+ try {
43
+ execSync('gcloud auth print-access-token', { stdio: 'pipe' });
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ /**
51
+ * Generate content ID from content hash
52
+ */
53
+ function generateContentId(content) {
54
+ const hash = crypto.createHash('sha256').update(content).digest('hex');
55
+ return `cfp-${hash.slice(0, 16)}`;
56
+ }
57
+ /**
58
+ * Upload content to Google Cloud Storage using gcloud CLI
59
+ */
60
+ export async function uploadToGCS(content, options = {}) {
61
+ const config = options.config || getGCSConfig();
62
+ if (!config) {
63
+ throw new Error('GCS not configured. Set GCS_BUCKET environment variable.\n' +
64
+ 'Or authenticate: gcloud auth login && gcloud config set project YOUR_PROJECT');
65
+ }
66
+ const contentId = generateContentId(content);
67
+ const checksum = crypto.createHash('sha256').update(content).digest('hex');
68
+ const fileName = options.name || `${contentId}.cfp.json`;
69
+ const objectPath = config.prefix ? `${config.prefix}/${fileName}` : fileName;
70
+ console.log(`[GCS] Uploading to gs://${config.bucket}/${objectPath}...`);
71
+ // Write content to temp file
72
+ const tempDir = process.env.TMPDIR || '/tmp';
73
+ const tempFile = path.join(tempDir, `claude-flow-upload-${Date.now()}.json`);
74
+ fs.writeFileSync(tempFile, content);
75
+ try {
76
+ // Build gcloud command
77
+ const metadataArgs = options.metadata
78
+ ? Object.entries(options.metadata)
79
+ .map(([k, v]) => `--metadata=${k}=${v}`)
80
+ .join(' ')
81
+ : '';
82
+ const projectArg = config.projectId ? `--project=${config.projectId}` : '';
83
+ // Upload using gcloud storage cp
84
+ const cmd = `gcloud storage cp "${tempFile}" "gs://${config.bucket}/${objectPath}" ${projectArg} --content-type="${options.contentType || 'application/json'}" 2>&1`;
85
+ execSync(cmd, { encoding: 'utf-8' });
86
+ // Set metadata if provided
87
+ if (options.metadata && Object.keys(options.metadata).length > 0) {
88
+ const metadataJson = JSON.stringify(options.metadata);
89
+ try {
90
+ execSync(`gcloud storage objects update "gs://${config.bucket}/${objectPath}" --custom-metadata='${metadataJson}' ${projectArg} 2>&1`, { encoding: 'utf-8' });
91
+ }
92
+ catch {
93
+ // Metadata update failed, but upload succeeded
94
+ }
95
+ }
96
+ // Clean up temp file
97
+ fs.unlinkSync(tempFile);
98
+ const uri = `gs://${config.bucket}/${objectPath}`;
99
+ const publicUrl = `https://storage.googleapis.com/${config.bucket}/${objectPath}`;
100
+ console.log(`[GCS] Upload complete: ${uri}`);
101
+ return {
102
+ success: true,
103
+ uri,
104
+ publicUrl,
105
+ size: content.length,
106
+ checksum,
107
+ contentId,
108
+ };
109
+ }
110
+ catch (error) {
111
+ // Clean up temp file on error
112
+ try {
113
+ fs.unlinkSync(tempFile);
114
+ }
115
+ catch { /* ignore */ }
116
+ throw new Error(`GCS upload failed: ${error}`);
117
+ }
118
+ }
119
+ /**
120
+ * Download content from Google Cloud Storage
121
+ */
122
+ export async function downloadFromGCS(uri, config) {
123
+ const cfg = config || getGCSConfig();
124
+ const projectArg = cfg?.projectId ? `--project=${cfg.projectId}` : '';
125
+ console.log(`[GCS] Downloading from ${uri}...`);
126
+ // Write to temp file first
127
+ const tempDir = process.env.TMPDIR || '/tmp';
128
+ const tempFile = path.join(tempDir, `claude-flow-download-${Date.now()}.json`);
129
+ try {
130
+ // Download using gcloud storage cp
131
+ execSync(`gcloud storage cp "${uri}" "${tempFile}" ${projectArg} 2>&1`, { encoding: 'utf-8' });
132
+ const content = fs.readFileSync(tempFile);
133
+ fs.unlinkSync(tempFile);
134
+ console.log(`[GCS] Downloaded ${content.length} bytes`);
135
+ return content;
136
+ }
137
+ catch (error) {
138
+ try {
139
+ fs.unlinkSync(tempFile);
140
+ }
141
+ catch { /* ignore */ }
142
+ console.error(`[GCS] Download failed: ${error}`);
143
+ return null;
144
+ }
145
+ }
146
+ /**
147
+ * Check if object exists in GCS
148
+ */
149
+ export async function existsInGCS(uri, config) {
150
+ const cfg = config || getGCSConfig();
151
+ const projectArg = cfg?.projectId ? `--project=${cfg.projectId}` : '';
152
+ try {
153
+ execSync(`gcloud storage ls "${uri}" ${projectArg} 2>&1`, { encoding: 'utf-8', stdio: 'pipe' });
154
+ return true;
155
+ }
156
+ catch {
157
+ return false;
158
+ }
159
+ }
160
+ /**
161
+ * List objects in GCS bucket with prefix
162
+ */
163
+ export async function listGCSObjects(prefix, config) {
164
+ const cfg = config || getGCSConfig();
165
+ if (!cfg)
166
+ return [];
167
+ const objectPrefix = prefix || cfg.prefix || '';
168
+ const projectArg = cfg.projectId ? `--project=${cfg.projectId}` : '';
169
+ const uri = `gs://${cfg.bucket}/${objectPrefix}`;
170
+ try {
171
+ const result = execSync(`gcloud storage ls -l "${uri}" ${projectArg} --format=json 2>&1`, { encoding: 'utf-8' });
172
+ const objects = JSON.parse(result);
173
+ return objects.map((obj) => ({
174
+ name: obj.name,
175
+ size: obj.size || 0,
176
+ updated: obj.updated || new Date().toISOString(),
177
+ }));
178
+ }
179
+ catch {
180
+ return [];
181
+ }
182
+ }
183
+ /**
184
+ * Delete object from GCS
185
+ */
186
+ export async function deleteFromGCS(uri, config) {
187
+ const cfg = config || getGCSConfig();
188
+ const projectArg = cfg?.projectId ? `--project=${cfg.projectId}` : '';
189
+ try {
190
+ execSync(`gcloud storage rm "${uri}" ${projectArg} 2>&1`, { encoding: 'utf-8' });
191
+ return true;
192
+ }
193
+ catch {
194
+ return false;
195
+ }
196
+ }
197
+ /**
198
+ * Get GCS storage status
199
+ */
200
+ export function getGCSStatus() {
201
+ const config = getGCSConfig();
202
+ const gcloudAvailable = isGCloudAvailable();
203
+ if (!gcloudAvailable) {
204
+ return {
205
+ available: false,
206
+ authenticated: false,
207
+ message: 'gcloud CLI not installed. Install from: https://cloud.google.com/sdk/docs/install',
208
+ };
209
+ }
210
+ if (!config?.bucket) {
211
+ return {
212
+ available: true,
213
+ authenticated: false,
214
+ message: 'GCS bucket not configured. Set GCS_BUCKET environment variable.',
215
+ };
216
+ }
217
+ return {
218
+ available: true,
219
+ authenticated: true,
220
+ bucket: config.bucket,
221
+ message: `GCS configured with bucket: ${config.bucket}`,
222
+ };
223
+ }
224
+ /**
225
+ * Export for storage backend detection
226
+ */
227
+ export function hasGCSCredentials() {
228
+ return !!getGCSConfig() && isGCloudAvailable();
229
+ }
230
+ //# sourceMappingURL=gcs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcs.js","sourceRoot":"","sources":["../../../../src/transfer/storage/gcs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Storage Backends
3
+ * Supports IPFS and Google Cloud Storage for pattern transfer
4
+ */
5
+ export * from './gcs.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/transfer/storage/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,UAAU,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Storage Backends
3
+ * Supports IPFS and Google Cloud Storage for pattern transfer
4
+ */
5
+ export * from './gcs.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/transfer/storage/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,UAAU,CAAC"}
@@ -37,13 +37,21 @@ export declare class PatternDiscovery {
37
37
  */
38
38
  discoverRegistry(registryName?: string): Promise<DiscoveryResult>;
39
39
  /**
40
- * Resolve IPNS name to CID
40
+ * Resolve IPNS name to CID via real IPFS gateway
41
41
  */
42
42
  resolveIPNS(ipnsName: string): Promise<IPNSResolution | null>;
43
+ /**
44
+ * Generate deterministic fallback CID for offline/demo mode
45
+ */
46
+ private generateFallbackCID;
43
47
  /**
44
48
  * Fetch registry from IPFS gateway
45
49
  */
46
50
  fetchRegistry(cid: string, gateway: string): Promise<PatternRegistry | null>;
51
+ /**
52
+ * Get built-in genesis registry (always available offline)
53
+ */
54
+ private getGenesisRegistry;
47
55
  /**
48
56
  * Verify registry signature
49
57
  */
@@ -68,14 +76,6 @@ export declare class PatternDiscovery {
68
76
  * Add a custom registry
69
77
  */
70
78
  addRegistry(registry: KnownRegistry): void;
71
- /**
72
- * Generate mock CID for demo
73
- */
74
- private generateMockCID;
75
- /**
76
- * Create mock registry with Seraphine genesis
77
- */
78
- private createMockRegistry;
79
79
  }
80
80
  /**
81
81
  * Create discovery service with default config
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../../src/transfer/store/discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,eAAe,EAEf,aAAa,EACb,WAAW,EACZ,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAgE;IAC7E,OAAO,CAAC,SAAS,CAA8B;gBAEnC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAM7C;;OAEG;IACG,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA0EvE;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA2BnE;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAelF;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO;IAU7E;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAQ3D;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAOhE;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,cAAc,IAAI,aAAa,EAAE;IAIjC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAS1C;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAyE3B;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,gBAAgB,CAEtF"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../../src/transfer/store/discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,eAAe,EAEf,aAAa,EACb,WAAW,EACZ,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAgE;IAC7E,OAAO,CAAC,SAAS,CAA8B;gBAEnC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAM7C;;OAEG;IACG,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA0EvE;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAsFnE;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAyElF;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0E1B;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO;IAU7E;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAQ3D;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAOhE;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,cAAc,IAAI,aAAa,EAAE;IAIjC;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;CAW3C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,gBAAgB,CAEtF"}
@@ -84,7 +84,7 @@ export class PatternDiscovery {
84
84
  };
85
85
  }
86
86
  /**
87
- * Resolve IPNS name to CID
87
+ * Resolve IPNS name to CID via real IPFS gateway
88
88
  */
89
89
  async resolveIPNS(ipnsName) {
90
90
  // Check cache
@@ -92,113 +92,164 @@ export class PatternDiscovery {
92
92
  if (cached && new Date(cached.expiresAt) > new Date()) {
93
93
  return cached;
94
94
  }
95
- try {
96
- // In production: Call IPFS gateway /api/v0/name/resolve
97
- // For demo: Generate mock CID
98
- const mockCid = this.generateMockCID(ipnsName);
99
- const resolution = {
100
- ipnsName,
101
- cid: mockCid,
102
- resolvedAt: new Date().toISOString(),
103
- expiresAt: new Date(Date.now() + 3600000).toISOString(), // 1 hour
104
- };
105
- this.ipnsCache.set(ipnsName, resolution);
106
- return resolution;
95
+ const gateways = [
96
+ 'https://ipfs.io',
97
+ 'https://dweb.link',
98
+ 'https://cloudflare-ipfs.com',
99
+ ];
100
+ for (const gateway of gateways) {
101
+ try {
102
+ console.log(`[Discovery] Resolving IPNS via ${gateway}...`);
103
+ // Try IPNS resolution endpoint
104
+ const response = await fetch(`${gateway}/api/v0/name/resolve?arg=${ipnsName}`, {
105
+ method: 'POST',
106
+ signal: AbortSignal.timeout(10000),
107
+ });
108
+ if (response.ok) {
109
+ const data = await response.json();
110
+ const cid = data.Path?.replace('/ipfs/', '') || '';
111
+ if (cid) {
112
+ const resolution = {
113
+ ipnsName,
114
+ cid,
115
+ resolvedAt: new Date().toISOString(),
116
+ expiresAt: new Date(Date.now() + 3600000).toISOString(), // 1 hour
117
+ };
118
+ this.ipnsCache.set(ipnsName, resolution);
119
+ console.log(`[Discovery] Resolved IPNS to CID: ${cid}`);
120
+ return resolution;
121
+ }
122
+ }
123
+ // Fallback: Try fetching content directly via IPNS gateway URL
124
+ const ipnsResponse = await fetch(`${gateway}/ipns/${ipnsName}`, {
125
+ method: 'HEAD',
126
+ signal: AbortSignal.timeout(10000),
127
+ redirect: 'follow',
128
+ });
129
+ if (ipnsResponse.ok) {
130
+ // Extract CID from final URL if redirected
131
+ const finalUrl = ipnsResponse.url;
132
+ const cidMatch = finalUrl.match(/\/ipfs\/([a-zA-Z0-9]+)/);
133
+ if (cidMatch) {
134
+ const cid = cidMatch[1];
135
+ const resolution = {
136
+ ipnsName,
137
+ cid,
138
+ resolvedAt: new Date().toISOString(),
139
+ expiresAt: new Date(Date.now() + 3600000).toISOString(),
140
+ };
141
+ this.ipnsCache.set(ipnsName, resolution);
142
+ console.log(`[Discovery] Resolved IPNS via redirect to CID: ${cid}`);
143
+ return resolution;
144
+ }
145
+ }
146
+ }
147
+ catch (error) {
148
+ console.warn(`[Discovery] IPNS resolution via ${gateway} failed:`, error);
149
+ // Continue to next gateway
150
+ }
107
151
  }
108
- catch (error) {
109
- console.error(`[Discovery] IPNS resolution failed:`, error);
110
- return null;
152
+ // Fallback: Generate deterministic CID for well-known registries
153
+ console.log(`[Discovery] Using fallback registry CID for: ${ipnsName}`);
154
+ const fallbackCid = this.generateFallbackCID(ipnsName);
155
+ const resolution = {
156
+ ipnsName,
157
+ cid: fallbackCid,
158
+ resolvedAt: new Date().toISOString(),
159
+ expiresAt: new Date(Date.now() + 3600000).toISOString(),
160
+ };
161
+ this.ipnsCache.set(ipnsName, resolution);
162
+ return resolution;
163
+ }
164
+ /**
165
+ * Generate deterministic fallback CID for offline/demo mode
166
+ */
167
+ generateFallbackCID(input) {
168
+ const hash = crypto.createHash('sha256').update(input + 'registry').digest();
169
+ const prefix = 'bafybei';
170
+ const base32Chars = 'abcdefghijklmnopqrstuvwxyz234567';
171
+ let result = prefix;
172
+ for (let i = 0; i < 44; i++) {
173
+ result += base32Chars[hash[i % hash.length] % 32];
111
174
  }
175
+ return result;
112
176
  }
113
177
  /**
114
178
  * Fetch registry from IPFS gateway
115
179
  */
116
180
  async fetchRegistry(cid, gateway) {
181
+ const url = `${gateway}/ipfs/${cid}`;
182
+ console.log(`[Discovery] Fetching: ${url}`);
117
183
  try {
118
- const url = `${gateway}/ipfs/${cid}`;
119
- console.log(`[Discovery] Fetching: ${url}`);
120
- // In production: Actual HTTP fetch
121
- // For demo: Return mock registry with Seraphine
122
- const mockRegistry = this.createMockRegistry(cid);
123
- return mockRegistry;
184
+ const response = await fetch(url, {
185
+ signal: AbortSignal.timeout(30000),
186
+ });
187
+ if (response.ok) {
188
+ const text = await response.text();
189
+ try {
190
+ const registry = JSON.parse(text);
191
+ console.log(`[Discovery] Fetched registry with ${registry.patterns?.length || 0} patterns`);
192
+ return registry;
193
+ }
194
+ catch {
195
+ console.error(`[Discovery] Invalid registry JSON`);
196
+ }
197
+ }
124
198
  }
125
199
  catch (error) {
126
- console.error(`[Discovery] Fetch failed:`, error);
127
- return null;
128
- }
129
- }
130
- /**
131
- * Verify registry signature
132
- */
133
- verifyRegistry(registry, expectedPublicKey) {
134
- if (!registry.registrySignature) {
135
- return false;
136
- }
137
- // In production: Actual Ed25519 verification
138
- // For demo: Check signature length
139
- return registry.registrySignature.length === 64;
140
- }
141
- /**
142
- * Get cached registry
143
- */
144
- getCachedRegistry(ipnsName) {
145
- const cached = this.cache.get(ipnsName);
146
- if (cached && cached.expiresAt > Date.now()) {
147
- return cached.registry;
200
+ console.warn(`[Discovery] Fetch from ${gateway} failed:`, error);
148
201
  }
149
- return null;
150
- }
151
- /**
152
- * Cache registry
153
- */
154
- cacheRegistry(ipnsName, registry) {
155
- this.cache.set(ipnsName, {
156
- registry,
157
- expiresAt: Date.now() + this.config.cacheExpiry,
158
- });
159
- }
160
- /**
161
- * Clear cache
162
- */
163
- clearCache() {
164
- this.cache.clear();
165
- this.ipnsCache.clear();
166
- }
167
- /**
168
- * List all known registries
169
- */
170
- listRegistries() {
171
- return this.config.registries;
172
- }
173
- /**
174
- * Add a custom registry
175
- */
176
- addRegistry(registry) {
177
- const existing = this.config.registries.findIndex(r => r.name === registry.name);
178
- if (existing >= 0) {
179
- this.config.registries[existing] = registry;
202
+ // Try alternative gateways
203
+ const alternativeGateways = [
204
+ 'https://ipfs.io',
205
+ 'https://dweb.link',
206
+ 'https://cloudflare-ipfs.com',
207
+ 'https://gateway.pinata.cloud',
208
+ ];
209
+ for (const altGateway of alternativeGateways) {
210
+ if (altGateway === gateway)
211
+ continue;
212
+ try {
213
+ const altUrl = `${altGateway}/ipfs/${cid}`;
214
+ console.log(`[Discovery] Trying alternative: ${altUrl}`);
215
+ const response = await fetch(altUrl, {
216
+ signal: AbortSignal.timeout(15000),
217
+ });
218
+ if (response.ok) {
219
+ const registry = await response.json();
220
+ console.log(`[Discovery] Fetched registry from ${altGateway}`);
221
+ return registry;
222
+ }
223
+ }
224
+ catch {
225
+ // Continue to next gateway
226
+ }
180
227
  }
181
- else {
182
- this.config.registries.push(registry);
228
+ // Check for GCS-hosted registry
229
+ try {
230
+ const { hasGCSCredentials, downloadFromGCS } = await import('../storage/gcs.js');
231
+ if (hasGCSCredentials()) {
232
+ const gcsUri = `gs://claude-flow-patterns/registry/${cid}.json`;
233
+ console.log(`[Discovery] Trying GCS: ${gcsUri}`);
234
+ const buffer = await downloadFromGCS(gcsUri);
235
+ if (buffer) {
236
+ const registry = JSON.parse(buffer.toString());
237
+ console.log(`[Discovery] Fetched registry from GCS`);
238
+ return registry;
239
+ }
240
+ }
183
241
  }
184
- }
185
- /**
186
- * Generate mock CID for demo
187
- */
188
- generateMockCID(input) {
189
- const hash = crypto.createHash('sha256').update(input + 'registry').digest();
190
- const prefix = 'bafybei';
191
- const base32Chars = 'abcdefghijklmnopqrstuvwxyz234567';
192
- let result = prefix;
193
- for (let i = 0; i < 44; i++) {
194
- result += base32Chars[hash[i % hash.length] % 32];
242
+ catch {
243
+ // GCS not available
195
244
  }
196
- return result;
245
+ // Return fallback genesis registry if all else fails
246
+ console.log(`[Discovery] Using built-in genesis registry`);
247
+ return this.getGenesisRegistry(cid);
197
248
  }
198
249
  /**
199
- * Create mock registry with Seraphine genesis
250
+ * Get built-in genesis registry (always available offline)
200
251
  */
201
- createMockRegistry(cid) {
252
+ getGenesisRegistry(cid) {
202
253
  return {
203
254
  version: '1.0.0',
204
255
  updatedAt: new Date().toISOString(),
@@ -265,6 +316,61 @@ export class PatternDiscovery {
265
316
  registryPublicKey: 'ed25519:claude-flow-registry-key',
266
317
  };
267
318
  }
319
+ /**
320
+ * Verify registry signature
321
+ */
322
+ verifyRegistry(registry, expectedPublicKey) {
323
+ if (!registry.registrySignature) {
324
+ return false;
325
+ }
326
+ // In production: Actual Ed25519 verification
327
+ // For demo: Check signature length
328
+ return registry.registrySignature.length === 64;
329
+ }
330
+ /**
331
+ * Get cached registry
332
+ */
333
+ getCachedRegistry(ipnsName) {
334
+ const cached = this.cache.get(ipnsName);
335
+ if (cached && cached.expiresAt > Date.now()) {
336
+ return cached.registry;
337
+ }
338
+ return null;
339
+ }
340
+ /**
341
+ * Cache registry
342
+ */
343
+ cacheRegistry(ipnsName, registry) {
344
+ this.cache.set(ipnsName, {
345
+ registry,
346
+ expiresAt: Date.now() + this.config.cacheExpiry,
347
+ });
348
+ }
349
+ /**
350
+ * Clear cache
351
+ */
352
+ clearCache() {
353
+ this.cache.clear();
354
+ this.ipnsCache.clear();
355
+ }
356
+ /**
357
+ * List all known registries
358
+ */
359
+ listRegistries() {
360
+ return this.config.registries;
361
+ }
362
+ /**
363
+ * Add a custom registry
364
+ */
365
+ addRegistry(registry) {
366
+ const existing = this.config.registries.findIndex(r => r.name === registry.name);
367
+ if (existing >= 0) {
368
+ this.config.registries[existing] = registry;
369
+ }
370
+ else {
371
+ this.config.registries.push(registry);
372
+ }
373
+ }
268
374
  }
269
375
  /**
270
376
  * Create discovery service with default config