@memberjunction/unit-testing 6.1.0-edge.6 → 6.1.0-edge.7

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.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @fileoverview Shared native-tool-calling conformance suite for `BaseLLM` drivers.
3
+ *
4
+ * WHY THIS IS SEPARATE FROM `llm-conformance.ts`: that suite drives the streaming / cancellation /
5
+ * failure template method, and adopting it requires scripting a vendor mock for all of those paths.
6
+ * The tool-calling contract is independent of them and much cheaper to adopt, so it ships as its own
7
+ * entry point — a driver can conform on tools without first conforming on streaming. Run both when
8
+ * a provider has configs for both; they register separate `describe` blocks and do not interact.
9
+ *
10
+ * WHAT THIS ASSERTS — the parts of the tool contract that are the SAME for every provider, because
11
+ * they live in `BaseLLM` and in the normalized `ChatResult` shape rather than in any SDK mapping:
12
+ *
13
+ * - `SupportsTools` reports the driver's real capability (a CODE-level fact: "has the mapping been
14
+ * written?", distinct from the metadata capability flag `LLM.SupportsNativeToolCalling`).
15
+ * - A tool-call turn normalizes to `ChatCompletionMessage.toolCalls` with **parsed** arguments —
16
+ * never a JSON string, whatever the wire format was.
17
+ * - Such a turn reports `finish_reason === 'tool_calls'`.
18
+ * - Text and tool calls coexist: a turn carrying both surfaces both, and a turn carrying only
19
+ * calls is a SUCCESS with empty content — not a "no output from model" failure.
20
+ * - An ordinary turn is untouched: no `toolCalls`, and the driver's own finish reason preserved.
21
+ * - Streaming plus tools takes the non-streaming path and flags `streamingSuppressedForTools`
22
+ * (native tool calling is non-streaming only).
23
+ * - An orphaned tool result — one whose call was never declared by an earlier assistant turn —
24
+ * is rejected at the MJ boundary rather than at the provider.
25
+ *
26
+ * Provider-SPECIFIC request mapping (Anthropic `input_schema` vs OpenAI `parameters` vs Gemini
27
+ * `parametersJsonSchema`; `tool_choice` vocabularies; how results are shaped into the history) stays
28
+ * in each driver's own test file — there is no shared truth to assert about it.
29
+ *
30
+ * A driver that does NOT implement tools passes `SupportsTools: false` and gets the negative
31
+ * contract asserted instead: it declares false, and declaring tools to it is harmless.
32
+ *
33
+ * HOW A PROVIDER PACKAGE USES IT:
34
+ * ```ts
35
+ * import { RunLLMToolCallingConformanceSuite } from '@memberjunction/unit-testing';
36
+ *
37
+ * RunLLMToolCallingConformanceSuite({
38
+ * ProviderName: 'MyProvider',
39
+ * CreateLLM: () => buildLLMWithMockedVendorClient(),
40
+ * SupportsTools: true,
41
+ * ScriptToolCallResponse: (calls, text) => { ... },
42
+ * ScriptTextResponse: (text) => { ... },
43
+ * OrdinaryFinishReason: 'stop',
44
+ * });
45
+ * ```
46
+ *
47
+ * Same rules as the streaming suite: do NOT `vi.mock('@memberjunction/ai')` in a file that runs
48
+ * this — the point is to drive the REAL `BaseLLM` and the REAL normalized result types. Mock only
49
+ * the vendor SDK seam.
50
+ */
51
+ import type { BaseLLM } from '@memberjunction/ai';
52
+ /** One tool call a scripted vendor response should report. */
53
+ export interface ScriptedToolCall {
54
+ /** Provider call id. Drivers that synthesize ids (Gemini) may ignore this. */
55
+ Id: string;
56
+ /** Tool name — matches a declared {@link ChatTool.name}. */
57
+ Name: string;
58
+ /** Arguments as a structured object; the mock renders them in its own wire format. */
59
+ Arguments: Record<string, unknown>;
60
+ }
61
+ export interface LLMToolConformanceSuiteConfig {
62
+ /** Human-readable provider name, used in describe() labels. */
63
+ ProviderName: string;
64
+ /**
65
+ * Construct a fresh driver instance wired to the scriptable vendor mock. Called in beforeEach,
66
+ * so every test gets a clean instance.
67
+ */
68
+ CreateLLM: () => BaseLLM;
69
+ /** Whether the driver implements the tool mapping (asserted against `SupportsTools`). */
70
+ SupportsTools: boolean;
71
+ /**
72
+ * Program the vendor mock: the next call returns these tool calls, plus `text` when the
73
+ * provider is also emitting prose on the same turn. Required when `SupportsTools` is true.
74
+ *
75
+ * The mock must render the calls the way its SDK really does — OpenAI's JSON-STRING arguments,
76
+ * Anthropic's parsed `input`, Gemini's `functionCall` parts — because turning that back into
77
+ * parsed arguments is exactly what the suite is checking.
78
+ */
79
+ ScriptToolCallResponse?: (calls: ScriptedToolCall[], text?: string) => void;
80
+ /** Program the vendor mock: the next call returns an ordinary text answer, no tool calls. */
81
+ ScriptTextResponse?: (text: string) => void;
82
+ /**
83
+ * The `finish_reason` this driver reports on an ordinary (non-tool) turn — `'stop'` for the
84
+ * OpenAI family, `'completed'` for Anthropic, `'STOP'` for Gemini.
85
+ *
86
+ * That these differ at all is a known gap: `finish_reason` is typed as a bare `string` and has
87
+ * never been normalized across drivers. Native tool calling adds the FIRST normalized value
88
+ * (`'tool_calls'`); the rest is captured here rather than papered over, so the inconsistency is
89
+ * visible in one place.
90
+ *
91
+ * Tracked in MemberJunction/MJ#4335. When that lands, every driver reports the same value here
92
+ * and this knob should be deleted rather than updated.
93
+ */
94
+ OrdinaryFinishReason?: string;
95
+ }
96
+ /**
97
+ * Run the shared native-tool-calling conformance suite against one provider driver. Registers a
98
+ * full `describe` block — call it at the top level of a provider test file.
99
+ */
100
+ export declare function RunLLMToolCallingConformanceSuite(config: LLMToolConformanceSuiteConfig): void;
101
+ //# sourceMappingURL=llm-tool-conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-tool-conformance.d.ts","sourceRoot":"","sources":["../../src/ai/llm-tool-conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAmD,MAAM,oBAAoB,CAAC;AAGnG,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC7B,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,6BAA6B;IAC1C,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC;IAEzB,yFAAyF;IACzF,aAAa,EAAE,OAAO,CAAC;IAEvB;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAE5E,6FAA6F;IAC7F,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAE5C;;;;;;;;;;;OAWG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACjC;AA8BD;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,6BAA6B,GAAG,IAAI,CAwK7F"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * @fileoverview Shared native-tool-calling conformance suite for `BaseLLM` drivers.
3
+ *
4
+ * WHY THIS IS SEPARATE FROM `llm-conformance.ts`: that suite drives the streaming / cancellation /
5
+ * failure template method, and adopting it requires scripting a vendor mock for all of those paths.
6
+ * The tool-calling contract is independent of them and much cheaper to adopt, so it ships as its own
7
+ * entry point — a driver can conform on tools without first conforming on streaming. Run both when
8
+ * a provider has configs for both; they register separate `describe` blocks and do not interact.
9
+ *
10
+ * WHAT THIS ASSERTS — the parts of the tool contract that are the SAME for every provider, because
11
+ * they live in `BaseLLM` and in the normalized `ChatResult` shape rather than in any SDK mapping:
12
+ *
13
+ * - `SupportsTools` reports the driver's real capability (a CODE-level fact: "has the mapping been
14
+ * written?", distinct from the metadata capability flag `LLM.SupportsNativeToolCalling`).
15
+ * - A tool-call turn normalizes to `ChatCompletionMessage.toolCalls` with **parsed** arguments —
16
+ * never a JSON string, whatever the wire format was.
17
+ * - Such a turn reports `finish_reason === 'tool_calls'`.
18
+ * - Text and tool calls coexist: a turn carrying both surfaces both, and a turn carrying only
19
+ * calls is a SUCCESS with empty content — not a "no output from model" failure.
20
+ * - An ordinary turn is untouched: no `toolCalls`, and the driver's own finish reason preserved.
21
+ * - Streaming plus tools takes the non-streaming path and flags `streamingSuppressedForTools`
22
+ * (native tool calling is non-streaming only).
23
+ * - An orphaned tool result — one whose call was never declared by an earlier assistant turn —
24
+ * is rejected at the MJ boundary rather than at the provider.
25
+ *
26
+ * Provider-SPECIFIC request mapping (Anthropic `input_schema` vs OpenAI `parameters` vs Gemini
27
+ * `parametersJsonSchema`; `tool_choice` vocabularies; how results are shaped into the history) stays
28
+ * in each driver's own test file — there is no shared truth to assert about it.
29
+ *
30
+ * A driver that does NOT implement tools passes `SupportsTools: false` and gets the negative
31
+ * contract asserted instead: it declares false, and declaring tools to it is harmless.
32
+ *
33
+ * HOW A PROVIDER PACKAGE USES IT:
34
+ * ```ts
35
+ * import { RunLLMToolCallingConformanceSuite } from '@memberjunction/unit-testing';
36
+ *
37
+ * RunLLMToolCallingConformanceSuite({
38
+ * ProviderName: 'MyProvider',
39
+ * CreateLLM: () => buildLLMWithMockedVendorClient(),
40
+ * SupportsTools: true,
41
+ * ScriptToolCallResponse: (calls, text) => { ... },
42
+ * ScriptTextResponse: (text) => { ... },
43
+ * OrdinaryFinishReason: 'stop',
44
+ * });
45
+ * ```
46
+ *
47
+ * Same rules as the streaming suite: do NOT `vi.mock('@memberjunction/ai')` in a file that runs
48
+ * this — the point is to drive the REAL `BaseLLM` and the REAL normalized result types. Mock only
49
+ * the vendor SDK seam.
50
+ */
51
+ import { describe, it, expect, beforeEach } from 'vitest';
52
+ import { ChatParams, ChatMessageRole } from '@memberjunction/ai';
53
+ /** The tool every scripted case declares — shape is irrelevant to the assertions, so keep it small. */
54
+ const WEATHER_TOOL = {
55
+ name: 'get_weather',
56
+ description: 'Call this when the user asks about the weather.',
57
+ inputSchema: {
58
+ type: 'object',
59
+ properties: { city: { type: 'string', description: 'City name' } },
60
+ required: ['city']
61
+ }
62
+ };
63
+ const TOOL_CALL = { Id: 'call_conformance_1', Name: 'get_weather', Arguments: { city: 'NYC' } };
64
+ function buildToolParams(overrides = {}) {
65
+ const params = new ChatParams();
66
+ params.model = 'conformance-test-model';
67
+ params.messages = [{ role: ChatMessageRole.user, content: 'What is the weather in NYC?' }];
68
+ params.tools = [WEATHER_TOOL];
69
+ Object.assign(params, overrides);
70
+ return params;
71
+ }
72
+ /** The single choice of a result, asserting the shape on the way. */
73
+ function firstChoice(result) {
74
+ expect(result.data.choices.length).toBeGreaterThanOrEqual(1);
75
+ return result.data.choices[0];
76
+ }
77
+ /**
78
+ * Run the shared native-tool-calling conformance suite against one provider driver. Registers a
79
+ * full `describe` block — call it at the top level of a provider test file.
80
+ */
81
+ export function RunLLMToolCallingConformanceSuite(config) {
82
+ if (config.SupportsTools && (!config.ScriptToolCallResponse || !config.ScriptTextResponse)) {
83
+ throw new Error(`${config.ProviderName}: ScriptToolCallResponse and ScriptTextResponse are required when SupportsTools is true.`);
84
+ }
85
+ describe(`${config.ProviderName} — BaseLLM native tool-calling conformance`, () => {
86
+ let llm;
87
+ beforeEach(() => {
88
+ llm = config.CreateLLM();
89
+ });
90
+ describe('capability declaration', () => {
91
+ it(`declares SupportsTools = ${config.SupportsTools}`, () => {
92
+ expect(llm.SupportsTools).toBe(config.SupportsTools);
93
+ });
94
+ });
95
+ if (!config.SupportsTools) {
96
+ describe('driver without the tool mapping', () => {
97
+ it('ignores declared tools rather than failing the request', async () => {
98
+ config.ScriptTextResponse?.('plain answer');
99
+ const result = await llm.ChatCompletion(buildToolParams());
100
+ expect(result.success).toBe(true);
101
+ expect(firstChoice(result).message.toolCalls).toBeUndefined();
102
+ });
103
+ });
104
+ return;
105
+ }
106
+ describe('response normalization', () => {
107
+ it('normalizes a tool call, with arguments PARSED rather than left as a JSON string', async () => {
108
+ config.ScriptToolCallResponse([TOOL_CALL]);
109
+ const result = await llm.ChatCompletion(buildToolParams());
110
+ expect(result.success).toBe(true);
111
+ const calls = firstChoice(result).message.toolCalls;
112
+ expect(calls).toHaveLength(1);
113
+ expect(calls[0].name).toBe('get_weather');
114
+ expect(calls[0].arguments).toEqual({ city: 'NYC' });
115
+ expect(typeof calls[0].id).toBe('string');
116
+ expect(calls[0].id.length).toBeGreaterThan(0);
117
+ });
118
+ it("reports finish_reason 'tool_calls' on a tool-call turn", async () => {
119
+ config.ScriptToolCallResponse([TOOL_CALL]);
120
+ const result = await llm.ChatCompletion(buildToolParams());
121
+ expect(firstChoice(result).finish_reason).toBe('tool_calls');
122
+ });
123
+ it('treats a text-free tool call as SUCCESS — a call is output, not a missing answer', async () => {
124
+ config.ScriptToolCallResponse([TOOL_CALL]);
125
+ const result = await llm.ChatCompletion(buildToolParams());
126
+ expect(result.success).toBe(true);
127
+ expect(result.errorMessage ?? '').not.toContain('No output received');
128
+ });
129
+ it('surfaces text AND tool calls together when the model emits both', async () => {
130
+ config.ScriptToolCallResponse([TOOL_CALL], 'Let me check that for you.');
131
+ const result = await llm.ChatCompletion(buildToolParams());
132
+ const choice = firstChoice(result);
133
+ expect(choice.message.content).toContain('Let me check that for you.');
134
+ expect(choice.message.toolCalls).toHaveLength(1);
135
+ });
136
+ it('normalizes several calls made in one turn, preserving order', async () => {
137
+ config.ScriptToolCallResponse([
138
+ TOOL_CALL,
139
+ { Id: 'call_conformance_2', Name: 'get_weather', Arguments: { city: 'Boston' } }
140
+ ]);
141
+ const result = await llm.ChatCompletion(buildToolParams());
142
+ const calls = firstChoice(result).message.toolCalls;
143
+ expect(calls).toHaveLength(2);
144
+ expect(calls.map(c => c.arguments.city)).toEqual(['NYC', 'Boston']);
145
+ });
146
+ it('leaves an ordinary turn untouched — no toolCalls, own finish reason preserved', async () => {
147
+ config.ScriptTextResponse('The weather is fine.');
148
+ const params = buildToolParams();
149
+ params.tools = undefined;
150
+ const result = await llm.ChatCompletion(params);
151
+ const choice = firstChoice(result);
152
+ expect(choice.message.toolCalls).toBeUndefined();
153
+ if (config.OrdinaryFinishReason !== undefined) {
154
+ expect(choice.finish_reason).toBe(config.OrdinaryFinishReason);
155
+ }
156
+ expect(choice.finish_reason).not.toBe('tool_calls');
157
+ });
158
+ });
159
+ describe('streaming is suppressed while tools are declared (non-streaming only)', () => {
160
+ it('takes the non-streaming path and flags the downgrade', async () => {
161
+ config.ScriptToolCallResponse([TOOL_CALL]);
162
+ const onContent = [];
163
+ const result = await llm.ChatCompletion(buildToolParams({
164
+ streaming: true,
165
+ streamingCallbacks: {
166
+ OnContent: (chunk) => { onContent.push(chunk); },
167
+ OnComplete: () => undefined,
168
+ OnError: () => undefined
169
+ }
170
+ }));
171
+ expect(result.modelSpecificResponseDetails?.streamingSuppressedForTools).toBe(true);
172
+ expect(onContent).toHaveLength(0);
173
+ expect(firstChoice(result).message.toolCalls).toHaveLength(1);
174
+ });
175
+ it('does not flag the downgrade when no tools are declared', async () => {
176
+ config.ScriptTextResponse('plain answer');
177
+ const params = buildToolParams();
178
+ params.tools = undefined;
179
+ const result = await llm.ChatCompletion(params);
180
+ expect(result.modelSpecificResponseDetails?.streamingSuppressedForTools).toBeUndefined();
181
+ });
182
+ });
183
+ describe('conversation validity guard', () => {
184
+ /** A history whose tool result answers a call no assistant turn ever declared. */
185
+ const orphanedHistory = () => ([
186
+ { role: ChatMessageRole.user, content: 'What is the weather in NYC?' },
187
+ // The assistant turn is missing its `toolCalls` — the mistake this guard exists for.
188
+ { role: ChatMessageRole.assistant, content: '' },
189
+ {
190
+ role: ChatMessageRole.tool,
191
+ content: [{ type: 'tool_result', content: '72F', toolCallId: 'call_conformance_1' }]
192
+ }
193
+ ]);
194
+ it('rejects a tool result whose call was never declared, naming the id', async () => {
195
+ config.ScriptToolCallResponse([TOOL_CALL]);
196
+ const params = buildToolParams();
197
+ params.messages = orphanedHistory();
198
+ await expect(llm.ChatCompletion(params)).rejects.toThrow(/call_conformance_1/);
199
+ });
200
+ it('accepts the same history once the assistant turn carries its toolCalls', async () => {
201
+ config.ScriptTextResponse('It is 72F in NYC.');
202
+ const params = buildToolParams();
203
+ const history = orphanedHistory();
204
+ history[1].toolCalls = [{ id: 'call_conformance_1', name: 'get_weather', arguments: { city: 'NYC' } }];
205
+ params.messages = history;
206
+ const result = await llm.ChatCompletion(params);
207
+ expect(result.success).toBe(true);
208
+ });
209
+ });
210
+ });
211
+ }
212
+ //# sourceMappingURL=llm-tool-conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-tool-conformance.js","sourceRoot":"","sources":["../../src/ai/llm-tool-conformance.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -7,5 +7,6 @@ export { TestLLM, registerTestLLM, type TestLLMOutcome } from './ai/test-llm.js'
7
7
  export { makeModelUsage, makeSuccessChatResult, makeFailedChatResult, makeDriverFailureChatResult, makeErrorInfo, makeChatParams, type ModelUsageOverrides, type SuccessChatResultOptions, type FailedChatResultOptions, } from './ai/chat-result-factories.js';
