ccsini 0.1.5 → 0.1.7
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/index.js +52 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -26950,7 +26950,7 @@ var {
|
|
|
26950
26950
|
} = import__.default;
|
|
26951
26951
|
|
|
26952
26952
|
// src/version.ts
|
|
26953
|
-
var VERSION = "0.1.
|
|
26953
|
+
var VERSION = "0.1.7";
|
|
26954
26954
|
|
|
26955
26955
|
// src/commands/init.ts
|
|
26956
26956
|
init_source();
|
|
@@ -28369,13 +28369,19 @@ async function walkDir(dir) {
|
|
|
28369
28369
|
}
|
|
28370
28370
|
return files;
|
|
28371
28371
|
}
|
|
28372
|
-
async function scanClaudeDir(claudeDir) {
|
|
28372
|
+
async function scanClaudeDir(claudeDir, onProgress) {
|
|
28373
|
+
const progress = onProgress ?? (() => {});
|
|
28374
|
+
progress("Walking directory tree...");
|
|
28373
28375
|
const allFiles = await walkDir(claudeDir);
|
|
28376
|
+
progress(`Found ${allFiles.length} files, hashing...`);
|
|
28374
28377
|
const results = [];
|
|
28378
|
+
let processed = 0;
|
|
28375
28379
|
for (const absolutePath of allFiles) {
|
|
28376
28380
|
const relativePath = relative(claudeDir, absolutePath).split("\\").join("/");
|
|
28377
|
-
if (isExcluded(relativePath))
|
|
28381
|
+
if (isExcluded(relativePath)) {
|
|
28382
|
+
processed++;
|
|
28378
28383
|
continue;
|
|
28384
|
+
}
|
|
28379
28385
|
const fileStat = await stat(absolutePath);
|
|
28380
28386
|
const hash = await hashFile(absolutePath);
|
|
28381
28387
|
results.push({
|
|
@@ -28386,13 +28392,17 @@ async function scanClaudeDir(claudeDir) {
|
|
|
28386
28392
|
modified: fileStat.mtimeMs,
|
|
28387
28393
|
category: categorizeFile(relativePath)
|
|
28388
28394
|
});
|
|
28395
|
+
processed++;
|
|
28396
|
+
if (processed % 10 === 0 || processed === allFiles.length) {
|
|
28397
|
+
progress(`Scanning ${processed}/${allFiles.length}: ${relativePath}`);
|
|
28398
|
+
}
|
|
28389
28399
|
}
|
|
28390
28400
|
return results;
|
|
28391
28401
|
}
|
|
28392
28402
|
|
|
28393
28403
|
// src/core/manifest.ts
|
|
28394
|
-
async function generateManifest(claudeDir, deviceName) {
|
|
28395
|
-
const files = await scanClaudeDir(claudeDir);
|
|
28404
|
+
async function generateManifest(claudeDir, deviceName, onProgress) {
|
|
28405
|
+
const files = await scanClaudeDir(claudeDir, onProgress);
|
|
28396
28406
|
const entries = {};
|
|
28397
28407
|
for (const file of files) {
|
|
28398
28408
|
entries[file.relativePath] = {
|
|
@@ -28498,12 +28508,16 @@ function mergeLastWriteWins(localContent, remoteContent, localModified, remoteMo
|
|
|
28498
28508
|
function getClaudeDir() {
|
|
28499
28509
|
return join6(homedir2(), ".claude");
|
|
28500
28510
|
}
|
|
28501
|
-
async function pushSync(client, masterKey, deviceName, configDir) {
|
|
28511
|
+
async function pushSync(client, masterKey, deviceName, configDir, onProgress) {
|
|
28502
28512
|
const start = Date.now();
|
|
28503
28513
|
const claudeDir = getClaudeDir();
|
|
28504
28514
|
const errors2 = [];
|
|
28505
28515
|
let bytesTransferred = 0;
|
|
28506
|
-
const
|
|
28516
|
+
const progress = onProgress ?? (() => {});
|
|
28517
|
+
const localManifest = await generateManifest(claudeDir, deviceName, progress);
|
|
28518
|
+
const fileCount = Object.keys(localManifest.files).length;
|
|
28519
|
+
progress(`Scanned ${fileCount} files`);
|
|
28520
|
+
progress("Fetching remote manifest...");
|
|
28507
28521
|
const remoteManifestEnc = await client.getManifest();
|
|
28508
28522
|
let remoteManifest = null;
|
|
28509
28523
|
if (remoteManifestEnc) {
|
|
@@ -28514,8 +28528,11 @@ async function pushSync(client, masterKey, deviceName, configDir) {
|
|
|
28514
28528
|
remoteManifest = null;
|
|
28515
28529
|
}
|
|
28516
28530
|
}
|
|
28531
|
+
progress("Comparing manifests...");
|
|
28517
28532
|
const diffs = diffManifests(localManifest, remoteManifest);
|
|
28518
28533
|
const toPush = diffs.filter((d) => d.action === "push" || d.action === "merge");
|
|
28534
|
+
progress(`${toPush.length} files to push`);
|
|
28535
|
+
let uploaded = 0;
|
|
28519
28536
|
const chunks = chunkArray(toPush, MAX_CONCURRENT_TRANSFERS);
|
|
28520
28537
|
for (const chunk of chunks) {
|
|
28521
28538
|
await Promise.all(chunk.map(async (diff) => {
|
|
@@ -28525,16 +28542,20 @@ async function pushSync(client, masterKey, deviceName, configDir) {
|
|
|
28525
28542
|
const encrypted = encryptFile(masterKey, diff.path, content);
|
|
28526
28543
|
await client.uploadBlob(diff.localHash, encrypted);
|
|
28527
28544
|
bytesTransferred += encrypted.length;
|
|
28545
|
+
uploaded++;
|
|
28546
|
+
progress(`Uploading ${uploaded}/${toPush.length}: ${diff.path}`);
|
|
28528
28547
|
} catch (e) {
|
|
28529
28548
|
errors2.push(`Push ${diff.path}: ${e.message}`);
|
|
28530
28549
|
}
|
|
28531
28550
|
}));
|
|
28532
28551
|
}
|
|
28552
|
+
progress("Saving manifest...");
|
|
28533
28553
|
const manifestJson = JSON.stringify(localManifest);
|
|
28534
28554
|
const manifestEnc = encryptFile(masterKey, "__manifest__", new TextEncoder().encode(manifestJson));
|
|
28535
28555
|
await client.putManifest(manifestEnc);
|
|
28536
28556
|
await saveManifest(configDir, localManifest);
|
|
28537
28557
|
const durationMs = Date.now() - start;
|
|
28558
|
+
progress("Logging sync event...");
|
|
28538
28559
|
await client.logSyncEvent({
|
|
28539
28560
|
action: "push",
|
|
28540
28561
|
filesChanged: toPush.length,
|
|
@@ -28549,11 +28570,13 @@ async function pushSync(client, masterKey, deviceName, configDir) {
|
|
|
28549
28570
|
errors: errors2
|
|
28550
28571
|
};
|
|
28551
28572
|
}
|
|
28552
|
-
async function pullSync(client, masterKey, deviceName, configDir) {
|
|
28573
|
+
async function pullSync(client, masterKey, deviceName, configDir, onProgress) {
|
|
28553
28574
|
const start = Date.now();
|
|
28554
28575
|
const claudeDir = getClaudeDir();
|
|
28555
28576
|
const errors2 = [];
|
|
28556
28577
|
let bytesTransferred = 0;
|
|
28578
|
+
const progress = onProgress ?? (() => {});
|
|
28579
|
+
progress("Fetching remote manifest...");
|
|
28557
28580
|
const remoteManifestEnc = await client.getManifest();
|
|
28558
28581
|
if (!remoteManifestEnc) {
|
|
28559
28582
|
return {
|
|
@@ -28579,9 +28602,13 @@ async function pullSync(client, masterKey, deviceName, configDir) {
|
|
|
28579
28602
|
]
|
|
28580
28603
|
};
|
|
28581
28604
|
}
|
|
28605
|
+
progress("Loading local manifest...");
|
|
28582
28606
|
const localManifest = await loadManifest(configDir);
|
|
28607
|
+
progress("Comparing manifests...");
|
|
28583
28608
|
const diffs = diffManifests(localManifest, remoteManifest);
|
|
28584
28609
|
const toPull = diffs.filter((d) => d.action === "pull" || d.action === "merge");
|
|
28610
|
+
progress(`${toPull.length} files to pull`);
|
|
28611
|
+
let downloaded = 0;
|
|
28585
28612
|
const chunks = chunkArray(toPull, MAX_CONCURRENT_TRANSFERS);
|
|
28586
28613
|
for (const chunk of chunks) {
|
|
28587
28614
|
await Promise.all(chunk.map(async (diff) => {
|
|
@@ -28596,6 +28623,8 @@ async function pullSync(client, masterKey, deviceName, configDir) {
|
|
|
28596
28623
|
if (diff.category === "session") {
|
|
28597
28624
|
const merged = mergeSessionFiles(localContent, remoteContent);
|
|
28598
28625
|
await writeFile5(localPath2, merged);
|
|
28626
|
+
downloaded++;
|
|
28627
|
+
progress(`Downloading ${downloaded}/${toPull.length}: ${diff.path}`);
|
|
28599
28628
|
return;
|
|
28600
28629
|
}
|
|
28601
28630
|
const entry = remoteManifest.files[diff.path];
|
|
@@ -28604,19 +28633,25 @@ async function pullSync(client, masterKey, deviceName, configDir) {
|
|
|
28604
28633
|
const result = mergeLastWriteWins(localContent, remoteContent, localEntry.modified, entry.modified);
|
|
28605
28634
|
await writeFile5(localPath2, result.content);
|
|
28606
28635
|
await writeFile5(`${localPath2}.bak`, result.backupContent);
|
|
28636
|
+
downloaded++;
|
|
28637
|
+
progress(`Downloading ${downloaded}/${toPull.length}: ${diff.path}`);
|
|
28607
28638
|
return;
|
|
28608
28639
|
}
|
|
28609
28640
|
}
|
|
28610
28641
|
const localPath = join6(claudeDir, diff.path);
|
|
28611
28642
|
await mkdir2(dirname(localPath), { recursive: true });
|
|
28612
28643
|
await writeFile5(localPath, decrypted);
|
|
28644
|
+
downloaded++;
|
|
28645
|
+
progress(`Downloading ${downloaded}/${toPull.length}: ${diff.path}`);
|
|
28613
28646
|
} catch (e) {
|
|
28614
28647
|
errors2.push(`Pull ${diff.path}: ${e.message}`);
|
|
28615
28648
|
}
|
|
28616
28649
|
}));
|
|
28617
28650
|
}
|
|
28651
|
+
progress("Saving manifest...");
|
|
28618
28652
|
await saveManifest(configDir, remoteManifest);
|
|
28619
28653
|
const durationMs = Date.now() - start;
|
|
28654
|
+
progress("Logging sync event...");
|
|
28620
28655
|
await client.logSyncEvent({
|
|
28621
28656
|
action: "pull",
|
|
28622
28657
|
filesChanged: toPull.length,
|
|
@@ -29004,7 +29039,9 @@ function registerSyncCommands(program2) {
|
|
|
29004
29039
|
const client = await getAuthenticatedClient2(configDir);
|
|
29005
29040
|
const config = await loadKeys(configDir);
|
|
29006
29041
|
const spinner = ora2("Scanning files...").start();
|
|
29007
|
-
const result = await pushSync(client, masterKey, config.deviceName, configDir)
|
|
29042
|
+
const result = await pushSync(client, masterKey, config.deviceName, configDir, (msg) => {
|
|
29043
|
+
spinner.text = msg;
|
|
29044
|
+
});
|
|
29008
29045
|
if (result.errors.length > 0) {
|
|
29009
29046
|
spinner.warn("Push completed with errors");
|
|
29010
29047
|
for (const err of result.errors) {
|
|
@@ -29032,7 +29069,9 @@ function registerSyncCommands(program2) {
|
|
|
29032
29069
|
const client = await getAuthenticatedClient2(configDir);
|
|
29033
29070
|
const config = await loadKeys(configDir);
|
|
29034
29071
|
const spinner = ora2("Pulling from cloud...").start();
|
|
29035
|
-
const result = await pullSync(client, masterKey, config.deviceName, configDir)
|
|
29072
|
+
const result = await pullSync(client, masterKey, config.deviceName, configDir, (msg) => {
|
|
29073
|
+
spinner.text = msg;
|
|
29074
|
+
});
|
|
29036
29075
|
if (result.errors.length > 0) {
|
|
29037
29076
|
spinner.warn("Pull completed with errors");
|
|
29038
29077
|
for (const err of result.errors) {
|
|
@@ -29062,7 +29101,9 @@ function registerSyncCommands(program2) {
|
|
|
29062
29101
|
const spinner = ora2("Checking status...").start();
|
|
29063
29102
|
const localManifest = await loadManifest(configDir);
|
|
29064
29103
|
const claudeDir = getClaudeDir();
|
|
29065
|
-
const currentManifest = await generateManifest(claudeDir, config.deviceName)
|
|
29104
|
+
const currentManifest = await generateManifest(claudeDir, config.deviceName, (msg) => {
|
|
29105
|
+
spinner.text = msg;
|
|
29106
|
+
});
|
|
29066
29107
|
let remoteManifest = null;
|
|
29067
29108
|
const remoteManifestEnc = await client.getManifest();
|
|
29068
29109
|
if (remoteManifestEnc) {
|