@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.
Files changed (61) hide show
  1. package/CHANGELOG.md +82 -2
  2. package/README.md +31 -9
  3. package/esm/gambit/simulator-ui/dist/bundle.js +4744 -4360
  4. package/esm/gambit/simulator-ui/dist/bundle.js.map +4 -4
  5. package/esm/gambit/simulator-ui/dist/favicon.ico +0 -0
  6. package/esm/mod.d.ts +7 -3
  7. package/esm/mod.d.ts.map +1 -1
  8. package/esm/mod.js +5 -1
  9. package/esm/src/cli_utils.d.ts +3 -2
  10. package/esm/src/cli_utils.d.ts.map +1 -1
  11. package/esm/src/cli_utils.js +43 -27
  12. package/esm/src/openai_compat.d.ts +63 -0
  13. package/esm/src/openai_compat.d.ts.map +1 -0
  14. package/esm/src/openai_compat.js +277 -0
  15. package/esm/src/providers/google.d.ts +16 -0
  16. package/esm/src/providers/google.d.ts.map +1 -0
  17. package/esm/src/providers/google.js +352 -0
  18. package/esm/src/providers/ollama.d.ts +17 -0
  19. package/esm/src/providers/ollama.d.ts.map +1 -0
  20. package/esm/src/providers/ollama.js +509 -0
  21. package/esm/src/providers/openrouter.d.ts +14 -1
  22. package/esm/src/providers/openrouter.d.ts.map +1 -1
  23. package/esm/src/providers/openrouter.js +460 -463
  24. package/esm/src/server.d.ts +4 -0
  25. package/esm/src/server.d.ts.map +1 -1
  26. package/esm/src/server.js +623 -164
  27. package/esm/src/trace.d.ts.map +1 -1
  28. package/esm/src/trace.js +3 -6
  29. package/package.json +2 -2
  30. package/script/gambit/simulator-ui/dist/bundle.js +4744 -4360
  31. package/script/gambit/simulator-ui/dist/bundle.js.map +4 -4
  32. package/script/gambit/simulator-ui/dist/favicon.ico +0 -0
  33. package/script/mod.d.ts +7 -3
  34. package/script/mod.d.ts.map +1 -1
  35. package/script/mod.js +9 -3
  36. package/script/src/cli_utils.d.ts +3 -2
  37. package/script/src/cli_utils.d.ts.map +1 -1
  38. package/script/src/cli_utils.js +42 -26
  39. package/script/src/openai_compat.d.ts +63 -0
  40. package/script/src/openai_compat.d.ts.map +1 -0
  41. package/script/src/openai_compat.js +281 -0
  42. package/script/src/providers/google.d.ts +16 -0
  43. package/script/src/providers/google.d.ts.map +1 -0
  44. package/script/src/providers/google.js +359 -0
  45. package/script/src/providers/ollama.d.ts +17 -0
  46. package/script/src/providers/ollama.d.ts.map +1 -0
  47. package/script/src/providers/ollama.js +551 -0
  48. package/script/src/providers/openrouter.d.ts +14 -1
  49. package/script/src/providers/openrouter.d.ts.map +1 -1
  50. package/script/src/providers/openrouter.js +461 -463
  51. package/script/src/server.d.ts +4 -0
  52. package/script/src/server.d.ts.map +1 -1
  53. package/script/src/server.js +623 -164
  54. package/script/src/trace.d.ts.map +1 -1
  55. package/script/src/trace.js +3 -6
  56. package/esm/src/compat/openai.d.ts +0 -2
  57. package/esm/src/compat/openai.d.ts.map +0 -1
  58. package/esm/src/compat/openai.js +0 -1
  59. package/script/src/compat/openai.d.ts +0 -2
  60. package/script/src/compat/openai.d.ts.map +0 -1
  61. package/script/src/compat/openai.js +0 -5
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/compat/openai.js";
38
+ export { chatCompletionsWithDeck } from "./src/openai_compat.js";
39
39
  /** OpenAI-compatible request payload. */
40
- export type { ChatCompletionsRequest } from "./src/compat/openai.js";
40
+ export type { ChatCompletionsRequest } from "./src/openai_compat.js";
41
41
  /** OpenAI-compatible response payload. */
42
- export type { ChatCompletionsResponse } from "./src/compat/openai.js";
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/compat/openai.js";
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";
@@ -1,4 +1,5 @@
1
- import type { OpenResponseItem, SavedState } from "@bolt-foundry/gambit-core";
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<OpenResponseItem>): string | undefined;
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":"AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,UAAU,EACX,MAAM,2BAA2B,CAAC;AAEnC,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;AAmBD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,GAChC,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAkB/D"}
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"}
@@ -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?.type === "message" && msg.role === "assistant") {
117
- if (typeof msg.content === "string")
118
- return msg.content;
119
- if (Array.isArray(msg.content)) {
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?.messages)
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.type === "message" && msg.role === "tool" &&
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"}