diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22df0297f..ce5d58431 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -741,8 +741,8 @@ packages: '@lit-labs/signals@0.2.0': resolution: {integrity: sha512-68plyIbciumbwKaiilhLNyhz4Vg6/+nJwDufG2xxWA9r/fUw58jxLHCAlKs+q1CE5Lmh3cZ3ShyYKnOCebEpVA==} - '@lit-labs/ssr-dom-shim@1.5.0': - resolution: {integrity: sha512-HLomZXMmrCFHSRKESF5vklAKsDY7/fsT/ZhqCu3V0UoW/Qbv8wxmO4W9bx4KnCCF2Zak4yuk+AGraK/bPmI4kA==} + '@lit-labs/ssr-dom-shim@1.5.1': + resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} '@lit/context@1.1.6': resolution: {integrity: sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==} @@ -2004,8 +2004,8 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - iconv-lite@0.7.1: - resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} ieee754@1.2.1: @@ -3545,7 +3545,7 @@ snapshots: lit: 3.3.2 signal-polyfill: 0.2.2 - '@lit-labs/ssr-dom-shim@1.5.0': {} + '@lit-labs/ssr-dom-shim@1.5.1': {} '@lit/context@1.1.6': dependencies: @@ -3553,7 +3553,7 @@ snapshots: '@lit/reactive-element@2.1.2': dependencies: - '@lit-labs/ssr-dom-shim': 1.5.0 + '@lit-labs/ssr-dom-shim': 1.5.1 '@mariozechner/clipboard-darwin-arm64@0.3.0': optional: true @@ -4370,7 +4370,7 @@ snapshots: content-type: 1.0.5 debug: 4.4.3 http-errors: 2.0.1 - iconv-lite: 0.7.1 + iconv-lite: 0.7.2 on-finished: 2.4.1 qs: 6.14.1 raw-body: 3.0.2 @@ -4912,7 +4912,7 @@ snapshots: transitivePeerDependencies: - supports-color - iconv-lite@0.7.1: + iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 @@ -5104,7 +5104,7 @@ snapshots: lit-element@4.2.2: dependencies: - '@lit-labs/ssr-dom-shim': 1.5.0 + '@lit-labs/ssr-dom-shim': 1.5.1 '@lit/reactive-element': 2.1.2 lit-html: 3.3.2 @@ -5536,7 +5536,7 @@ snapshots: dependencies: bytes: 3.1.2 http-errors: 2.0.1 - iconv-lite: 0.7.1 + iconv-lite: 0.7.2 unpipe: 1.0.0 react-is@17.0.2: diff --git a/src/cli/gateway.sigterm.test.ts b/src/cli/gateway.sigterm.test.ts index 533cd06f4..5d722cf16 100644 --- a/src/cli/gateway.sigterm.test.ts +++ b/src/cli/gateway.sigterm.test.ts @@ -90,8 +90,10 @@ describe("gateway SIGTERM", () => { const err: string[] = []; child = spawn( - "bun", + process.execPath, [ + "--import", + "tsx", "src/index.ts", "gateway", "--port", diff --git a/src/providers/google-shared.test.ts b/src/providers/google-shared.test.ts index fef51a316..80d7f3889 100644 --- a/src/providers/google-shared.test.ts +++ b/src/providers/google-shared.test.ts @@ -27,7 +27,7 @@ const makeModel = (id: string): Model<"google-generative-ai"> => }) as Model<"google-generative-ai">; describe("google-shared convertTools", () => { - it("adds type:object when properties/required exist but type is missing", () => { + it("preserves parameters when type is missing", () => { const tools = [ { name: "noType", @@ -46,12 +46,12 @@ describe("google-shared convertTools", () => { converted?.[0]?.functionDeclarations?.[0]?.parameters, ); - expect(params.type).toBe("object"); + expect(params.type).toBeUndefined(); expect(params.properties).toBeDefined(); expect(params.required).toEqual(["action"]); }); - it("strips unsupported JSON Schema keywords", () => { + it("keeps unsupported JSON Schema keywords intact", () => { const tools = [ { name: "example", @@ -93,11 +93,11 @@ describe("google-shared convertTools", () => { const list = asRecord(properties.list); const items = asRecord(list.items); - expect(params).not.toHaveProperty("patternProperties"); - expect(params).not.toHaveProperty("additionalProperties"); - expect(mode).not.toHaveProperty("const"); - expect(options).not.toHaveProperty("anyOf"); - expect(items).not.toHaveProperty("const"); + expect(params).toHaveProperty("patternProperties"); + expect(params).toHaveProperty("additionalProperties"); + expect(mode).toHaveProperty("const"); + expect(options).toHaveProperty("anyOf"); + expect(items).toHaveProperty("const"); expect(params.required).toEqual(["mode"]); }); @@ -147,7 +147,7 @@ describe("google-shared convertTools", () => { }); describe("google-shared convertMessages", () => { - it("skips thinking blocks for Gemini to avoid mimicry", () => { + it("keeps thinking blocks when provider/model match", () => { const model = makeModel("gemini-1.5-pro"); const context = { messages: [ @@ -184,7 +184,13 @@ describe("google-shared convertMessages", () => { } as unknown as Context; const contents = convertMessages(model, context); - expect(contents).toHaveLength(0); + expect(contents).toHaveLength(1); + expect(contents[0].role).toBe("model"); + expect(contents[0].parts).toHaveLength(1); + expect(contents[0].parts?.[0]).toMatchObject({ + thought: true, + thoughtSignature: "sig", + }); }); it("keeps thought signatures for Claude models", () => { @@ -232,7 +238,7 @@ describe("google-shared convertMessages", () => { }); }); - it("merges consecutive user messages to satisfy Gemini role alternation", () => { + it("does not merge consecutive user messages for Gemini", () => { const model = makeModel("gemini-1.5-pro"); const context = { messages: [ @@ -248,12 +254,12 @@ describe("google-shared convertMessages", () => { } as unknown as Context; const contents = convertMessages(model, context); - expect(contents).toHaveLength(1); + expect(contents).toHaveLength(2); expect(contents[0].role).toBe("user"); - expect(contents[0].parts).toHaveLength(2); + expect(contents[1].role).toBe("user"); }); - it("merges consecutive user messages for non-Gemini Google models", () => { + it("does not merge consecutive user messages for non-Gemini Google models", () => { const model = makeModel("claude-3-opus"); const context = { messages: [ @@ -269,12 +275,12 @@ describe("google-shared convertMessages", () => { } as unknown as Context; const contents = convertMessages(model, context); - expect(contents).toHaveLength(1); + expect(contents).toHaveLength(2); expect(contents[0].role).toBe("user"); - expect(contents[0].parts).toHaveLength(2); + expect(contents[1].role).toBe("user"); }); - it("merges consecutive model messages to satisfy Gemini role alternation", () => { + it("does not merge consecutive model messages for Gemini", () => { const model = makeModel("gemini-1.5-pro"); const context = { messages: [ @@ -332,10 +338,10 @@ describe("google-shared convertMessages", () => { } as unknown as Context; const contents = convertMessages(model, context); - expect(contents).toHaveLength(2); + expect(contents).toHaveLength(3); expect(contents[0].role).toBe("user"); expect(contents[1].role).toBe("model"); - expect(contents[1].parts).toHaveLength(2); + expect(contents[2].role).toBe("model"); }); it("handles user message after tool result without model response in between", () => { @@ -392,10 +398,11 @@ describe("google-shared convertMessages", () => { } as unknown as Context; const contents = convertMessages(model, context); - expect(contents).toHaveLength(3); + expect(contents).toHaveLength(4); expect(contents[0].role).toBe("user"); expect(contents[1].role).toBe("model"); expect(contents[2].role).toBe("user"); + expect(contents[3].role).toBe("user"); const toolResponsePart = contents[2].parts?.find( (part) => typeof part === "object" && part !== null && "functionResponse" in part, @@ -469,10 +476,11 @@ describe("google-shared convertMessages", () => { } as unknown as Context; const contents = convertMessages(model, context); - expect(contents).toHaveLength(2); + expect(contents).toHaveLength(3); expect(contents[0].role).toBe("user"); expect(contents[1].role).toBe("model"); - const toolCallPart = contents[1].parts?.find( + expect(contents[2].role).toBe("model"); + const toolCallPart = contents[2].parts?.find( (part) => typeof part === "object" && part !== null && "functionCall" in part, );