Skip to content

Commit 50e578c

Browse files
authored
fix(llm-builtin): turn json graphs into a cell links where they repeat (commontoolsinc#2084)
fix(llm-builtin): turn json graphs into a cell links where they repeat since our data structure allows graphs, but we need to output json this can happen. we will return everything after the first occurence as a link, which we can get back since this data must have been generated from a Cell.get()
1 parent 3b3c231 commit 50e578c

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

packages/runner/src/builtins/llm-dialog.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import { formatTransactionSummary } from "../storage/transaction-summary.ts";
2525
import { type NormalizedFullLink, parseLink } from "../link-utils.ts";
2626
import { resolveLink } from "../link-resolution.ts";
2727
import { navigateTo } from "./navigate-to.ts";
28+
import {
29+
getCellOrThrow,
30+
isCellResultForDereferencing,
31+
} from "../query-result-proxy.ts";
32+
2833
// Avoid importing from @commontools/charm to prevent circular deps in tests
2934

3035
const logger = getLogger("llm-dialog", {
@@ -215,22 +220,39 @@ function createLLMFriendlyLink(link: NormalizedFullLink): string {
215220
* @param value - The value to traverse and serialize
216221
* @returns The serialized value
217222
*/
218-
function traverseAndSerialize(value: unknown): unknown {
223+
function traverseAndSerialize(
224+
value: unknown,
225+
seen: Set<unknown> = new Set(),
226+
): unknown {
227+
if (!isRecord(value)) return value;
228+
219229
if (isCell(value)) {
220230
const link = value.getAsNormalizedFullLink();
221231
return { "/": encodeJsonPointer(["", link.id, ...link.path]) };
222232
}
223-
if (Array.isArray(value)) {
224-
return value.map(traverseAndSerialize);
233+
234+
// If we've already seen this and it can be mapped to a cell, serialized as
235+
// cell link, otherwise throw (this should never happen in our cases)
236+
if (seen.has(value)) {
237+
if (isCellResultForDereferencing(value)) {
238+
return traverseAndSerialize(getCellOrThrow(value), seen);
239+
} else {
240+
throw new Error(
241+
"Cannot serialize a value that has already been seen and cannot be mapped to a cell.",
242+
);
243+
}
225244
}
226-
if (isRecord(value)) {
245+
seen.add(value);
246+
247+
if (Array.isArray(value)) {
248+
return value.map((v) => traverseAndSerialize(v, seen));
249+
} else {
227250
return Object.fromEntries(
228251
Object.entries(value).map((
229252
[key, value],
230-
) => [key, traverseAndSerialize(value)]),
253+
) => [key, traverseAndSerialize(value, seen)]),
231254
);
232255
}
233-
return value;
234256
}
235257

236258
const matchLLMFriendlyLink = new RegExp("^/[a-zA-Z0-9]+:");

0 commit comments

Comments
 (0)