@bolt-foundry/gambit 0.8.0 → 0.8.3
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/CHANGELOG.md +82 -2
- package/README.md +31 -9
- package/esm/gambit/simulator-ui/dist/bundle.js +4744 -4360
- package/esm/gambit/simulator-ui/dist/bundle.js.map +4 -4
- package/esm/gambit/simulator-ui/dist/favicon.ico +0 -0
- package/esm/mod.d.ts +7 -3
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +5 -1
- package/esm/src/cli_utils.d.ts +3 -2
- package/esm/src/cli_utils.d.ts.map +1 -1
- package/esm/src/cli_utils.js +43 -27
- package/esm/src/openai_compat.d.ts +63 -0
- package/esm/src/openai_compat.d.ts.map +1 -0
- package/esm/src/openai_compat.js +277 -0
- package/esm/src/providers/google.d.ts +16 -0
- package/esm/src/providers/google.d.ts.map +1 -0
- package/esm/src/providers/google.js +352 -0
- package/esm/src/providers/ollama.d.ts +17 -0
- package/esm/src/providers/ollama.d.ts.map +1 -0
- package/esm/src/providers/ollama.js +509 -0
- package/esm/src/providers/openrouter.d.ts +14 -1
- package/esm/src/providers/openrouter.d.ts.map +1 -1
- package/esm/src/providers/openrouter.js +460 -463
- package/esm/src/server.d.ts +4 -0
- package/esm/src/server.d.ts.map +1 -1
- package/esm/src/server.js +623 -164
- package/esm/src/trace.d.ts.map +1 -1
- package/esm/src/trace.js +3 -6
- package/package.json +2 -2
- package/script/gambit/simulator-ui/dist/bundle.js +4744 -4360
- package/script/gambit/simulator-ui/dist/bundle.js.map +4 -4
- package/script/gambit/simulator-ui/dist/favicon.ico +0 -0
- package/script/mod.d.ts +7 -3
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +9 -3
- package/script/src/cli_utils.d.ts +3 -2
- package/script/src/cli_utils.d.ts.map +1 -1
- package/script/src/cli_utils.js +42 -26
- package/script/src/openai_compat.d.ts +63 -0
- package/script/src/openai_compat.d.ts.map +1 -0
- package/script/src/openai_compat.js +281 -0
- package/script/src/providers/google.d.ts +16 -0
- package/script/src/providers/google.d.ts.map +1 -0
- package/script/src/providers/google.js +359 -0
- package/script/src/providers/ollama.d.ts +17 -0
- package/script/src/providers/ollama.d.ts.map +1 -0
- package/script/src/providers/ollama.js +551 -0
- package/script/src/providers/openrouter.d.ts +14 -1
- package/script/src/providers/openrouter.d.ts.map +1 -1
- package/script/src/providers/openrouter.js +461 -463
- package/script/src/server.d.ts +4 -0
- package/script/src/server.d.ts.map +1 -1
- package/script/src/server.js +623 -164
- package/script/src/trace.d.ts.map +1 -1
- package/script/src/trace.js +3 -6
- package/esm/src/compat/openai.d.ts +0 -2
- package/esm/src/compat/openai.d.ts.map +0 -1
- package/esm/src/compat/openai.js +0 -1
- package/script/src/compat/openai.d.ts +0 -2
- package/script/src/compat/openai.d.ts.map +0 -1
- package/script/src/compat/openai.js +0 -5
|
Binary file
|
package/esm/mod.d.ts
CHANGED
|
@@ -35,11 +35,11 @@ export { runDeck } from "@bolt-foundry/gambit-core";
|
|
|
35
35
|
/** Signal for explicitly ending a Gambit run. */
|
|
36
36
|
export type { GambitEndSignal } from "@bolt-foundry/gambit-core";
|
|
37
37
|
/** OpenAI Chat Completions compatibility helper for a deck. */
|
|
38
|
-
export { chatCompletionsWithDeck } from "./src/
|
|
38
|
+
export { chatCompletionsWithDeck } from "./src/openai_compat.js";
|
|
39
39
|
/** OpenAI-compatible request payload. */
|
|
40
|
-
export type { ChatCompletionsRequest } from "./src/
|
|
40
|
+
export type { ChatCompletionsRequest } from "./src/openai_compat.js";
|
|
41
41
|
/** OpenAI-compatible response payload. */
|
|
42
|
-
export type { ChatCompletionsResponse } from "./src/
|
|
42
|
+
export type { ChatCompletionsResponse } from "./src/openai_compat.js";
|
|
43
43
|
/** Render a deck to a human-readable outline or debug view. */
|
|
44
44
|
export { renderDeck } from "@bolt-foundry/gambit-core";
|
|
45
45
|
/** Options for deck rendering. */
|
|
@@ -48,6 +48,10 @@ export type { RenderDeckOptions } from "@bolt-foundry/gambit-core";
|
|
|
48
48
|
export type { RenderDeckResult } from "@bolt-foundry/gambit-core";
|
|
49
49
|
/** Provider factory for OpenRouter-backed model calls. */
|
|
50
50
|
export { createOpenRouterProvider } from "./src/providers/openrouter.js";
|
|
51
|
+
/** Provider factory for Ollama-backed model calls. */
|
|
52
|
+
export { createOllamaProvider } from "./src/providers/ollama.js";
|
|
53
|
+
/** Provider factory for Google Gemini-backed model calls. */
|
|
54
|
+
export { createGoogleProvider } from "./src/providers/google.js";
|
|
51
55
|
/** Start the WebSocket simulator server for the Gambit UI. */
|
|
52
56
|
export { startWebSocketSimulator } from "./src/server.js";
|
|
53
57
|
//# sourceMappingURL=mod.d.ts.map
|
package/esm/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,yEAAyE;AACzE,OAAO,qBAAqB,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,oDAAoD;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,oCAAoC;AACpC,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,6BAA6B;AAC7B,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,6BAA6B;AAC7B,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,iCAAiC;AACjC,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,yCAAyC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,oCAAoC;AACpC,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,uCAAuC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,2DAA2D;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,iDAAiD;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,kCAAkC;AAClC,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,yDAAyD;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,kDAAkD;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,iDAAiD;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,+DAA+D;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,yCAAyC;AACzC,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,0CAA0C;AAC1C,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,+DAA+D;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,kCAAkC;AAClC,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,yCAAyC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,0DAA0D;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,8DAA8D;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,yEAAyE;AACzE,OAAO,qBAAqB,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,oDAAoD;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,oCAAoC;AACpC,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,6BAA6B;AAC7B,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,6BAA6B;AAC7B,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,iCAAiC;AACjC,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,yCAAyC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,oCAAoC;AACpC,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,uCAAuC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,2DAA2D;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,iDAAiD;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,kCAAkC;AAClC,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,yDAAyD;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,kDAAkD;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,iDAAiD;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,+DAA+D;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,yCAAyC;AACzC,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,0CAA0C;AAC1C,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,+DAA+D;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,kCAAkC;AAClC,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,yCAAyC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,0DAA0D;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,sDAAsD;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,6DAA6D;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,8DAA8D;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/esm/mod.js
CHANGED
|
@@ -13,10 +13,14 @@ export { isGambitEndSignal } from "@bolt-foundry/gambit-core";
|
|
|
13
13
|
/** Run a deck and return its execution result. */
|
|
14
14
|
export { runDeck } from "@bolt-foundry/gambit-core";
|
|
15
15
|
/** OpenAI Chat Completions compatibility helper for a deck. */
|
|
16
|
-
export { chatCompletionsWithDeck } from "./src/
|
|
16
|
+
export { chatCompletionsWithDeck } from "./src/openai_compat.js";
|
|
17
17
|
/** Render a deck to a human-readable outline or debug view. */
|
|
18
18
|
export { renderDeck } from "@bolt-foundry/gambit-core";
|
|
19
19
|
/** Provider factory for OpenRouter-backed model calls. */
|
|
20
20
|
export { createOpenRouterProvider } from "./src/providers/openrouter.js";
|
|
21
|
+
/** Provider factory for Ollama-backed model calls. */
|
|
22
|
+
export { createOllamaProvider } from "./src/providers/ollama.js";
|
|
23
|
+
/** Provider factory for Google Gemini-backed model calls. */
|
|
24
|
+
export { createGoogleProvider } from "./src/providers/google.js";
|
|
21
25
|
/** Start the WebSocket simulator server for the Gambit UI. */
|
|
22
26
|
export { startWebSocketSimulator } from "./src/server.js";
|
package/esm/src/cli_utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ModelMessage } from "@bolt-foundry/gambit-core";
|
|
2
|
+
import type { SavedState } from "@bolt-foundry/gambit-core";
|
|
2
3
|
export declare function parsePortValue(value: unknown, label?: string): number | undefined;
|
|
3
4
|
export declare function normalizeFlagList(value: string | Array<string> | undefined): Array<string>;
|
|
4
5
|
export declare function slugifyDeckPath(deckPath: string): string;
|
|
@@ -8,6 +9,6 @@ export declare function enrichStateMeta(state: SavedState, deckPath: string): Sa
|
|
|
8
9
|
export declare function parseContext(raw?: string): unknown;
|
|
9
10
|
export declare function parseMessage(raw?: string): unknown;
|
|
10
11
|
export declare function parseBotInput(raw?: string): unknown;
|
|
11
|
-
export declare function findLastAssistantMessage(messages: Array<
|
|
12
|
+
export declare function findLastAssistantMessage(messages: Array<ModelMessage>): string | undefined;
|
|
12
13
|
export declare function extractContextInput(state?: SavedState): unknown;
|
|
13
14
|
//# sourceMappingURL=cli_utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli_utils.d.ts","sourceRoot":"","sources":["../../src/src/cli_utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli_utils.d.ts","sourceRoot":"","sources":["../../src/src/cli_utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,KAAK,SAAS,GACb,MAAM,GAAG,SAAS,CAOpB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,SAAS,GACxC,KAAK,CAAC,MAAM,CAAC,CAGf;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD;AAuBD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQhE;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,GACf,UAAU,CAOZ;AAED,wBAAgB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED,wBAAgB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,GAC5B,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAuB/D"}
|
package/esm/src/cli_utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as dntShim from "../_dnt.shims.js";
|
|
2
2
|
import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
3
|
-
import { GAMBIT_TOOL_INIT } from "@bolt-foundry/gambit-core";
|
|
3
|
+
import { GAMBIT_TOOL_CONTEXT, GAMBIT_TOOL_INIT, } from "@bolt-foundry/gambit-core";
|
|
4
4
|
export function parsePortValue(value, label = "port") {
|
|
5
5
|
if (value === undefined || value === null || value === "")
|
|
6
6
|
return undefined;
|
|
@@ -94,43 +94,32 @@ export function parseBotInput(raw) {
|
|
|
94
94
|
return raw;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
function contentText(parts) {
|
|
98
|
-
return parts.map((part) => {
|
|
99
|
-
switch (part.type) {
|
|
100
|
-
case "input_text":
|
|
101
|
-
case "output_text":
|
|
102
|
-
case "text":
|
|
103
|
-
case "summary_text":
|
|
104
|
-
case "reasoning_text":
|
|
105
|
-
return part.text;
|
|
106
|
-
case "refusal":
|
|
107
|
-
return part.refusal;
|
|
108
|
-
default:
|
|
109
|
-
return "";
|
|
110
|
-
}
|
|
111
|
-
}).join("");
|
|
112
|
-
}
|
|
113
97
|
export function findLastAssistantMessage(messages) {
|
|
114
98
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
115
99
|
const msg = messages[i];
|
|
116
|
-
if (msg?.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return contentText(msg.content);
|
|
121
|
-
}
|
|
122
|
-
return JSON.stringify(msg.content ?? "");
|
|
100
|
+
if (msg?.role === "assistant") {
|
|
101
|
+
return typeof msg.content === "string"
|
|
102
|
+
? msg.content
|
|
103
|
+
: JSON.stringify(msg.content ?? "");
|
|
123
104
|
}
|
|
124
105
|
}
|
|
125
106
|
return undefined;
|
|
126
107
|
}
|
|
127
108
|
export function extractContextInput(state) {
|
|
128
|
-
if (!state
|
|
109
|
+
if (!state)
|
|
129
110
|
return undefined;
|
|
111
|
+
if (state.format === "responses" && Array.isArray(state.items)) {
|
|
112
|
+
return extractContextInputFromItems(state.items);
|
|
113
|
+
}
|
|
114
|
+
if (!state.messages)
|
|
115
|
+
return undefined;
|
|
116
|
+
const contextToolNames = new Set([
|
|
117
|
+
GAMBIT_TOOL_CONTEXT,
|
|
118
|
+
GAMBIT_TOOL_INIT,
|
|
119
|
+
]);
|
|
130
120
|
for (let i = state.messages.length - 1; i >= 0; i--) {
|
|
131
121
|
const msg = state.messages[i];
|
|
132
|
-
if (msg.
|
|
133
|
-
msg.name === GAMBIT_TOOL_INIT) {
|
|
122
|
+
if (msg.role === "tool" && contextToolNames.has(msg.name ?? "")) {
|
|
134
123
|
const content = msg.content;
|
|
135
124
|
if (typeof content !== "string")
|
|
136
125
|
return undefined;
|
|
@@ -144,3 +133,30 @@ export function extractContextInput(state) {
|
|
|
144
133
|
}
|
|
145
134
|
return undefined;
|
|
146
135
|
}
|
|
136
|
+
function extractContextInputFromItems(items) {
|
|
137
|
+
const contextToolNames = new Set([
|
|
138
|
+
GAMBIT_TOOL_CONTEXT,
|
|
139
|
+
GAMBIT_TOOL_INIT,
|
|
140
|
+
]);
|
|
141
|
+
const callNameById = new Map();
|
|
142
|
+
for (const item of items) {
|
|
143
|
+
if (item.type === "function_call") {
|
|
144
|
+
callNameById.set(item.call_id, item.name);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
148
|
+
const item = items[i];
|
|
149
|
+
if (item.type !== "function_call_output")
|
|
150
|
+
continue;
|
|
151
|
+
const name = callNameById.get(item.call_id);
|
|
152
|
+
if (!name || !contextToolNames.has(name))
|
|
153
|
+
continue;
|
|
154
|
+
try {
|
|
155
|
+
return JSON.parse(item.output);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return item.output;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Guardrails, ModelMessage, ModelProvider, ToolDefinition } from "@bolt-foundry/gambit-core";
|
|
2
|
+
export declare const logger: Console;
|
|
3
|
+
export type ChatCompletionsRequest = {
|
|
4
|
+
model: string;
|
|
5
|
+
messages: Array<{
|
|
6
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
7
|
+
content: string | null | Array<string | {
|
|
8
|
+
text?: string;
|
|
9
|
+
type?: string;
|
|
10
|
+
}>;
|
|
11
|
+
name?: string;
|
|
12
|
+
tool_call_id?: string;
|
|
13
|
+
tool_calls?: ModelMessage["tool_calls"];
|
|
14
|
+
}>;
|
|
15
|
+
tools?: Array<ToolDefinition>;
|
|
16
|
+
stream?: boolean;
|
|
17
|
+
temperature?: number;
|
|
18
|
+
top_p?: number;
|
|
19
|
+
frequency_penalty?: number;
|
|
20
|
+
presence_penalty?: number;
|
|
21
|
+
max_tokens?: number;
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
export type ChatCompletionsResponse = {
|
|
25
|
+
id: string;
|
|
26
|
+
object: "chat.completion";
|
|
27
|
+
created: number;
|
|
28
|
+
model: string;
|
|
29
|
+
choices: Array<{
|
|
30
|
+
index: number;
|
|
31
|
+
message: ModelMessage;
|
|
32
|
+
finish_reason: "stop" | "tool_calls" | "length";
|
|
33
|
+
logprobs: null;
|
|
34
|
+
}>;
|
|
35
|
+
usage?: {
|
|
36
|
+
prompt_tokens: number;
|
|
37
|
+
completion_tokens: number;
|
|
38
|
+
total_tokens: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Non-OpenAI extension field containing the full transcript and metadata.
|
|
42
|
+
* Most clients will ignore unknown fields.
|
|
43
|
+
*/
|
|
44
|
+
gambit?: {
|
|
45
|
+
deckPath: string;
|
|
46
|
+
messages: Array<ModelMessage>;
|
|
47
|
+
runId: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export declare function chatCompletionsWithDeck(args: {
|
|
51
|
+
deckPath: string;
|
|
52
|
+
request: ChatCompletionsRequest;
|
|
53
|
+
modelProvider: ModelProvider;
|
|
54
|
+
/**
|
|
55
|
+
* When true (default), Gambit will execute tool calls that match deck actions.
|
|
56
|
+
* Any other tool calls are returned to the caller as normal OpenAI tool calls.
|
|
57
|
+
*/
|
|
58
|
+
executeDeckTools?: boolean;
|
|
59
|
+
guardrails?: Partial<Guardrails>;
|
|
60
|
+
defaultModel?: string;
|
|
61
|
+
onStreamText?: (chunk: string) => void;
|
|
62
|
+
}): Promise<ChatCompletionsResponse>;
|
|
63
|
+
//# sourceMappingURL=openai_compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai_compat.d.ts","sourceRoot":"","sources":["../../src/src/openai_compat.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,UAAU,EAEV,YAAY,EACZ,aAAa,EACb,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,MAAM,SAAU,CAAC;AAO9B,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;QAC/C,OAAO,EACH,MAAM,GACN,IAAI,GACJ,KAAK,CAAC,MAAM,GAAG;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;KACzC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,YAAY,CAAC;QACtB,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,CAAC;QAChD,QAAQ,EAAE,IAAI,CAAC;KAChB,CAAC,CAAC;IACH,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;;OAGG;IACH,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AA8KF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,sBAAsB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAsJnC"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { assertZodSchema, DEFAULT_GUARDRAILS, loadDeck, RESERVED_TOOL_PREFIX, runDeck, toJsonSchema, } from "@bolt-foundry/gambit-core";
|
|
2
|
+
export const logger = console;
|
|
3
|
+
function randomId(prefix) {
|
|
4
|
+
const suffix = crypto.randomUUID().replace(/-/g, "").slice(0, 24);
|
|
5
|
+
return `${prefix}-${suffix}`;
|
|
6
|
+
}
|
|
7
|
+
function normalizeContent(content) {
|
|
8
|
+
if (content === null)
|
|
9
|
+
return null;
|
|
10
|
+
if (typeof content === "string")
|
|
11
|
+
return content;
|
|
12
|
+
if (!Array.isArray(content))
|
|
13
|
+
return String(content);
|
|
14
|
+
return content
|
|
15
|
+
.map((c) => (typeof c === "string" ? c : (c.text ?? "")))
|
|
16
|
+
.join("");
|
|
17
|
+
}
|
|
18
|
+
function normalizeMessages(input) {
|
|
19
|
+
return input.map((m) => ({
|
|
20
|
+
role: m.role,
|
|
21
|
+
content: normalizeContent(m.content),
|
|
22
|
+
name: m.name,
|
|
23
|
+
tool_call_id: m.tool_call_id,
|
|
24
|
+
tool_calls: m.tool_calls && m.tool_calls.length > 0
|
|
25
|
+
? m.tool_calls
|
|
26
|
+
: undefined,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
function providerParamsFromRequest(req) {
|
|
30
|
+
const out = {};
|
|
31
|
+
if (req.temperature !== undefined)
|
|
32
|
+
out.temperature = req.temperature;
|
|
33
|
+
if (req.top_p !== undefined)
|
|
34
|
+
out.top_p = req.top_p;
|
|
35
|
+
if (req.frequency_penalty !== undefined) {
|
|
36
|
+
out.frequency_penalty = req.frequency_penalty;
|
|
37
|
+
}
|
|
38
|
+
if (req.presence_penalty !== undefined) {
|
|
39
|
+
out.presence_penalty = req.presence_penalty;
|
|
40
|
+
}
|
|
41
|
+
if (req.max_tokens !== undefined)
|
|
42
|
+
out.max_tokens = req.max_tokens;
|
|
43
|
+
return Object.keys(out).length ? out : undefined;
|
|
44
|
+
}
|
|
45
|
+
function mergeToolDefs(gambitTools, externalTools) {
|
|
46
|
+
if (!externalTools?.length)
|
|
47
|
+
return gambitTools;
|
|
48
|
+
return [...gambitTools, ...externalTools];
|
|
49
|
+
}
|
|
50
|
+
function toolName(tool) {
|
|
51
|
+
return tool.function?.name ?? "";
|
|
52
|
+
}
|
|
53
|
+
function resolveContextSchema(deck) {
|
|
54
|
+
return deck.contextSchema ?? deck.inputSchema;
|
|
55
|
+
}
|
|
56
|
+
function resolveResponseSchema(deck) {
|
|
57
|
+
return deck.responseSchema ?? deck.outputSchema;
|
|
58
|
+
}
|
|
59
|
+
function assertNoToolNameCollisions(args) {
|
|
60
|
+
if (!args.externalTools?.length)
|
|
61
|
+
return;
|
|
62
|
+
const gambit = new Set(args.gambitTools.map(toolName));
|
|
63
|
+
for (const t of args.externalTools) {
|
|
64
|
+
const name = toolName(t);
|
|
65
|
+
if (!name)
|
|
66
|
+
continue;
|
|
67
|
+
if (name.startsWith(RESERVED_TOOL_PREFIX)) {
|
|
68
|
+
throw new Error(`External tool name ${name} is reserved (prefix ${RESERVED_TOOL_PREFIX})`);
|
|
69
|
+
}
|
|
70
|
+
if (gambit.has(name)) {
|
|
71
|
+
throw new Error(`Tool name collision for ${name} between Gambit deck actions and external tools`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function buildGambitActionTools(deck) {
|
|
76
|
+
const tools = [];
|
|
77
|
+
const toolNameSet = new Set();
|
|
78
|
+
const actionPathByName = new Map();
|
|
79
|
+
for (const action of deck.actionDecks) {
|
|
80
|
+
const child = await loadDeck(action.path, deck.path);
|
|
81
|
+
const contextSchema = resolveContextSchema(child);
|
|
82
|
+
const responseSchema = resolveResponseSchema(child);
|
|
83
|
+
if (!contextSchema || !responseSchema) {
|
|
84
|
+
throw new Error(`Deck ${child.path} must declare contextSchema and responseSchema (non-root)`);
|
|
85
|
+
}
|
|
86
|
+
assertZodSchema(contextSchema, "contextSchema");
|
|
87
|
+
assertZodSchema(responseSchema, "responseSchema");
|
|
88
|
+
const params = toJsonSchema(contextSchema);
|
|
89
|
+
tools.push({
|
|
90
|
+
type: "function",
|
|
91
|
+
function: {
|
|
92
|
+
name: action.name,
|
|
93
|
+
description: action.description,
|
|
94
|
+
parameters: params,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
toolNameSet.add(action.name);
|
|
98
|
+
actionPathByName.set(action.name, action.path);
|
|
99
|
+
}
|
|
100
|
+
return { tools, toolNameSet, actionPathByName };
|
|
101
|
+
}
|
|
102
|
+
function deckSystemPrompt(deck) {
|
|
103
|
+
const parts = [];
|
|
104
|
+
const prompt = deck.body ?? deck.prompt;
|
|
105
|
+
if (prompt)
|
|
106
|
+
parts.push(prompt.trim());
|
|
107
|
+
for (const card of deck.cards) {
|
|
108
|
+
if (card.body)
|
|
109
|
+
parts.push(card.body.trim());
|
|
110
|
+
}
|
|
111
|
+
return parts.join("\n\n").trim();
|
|
112
|
+
}
|
|
113
|
+
function shouldPrependDeckSystem(messages, systemPrompt) {
|
|
114
|
+
if (!systemPrompt)
|
|
115
|
+
return false;
|
|
116
|
+
if (!messages.length)
|
|
117
|
+
return true;
|
|
118
|
+
const hasExact = messages.some((m) => m.role === "system" && m.content === systemPrompt);
|
|
119
|
+
return !hasExact;
|
|
120
|
+
}
|
|
121
|
+
function warnIfSystemMismatch(args) {
|
|
122
|
+
if (!args.systemPrompt)
|
|
123
|
+
return;
|
|
124
|
+
const existing = args.provided.find((m) => m.role === "system");
|
|
125
|
+
if (!existing)
|
|
126
|
+
return;
|
|
127
|
+
if (existing.content === args.systemPrompt)
|
|
128
|
+
return;
|
|
129
|
+
logger.warn(`[gambit] chatCompletionsWithDeck: request includes a system message that does not match the deck prompt (${args.deckPath})`);
|
|
130
|
+
}
|
|
131
|
+
function toolResultContent(result) {
|
|
132
|
+
if (typeof result === "string")
|
|
133
|
+
return result;
|
|
134
|
+
try {
|
|
135
|
+
return JSON.stringify(result);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return String(result);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function normalizeError(err) {
|
|
142
|
+
return { message: err instanceof Error ? err.message : String(err) };
|
|
143
|
+
}
|
|
144
|
+
export async function chatCompletionsWithDeck(args) {
|
|
145
|
+
const executeDeckTools = args.executeDeckTools ?? true;
|
|
146
|
+
const guardrails = { ...DEFAULT_GUARDRAILS, ...args.guardrails };
|
|
147
|
+
const runId = randomId("run");
|
|
148
|
+
const deck = await loadDeck(args.deckPath);
|
|
149
|
+
const systemPrompt = deckSystemPrompt(deck);
|
|
150
|
+
const providedMessages = normalizeMessages(args.request.messages);
|
|
151
|
+
const messages = [];
|
|
152
|
+
warnIfSystemMismatch({
|
|
153
|
+
provided: providedMessages,
|
|
154
|
+
systemPrompt,
|
|
155
|
+
deckPath: deck.path,
|
|
156
|
+
});
|
|
157
|
+
if (shouldPrependDeckSystem(providedMessages, systemPrompt)) {
|
|
158
|
+
messages.push({ role: "system", content: systemPrompt });
|
|
159
|
+
}
|
|
160
|
+
messages.push(...providedMessages);
|
|
161
|
+
const gambit = await buildGambitActionTools(deck);
|
|
162
|
+
assertNoToolNameCollisions({
|
|
163
|
+
gambitTools: gambit.tools,
|
|
164
|
+
externalTools: args.request.tools,
|
|
165
|
+
});
|
|
166
|
+
const tools = mergeToolDefs(gambit.tools, args.request.tools);
|
|
167
|
+
const start = performance.now();
|
|
168
|
+
let passes = 0;
|
|
169
|
+
while (passes < guardrails.maxPasses) {
|
|
170
|
+
passes++;
|
|
171
|
+
if (performance.now() - start > guardrails.timeoutMs) {
|
|
172
|
+
throw new Error("Timeout exceeded");
|
|
173
|
+
}
|
|
174
|
+
const model = args.request.model ?? args.defaultModel ??
|
|
175
|
+
(() => {
|
|
176
|
+
throw new Error("No model provided");
|
|
177
|
+
})();
|
|
178
|
+
const result = await args.modelProvider.chat({
|
|
179
|
+
model,
|
|
180
|
+
messages,
|
|
181
|
+
tools: tools.length ? tools : undefined,
|
|
182
|
+
stream: Boolean(args.request.stream),
|
|
183
|
+
onStreamText: args.onStreamText,
|
|
184
|
+
params: providerParamsFromRequest(args.request),
|
|
185
|
+
});
|
|
186
|
+
messages.push(result.message);
|
|
187
|
+
if (result.toolCalls && result.toolCalls.length > 0) {
|
|
188
|
+
const gambitCalls = result.toolCalls.filter((c) => gambit.toolNameSet.has(c.name));
|
|
189
|
+
const externalCalls = result.toolCalls.filter((c) => !gambit.toolNameSet.has(c.name));
|
|
190
|
+
if (!executeDeckTools || externalCalls.length > 0) {
|
|
191
|
+
return {
|
|
192
|
+
id: randomId("chatcmpl"),
|
|
193
|
+
object: "chat.completion",
|
|
194
|
+
created: Math.floor(Date.now() / 1000),
|
|
195
|
+
model,
|
|
196
|
+
choices: [{
|
|
197
|
+
index: 0,
|
|
198
|
+
message: result.message,
|
|
199
|
+
finish_reason: "tool_calls",
|
|
200
|
+
logprobs: null,
|
|
201
|
+
}],
|
|
202
|
+
usage: result.usage
|
|
203
|
+
? {
|
|
204
|
+
prompt_tokens: result.usage.promptTokens,
|
|
205
|
+
completion_tokens: result.usage.completionTokens,
|
|
206
|
+
total_tokens: result.usage.totalTokens,
|
|
207
|
+
}
|
|
208
|
+
: undefined,
|
|
209
|
+
gambit: { deckPath: deck.path, messages, runId },
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
// Execute only deck-defined tool calls.
|
|
213
|
+
for (const call of gambitCalls) {
|
|
214
|
+
const actionPath = gambit.actionPathByName.get(call.name);
|
|
215
|
+
if (!actionPath)
|
|
216
|
+
continue;
|
|
217
|
+
try {
|
|
218
|
+
const childResult = await runDeck({
|
|
219
|
+
path: actionPath,
|
|
220
|
+
input: call.args,
|
|
221
|
+
modelProvider: args.modelProvider,
|
|
222
|
+
isRoot: false,
|
|
223
|
+
guardrails,
|
|
224
|
+
depth: 1,
|
|
225
|
+
parentActionCallId: call.id,
|
|
226
|
+
runId,
|
|
227
|
+
defaultModel: model,
|
|
228
|
+
modelOverride: undefined,
|
|
229
|
+
trace: undefined,
|
|
230
|
+
stream: Boolean(args.request.stream),
|
|
231
|
+
onStreamText: args.onStreamText,
|
|
232
|
+
inputProvided: true,
|
|
233
|
+
});
|
|
234
|
+
messages.push({
|
|
235
|
+
role: "tool",
|
|
236
|
+
name: call.name,
|
|
237
|
+
tool_call_id: call.id,
|
|
238
|
+
content: toolResultContent(childResult),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
messages.push({
|
|
243
|
+
role: "tool",
|
|
244
|
+
name: call.name,
|
|
245
|
+
tool_call_id: call.id,
|
|
246
|
+
content: JSON.stringify({ error: normalizeError(err) }),
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (result.finishReason === "tool_calls") {
|
|
253
|
+
throw new Error("Model requested tool_calls but provided none");
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
id: randomId("chatcmpl"),
|
|
257
|
+
object: "chat.completion",
|
|
258
|
+
created: Math.floor(Date.now() / 1000),
|
|
259
|
+
model,
|
|
260
|
+
choices: [{
|
|
261
|
+
index: 0,
|
|
262
|
+
message: result.message,
|
|
263
|
+
finish_reason: result.finishReason,
|
|
264
|
+
logprobs: null,
|
|
265
|
+
}],
|
|
266
|
+
usage: result.usage
|
|
267
|
+
? {
|
|
268
|
+
prompt_tokens: result.usage.promptTokens,
|
|
269
|
+
completion_tokens: result.usage.completionTokens,
|
|
270
|
+
total_tokens: result.usage.totalTokens,
|
|
271
|
+
}
|
|
272
|
+
: undefined,
|
|
273
|
+
gambit: { deckPath: deck.path, messages, runId },
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
throw new Error("Max passes exceeded without completing");
|
|
277
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ModelProvider } from "@bolt-foundry/gambit-core";
|
|
2
|
+
export declare const GOOGLE_PREFIX = "google/";
|
|
3
|
+
type OpenAIClient = {
|
|
4
|
+
chat: {
|
|
5
|
+
completions: {
|
|
6
|
+
create: (params: unknown) => Promise<unknown>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export declare function createGoogleProvider(opts: {
|
|
11
|
+
apiKey: string;
|
|
12
|
+
baseURL?: string;
|
|
13
|
+
client?: OpenAIClient;
|
|
14
|
+
}): ModelProvider;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/src/providers/google.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,aAAa,EAId,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,aAAa,YAAY,CAAC;AAIvC,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAC/C,CAAC;KACH,CAAC;CACH,CAAC;AAwIF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,aAAa,CA6RhB"}
|