Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/adapters/standalone/llm-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import fsPromises from "node:fs/promises";
import path from "node:path";
import { generateText, tool, stepCountIs, jsonSchema } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import { createOpenAI, type OpenAIProviderSettings } from "@ai-sdk/openai";
import { report } from "../../core/report/reporter.js";
import { createNoThinkFetch, type DisableThinkingStrategy } from "../../utils/no-think-fetch.js";
import type {
Expand Down Expand Up @@ -203,9 +203,8 @@ export class StandaloneLLMRunner implements LLMRunner {
const provider = createOpenAI({
baseURL: this.config.baseUrl,
apiKey: this.config.apiKey,
compatibility: "compatible",
...(this.customFetch ? { fetch: this.customFetch } : {}),
});
} satisfies OpenAIProviderSettings);

// For pure text tasks like L1 extraction, avoid exposing any tools.
const tools = this.enableTools
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/auto-recall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ async function searchMemories(
// Hybrid: if the store natively supports hybrid search (e.g. TCVDB does
// server-side dense + sparse + RRF in a single API call), short-circuit
// to avoid a redundant second HTTP request and a wasted local embed().
if (vectorStore?.getCapabilities().nativeHybridSearch) {
if (vectorStore?.getCapabilities().nativeHybridSearch && typeof vectorStore.searchL1Hybrid === "function") {
const tNative = performance.now();
const results = await vectorStore.searchL1Hybrid({ query: cleanText, topK: maxResults });
const nativeMs = performance.now() - tNative;
Expand Down
2 changes: 1 addition & 1 deletion src/offload/benchmark-token-estimate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Benchmark: fastEstimateTokens vs tiktoken cl100k_base
*/
import { fastEstimateTokens } from "../src/offload/fast-token-estimate.ts";
import { fastEstimateTokens } from "./fast-token-estimate.ts";
import { getEncoding } from "js-tiktoken";
import { readFileSync, existsSync } from "fs";
import { join, dirname } from "path";
Expand Down
6 changes: 4 additions & 2 deletions src/offload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,10 @@ export function registerOffload(api: any, offloadConfig: OffloadConfig): void {
stateManager._l1ChunkFailCounts.delete(chunkKey);
if (resp.entries && resp.entries.length > 0) {
for (const entry of resp.entries) {
if (!entry.result_ref && refByToolCallId.has(entry.tool_call_id)) {
entry.result_ref = refByToolCallId.get(entry.tool_call_id)!;
const lookupId = entry.tool_call_id;
const refId = lookupId && (refByToolCallId.get(lookupId) ?? refByToolCallId.get(normalizeToolCallIdForLookup(lookupId)));
if (!entry.result_ref && refId) {
entry.result_ref = refId;
}
}
await appendOffloadEntries(stateManager.ctx, resp.entries, undefined, logger);
Expand Down
2 changes: 1 addition & 1 deletion src/offload/l3-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export function replaceWithSummary(msg: any, entry: OffloadEntry): { originalLen
const summaryContent = [
`[Offloaded Tool Result | node: ${entry.node_id ?? "N/A"}]`,
`Summary: ${entry.summary}`,
`result_ref: ${entry.result_ref} (read this file for full tool call and raw result)`,
`result_ref: ${entry.result_ref ?? ""} (read this file for full tool call and raw result)`,
].join("\n");

// Measure original content length
Expand Down
5 changes: 2 additions & 3 deletions src/offload/local-llm/llm-caller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* to support any OpenAI-compatible backend.
*/
import { generateText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import { createOpenAI, type OpenAIProviderSettings } from "@ai-sdk/openai";
import { createNoThinkFetch, type DisableThinkingStrategy } from "../../utils/no-think-fetch.js";
import type { PluginLogger } from "../types.js";

Expand Down Expand Up @@ -63,9 +63,8 @@ export async function callLlm(
const provider = createOpenAI({
baseURL: config.baseUrl,
apiKey: config.apiKey,
compatibility: "compatible",
...(customFetch ? { fetch: customFetch } : {}),
});
} satisfies OpenAIProviderSettings);

try {
const result = await generateText({
Expand Down
41 changes: 41 additions & 0 deletions src/offload/local-llm/parsers/l1-parser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, it, expect } from "vitest";
import { parseL1Response } from "./l1-parser.js";

describe("L1 Response Parser", () => {
it("should parse L1 entries correctly and ensure result_ref is present", () => {
const raw = JSON.stringify([
{
tool_call: "read_file({path: 'foo.ts'})",
summary: "Reads content of foo.ts",
tool_call_id: "call_abc123",
timestamp: "2026-07-11T12:00:00Z",
score: 8,
},
]);

const entries = parseL1Response(raw);
expect(entries).toHaveLength(1);
expect(entries[0]).toEqual({
tool_call_id: "call_abc123",
tool_call: "read_file({path: 'foo.ts'})",
summary: "Reads content of foo.ts",
timestamp: "2026-07-11T12:00:00Z",
score: 8,
node_id: null,
result_ref: "",
});
});

it("should ignore entries with empty tool_call_id", () => {
const raw = JSON.stringify([
{
tool_call: "read_file({path: 'foo.ts'})",
summary: "Reads content of foo.ts",
timestamp: "2026-07-11T12:00:00Z",
},
]);

const entries = parseL1Response(raw);
expect(entries).toHaveLength(0);
});
});
1 change: 1 addition & 0 deletions src/offload/local-llm/parsers/l1-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export function parseL1Response(raw: string): OffloadEntry[] {
timestamp: item.timestamp ?? "",
score: typeof item.score === "number" ? item.score : 5,
node_id: null,
result_ref: "",
});
}

Expand Down