8
8
  export { VENDOR_TYPE, VENDOR, MODEL_TYPE, CONFIG, MODEL, makeModelVendor, makeModel, makePromptModel, buildRealisticCatalog, DEFAULT_CONFIGURED_DRIVERS, type FxVendorType, type FxVendor, type FxModelType, type FxConfiguration, type FxModelVendor, type FxModel, type FxPromptModel, type AICatalog, } from './ai/catalog-fixtures.js';
9
9
  export { RunLLMConformanceSuite, type ExpectedUsageCounts, type FailureSite, type LLMConformanceDeviationKind, type LLMConformanceDeviation, type LLMConformanceSuiteConfig, } from './ai/llm-conformance.js';
10
+ export { RunLLMToolCallingConformanceSuite, type ScriptedToolCall, type LLMToolConformanceSuiteConfig, } from './ai/llm-tool-conformance.js';
10
11
  export { CreateOpenAICompatibleSeamMock, type OpenAICompatibleSeam, type OpenAICompatibleChatClient, type OpenAICompatibleUsagePayload, type OpenAICompatibleResponsePayload, type OpenAICompatibleChunkPayload, type OpenAICompatibleRequestBody, type OpenAICompatibleRequestOptions, } from './ai/openai-compatible-seam.js';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,MAAM,YAAY,CAAC;AAGjC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,aAAa,EACb,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,WAAW,EACX,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,8BAA8B,EAC9B,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,GACpC,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,MAAM,YAAY,CAAC;AAGjC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,aAAa,EACb,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,WAAW,EACX,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,GAC/B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,iCAAiC,EACjC,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,EAC9B,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,EACpC,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,GACpC,MAAM,6BAA6B,CAAC"}
