ccsini 0.1.49 → 0.1.50
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 +44 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28020,7 +28020,7 @@ var {
|
|
|
28020
28020
|
} = import__.default;
|
|
28021
28021
|
|
|
28022
28022
|
// src/version.ts
|
|
28023
|
-
var VERSION = "0.1.
|
|
28023
|
+
var VERSION = "0.1.50";
|
|
28024
28024
|
|
|
28025
28025
|
// src/commands/init.ts
|
|
28026
28026
|
init_source();
|
|
@@ -29098,7 +29098,7 @@ class CcsiniClient {
|
|
|
29098
29098
|
// src/core/sync.ts
|
|
29099
29099
|
import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir2 } from "fs/promises";
|
|
29100
29100
|
import { join as join6, dirname } from "path";
|
|
29101
|
-
import { homedir as
|
|
29101
|
+
import { homedir as homedir3 } from "os";
|
|
29102
29102
|
import { createHash as createHash2 } from "crypto";
|
|
29103
29103
|
|
|
29104
29104
|
// src/core/manifest.ts
|
|
@@ -29107,8 +29107,9 @@ import { join as join5 } from "path";
|
|
|
29107
29107
|
|
|
29108
29108
|
// src/core/scanner.ts
|
|
29109
29109
|
init_src();
|
|
29110
|
-
import { readdir, readFile as readFile4, stat } from "fs/promises";
|
|
29110
|
+
import { readdir, readFile as readFile4, stat, appendFile } from "fs/promises";
|
|
29111
29111
|
import { join as join4, relative } from "path";
|
|
29112
|
+
import { homedir as homedir2 } from "os";
|
|
29112
29113
|
import { createHash } from "crypto";
|
|
29113
29114
|
function categorizeFile(relativePath) {
|
|
29114
29115
|
for (const [category, patterns] of Object.entries(DEFAULT_CATEGORY_PATTERNS)) {
|
|
@@ -29165,17 +29166,23 @@ function filterSessionFiles(files, options) {
|
|
|
29165
29166
|
}
|
|
29166
29167
|
var cacheHits = 0;
|
|
29167
29168
|
var cacheMisses = 0;
|
|
29169
|
+
async function logDebug(message2) {
|
|
29170
|
+
const logPath = join4(homedir2(), ".ccsini", "cache-debug.log");
|
|
29171
|
+
const timestamp = new Date().toISOString();
|
|
29172
|
+
await appendFile(logPath, `[${timestamp}] ${message2}
|
|
29173
|
+
`).catch(() => {});
|
|
29174
|
+
}
|
|
29168
29175
|
async function hashFileIfNeeded(filePath, relativePath, currentMtime, cachedManifest) {
|
|
29169
29176
|
if (cachedManifest) {
|
|
29170
29177
|
const cached = cachedManifest.files[relativePath];
|
|
29171
|
-
if (cached && Math.abs(cached.modified - currentMtime) <
|
|
29178
|
+
if (cached && Math.abs(cached.modified - currentMtime) < 100) {
|
|
29172
29179
|
cacheHits++;
|
|
29173
29180
|
return cached.hash;
|
|
29174
29181
|
}
|
|
29175
29182
|
if (cached) {
|
|
29176
29183
|
const diff = Math.abs(cached.modified - currentMtime);
|
|
29177
|
-
if (diff
|
|
29178
|
-
|
|
29184
|
+
if (diff >= 100) {
|
|
29185
|
+
await logDebug(`Cache MISS: ${relativePath} (\u0394${diff.toFixed(2)}ms)`);
|
|
29179
29186
|
}
|
|
29180
29187
|
}
|
|
29181
29188
|
}
|
|
@@ -29236,16 +29243,21 @@ async function scanClaudeDir(claudeDir, onProgress, sessionOptions, cachedManife
|
|
|
29236
29243
|
const diff = results.length - filtered.length;
|
|
29237
29244
|
progress(`Filtered ${diff} session files (${filtered.length} files to sync)`);
|
|
29238
29245
|
}
|
|
29239
|
-
|
|
29246
|
+
const stats = cacheHits + cacheMisses > 0 ? {
|
|
29247
|
+
hits: cacheHits,
|
|
29248
|
+
misses: cacheMisses,
|
|
29249
|
+
hitRate: cacheHits / (cacheHits + cacheMisses) * 100
|
|
29250
|
+
} : undefined;
|
|
29251
|
+
return { files: filtered, cacheStats: stats };
|
|
29240
29252
|
}
|
|
29241
29253
|
|
|
29242
29254
|
// src/core/manifest.ts
|
|
29243
29255
|
async function generateManifest(claudeDir, deviceName, onProgress, sessionOptions) {
|
|
29244
29256
|
const configDir = getConfigDir();
|
|
29245
29257
|
const cachedManifest = await loadManifest(configDir);
|
|
29246
|
-
const
|
|
29258
|
+
const scanResult = await scanClaudeDir(claudeDir, onProgress, sessionOptions, cachedManifest ?? undefined);
|
|
29247
29259
|
const entries = {};
|
|
29248
|
-
for (const file of files) {
|
|
29260
|
+
for (const file of scanResult.files) {
|
|
29249
29261
|
entries[file.relativePath] = {
|
|
29250
29262
|
hash: file.hash,
|
|
29251
29263
|
size: file.size,
|
|
@@ -29254,10 +29266,13 @@ async function generateManifest(claudeDir, deviceName, onProgress, sessionOption
|
|
|
29254
29266
|
};
|
|
29255
29267
|
}
|
|
29256
29268
|
return {
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
|
|
29260
|
-
|
|
29269
|
+
manifest: {
|
|
29270
|
+
version: 1,
|
|
29271
|
+
device: deviceName,
|
|
29272
|
+
timestamp: Date.now(),
|
|
29273
|
+
files: entries
|
|
29274
|
+
},
|
|
29275
|
+
cacheStats: scanResult.cacheStats
|
|
29261
29276
|
};
|
|
29262
29277
|
}
|
|
29263
29278
|
async function saveManifest(configDir, manifest) {
|
|
@@ -29352,7 +29367,7 @@ function blobKey(filePath, contentHash) {
|
|
|
29352
29367
|
return createHash2("sha256").update(`${filePath}:${contentHash}`).digest("hex");
|
|
29353
29368
|
}
|
|
29354
29369
|
function getClaudeDir() {
|
|
29355
|
-
return join6(
|
|
29370
|
+
return join6(homedir3(), ".claude");
|
|
29356
29371
|
}
|
|
29357
29372
|
function extractProjects(manifest) {
|
|
29358
29373
|
const projectMap = new Map;
|
|
@@ -29387,7 +29402,7 @@ async function pushSync(client, masterKey, deviceName, configDir, onProgress, se
|
|
|
29387
29402
|
const conflicts = [];
|
|
29388
29403
|
let bytesTransferred = 0;
|
|
29389
29404
|
const progress = onProgress ?? (() => {});
|
|
29390
|
-
const localManifest = await generateManifest(claudeDir, deviceName, progress, sessionOptions);
|
|
29405
|
+
const { manifest: localManifest, cacheStats } = await generateManifest(claudeDir, deviceName, progress, sessionOptions);
|
|
29391
29406
|
const fileCount = Object.keys(localManifest.files).length;
|
|
29392
29407
|
progress(`Scanned ${fileCount} files`);
|
|
29393
29408
|
progress("Fetching remote manifest...");
|
|
@@ -29481,7 +29496,8 @@ async function pushSync(client, masterKey, deviceName, configDir, onProgress, se
|
|
|
29481
29496
|
bytesTransferred,
|
|
29482
29497
|
durationMs,
|
|
29483
29498
|
errors: errors2,
|
|
29484
|
-
conflicts
|
|
29499
|
+
conflicts,
|
|
29500
|
+
cacheStats
|
|
29485
29501
|
};
|
|
29486
29502
|
}
|
|
29487
29503
|
async function pullSync(client, masterKey, deviceName, configDir, onProgress, sessionOptions) {
|
|
@@ -29628,7 +29644,7 @@ import { execSync } from "child_process";
|
|
|
29628
29644
|
import { platform } from "os";
|
|
29629
29645
|
import { writeFile as writeFile6, unlink } from "fs/promises";
|
|
29630
29646
|
import { join as join7 } from "path";
|
|
29631
|
-
import { homedir as
|
|
29647
|
+
import { homedir as homedir4 } from "os";
|
|
29632
29648
|
var TASK_NAME = "ccsini-heartbeat";
|
|
29633
29649
|
var INTERVAL_MINUTES = 3;
|
|
29634
29650
|
async function installHeartbeatScheduler() {
|
|
@@ -29663,7 +29679,7 @@ async function uninstallWindows() {
|
|
|
29663
29679
|
} catch {}
|
|
29664
29680
|
}
|
|
29665
29681
|
function getLaunchAgentPath() {
|
|
29666
|
-
return join7(
|
|
29682
|
+
return join7(homedir4(), "Library", "LaunchAgents", `com.ccsini.heartbeat.plist`);
|
|
29667
29683
|
}
|
|
29668
29684
|
async function installMacOS() {
|
|
29669
29685
|
const plistPath = getLaunchAgentPath();
|
|
@@ -30002,7 +30018,11 @@ function registerAutoCommands(program2) {
|
|
|
30002
30018
|
};
|
|
30003
30019
|
const result = await pushSync(client, masterKey, config.deviceName, configDir, undefined, sessionOptions, { skipConflictBackup: true });
|
|
30004
30020
|
if (result.filesChanged > 0) {
|
|
30005
|
-
|
|
30021
|
+
let msg = `[ccsini] Pushed ${result.filesChanged} files (${result.durationMs}ms)`;
|
|
30022
|
+
if (result.cacheStats && result.cacheStats.hits > 0) {
|
|
30023
|
+
msg += ` [cache: ${result.cacheStats.hitRate.toFixed(0)}% hits]`;
|
|
30024
|
+
}
|
|
30025
|
+
console.log(msg);
|
|
30006
30026
|
}
|
|
30007
30027
|
if (result.conflicts.length > 0) {
|
|
30008
30028
|
console.log(`[ccsini] \u26A0 ${result.conflicts.length} conflict(s) \u2014 check .conflict files in ~/.claude/`);
|
|
@@ -30422,7 +30442,7 @@ function registerSyncCommands(program2) {
|
|
|
30422
30442
|
const spinner = ora2("Checking status...").start();
|
|
30423
30443
|
const localManifest = await loadManifest(configDir);
|
|
30424
30444
|
const claudeDir = getClaudeDir();
|
|
30425
|
-
const currentManifest = await generateManifest(claudeDir, config.deviceName, (msg) => {
|
|
30445
|
+
const { manifest: currentManifest } = await generateManifest(claudeDir, config.deviceName, (msg) => {
|
|
30426
30446
|
spinner.text = msg;
|
|
30427
30447
|
});
|
|
30428
30448
|
let remoteManifest = null;
|
|
@@ -30604,14 +30624,15 @@ function registerSessionsCommand(program2) {
|
|
|
30604
30624
|
maxPerProject: sessionConfig.maxPerProject,
|
|
30605
30625
|
maxFileSize: SESSION_SYNC_DEFAULTS.maxFileSize
|
|
30606
30626
|
};
|
|
30607
|
-
const
|
|
30608
|
-
const sessionFiles =
|
|
30627
|
+
const withSessionsResult = await scanClaudeDir(claudeDir, undefined, enabledOpts);
|
|
30628
|
+
const sessionFiles = withSessionsResult.files.filter((f) => isSessionFile(f.relativePath));
|
|
30609
30629
|
const disabledOpts = {
|
|
30610
30630
|
enabled: false,
|
|
30611
30631
|
maxPerProject: sessionConfig.maxPerProject,
|
|
30612
30632
|
maxFileSize: SESSION_SYNC_DEFAULTS.maxFileSize
|
|
30613
30633
|
};
|
|
30614
|
-
const
|
|
30634
|
+
const withoutSessionsResult = await scanClaudeDir(claudeDir, undefined, disabledOpts);
|
|
30635
|
+
const withoutSessions = withoutSessionsResult.files;
|
|
30615
30636
|
spinner.stop();
|
|
30616
30637
|
const totalSessionSize = sessionFiles.reduce((sum, f) => sum + f.size, 0);
|
|
30617
30638
|
const projects = new Set(sessionFiles.map((f) => f.relativePath.split("/").slice(0, 2).join("/")));
|