crispy-recall 0.2.0 → 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/README.md +25 -2
- package/dist/embed-pending.js +100 -15
- package/dist/recall.js +417 -215
- package/dist/stop-hook.js +4 -1
- package/package.json +2 -2
package/dist/recall.js
CHANGED
|
@@ -2378,11 +2378,11 @@ var require_extract_zip = __commonJS({
|
|
|
2378
2378
|
var { createWriteStream: createWriteStream3, promises: fs5 } = require("fs");
|
|
2379
2379
|
var getStream = require_get_stream();
|
|
2380
2380
|
var path4 = require("path");
|
|
2381
|
-
var { promisify:
|
|
2381
|
+
var { promisify: promisify4 } = require("util");
|
|
2382
2382
|
var stream2 = require("stream");
|
|
2383
2383
|
var yauzl = require_yauzl();
|
|
2384
|
-
var openZip =
|
|
2385
|
-
var pipeline =
|
|
2384
|
+
var openZip = promisify4(yauzl.open);
|
|
2385
|
+
var pipeline = promisify4(stream2.pipeline);
|
|
2386
2386
|
var Extractor = class {
|
|
2387
2387
|
constructor(zipPath, opts) {
|
|
2388
2388
|
this.zipPath = zipPath;
|
|
@@ -2466,7 +2466,7 @@ var require_extract_zip = __commonJS({
|
|
|
2466
2466
|
if (isDir)
|
|
2467
2467
|
return;
|
|
2468
2468
|
debug("opening read stream", dest);
|
|
2469
|
-
const readStream = await
|
|
2469
|
+
const readStream = await promisify4(this.zipfile.openReadStream.bind(this.zipfile))(entry);
|
|
2470
2470
|
if (symlink) {
|
|
2471
2471
|
const link = await getStream(readStream);
|
|
2472
2472
|
debug("creating symlink", link, dest);
|
|
@@ -2584,16 +2584,55 @@ var init_paths = __esm({
|
|
|
2584
2584
|
}
|
|
2585
2585
|
});
|
|
2586
2586
|
|
|
2587
|
+
// src/installer/stable-node.ts
|
|
2588
|
+
function stableNodePath(opts = {}) {
|
|
2589
|
+
const execPath = opts.execPath ?? process.execPath;
|
|
2590
|
+
const platform2 = opts.platform ?? process.platform;
|
|
2591
|
+
if (platform2 !== "darwin")
|
|
2592
|
+
return execPath;
|
|
2593
|
+
const candidates = opts.candidates ?? DEFAULT_CANDIDATES;
|
|
2594
|
+
let realExec;
|
|
2595
|
+
try {
|
|
2596
|
+
realExec = (0, import_node_fs2.realpathSync)(execPath);
|
|
2597
|
+
} catch {
|
|
2598
|
+
return execPath;
|
|
2599
|
+
}
|
|
2600
|
+
for (const candidate of candidates) {
|
|
2601
|
+
try {
|
|
2602
|
+
if ((0, import_node_fs2.existsSync)(candidate) && (0, import_node_fs2.realpathSync)(candidate) === realExec) {
|
|
2603
|
+
return candidate;
|
|
2604
|
+
}
|
|
2605
|
+
} catch {
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
return execPath;
|
|
2609
|
+
}
|
|
2610
|
+
var import_node_fs2, DEFAULT_CANDIDATES;
|
|
2611
|
+
var init_stable_node = __esm({
|
|
2612
|
+
"src/installer/stable-node.ts"() {
|
|
2613
|
+
"use strict";
|
|
2614
|
+
import_node_fs2 = require("node:fs");
|
|
2615
|
+
DEFAULT_CANDIDATES = [
|
|
2616
|
+
"/opt/homebrew/bin/node",
|
|
2617
|
+
// Apple Silicon Homebrew
|
|
2618
|
+
"/opt/homebrew/opt/node/bin/node",
|
|
2619
|
+
"/usr/local/bin/node",
|
|
2620
|
+
// Intel Homebrew
|
|
2621
|
+
"/usr/local/opt/node/bin/node"
|
|
2622
|
+
];
|
|
2623
|
+
}
|
|
2624
|
+
});
|
|
2625
|
+
|
|
2587
2626
|
// src/installer/settings-merge.ts
|
|
2588
2627
|
function writeFileAtomic(path4, contents) {
|
|
2589
2628
|
const tmp = `${path4}.tmp.${process.pid}`;
|
|
2590
2629
|
try {
|
|
2591
|
-
(0,
|
|
2592
|
-
(0,
|
|
2630
|
+
(0, import_node_fs3.writeFileSync)(tmp, contents);
|
|
2631
|
+
(0, import_node_fs3.renameSync)(tmp, path4);
|
|
2593
2632
|
} catch (err) {
|
|
2594
2633
|
try {
|
|
2595
|
-
if ((0,
|
|
2596
|
-
(0,
|
|
2634
|
+
if ((0, import_node_fs3.existsSync)(tmp))
|
|
2635
|
+
(0, import_node_fs3.unlinkSync)(tmp);
|
|
2597
2636
|
} catch {
|
|
2598
2637
|
}
|
|
2599
2638
|
throw err;
|
|
@@ -2604,7 +2643,7 @@ function backupStamp() {
|
|
|
2604
2643
|
}
|
|
2605
2644
|
function backupFile(path4) {
|
|
2606
2645
|
const dest = `${path4}.bak.${backupStamp()}`;
|
|
2607
|
-
(0,
|
|
2646
|
+
(0, import_node_fs3.copyFileSync)(path4, dest);
|
|
2608
2647
|
return dest;
|
|
2609
2648
|
}
|
|
2610
2649
|
function detectLineEnding(raw2) {
|
|
@@ -2653,9 +2692,9 @@ function makeEntry(command) {
|
|
|
2653
2692
|
return { matcher: "", hooks: [{ type: "command", command }] };
|
|
2654
2693
|
}
|
|
2655
2694
|
function mergeStopHook(filePath, hookScriptPath) {
|
|
2656
|
-
const desiredCommand = `"${
|
|
2657
|
-
const exists = (0,
|
|
2658
|
-
const raw2 = exists ? (0,
|
|
2695
|
+
const desiredCommand = `"${stableNodePath()}" "${hookScriptPath}"`;
|
|
2696
|
+
const exists = (0, import_node_fs3.existsSync)(filePath);
|
|
2697
|
+
const raw2 = exists ? (0, import_node_fs3.readFileSync)(filePath, "utf-8") : null;
|
|
2659
2698
|
const obj = raw2 && raw2.trim().length > 0 ? parseTolerant(raw2) : {};
|
|
2660
2699
|
if (!obj.hooks || typeof obj.hooks !== "object")
|
|
2661
2700
|
obj.hooks = {};
|
|
@@ -2681,9 +2720,9 @@ function mergeStopHook(filePath, hookScriptPath) {
|
|
|
2681
2720
|
return backup ? { changed: true, backup } : { changed: true };
|
|
2682
2721
|
}
|
|
2683
2722
|
function removeStopHook(filePath) {
|
|
2684
|
-
if (!(0,
|
|
2723
|
+
if (!(0, import_node_fs3.existsSync)(filePath))
|
|
2685
2724
|
return { changed: false };
|
|
2686
|
-
const raw2 = (0,
|
|
2725
|
+
const raw2 = (0, import_node_fs3.readFileSync)(filePath, "utf-8");
|
|
2687
2726
|
if (raw2.trim().length === 0)
|
|
2688
2727
|
return { changed: false };
|
|
2689
2728
|
const obj = parseTolerant(raw2);
|
|
@@ -2713,11 +2752,12 @@ function removeStopHook(filePath) {
|
|
|
2713
2752
|
writeFileAtomic(filePath, serialize(obj, raw2));
|
|
2714
2753
|
return { changed: true, backup };
|
|
2715
2754
|
}
|
|
2716
|
-
var
|
|
2755
|
+
var import_node_fs3, HOOK_ARRAYS;
|
|
2717
2756
|
var init_settings_merge = __esm({
|
|
2718
2757
|
"src/installer/settings-merge.ts"() {
|
|
2719
2758
|
"use strict";
|
|
2720
|
-
|
|
2759
|
+
import_node_fs3 = require("node:fs");
|
|
2760
|
+
init_stable_node();
|
|
2721
2761
|
HOOK_ARRAYS = ["Stop", "SubagentStop"];
|
|
2722
2762
|
}
|
|
2723
2763
|
});
|
|
@@ -2728,10 +2768,10 @@ function configPath() {
|
|
|
2728
2768
|
}
|
|
2729
2769
|
function readConfig() {
|
|
2730
2770
|
const p = configPath();
|
|
2731
|
-
if (!(0,
|
|
2771
|
+
if (!(0, import_node_fs4.existsSync)(p))
|
|
2732
2772
|
return null;
|
|
2733
2773
|
try {
|
|
2734
|
-
return JSON.parse((0,
|
|
2774
|
+
return JSON.parse((0, import_node_fs4.readFileSync)(p, "utf-8"));
|
|
2735
2775
|
} catch (err) {
|
|
2736
2776
|
log({
|
|
2737
2777
|
source: "installer/config",
|
|
@@ -2743,7 +2783,7 @@ function readConfig() {
|
|
|
2743
2783
|
}
|
|
2744
2784
|
function writeEmbedderConfig(embedder) {
|
|
2745
2785
|
const p = configPath();
|
|
2746
|
-
(0,
|
|
2786
|
+
(0, import_node_fs4.mkdirSync)((0, import_node_path2.dirname)(p), { recursive: true });
|
|
2747
2787
|
const existing = readConfig() ?? {};
|
|
2748
2788
|
const merged = { ...existing, embedder };
|
|
2749
2789
|
writeFileAtomic(p, JSON.stringify(merged, null, 2) + "\n");
|
|
@@ -2760,11 +2800,11 @@ function readEmbedderConfig() {
|
|
|
2760
2800
|
return cfg.embedder;
|
|
2761
2801
|
return { mode: "cpu", ngl: 0, libDir: null, detectedAt: "" };
|
|
2762
2802
|
}
|
|
2763
|
-
var
|
|
2803
|
+
var import_node_fs4, import_node_path2;
|
|
2764
2804
|
var init_config = __esm({
|
|
2765
2805
|
"src/installer/config.ts"() {
|
|
2766
2806
|
"use strict";
|
|
2767
|
-
|
|
2807
|
+
import_node_fs4 = require("node:fs");
|
|
2768
2808
|
import_node_path2 = require("node:path");
|
|
2769
2809
|
init_paths();
|
|
2770
2810
|
init_log();
|
|
@@ -2775,15 +2815,21 @@ var init_config = __esm({
|
|
|
2775
2815
|
// src/recall/embedder.ts
|
|
2776
2816
|
var embedder_exports = {};
|
|
2777
2817
|
__export(embedder_exports, {
|
|
2818
|
+
LLAMA_RELEASE_TAG: () => LLAMA_RELEASE_TAG,
|
|
2819
|
+
MACOS_MIN_VERSION: () => MACOS_MIN_VERSION,
|
|
2820
|
+
buildUnzipInvocations: () => buildUnzipInvocations,
|
|
2778
2821
|
disposeEmbedder: () => disposeEmbedder,
|
|
2779
2822
|
embed: () => embed,
|
|
2780
2823
|
embedBatch: () => embedBatch,
|
|
2781
2824
|
ensureBinary: () => ensureBinary,
|
|
2782
2825
|
ensureModel: () => ensureModel,
|
|
2826
|
+
extractArchive: () => extractArchive,
|
|
2783
2827
|
getBinaryPath: () => getBinaryPath,
|
|
2784
2828
|
getModelPath: () => getModelPath,
|
|
2785
2829
|
hasNvidiaGpu: () => hasNvidiaGpu,
|
|
2786
|
-
initEmbedder: () => initEmbedder
|
|
2830
|
+
initEmbedder: () => initEmbedder,
|
|
2831
|
+
installExtractedBinaries: () => installExtractedBinaries,
|
|
2832
|
+
withTimeout: () => withTimeout
|
|
2787
2833
|
});
|
|
2788
2834
|
function gpuRuntime() {
|
|
2789
2835
|
if (_gpuRuntime === void 0) {
|
|
@@ -2860,8 +2906,8 @@ async function getBinaryAssetCandidates() {
|
|
|
2860
2906
|
async function ensureBinary() {
|
|
2861
2907
|
const binPath = getBinaryPath();
|
|
2862
2908
|
const serverBinPath = getServerBinaryPath();
|
|
2863
|
-
const embeddingExists = (0,
|
|
2864
|
-
const serverNeeded = SERVER_SUPPORTED && !(0,
|
|
2909
|
+
const embeddingExists = (0, import_node_fs5.existsSync)(binPath);
|
|
2910
|
+
const serverNeeded = SERVER_SUPPORTED && !(0, import_node_fs5.existsSync)(serverBinPath);
|
|
2865
2911
|
if (embeddingExists && !serverNeeded) {
|
|
2866
2912
|
binaryPath = binPath;
|
|
2867
2913
|
return binPath;
|
|
@@ -2904,11 +2950,11 @@ async function validateBinary(binPath) {
|
|
|
2904
2950
|
}
|
|
2905
2951
|
}
|
|
2906
2952
|
async function clearBinDir() {
|
|
2907
|
-
if (!(0,
|
|
2953
|
+
if (!(0, import_node_fs5.existsSync)(binDir()))
|
|
2908
2954
|
return;
|
|
2909
2955
|
for (const file of await (0, import_promises.readdir)(binDir())) {
|
|
2910
2956
|
try {
|
|
2911
|
-
(0,
|
|
2957
|
+
(0, import_node_fs5.unlinkSync)((0, import_node_path3.join)(binDir(), file));
|
|
2912
2958
|
} catch {
|
|
2913
2959
|
}
|
|
2914
2960
|
}
|
|
@@ -2957,10 +3003,86 @@ async function performBinaryDownload(binPath) {
|
|
|
2957
3003
|
}
|
|
2958
3004
|
throw new Error("No suitable llama-embedding binary found");
|
|
2959
3005
|
}
|
|
3006
|
+
function withTimeout(promise, ms, label) {
|
|
3007
|
+
let timer;
|
|
3008
|
+
const timeout = new Promise((_3, reject) => {
|
|
3009
|
+
timer = setTimeout(
|
|
3010
|
+
() => reject(new Error(`${label} timed out after ${Math.round(ms / 1e3)}s`)),
|
|
3011
|
+
ms
|
|
3012
|
+
);
|
|
3013
|
+
});
|
|
3014
|
+
promise.catch(() => {
|
|
3015
|
+
});
|
|
3016
|
+
return Promise.race([promise, timeout]).finally(() => {
|
|
3017
|
+
if (timer)
|
|
3018
|
+
clearTimeout(timer);
|
|
3019
|
+
});
|
|
3020
|
+
}
|
|
3021
|
+
function psQuote(p) {
|
|
3022
|
+
return p.replace(/'/g, "''");
|
|
3023
|
+
}
|
|
3024
|
+
function buildUnzipInvocations(plat, archivePath, dir) {
|
|
3025
|
+
if (plat === "win32") {
|
|
3026
|
+
return [{
|
|
3027
|
+
cmd: "powershell",
|
|
3028
|
+
args: [
|
|
3029
|
+
"-NoProfile",
|
|
3030
|
+
"-NonInteractive",
|
|
3031
|
+
"-Command",
|
|
3032
|
+
`Expand-Archive -LiteralPath '${psQuote(archivePath)}' -DestinationPath '${psQuote(dir)}' -Force`
|
|
3033
|
+
]
|
|
3034
|
+
}];
|
|
3035
|
+
}
|
|
3036
|
+
const unzip = { cmd: "unzip", args: ["-o", "-q", archivePath, "-d", dir] };
|
|
3037
|
+
return plat === "darwin" ? [unzip, { cmd: "ditto", args: ["-x", "-k", archivePath, dir] }] : [unzip];
|
|
3038
|
+
}
|
|
3039
|
+
async function osUnzip(archivePath, dir) {
|
|
3040
|
+
(0, import_node_fs5.mkdirSync)(dir, { recursive: true });
|
|
3041
|
+
const invocations = buildUnzipInvocations((0, import_node_os2.platform)(), archivePath, dir);
|
|
3042
|
+
let lastErr;
|
|
3043
|
+
for (const { cmd, args } of invocations) {
|
|
3044
|
+
try {
|
|
3045
|
+
await execFileAsync(cmd, args, { timeout: EXTRACT_TIMEOUT_MS, windowsHide: true });
|
|
3046
|
+
return;
|
|
3047
|
+
} catch (err) {
|
|
3048
|
+
lastErr = err;
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
throw lastErr instanceof Error ? lastErr : new Error(`Native unzip failed for ${archivePath}`);
|
|
3052
|
+
}
|
|
3053
|
+
async function extractArchive(archivePath, baseDir, assetName, timeoutMs = EXTRACT_TIMEOUT_MS) {
|
|
3054
|
+
try {
|
|
3055
|
+
await withTimeout((0, import_extract_zip.default)(archivePath, { dir: baseDir }), timeoutMs, `Extracting ${assetName}`);
|
|
3056
|
+
return baseDir;
|
|
3057
|
+
} catch (err) {
|
|
3058
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3059
|
+
log({
|
|
3060
|
+
source: "recall-catchup",
|
|
3061
|
+
level: "warn",
|
|
3062
|
+
summary: `Bundled unzip failed for ${assetName} (${msg}); falling back to system unzip`
|
|
3063
|
+
});
|
|
3064
|
+
const fallbackDir = (0, import_node_path3.join)(baseDir, "__os_unzip__");
|
|
3065
|
+
await osUnzip(archivePath, fallbackDir);
|
|
3066
|
+
return fallbackDir;
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
async function installExtractedBinaries(extractedDir, destDir = binDir()) {
|
|
3070
|
+
const buildBinDir = (0, import_node_path3.join)(extractedDir, "build", "bin");
|
|
3071
|
+
const sourceDir = (0, import_node_fs5.existsSync)(buildBinDir) ? buildBinDir : extractedDir;
|
|
3072
|
+
(0, import_node_fs5.mkdirSync)(destDir, { recursive: true });
|
|
3073
|
+
let copiedCount = 0;
|
|
3074
|
+
for (const file of await (0, import_promises.readdir)(sourceDir)) {
|
|
3075
|
+
if (!isWantedFile(file))
|
|
3076
|
+
continue;
|
|
3077
|
+
await (0, import_promises.cp)((0, import_node_path3.join)(sourceDir, file), (0, import_node_path3.join)(destDir, file), { force: true });
|
|
3078
|
+
copiedCount++;
|
|
3079
|
+
}
|
|
3080
|
+
return copiedCount;
|
|
3081
|
+
}
|
|
2960
3082
|
async function downloadAndExtract(assetName, binPath) {
|
|
2961
3083
|
const url = `https://github.com/ggml-org/llama.cpp/releases/download/${LLAMA_RELEASE_TAG}/${assetName}`;
|
|
2962
3084
|
const isGpu = assetName.includes("cuda") || assetName.includes("vulkan");
|
|
2963
|
-
(0,
|
|
3085
|
+
(0, import_node_fs5.mkdirSync)(binDir(), { recursive: true });
|
|
2964
3086
|
const archivePath = (0, import_node_path3.join)(binDir(), assetName);
|
|
2965
3087
|
const tmpPath = archivePath + ".tmp";
|
|
2966
3088
|
log({
|
|
@@ -2970,56 +3092,46 @@ async function downloadAndExtract(assetName, binPath) {
|
|
|
2970
3092
|
data: { url, dest: binPath }
|
|
2971
3093
|
});
|
|
2972
3094
|
try {
|
|
2973
|
-
if ((0,
|
|
2974
|
-
(0,
|
|
3095
|
+
if ((0, import_node_fs5.existsSync)(tmpPath))
|
|
3096
|
+
(0, import_node_fs5.unlinkSync)(tmpPath);
|
|
2975
3097
|
await downloadFile(url, tmpPath);
|
|
2976
|
-
(0,
|
|
3098
|
+
(0, import_node_fs5.renameSync)(tmpPath, archivePath);
|
|
2977
3099
|
const tmpExtractDir = (0, import_node_path3.join)((0, import_node_os2.tmpdir)(), `llama-extract-${Date.now()}`);
|
|
2978
|
-
(0,
|
|
3100
|
+
(0, import_node_fs5.mkdirSync)(tmpExtractDir, { recursive: true });
|
|
2979
3101
|
try {
|
|
2980
|
-
await (
|
|
2981
|
-
const
|
|
2982
|
-
const sourceDir = (0, import_node_fs4.existsSync)(buildBinDir) ? buildBinDir : tmpExtractDir;
|
|
2983
|
-
let copiedCount = 0;
|
|
2984
|
-
for (const file of await (0, import_promises.readdir)(sourceDir)) {
|
|
2985
|
-
if (!isWantedFile(file))
|
|
2986
|
-
continue;
|
|
2987
|
-
const src = (0, import_node_path3.join)(sourceDir, file);
|
|
2988
|
-
const dest = (0, import_node_path3.join)(binDir(), file);
|
|
2989
|
-
await (0, import_promises.cp)(src, dest, { force: true });
|
|
2990
|
-
copiedCount++;
|
|
2991
|
-
}
|
|
3102
|
+
const extractedDir = await extractArchive(archivePath, tmpExtractDir, assetName);
|
|
3103
|
+
const copiedCount = await installExtractedBinaries(extractedDir);
|
|
2992
3104
|
if (copiedCount === 0) {
|
|
2993
3105
|
throw new Error(`No binaries found in archive ${assetName}`);
|
|
2994
3106
|
}
|
|
2995
3107
|
} finally {
|
|
2996
3108
|
try {
|
|
2997
|
-
(0,
|
|
3109
|
+
(0, import_node_fs5.rmSync)(tmpExtractDir, { recursive: true, force: true });
|
|
2998
3110
|
} catch {
|
|
2999
3111
|
}
|
|
3000
3112
|
}
|
|
3001
|
-
if ((0,
|
|
3113
|
+
if ((0, import_node_fs5.existsSync)(archivePath)) {
|
|
3002
3114
|
try {
|
|
3003
|
-
(0,
|
|
3115
|
+
(0, import_node_fs5.unlinkSync)(archivePath);
|
|
3004
3116
|
} catch {
|
|
3005
3117
|
}
|
|
3006
3118
|
}
|
|
3007
3119
|
if ((0, import_node_os2.platform)() !== "win32") {
|
|
3008
|
-
if ((0,
|
|
3009
|
-
(0,
|
|
3120
|
+
if ((0, import_node_fs5.existsSync)(binPath))
|
|
3121
|
+
(0, import_node_fs5.chmodSync)(binPath, 493);
|
|
3010
3122
|
const serverBin = getServerBinaryPath();
|
|
3011
|
-
if ((0,
|
|
3012
|
-
(0,
|
|
3123
|
+
if ((0, import_node_fs5.existsSync)(serverBin)) {
|
|
3124
|
+
(0, import_node_fs5.chmodSync)(serverBin, 493);
|
|
3013
3125
|
}
|
|
3014
3126
|
}
|
|
3015
|
-
if (!(0,
|
|
3127
|
+
if (!(0, import_node_fs5.existsSync)(binPath)) {
|
|
3016
3128
|
throw new Error(`${BIN_NAME} not found after extracting ${assetName}`);
|
|
3017
3129
|
}
|
|
3018
3130
|
} catch (err) {
|
|
3019
3131
|
for (const p of [tmpPath, archivePath]) {
|
|
3020
|
-
if ((0,
|
|
3132
|
+
if ((0, import_node_fs5.existsSync)(p)) {
|
|
3021
3133
|
try {
|
|
3022
|
-
(0,
|
|
3134
|
+
(0, import_node_fs5.unlinkSync)(p);
|
|
3023
3135
|
} catch {
|
|
3024
3136
|
}
|
|
3025
3137
|
}
|
|
@@ -3032,8 +3144,8 @@ function getModelPath() {
|
|
|
3032
3144
|
}
|
|
3033
3145
|
async function ensureModel() {
|
|
3034
3146
|
const modelPath = getModelPath();
|
|
3035
|
-
if ((0,
|
|
3036
|
-
const stat = (0,
|
|
3147
|
+
if ((0, import_node_fs5.existsSync)(modelPath)) {
|
|
3148
|
+
const stat = (0, import_node_fs5.statSync)(modelPath);
|
|
3037
3149
|
if (stat.size > 1e8)
|
|
3038
3150
|
return modelPath;
|
|
3039
3151
|
}
|
|
@@ -3049,9 +3161,9 @@ async function ensureModel() {
|
|
|
3049
3161
|
async function performModelDownload(modelPath) {
|
|
3050
3162
|
const tmpPath = modelPath + ".tmp";
|
|
3051
3163
|
try {
|
|
3052
|
-
(0,
|
|
3053
|
-
if ((0,
|
|
3054
|
-
(0,
|
|
3164
|
+
(0, import_node_fs5.mkdirSync)(modelsDir(), { recursive: true });
|
|
3165
|
+
if ((0, import_node_fs5.existsSync)(tmpPath)) {
|
|
3166
|
+
(0, import_node_fs5.unlinkSync)(tmpPath);
|
|
3055
3167
|
}
|
|
3056
3168
|
log({
|
|
3057
3169
|
source: "recall-catchup",
|
|
@@ -3060,7 +3172,7 @@ async function performModelDownload(modelPath) {
|
|
|
3060
3172
|
data: { url: MODEL_URL, dest: modelPath }
|
|
3061
3173
|
});
|
|
3062
3174
|
await downloadFile(MODEL_URL, tmpPath);
|
|
3063
|
-
(0,
|
|
3175
|
+
(0, import_node_fs5.renameSync)(tmpPath, modelPath);
|
|
3064
3176
|
log({
|
|
3065
3177
|
source: "recall-catchup",
|
|
3066
3178
|
level: "info",
|
|
@@ -3068,9 +3180,9 @@ async function performModelDownload(modelPath) {
|
|
|
3068
3180
|
});
|
|
3069
3181
|
return modelPath;
|
|
3070
3182
|
} catch (err) {
|
|
3071
|
-
if ((0,
|
|
3183
|
+
if ((0, import_node_fs5.existsSync)(tmpPath)) {
|
|
3072
3184
|
try {
|
|
3073
|
-
(0,
|
|
3185
|
+
(0, import_node_fs5.unlinkSync)(tmpPath);
|
|
3074
3186
|
} catch {
|
|
3075
3187
|
}
|
|
3076
3188
|
}
|
|
@@ -3088,7 +3200,7 @@ async function downloadFile(url, destPath) {
|
|
|
3088
3200
|
}
|
|
3089
3201
|
};
|
|
3090
3202
|
import("node:https").then(({ default: https }) => {
|
|
3091
|
-
const file = (0,
|
|
3203
|
+
const file = (0, import_node_fs5.createWriteStream)(destPath);
|
|
3092
3204
|
const pipeResponse = (response) => {
|
|
3093
3205
|
if (response.statusCode !== 200) {
|
|
3094
3206
|
cleanup();
|
|
@@ -3158,7 +3270,7 @@ function getPidFilePath() {
|
|
|
3158
3270
|
return (0, import_node_path3.join)(runDir(), `llama-embed-${process.pid}.pid`);
|
|
3159
3271
|
}
|
|
3160
3272
|
function writePidFile(pid, socketPath) {
|
|
3161
|
-
(0,
|
|
3273
|
+
(0, import_node_fs5.writeFileSync)(getPidFilePath(), JSON.stringify({
|
|
3162
3274
|
pid,
|
|
3163
3275
|
socketPath,
|
|
3164
3276
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3168,20 +3280,20 @@ function writePidFile(pid, socketPath) {
|
|
|
3168
3280
|
function cleanupPidAndSocket() {
|
|
3169
3281
|
for (const f3 of [getPidFilePath(), getSocketPath()]) {
|
|
3170
3282
|
try {
|
|
3171
|
-
(0,
|
|
3283
|
+
(0, import_node_fs5.unlinkSync)(f3);
|
|
3172
3284
|
} catch {
|
|
3173
3285
|
}
|
|
3174
3286
|
}
|
|
3175
3287
|
}
|
|
3176
3288
|
function cleanupStalePidFiles() {
|
|
3177
|
-
if (!(0,
|
|
3289
|
+
if (!(0, import_node_fs5.existsSync)(runDir()))
|
|
3178
3290
|
return;
|
|
3179
3291
|
try {
|
|
3180
|
-
const files = (0,
|
|
3292
|
+
const files = (0, import_node_fs5.readdirSync)(runDir()).filter((f3) => f3.startsWith("llama-embed-") && f3.endsWith(".pid"));
|
|
3181
3293
|
for (const f3 of files) {
|
|
3182
3294
|
const pidFile = (0, import_node_path3.join)(runDir(), f3);
|
|
3183
3295
|
try {
|
|
3184
|
-
const data = JSON.parse((0,
|
|
3296
|
+
const data = JSON.parse((0, import_node_fs5.readFileSync)(pidFile, "utf-8"));
|
|
3185
3297
|
const ownerPid = data.ownerPid ?? data.pid;
|
|
3186
3298
|
if (!isProcessAlive(ownerPid)) {
|
|
3187
3299
|
if (data.pid && isProcessAlive(data.pid)) {
|
|
@@ -3191,19 +3303,19 @@ function cleanupStalePidFiles() {
|
|
|
3191
3303
|
}
|
|
3192
3304
|
}
|
|
3193
3305
|
try {
|
|
3194
|
-
(0,
|
|
3306
|
+
(0, import_node_fs5.unlinkSync)(pidFile);
|
|
3195
3307
|
} catch {
|
|
3196
3308
|
}
|
|
3197
3309
|
if (data.socketPath) {
|
|
3198
3310
|
try {
|
|
3199
|
-
(0,
|
|
3311
|
+
(0, import_node_fs5.unlinkSync)(data.socketPath);
|
|
3200
3312
|
} catch {
|
|
3201
3313
|
}
|
|
3202
3314
|
}
|
|
3203
3315
|
}
|
|
3204
3316
|
} catch {
|
|
3205
3317
|
try {
|
|
3206
|
-
(0,
|
|
3318
|
+
(0, import_node_fs5.unlinkSync)(pidFile);
|
|
3207
3319
|
} catch {
|
|
3208
3320
|
}
|
|
3209
3321
|
}
|
|
@@ -3242,14 +3354,14 @@ async function waitForHealth(socketPath, child) {
|
|
|
3242
3354
|
async function startServer() {
|
|
3243
3355
|
const modelPath = await ensureModel();
|
|
3244
3356
|
const serverBin = getServerBinaryPath();
|
|
3245
|
-
if (!(0,
|
|
3357
|
+
if (!(0, import_node_fs5.existsSync)(serverBin)) {
|
|
3246
3358
|
throw new Error("llama-server binary not available");
|
|
3247
3359
|
}
|
|
3248
|
-
(0,
|
|
3360
|
+
(0, import_node_fs5.mkdirSync)(runDir(), { recursive: true });
|
|
3249
3361
|
const socket = getSocketPath();
|
|
3250
|
-
if ((0,
|
|
3362
|
+
if ((0, import_node_fs5.existsSync)(socket)) {
|
|
3251
3363
|
try {
|
|
3252
|
-
(0,
|
|
3364
|
+
(0, import_node_fs5.unlinkSync)(socket);
|
|
3253
3365
|
} catch {
|
|
3254
3366
|
}
|
|
3255
3367
|
}
|
|
@@ -3612,12 +3724,12 @@ async function embedBatchInner(texts) {
|
|
|
3612
3724
|
async function disposeEmbedder() {
|
|
3613
3725
|
await killServer();
|
|
3614
3726
|
}
|
|
3615
|
-
var import_node_child_process,
|
|
3727
|
+
var import_node_child_process, import_node_fs5, import_promises, import_node_http, import_node_path3, import_node_os2, import_node_util, import_extract_zip, execFileAsync, _gpuRuntime, MODEL_FILENAME, MODEL_URL, EXPECTED_DIMS, BATCH_SEPARATOR, MAX_ARG_BYTES, LLAMA_RELEASE_TAG, MACOS_MIN_VERSION, BIN_NAME, SERVER_BIN_NAME, SERVER_SUPPORTED, SERVER_THRESHOLD, IDLE_TIMEOUT_MS, HEALTH_POLL_INTERVAL_MS, HEALTH_POLL_TIMEOUT_MS, HTTP_REQUEST_TIMEOUT_MS, SERVER_KILL_TIMEOUT_MS, SERVER_COOLDOWN_MS, EXTRACT_TIMEOUT_MS, embedQueue, embedRunning, binaryPath, downloadPromise, binaryDownloadPromise, serverProcess, activeSocketPath, idleTimer, serverStartPromise, serverCooldownUntil, serverRetryPromise, activeServerRequests, WANTED_FILES, WANTED_LIB_PATTERNS;
|
|
3616
3728
|
var init_embedder = __esm({
|
|
3617
3729
|
"src/recall/embedder.ts"() {
|
|
3618
3730
|
"use strict";
|
|
3619
3731
|
import_node_child_process = require("node:child_process");
|
|
3620
|
-
|
|
3732
|
+
import_node_fs5 = require("node:fs");
|
|
3621
3733
|
import_promises = require("node:fs/promises");
|
|
3622
3734
|
import_node_http = require("node:http");
|
|
3623
3735
|
import_node_path3 = require("node:path");
|
|
@@ -3634,6 +3746,7 @@ var init_embedder = __esm({
|
|
|
3634
3746
|
BATCH_SEPARATOR = "<#sep#>";
|
|
3635
3747
|
MAX_ARG_BYTES = (0, import_node_os2.platform)() === "win32" ? 0 : 1e5;
|
|
3636
3748
|
LLAMA_RELEASE_TAG = "b5300";
|
|
3749
|
+
MACOS_MIN_VERSION = { arm64: "14.0", x64: "13.7" };
|
|
3637
3750
|
BIN_NAME = (0, import_node_os2.platform)() === "win32" ? "llama-embedding.exe" : "llama-embedding";
|
|
3638
3751
|
SERVER_BIN_NAME = (0, import_node_os2.platform)() === "win32" ? "llama-server.exe" : "llama-server";
|
|
3639
3752
|
SERVER_SUPPORTED = (0, import_node_os2.platform)() !== "win32";
|
|
@@ -3644,6 +3757,7 @@ var init_embedder = __esm({
|
|
|
3644
3757
|
HTTP_REQUEST_TIMEOUT_MS = 12e4;
|
|
3645
3758
|
SERVER_KILL_TIMEOUT_MS = 5e3;
|
|
3646
3759
|
SERVER_COOLDOWN_MS = 6e4;
|
|
3760
|
+
EXTRACT_TIMEOUT_MS = 12e4;
|
|
3647
3761
|
embedQueue = [];
|
|
3648
3762
|
embedRunning = false;
|
|
3649
3763
|
binaryPath = null;
|
|
@@ -4127,9 +4241,9 @@ var require_backup = __commonJS({
|
|
|
4127
4241
|
"use strict";
|
|
4128
4242
|
var fs5 = require("fs");
|
|
4129
4243
|
var path4 = require("path");
|
|
4130
|
-
var { promisify:
|
|
4244
|
+
var { promisify: promisify4 } = require("util");
|
|
4131
4245
|
var { cppdb } = require_util();
|
|
4132
|
-
var fsAccess =
|
|
4246
|
+
var fsAccess = promisify4(fs5.access);
|
|
4133
4247
|
module2.exports = async function backup(filename, options) {
|
|
4134
4248
|
if (options == null)
|
|
4135
4249
|
options = {};
|
|
@@ -4591,7 +4705,7 @@ function getDb(dbPath2) {
|
|
|
4591
4705
|
if (db) {
|
|
4592
4706
|
closeDb();
|
|
4593
4707
|
}
|
|
4594
|
-
(0,
|
|
4708
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path4.dirname)(dbPath2), { recursive: true });
|
|
4595
4709
|
cleanupWasmArtifacts(dbPath2);
|
|
4596
4710
|
const raw2 = openDatabase(dbPath2);
|
|
4597
4711
|
try {
|
|
@@ -4628,13 +4742,13 @@ function openDatabase(dbPath2) {
|
|
|
4628
4742
|
}
|
|
4629
4743
|
function resolveNativeBinding() {
|
|
4630
4744
|
const sibling = (0, import_node_path4.join)(__dirname, "better_sqlite3.node");
|
|
4631
|
-
if ((0,
|
|
4745
|
+
if ((0, import_node_fs6.existsSync)(sibling))
|
|
4632
4746
|
return sibling;
|
|
4633
4747
|
const resolved = resolveInstalledBinding();
|
|
4634
4748
|
if (resolved)
|
|
4635
4749
|
return resolved;
|
|
4636
4750
|
const staged = (0, import_node_path4.join)(binDir(), "better_sqlite3.node");
|
|
4637
|
-
if ((0,
|
|
4751
|
+
if ((0, import_node_fs6.existsSync)(staged))
|
|
4638
4752
|
return staged;
|
|
4639
4753
|
return null;
|
|
4640
4754
|
}
|
|
@@ -4652,7 +4766,7 @@ function findNativeBinding(baseDir) {
|
|
|
4652
4766
|
(0, import_node_path4.join)(baseDir, "build", "Debug", "better_sqlite3.node")
|
|
4653
4767
|
]) {
|
|
4654
4768
|
try {
|
|
4655
|
-
if ((0,
|
|
4769
|
+
if ((0, import_node_fs6.statSync)(c).isFile())
|
|
4656
4770
|
return c;
|
|
4657
4771
|
} catch {
|
|
4658
4772
|
}
|
|
@@ -4662,7 +4776,7 @@ function findNativeBinding(baseDir) {
|
|
|
4662
4776
|
const dir = stack.pop();
|
|
4663
4777
|
let entries;
|
|
4664
4778
|
try {
|
|
4665
|
-
entries = (0,
|
|
4779
|
+
entries = (0, import_node_fs6.readdirSync)(dir, { withFileTypes: true });
|
|
4666
4780
|
} catch {
|
|
4667
4781
|
continue;
|
|
4668
4782
|
}
|
|
@@ -4710,12 +4824,12 @@ function configurePragmas(raw2, dbPath2) {
|
|
|
4710
4824
|
}
|
|
4711
4825
|
function cleanupWasmArtifacts(dbPath2) {
|
|
4712
4826
|
try {
|
|
4713
|
-
(0,
|
|
4827
|
+
(0, import_node_fs6.rmSync)(`${dbPath2}.lock`, { recursive: true, force: true });
|
|
4714
4828
|
} catch {
|
|
4715
4829
|
}
|
|
4716
4830
|
try {
|
|
4717
|
-
if ((0,
|
|
4718
|
-
(0,
|
|
4831
|
+
if ((0, import_node_fs6.existsSync)(`${dbPath2}.owner`))
|
|
4832
|
+
(0, import_node_fs6.unlinkSync)(`${dbPath2}.owner`);
|
|
4719
4833
|
} catch {
|
|
4720
4834
|
}
|
|
4721
4835
|
}
|
|
@@ -4803,11 +4917,11 @@ function ensureSchema(db4) {
|
|
|
4803
4917
|
CREATE INDEX IF NOT EXISTS idx_watermark_vendor ON ingest_watermark(vendor);
|
|
4804
4918
|
`);
|
|
4805
4919
|
}
|
|
4806
|
-
var
|
|
4920
|
+
var import_node_fs6, import_node_path4, import_node_module, import_better_sqlite3, BindingLoadError, db, currentDbPath;
|
|
4807
4921
|
var init_db = __esm({
|
|
4808
4922
|
"src/db.ts"() {
|
|
4809
4923
|
"use strict";
|
|
4810
|
-
|
|
4924
|
+
import_node_fs6 = require("node:fs");
|
|
4811
4925
|
import_node_path4 = require("node:path");
|
|
4812
4926
|
import_node_module = require("node:module");
|
|
4813
4927
|
init_log();
|
|
@@ -4817,7 +4931,10 @@ var init_db = __esm({
|
|
|
4817
4931
|
constructor(dbPath2, cause) {
|
|
4818
4932
|
super(
|
|
4819
4933
|
`recall: failed to load the better-sqlite3 native binding while opening ${dbPath2}: ${cause.message}
|
|
4820
|
-
The binding is ABI-locked to the Node it was built for
|
|
4934
|
+
The native SQLite binding is ABI-locked to the Node it was built for. This is usually one of:
|
|
4935
|
+
\u2022 recall is running under a different Node than the one npm installed it with (e.g. Homebrew node vs nvm) \u2014 reinstall with \`npm install -g crispy-recall\` using the node on your PATH, then \`recall install\`.
|
|
4936
|
+
\u2022 no prebuilt binary matched your Node version and it could not compile \u2014 use Node 22 LTS or 24+ (Node 23 has no prebuilt SQLite binding), and on macOS make sure Xcode Command Line Tools are installed (\`xcode-select --install\`).
|
|
4937
|
+
Run \`recall doctor\` for details.`
|
|
4821
4938
|
);
|
|
4822
4939
|
this.dbPath = dbPath2;
|
|
4823
4940
|
this.cause = cause;
|
|
@@ -9465,7 +9582,7 @@ var init_esm3 = __esm({
|
|
|
9465
9582
|
});
|
|
9466
9583
|
|
|
9467
9584
|
// node_modules/path-scurry/dist/esm/index.js
|
|
9468
|
-
var import_node_path5, import_node_url, import_fs, actualFS, import_promises2,
|
|
9585
|
+
var import_node_path5, import_node_url, import_fs, actualFS, import_promises2, realpathSync2, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
|
|
9469
9586
|
var init_esm4 = __esm({
|
|
9470
9587
|
"node_modules/path-scurry/dist/esm/index.js"() {
|
|
9471
9588
|
init_esm2();
|
|
@@ -9475,13 +9592,13 @@ var init_esm4 = __esm({
|
|
|
9475
9592
|
actualFS = __toESM(require("node:fs"), 1);
|
|
9476
9593
|
import_promises2 = require("node:fs/promises");
|
|
9477
9594
|
init_esm3();
|
|
9478
|
-
|
|
9595
|
+
realpathSync2 = import_fs.realpathSync.native;
|
|
9479
9596
|
defaultFS = {
|
|
9480
9597
|
lstatSync: import_fs.lstatSync,
|
|
9481
9598
|
readdir: import_fs.readdir,
|
|
9482
9599
|
readdirSync: import_fs.readdirSync,
|
|
9483
9600
|
readlinkSync: import_fs.readlinkSync,
|
|
9484
|
-
realpathSync,
|
|
9601
|
+
realpathSync: realpathSync2,
|
|
9485
9602
|
promises: {
|
|
9486
9603
|
lstat: import_promises2.lstat,
|
|
9487
9604
|
readdir: import_promises2.readdir,
|
|
@@ -13319,7 +13436,7 @@ async function mtimeScan(opts) {
|
|
|
13319
13436
|
result.scanned++;
|
|
13320
13437
|
let stat;
|
|
13321
13438
|
try {
|
|
13322
|
-
stat = (0,
|
|
13439
|
+
stat = (0, import_node_fs7.statSync)(file);
|
|
13323
13440
|
} catch {
|
|
13324
13441
|
continue;
|
|
13325
13442
|
}
|
|
@@ -13363,12 +13480,12 @@ function sessionIdFromPath(file, vendor) {
|
|
|
13363
13480
|
const m2 = base.match(/^rollout-.+-([0-9a-f-]{36})$/i);
|
|
13364
13481
|
return m2 ? m2[1] : base;
|
|
13365
13482
|
}
|
|
13366
|
-
var
|
|
13483
|
+
var import_node_fs7, import_node_os3, import_node_path6;
|
|
13367
13484
|
var init_mtime_scan = __esm({
|
|
13368
13485
|
"src/recall/mtime-scan.ts"() {
|
|
13369
13486
|
"use strict";
|
|
13370
13487
|
init_esm5();
|
|
13371
|
-
|
|
13488
|
+
import_node_fs7 = require("node:fs");
|
|
13372
13489
|
import_node_os3 = require("node:os");
|
|
13373
13490
|
import_node_path6 = require("node:path");
|
|
13374
13491
|
init_db();
|
|
@@ -14155,21 +14272,21 @@ function isAlive(pid) {
|
|
|
14155
14272
|
function tryAcquireEmbedLock() {
|
|
14156
14273
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
14157
14274
|
try {
|
|
14158
|
-
(0,
|
|
14275
|
+
(0, import_node_fs8.writeFileSync)(LOCK_PATH, String(process.pid), { flag: "wx" });
|
|
14159
14276
|
return true;
|
|
14160
14277
|
} catch {
|
|
14161
14278
|
let heldPid;
|
|
14162
14279
|
let ageMs;
|
|
14163
14280
|
try {
|
|
14164
|
-
heldPid = parseInt((0,
|
|
14165
|
-
ageMs = Date.now() - (0,
|
|
14281
|
+
heldPid = parseInt((0, import_node_fs8.readFileSync)(LOCK_PATH, "utf8"), 10);
|
|
14282
|
+
ageMs = Date.now() - (0, import_node_fs8.statSync)(LOCK_PATH).mtimeMs;
|
|
14166
14283
|
} catch {
|
|
14167
14284
|
continue;
|
|
14168
14285
|
}
|
|
14169
14286
|
if (isAlive(heldPid) && ageMs < STALE_MS)
|
|
14170
14287
|
return false;
|
|
14171
14288
|
try {
|
|
14172
|
-
(0,
|
|
14289
|
+
(0, import_node_fs8.unlinkSync)(LOCK_PATH);
|
|
14173
14290
|
} catch {
|
|
14174
14291
|
}
|
|
14175
14292
|
}
|
|
@@ -14178,17 +14295,17 @@ function tryAcquireEmbedLock() {
|
|
|
14178
14295
|
}
|
|
14179
14296
|
function releaseEmbedLock() {
|
|
14180
14297
|
try {
|
|
14181
|
-
const held = parseInt((0,
|
|
14298
|
+
const held = parseInt((0, import_node_fs8.readFileSync)(LOCK_PATH, "utf8"), 10);
|
|
14182
14299
|
if (held === process.pid)
|
|
14183
|
-
(0,
|
|
14300
|
+
(0, import_node_fs8.unlinkSync)(LOCK_PATH);
|
|
14184
14301
|
} catch {
|
|
14185
14302
|
}
|
|
14186
14303
|
}
|
|
14187
|
-
var
|
|
14304
|
+
var import_node_fs8, import_node_path8, LOCK_PATH, STALE_MS;
|
|
14188
14305
|
var init_embed_lock = __esm({
|
|
14189
14306
|
"src/recall/embed-lock.ts"() {
|
|
14190
14307
|
"use strict";
|
|
14191
|
-
|
|
14308
|
+
import_node_fs8 = require("node:fs");
|
|
14192
14309
|
import_node_path8 = require("node:path");
|
|
14193
14310
|
init_paths();
|
|
14194
14311
|
LOCK_PATH = (0, import_node_path8.join)(runDir(), "embed.lock");
|
|
@@ -14244,7 +14361,7 @@ function clearCancelFlag() {
|
|
|
14244
14361
|
function startLockHeartbeat(lockPath) {
|
|
14245
14362
|
const t = setInterval(() => {
|
|
14246
14363
|
try {
|
|
14247
|
-
(0,
|
|
14364
|
+
(0, import_node_fs9.utimesSync)(lockPath, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date());
|
|
14248
14365
|
} catch {
|
|
14249
14366
|
}
|
|
14250
14367
|
}, 5 * 60 * 1e3);
|
|
@@ -14264,7 +14381,7 @@ async function runFts5Catchup(opts) {
|
|
|
14264
14381
|
continue;
|
|
14265
14382
|
if (alreadyIndexed.has(s.sessionId))
|
|
14266
14383
|
continue;
|
|
14267
|
-
if (!(0,
|
|
14384
|
+
if (!(0, import_node_fs9.existsSync)(s.path))
|
|
14268
14385
|
continue;
|
|
14269
14386
|
try {
|
|
14270
14387
|
const result = await ingestSessionMessages(s.sessionId, s.path, s.vendor);
|
|
@@ -14457,11 +14574,11 @@ async function startRecallCatchup(opts = {}) {
|
|
|
14457
14574
|
running = false;
|
|
14458
14575
|
}
|
|
14459
14576
|
}
|
|
14460
|
-
var
|
|
14577
|
+
var import_node_fs9, import_node_os5, SILENT_EMBED_THRESHOLD, FREE_MEM_FLOOR_MB, SECONDS_PER_MESSAGE, CATCHUP_BATCH_SIZE, MAX_CONSECUTIVE_FAILURES, status, cancelRequested, running;
|
|
14461
14578
|
var init_catchup = __esm({
|
|
14462
14579
|
"src/recall/catchup.ts"() {
|
|
14463
14580
|
"use strict";
|
|
14464
|
-
|
|
14581
|
+
import_node_fs9 = require("node:fs");
|
|
14465
14582
|
import_node_os5 = require("node:os");
|
|
14466
14583
|
init_dist2();
|
|
14467
14584
|
init_session_manager_shim();
|
|
@@ -14495,7 +14612,7 @@ function cudaAssetUrl() {
|
|
|
14495
14612
|
let version = "";
|
|
14496
14613
|
try {
|
|
14497
14614
|
const pkgPath = (0, import_node_path9.join)(__dirname, "..", "package.json");
|
|
14498
|
-
const pkg = JSON.parse((0,
|
|
14615
|
+
const pkg = JSON.parse((0, import_node_fs10.readFileSync)(pkgPath, "utf8"));
|
|
14499
14616
|
version = typeof pkg.version === "string" ? pkg.version : "";
|
|
14500
14617
|
const repoUrl = typeof pkg.repository === "string" ? pkg.repository : pkg.repository?.url;
|
|
14501
14618
|
const m2 = repoUrl?.match(/github\.com[/:]([^/]+)\/([^/.]+)/);
|
|
@@ -14541,7 +14658,7 @@ async function detectGpu(opts = {}) {
|
|
|
14541
14658
|
if (p === "win32" && a3 === "x64") {
|
|
14542
14659
|
return { ...base, cudaAvailable: "prebuilt", plannedMode: "gpu" };
|
|
14543
14660
|
}
|
|
14544
|
-
if (p === "linux" && a3 === "x64" && (0,
|
|
14661
|
+
if (p === "linux" && a3 === "x64" && (0, import_node_fs10.existsSync)(cudaBackendLib())) {
|
|
14545
14662
|
return { ...base, cudaAvailable: "reuse-existing", plannedMode: "gpu" };
|
|
14546
14663
|
}
|
|
14547
14664
|
if (p === "linux" && a3 === "x64") {
|
|
@@ -14676,16 +14793,16 @@ async function runGpuPhase(opts = {}) {
|
|
|
14676
14793
|
async function defaultStage(args) {
|
|
14677
14794
|
const target = binDir();
|
|
14678
14795
|
const libPath = cudaBackendLib();
|
|
14679
|
-
if ((0,
|
|
14796
|
+
if ((0, import_node_fs10.existsSync)(libPath))
|
|
14680
14797
|
return target;
|
|
14681
14798
|
if (args.offline)
|
|
14682
14799
|
return null;
|
|
14683
14800
|
try {
|
|
14684
|
-
(0,
|
|
14801
|
+
(0, import_node_fs10.mkdirSync)(target, { recursive: true });
|
|
14685
14802
|
const zipPath = (0, import_node_path9.join)((0, import_node_os6.tmpdir)(), CUDA_ASSET_NAME);
|
|
14686
14803
|
await downloadFile2(CUDA_ASSET_URL, zipPath);
|
|
14687
14804
|
await (0, import_extract_zip2.default)(zipPath, { dir: target });
|
|
14688
|
-
return (0,
|
|
14805
|
+
return (0, import_node_fs10.existsSync)(libPath) ? target : null;
|
|
14689
14806
|
} catch (err) {
|
|
14690
14807
|
log({ source: "installer/gpu", level: "info", summary: `prebuilt CUDA staging failed: ${err.message}` });
|
|
14691
14808
|
return null;
|
|
@@ -14708,7 +14825,7 @@ function downloadFile2(url, destPath) {
|
|
|
14708
14825
|
done(new Error(`HTTP ${status2}`));
|
|
14709
14826
|
return;
|
|
14710
14827
|
}
|
|
14711
|
-
const file = (0,
|
|
14828
|
+
const file = (0, import_node_fs10.createWriteStream)(destPath);
|
|
14712
14829
|
res.pipe(file);
|
|
14713
14830
|
file.on("finish", () => file.close(() => done()));
|
|
14714
14831
|
file.on("error", done);
|
|
@@ -14716,12 +14833,12 @@ function downloadFile2(url, destPath) {
|
|
|
14716
14833
|
(0, import_node_https.get)(url, { headers: { "User-Agent": "recall" } }, pipeTo).on("error", done);
|
|
14717
14834
|
});
|
|
14718
14835
|
}
|
|
14719
|
-
var import_node_child_process3,
|
|
14836
|
+
var import_node_child_process3, import_node_fs10, import_node_path9, import_node_util2, import_node_os6, import_node_https, import_extract_zip2, execFileAsync2, EXPECTED_DIMS2, OFFLOAD_TIMEOUT_MS, DEFAULT_NGL, CUDA_ASSET_NAME, CUDA_ASSET_URL, STAGE_DOWNLOAD_TIMEOUT_MS;
|
|
14720
14837
|
var init_gpu = __esm({
|
|
14721
14838
|
"src/installer/gpu.ts"() {
|
|
14722
14839
|
"use strict";
|
|
14723
14840
|
import_node_child_process3 = require("node:child_process");
|
|
14724
|
-
|
|
14841
|
+
import_node_fs10 = require("node:fs");
|
|
14725
14842
|
import_node_path9 = require("node:path");
|
|
14726
14843
|
import_node_util2 = require("node:util");
|
|
14727
14844
|
import_node_os6 = require("node:os");
|
|
@@ -14776,7 +14893,7 @@ function installLockPath() {
|
|
|
14776
14893
|
}
|
|
14777
14894
|
function readLockBody() {
|
|
14778
14895
|
try {
|
|
14779
|
-
return JSON.parse((0,
|
|
14896
|
+
return JSON.parse((0, import_node_fs11.readFileSync)(installLockPath(), "utf-8"));
|
|
14780
14897
|
} catch {
|
|
14781
14898
|
return null;
|
|
14782
14899
|
}
|
|
@@ -14790,17 +14907,17 @@ function pidAlive(pid) {
|
|
|
14790
14907
|
}
|
|
14791
14908
|
}
|
|
14792
14909
|
function acquireInstallLock() {
|
|
14793
|
-
(0,
|
|
14910
|
+
(0, import_node_fs11.mkdirSync)(runDir(), { recursive: true });
|
|
14794
14911
|
const body = JSON.stringify({ pid: process.pid, ts: Date.now() });
|
|
14795
14912
|
try {
|
|
14796
|
-
(0,
|
|
14913
|
+
(0, import_node_fs11.writeFileSync)(installLockPath(), body, { flag: "wx" });
|
|
14797
14914
|
return { ok: true, tookOver: false };
|
|
14798
14915
|
} catch {
|
|
14799
14916
|
const existing = readLockBody();
|
|
14800
14917
|
if (existing && pidAlive(existing.pid) && Date.now() - existing.ts < STALE_LOCK_MS) {
|
|
14801
14918
|
return { ok: false, tookOver: false, existingPid: existing.pid };
|
|
14802
14919
|
}
|
|
14803
|
-
(0,
|
|
14920
|
+
(0, import_node_fs11.writeFileSync)(installLockPath(), body);
|
|
14804
14921
|
return { ok: true, tookOver: true, ...existing ? { existingPid: existing.pid } : {} };
|
|
14805
14922
|
}
|
|
14806
14923
|
}
|
|
@@ -14808,7 +14925,7 @@ function releaseInstallLock() {
|
|
|
14808
14925
|
try {
|
|
14809
14926
|
const existing = readLockBody();
|
|
14810
14927
|
if (existing && existing.pid === process.pid) {
|
|
14811
|
-
(0,
|
|
14928
|
+
(0, import_node_fs11.unlinkSync)(installLockPath());
|
|
14812
14929
|
}
|
|
14813
14930
|
} catch {
|
|
14814
14931
|
}
|
|
@@ -14817,14 +14934,14 @@ function detectWsl() {
|
|
|
14817
14934
|
if (process.env["WSL_DISTRO_NAME"])
|
|
14818
14935
|
return true;
|
|
14819
14936
|
try {
|
|
14820
|
-
return /microsoft/i.test((0,
|
|
14937
|
+
return /microsoft/i.test((0, import_node_fs11.readFileSync)("/proc/version", "utf-8"));
|
|
14821
14938
|
} catch {
|
|
14822
14939
|
return false;
|
|
14823
14940
|
}
|
|
14824
14941
|
}
|
|
14825
14942
|
function canWrite(path4) {
|
|
14826
14943
|
try {
|
|
14827
|
-
(0,
|
|
14944
|
+
(0, import_node_fs11.accessSync)(path4, import_node_fs11.constants.W_OK);
|
|
14828
14945
|
return true;
|
|
14829
14946
|
} catch {
|
|
14830
14947
|
return false;
|
|
@@ -14844,7 +14961,7 @@ function checkPlatform(report, opts) {
|
|
|
14844
14961
|
remediation: "recall supports Linux x64/arm64, macOS x64/arm64, Windows x64."
|
|
14845
14962
|
});
|
|
14846
14963
|
}
|
|
14847
|
-
if (isWsl && (0,
|
|
14964
|
+
if (isWsl && (0, import_node_fs11.existsSync)((0, import_node_path10.join)((0, import_node_os7.homedir)(), ".claude")) && process.env["CLAUDE_CONFIG_DIR"] === void 0) {
|
|
14848
14965
|
report.warnings.push({
|
|
14849
14966
|
check: "platform.wsl",
|
|
14850
14967
|
severity: "WARN",
|
|
@@ -14852,6 +14969,51 @@ function checkPlatform(report, opts) {
|
|
|
14852
14969
|
});
|
|
14853
14970
|
}
|
|
14854
14971
|
}
|
|
14972
|
+
async function readMacosProductVersion() {
|
|
14973
|
+
try {
|
|
14974
|
+
const { stdout } = await execFileAsync3("sw_vers", ["-productVersion"], { timeout: 5e3, windowsHide: true });
|
|
14975
|
+
const v2 = stdout.trim();
|
|
14976
|
+
return v2.length > 0 ? v2 : null;
|
|
14977
|
+
} catch {
|
|
14978
|
+
return null;
|
|
14979
|
+
}
|
|
14980
|
+
}
|
|
14981
|
+
function compareMajorMinor(a3, b3) {
|
|
14982
|
+
const pa = a3.split(".").map((n) => parseInt(n, 10) || 0);
|
|
14983
|
+
const pb = b3.split(".").map((n) => parseInt(n, 10) || 0);
|
|
14984
|
+
for (let i = 0; i < 2; i++) {
|
|
14985
|
+
const da = pa[i] ?? 0;
|
|
14986
|
+
const db4 = pb[i] ?? 0;
|
|
14987
|
+
if (da !== db4)
|
|
14988
|
+
return da - db4;
|
|
14989
|
+
}
|
|
14990
|
+
return 0;
|
|
14991
|
+
}
|
|
14992
|
+
async function checkMacosFloor(report, opts) {
|
|
14993
|
+
const os3 = opts.platform ?? (0, import_node_os7.platform)();
|
|
14994
|
+
if (os3 !== "darwin")
|
|
14995
|
+
return;
|
|
14996
|
+
const a3 = opts.arch ?? (0, import_node_os7.arch)();
|
|
14997
|
+
const { MACOS_MIN_VERSION: MACOS_MIN_VERSION2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
14998
|
+
const floor = a3 === "arm64" ? MACOS_MIN_VERSION2.arm64 : MACOS_MIN_VERSION2.x64;
|
|
14999
|
+
const version = opts.macosProductVersion ? await opts.macosProductVersion() : await readMacosProductVersion();
|
|
15000
|
+
if (!version) {
|
|
15001
|
+
report.warnings.push({
|
|
15002
|
+
check: "platform.macos-version",
|
|
15003
|
+
severity: "WARN",
|
|
15004
|
+
message: "Could not determine the macOS version (sw_vers unavailable) \u2014 skipping the minimum-OS check for the bundled llama.cpp binaries."
|
|
15005
|
+
});
|
|
15006
|
+
return;
|
|
15007
|
+
}
|
|
15008
|
+
if (compareMajorMinor(version, floor) < 0) {
|
|
15009
|
+
report.failures.push({
|
|
15010
|
+
check: "platform.macos-version",
|
|
15011
|
+
severity: "FAIL",
|
|
15012
|
+
message: `macOS ${version} is below the minimum for recall's bundled llama.cpp binaries (needs ${MACOS_MIN_VERSION2.arm64}+ on Apple Silicon, ${MACOS_MIN_VERSION2.x64}+ on Intel). Semantic embedding cannot run.`,
|
|
15013
|
+
remediation: `Upgrade macOS to ${floor} or newer to install recall.`
|
|
15014
|
+
});
|
|
15015
|
+
}
|
|
15016
|
+
}
|
|
14855
15017
|
function checkClaude(report) {
|
|
14856
15018
|
const dir = claudeDir();
|
|
14857
15019
|
const settings = claudeSettingsPath();
|
|
@@ -14861,7 +15023,7 @@ function checkClaude(report) {
|
|
|
14861
15023
|
let ok = true;
|
|
14862
15024
|
let status2 = "ready";
|
|
14863
15025
|
let existingHooks = 0;
|
|
14864
|
-
if (!(0,
|
|
15026
|
+
if (!(0, import_node_fs11.existsSync)(dir)) {
|
|
14865
15027
|
ok = false;
|
|
14866
15028
|
status2 = "missing";
|
|
14867
15029
|
report.failures.push({
|
|
@@ -14870,12 +15032,12 @@ function checkClaude(report) {
|
|
|
14870
15032
|
message: `~/.claude not found at ${dir}`,
|
|
14871
15033
|
remediation: "Install Claude Code first, or set CLAUDE_CONFIG_DIR."
|
|
14872
15034
|
});
|
|
14873
|
-
report.claude = { ok, status: status2, paths, existingHooks, existingInstall: (0,
|
|
15035
|
+
report.claude = { ok, status: status2, paths, existingHooks, existingInstall: (0, import_node_fs11.existsSync)(recallRoot()) };
|
|
14874
15036
|
return;
|
|
14875
15037
|
}
|
|
14876
|
-
if ((0,
|
|
15038
|
+
if ((0, import_node_fs11.existsSync)(settings)) {
|
|
14877
15039
|
try {
|
|
14878
|
-
const parsed = JSON.parse((0,
|
|
15040
|
+
const parsed = JSON.parse((0, import_node_fs11.readFileSync)(settings, "utf-8"));
|
|
14879
15041
|
const stop = parsed?.hooks?.Stop;
|
|
14880
15042
|
const subStop = parsed?.hooks?.SubagentStop;
|
|
14881
15043
|
existingHooks = (Array.isArray(stop) ? stop.length : 0) + (Array.isArray(subStop) ? subStop.length : 0);
|
|
@@ -14889,17 +15051,17 @@ function checkClaude(report) {
|
|
|
14889
15051
|
status2 = "fresh";
|
|
14890
15052
|
report.warnings.push({ check: "claude.settings", severity: "WARN", message: "No settings.json \u2014 will create one." });
|
|
14891
15053
|
}
|
|
14892
|
-
if (!(0,
|
|
15054
|
+
if (!(0, import_node_fs11.existsSync)(skills)) {
|
|
14893
15055
|
report.warnings.push({ check: "claude.skills", severity: "WARN", message: "skills/ absent \u2014 will create it." });
|
|
14894
15056
|
}
|
|
14895
|
-
if ((0,
|
|
15057
|
+
if ((0, import_node_fs11.existsSync)(skillFile)) {
|
|
14896
15058
|
report.warnings.push({ check: "claude.recall-skill", severity: "WARN", message: "recall skill present \u2014 will back up + overwrite." });
|
|
14897
15059
|
}
|
|
14898
|
-
report.claude = { ok, status: status2, paths, existingHooks, existingInstall: (0,
|
|
15060
|
+
report.claude = { ok, status: status2, paths, existingHooks, existingInstall: (0, import_node_fs11.existsSync)(recallRoot()) };
|
|
14899
15061
|
}
|
|
14900
15062
|
function checkCodex(report) {
|
|
14901
15063
|
const dir = codexDir();
|
|
14902
|
-
if (!(0,
|
|
15064
|
+
if (!(0, import_node_fs11.existsSync)(dir)) {
|
|
14903
15065
|
report.codex = null;
|
|
14904
15066
|
return;
|
|
14905
15067
|
}
|
|
@@ -14910,8 +15072,8 @@ function checkCodex(report) {
|
|
|
14910
15072
|
}
|
|
14911
15073
|
function checkDisk() {
|
|
14912
15074
|
try {
|
|
14913
|
-
const base = (0,
|
|
14914
|
-
const st = (0,
|
|
15075
|
+
const base = (0, import_node_fs11.existsSync)(recallRoot()) ? recallRoot() : (0, import_node_os7.homedir)();
|
|
15076
|
+
const st = (0, import_node_fs11.statfsSync)(base);
|
|
14915
15077
|
const freeBytes = Number(st.bavail) * Number(st.bsize);
|
|
14916
15078
|
const freeMb = Math.floor(freeBytes / (1024 * 1024));
|
|
14917
15079
|
const disk = `${freeMb} MB free`;
|
|
@@ -14955,8 +15117,8 @@ function httpReachable(url, timeoutMs) {
|
|
|
14955
15117
|
async function checkNetwork(offline) {
|
|
14956
15118
|
if (offline) {
|
|
14957
15119
|
const { getBinaryPath: getBinaryPath2, getModelPath: getModelPath2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
14958
|
-
const haveBin = (0,
|
|
14959
|
-
const haveModel = (0,
|
|
15120
|
+
const haveBin = (0, import_node_fs11.existsSync)(getBinaryPath2());
|
|
15121
|
+
const haveModel = (0, import_node_fs11.existsSync)(getModelPath2());
|
|
14960
15122
|
if (haveBin && haveModel)
|
|
14961
15123
|
return { network: "offline (pre-staged binary + model present)" };
|
|
14962
15124
|
if (haveBin || haveModel)
|
|
@@ -14981,6 +15143,7 @@ async function runPreflight(opts = {}) {
|
|
|
14981
15143
|
failures: []
|
|
14982
15144
|
};
|
|
14983
15145
|
checkPlatform(report, opts);
|
|
15146
|
+
await checkMacosFloor(report, opts);
|
|
14984
15147
|
checkClaude(report);
|
|
14985
15148
|
checkCodex(report);
|
|
14986
15149
|
const node = checkNode();
|
|
@@ -15012,16 +15175,19 @@ async function runPreflight(opts = {}) {
|
|
|
15012
15175
|
function preflightPassed(report) {
|
|
15013
15176
|
return report.failures.length === 0;
|
|
15014
15177
|
}
|
|
15015
|
-
var
|
|
15178
|
+
var import_node_fs11, import_node_os7, import_node_path10, import_node_https2, import_node_child_process4, import_node_util3, execFileAsync3, STALE_LOCK_MS;
|
|
15016
15179
|
var init_preflight = __esm({
|
|
15017
15180
|
"src/installer/preflight.ts"() {
|
|
15018
15181
|
"use strict";
|
|
15019
|
-
|
|
15182
|
+
import_node_fs11 = require("node:fs");
|
|
15020
15183
|
import_node_os7 = require("node:os");
|
|
15021
15184
|
import_node_path10 = require("node:path");
|
|
15022
15185
|
import_node_https2 = require("node:https");
|
|
15186
|
+
import_node_child_process4 = require("node:child_process");
|
|
15187
|
+
import_node_util3 = require("node:util");
|
|
15023
15188
|
init_paths();
|
|
15024
15189
|
init_gpu();
|
|
15190
|
+
execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process4.execFile);
|
|
15025
15191
|
STALE_LOCK_MS = 60 * 60 * 1e3;
|
|
15026
15192
|
}
|
|
15027
15193
|
});
|
|
@@ -15130,7 +15296,7 @@ var init_manifest = __esm({
|
|
|
15130
15296
|
function openReadonly(dbFile) {
|
|
15131
15297
|
const staged = (0, import_node_path11.join)(binDir(), "better_sqlite3.node");
|
|
15132
15298
|
try {
|
|
15133
|
-
return (0,
|
|
15299
|
+
return (0, import_node_fs12.existsSync)(staged) ? new import_better_sqlite32.default(dbFile, { readonly: true, fileMustExist: true, nativeBinding: staged }) : new import_better_sqlite32.default(dbFile, { readonly: true, fileMustExist: true });
|
|
15134
15300
|
} catch {
|
|
15135
15301
|
try {
|
|
15136
15302
|
return new import_better_sqlite32.default(dbFile, { readonly: true, fileMustExist: true });
|
|
@@ -15141,10 +15307,10 @@ function openReadonly(dbFile) {
|
|
|
15141
15307
|
}
|
|
15142
15308
|
function classifyUpgrade() {
|
|
15143
15309
|
const dbFile = dbPath();
|
|
15144
|
-
if (!(0,
|
|
15310
|
+
if (!(0, import_node_fs12.existsSync)(dbFile)) {
|
|
15145
15311
|
return { state: "fresh", journalMode: null, markerPresent: false, coverage: 1 };
|
|
15146
15312
|
}
|
|
15147
|
-
const markerPresent = (0,
|
|
15313
|
+
const markerPresent = (0, import_node_fs12.existsSync)((0, import_node_path11.join)(binDir(), ".binding-info.json"));
|
|
15148
15314
|
let journalMode = null;
|
|
15149
15315
|
let coverage = 1;
|
|
15150
15316
|
const raw2 = openReadonly(dbFile);
|
|
@@ -15176,14 +15342,14 @@ function classifyUpgrade() {
|
|
|
15176
15342
|
}
|
|
15177
15343
|
function snapshotDb() {
|
|
15178
15344
|
const dbFile = dbPath();
|
|
15179
|
-
if (!(0,
|
|
15345
|
+
if (!(0, import_node_fs12.existsSync)(dbFile))
|
|
15180
15346
|
return null;
|
|
15181
15347
|
const dest = `${dbFile}.pre-upgrade-${backupStamp()}`;
|
|
15182
15348
|
try {
|
|
15183
|
-
(0,
|
|
15349
|
+
(0, import_node_fs12.copyFileSync)(dbFile, dest);
|
|
15184
15350
|
const journal = `${dbFile}-journal`;
|
|
15185
|
-
if ((0,
|
|
15186
|
-
(0,
|
|
15351
|
+
if ((0, import_node_fs12.existsSync)(journal))
|
|
15352
|
+
(0, import_node_fs12.copyFileSync)(journal, `${dest}-journal`);
|
|
15187
15353
|
return dest;
|
|
15188
15354
|
} catch (e2) {
|
|
15189
15355
|
log({ source: "installer/upgrade", level: "warn", summary: `pre-upgrade snapshot failed: ${e2.message}` });
|
|
@@ -15223,10 +15389,10 @@ function handleIntegrity() {
|
|
|
15223
15389
|
}
|
|
15224
15390
|
function backfillAlreadyRunning() {
|
|
15225
15391
|
const pidFile = (0, import_node_path11.join)(runDir(), "backfill.pid");
|
|
15226
|
-
if (!(0,
|
|
15392
|
+
if (!(0, import_node_fs12.existsSync)(pidFile))
|
|
15227
15393
|
return false;
|
|
15228
15394
|
try {
|
|
15229
|
-
const pid = parseInt((0,
|
|
15395
|
+
const pid = parseInt((0, import_node_fs12.readFileSync)(pidFile, "utf-8").trim(), 10);
|
|
15230
15396
|
if (Number.isNaN(pid))
|
|
15231
15397
|
return false;
|
|
15232
15398
|
process.kill(pid, 0);
|
|
@@ -15241,11 +15407,11 @@ function migrationReportLine(coverage) {
|
|
|
15241
15407
|
const pct = Math.round(coverage * 100);
|
|
15242
15408
|
return `Embed migration: re-embedding in background (${pct}% at v${EMBED_VERSION}) \u2014 semantic search stays available`;
|
|
15243
15409
|
}
|
|
15244
|
-
var
|
|
15410
|
+
var import_node_fs12, import_node_path11, import_better_sqlite32;
|
|
15245
15411
|
var init_upgrade_migrate = __esm({
|
|
15246
15412
|
"src/installer/upgrade-migrate.ts"() {
|
|
15247
15413
|
"use strict";
|
|
15248
|
-
|
|
15414
|
+
import_node_fs12 = require("node:fs");
|
|
15249
15415
|
import_node_path11 = require("node:path");
|
|
15250
15416
|
import_better_sqlite32 = __toESM(require_lib());
|
|
15251
15417
|
init_db();
|
|
@@ -15258,8 +15424,8 @@ var init_upgrade_migrate = __esm({
|
|
|
15258
15424
|
|
|
15259
15425
|
// src/installer/claudemd-nudge.ts
|
|
15260
15426
|
function applyNudge(filePath) {
|
|
15261
|
-
const exists = (0,
|
|
15262
|
-
const raw2 = exists ? (0,
|
|
15427
|
+
const exists = (0, import_node_fs13.existsSync)(filePath);
|
|
15428
|
+
const raw2 = exists ? (0, import_node_fs13.readFileSync)(filePath, "utf-8") : "";
|
|
15263
15429
|
if (RECALL_HEADING.test(raw2))
|
|
15264
15430
|
return { changed: false };
|
|
15265
15431
|
const ending = raw2.includes("\r\n") ? "\r\n" : "\n";
|
|
@@ -15273,9 +15439,9 @@ function applyNudge(filePath) {
|
|
|
15273
15439
|
return backup ? { changed: true, backup } : { changed: true };
|
|
15274
15440
|
}
|
|
15275
15441
|
function removeNudge(filePath) {
|
|
15276
|
-
if (!(0,
|
|
15442
|
+
if (!(0, import_node_fs13.existsSync)(filePath))
|
|
15277
15443
|
return { changed: false };
|
|
15278
|
-
const raw2 = (0,
|
|
15444
|
+
const raw2 = (0, import_node_fs13.readFileSync)(filePath, "utf-8");
|
|
15279
15445
|
if (!RECALL_HEADING.test(raw2))
|
|
15280
15446
|
return { changed: false };
|
|
15281
15447
|
const ending = raw2.includes("\r\n") ? "\r\n" : "\n";
|
|
@@ -15303,11 +15469,11 @@ function removeNudge(filePath) {
|
|
|
15303
15469
|
writeFileAtomic(filePath, next);
|
|
15304
15470
|
return { changed: true, backup };
|
|
15305
15471
|
}
|
|
15306
|
-
var
|
|
15472
|
+
var import_node_fs13, RECALL_BLOCK, RECALL_HEADING;
|
|
15307
15473
|
var init_claudemd_nudge = __esm({
|
|
15308
15474
|
"src/installer/claudemd-nudge.ts"() {
|
|
15309
15475
|
"use strict";
|
|
15310
|
-
|
|
15476
|
+
import_node_fs13 = require("node:fs");
|
|
15311
15477
|
init_settings_merge();
|
|
15312
15478
|
RECALL_BLOCK = [
|
|
15313
15479
|
"",
|
|
@@ -15325,13 +15491,14 @@ var init_claudemd_nudge = __esm({
|
|
|
15325
15491
|
var install_exports = {};
|
|
15326
15492
|
__export(install_exports, {
|
|
15327
15493
|
defaultDistDir: () => defaultDistDir,
|
|
15494
|
+
probeStagedBinding: () => probeStagedBinding,
|
|
15328
15495
|
runInstall: () => runInstall
|
|
15329
15496
|
});
|
|
15330
15497
|
function defaultDistDir() {
|
|
15331
15498
|
const argv1 = process.argv[1];
|
|
15332
15499
|
if (argv1) {
|
|
15333
15500
|
try {
|
|
15334
|
-
return (0, import_node_path12.dirname)((0,
|
|
15501
|
+
return (0, import_node_path12.dirname)((0, import_node_fs14.realpathSync)(argv1));
|
|
15335
15502
|
} catch {
|
|
15336
15503
|
return (0, import_node_path12.dirname)(argv1);
|
|
15337
15504
|
}
|
|
@@ -15339,7 +15506,7 @@ function defaultDistDir() {
|
|
|
15339
15506
|
return __dirname;
|
|
15340
15507
|
}
|
|
15341
15508
|
function resolveTemplatePath(explicit) {
|
|
15342
|
-
if (explicit && (0,
|
|
15509
|
+
if (explicit && (0, import_node_fs14.existsSync)(explicit))
|
|
15343
15510
|
return explicit;
|
|
15344
15511
|
const here = __dirname;
|
|
15345
15512
|
const candidates = [
|
|
@@ -15351,44 +15518,44 @@ function resolveTemplatePath(explicit) {
|
|
|
15351
15518
|
// source: src/installer/
|
|
15352
15519
|
];
|
|
15353
15520
|
for (const c of candidates)
|
|
15354
|
-
if ((0,
|
|
15521
|
+
if ((0, import_node_fs14.existsSync)(c))
|
|
15355
15522
|
return c;
|
|
15356
15523
|
return candidates[candidates.length - 1];
|
|
15357
15524
|
}
|
|
15358
15525
|
function recallBinCommand() {
|
|
15359
|
-
return `"${
|
|
15526
|
+
return `"${stableNodePath()}" "${(0, import_node_path12.join)(binDir(), "recall.js")}"`;
|
|
15360
15527
|
}
|
|
15361
15528
|
function writeSkill(targetPath, templatePath, runnable) {
|
|
15362
|
-
const template = (0,
|
|
15529
|
+
const template = (0, import_node_fs14.readFileSync)(templatePath, "utf-8");
|
|
15363
15530
|
const body = template.replaceAll("$RECALL_BIN", runnable);
|
|
15364
|
-
(0,
|
|
15365
|
-
if ((0,
|
|
15366
|
-
if ((0,
|
|
15531
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path12.dirname)(targetPath), { recursive: true });
|
|
15532
|
+
if ((0, import_node_fs14.existsSync)(targetPath)) {
|
|
15533
|
+
if ((0, import_node_fs14.readFileSync)(targetPath, "utf-8") === body)
|
|
15367
15534
|
return false;
|
|
15368
15535
|
backupFile(targetPath);
|
|
15369
15536
|
}
|
|
15370
|
-
(0,
|
|
15537
|
+
(0, import_node_fs14.writeFileSync)(targetPath, body);
|
|
15371
15538
|
return true;
|
|
15372
15539
|
}
|
|
15373
15540
|
function stageBundles(distDir, written) {
|
|
15374
|
-
(0,
|
|
15541
|
+
(0, import_node_fs14.mkdirSync)(binDir(), { recursive: true });
|
|
15375
15542
|
for (const name of STAGED_BUNDLES) {
|
|
15376
15543
|
const src = (0, import_node_path12.join)(distDir, name);
|
|
15377
|
-
if (!(0,
|
|
15544
|
+
if (!(0, import_node_fs14.existsSync)(src)) {
|
|
15378
15545
|
log({ source: "installer/install", level: "warn", summary: `bundle ${name} not found in ${distDir} \u2014 skipping stage` });
|
|
15379
15546
|
continue;
|
|
15380
15547
|
}
|
|
15381
15548
|
const dest = (0, import_node_path12.join)(binDir(), name);
|
|
15382
|
-
(0,
|
|
15549
|
+
(0, import_node_fs14.copyFileSync)(src, dest);
|
|
15383
15550
|
written.push(dest);
|
|
15384
15551
|
}
|
|
15385
|
-
stageNativeBinding(written);
|
|
15552
|
+
return stageNativeBinding(written);
|
|
15386
15553
|
}
|
|
15387
15554
|
function stageNativeBinding(written) {
|
|
15388
15555
|
const staleWasm = (0, import_node_path12.join)(binDir(), "node-sqlite3-wasm.wasm");
|
|
15389
|
-
if ((0,
|
|
15556
|
+
if ((0, import_node_fs14.existsSync)(staleWasm)) {
|
|
15390
15557
|
try {
|
|
15391
|
-
(0,
|
|
15558
|
+
(0, import_node_fs14.unlinkSync)(staleWasm);
|
|
15392
15559
|
} catch {
|
|
15393
15560
|
}
|
|
15394
15561
|
}
|
|
@@ -15399,26 +15566,45 @@ function stageNativeBinding(written) {
|
|
|
15399
15566
|
level: "warn",
|
|
15400
15567
|
summary: "better_sqlite3.node not found in node_modules \u2014 the CLI/hooks will fail to load SQLite until reinstalled"
|
|
15401
15568
|
});
|
|
15402
|
-
return;
|
|
15569
|
+
return { ok: true };
|
|
15403
15570
|
}
|
|
15404
15571
|
const dest = (0, import_node_path12.join)(binDir(), "better_sqlite3.node");
|
|
15405
|
-
(0,
|
|
15572
|
+
(0, import_node_fs14.copyFileSync)(binding, dest);
|
|
15406
15573
|
written.push(dest);
|
|
15574
|
+
const probe = probeStagedBinding(dest);
|
|
15575
|
+
if (!probe.ok) {
|
|
15576
|
+
const remediation = isBindingLoadError({ message: probe.message }) ? `The SQLite binding npm installed was built for a different Node than the one running recall (${process.execPath}, ${process.version}). This usually means \`npm install -g\` ran under a different Node (e.g. Homebrew vs nvm). Re-run \`npm install -g crispy-recall\` using the same node that is on your PATH, then \`recall install\`. (${probe.message})` : `The staged SQLite binding could not be loaded (${probe.message}). Re-run \`npm install -g crispy-recall\` with the node that is on your PATH, then \`recall install\`.`;
|
|
15577
|
+
return { ok: false, remediation };
|
|
15578
|
+
}
|
|
15407
15579
|
const markerPath = (0, import_node_path12.join)(binDir(), ".binding-info.json");
|
|
15408
|
-
(0,
|
|
15580
|
+
(0, import_node_fs14.writeFileSync)(
|
|
15409
15581
|
markerPath,
|
|
15410
15582
|
JSON.stringify(
|
|
15411
15583
|
{
|
|
15412
15584
|
platform: process.platform,
|
|
15413
15585
|
arch: process.arch,
|
|
15414
15586
|
nodeModuleVersion: process.versions.modules,
|
|
15415
|
-
|
|
15587
|
+
// Upgrade-stable public path, not the Cellar path brew upgrade deletes;
|
|
15588
|
+
// doctor's pinnedNodeOk checks existsSync(nodePath), which this satisfies.
|
|
15589
|
+
nodePath: stableNodePath()
|
|
15416
15590
|
},
|
|
15417
15591
|
null,
|
|
15418
15592
|
2
|
|
15419
15593
|
)
|
|
15420
15594
|
);
|
|
15421
15595
|
written.push(markerPath);
|
|
15596
|
+
return { ok: true };
|
|
15597
|
+
}
|
|
15598
|
+
function probeStagedBinding(dest) {
|
|
15599
|
+
const res = (0, import_node_child_process5.spawnSync)(process.execPath, ["-e", "require(process.argv[1])", dest], {
|
|
15600
|
+
encoding: "utf-8",
|
|
15601
|
+
timeout: 2e4,
|
|
15602
|
+
windowsHide: true
|
|
15603
|
+
});
|
|
15604
|
+
if (res.status === 0)
|
|
15605
|
+
return { ok: true };
|
|
15606
|
+
const message = (res.stderr || res.stdout || "").trim() || (res.error ? res.error.message : `binding probe exited with code ${res.status}`);
|
|
15607
|
+
return { ok: false, message };
|
|
15422
15608
|
}
|
|
15423
15609
|
function resolveInstalledBinding2() {
|
|
15424
15610
|
try {
|
|
@@ -15434,7 +15620,7 @@ function findDotNode(baseDir) {
|
|
|
15434
15620
|
(0, import_node_path12.join)(baseDir, "build", "Debug", "better_sqlite3.node")
|
|
15435
15621
|
]) {
|
|
15436
15622
|
try {
|
|
15437
|
-
if ((0,
|
|
15623
|
+
if ((0, import_node_fs14.statSync)(c).isFile())
|
|
15438
15624
|
return c;
|
|
15439
15625
|
} catch {
|
|
15440
15626
|
}
|
|
@@ -15444,7 +15630,7 @@ function findDotNode(baseDir) {
|
|
|
15444
15630
|
const dir = stack.pop();
|
|
15445
15631
|
let entries;
|
|
15446
15632
|
try {
|
|
15447
|
-
entries = (0,
|
|
15633
|
+
entries = (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true });
|
|
15448
15634
|
} catch {
|
|
15449
15635
|
continue;
|
|
15450
15636
|
}
|
|
@@ -15530,12 +15716,27 @@ ${wmsg}` });
|
|
|
15530
15716
|
say("upgrade: quiesced stale Stop hook before migration");
|
|
15531
15717
|
}
|
|
15532
15718
|
for (const d3 of [binDir(), modelsDir(), runDir(), logsDir()])
|
|
15533
|
-
(0,
|
|
15534
|
-
stageBundles(opts.distDir ?? defaultDistDir(), filesWritten);
|
|
15719
|
+
(0, import_node_fs14.mkdirSync)(d3, { recursive: true });
|
|
15720
|
+
const staged = stageBundles(opts.distDir ?? defaultDistDir(), filesWritten);
|
|
15721
|
+
if (!staged.ok) {
|
|
15722
|
+
if (interactive)
|
|
15723
|
+
le(staged.remediation, "Install aborted");
|
|
15724
|
+
else
|
|
15725
|
+
log({ source: "installer/install", level: "error", summary: `install aborted: ${staged.remediation}` });
|
|
15726
|
+
return {
|
|
15727
|
+
aborted: true,
|
|
15728
|
+
abortReason: staged.remediation,
|
|
15729
|
+
report,
|
|
15730
|
+
selected: [...selected],
|
|
15731
|
+
gpu,
|
|
15732
|
+
filesWritten,
|
|
15733
|
+
migration: { state: migration.state, coverage: migration.coverage, drainLaunched: false }
|
|
15734
|
+
};
|
|
15735
|
+
}
|
|
15535
15736
|
say(`scaffolded ${recallRoot()}`);
|
|
15536
15737
|
if (opts.offline) {
|
|
15537
|
-
const haveBin = (0,
|
|
15538
|
-
const haveModel = (0,
|
|
15738
|
+
const haveBin = (0, import_node_fs14.existsSync)(getBinaryPath());
|
|
15739
|
+
const haveModel = (0, import_node_fs14.existsSync)(getModelPath());
|
|
15539
15740
|
if (!haveBin || !haveModel) {
|
|
15540
15741
|
const msg = `--offline but runtime not pre-staged (binary=${haveBin}, model=${haveModel}). Pre-stage ~/.recall/bin + model (or drop --offline), then re-run \`recall install\`` + (migration.state === "needs-migration" ? " (which restores the recall Stop hook)." : ".");
|
|
15541
15742
|
log({ source: "installer/install", level: "error", summary: msg });
|
|
@@ -15716,29 +15917,29 @@ ${wmsg}` });
|
|
|
15716
15917
|
};
|
|
15717
15918
|
}
|
|
15718
15919
|
function spawnDetachedBackfill() {
|
|
15719
|
-
(0,
|
|
15720
|
-
(0,
|
|
15920
|
+
(0, import_node_fs14.mkdirSync)(runDir(), { recursive: true });
|
|
15921
|
+
(0, import_node_fs14.mkdirSync)(logsDir(), { recursive: true });
|
|
15721
15922
|
const recallBundle = (0, import_node_path12.join)(binDir(), "recall.js");
|
|
15722
|
-
const logFd = (0,
|
|
15723
|
-
const child = (0,
|
|
15923
|
+
const logFd = (0, import_node_fs14.openSync)((0, import_node_path12.join)(logsDir(), "backfill.log"), "a");
|
|
15924
|
+
const child = (0, import_node_child_process5.spawn)(process.execPath, [recallBundle, "backfill", "--auto-embed"], {
|
|
15724
15925
|
detached: true,
|
|
15725
15926
|
stdio: ["ignore", logFd, logFd],
|
|
15726
15927
|
windowsHide: true,
|
|
15727
15928
|
env: { ...process.env }
|
|
15728
15929
|
});
|
|
15729
15930
|
if (child.pid !== void 0) {
|
|
15730
|
-
(0,
|
|
15931
|
+
(0, import_node_fs14.writeFileSync)((0, import_node_path12.join)(runDir(), "backfill.pid"), String(child.pid));
|
|
15731
15932
|
}
|
|
15732
15933
|
child.unref();
|
|
15733
15934
|
return child.pid;
|
|
15734
15935
|
}
|
|
15735
|
-
var
|
|
15936
|
+
var import_node_fs14, import_node_child_process5, import_node_module2, import_node_path12, STAGED_BUNDLES;
|
|
15736
15937
|
var init_install = __esm({
|
|
15737
15938
|
"src/installer/install.ts"() {
|
|
15738
15939
|
"use strict";
|
|
15739
15940
|
init_dist2();
|
|
15740
|
-
|
|
15741
|
-
|
|
15941
|
+
import_node_fs14 = require("node:fs");
|
|
15942
|
+
import_node_child_process5 = require("node:child_process");
|
|
15742
15943
|
import_node_module2 = require("node:module");
|
|
15743
15944
|
import_node_path12 = require("node:path");
|
|
15744
15945
|
init_paths();
|
|
@@ -15748,6 +15949,7 @@ var init_install = __esm({
|
|
|
15748
15949
|
init_manifest();
|
|
15749
15950
|
init_gpu();
|
|
15750
15951
|
init_settings_merge();
|
|
15952
|
+
init_stable_node();
|
|
15751
15953
|
init_upgrade_migrate();
|
|
15752
15954
|
init_claudemd_nudge();
|
|
15753
15955
|
init_embedder();
|
|
@@ -15765,8 +15967,8 @@ function runUninstall(opts = {}) {
|
|
|
15765
15967
|
const removed = [];
|
|
15766
15968
|
for (const skillFile of [claudeRecallSkillPath(), codexRecallSkillPath()]) {
|
|
15767
15969
|
const dir = (0, import_node_path13.dirname)(skillFile);
|
|
15768
|
-
if ((0,
|
|
15769
|
-
(0,
|
|
15970
|
+
if ((0, import_node_fs15.existsSync)(dir)) {
|
|
15971
|
+
(0, import_node_fs15.rmSync)(dir, { recursive: true, force: true });
|
|
15770
15972
|
removed.push(dir);
|
|
15771
15973
|
}
|
|
15772
15974
|
}
|
|
@@ -15781,8 +15983,8 @@ function runUninstall(opts = {}) {
|
|
|
15781
15983
|
let purged = false;
|
|
15782
15984
|
if (opts.purge) {
|
|
15783
15985
|
closeDb();
|
|
15784
|
-
if ((0,
|
|
15785
|
-
(0,
|
|
15986
|
+
if ((0, import_node_fs15.existsSync)(recallRoot())) {
|
|
15987
|
+
(0, import_node_fs15.rmSync)(recallRoot(), { recursive: true, force: true });
|
|
15786
15988
|
removed.push(recallRoot());
|
|
15787
15989
|
}
|
|
15788
15990
|
purged = true;
|
|
@@ -15790,11 +15992,11 @@ function runUninstall(opts = {}) {
|
|
|
15790
15992
|
log({ source: "installer/uninstall", level: "info", summary: `uninstall removed ${removed.length} targets (purge=${purged})` });
|
|
15791
15993
|
return { removed, purged };
|
|
15792
15994
|
}
|
|
15793
|
-
var
|
|
15995
|
+
var import_node_fs15, import_node_path13;
|
|
15794
15996
|
var init_uninstall = __esm({
|
|
15795
15997
|
"src/installer/uninstall.ts"() {
|
|
15796
15998
|
"use strict";
|
|
15797
|
-
|
|
15999
|
+
import_node_fs15 = require("node:fs");
|
|
15798
16000
|
import_node_path13 = require("node:path");
|
|
15799
16001
|
init_settings_merge();
|
|
15800
16002
|
init_claudemd_nudge();
|
|
@@ -15816,14 +16018,14 @@ function getStatus() {
|
|
|
15816
16018
|
const messageCount = d3.get("SELECT COUNT(*) AS c FROM messages").c;
|
|
15817
16019
|
const lastRow = d3.get("SELECT MAX(created_at) AS m FROM messages");
|
|
15818
16020
|
const lastIngest = lastRow.m ? new Date(lastRow.m).toISOString() : null;
|
|
15819
|
-
const dbSizeBytes = (0,
|
|
16021
|
+
const dbSizeBytes = (0, import_node_fs16.existsSync)(dbPath()) ? (0, import_node_fs16.statSync)(dbPath()).size : 0;
|
|
15820
16022
|
const embeddingGap = getEmbeddingGapStats();
|
|
15821
16023
|
const embedVersions = getEmbedVersionStats();
|
|
15822
16024
|
let backfillPid = null;
|
|
15823
16025
|
let backfillRunning = false;
|
|
15824
16026
|
const pidFile = (0, import_node_path14.join)(runDir(), "backfill.pid");
|
|
15825
|
-
if ((0,
|
|
15826
|
-
const pid = parseInt((0,
|
|
16027
|
+
if ((0, import_node_fs16.existsSync)(pidFile)) {
|
|
16028
|
+
const pid = parseInt((0, import_node_fs16.readFileSync)(pidFile, "utf-8").trim(), 10);
|
|
15827
16029
|
if (!Number.isNaN(pid)) {
|
|
15828
16030
|
backfillPid = pid;
|
|
15829
16031
|
try {
|
|
@@ -15866,11 +16068,11 @@ function printStatus(json) {
|
|
|
15866
16068
|
console.log(`Embedder: ${s.embedder.toUpperCase()}`);
|
|
15867
16069
|
console.log(`Backfill: ${s.backfillPid === null ? "none recorded" : `PID ${s.backfillPid} (${s.backfillRunning ? "running" : "finished"})`}`);
|
|
15868
16070
|
}
|
|
15869
|
-
var
|
|
16071
|
+
var import_node_fs16, import_node_path14;
|
|
15870
16072
|
var init_status = __esm({
|
|
15871
16073
|
"src/installer/status.ts"() {
|
|
15872
16074
|
"use strict";
|
|
15873
|
-
|
|
16075
|
+
import_node_fs16 = require("node:fs");
|
|
15874
16076
|
import_node_path14 = require("node:path");
|
|
15875
16077
|
init_db();
|
|
15876
16078
|
init_paths();
|
|
@@ -15983,7 +16185,7 @@ function stagedBindingPath() {
|
|
|
15983
16185
|
}
|
|
15984
16186
|
function checkBindingHealth() {
|
|
15985
16187
|
const problems = [];
|
|
15986
|
-
const installed = (0,
|
|
16188
|
+
const installed = (0, import_node_fs17.existsSync)((0, import_node_path15.join)(binDir(), "recall.js"));
|
|
15987
16189
|
if (!installed) {
|
|
15988
16190
|
return {
|
|
15989
16191
|
installed: false,
|
|
@@ -15997,21 +16199,21 @@ function checkBindingHealth() {
|
|
|
15997
16199
|
};
|
|
15998
16200
|
}
|
|
15999
16201
|
const markerPath = (0, import_node_path15.join)(binDir(), ".binding-info.json");
|
|
16000
|
-
const markerPresent = (0,
|
|
16202
|
+
const markerPresent = (0, import_node_fs17.existsSync)(markerPath);
|
|
16001
16203
|
let abiOk = null;
|
|
16002
16204
|
let pinnedNodeOk = null;
|
|
16003
16205
|
if (!markerPresent) {
|
|
16004
16206
|
problems.push("no .binding-info.json marker \u2014 pre-migration (wasm-era) install; run `recall install`");
|
|
16005
16207
|
} else {
|
|
16006
16208
|
try {
|
|
16007
|
-
const marker = JSON.parse((0,
|
|
16209
|
+
const marker = JSON.parse((0, import_node_fs17.readFileSync)(markerPath, "utf-8"));
|
|
16008
16210
|
abiOk = String(marker.nodeModuleVersion) === String(process.versions.modules);
|
|
16009
16211
|
if (!abiOk) {
|
|
16010
16212
|
problems.push(
|
|
16011
16213
|
`binding ABI mismatch (staged for NODE_MODULE_VERSION ${marker.nodeModuleVersion}, current ${process.versions.modules}) \u2014 run \`recall install\``
|
|
16012
16214
|
);
|
|
16013
16215
|
}
|
|
16014
|
-
pinnedNodeOk = !!marker.nodePath && (0,
|
|
16216
|
+
pinnedNodeOk = !!marker.nodePath && (0, import_node_fs17.existsSync)(marker.nodePath);
|
|
16015
16217
|
if (!pinnedNodeOk) {
|
|
16016
16218
|
problems.push(`pinned Node path missing (${marker.nodePath ?? "unset"}) \u2014 run \`recall install\``);
|
|
16017
16219
|
}
|
|
@@ -16024,9 +16226,9 @@ function checkBindingHealth() {
|
|
|
16024
16226
|
let embedCoverage = null;
|
|
16025
16227
|
const localBinding = stagedBindingPath();
|
|
16026
16228
|
const dbFile = dbPath();
|
|
16027
|
-
if ((0,
|
|
16229
|
+
if ((0, import_node_fs17.existsSync)(dbFile)) {
|
|
16028
16230
|
try {
|
|
16029
|
-
const raw2 = (0,
|
|
16231
|
+
const raw2 = (0, import_node_fs17.existsSync)(localBinding) ? new import_better_sqlite33.default(dbFile, { readonly: true, fileMustExist: true, nativeBinding: localBinding }) : new import_better_sqlite33.default(dbFile, { readonly: true, fileMustExist: true });
|
|
16030
16232
|
bindingLoads = true;
|
|
16031
16233
|
journalMode = String(raw2.pragma("journal_mode", { simple: true }));
|
|
16032
16234
|
try {
|
|
@@ -16056,7 +16258,7 @@ function checkBindingHealth() {
|
|
|
16056
16258
|
}
|
|
16057
16259
|
} else {
|
|
16058
16260
|
try {
|
|
16059
|
-
const raw2 = (0,
|
|
16261
|
+
const raw2 = (0, import_node_fs17.existsSync)(localBinding) ? new import_better_sqlite33.default(":memory:", { nativeBinding: localBinding }) : new import_better_sqlite33.default(":memory:");
|
|
16060
16262
|
bindingLoads = true;
|
|
16061
16263
|
raw2.close();
|
|
16062
16264
|
} catch (e2) {
|
|
@@ -16130,11 +16332,11 @@ function printTable(report, embedderMode, fallbackReason) {
|
|
|
16130
16332
|
if (!report.warnings.length && !report.failures.length)
|
|
16131
16333
|
console.log("\nAll checks passed.");
|
|
16132
16334
|
}
|
|
16133
|
-
var
|
|
16335
|
+
var import_node_fs17, import_node_path15, import_better_sqlite33;
|
|
16134
16336
|
var init_doctor = __esm({
|
|
16135
16337
|
"src/installer/doctor.ts"() {
|
|
16136
16338
|
"use strict";
|
|
16137
|
-
|
|
16339
|
+
import_node_fs17 = require("node:fs");
|
|
16138
16340
|
import_node_path15 = require("node:path");
|
|
16139
16341
|
import_better_sqlite33 = __toESM(require_lib());
|
|
16140
16342
|
init_preflight();
|
|
@@ -16738,8 +16940,8 @@ function gitSafe(repoRoot, args) {
|
|
|
16738
16940
|
}
|
|
16739
16941
|
|
|
16740
16942
|
// src/cli/recall.ts
|
|
16741
|
-
var
|
|
16742
|
-
var
|
|
16943
|
+
var import_node_fs18 = require("node:fs");
|
|
16944
|
+
var import_node_child_process6 = require("node:child_process");
|
|
16743
16945
|
var import_node_path16 = require("node:path");
|
|
16744
16946
|
var UUID_PREFIX = /^[0-9a-f]{8}/i;
|
|
16745
16947
|
var argv = process.argv.slice(2);
|
|
@@ -16830,7 +17032,7 @@ for (let i = 0; i < argv.length; i++) {
|
|
|
16830
17032
|
function getVersion() {
|
|
16831
17033
|
try {
|
|
16832
17034
|
const pkg = JSON.parse(
|
|
16833
|
-
(0,
|
|
17035
|
+
(0, import_node_fs18.readFileSync)((0, import_node_path16.join)(__dirname, "..", "package.json"), "utf8")
|
|
16834
17036
|
);
|
|
16835
17037
|
return pkg.version ?? "unknown";
|
|
16836
17038
|
} catch {
|
|
@@ -17406,22 +17608,22 @@ async function runBackfill() {
|
|
|
17406
17608
|
clearCancelFlag();
|
|
17407
17609
|
const detach = hasFlag("--detach");
|
|
17408
17610
|
if (detach) {
|
|
17409
|
-
(0,
|
|
17410
|
-
(0,
|
|
17611
|
+
(0, import_node_fs18.mkdirSync)(logsDir(), { recursive: true });
|
|
17612
|
+
(0, import_node_fs18.mkdirSync)(runDir(), { recursive: true });
|
|
17411
17613
|
const logPath = (0, import_node_path16.join)(logsDir(), "backfill.log");
|
|
17412
|
-
const logFd = (0,
|
|
17614
|
+
const logFd = (0, import_node_fs18.openSync)(logPath, "a");
|
|
17413
17615
|
const args = [process.argv[1], "backfill", "--auto-embed"];
|
|
17414
17616
|
const vendors2 = parseVendors();
|
|
17415
17617
|
if (vendors2) {
|
|
17416
17618
|
args.push("--vendor", vendors2[0]);
|
|
17417
17619
|
}
|
|
17418
|
-
const child = (0,
|
|
17620
|
+
const child = (0, import_node_child_process6.spawn)(process.execPath, args, {
|
|
17419
17621
|
detached: true,
|
|
17420
17622
|
stdio: ["ignore", logFd, logFd],
|
|
17421
17623
|
windowsHide: true
|
|
17422
17624
|
});
|
|
17423
17625
|
if (child.pid !== void 0) {
|
|
17424
|
-
(0,
|
|
17626
|
+
(0, import_node_fs18.writeFileSync)((0, import_node_path16.join)(runDir(), "backfill.pid"), String(child.pid));
|
|
17425
17627
|
}
|
|
17426
17628
|
child.unref();
|
|
17427
17629
|
process.stderr.write(`[recall] backfill detached (pid=${child.pid}, log=${logPath})
|