crispy-recall 0.1.1 → 0.1.3
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/embed-pending.js +61 -37
- package/dist/recall.js +73 -33
- package/dist/stop-hook.js +18 -5
- package/package.json +1 -1
package/dist/embed-pending.js
CHANGED
|
@@ -4594,6 +4594,11 @@ async function startServer() {
|
|
|
4594
4594
|
"-ub",
|
|
4595
4595
|
"8192",
|
|
4596
4596
|
// micro-batch (ubatch) — also defaults to 512, must be raised
|
|
4597
|
+
// Flash Attention: the attention compute buffer is otherwise O(n²) in the
|
|
4598
|
+
// 8192-token batch (~3.7 GB on GPU), which OOMs cards <6 GB and forces CPU.
|
|
4599
|
+
// -fa makes it O(n) (~0.8 GB → ~2.9 GB total), so 4 GB cards run on GPU,
|
|
4600
|
+
// with numerically identical embeddings (verified cosine 1.0 vs non-FA).
|
|
4601
|
+
"-fa",
|
|
4597
4602
|
// nomic-embed-text-v1.5 is trained at 2048 ctx and uses Dynamic NTK-aware
|
|
4598
4603
|
// RoPE scaling to extend to 8192. Without these flags, newer llama.cpp
|
|
4599
4604
|
// (b9253+) refuses inputs >2048 tokens, and older versions silently
|
|
@@ -4801,6 +4806,9 @@ async function embedViaProcess(texts, modelPath) {
|
|
|
4801
4806
|
"array",
|
|
4802
4807
|
"-c",
|
|
4803
4808
|
"8192",
|
|
4809
|
+
// Flash Attention — see startServer: O(n) attention buffer instead of
|
|
4810
|
+
// O(n²), so the one-shot path also fits cards <6 GB. Identical embeddings.
|
|
4811
|
+
"-fa",
|
|
4804
4812
|
// Match the YaRN flags on the llama-server batch path — nomic-embed-text-v1.5
|
|
4805
4813
|
// is trained at 2048 ctx and extends to 8192 via Dynamic NTK-aware RoPE.
|
|
4806
4814
|
// Without these, newer llama.cpp (b9253+) refuses inputs >2048 tokens here
|
|
@@ -5552,6 +5560,9 @@ function normalizePath(p) {
|
|
|
5552
5560
|
return normalized;
|
|
5553
5561
|
}
|
|
5554
5562
|
|
|
5563
|
+
// src/recall/message-ingest.ts
|
|
5564
|
+
init_log();
|
|
5565
|
+
|
|
5555
5566
|
// src/adapters/claude/jsonl-reader.ts
|
|
5556
5567
|
var fs = __toESM(require("fs"));
|
|
5557
5568
|
init_log();
|
|
@@ -5962,8 +5973,7 @@ function emitFunctionCall(payload, base, outputIndex, _counter) {
|
|
|
5962
5973
|
const outputRecord = outputIndex.get(callId);
|
|
5963
5974
|
if (outputRecord) {
|
|
5964
5975
|
const outputPayload = outputRecord.payload;
|
|
5965
|
-
const
|
|
5966
|
-
const { exitCode, body } = parseExecOutputHeader(rawOutput);
|
|
5976
|
+
const { exitCode, body } = parseExecOutputHeader(outputPayload.output);
|
|
5967
5977
|
const isError = exitCode !== 0;
|
|
5968
5978
|
const toolResult = {
|
|
5969
5979
|
type: "tool_result",
|
|
@@ -6101,7 +6111,7 @@ function emitApplyPatch(callId, input, base, outputIndex) {
|
|
|
6101
6111
|
return entries;
|
|
6102
6112
|
}
|
|
6103
6113
|
function buildCustomToolResult(parentUuid, callId, outputRecord, base) {
|
|
6104
|
-
const rawOutput = outputRecord.payload.output;
|
|
6114
|
+
const rawOutput = coerceOutputText(outputRecord.payload.output);
|
|
6105
6115
|
let content;
|
|
6106
6116
|
let isError = false;
|
|
6107
6117
|
try {
|
|
@@ -6182,7 +6192,7 @@ function emitOrphanedOutput(payload, subtype, base, outputIndex, _counter) {
|
|
|
6182
6192
|
return [];
|
|
6183
6193
|
if (!outputIndex.has(callId))
|
|
6184
6194
|
return [];
|
|
6185
|
-
const rawOutput = payload.output;
|
|
6195
|
+
const rawOutput = coerceOutputText(payload.output);
|
|
6186
6196
|
let content;
|
|
6187
6197
|
let isError = false;
|
|
6188
6198
|
if (subtype === "function_call_output") {
|
|
@@ -6295,7 +6305,18 @@ function mapFunctionCall(name, args) {
|
|
|
6295
6305
|
return { toolName: name, toolInput: args };
|
|
6296
6306
|
}
|
|
6297
6307
|
}
|
|
6298
|
-
function
|
|
6308
|
+
function coerceOutputText(output) {
|
|
6309
|
+
if (typeof output === "string")
|
|
6310
|
+
return output;
|
|
6311
|
+
if (Array.isArray(output)) {
|
|
6312
|
+
return output.map(
|
|
6313
|
+
(item) => item && typeof item === "object" && typeof item.text === "string" ? item.text : ""
|
|
6314
|
+
).filter(Boolean).join("\n");
|
|
6315
|
+
}
|
|
6316
|
+
return "";
|
|
6317
|
+
}
|
|
6318
|
+
function parseExecOutputHeader(rawOutput) {
|
|
6319
|
+
const output = coerceOutputText(rawOutput);
|
|
6299
6320
|
if (!output)
|
|
6300
6321
|
return { exitCode: 0, body: "" };
|
|
6301
6322
|
const currentMatch = output.match(/Process exited with code (\d+)/);
|
|
@@ -6460,6 +6481,39 @@ async function ingestSessionMessages(sessionId, transcriptPath, vendor, options)
|
|
|
6460
6481
|
}
|
|
6461
6482
|
var MAX_EMBED_CHARS = 14e3;
|
|
6462
6483
|
var MAX_EMBED_BATCH = 10;
|
|
6484
|
+
var SAFE_EMBED_CHARS = 6e3;
|
|
6485
|
+
async function embedRowsResilient(rows) {
|
|
6486
|
+
const { embedBatch: embedBatch2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
6487
|
+
const { quantizeToQ8: quantizeToQ82, computeNorm: computeNorm2 } = await Promise.resolve().then(() => (init_quantize(), quantize_exports));
|
|
6488
|
+
const toRecord = (messageId, f32) => {
|
|
6489
|
+
const { q8, scale } = quantizeToQ82(f32);
|
|
6490
|
+
return { messageId, embeddingQ8: q8, norm: computeNorm2(f32), quantScale: scale };
|
|
6491
|
+
};
|
|
6492
|
+
try {
|
|
6493
|
+
const vectors = await embedBatch2(rows.map((r) => r.text));
|
|
6494
|
+
return rows.map((r, j) => toRecord(r.messageId, vectors[j]));
|
|
6495
|
+
} catch {
|
|
6496
|
+
const records = [];
|
|
6497
|
+
for (const r of rows) {
|
|
6498
|
+
try {
|
|
6499
|
+
const [v] = await embedBatch2([r.text]);
|
|
6500
|
+
records.push(toRecord(r.messageId, v));
|
|
6501
|
+
} catch {
|
|
6502
|
+
try {
|
|
6503
|
+
const [v] = await embedBatch2([r.text.slice(0, SAFE_EMBED_CHARS)]);
|
|
6504
|
+
records.push(toRecord(r.messageId, v));
|
|
6505
|
+
} catch (err) {
|
|
6506
|
+
log({
|
|
6507
|
+
source: "recall:embed",
|
|
6508
|
+
level: "warn",
|
|
6509
|
+
summary: `skipped message ${r.messageId} (embed failed even at ${SAFE_EMBED_CHARS} chars): ${err.message}`
|
|
6510
|
+
});
|
|
6511
|
+
}
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
return records;
|
|
6515
|
+
}
|
|
6516
|
+
}
|
|
6463
6517
|
async function embedSessionMessages(sessionId, force) {
|
|
6464
6518
|
const d = getDb(dbPath());
|
|
6465
6519
|
const rows = d.all(
|
|
@@ -6484,22 +6538,7 @@ async function embedSessionMessages(sessionId, force) {
|
|
|
6484
6538
|
if (validRows.length > MAX_EMBED_BATCH) {
|
|
6485
6539
|
validRows.length = MAX_EMBED_BATCH;
|
|
6486
6540
|
}
|
|
6487
|
-
const
|
|
6488
|
-
const { quantizeToQ8: quantizeToQ82, computeNorm: computeNorm2 } = await Promise.resolve().then(() => (init_quantize(), quantize_exports));
|
|
6489
|
-
const texts = validRows.map((r) => r.text);
|
|
6490
|
-
const vectors = await embedBatch2(texts);
|
|
6491
|
-
const records = [];
|
|
6492
|
-
for (let j = 0; j < validRows.length; j++) {
|
|
6493
|
-
const f32 = vectors[j];
|
|
6494
|
-
const { q8, scale } = quantizeToQ82(f32);
|
|
6495
|
-
const norm = computeNorm2(f32);
|
|
6496
|
-
records.push({
|
|
6497
|
-
messageId: validRows[j].messageId,
|
|
6498
|
-
embeddingQ8: q8,
|
|
6499
|
-
norm,
|
|
6500
|
-
quantScale: scale
|
|
6501
|
-
});
|
|
6502
|
-
}
|
|
6541
|
+
const records = await embedRowsResilient(validRows);
|
|
6503
6542
|
insertMessageVectors(records);
|
|
6504
6543
|
return records.length;
|
|
6505
6544
|
}
|
|
@@ -6518,22 +6557,7 @@ async function embedMessageBatch(messages) {
|
|
|
6518
6557
|
}
|
|
6519
6558
|
if (truncated.length === 0)
|
|
6520
6559
|
return 0;
|
|
6521
|
-
const
|
|
6522
|
-
const { quantizeToQ8: quantizeToQ82, computeNorm: computeNorm2 } = await Promise.resolve().then(() => (init_quantize(), quantize_exports));
|
|
6523
|
-
const texts = truncated.map((r) => r.text);
|
|
6524
|
-
const vectors = await embedBatch2(texts);
|
|
6525
|
-
const records = [];
|
|
6526
|
-
for (let j = 0; j < truncated.length; j++) {
|
|
6527
|
-
const f32 = vectors[j];
|
|
6528
|
-
const { q8, scale } = quantizeToQ82(f32);
|
|
6529
|
-
const norm = computeNorm2(f32);
|
|
6530
|
-
records.push({
|
|
6531
|
-
messageId: truncated[j].messageId,
|
|
6532
|
-
embeddingQ8: q8,
|
|
6533
|
-
norm,
|
|
6534
|
-
quantScale: scale
|
|
6535
|
-
});
|
|
6536
|
-
}
|
|
6560
|
+
const records = await embedRowsResilient(truncated);
|
|
6537
6561
|
insertMessageVectors(records);
|
|
6538
6562
|
return records.length;
|
|
6539
6563
|
}
|
package/dist/recall.js
CHANGED
|
@@ -3268,6 +3268,11 @@ async function startServer() {
|
|
|
3268
3268
|
"-ub",
|
|
3269
3269
|
"8192",
|
|
3270
3270
|
// micro-batch (ubatch) — also defaults to 512, must be raised
|
|
3271
|
+
// Flash Attention: the attention compute buffer is otherwise O(n²) in the
|
|
3272
|
+
// 8192-token batch (~3.7 GB on GPU), which OOMs cards <6 GB and forces CPU.
|
|
3273
|
+
// -fa makes it O(n) (~0.8 GB → ~2.9 GB total), so 4 GB cards run on GPU,
|
|
3274
|
+
// with numerically identical embeddings (verified cosine 1.0 vs non-FA).
|
|
3275
|
+
"-fa",
|
|
3271
3276
|
// nomic-embed-text-v1.5 is trained at 2048 ctx and uses Dynamic NTK-aware
|
|
3272
3277
|
// RoPE scaling to extend to 8192. Without these flags, newer llama.cpp
|
|
3273
3278
|
// (b9253+) refuses inputs >2048 tokens, and older versions silently
|
|
@@ -3475,6 +3480,9 @@ async function embedViaProcess(texts, modelPath) {
|
|
|
3475
3480
|
"array",
|
|
3476
3481
|
"-c",
|
|
3477
3482
|
"8192",
|
|
3483
|
+
// Flash Attention — see startServer: O(n) attention buffer instead of
|
|
3484
|
+
// O(n²), so the one-shot path also fits cards <6 GB. Identical embeddings.
|
|
3485
|
+
"-fa",
|
|
3478
3486
|
// Match the YaRN flags on the llama-server batch path — nomic-embed-text-v1.5
|
|
3479
3487
|
// is trained at 2048 ctx and extends to 8192 via Dynamic NTK-aware RoPE.
|
|
3480
3488
|
// Without these, newer llama.cpp (b9253+) refuses inputs >2048 tokens here
|
|
@@ -13157,8 +13165,7 @@ function emitFunctionCall(payload, base, outputIndex, _counter) {
|
|
|
13157
13165
|
const outputRecord = outputIndex.get(callId);
|
|
13158
13166
|
if (outputRecord) {
|
|
13159
13167
|
const outputPayload = outputRecord.payload;
|
|
13160
|
-
const
|
|
13161
|
-
const { exitCode, body } = parseExecOutputHeader(rawOutput);
|
|
13168
|
+
const { exitCode, body } = parseExecOutputHeader(outputPayload.output);
|
|
13162
13169
|
const isError = exitCode !== 0;
|
|
13163
13170
|
const toolResult = {
|
|
13164
13171
|
type: "tool_result",
|
|
@@ -13296,7 +13303,7 @@ function emitApplyPatch(callId, input, base, outputIndex) {
|
|
|
13296
13303
|
return entries;
|
|
13297
13304
|
}
|
|
13298
13305
|
function buildCustomToolResult(parentUuid, callId, outputRecord, base) {
|
|
13299
|
-
const rawOutput = outputRecord.payload.output;
|
|
13306
|
+
const rawOutput = coerceOutputText(outputRecord.payload.output);
|
|
13300
13307
|
let content;
|
|
13301
13308
|
let isError = false;
|
|
13302
13309
|
try {
|
|
@@ -13377,7 +13384,7 @@ function emitOrphanedOutput(payload, subtype, base, outputIndex, _counter) {
|
|
|
13377
13384
|
return [];
|
|
13378
13385
|
if (!outputIndex.has(callId))
|
|
13379
13386
|
return [];
|
|
13380
|
-
const rawOutput = payload.output;
|
|
13387
|
+
const rawOutput = coerceOutputText(payload.output);
|
|
13381
13388
|
let content;
|
|
13382
13389
|
let isError = false;
|
|
13383
13390
|
if (subtype === "function_call_output") {
|
|
@@ -13490,7 +13497,18 @@ function mapFunctionCall(name, args) {
|
|
|
13490
13497
|
return { toolName: name, toolInput: args };
|
|
13491
13498
|
}
|
|
13492
13499
|
}
|
|
13493
|
-
function
|
|
13500
|
+
function coerceOutputText(output) {
|
|
13501
|
+
if (typeof output === "string")
|
|
13502
|
+
return output;
|
|
13503
|
+
if (Array.isArray(output)) {
|
|
13504
|
+
return output.map(
|
|
13505
|
+
(item) => item && typeof item === "object" && typeof item.text === "string" ? item.text : ""
|
|
13506
|
+
).filter(Boolean).join("\n");
|
|
13507
|
+
}
|
|
13508
|
+
return "";
|
|
13509
|
+
}
|
|
13510
|
+
function parseExecOutputHeader(rawOutput) {
|
|
13511
|
+
const output = coerceOutputText(rawOutput);
|
|
13494
13512
|
if (!output)
|
|
13495
13513
|
return { exitCode: 0, body: "" };
|
|
13496
13514
|
const currentMatch = output.match(/Process exited with code (\d+)/);
|
|
@@ -13658,6 +13676,38 @@ async function ingestSessionMessages(sessionId, transcriptPath, vendor, options)
|
|
|
13658
13676
|
skipped: false
|
|
13659
13677
|
};
|
|
13660
13678
|
}
|
|
13679
|
+
async function embedRowsResilient(rows) {
|
|
13680
|
+
const { embedBatch: embedBatch2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
13681
|
+
const { quantizeToQ8: quantizeToQ82, computeNorm: computeNorm2 } = await Promise.resolve().then(() => (init_quantize(), quantize_exports));
|
|
13682
|
+
const toRecord = (messageId, f32) => {
|
|
13683
|
+
const { q8, scale } = quantizeToQ82(f32);
|
|
13684
|
+
return { messageId, embeddingQ8: q8, norm: computeNorm2(f32), quantScale: scale };
|
|
13685
|
+
};
|
|
13686
|
+
try {
|
|
13687
|
+
const vectors = await embedBatch2(rows.map((r2) => r2.text));
|
|
13688
|
+
return rows.map((r2, j2) => toRecord(r2.messageId, vectors[j2]));
|
|
13689
|
+
} catch {
|
|
13690
|
+
const records = [];
|
|
13691
|
+
for (const r2 of rows) {
|
|
13692
|
+
try {
|
|
13693
|
+
const [v2] = await embedBatch2([r2.text]);
|
|
13694
|
+
records.push(toRecord(r2.messageId, v2));
|
|
13695
|
+
} catch {
|
|
13696
|
+
try {
|
|
13697
|
+
const [v2] = await embedBatch2([r2.text.slice(0, SAFE_EMBED_CHARS)]);
|
|
13698
|
+
records.push(toRecord(r2.messageId, v2));
|
|
13699
|
+
} catch (err) {
|
|
13700
|
+
log({
|
|
13701
|
+
source: "recall:embed",
|
|
13702
|
+
level: "warn",
|
|
13703
|
+
summary: `skipped message ${r2.messageId} (embed failed even at ${SAFE_EMBED_CHARS} chars): ${err.message}`
|
|
13704
|
+
});
|
|
13705
|
+
}
|
|
13706
|
+
}
|
|
13707
|
+
}
|
|
13708
|
+
return records;
|
|
13709
|
+
}
|
|
13710
|
+
}
|
|
13661
13711
|
async function embedMessageBatch(messages) {
|
|
13662
13712
|
if (messages.length === 0)
|
|
13663
13713
|
return 0;
|
|
@@ -13673,26 +13723,11 @@ async function embedMessageBatch(messages) {
|
|
|
13673
13723
|
}
|
|
13674
13724
|
if (truncated.length === 0)
|
|
13675
13725
|
return 0;
|
|
13676
|
-
const
|
|
13677
|
-
const { quantizeToQ8: quantizeToQ82, computeNorm: computeNorm2 } = await Promise.resolve().then(() => (init_quantize(), quantize_exports));
|
|
13678
|
-
const texts = truncated.map((r2) => r2.text);
|
|
13679
|
-
const vectors = await embedBatch2(texts);
|
|
13680
|
-
const records = [];
|
|
13681
|
-
for (let j2 = 0; j2 < truncated.length; j2++) {
|
|
13682
|
-
const f32 = vectors[j2];
|
|
13683
|
-
const { q8, scale } = quantizeToQ82(f32);
|
|
13684
|
-
const norm = computeNorm2(f32);
|
|
13685
|
-
records.push({
|
|
13686
|
-
messageId: truncated[j2].messageId,
|
|
13687
|
-
embeddingQ8: q8,
|
|
13688
|
-
norm,
|
|
13689
|
-
quantScale: scale
|
|
13690
|
-
});
|
|
13691
|
-
}
|
|
13726
|
+
const records = await embedRowsResilient(truncated);
|
|
13692
13727
|
insertMessageVectors(records);
|
|
13693
13728
|
return records.length;
|
|
13694
13729
|
}
|
|
13695
|
-
var MAX_EMBED_CHARS;
|
|
13730
|
+
var MAX_EMBED_CHARS, SAFE_EMBED_CHARS;
|
|
13696
13731
|
var init_message_ingest = __esm({
|
|
13697
13732
|
"src/recall/message-ingest.ts"() {
|
|
13698
13733
|
"use strict";
|
|
@@ -13701,11 +13736,13 @@ var init_message_ingest = __esm({
|
|
|
13701
13736
|
init_db();
|
|
13702
13737
|
init_paths();
|
|
13703
13738
|
init_url_path_resolver();
|
|
13739
|
+
init_log();
|
|
13704
13740
|
init_jsonl_reader();
|
|
13705
13741
|
init_claude_entry_adapter();
|
|
13706
13742
|
init_codex_jsonl_reader();
|
|
13707
13743
|
init_codex_jsonl_adapter();
|
|
13708
13744
|
MAX_EMBED_CHARS = 14e3;
|
|
13745
|
+
SAFE_EMBED_CHARS = 6e3;
|
|
13709
13746
|
}
|
|
13710
13747
|
});
|
|
13711
13748
|
|
|
@@ -14924,8 +14961,8 @@ function cudaAssetUrl() {
|
|
|
14924
14961
|
const tag = version ? `download/v${version}` : "latest/download";
|
|
14925
14962
|
return `https://github.com/${owner}/${repo}/releases/${tag}/${CUDA_ASSET_NAME}`;
|
|
14926
14963
|
}
|
|
14927
|
-
function
|
|
14928
|
-
return (0, import_node_path9.join)(
|
|
14964
|
+
function cudaBackendLib() {
|
|
14965
|
+
return (0, import_node_path9.join)(binDir(), "libggml-cuda.so");
|
|
14929
14966
|
}
|
|
14930
14967
|
async function readVram() {
|
|
14931
14968
|
try {
|
|
@@ -14957,7 +14994,7 @@ async function detectGpu(opts = {}) {
|
|
|
14957
14994
|
if (p === "win32" && a3 === "x64") {
|
|
14958
14995
|
return { ...base, cudaAvailable: "prebuilt", plannedMode: "gpu" };
|
|
14959
14996
|
}
|
|
14960
|
-
if (p === "linux" && a3 === "x64" && (0, import_node_fs9.existsSync)(
|
|
14997
|
+
if (p === "linux" && a3 === "x64" && (0, import_node_fs9.existsSync)(cudaBackendLib())) {
|
|
14961
14998
|
return { ...base, cudaAvailable: "reuse-existing", plannedMode: "gpu" };
|
|
14962
14999
|
}
|
|
14963
15000
|
if (p === "linux" && a3 === "x64") {
|
|
@@ -14966,10 +15003,7 @@ async function detectGpu(opts = {}) {
|
|
|
14966
15003
|
return { ...base, cudaAvailable: "none", plannedMode: "cpu" };
|
|
14967
15004
|
}
|
|
14968
15005
|
function stderrIndicatesOffload(stderr) {
|
|
14969
|
-
|
|
14970
|
-
return true;
|
|
14971
|
-
const m2 = /offloaded\s+(\d+)\s*\/\s*\d+\s+layers?\s+to\s+GPU/i.exec(stderr);
|
|
14972
|
-
return m2 ? Number(m2[1]) > 0 : false;
|
|
15006
|
+
return /ggml_cuda_init|found\s+\d+\s+CUDA\s+devices|loaded CUDA backend|using device CUDA|CUDA0[^\n]*buffer/i.test(stderr);
|
|
14973
15007
|
}
|
|
14974
15008
|
async function defaultProbe(args) {
|
|
14975
15009
|
const { binaryPath: binaryPath2, modelPath, libDir, ngl, platform: platform2 } = args;
|
|
@@ -14990,6 +15024,12 @@ async function defaultProbe(args) {
|
|
|
14990
15024
|
"array",
|
|
14991
15025
|
"-c",
|
|
14992
15026
|
"8192",
|
|
15027
|
+
// Probe with the SAME flags the real embed server uses (esp. -fa). Without
|
|
15028
|
+
// Flash Attention the probe allocates the ~3.7 GB O(n²) attention buffer and
|
|
15029
|
+
// OOMs on a 4 GB card — failing the probe and falling back to CPU even
|
|
15030
|
+
// though the actual -fa server (~2.9 GB) would have fit. Probe must mirror
|
|
15031
|
+
// runtime to gate GPU adoption correctly.
|
|
15032
|
+
"-fa",
|
|
14993
15033
|
"--rope-scaling",
|
|
14994
15034
|
"yarn",
|
|
14995
15035
|
"--rope-freq-scale",
|
|
@@ -15044,7 +15084,7 @@ async function runGpuPhase(opts = {}) {
|
|
|
15044
15084
|
return { mode, libDir: libDir2, ngl: mode === "gpu" ? DEFAULT_NGL : 0, cudaAvailable: info.cudaAvailable, ...reason ? { reason } : {} };
|
|
15045
15085
|
};
|
|
15046
15086
|
if (info.plannedMode === "cpu") {
|
|
15047
|
-
const reason = info.detected && info.vendor === "nvidia" ? "NVIDIA GPU detected but no usable CUDA libs (no prebuilt for this platform; no ~/.recall/bin-cuda
|
|
15087
|
+
const reason = info.detected && info.vendor === "nvidia" ? "NVIDIA GPU detected but no usable CUDA libs (no prebuilt for this platform; no ~/.recall/bin/libggml-cuda.so present)" : void 0;
|
|
15048
15088
|
return persist("cpu", null, reason);
|
|
15049
15089
|
}
|
|
15050
15090
|
if (info.cudaAvailable === "metal") {
|
|
@@ -15052,7 +15092,7 @@ async function runGpuPhase(opts = {}) {
|
|
|
15052
15092
|
}
|
|
15053
15093
|
let libDir;
|
|
15054
15094
|
if (info.cudaAvailable === "reuse-existing") {
|
|
15055
|
-
libDir =
|
|
15095
|
+
libDir = binDir();
|
|
15056
15096
|
} else if (info.cudaAvailable === "prebuilt" && p === "win32") {
|
|
15057
15097
|
libDir = binDir();
|
|
15058
15098
|
} else if (info.cudaAvailable === "prebuilt") {
|
|
@@ -15087,8 +15127,8 @@ async function runGpuPhase(opts = {}) {
|
|
|
15087
15127
|
}
|
|
15088
15128
|
}
|
|
15089
15129
|
async function defaultStage(args) {
|
|
15090
|
-
const target =
|
|
15091
|
-
const libPath = (
|
|
15130
|
+
const target = binDir();
|
|
15131
|
+
const libPath = cudaBackendLib();
|
|
15092
15132
|
if ((0, import_node_fs9.existsSync)(libPath))
|
|
15093
15133
|
return target;
|
|
15094
15134
|
if (args.offline)
|
package/dist/stop-hook.js
CHANGED
|
@@ -1807,6 +1807,9 @@ function normalizePath(p) {
|
|
|
1807
1807
|
return normalized;
|
|
1808
1808
|
}
|
|
1809
1809
|
|
|
1810
|
+
// src/recall/message-ingest.ts
|
|
1811
|
+
init_log();
|
|
1812
|
+
|
|
1810
1813
|
// src/adapters/claude/jsonl-reader.ts
|
|
1811
1814
|
var fs = __toESM(require("fs"));
|
|
1812
1815
|
init_log();
|
|
@@ -2217,8 +2220,7 @@ function emitFunctionCall(payload, base, outputIndex, _counter) {
|
|
|
2217
2220
|
const outputRecord = outputIndex.get(callId);
|
|
2218
2221
|
if (outputRecord) {
|
|
2219
2222
|
const outputPayload = outputRecord.payload;
|
|
2220
|
-
const
|
|
2221
|
-
const { exitCode, body } = parseExecOutputHeader(rawOutput);
|
|
2223
|
+
const { exitCode, body } = parseExecOutputHeader(outputPayload.output);
|
|
2222
2224
|
const isError = exitCode !== 0;
|
|
2223
2225
|
const toolResult = {
|
|
2224
2226
|
type: "tool_result",
|
|
@@ -2356,7 +2358,7 @@ function emitApplyPatch(callId, input, base, outputIndex) {
|
|
|
2356
2358
|
return entries;
|
|
2357
2359
|
}
|
|
2358
2360
|
function buildCustomToolResult(parentUuid, callId, outputRecord, base) {
|
|
2359
|
-
const rawOutput = outputRecord.payload.output;
|
|
2361
|
+
const rawOutput = coerceOutputText(outputRecord.payload.output);
|
|
2360
2362
|
let content;
|
|
2361
2363
|
let isError = false;
|
|
2362
2364
|
try {
|
|
@@ -2437,7 +2439,7 @@ function emitOrphanedOutput(payload, subtype, base, outputIndex, _counter) {
|
|
|
2437
2439
|
return [];
|
|
2438
2440
|
if (!outputIndex.has(callId))
|
|
2439
2441
|
return [];
|
|
2440
|
-
const rawOutput = payload.output;
|
|
2442
|
+
const rawOutput = coerceOutputText(payload.output);
|
|
2441
2443
|
let content;
|
|
2442
2444
|
let isError = false;
|
|
2443
2445
|
if (subtype === "function_call_output") {
|
|
@@ -2550,7 +2552,18 @@ function mapFunctionCall(name, args) {
|
|
|
2550
2552
|
return { toolName: name, toolInput: args };
|
|
2551
2553
|
}
|
|
2552
2554
|
}
|
|
2553
|
-
function
|
|
2555
|
+
function coerceOutputText(output) {
|
|
2556
|
+
if (typeof output === "string")
|
|
2557
|
+
return output;
|
|
2558
|
+
if (Array.isArray(output)) {
|
|
2559
|
+
return output.map(
|
|
2560
|
+
(item) => item && typeof item === "object" && typeof item.text === "string" ? item.text : ""
|
|
2561
|
+
).filter(Boolean).join("\n");
|
|
2562
|
+
}
|
|
2563
|
+
return "";
|
|
2564
|
+
}
|
|
2565
|
+
function parseExecOutputHeader(rawOutput) {
|
|
2566
|
+
const output = coerceOutputText(rawOutput);
|
|
2554
2567
|
if (!output)
|
|
2555
2568
|
return { exitCode: 0, body: "" };
|
|
2556
2569
|
const currentMatch = output.match(/Process exited with code (\d+)/);
|
package/package.json
CHANGED