bisync-cli 0.0.9 → 0.0.10
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/bisync.js +79 -47
- package/package.json +1 -1
package/dist/bisync.js
CHANGED
|
@@ -21,8 +21,6 @@ var CLAUDE_PROJECTS_DIR = join(homedir(), ".claude", "projects");
|
|
|
21
21
|
var DEBUG_LOG_PATH = join(CONFIG_DIR, "debug.log");
|
|
22
22
|
var CLIENT_ID = "bisync-cli";
|
|
23
23
|
var MAX_LINES_PER_BATCH = 200;
|
|
24
|
-
var MAX_STATE_CHUNKS_PER_BATCH = 50;
|
|
25
|
-
var MAX_STATE_CHUNK_SIZE = 256 * 1024;
|
|
26
24
|
var parseArgs = () => {
|
|
27
25
|
const parsed = parseArgsUtil({
|
|
28
26
|
args: process.argv.slice(2),
|
|
@@ -377,30 +375,67 @@ var collectSessionStateFiles = async (sessionDir) => {
|
|
|
377
375
|
await walk(sessionDir);
|
|
378
376
|
return files;
|
|
379
377
|
};
|
|
380
|
-
var
|
|
378
|
+
var getStateUploadUrls = async (siteUrl, token, count) => {
|
|
379
|
+
const response = await fetch(`${siteUrl}/api/storage/upload-url`, {
|
|
380
|
+
method: "POST",
|
|
381
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
382
|
+
body: JSON.stringify({ count })
|
|
383
|
+
});
|
|
384
|
+
if (!response.ok) {
|
|
385
|
+
const errorText = await response.text();
|
|
386
|
+
const error = new Error(`Upload URL request failed: ${response.status} ${errorText}`);
|
|
387
|
+
error.status = response.status;
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
const data = await response.json();
|
|
391
|
+
if (!Array.isArray(data.uploadUrls) || data.uploadUrls.length !== count) {
|
|
392
|
+
throw new Error("Upload URL response missing uploadUrls");
|
|
393
|
+
}
|
|
394
|
+
return data.uploadUrls;
|
|
395
|
+
};
|
|
396
|
+
var uploadStateFileToUrl = async (uploadUrl, filePath) => {
|
|
397
|
+
const response = await fetch(uploadUrl, {
|
|
398
|
+
method: "POST",
|
|
399
|
+
headers: { "Content-Type": "application/octet-stream" },
|
|
400
|
+
body: Bun.file(filePath)
|
|
401
|
+
});
|
|
402
|
+
if (!response.ok) {
|
|
403
|
+
const errorText = await response.text();
|
|
404
|
+
const error = new Error(`State upload failed: ${response.status} ${errorText}`);
|
|
405
|
+
error.status = response.status;
|
|
406
|
+
throw error;
|
|
407
|
+
}
|
|
408
|
+
const data = await response.json();
|
|
409
|
+
if (!data.storageId) {
|
|
410
|
+
throw new Error("State upload response missing storageId");
|
|
411
|
+
}
|
|
412
|
+
return data.storageId;
|
|
413
|
+
};
|
|
414
|
+
var buildStateFiles = async (sessionDir, siteUrl, token) => {
|
|
381
415
|
const files = await collectSessionStateFiles(sessionDir);
|
|
382
|
-
|
|
383
|
-
|
|
416
|
+
if (files.length === 0) {
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
419
|
+
const uploadUrls = await getStateUploadUrls(siteUrl, token, files.length);
|
|
420
|
+
const entries = [];
|
|
421
|
+
for (let index = 0;index < files.length; index += 1) {
|
|
422
|
+
const file = files[index];
|
|
423
|
+
const uploadUrl = uploadUrls[index];
|
|
424
|
+
if (!file || !uploadUrl) {
|
|
425
|
+
throw new Error("Upload URL list did not match file list");
|
|
426
|
+
}
|
|
384
427
|
const data = new Uint8Array(await Bun.file(file.fullPath).arrayBuffer());
|
|
385
428
|
const fileHash = createHash("sha256").update(data).digest("hex");
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
encoding: "base64",
|
|
395
|
-
fileHash,
|
|
396
|
-
partIndex,
|
|
397
|
-
partCount,
|
|
398
|
-
size: file.size,
|
|
399
|
-
mtimeMs: file.mtimeMs
|
|
400
|
-
});
|
|
401
|
-
}
|
|
429
|
+
const storageId = await uploadStateFileToUrl(uploadUrl, file.fullPath);
|
|
430
|
+
entries.push({
|
|
431
|
+
path: file.relativePath,
|
|
432
|
+
fileHash,
|
|
433
|
+
storageId,
|
|
434
|
+
size: file.size,
|
|
435
|
+
mtimeMs: file.mtimeMs
|
|
436
|
+
});
|
|
402
437
|
}
|
|
403
|
-
return
|
|
438
|
+
return entries;
|
|
404
439
|
};
|
|
405
440
|
var buildLogLines = (raw) => {
|
|
406
441
|
const lines = raw.split(`
|
|
@@ -443,27 +478,24 @@ var uploadLogs = async (siteUrl, token, sessionId, raw) => {
|
|
|
443
478
|
}
|
|
444
479
|
}
|
|
445
480
|
};
|
|
446
|
-
var uploadStateFiles = async (siteUrl, token, sessionId,
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
error.status = response.status;
|
|
465
|
-
throw error;
|
|
466
|
-
}
|
|
481
|
+
var uploadStateFiles = async (siteUrl, token, sessionId, files) => {
|
|
482
|
+
const response = await fetch(`${siteUrl}/api/ingest/state`, {
|
|
483
|
+
method: "POST",
|
|
484
|
+
headers: {
|
|
485
|
+
"Content-Type": "application/json",
|
|
486
|
+
Authorization: `Bearer ${token}`,
|
|
487
|
+
...process.env.BISYNC_SESSION_ID ? { "X-Bisync-Session-Id": process.env.BISYNC_SESSION_ID } : {}
|
|
488
|
+
},
|
|
489
|
+
body: JSON.stringify({
|
|
490
|
+
session_id: sessionId,
|
|
491
|
+
files
|
|
492
|
+
})
|
|
493
|
+
});
|
|
494
|
+
if (!response.ok) {
|
|
495
|
+
const errorText = await response.text();
|
|
496
|
+
const error = new Error(`State ingestion failed: ${response.status} ${errorText}`);
|
|
497
|
+
error.status = response.status;
|
|
498
|
+
throw error;
|
|
467
499
|
}
|
|
468
500
|
};
|
|
469
501
|
var signOutRemote = async (siteUrl, token) => {
|
|
@@ -676,15 +708,15 @@ var runHook = async (hookName) => {
|
|
|
676
708
|
}
|
|
677
709
|
}
|
|
678
710
|
}
|
|
679
|
-
if (sessionDir) {
|
|
711
|
+
if (sessionDir && hookName === "SessionEnd") {
|
|
680
712
|
log("debug", `runHook`, { sessionDir });
|
|
681
713
|
try {
|
|
682
|
-
const
|
|
683
|
-
if (
|
|
714
|
+
const stateFiles = await buildStateFiles(sessionDir, siteUrl, token);
|
|
715
|
+
if (stateFiles.length === 0) {
|
|
684
716
|
log("debug", `runHook`, { sessionId, error: "no-state-files" });
|
|
685
717
|
return;
|
|
686
718
|
}
|
|
687
|
-
await uploadStateFiles(siteUrl, token, sessionId,
|
|
719
|
+
await uploadStateFiles(siteUrl, token, sessionId, stateFiles);
|
|
688
720
|
log("debug", `runHook`, { sessionId, error: "state-upload-ok" });
|
|
689
721
|
} catch (error) {
|
|
690
722
|
log("debug", `runHook`, {
|