@savestate/cli 0.1.1 → 0.2.1
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/adapters/chatgpt.d.ts +113 -0
- package/dist/adapters/chatgpt.d.ts.map +1 -0
- package/dist/adapters/chatgpt.js +668 -0
- package/dist/adapters/chatgpt.js.map +1 -0
- package/dist/adapters/claude-web.d.ts +81 -0
- package/dist/adapters/claude-web.d.ts.map +1 -0
- package/dist/adapters/claude-web.js +903 -0
- package/dist/adapters/claude-web.js.map +1 -0
- package/dist/adapters/gemini.d.ts +108 -0
- package/dist/adapters/gemini.d.ts.map +1 -0
- package/dist/adapters/gemini.js +814 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/index.d.ts +1 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +1 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/openai-assistants.d.ts +79 -36
- package/dist/adapters/openai-assistants.d.ts.map +1 -1
- package/dist/adapters/openai-assistants.js +802 -78
- package/dist/adapters/openai-assistants.js.map +1 -1
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +6 -4
- package/dist/adapters/registry.js.map +1 -1
- package/dist/commands/adapters.js +5 -5
- package/dist/commands/adapters.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +40 -9
- package/dist/commands/config.js.map +1 -1
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/resolve.d.ts.map +1 -1
- package/dist/storage/resolve.js +19 -4
- package/dist/storage/resolve.js.map +1 -1
- package/dist/storage/s3.d.ts +64 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +360 -0
- package/dist/storage/s3.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3-Compatible Storage Backend
|
|
3
|
+
*
|
|
4
|
+
* Works with AWS S3, Cloudflare R2, Backblaze B2, and any S3-compatible service.
|
|
5
|
+
* Uses native fetch() and implements AWS Signature V4 from scratch — zero dependencies.
|
|
6
|
+
*
|
|
7
|
+
* Path-style access only (most compatible across providers).
|
|
8
|
+
*/
|
|
9
|
+
import { createHmac, createHash } from 'node:crypto';
|
|
10
|
+
// ─── Errors ──────────────────────────────────────────────────
|
|
11
|
+
export class S3Error extends Error {
|
|
12
|
+
statusCode;
|
|
13
|
+
code;
|
|
14
|
+
requestId;
|
|
15
|
+
constructor(message, statusCode, code, requestId) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.statusCode = statusCode;
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.requestId = requestId;
|
|
20
|
+
this.name = 'S3Error';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// ─── AWS Signature V4 ───────────────────────────────────────
|
|
24
|
+
const ALGORITHM = 'AWS4-HMAC-SHA256';
|
|
25
|
+
const SERVICE = 's3';
|
|
26
|
+
const UNSIGNED_PAYLOAD = 'UNSIGNED-PAYLOAD';
|
|
27
|
+
function sha256(data) {
|
|
28
|
+
return createHash('sha256').update(data).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
function hmacSha256(key, data) {
|
|
31
|
+
return createHmac('sha256', key).update(data).digest();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format a Date as YYYYMMDD'T'HHMMSS'Z' (ISO 8601 basic)
|
|
35
|
+
*/
|
|
36
|
+
function toAmzDate(date) {
|
|
37
|
+
return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Format a Date as YYYYMMDD
|
|
41
|
+
*/
|
|
42
|
+
function toDateStamp(date) {
|
|
43
|
+
return toAmzDate(date).slice(0, 8);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* URI-encode per AWS spec (RFC 3986 with some extras).
|
|
47
|
+
* Encodes everything except unreserved characters: A-Za-z0-9 _.-~
|
|
48
|
+
*/
|
|
49
|
+
function uriEncode(str, encodeSlash = true) {
|
|
50
|
+
return str
|
|
51
|
+
.split('')
|
|
52
|
+
.map((ch) => {
|
|
53
|
+
if ((ch >= 'A' && ch <= 'Z') ||
|
|
54
|
+
(ch >= 'a' && ch <= 'z') ||
|
|
55
|
+
(ch >= '0' && ch <= '9') ||
|
|
56
|
+
ch === '_' ||
|
|
57
|
+
ch === '-' ||
|
|
58
|
+
ch === '~' ||
|
|
59
|
+
ch === '.') {
|
|
60
|
+
return ch;
|
|
61
|
+
}
|
|
62
|
+
if (ch === '/' && !encodeSlash) {
|
|
63
|
+
return '/';
|
|
64
|
+
}
|
|
65
|
+
return '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0');
|
|
66
|
+
})
|
|
67
|
+
.join('');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* AWS Signature V4 signing implementation.
|
|
71
|
+
*
|
|
72
|
+
* Steps:
|
|
73
|
+
* 1. Create canonical request
|
|
74
|
+
* 2. Create string to sign
|
|
75
|
+
* 3. Derive signing key (HMAC chain)
|
|
76
|
+
* 4. Calculate signature
|
|
77
|
+
* 5. Build Authorization header
|
|
78
|
+
*/
|
|
79
|
+
function signRequest(params) {
|
|
80
|
+
const { method, path, query, headers, payloadHash, date, region, accessKeyId, secretAccessKey } = params;
|
|
81
|
+
const dateStamp = toDateStamp(date);
|
|
82
|
+
const amzDate = toAmzDate(date);
|
|
83
|
+
const scope = `${dateStamp}/${region}/${SERVICE}/aws4_request`;
|
|
84
|
+
// Step 1: Canonical request
|
|
85
|
+
// Sort query string parameters
|
|
86
|
+
const canonicalQueryString = query
|
|
87
|
+
? Object.keys(query)
|
|
88
|
+
.sort()
|
|
89
|
+
.map((k) => `${uriEncode(k)}=${uriEncode(query[k])}`)
|
|
90
|
+
.join('&')
|
|
91
|
+
: '';
|
|
92
|
+
// Canonical headers: lowercase, sorted, trimmed
|
|
93
|
+
const signedHeaderNames = Object.keys(headers)
|
|
94
|
+
.map((h) => h.toLowerCase())
|
|
95
|
+
.sort();
|
|
96
|
+
const canonicalHeaders = signedHeaderNames.map((h) => `${h}:${headers[h.toLowerCase()] ?? headers[h]}\n`).join('');
|
|
97
|
+
const signedHeaders = signedHeaderNames.join(';');
|
|
98
|
+
const canonicalRequest = [
|
|
99
|
+
method,
|
|
100
|
+
uriEncode(path, false),
|
|
101
|
+
canonicalQueryString,
|
|
102
|
+
canonicalHeaders,
|
|
103
|
+
signedHeaders,
|
|
104
|
+
payloadHash,
|
|
105
|
+
].join('\n');
|
|
106
|
+
// Step 2: String to sign
|
|
107
|
+
const stringToSign = [ALGORITHM, amzDate, scope, sha256(canonicalRequest)].join('\n');
|
|
108
|
+
// Step 3: Signing key (HMAC chain)
|
|
109
|
+
const kDate = hmacSha256(`AWS4${secretAccessKey}`, dateStamp);
|
|
110
|
+
const kRegion = hmacSha256(kDate, region);
|
|
111
|
+
const kService = hmacSha256(kRegion, SERVICE);
|
|
112
|
+
const kSigning = hmacSha256(kService, 'aws4_request');
|
|
113
|
+
// Step 4: Signature
|
|
114
|
+
const signature = hmacSha256(kSigning, stringToSign).toString('hex');
|
|
115
|
+
// Step 5: Authorization header
|
|
116
|
+
return `${ALGORITHM} Credential=${accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
|
|
117
|
+
}
|
|
118
|
+
// ─── XML Parsing Helpers ─────────────────────────────────────
|
|
119
|
+
function extractXmlTag(xml, tag) {
|
|
120
|
+
const match = xml.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
121
|
+
return match?.[1];
|
|
122
|
+
}
|
|
123
|
+
function extractAllXmlTags(xml, tag) {
|
|
124
|
+
return [...xml.matchAll(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`, 'g'))].map((m) => m[1]);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Parse S3 error XML response.
|
|
128
|
+
*/
|
|
129
|
+
function parseS3ErrorXml(xml) {
|
|
130
|
+
return {
|
|
131
|
+
code: extractXmlTag(xml, 'Code'),
|
|
132
|
+
message: extractXmlTag(xml, 'Message'),
|
|
133
|
+
requestId: extractXmlTag(xml, 'RequestId'),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// ─── S3 Storage Backend ──────────────────────────────────────
|
|
137
|
+
export class S3Storage {
|
|
138
|
+
id;
|
|
139
|
+
bucket;
|
|
140
|
+
endpoint;
|
|
141
|
+
region;
|
|
142
|
+
accessKeyId;
|
|
143
|
+
secretAccessKey;
|
|
144
|
+
prefix;
|
|
145
|
+
timeoutMs;
|
|
146
|
+
maxRetries;
|
|
147
|
+
host;
|
|
148
|
+
constructor(options) {
|
|
149
|
+
this.bucket = options.bucket || this.env('SAVESTATE_S3_BUCKET', '') || '';
|
|
150
|
+
this.endpoint = (options.endpoint || this.env('SAVESTATE_S3_ENDPOINT', 'AWS_ENDPOINT_URL') || '').replace(/\/+$/, '');
|
|
151
|
+
this.region = options.region || this.env('SAVESTATE_S3_REGION', 'AWS_REGION', 'AWS_DEFAULT_REGION') || 'auto';
|
|
152
|
+
this.accessKeyId = options.accessKeyId || this.env('SAVESTATE_S3_ACCESS_KEY_ID', 'AWS_ACCESS_KEY_ID') || '';
|
|
153
|
+
this.secretAccessKey = options.secretAccessKey || this.env('SAVESTATE_S3_SECRET_ACCESS_KEY', 'AWS_SECRET_ACCESS_KEY') || '';
|
|
154
|
+
this.prefix = options.prefix ?? '';
|
|
155
|
+
this.timeoutMs = options.timeoutMs ?? 30_000;
|
|
156
|
+
this.maxRetries = options.maxRetries ?? 3;
|
|
157
|
+
// Validate required fields
|
|
158
|
+
if (!this.bucket) {
|
|
159
|
+
throw new Error('S3 storage: bucket is required. Set storage.options.bucket in config or SAVESTATE_S3_BUCKET env var.');
|
|
160
|
+
}
|
|
161
|
+
if (!this.endpoint) {
|
|
162
|
+
throw new Error('S3 storage: endpoint is required. Set storage.options.endpoint in config or SAVESTATE_S3_ENDPOINT env var.\n' +
|
|
163
|
+
' Examples:\n' +
|
|
164
|
+
' Cloudflare R2: https://<account_id>.r2.cloudflarestorage.com\n' +
|
|
165
|
+
' AWS S3: https://s3.<region>.amazonaws.com\n' +
|
|
166
|
+
' Backblaze B2: https://s3.<region>.backblazeb2.com');
|
|
167
|
+
}
|
|
168
|
+
if (!this.accessKeyId || !this.secretAccessKey) {
|
|
169
|
+
throw new Error('S3 storage: credentials are required.\n' +
|
|
170
|
+
' Set storage.options.accessKeyId/secretAccessKey in config, or env vars:\n' +
|
|
171
|
+
' SAVESTATE_S3_ACCESS_KEY_ID / AWS_ACCESS_KEY_ID\n' +
|
|
172
|
+
' SAVESTATE_S3_SECRET_ACCESS_KEY / AWS_SECRET_ACCESS_KEY');
|
|
173
|
+
}
|
|
174
|
+
// Extract host from endpoint
|
|
175
|
+
const url = new URL(this.endpoint);
|
|
176
|
+
this.host = url.host;
|
|
177
|
+
// Determine backend id
|
|
178
|
+
if (this.endpoint.includes('.r2.cloudflarestorage.com')) {
|
|
179
|
+
this.id = 'r2';
|
|
180
|
+
}
|
|
181
|
+
else if (this.endpoint.includes('.backblazeb2.com')) {
|
|
182
|
+
this.id = 'b2';
|
|
183
|
+
}
|
|
184
|
+
else if (this.endpoint.includes('.amazonaws.com')) {
|
|
185
|
+
this.id = 's3';
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
this.id = 's3';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Read from env vars, trying multiple names in order.
|
|
193
|
+
*/
|
|
194
|
+
env(...names) {
|
|
195
|
+
for (const name of names) {
|
|
196
|
+
const val = process.env[name];
|
|
197
|
+
if (val)
|
|
198
|
+
return val;
|
|
199
|
+
}
|
|
200
|
+
return '';
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Build the full object key with prefix.
|
|
204
|
+
*/
|
|
205
|
+
fullKey(key) {
|
|
206
|
+
return this.prefix + key;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Execute a signed S3 request with retries.
|
|
210
|
+
*/
|
|
211
|
+
async request(method, objectKey, options) {
|
|
212
|
+
const { body, query, allow404 } = options ?? {};
|
|
213
|
+
const path = `/${this.bucket}/${objectKey}`.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
|
|
214
|
+
const payloadHash = body ? sha256(body) : sha256('');
|
|
215
|
+
let lastError;
|
|
216
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
217
|
+
if (attempt > 0) {
|
|
218
|
+
// Exponential backoff: 200ms, 400ms, 800ms...
|
|
219
|
+
const delay = Math.min(200 * Math.pow(2, attempt - 1), 5000);
|
|
220
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
221
|
+
}
|
|
222
|
+
const now = new Date();
|
|
223
|
+
const amzDate = toAmzDate(now);
|
|
224
|
+
// Build headers (lowercase keys for canonical request)
|
|
225
|
+
const headers = {
|
|
226
|
+
host: this.host,
|
|
227
|
+
'x-amz-date': amzDate,
|
|
228
|
+
'x-amz-content-sha256': payloadHash,
|
|
229
|
+
};
|
|
230
|
+
if (body) {
|
|
231
|
+
headers['content-length'] = String(body.length);
|
|
232
|
+
}
|
|
233
|
+
// Sign the request
|
|
234
|
+
const authorization = signRequest({
|
|
235
|
+
method,
|
|
236
|
+
path,
|
|
237
|
+
query,
|
|
238
|
+
headers,
|
|
239
|
+
payloadHash,
|
|
240
|
+
date: now,
|
|
241
|
+
region: this.region,
|
|
242
|
+
accessKeyId: this.accessKeyId,
|
|
243
|
+
secretAccessKey: this.secretAccessKey,
|
|
244
|
+
});
|
|
245
|
+
headers['authorization'] = authorization;
|
|
246
|
+
// Build URL with query string
|
|
247
|
+
let url = `${this.endpoint}${path}`;
|
|
248
|
+
if (query && Object.keys(query).length > 0) {
|
|
249
|
+
const qs = Object.entries(query)
|
|
250
|
+
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
|
|
251
|
+
.join('&');
|
|
252
|
+
url += `?${qs}`;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
const response = await fetch(url, {
|
|
256
|
+
method,
|
|
257
|
+
headers,
|
|
258
|
+
body: body ?? undefined,
|
|
259
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
260
|
+
});
|
|
261
|
+
// Retry on 5xx server errors
|
|
262
|
+
if (response.status >= 500 && attempt < this.maxRetries) {
|
|
263
|
+
lastError = new S3Error(`S3 server error (${response.status})`, response.status);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
// Handle 404 — return response if allowed, otherwise throw
|
|
267
|
+
if (response.status === 404) {
|
|
268
|
+
if (allow404)
|
|
269
|
+
return response;
|
|
270
|
+
const text = await response.text();
|
|
271
|
+
const err = parseS3ErrorXml(text);
|
|
272
|
+
throw new S3Error(`Object not found: ${objectKey}` + (err.code ? ` (${err.code})` : ''), 404, err.code ?? 'NoSuchKey', err.requestId);
|
|
273
|
+
}
|
|
274
|
+
// Handle other errors
|
|
275
|
+
if (!response.ok) {
|
|
276
|
+
const text = await response.text();
|
|
277
|
+
const err = parseS3ErrorXml(text);
|
|
278
|
+
const msg = err.message ?? `S3 request failed: ${method} ${path} → ${response.status}`;
|
|
279
|
+
throw new S3Error(msg, response.status, err.code, err.requestId);
|
|
280
|
+
}
|
|
281
|
+
return response;
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
if (error instanceof S3Error)
|
|
285
|
+
throw error;
|
|
286
|
+
// Network/timeout errors — retry if possible
|
|
287
|
+
if (attempt < this.maxRetries) {
|
|
288
|
+
lastError =
|
|
289
|
+
error instanceof Error ? error : new Error(String(error));
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (error instanceof Error && error.name === 'TimeoutError') {
|
|
293
|
+
throw new S3Error(`S3 request timed out after ${this.timeoutMs}ms: ${method} ${path}`, 0, 'TimeoutError');
|
|
294
|
+
}
|
|
295
|
+
throw error;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// Should not reach here, but just in case
|
|
299
|
+
throw lastError ?? new Error('S3 request failed after retries');
|
|
300
|
+
}
|
|
301
|
+
// ─── StorageBackend Interface ────────────────────────────
|
|
302
|
+
async put(key, data) {
|
|
303
|
+
await this.request('PUT', this.fullKey(key), { body: data });
|
|
304
|
+
}
|
|
305
|
+
async get(key) {
|
|
306
|
+
const response = await this.request('GET', this.fullKey(key));
|
|
307
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
308
|
+
return Buffer.from(arrayBuffer);
|
|
309
|
+
}
|
|
310
|
+
async list(prefix) {
|
|
311
|
+
const keys = [];
|
|
312
|
+
let continuationToken;
|
|
313
|
+
do {
|
|
314
|
+
const query = {
|
|
315
|
+
'list-type': '2',
|
|
316
|
+
};
|
|
317
|
+
// Combine storage prefix with caller's prefix
|
|
318
|
+
const fullPrefix = this.prefix + (prefix ?? '');
|
|
319
|
+
if (fullPrefix) {
|
|
320
|
+
query['prefix'] = fullPrefix;
|
|
321
|
+
}
|
|
322
|
+
if (continuationToken) {
|
|
323
|
+
query['continuation-token'] = continuationToken;
|
|
324
|
+
}
|
|
325
|
+
// List is on the bucket root path
|
|
326
|
+
const response = await this.request('GET', '', { query });
|
|
327
|
+
const xml = await response.text();
|
|
328
|
+
// Extract keys from XML
|
|
329
|
+
const rawKeys = extractAllXmlTags(xml, 'Key');
|
|
330
|
+
// Strip the storage prefix from keys so callers see relative paths
|
|
331
|
+
for (const rawKey of rawKeys) {
|
|
332
|
+
if (this.prefix && rawKey.startsWith(this.prefix)) {
|
|
333
|
+
keys.push(rawKey.slice(this.prefix.length));
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
keys.push(rawKey);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Check for pagination
|
|
340
|
+
const isTruncated = xml.includes('<IsTruncated>true</IsTruncated>');
|
|
341
|
+
if (isTruncated) {
|
|
342
|
+
continuationToken = extractXmlTag(xml, 'NextContinuationToken');
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
continuationToken = undefined;
|
|
346
|
+
}
|
|
347
|
+
} while (continuationToken);
|
|
348
|
+
return keys;
|
|
349
|
+
}
|
|
350
|
+
async delete(key) {
|
|
351
|
+
await this.request('DELETE', this.fullKey(key));
|
|
352
|
+
}
|
|
353
|
+
async exists(key) {
|
|
354
|
+
const response = await this.request('HEAD', this.fullKey(key), {
|
|
355
|
+
allow404: true,
|
|
356
|
+
});
|
|
357
|
+
return response.status !== 404;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=s3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/storage/s3.ts"],"names":[],"mappings":"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"}
|