From 58d072f0a16794e96e07302cac8169c74017c14c Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Tue, 15 Oct 2024 15:39:54 +0200 Subject: [PATCH] fix(serialization): handle bounded functions Ref: #92 Signed-off-by: Tomas Dvorak --- src/serializer/serializer.test.ts | 26 ++++++++++++++++++++++++++ src/serializer/serializer.ts | 4 +++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/serializer/serializer.test.ts b/src/serializer/serializer.test.ts index 16c831bd..40098620 100644 --- a/src/serializer/serializer.test.ts +++ b/src/serializer/serializer.test.ts @@ -25,6 +25,7 @@ import { BAMLLM } from "@/adapters/bam/llm.js"; import { BAMChatLLM } from "@/adapters/bam/chat.js"; import { SerializerError } from "@/serializer/error.js"; import { ValueOf } from "@/internals/types.js"; +import { toBoundedFunction } from "@/serializer/utils.js"; describe("Serializer", () => { it.each([ @@ -265,6 +266,31 @@ describe("Serializer", () => { expect(() => Serializer.deserialize(json, [BaseMessage])).not.toThrowError(); }); + it("Handles bounded functions", () => { + const a = 1; + const b = 2; + + let fn = toBoundedFunction( + (...args: any[]) => [a, b, ...args].reduce((a, b) => a + b, 0), + [ + { + name: "a", + value: a, + }, + { + name: "b", + value: b, + }, + ], + ); + + for (let i = 0; i < 5; ++i) { + const serialized = Serializer.serialize(fn); + fn = Serializer.deserialize(serialized); + expect(fn(3)).toBe(6); + } + }); + it("Handles nested functions", () => { vi.stubEnv("GENAI_API_KEY", "123"); const { data } = JSON.parse( diff --git a/src/serializer/serializer.ts b/src/serializer/serializer.ts index 109c2890..3482b095 100644 --- a/src/serializer/serializer.ts +++ b/src/serializer/serializer.ts @@ -31,6 +31,7 @@ import { RootNode, SerializerNode, SerializerRefIdentifier, + toBoundedFunction, traverseObject, traverseWithUpdate, } from "@/serializer/utils.js"; @@ -43,6 +44,7 @@ import { SerializerError } from "@/serializer/error.js"; import { ZodType } from "zod"; import { toJsonSchema } from "@/internals/helpers/schema.js"; import { createAbortController } from "@/internals/helpers/cancellation.js"; +import { hasMinLength } from "@/internals/helpers/array.js"; export interface SerializeFactory { ref: ClassConstructor | NamedFunction; @@ -530,7 +532,7 @@ Serializer.register(Function, { value: () => value.fn, }), ); - return fn; + return hasMinLength(binds, 1) ? toBoundedFunction(fn, binds) : fn; }, });