@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.
- package/dist/src/commands/claims.d.ts.map +1 -1
- package/dist/src/commands/claims.js +92 -7
- package/dist/src/commands/claims.js.map +1 -1
- package/dist/src/commands/embeddings.d.ts.map +1 -1
- package/dist/src/commands/embeddings.js +99 -5
- package/dist/src/commands/embeddings.js.map +1 -1
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +2 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/neural.d.ts.map +1 -1
- package/dist/src/commands/neural.js +68 -16
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/commands/performance.d.ts.map +1 -1
- package/dist/src/commands/performance.js +155 -9
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/security.d.ts.map +1 -1
- package/dist/src/commands/security.js +199 -31
- package/dist/src/commands/security.js.map +1 -1
- package/dist/src/commands/update.d.ts +8 -0
- package/dist/src/commands/update.d.ts.map +1 -0
- package/dist/src/commands/update.js +276 -0
- package/dist/src/commands/update.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +28 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/transfer/storage/gcs.d.ts +82 -0
- package/dist/src/transfer/storage/gcs.d.ts.map +1 -0
- package/dist/src/transfer/storage/gcs.js +230 -0
- package/dist/src/transfer/storage/gcs.js.map +1 -0
- package/dist/src/transfer/storage/index.d.ts +6 -0
- package/dist/src/transfer/storage/index.d.ts.map +1 -0
- package/dist/src/transfer/storage/index.js +6 -0
- package/dist/src/transfer/storage/index.js.map +1 -0
- package/dist/src/transfer/store/discovery.d.ts +9 -9
- package/dist/src/transfer/store/discovery.d.ts.map +1 -1
- package/dist/src/transfer/store/discovery.js +197 -91
- package/dist/src/transfer/store/discovery.js.map +1 -1
- package/dist/src/transfer/store/download.d.ts +6 -6
- package/dist/src/transfer/store/download.d.ts.map +1 -1
- package/dist/src/transfer/store/download.js +104 -65
- package/dist/src/transfer/store/download.js.map +1 -1
- package/dist/src/transfer/store/publish.d.ts.map +1 -1
- package/dist/src/transfer/store/publish.js +57 -25
- package/dist/src/transfer/store/publish.js.map +1 -1
- package/dist/src/update/checker.d.ts +34 -0
- package/dist/src/update/checker.d.ts.map +1 -0
- package/dist/src/update/checker.js +190 -0
- package/dist/src/update/checker.js.map +1 -0
- package/dist/src/update/executor.d.ts +32 -0
- package/dist/src/update/executor.d.ts.map +1 -0
- package/dist/src/update/executor.js +181 -0
- package/dist/src/update/executor.js.map +1 -0
- package/dist/src/update/index.d.ts +33 -0
- package/dist/src/update/index.d.ts.map +1 -0
- package/dist/src/update/index.js +64 -0
- package/dist/src/update/index.js.map +1 -0
- package/dist/src/update/rate-limiter.d.ts +20 -0
- package/dist/src/update/rate-limiter.d.ts.map +1 -0
- package/dist/src/update/rate-limiter.js +96 -0
- package/dist/src/update/rate-limiter.js.map +1 -0
- package/dist/src/update/validator.d.ts +17 -0
- package/dist/src/update/validator.d.ts.map +1 -0
- package/dist/src/update/validator.js +123 -0
- package/dist/src/update/validator.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- 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":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAQ,MAAM,eAAe,CAAC;AAwB/C;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACzE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO;QACL,MAAM;QACN,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB;QACzE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B;QACnD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,sBAAsB;KACzD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,QAAQ,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,IAAI,CAAC;QACH,QAAQ,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,UAKI,EAAE;IAEN,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,YAAY,EAAE,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,4DAA4D;YAC5D,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,SAAS,WAAW,CAAC;IACzD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAE7E,OAAO,CAAC,GAAG,CAAC,2BAA2B,MAAM,CAAC,MAAM,IAAI,UAAU,KAAK,CAAC,CAAC;IAEzE,6BAA6B;IAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC7E,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEpC,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ;YACnC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;iBAC7B,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;iBACvC,IAAI,CAAC,GAAG,CAAC;YACd,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3E,iCAAiC;QACjC,MAAM,GAAG,GAAG,sBAAsB,QAAQ,WAAW,MAAM,CAAC,MAAM,IAAI,UAAU,KAAK,UAAU,oBAAoB,OAAO,CAAC,WAAW,IAAI,kBAAkB,QAAQ,CAAC;QAErK,QAAQ,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAErC,2BAA2B;QAC3B,IAAI,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACtD,IAAI,CAAC;gBACH,QAAQ,CACN,uCAAuC,MAAM,CAAC,MAAM,IAAI,UAAU,wBAAwB,YAAY,KAAK,UAAU,OAAO,EAC5H,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,+CAA+C;YACjD,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAExB,MAAM,GAAG,GAAG,QAAQ,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAClD,MAAM,SAAS,GAAG,kCAAkC,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAElF,OAAO,CAAC,GAAG,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;QAE7C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,GAAG;YACH,SAAS;YACT,IAAI,EAAE,OAAO,CAAC,MAAM;YACpB,QAAQ;YACR,SAAS;SACV,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8BAA8B;QAC9B,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAExB,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,MAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtE,OAAO,CAAC,GAAG,CAAC,0BAA0B,GAAG,KAAK,CAAC,CAAC;IAEhD,2BAA2B;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE/E,IAAI,CAAC;QACH,mCAAmC;QACnC,QAAQ,CACN,sBAAsB,GAAG,MAAM,QAAQ,KAAK,UAAU,OAAO,EAC7D,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC1C,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAExB,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,CAAC,MAAM,QAAQ,CAAC,CAAC;QACxD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAExB,OAAO,CAAC,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAW,EACX,MAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtE,IAAI,CAAC;QACH,QAAQ,CACN,sBAAsB,GAAG,KAAK,UAAU,OAAO,EAC/C,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CACrC,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAe,EACf,MAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACrC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IAEpB,MAAM,YAAY,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,MAAM,GAAG,GAAG,QAAQ,GAAG,CAAC,MAAM,IAAI,YAAY,EAAE,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CACrB,yBAAyB,GAAG,KAAK,UAAU,qBAAqB,EAChE,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,GAAoD,EAAE,EAAE,CAAC,CAAC;YAC5E,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;YACnB,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACjD,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,MAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtE,IAAI,CAAC;QACH,QAAQ,CACN,sBAAsB,GAAG,KAAK,UAAU,OAAO,EAC/C,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAM1B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,eAAe,GAAG,iBAAiB,EAAE,CAAC;IAE5C,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,KAAK;YACpB,OAAO,EAAE,mFAAmF;SAC7F,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO;YACL,SAAS,EAAE,IAAI;YACf,aAAa,EAAE,KAAK;YACpB,OAAO,EAAE,iEAAiE;SAC3E,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,IAAI;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,+BAA+B,MAAM,CAAC,MAAM,EAAE;KACxD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,CAAC,CAAC,YAAY,EAAE,IAAI,iBAAiB,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -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 @@
|
|
|
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;
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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.
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
250
|
+
* Get built-in genesis registry (always available offline)
|
|
200
251
|
*/
|
|
201
|
-
|
|
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
|