@bolt-foundry/gambit 0.8.1 → 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 (53) hide show
  1. package/CHANGELOG.md +78 -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 +8 -4
  7. package/esm/mod.d.ts.map +1 -1
  8. package/esm/mod.js +6 -2
  9. package/esm/src/cli_utils.d.ts.map +1 -1
  10. package/esm/src/cli_utils.js +39 -3
  11. package/esm/src/openai_compat.d.ts +63 -0
  12. package/esm/src/openai_compat.d.ts.map +1 -0
  13. package/esm/src/openai_compat.js +277 -0
  14. package/esm/src/providers/google.d.ts +16 -0
  15. package/esm/src/providers/google.d.ts.map +1 -0
  16. package/esm/src/providers/google.js +352 -0
  17. package/esm/src/providers/ollama.d.ts +17 -0
  18. package/esm/src/providers/ollama.d.ts.map +1 -0
  19. package/esm/src/providers/ollama.js +509 -0
  20. package/esm/src/providers/openrouter.d.ts +22 -0
  21. package/esm/src/providers/openrouter.d.ts.map +1 -0
  22. package/esm/src/providers/openrouter.js +592 -0
  23. package/esm/src/server.d.ts +2 -0
  24. package/esm/src/server.d.ts.map +1 -1
  25. package/esm/src/server.js +612 -29
  26. package/esm/src/trace.d.ts.map +1 -1
  27. package/esm/src/trace.js +2 -2
  28. package/package.json +3 -2
  29. package/script/gambit/simulator-ui/dist/bundle.js +4744 -4360
  30. package/script/gambit/simulator-ui/dist/bundle.js.map +4 -4
  31. package/script/gambit/simulator-ui/dist/favicon.ico +0 -0
  32. package/script/mod.d.ts +8 -4
  33. package/script/mod.d.ts.map +1 -1
  34. package/script/mod.js +13 -7
  35. package/script/src/cli_utils.d.ts.map +1 -1
  36. package/script/src/cli_utils.js +38 -2
  37. package/script/src/openai_compat.d.ts +63 -0
  38. package/script/src/openai_compat.d.ts.map +1 -0
  39. package/script/src/openai_compat.js +281 -0
  40. package/script/src/providers/google.d.ts +16 -0
  41. package/script/src/providers/google.d.ts.map +1 -0
  42. package/script/src/providers/google.js +359 -0
  43. package/script/src/providers/ollama.d.ts +17 -0
  44. package/script/src/providers/ollama.d.ts.map +1 -0
  45. package/script/src/providers/ollama.js +551 -0
  46. package/script/src/providers/openrouter.d.ts +22 -0
  47. package/script/src/providers/openrouter.d.ts.map +1 -0
  48. package/script/src/providers/openrouter.js +632 -0
  49. package/script/src/server.d.ts +2 -0
  50. package/script/src/server.d.ts.map +1 -1
  51. package/script/src/server.js +612 -29
  52. package/script/src/trace.d.ts.map +1 -1
  53. package/script/src/trace.js +2 -2
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 "@bolt-foundry/gambit-core";
38
+ export { chatCompletionsWithDeck } from "./src/openai_compat.js";
39
39
  /** OpenAI-compatible request payload. */
40
- export type { ChatCompletionsRequest } from "@bolt-foundry/gambit-core";
40
+ export type { ChatCompletionsRequest } from "./src/openai_compat.js";
41
41
  /** OpenAI-compatible response payload. */
42
- export type { ChatCompletionsResponse } from "@bolt-foundry/gambit-core";
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. */
@@ -47,7 +47,11 @@ export type { RenderDeckOptions } from "@bolt-foundry/gambit-core";
47
47
  /** Result data from rendering a deck. */
48
48
  export type { RenderDeckResult } from "@bolt-foundry/gambit-core";
49
49
  /** Provider factory for OpenRouter-backed model calls. */
50
- export { createOpenRouterProvider } from "@bolt-foundry/gambit-core";
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,2BAA2B,CAAC;AACpE,yCAAyC;AACzC,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,0CAA0C;AAC1C,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,+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,2BAA2B,CAAC;AACrE,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 "@bolt-foundry/gambit-core";
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
- export { createOpenRouterProvider } from "@bolt-foundry/gambit-core";
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 +1 @@
1
- {"version":3,"file":"cli_utils.d.ts","sourceRoot":"","sources":["../../src/src/cli_utils.ts"],"names":[],"mappings":"AAGA,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,CAe/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;
@@ -106,11 +106,20 @@ export function findLastAssistantMessage(messages) {
106
106
  return undefined;
107
107
  }
108
108
  export function extractContextInput(state) {
109
- if (!state?.messages)
109
+ if (!state)
110
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
+ ]);
111
120
  for (let i = state.messages.length - 1; i >= 0; i--) {
112
121
  const msg = state.messages[i];
113
- if (msg.role === "tool" && msg.name === GAMBIT_TOOL_INIT) {
122
+ if (msg.role === "tool" && contextToolNames.has(msg.name ?? "")) {
114
123
  const content = msg.content;
115
124
  if (typeof content !== "string")
116
125
  return undefined;
@@ -124,3 +133,30 @@ export function extractContextInput(state) {
124
133
  }
125
134
  return undefined;
126
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"}