codexuse-cli 3.9.9 → 4.0.0
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 +163 -7
- package/dist/index.js.map +1 -1
- package/dist/server/{NodeSqliteClient-Cx2_VxdP.mjs → NodeSqliteClient-ColmybgR.mjs} +2 -2
- package/dist/server/{SqlError-CoqftVSq.mjs → SqlError-Bsa-lRNq.mjs} +1 -1
- package/dist/server/{SqliteClient-CXjquy8x.mjs → SqliteClient-CFZi0MEE.mjs} +2 -2
- package/dist/server/index.mjs +2241 -1537
- package/dist/server/{open-BWXrZXJl.mjs → open-qeX1IlWK.mjs} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2216,6 +2216,17 @@ var SQLITE_BUSY_MAX_ATTEMPTS = 3;
|
|
|
2216
2216
|
var SQLITE_BUSY_RETRY_DELAY_MS = 100;
|
|
2217
2217
|
var writeQueueByDbPath = /* @__PURE__ */ new Map();
|
|
2218
2218
|
var initializedDbPaths = /* @__PURE__ */ new Set();
|
|
2219
|
+
var AppStorageCorruptionError = class extends Error {
|
|
2220
|
+
constructor(message, options) {
|
|
2221
|
+
super(message);
|
|
2222
|
+
this.name = "AppStorageCorruptionError";
|
|
2223
|
+
this.dbPath = options.dbPath;
|
|
2224
|
+
this.namespace = options.namespace ?? null;
|
|
2225
|
+
if (options.cause !== void 0) {
|
|
2226
|
+
this.cause = options.cause;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
};
|
|
2219
2230
|
function isRecord(value) {
|
|
2220
2231
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2221
2232
|
}
|
|
@@ -2232,6 +2243,23 @@ function safeParseJson(raw) {
|
|
|
2232
2243
|
return null;
|
|
2233
2244
|
}
|
|
2234
2245
|
}
|
|
2246
|
+
function parseJsonStrict(raw, options) {
|
|
2247
|
+
if (typeof raw !== "string" || raw.trim().length === 0) {
|
|
2248
|
+
return null;
|
|
2249
|
+
}
|
|
2250
|
+
try {
|
|
2251
|
+
return JSON.parse(raw);
|
|
2252
|
+
} catch (error) {
|
|
2253
|
+
throw new AppStorageCorruptionError(
|
|
2254
|
+
`App storage document ${options.namespace} contains invalid JSON.`,
|
|
2255
|
+
{
|
|
2256
|
+
dbPath: options.dbPath,
|
|
2257
|
+
namespace: options.namespace,
|
|
2258
|
+
cause: error
|
|
2259
|
+
}
|
|
2260
|
+
);
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2235
2263
|
function sleep(ms) {
|
|
2236
2264
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2237
2265
|
}
|
|
@@ -2240,9 +2268,32 @@ function isSqliteBusyError(error) {
|
|
|
2240
2268
|
return false;
|
|
2241
2269
|
}
|
|
2242
2270
|
const sqliteError = error;
|
|
2243
|
-
|
|
2271
|
+
if (sqliteError.cause && sqliteError.cause !== error && isSqliteBusyError(sqliteError.cause)) {
|
|
2272
|
+
return true;
|
|
2273
|
+
}
|
|
2274
|
+
if (sqliteError.error && sqliteError.error !== error && isSqliteBusyError(sqliteError.error)) {
|
|
2275
|
+
return true;
|
|
2276
|
+
}
|
|
2277
|
+
const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : String(error).toLowerCase();
|
|
2244
2278
|
return sqliteError.code === "SQLITE_BUSY" || sqliteError.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
|
|
2245
2279
|
}
|
|
2280
|
+
function isSqliteCorruptionError(error) {
|
|
2281
|
+
if (!error || typeof error !== "object") {
|
|
2282
|
+
return false;
|
|
2283
|
+
}
|
|
2284
|
+
const sqliteError = error;
|
|
2285
|
+
if (sqliteError.cause && sqliteError.cause !== error && isSqliteCorruptionError(sqliteError.cause)) {
|
|
2286
|
+
return true;
|
|
2287
|
+
}
|
|
2288
|
+
if (sqliteError.error && sqliteError.error !== error && isSqliteCorruptionError(sqliteError.error)) {
|
|
2289
|
+
return true;
|
|
2290
|
+
}
|
|
2291
|
+
const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : "";
|
|
2292
|
+
return sqliteError.code === "SQLITE_CORRUPT" || sqliteError.code === "SQLITE_NOTADB" || sqliteError.errno === 11 || sqliteError.errno === 26 || message.includes("database disk image is malformed") || message.includes("file is not a database") || message.includes("database corruption") || message.includes("sqlite_corrupt") || message.includes("sqlite_notadb");
|
|
2293
|
+
}
|
|
2294
|
+
function isAppStorageCorruptionError(error) {
|
|
2295
|
+
return error instanceof AppStorageCorruptionError || isSqliteCorruptionError(error);
|
|
2296
|
+
}
|
|
2246
2297
|
function beginImmediate(db) {
|
|
2247
2298
|
db.exec("BEGIN IMMEDIATE");
|
|
2248
2299
|
}
|
|
@@ -2317,19 +2368,55 @@ async function openDatabase(dbPath) {
|
|
|
2317
2368
|
close: database.close.bind(database)
|
|
2318
2369
|
};
|
|
2319
2370
|
}
|
|
2371
|
+
function resetAppStorageInitialization(dbPath) {
|
|
2372
|
+
initializedDbPaths.delete(dbPath);
|
|
2373
|
+
}
|
|
2374
|
+
async function backupCorruptAppStorageDb(dbPath) {
|
|
2375
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2376
|
+
const backupPath = `${dbPath}.corrupt-${stamp}`;
|
|
2377
|
+
let moved = false;
|
|
2378
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
2379
|
+
const source = `${dbPath}${suffix}`;
|
|
2380
|
+
const destination = `${backupPath}${suffix}`;
|
|
2381
|
+
try {
|
|
2382
|
+
const stats = await import_node_fs.promises.stat(source);
|
|
2383
|
+
if (!stats.isFile()) {
|
|
2384
|
+
continue;
|
|
2385
|
+
}
|
|
2386
|
+
await import_node_fs.promises.rename(source, destination);
|
|
2387
|
+
moved = true;
|
|
2388
|
+
} catch (error) {
|
|
2389
|
+
if (error.code !== "ENOENT") {
|
|
2390
|
+
throw error;
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
resetAppStorageInitialization(dbPath);
|
|
2395
|
+
return moved ? backupPath : null;
|
|
2396
|
+
}
|
|
2320
2397
|
async function withDatabase(dbPath, task) {
|
|
2321
2398
|
for (let attempt = 1; attempt <= SQLITE_BUSY_MAX_ATTEMPTS; attempt += 1) {
|
|
2322
|
-
|
|
2399
|
+
let db = null;
|
|
2323
2400
|
try {
|
|
2401
|
+
db = await openDatabase(dbPath);
|
|
2324
2402
|
applyConnectionPragmas(db);
|
|
2325
2403
|
ensureSchema(db, dbPath);
|
|
2326
2404
|
return task(db);
|
|
2327
2405
|
} catch (error) {
|
|
2406
|
+
if (error instanceof AppStorageCorruptionError) {
|
|
2407
|
+
throw error;
|
|
2408
|
+
}
|
|
2409
|
+
if (isSqliteCorruptionError(error)) {
|
|
2410
|
+
throw new AppStorageCorruptionError(
|
|
2411
|
+
"App storage database is corrupt.",
|
|
2412
|
+
{ dbPath, cause: error }
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2328
2415
|
if (!isSqliteBusyError(error) || attempt >= SQLITE_BUSY_MAX_ATTEMPTS) {
|
|
2329
2416
|
throw error;
|
|
2330
2417
|
}
|
|
2331
2418
|
} finally {
|
|
2332
|
-
db
|
|
2419
|
+
db?.close();
|
|
2333
2420
|
}
|
|
2334
2421
|
await sleep(SQLITE_BUSY_RETRY_DELAY_MS * attempt);
|
|
2335
2422
|
}
|
|
@@ -2352,6 +2439,40 @@ async function readDocument(dbPath, namespace, normalize) {
|
|
|
2352
2439
|
return normalize(parsed);
|
|
2353
2440
|
});
|
|
2354
2441
|
}
|
|
2442
|
+
async function readDocumentStrict(dbPath, namespace, normalize) {
|
|
2443
|
+
return withDatabase(dbPath, (db) => {
|
|
2444
|
+
const row = useStatement(
|
|
2445
|
+
db,
|
|
2446
|
+
`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
2447
|
+
(statement) => statement.get(namespace)
|
|
2448
|
+
);
|
|
2449
|
+
if (!isRecord(row)) {
|
|
2450
|
+
return null;
|
|
2451
|
+
}
|
|
2452
|
+
const parsed = parseJsonStrict(row.valueJson, {
|
|
2453
|
+
dbPath,
|
|
2454
|
+
namespace
|
|
2455
|
+
});
|
|
2456
|
+
if (parsed === null) {
|
|
2457
|
+
throw new AppStorageCorruptionError(
|
|
2458
|
+
`App storage document ${namespace} is empty.`,
|
|
2459
|
+
{ dbPath, namespace }
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
try {
|
|
2463
|
+
return normalize(parsed);
|
|
2464
|
+
} catch (error) {
|
|
2465
|
+
throw new AppStorageCorruptionError(
|
|
2466
|
+
`App storage document ${namespace} failed normalization.`,
|
|
2467
|
+
{
|
|
2468
|
+
dbPath,
|
|
2469
|
+
namespace,
|
|
2470
|
+
cause: error
|
|
2471
|
+
}
|
|
2472
|
+
);
|
|
2473
|
+
}
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2355
2476
|
async function writeDocument(dbPath, namespace, value) {
|
|
2356
2477
|
return withWriteQueue(
|
|
2357
2478
|
dbPath,
|
|
@@ -3031,7 +3152,7 @@ async function readLegacyAppStateFromDisk() {
|
|
|
3031
3152
|
}
|
|
3032
3153
|
}
|
|
3033
3154
|
async function readAppStateFromStorage() {
|
|
3034
|
-
return
|
|
3155
|
+
return readDocumentStrict(
|
|
3035
3156
|
resolveStorageDbPath(),
|
|
3036
3157
|
APP_STATE_DOCUMENT,
|
|
3037
3158
|
normalizeAppState
|
|
@@ -3044,11 +3165,42 @@ async function writeAppStateToStorage(state) {
|
|
|
3044
3165
|
normalizeAppState(state)
|
|
3045
3166
|
);
|
|
3046
3167
|
}
|
|
3168
|
+
function compactRecoveryMessage(error) {
|
|
3169
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
|
|
3170
|
+
return message.replace(/\s+/g, " ").trim().slice(0, 240) || "unknown corruption";
|
|
3171
|
+
}
|
|
3172
|
+
async function recoverCorruptAppStateStorage(error) {
|
|
3173
|
+
const dbPath = resolveStorageDbPath();
|
|
3174
|
+
if (error instanceof AppStorageCorruptionError && error.namespace === APP_STATE_DOCUMENT) {
|
|
3175
|
+
appStateCache = null;
|
|
3176
|
+
resetAppStorageInitialization(dbPath);
|
|
3177
|
+
const legacyState2 = await readLegacyAppStateFromDisk().catch(() => null);
|
|
3178
|
+
const recovered2 = normalizeAppState(legacyState2 ?? null);
|
|
3179
|
+
recovered2.migration.lastError = `Recovered app-state document after corruption (${compactRecoveryMessage(error)}). Shared storage database preserved.`;
|
|
3180
|
+
return writeAppStateToStorage(recovered2);
|
|
3181
|
+
}
|
|
3182
|
+
const backupPath = await backupCorruptAppStorageDb(dbPath);
|
|
3183
|
+
appStateCache = null;
|
|
3184
|
+
resetAppStorageInitialization(dbPath);
|
|
3185
|
+
const legacyState = await readLegacyAppStateFromDisk().catch(() => null);
|
|
3186
|
+
const recovered = normalizeAppState(legacyState ?? null);
|
|
3187
|
+
recovered.migration.lastError = backupPath ? `Recovered app-state storage after corruption (${compactRecoveryMessage(error)}). Backup: ${import_node_path2.default.basename(backupPath)}` : `Recovered app-state storage after corruption (${compactRecoveryMessage(error)}). No existing DB file was present.`;
|
|
3188
|
+
return writeAppStateToStorage(recovered);
|
|
3189
|
+
}
|
|
3047
3190
|
async function ensureInitialized() {
|
|
3048
3191
|
if (appStateCache) {
|
|
3049
3192
|
return appStateCache;
|
|
3050
3193
|
}
|
|
3051
|
-
|
|
3194
|
+
let loaded = null;
|
|
3195
|
+
try {
|
|
3196
|
+
loaded = await readAppStateFromStorage() ?? await readLegacyAppStateFromDisk();
|
|
3197
|
+
} catch (error) {
|
|
3198
|
+
if (!isAppStorageCorruptionError(error)) {
|
|
3199
|
+
throw error;
|
|
3200
|
+
}
|
|
3201
|
+
appStateCache = await recoverCorruptAppStateStorage(error);
|
|
3202
|
+
return clone2(appStateCache);
|
|
3203
|
+
}
|
|
3052
3204
|
const normalized = loaded ?? normalizeAppState(null);
|
|
3053
3205
|
appStateCache = await writeAppStateToStorage(normalized);
|
|
3054
3206
|
return clone2(appStateCache);
|
|
@@ -3072,7 +3224,11 @@ async function withWriteLock(task) {
|
|
|
3072
3224
|
}
|
|
3073
3225
|
}
|
|
3074
3226
|
async function initializeAppState(userDataDir) {
|
|
3075
|
-
configuredUserDataDir
|
|
3227
|
+
if (configuredUserDataDir !== userDataDir) {
|
|
3228
|
+
configuredUserDataDir = userDataDir;
|
|
3229
|
+
appStateCache = null;
|
|
3230
|
+
resetAppStorageInitialization(resolveStorageDbPath());
|
|
3231
|
+
}
|
|
3076
3232
|
const state = await ensureInitialized();
|
|
3077
3233
|
return clone2(state);
|
|
3078
3234
|
}
|
|
@@ -12549,7 +12705,7 @@ async function ensureCliStorageReady() {
|
|
|
12549
12705
|
}
|
|
12550
12706
|
|
|
12551
12707
|
// src/app/main.ts
|
|
12552
|
-
var VERSION = true ? "
|
|
12708
|
+
var VERSION = true ? "4.0.0" : "0.0.0";
|
|
12553
12709
|
async function runCli() {
|
|
12554
12710
|
const args = process.argv.slice(2);
|
|
12555
12711
|
if (args.length === 0) {
|