package/dist/index.js CHANGED
@@ -8,5 +8,7 @@ export { makeModelUsage, makeSuccessChatResult, makeFailedChatResult, makeDriver
8
8
  export { VENDOR_TYPE, VENDOR, MODEL_TYPE, CONFIG, MODEL, makeModelVendor, makeModel, makePromptModel, buildRealisticCatalog, DEFAULT_CONFIGURED_DRIVERS, } from './ai/catalog-fixtures.js';
9
9
  // ---- Shared BaseLLM streaming/ChatResult conformance suite (applied by provider packages) ----
10
10
  export { RunLLMConformanceSuite, } from './ai/llm-conformance.js';
11
+ // ---- Shared native-tool-calling conformance suite (applied by provider packages) ----
12
+ export { RunLLMToolCallingConformanceSuite, } from './ai/llm-tool-conformance.js';
11
13
  export { CreateOpenAICompatibleSeamMock, } from './ai/openai-compatible-seam.js';
12
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAA0B,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,4FAA4F;AAC5F,OAAO,EAAE,OAAO,EAAE,eAAe,EAAuB,MAAM,eAAe,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,aAAa,EACb,cAAc,GAIf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,WAAW,EACX,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,0BAA0B,GAS3B,MAAM,uBAAuB,CAAC;AAE/B,iGAAiG;AACjG,OAAO,EACL,sBAAsB,GAMvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,8BAA8B,GAQ/B,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAA0B,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,4FAA4F;AAC5F,OAAO,EAAE,OAAO,EAAE,eAAe,EAAuB,MAAM,eAAe,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,aAAa,EACb,cAAc,GAIf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,WAAW,EACX,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,0BAA0B,GAS3B,MAAM,uBAAuB,CAAC;AAE/B,iGAAiG;AACjG,OAAO,EACL,sBAAsB,GAMvB,MAAM,sBAAsB,CAAC;AAE9B,wFAAwF;AACxF,OAAO,EACL,iCAAiC,GAGlC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,GAQ/B,MAAM,6BAA6B,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/unit-testing",
3
3
  "type": "module",
4
- "version": "6.1.0-edge.6",
4
+ "version": "6.1.0-edge.7",
5
5
  "description": "MemberJunction: Unit testing utilities and mock infrastructure for Vitest",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -16,8 +16,8 @@
16
16
  "vitest": "^4.0.18"
17
17
  },
18
18
  "dependencies": {
19
- "@memberjunction/ai": "6.1.0-edge.6",
20
- "@memberjunction/global": "6.1.0-edge.6"
19
+ "@memberjunction/ai": "6.1.0-edge.7",
20
+ "@memberjunction/global": "6.1.0-edge.7"
21
21
  },
22
22
  "repository": {
23
23
  "type": "git",