@jambonz/llm 0.1.0 → 0.2.0
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.
- package/dist/index.cjs +92 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -1
- package/dist/test-kit/index.cjs +142 -22
- package/dist/test-kit/index.cjs.map +1 -1
- package/dist/test-kit/index.d.cts +2 -14
- package/dist/test-kit/index.d.ts +2 -14
- package/dist/test-kit/index.js +142 -22
- package/dist/test-kit/index.js.map +1 -1
- package/dist/{types-D8rgMCbi.d.cts → types-bq1XMi_T.d.cts} +23 -4
- package/dist/{types-D8rgMCbi.d.ts → types-bq1XMi_T.d.ts} +23 -4
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AdapterFactory, d as AuthKind, A as AuthSpec,
|
|
1
|
+
import { a as AdapterFactory, d as AuthKind, A as AuthSpec, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, l as LlmEvent, M as Message, o as ToolCallEvent, n as ModelInfo, b as AdapterManifest } from '../types-bq1XMi_T.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Named scenarios the harness must be able to stage. Each scenario configures
|
|
@@ -88,19 +88,6 @@ interface ContractHarness {
|
|
|
88
88
|
* (toolCallStart precedes toolCall) runs; if false, that check is skipped.
|
|
89
89
|
*/
|
|
90
90
|
emitsToolCallStart: boolean;
|
|
91
|
-
/**
|
|
92
|
-
* Construct an assistant `Message` (with `vendorRaw` populated in the shape
|
|
93
|
-
* THIS adapter expects back on re-submission) given a `toolCall` event the
|
|
94
|
-
* adapter previously emitted. Used by checks #13 and #20 to round-trip a
|
|
95
|
-
* realistic history through a subsequent `stream()` call.
|
|
96
|
-
*
|
|
97
|
-
* Implementation tip: set `vendorRaw` to the full vendor-native assistant
|
|
98
|
-
* message — the same shape your adapter puts in history after emitting a
|
|
99
|
-
* tool call during streaming.
|
|
100
|
-
*/
|
|
101
|
-
buildAssistantWithToolCall(tc: Extract<LlmEvent, {
|
|
102
|
-
type: 'toolCall';
|
|
103
|
-
}>): Message;
|
|
104
91
|
}
|
|
105
92
|
|
|
106
93
|
/**
|
|
@@ -142,6 +129,7 @@ declare class FakeAdapter implements LlmAdapter<ApiKeyAuth> {
|
|
|
142
129
|
constructor(state: FakeState);
|
|
143
130
|
init(auth: ApiKeyAuth, _client?: ClientOptions): void;
|
|
144
131
|
stream(req: PromptRequest): AsyncIterable<LlmEvent>;
|
|
132
|
+
appendAssistantToolCall(history: Message[], toolCalls: ReadonlyArray<ToolCallEvent>): Message[];
|
|
145
133
|
appendToolResult(history: Message[], toolCallId: string, result: unknown): Message[];
|
|
146
134
|
listAvailableModels(): Promise<ModelInfo[]>;
|
|
147
135
|
private ensureInitialized;
|
package/dist/test-kit/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AdapterFactory, d as AuthKind, A as AuthSpec,
|
|
1
|
+
import { a as AdapterFactory, d as AuthKind, A as AuthSpec, L as LlmAdapter, c as ApiKeyAuth, g as ClientOptions, P as PromptRequest, l as LlmEvent, M as Message, o as ToolCallEvent, n as ModelInfo, b as AdapterManifest } from '../types-bq1XMi_T.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Named scenarios the harness must be able to stage. Each scenario configures
|
|
@@ -88,19 +88,6 @@ interface ContractHarness {
|
|
|
88
88
|
* (toolCallStart precedes toolCall) runs; if false, that check is skipped.
|
|
89
89
|
*/
|
|
90
90
|
emitsToolCallStart: boolean;
|
|
91
|
-
/**
|
|
92
|
-
* Construct an assistant `Message` (with `vendorRaw` populated in the shape
|
|
93
|
-
* THIS adapter expects back on re-submission) given a `toolCall` event the
|
|
94
|
-
* adapter previously emitted. Used by checks #13 and #20 to round-trip a
|
|
95
|
-
* realistic history through a subsequent `stream()` call.
|
|
96
|
-
*
|
|
97
|
-
* Implementation tip: set `vendorRaw` to the full vendor-native assistant
|
|
98
|
-
* message — the same shape your adapter puts in history after emitting a
|
|
99
|
-
* tool call during streaming.
|
|
100
|
-
*/
|
|
101
|
-
buildAssistantWithToolCall(tc: Extract<LlmEvent, {
|
|
102
|
-
type: 'toolCall';
|
|
103
|
-
}>): Message;
|
|
104
91
|
}
|
|
105
92
|
|
|
106
93
|
/**
|
|
@@ -142,6 +129,7 @@ declare class FakeAdapter implements LlmAdapter<ApiKeyAuth> {
|
|
|
142
129
|
constructor(state: FakeState);
|
|
143
130
|
init(auth: ApiKeyAuth, _client?: ClientOptions): void;
|
|
144
131
|
stream(req: PromptRequest): AsyncIterable<LlmEvent>;
|
|
132
|
+
appendAssistantToolCall(history: Message[], toolCalls: ReadonlyArray<ToolCallEvent>): Message[];
|
|
145
133
|
appendToolResult(history: Message[], toolCallId: string, result: unknown): Message[];
|
|
146
134
|
listAvailableModels(): Promise<ModelInfo[]>;
|
|
147
135
|
private ensureInitialized;
|
package/dist/test-kit/index.js
CHANGED
|
@@ -173,6 +173,28 @@ async function* streamFromOpenAI(client, req, options) {
|
|
|
173
173
|
};
|
|
174
174
|
yield endEvent;
|
|
175
175
|
}
|
|
176
|
+
function appendOpenAIAssistantToolCall(history, toolCalls) {
|
|
177
|
+
const wireMessage = {
|
|
178
|
+
role: "assistant",
|
|
179
|
+
content: null,
|
|
180
|
+
tool_calls: toolCalls.map((tc) => ({
|
|
181
|
+
id: tc.id,
|
|
182
|
+
type: "function",
|
|
183
|
+
function: {
|
|
184
|
+
name: tc.name,
|
|
185
|
+
arguments: typeof tc.arguments === "string" ? tc.arguments : JSON.stringify(tc.arguments ?? {})
|
|
186
|
+
}
|
|
187
|
+
}))
|
|
188
|
+
};
|
|
189
|
+
return [
|
|
190
|
+
...history,
|
|
191
|
+
{
|
|
192
|
+
role: "assistant",
|
|
193
|
+
content: "",
|
|
194
|
+
vendorRaw: wireMessage
|
|
195
|
+
}
|
|
196
|
+
];
|
|
197
|
+
}
|
|
176
198
|
function appendOpenAIToolResult(history, toolCallId, result) {
|
|
177
199
|
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
178
200
|
const wireMessage = {
|
|
@@ -394,6 +416,9 @@ var OpenAIAdapter = class {
|
|
|
394
416
|
knownModels: openAIManifest.knownModels
|
|
395
417
|
});
|
|
396
418
|
}
|
|
419
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
420
|
+
return appendOpenAIAssistantToolCall(history, toolCalls);
|
|
421
|
+
}
|
|
397
422
|
appendToolResult(history, toolCallId, result) {
|
|
398
423
|
return appendOpenAIToolResult(history, toolCallId, result);
|
|
399
424
|
}
|
|
@@ -744,6 +769,25 @@ var AnthropicAdapter = class {
|
|
|
744
769
|
};
|
|
745
770
|
yield endEvent;
|
|
746
771
|
}
|
|
772
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
773
|
+
const wireMessage = {
|
|
774
|
+
role: "assistant",
|
|
775
|
+
content: toolCalls.map((tc) => ({
|
|
776
|
+
type: "tool_use",
|
|
777
|
+
id: tc.id,
|
|
778
|
+
name: tc.name,
|
|
779
|
+
input: tc.arguments ?? {}
|
|
780
|
+
}))
|
|
781
|
+
};
|
|
782
|
+
return [
|
|
783
|
+
...history,
|
|
784
|
+
{
|
|
785
|
+
role: "assistant",
|
|
786
|
+
content: "",
|
|
787
|
+
vendorRaw: wireMessage
|
|
788
|
+
}
|
|
789
|
+
];
|
|
790
|
+
}
|
|
747
791
|
appendToolResult(history, toolCallId, result) {
|
|
748
792
|
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
749
793
|
const wireMessage = {
|
|
@@ -959,6 +1003,25 @@ async function* streamFromGemini(client, req) {
|
|
|
959
1003
|
};
|
|
960
1004
|
yield endEvent;
|
|
961
1005
|
}
|
|
1006
|
+
function appendGeminiAssistantToolCall(history, toolCalls) {
|
|
1007
|
+
const wireMessage = {
|
|
1008
|
+
role: "model",
|
|
1009
|
+
parts: toolCalls.map((tc) => ({
|
|
1010
|
+
functionCall: {
|
|
1011
|
+
name: parseToolName(tc.id),
|
|
1012
|
+
args: tc.arguments ?? {}
|
|
1013
|
+
}
|
|
1014
|
+
}))
|
|
1015
|
+
};
|
|
1016
|
+
return [
|
|
1017
|
+
...history,
|
|
1018
|
+
{
|
|
1019
|
+
role: "assistant",
|
|
1020
|
+
content: "",
|
|
1021
|
+
vendorRaw: wireMessage
|
|
1022
|
+
}
|
|
1023
|
+
];
|
|
1024
|
+
}
|
|
962
1025
|
function appendGeminiToolResult(history, toolCallId, result) {
|
|
963
1026
|
const name = parseToolName(toolCallId);
|
|
964
1027
|
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
@@ -1181,6 +1244,9 @@ var GoogleAdapter = class {
|
|
|
1181
1244
|
stream(req) {
|
|
1182
1245
|
return streamFromGemini(this.ensureClient(), req);
|
|
1183
1246
|
}
|
|
1247
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
1248
|
+
return appendGeminiAssistantToolCall(history, toolCalls);
|
|
1249
|
+
}
|
|
1184
1250
|
appendToolResult(history, toolCallId, result) {
|
|
1185
1251
|
return appendGeminiToolResult(history, toolCallId, result);
|
|
1186
1252
|
}
|
|
@@ -1348,6 +1414,9 @@ var VertexGeminiAdapter = class {
|
|
|
1348
1414
|
stream(req) {
|
|
1349
1415
|
return streamFromGemini(this.ensureClient(), req);
|
|
1350
1416
|
}
|
|
1417
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
1418
|
+
return appendGeminiAssistantToolCall(history, toolCalls);
|
|
1419
|
+
}
|
|
1351
1420
|
appendToolResult(history, toolCallId, result) {
|
|
1352
1421
|
return appendGeminiToolResult(history, toolCallId, result);
|
|
1353
1422
|
}
|
|
@@ -1514,6 +1583,9 @@ var VertexOpenAIAdapter = class {
|
|
|
1514
1583
|
knownModels: vertexOpenAIManifest.knownModels
|
|
1515
1584
|
});
|
|
1516
1585
|
}
|
|
1586
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
1587
|
+
return appendOpenAIAssistantToolCall(history, toolCalls);
|
|
1588
|
+
}
|
|
1517
1589
|
appendToolResult(history, toolCallId, result) {
|
|
1518
1590
|
return appendOpenAIToolResult(history, toolCallId, result);
|
|
1519
1591
|
}
|
|
@@ -1906,6 +1978,26 @@ var BedrockAdapter = class {
|
|
|
1906
1978
|
};
|
|
1907
1979
|
yield endEvent;
|
|
1908
1980
|
}
|
|
1981
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
1982
|
+
const wireMessage = {
|
|
1983
|
+
role: "assistant",
|
|
1984
|
+
content: toolCalls.map((tc) => ({
|
|
1985
|
+
toolUse: {
|
|
1986
|
+
toolUseId: tc.id,
|
|
1987
|
+
name: tc.name,
|
|
1988
|
+
input: tc.arguments ?? {}
|
|
1989
|
+
}
|
|
1990
|
+
}))
|
|
1991
|
+
};
|
|
1992
|
+
return [
|
|
1993
|
+
...history,
|
|
1994
|
+
{
|
|
1995
|
+
role: "assistant",
|
|
1996
|
+
content: "",
|
|
1997
|
+
vendorRaw: wireMessage
|
|
1998
|
+
}
|
|
1999
|
+
];
|
|
2000
|
+
}
|
|
1909
2001
|
appendToolResult(history, toolCallId, result) {
|
|
1910
2002
|
const text = typeof result === "string" ? result : JSON.stringify(result);
|
|
1911
2003
|
const wireMessage = {
|
|
@@ -2233,12 +2325,11 @@ function runContractTests(harness) {
|
|
|
2233
2325
|
(e) => e.type === "toolCall"
|
|
2234
2326
|
);
|
|
2235
2327
|
expect(tc).toBeDefined();
|
|
2236
|
-
const
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
expect(withResult.length).toBe(history.length + 1);
|
|
2328
|
+
const baseHistory = [{ role: "user", content: "call it" }];
|
|
2329
|
+
const afterAssistant = adapter.appendAssistantToolCall(baseHistory, [tc]);
|
|
2330
|
+
expect(afterAssistant.length).toBe(baseHistory.length + 1);
|
|
2331
|
+
const withResult = adapter.appendToolResult(afterAssistant, tc.id, { ok: true });
|
|
2332
|
+
expect(withResult.length).toBe(afterAssistant.length + 1);
|
|
2242
2333
|
await harness.mockScenario("simple-stream");
|
|
2243
2334
|
await expect(
|
|
2244
2335
|
drainStream(adapter, {
|
|
@@ -2326,11 +2417,11 @@ function runContractTests(harness) {
|
|
|
2326
2417
|
(e) => e.type === "toolCall"
|
|
2327
2418
|
);
|
|
2328
2419
|
expect(tc).toBeDefined();
|
|
2329
|
-
const
|
|
2330
|
-
{ role: "user", content: "go" },
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
const withResult = adapter.appendToolResult(
|
|
2420
|
+
const afterAssistant = adapter.appendAssistantToolCall(
|
|
2421
|
+
[{ role: "user", content: "go" }],
|
|
2422
|
+
[tc]
|
|
2423
|
+
);
|
|
2424
|
+
const withResult = adapter.appendToolResult(afterAssistant, tc.id, { ok: true });
|
|
2334
2425
|
await harness.mockScenario("simple-stream");
|
|
2335
2426
|
await drainStream(adapter, {
|
|
2336
2427
|
model: harness.toolCapableModel,
|
|
@@ -2340,6 +2431,28 @@ function runContractTests(harness) {
|
|
|
2340
2431
|
expect(captured).not.toBeNull();
|
|
2341
2432
|
expect(captured.vendorRawHonored).toBe(true);
|
|
2342
2433
|
});
|
|
2434
|
+
it("[21] appendAssistantToolCall output + appendToolResult re-stream preserves tool-call id on wire", async () => {
|
|
2435
|
+
await harness.mockScenario("tool-call");
|
|
2436
|
+
const adapter = await init(harness);
|
|
2437
|
+
const first = await drainStream(adapter, {
|
|
2438
|
+
model: harness.toolCapableModel,
|
|
2439
|
+
messages: [{ role: "user", content: "go" }],
|
|
2440
|
+
tools: [
|
|
2441
|
+
{ name: "test_tool", description: "x", parameters: { type: "object" } }
|
|
2442
|
+
]
|
|
2443
|
+
});
|
|
2444
|
+
const tc = first.find(
|
|
2445
|
+
(e) => e.type === "toolCall"
|
|
2446
|
+
);
|
|
2447
|
+
expect(tc).toBeDefined();
|
|
2448
|
+
const history = adapter.appendAssistantToolCall(
|
|
2449
|
+
[{ role: "user", content: "go" }],
|
|
2450
|
+
[tc]
|
|
2451
|
+
);
|
|
2452
|
+
const appended = history[history.length - 1];
|
|
2453
|
+
expect(appended.role).toBe("assistant");
|
|
2454
|
+
expect(appended.vendorRaw).toBeDefined();
|
|
2455
|
+
});
|
|
2343
2456
|
});
|
|
2344
2457
|
}
|
|
2345
2458
|
async function init(harness) {
|
|
@@ -2404,6 +2517,23 @@ var FakeAdapter = class {
|
|
|
2404
2517
|
throw new Error(`FakeAdapter: unknown scenario '${scenario}'`);
|
|
2405
2518
|
}
|
|
2406
2519
|
}
|
|
2520
|
+
appendAssistantToolCall(history, toolCalls) {
|
|
2521
|
+
return [
|
|
2522
|
+
...history,
|
|
2523
|
+
{
|
|
2524
|
+
role: "assistant",
|
|
2525
|
+
content: "",
|
|
2526
|
+
vendorRaw: {
|
|
2527
|
+
role: "assistant",
|
|
2528
|
+
toolCalls: toolCalls.map((tc) => ({
|
|
2529
|
+
id: tc.id,
|
|
2530
|
+
name: tc.name,
|
|
2531
|
+
arguments: tc.arguments
|
|
2532
|
+
}))
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
];
|
|
2536
|
+
}
|
|
2407
2537
|
appendToolResult(history, toolCallId, result) {
|
|
2408
2538
|
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
2409
2539
|
return [
|
|
@@ -2586,17 +2716,7 @@ function createFakeHarness() {
|
|
|
2586
2716
|
},
|
|
2587
2717
|
toolCapableModel: "fake-tool-model",
|
|
2588
2718
|
nonToolCapableModel: "fake-plain-model",
|
|
2589
|
-
emitsToolCallStart: true
|
|
2590
|
-
buildAssistantWithToolCall(tc) {
|
|
2591
|
-
return {
|
|
2592
|
-
role: "assistant",
|
|
2593
|
-
content: "",
|
|
2594
|
-
vendorRaw: {
|
|
2595
|
-
role: "assistant",
|
|
2596
|
-
toolCall: { id: tc.id, name: tc.name, arguments: tc.arguments }
|
|
2597
|
-
}
|
|
2598
|
-
};
|
|
2599
|
-
}
|
|
2719
|
+
emitsToolCallStart: true
|
|
2600
2720
|
};
|
|
2601
2721
|
}
|
|
2602
2722
|
export {
|