@bolt-foundry/gambit 0.8.1 → 0.8.5-rc.10
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 +150 -2
- package/README.md +109 -23
- package/esm/_dnt.polyfills.d.ts +17 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -1
- package/esm/_dnt.polyfills.js +123 -0
- package/esm/deps/jsr.io/@std/collections/1.1.6/deep_merge.d.ts +322 -0
- package/esm/deps/jsr.io/@std/collections/1.1.6/deep_merge.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/collections/1.1.6/deep_merge.js +105 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_create_walk_entry.d.ts +14 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_create_walk_entry.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_create_walk_entry.js +34 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_get_file_info_type.d.ts +13 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_get_file_info_type.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_get_file_info_type.js +18 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_is_same_path.d.ts +10 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_is_same_path.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_is_same_path.js +17 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_is_subdir.d.ts +12 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_is_subdir.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_is_subdir.js +25 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_to_path_string.d.ts +9 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_to_path_string.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/_to_path_string.js +13 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/copy.d.ts +117 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/copy.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/copy.js +313 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/empty_dir.d.ts +48 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/empty_dir.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/empty_dir.js +87 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_dir.d.ts +49 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_dir.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_dir.js +102 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_file.d.ts +47 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_file.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_file.js +90 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_link.d.ts +49 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_link.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_link.js +61 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_symlink.d.ts +70 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_symlink.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/ensure_symlink.js +156 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/eol.d.ts +52 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/eol.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/eol.js +67 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/exists.d.ts +218 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/exists.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/exists.js +271 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/expand_glob.d.ts +267 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/expand_glob.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/expand_glob.js +442 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/mod.d.ts +29 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/mod.js +29 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/move.d.ts +86 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/move.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/move.js +142 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/walk.d.ts +777 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/walk.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/fs/1.0.23/walk.js +846 -0
- package/esm/deps/jsr.io/@std/json/1.0.3/types.d.ts +7 -0
- package/esm/deps/jsr.io/@std/json/1.0.3/types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/json/1.0.3/types.js +3 -0
- package/esm/deps/jsr.io/@std/jsonc/1.0.2/mod.d.ts +20 -0
- package/esm/deps/jsr.io/@std/jsonc/1.0.2/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/jsonc/1.0.2/mod.js +21 -0
- package/esm/deps/jsr.io/@std/jsonc/1.0.2/parse.d.ts +21 -0
- package/esm/deps/jsr.io/@std/jsonc/1.0.2/parse.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/jsonc/1.0.2/parse.js +320 -0
- package/esm/deps/jsr.io/@std/path/1.1.4/constants.d.ts +1 -1
- package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.d.ts +93 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.js +753 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/mod.d.ts +109 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/mod.js +110 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/parse.d.ts +21 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/parse.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/parse.js +25 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/stringify.d.ts +35 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/stringify.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/toml/1.0.11/stringify.js +283 -0
- package/esm/gambit/simulator-ui/dist/bundle.js +12670 -5471
- 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 +21 -7
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +14 -4
- package/esm/src/cli_utils.d.ts +1 -0
- package/esm/src/cli_utils.d.ts.map +1 -1
- package/esm/src/cli_utils.js +52 -4
- package/esm/src/default_runtime.d.ts +46 -0
- package/esm/src/default_runtime.d.ts.map +1 -0
- package/esm/src/default_runtime.js +415 -0
- package/esm/src/durable_streams.js +26 -1
- package/esm/src/model_matchers.d.ts +10 -0
- package/esm/src/model_matchers.d.ts.map +1 -0
- package/esm/src/model_matchers.js +26 -0
- package/esm/src/openai_compat.d.ts +74 -0
- package/esm/src/openai_compat.d.ts.map +1 -0
- package/esm/src/openai_compat.js +329 -0
- package/esm/src/project_config.d.ts +47 -0
- package/esm/src/project_config.d.ts.map +1 -0
- package/esm/src/project_config.js +134 -0
- package/esm/src/providers/codex.d.ts +37 -0
- package/esm/src/providers/codex.d.ts.map +1 -0
- package/esm/src/providers/codex.js +810 -0
- package/esm/src/providers/google.d.ts +18 -0
- package/esm/src/providers/google.d.ts.map +1 -0
- package/esm/src/providers/google.js +428 -0
- package/esm/src/providers/ollama.d.ts +19 -0
- package/esm/src/providers/ollama.d.ts.map +1 -0
- package/esm/src/providers/ollama.js +789 -0
- package/esm/src/providers/openrouter.d.ts +26 -0
- package/esm/src/providers/openrouter.d.ts.map +1 -0
- package/esm/src/providers/openrouter.js +886 -0
- package/esm/src/providers/router.d.ts +19 -0
- package/esm/src/providers/router.d.ts.map +1 -0
- package/esm/src/providers/router.js +93 -0
- package/esm/src/server.d.ts +11 -0
- package/esm/src/server.d.ts.map +1 -1
- package/esm/src/server.js +3927 -689
- package/esm/src/server_feedback_grading_routes.d.ts +32 -0
- package/esm/src/server_feedback_grading_routes.d.ts.map +1 -0
- package/esm/src/server_feedback_grading_routes.js +305 -0
- package/esm/src/server_helpers.d.ts +4 -0
- package/esm/src/server_helpers.d.ts.map +1 -0
- package/esm/src/server_helpers.js +46 -0
- package/esm/src/server_session_store.d.ts +87 -0
- package/esm/src/server_session_store.d.ts.map +1 -0
- package/esm/src/server_session_store.js +873 -0
- package/esm/src/server_types.d.ts +110 -0
- package/esm/src/server_types.d.ts.map +1 -0
- package/esm/src/server_types.js +1 -0
- package/esm/src/server_ui_routes.d.ts +33 -0
- package/esm/src/server_ui_routes.d.ts.map +1 -0
- package/esm/src/server_ui_routes.js +136 -0
- package/esm/src/session_artifacts.d.ts +22 -0
- package/esm/src/session_artifacts.d.ts.map +1 -0
- package/esm/src/session_artifacts.js +243 -0
- package/esm/src/trace.d.ts.map +1 -1
- package/esm/src/trace.js +8 -5
- package/esm/src/workspace.d.ts +19 -0
- package/esm/src/workspace.d.ts.map +1 -0
- package/esm/src/workspace.js +162 -0
- package/esm/src/workspace_contract.d.ts +78 -0
- package/esm/src/workspace_contract.d.ts.map +1 -0
- package/esm/src/workspace_contract.js +76 -0
- package/package.json +3 -2
- package/script/_dnt.polyfills.d.ts +17 -0
- package/script/_dnt.polyfills.d.ts.map +1 -1
- package/script/_dnt.polyfills.js +123 -0
- package/script/deps/jsr.io/@std/collections/1.1.6/deep_merge.d.ts +322 -0
- package/script/deps/jsr.io/@std/collections/1.1.6/deep_merge.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/collections/1.1.6/deep_merge.js +108 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_create_walk_entry.d.ts +14 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_create_walk_entry.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_create_walk_entry.js +71 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_get_file_info_type.d.ts +13 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_get_file_info_type.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_get_file_info_type.js +21 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_is_same_path.d.ts +10 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_is_same_path.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_is_same_path.js +20 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_is_subdir.d.ts +12 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_is_subdir.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_is_subdir.js +28 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_to_path_string.d.ts +9 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_to_path_string.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/_to_path_string.js +16 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/copy.d.ts +117 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/copy.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/copy.js +350 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/empty_dir.d.ts +48 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/empty_dir.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/empty_dir.js +124 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_dir.d.ts +49 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_dir.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_dir.js +139 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_file.d.ts +47 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_file.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_file.js +127 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_link.d.ts +49 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_link.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_link.js +98 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_symlink.d.ts +70 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_symlink.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/ensure_symlink.js +193 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/eol.d.ts +52 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/eol.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/eol.js +105 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/exists.d.ts +218 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/exists.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/exists.js +308 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/expand_glob.d.ts +267 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/expand_glob.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/expand_glob.js +479 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/mod.d.ts +29 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/mod.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/mod.js +45 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/move.d.ts +86 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/move.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/move.js +179 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/walk.d.ts +777 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/walk.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/fs/1.0.23/walk.js +883 -0
- package/script/deps/jsr.io/@std/json/1.0.3/types.d.ts +7 -0
- package/script/deps/jsr.io/@std/json/1.0.3/types.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/json/1.0.3/types.js +4 -0
- package/script/deps/jsr.io/@std/jsonc/1.0.2/mod.d.ts +20 -0
- package/script/deps/jsr.io/@std/jsonc/1.0.2/mod.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/jsonc/1.0.2/mod.js +37 -0
- package/script/deps/jsr.io/@std/jsonc/1.0.2/parse.d.ts +21 -0
- package/script/deps/jsr.io/@std/jsonc/1.0.2/parse.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/jsonc/1.0.2/parse.js +323 -0
- package/script/deps/jsr.io/@std/path/1.1.4/constants.d.ts +1 -1
- package/script/deps/jsr.io/@std/toml/1.0.11/_parser.d.ts +93 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/_parser.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/_parser.js +781 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/mod.d.ts +109 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/mod.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/mod.js +126 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/parse.d.ts +21 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/parse.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/parse.js +28 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/stringify.d.ts +35 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/stringify.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/toml/1.0.11/stringify.js +286 -0
- package/script/gambit/simulator-ui/dist/bundle.js +12670 -5471
- 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 +21 -7
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +22 -7
- package/script/src/cli_utils.d.ts +1 -0
- package/script/src/cli_utils.d.ts.map +1 -1
- package/script/src/cli_utils.js +52 -3
- package/script/src/default_runtime.d.ts +46 -0
- package/script/src/default_runtime.d.ts.map +1 -0
- package/script/src/default_runtime.js +452 -0
- package/script/src/durable_streams.js +26 -1
- package/script/src/model_matchers.d.ts +10 -0
- package/script/src/model_matchers.d.ts.map +1 -0
- package/script/src/model_matchers.js +29 -0
- package/script/src/openai_compat.d.ts +74 -0
- package/script/src/openai_compat.d.ts.map +1 -0
- package/script/src/openai_compat.js +366 -0
- package/script/src/project_config.d.ts +47 -0
- package/script/src/project_config.d.ts.map +1 -0
- package/script/src/project_config.js +173 -0
- package/script/src/providers/codex.d.ts +37 -0
- package/script/src/providers/codex.d.ts.map +1 -0
- package/script/src/providers/codex.js +850 -0
- package/script/src/providers/google.d.ts +18 -0
- package/script/src/providers/google.d.ts.map +1 -0
- package/script/src/providers/google.js +435 -0
- package/script/src/providers/ollama.d.ts +19 -0
- package/script/src/providers/ollama.d.ts.map +1 -0
- package/script/src/providers/ollama.js +831 -0
- package/script/src/providers/openrouter.d.ts +26 -0
- package/script/src/providers/openrouter.d.ts.map +1 -0
- package/script/src/providers/openrouter.js +926 -0
- package/script/src/providers/router.d.ts +19 -0
- package/script/src/providers/router.d.ts.map +1 -0
- package/script/src/providers/router.js +96 -0
- package/script/src/server.d.ts +11 -0
- package/script/src/server.d.ts.map +1 -1
- package/script/src/server.js +3931 -693
- package/script/src/server_feedback_grading_routes.d.ts +32 -0
- package/script/src/server_feedback_grading_routes.d.ts.map +1 -0
- package/script/src/server_feedback_grading_routes.js +343 -0
- package/script/src/server_helpers.d.ts +4 -0
- package/script/src/server_helpers.d.ts.map +1 -0
- package/script/src/server_helpers.js +84 -0
- package/script/src/server_session_store.d.ts +87 -0
- package/script/src/server_session_store.d.ts.map +1 -0
- package/script/src/server_session_store.js +910 -0
- package/script/src/server_types.d.ts +110 -0
- package/script/src/server_types.d.ts.map +1 -0
- package/script/src/server_types.js +2 -0
- package/script/src/server_ui_routes.d.ts +33 -0
- package/script/src/server_ui_routes.d.ts.map +1 -0
- package/script/src/server_ui_routes.js +173 -0
- package/script/src/session_artifacts.d.ts +22 -0
- package/script/src/session_artifacts.d.ts.map +1 -0
- package/script/src/session_artifacts.js +279 -0
- package/script/src/trace.d.ts.map +1 -1
- package/script/src/trace.js +8 -5
- package/script/src/workspace.d.ts +19 -0
- package/script/src/workspace.d.ts.map +1 -0
- package/script/src/workspace.js +199 -0
- package/script/src/workspace_contract.d.ts +78 -0
- package/script/src/workspace_contract.d.ts.map +1 -0
- package/script/src/workspace_contract.js +84 -0
|
@@ -128,5 +128,30 @@ export async function handleDurableStreamRequest(request) {
|
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
130
|
function formatSseEvent(event) {
|
|
131
|
-
|
|
131
|
+
const payload = normalizeSsePayload(event.data);
|
|
132
|
+
const type = payload.type;
|
|
133
|
+
return `id: ${event.offset}\nevent: ${type}\ndata: ${JSON.stringify(payload)}\n\n`;
|
|
134
|
+
}
|
|
135
|
+
function normalizeSsePayload(value) {
|
|
136
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
137
|
+
const record = value;
|
|
138
|
+
const rawType = typeof record.type === "string"
|
|
139
|
+
? record.type.trim()
|
|
140
|
+
: "gambit.event";
|
|
141
|
+
const type = sanitizeSseEventType(rawType);
|
|
142
|
+
return {
|
|
143
|
+
...record,
|
|
144
|
+
type,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
type: "gambit.event",
|
|
149
|
+
value,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function sanitizeSseEventType(value) {
|
|
153
|
+
if (!value)
|
|
154
|
+
return "gambit.event";
|
|
155
|
+
const normalized = value.replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
156
|
+
return normalized.length > 0 ? normalized : "gambit.event";
|
|
132
157
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProviderKey } from "./providers/router.js";
|
|
2
|
+
export type ProviderMatchers = {
|
|
3
|
+
isUnprefixedModel: (model: string) => boolean;
|
|
4
|
+
matchesOpenRouter: (model: string) => boolean;
|
|
5
|
+
matchesOllama: (model: string) => boolean;
|
|
6
|
+
matchesGoogle: (model: string) => boolean;
|
|
7
|
+
matchesCodex: (model: string) => boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function createProviderMatchers(effectiveFallbackProvider: ProviderKey | null): ProviderMatchers;
|
|
10
|
+
//# sourceMappingURL=model_matchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_matchers.d.ts","sourceRoot":"","sources":["../../src/src/model_matchers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASzD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,yBAAyB,EAAE,WAAW,GAAG,IAAI,GAC5C,gBAAgB,CAyBlB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { GOOGLE_PREFIX } from "./providers/google.js";
|
|
2
|
+
import { OLLAMA_PREFIX } from "./providers/ollama.js";
|
|
3
|
+
import { OPENROUTER_PREFIX } from "./providers/openrouter.js";
|
|
4
|
+
import { CODEX_PREFIX } from "./providers/codex.js";
|
|
5
|
+
const LEGACY_CODEX_PREFIX = "codex/";
|
|
6
|
+
const CODEX_PROVIDER_ALIAS = "codex-cli";
|
|
7
|
+
export function createProviderMatchers(effectiveFallbackProvider) {
|
|
8
|
+
const isUnprefixedModel = (model) => model.trim() !== CODEX_PROVIDER_ALIAS &&
|
|
9
|
+
!model.startsWith(OPENROUTER_PREFIX) &&
|
|
10
|
+
!model.startsWith(OLLAMA_PREFIX) &&
|
|
11
|
+
!model.startsWith(GOOGLE_PREFIX) &&
|
|
12
|
+
!model.startsWith(CODEX_PREFIX) &&
|
|
13
|
+
!model.startsWith(LEGACY_CODEX_PREFIX);
|
|
14
|
+
return {
|
|
15
|
+
isUnprefixedModel,
|
|
16
|
+
matchesOpenRouter: (model) => model.startsWith(OPENROUTER_PREFIX) ||
|
|
17
|
+
(isUnprefixedModel(model) && effectiveFallbackProvider === "openrouter"),
|
|
18
|
+
matchesOllama: (model) => model.startsWith(OLLAMA_PREFIX) ||
|
|
19
|
+
(isUnprefixedModel(model) && effectiveFallbackProvider === "ollama"),
|
|
20
|
+
matchesGoogle: (model) => model.startsWith(GOOGLE_PREFIX) ||
|
|
21
|
+
(isUnprefixedModel(model) && effectiveFallbackProvider === "google"),
|
|
22
|
+
matchesCodex: (model) => model.trim() === CODEX_PROVIDER_ALIAS ||
|
|
23
|
+
model.startsWith(CODEX_PREFIX) ||
|
|
24
|
+
(isUnprefixedModel(model) && effectiveFallbackProvider === "codex-cli"),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { resolveEffectivePermissions } from "@bolt-foundry/gambit-core";
|
|
2
|
+
import type { Guardrails, ModelMessage, ModelProvider, PermissionDeclarationInput, PermissionTrace, ToolDefinition } from "@bolt-foundry/gambit-core";
|
|
3
|
+
export declare const logger: Console;
|
|
4
|
+
export type ChatCompletionsRequest = {
|
|
5
|
+
model: string;
|
|
6
|
+
messages: Array<{
|
|
7
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
8
|
+
content: string | null | Array<string | {
|
|
9
|
+
text?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
}>;
|
|
12
|
+
name?: string;
|
|
13
|
+
tool_call_id?: string;
|
|
14
|
+
tool_calls?: ModelMessage["tool_calls"];
|
|
15
|
+
}>;
|
|
16
|
+
tools?: Array<ToolDefinition>;
|
|
17
|
+
stream?: boolean;
|
|
18
|
+
temperature?: number;
|
|
19
|
+
top_p?: number;
|
|
20
|
+
frequency_penalty?: number;
|
|
21
|
+
presence_penalty?: number;
|
|
22
|
+
max_tokens?: number;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
};
|
|
25
|
+
export type ChatCompletionsResponse = {
|
|
26
|
+
id: string;
|
|
27
|
+
object: "chat.completion";
|
|
28
|
+
created: number;
|
|
29
|
+
model: string;
|
|
30
|
+
choices: Array<{
|
|
31
|
+
index: number;
|
|
32
|
+
message: ModelMessage;
|
|
33
|
+
finish_reason: "stop" | "tool_calls" | "length";
|
|
34
|
+
logprobs: null;
|
|
35
|
+
}>;
|
|
36
|
+
usage?: {
|
|
37
|
+
prompt_tokens: number;
|
|
38
|
+
completion_tokens: number;
|
|
39
|
+
total_tokens: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Non-OpenAI extension field containing the full transcript and metadata.
|
|
43
|
+
* Most clients will ignore unknown fields.
|
|
44
|
+
*/
|
|
45
|
+
gambit?: {
|
|
46
|
+
deckPath: string;
|
|
47
|
+
messages: Array<ModelMessage>;
|
|
48
|
+
runId: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export declare function chatCompletionsWithDeck(args: {
|
|
52
|
+
deckPath: string;
|
|
53
|
+
request: ChatCompletionsRequest;
|
|
54
|
+
modelProvider: ModelProvider;
|
|
55
|
+
/**
|
|
56
|
+
* When true (default), Gambit will execute tool calls that match deck actions.
|
|
57
|
+
* Any other tool calls are returned to the caller as normal OpenAI tool calls.
|
|
58
|
+
*/
|
|
59
|
+
executeDeckTools?: boolean;
|
|
60
|
+
guardrails?: Partial<Guardrails>;
|
|
61
|
+
defaultModel?: string;
|
|
62
|
+
onStreamText?: (chunk: string) => void;
|
|
63
|
+
workspacePermissions?: PermissionDeclarationInput;
|
|
64
|
+
workspacePermissionsBaseDir?: string;
|
|
65
|
+
sessionPermissions?: PermissionDeclarationInput;
|
|
66
|
+
sessionPermissionsBaseDir?: string;
|
|
67
|
+
parentPermissions?: ReturnType<typeof resolveEffectivePermissions>["effective"];
|
|
68
|
+
workerSandbox?: boolean;
|
|
69
|
+
trace?: (event: {
|
|
70
|
+
type: string;
|
|
71
|
+
permissions?: PermissionTrace;
|
|
72
|
+
}) => void;
|
|
73
|
+
}): Promise<ChatCompletionsResponse>;
|
|
74
|
+
//# 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":"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"}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import * as dntShim from "../_dnt.shims.js";
|
|
2
|
+
import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
3
|
+
import { assertZodSchema, DEFAULT_GUARDRAILS, loadDeck, RESERVED_TOOL_PREFIX, resolveEffectivePermissions, runDeck, toJsonSchema, } from "@bolt-foundry/gambit-core";
|
|
4
|
+
export const logger = console;
|
|
5
|
+
function randomId(prefix) {
|
|
6
|
+
const suffix = crypto.randomUUID().replace(/-/g, "").slice(0, 24);
|
|
7
|
+
return `${prefix}-${suffix}`;
|
|
8
|
+
}
|
|
9
|
+
function normalizeContent(content) {
|
|
10
|
+
if (content === null)
|
|
11
|
+
return null;
|
|
12
|
+
if (typeof content === "string")
|
|
13
|
+
return content;
|
|
14
|
+
if (!Array.isArray(content))
|
|
15
|
+
return String(content);
|
|
16
|
+
return content
|
|
17
|
+
.map((c) => (typeof c === "string" ? c : (c.text ?? "")))
|
|
18
|
+
.join("");
|
|
19
|
+
}
|
|
20
|
+
function normalizeMessages(input) {
|
|
21
|
+
return input.map((m) => ({
|
|
22
|
+
role: m.role,
|
|
23
|
+
content: normalizeContent(m.content),
|
|
24
|
+
name: m.name,
|
|
25
|
+
tool_call_id: m.tool_call_id,
|
|
26
|
+
tool_calls: m.tool_calls && m.tool_calls.length > 0
|
|
27
|
+
? m.tool_calls
|
|
28
|
+
: undefined,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
function providerParamsFromRequest(req) {
|
|
32
|
+
const out = {};
|
|
33
|
+
if (req.temperature !== undefined)
|
|
34
|
+
out.temperature = req.temperature;
|
|
35
|
+
if (req.top_p !== undefined)
|
|
36
|
+
out.top_p = req.top_p;
|
|
37
|
+
if (req.frequency_penalty !== undefined) {
|
|
38
|
+
out.frequency_penalty = req.frequency_penalty;
|
|
39
|
+
}
|
|
40
|
+
if (req.presence_penalty !== undefined) {
|
|
41
|
+
out.presence_penalty = req.presence_penalty;
|
|
42
|
+
}
|
|
43
|
+
if (req.max_tokens !== undefined)
|
|
44
|
+
out.max_tokens = req.max_tokens;
|
|
45
|
+
return Object.keys(out).length ? out : undefined;
|
|
46
|
+
}
|
|
47
|
+
function mergeToolDefs(gambitTools, externalTools) {
|
|
48
|
+
if (!externalTools?.length)
|
|
49
|
+
return gambitTools;
|
|
50
|
+
return [...gambitTools, ...externalTools];
|
|
51
|
+
}
|
|
52
|
+
function toolName(tool) {
|
|
53
|
+
return tool.function?.name ?? "";
|
|
54
|
+
}
|
|
55
|
+
function resolveContextSchema(deck) {
|
|
56
|
+
return deck.contextSchema ?? deck.inputSchema;
|
|
57
|
+
}
|
|
58
|
+
function resolveResponseSchema(deck) {
|
|
59
|
+
return deck.responseSchema ?? deck.outputSchema;
|
|
60
|
+
}
|
|
61
|
+
function assertNoToolNameCollisions(args) {
|
|
62
|
+
if (!args.externalTools?.length)
|
|
63
|
+
return;
|
|
64
|
+
const gambit = new Set(args.gambitTools.map(toolName));
|
|
65
|
+
for (const t of args.externalTools) {
|
|
66
|
+
const name = toolName(t);
|
|
67
|
+
if (!name)
|
|
68
|
+
continue;
|
|
69
|
+
if (name.startsWith(RESERVED_TOOL_PREFIX)) {
|
|
70
|
+
throw new Error(`External tool name ${name} is reserved (prefix ${RESERVED_TOOL_PREFIX})`);
|
|
71
|
+
}
|
|
72
|
+
if (gambit.has(name)) {
|
|
73
|
+
throw new Error(`Tool name collision for ${name} between Gambit deck actions and external tools`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function buildGambitActionTools(deck) {
|
|
78
|
+
const tools = [];
|
|
79
|
+
const toolNameSet = new Set();
|
|
80
|
+
const actionPathByName = new Map();
|
|
81
|
+
for (const action of deck.actionDecks) {
|
|
82
|
+
const child = await loadDeck(action.path, deck.path);
|
|
83
|
+
const contextSchema = resolveContextSchema(child);
|
|
84
|
+
const responseSchema = resolveResponseSchema(child);
|
|
85
|
+
if (!contextSchema || !responseSchema) {
|
|
86
|
+
throw new Error(`Deck ${child.path} must declare contextSchema and responseSchema (non-root)`);
|
|
87
|
+
}
|
|
88
|
+
assertZodSchema(contextSchema, "contextSchema");
|
|
89
|
+
assertZodSchema(responseSchema, "responseSchema");
|
|
90
|
+
const params = toJsonSchema(contextSchema);
|
|
91
|
+
tools.push({
|
|
92
|
+
type: "function",
|
|
93
|
+
function: {
|
|
94
|
+
name: action.name,
|
|
95
|
+
description: action.description,
|
|
96
|
+
parameters: params,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
toolNameSet.add(action.name);
|
|
100
|
+
actionPathByName.set(action.name, action.path);
|
|
101
|
+
}
|
|
102
|
+
return { tools, toolNameSet, actionPathByName };
|
|
103
|
+
}
|
|
104
|
+
function deckSystemPrompt(deck) {
|
|
105
|
+
const parts = [];
|
|
106
|
+
const prompt = deck.body ?? deck.prompt;
|
|
107
|
+
if (prompt)
|
|
108
|
+
parts.push(prompt.trim());
|
|
109
|
+
for (const card of deck.cards) {
|
|
110
|
+
if (card.body)
|
|
111
|
+
parts.push(card.body.trim());
|
|
112
|
+
}
|
|
113
|
+
return parts.join("\n\n").trim();
|
|
114
|
+
}
|
|
115
|
+
function shouldPrependDeckSystem(messages, systemPrompt) {
|
|
116
|
+
if (!systemPrompt)
|
|
117
|
+
return false;
|
|
118
|
+
if (!messages.length)
|
|
119
|
+
return true;
|
|
120
|
+
const hasExact = messages.some((m) => m.role === "system" && m.content === systemPrompt);
|
|
121
|
+
return !hasExact;
|
|
122
|
+
}
|
|
123
|
+
function warnIfSystemMismatch(args) {
|
|
124
|
+
if (!args.systemPrompt)
|
|
125
|
+
return;
|
|
126
|
+
const existing = args.provided.find((m) => m.role === "system");
|
|
127
|
+
if (!existing)
|
|
128
|
+
return;
|
|
129
|
+
if (existing.content === args.systemPrompt)
|
|
130
|
+
return;
|
|
131
|
+
logger.warn(`[gambit] chatCompletionsWithDeck: request includes a system message that does not match the deck prompt (${args.deckPath})`);
|
|
132
|
+
}
|
|
133
|
+
function toolResultContent(result) {
|
|
134
|
+
if (typeof result === "string")
|
|
135
|
+
return result;
|
|
136
|
+
try {
|
|
137
|
+
return JSON.stringify(result);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return String(result);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function normalizeError(err) {
|
|
144
|
+
return { message: err instanceof Error ? err.message : String(err) };
|
|
145
|
+
}
|
|
146
|
+
export async function chatCompletionsWithDeck(args) {
|
|
147
|
+
const executeDeckTools = args.executeDeckTools ?? true;
|
|
148
|
+
const guardrails = { ...DEFAULT_GUARDRAILS, ...args.guardrails };
|
|
149
|
+
const runId = randomId("run");
|
|
150
|
+
const deck = await loadDeck(args.deckPath);
|
|
151
|
+
const rootPermissions = resolveEffectivePermissions({
|
|
152
|
+
baseDir: path.dirname(deck.path),
|
|
153
|
+
parent: args.parentPermissions,
|
|
154
|
+
workspace: args.workspacePermissions
|
|
155
|
+
? {
|
|
156
|
+
baseDir: args.workspacePermissionsBaseDir ?? path.dirname(deck.path),
|
|
157
|
+
permissions: args.workspacePermissions,
|
|
158
|
+
}
|
|
159
|
+
: undefined,
|
|
160
|
+
declaration: deck.permissions
|
|
161
|
+
? {
|
|
162
|
+
baseDir: path.dirname(deck.path),
|
|
163
|
+
permissions: deck.permissions,
|
|
164
|
+
}
|
|
165
|
+
: undefined,
|
|
166
|
+
session: args.sessionPermissions
|
|
167
|
+
? {
|
|
168
|
+
baseDir: args.sessionPermissionsBaseDir ?? dntShim.Deno.cwd(),
|
|
169
|
+
permissions: args.sessionPermissions,
|
|
170
|
+
}
|
|
171
|
+
: undefined,
|
|
172
|
+
});
|
|
173
|
+
args.trace?.({
|
|
174
|
+
type: "openai_compat.permissions",
|
|
175
|
+
permissions: rootPermissions.trace,
|
|
176
|
+
});
|
|
177
|
+
const systemPrompt = deckSystemPrompt(deck);
|
|
178
|
+
const providedMessages = normalizeMessages(args.request.messages);
|
|
179
|
+
const messages = [];
|
|
180
|
+
warnIfSystemMismatch({
|
|
181
|
+
provided: providedMessages,
|
|
182
|
+
systemPrompt,
|
|
183
|
+
deckPath: deck.path,
|
|
184
|
+
});
|
|
185
|
+
if (shouldPrependDeckSystem(providedMessages, systemPrompt)) {
|
|
186
|
+
messages.push({ role: "system", content: systemPrompt });
|
|
187
|
+
}
|
|
188
|
+
messages.push(...providedMessages);
|
|
189
|
+
const gambit = await buildGambitActionTools(deck);
|
|
190
|
+
assertNoToolNameCollisions({
|
|
191
|
+
gambitTools: gambit.tools,
|
|
192
|
+
externalTools: args.request.tools,
|
|
193
|
+
});
|
|
194
|
+
const tools = mergeToolDefs(gambit.tools, args.request.tools);
|
|
195
|
+
const start = performance.now();
|
|
196
|
+
let passes = 0;
|
|
197
|
+
while (passes < guardrails.maxPasses) {
|
|
198
|
+
passes++;
|
|
199
|
+
if (performance.now() - start > guardrails.timeoutMs) {
|
|
200
|
+
throw new Error("Timeout exceeded");
|
|
201
|
+
}
|
|
202
|
+
const model = args.request.model ?? args.defaultModel ??
|
|
203
|
+
(() => {
|
|
204
|
+
throw new Error("No model provided");
|
|
205
|
+
})();
|
|
206
|
+
const result = await args.modelProvider.chat({
|
|
207
|
+
model,
|
|
208
|
+
messages,
|
|
209
|
+
tools: tools.length ? tools : undefined,
|
|
210
|
+
stream: Boolean(args.request.stream),
|
|
211
|
+
deckPath: deck.path,
|
|
212
|
+
onStreamText: args.onStreamText,
|
|
213
|
+
params: providerParamsFromRequest(args.request),
|
|
214
|
+
});
|
|
215
|
+
messages.push(result.message);
|
|
216
|
+
if (result.toolCalls && result.toolCalls.length > 0) {
|
|
217
|
+
const gambitCalls = result.toolCalls.filter((c) => gambit.toolNameSet.has(c.name));
|
|
218
|
+
const externalCalls = result.toolCalls.filter((c) => !gambit.toolNameSet.has(c.name));
|
|
219
|
+
if (!executeDeckTools || externalCalls.length > 0) {
|
|
220
|
+
return {
|
|
221
|
+
id: randomId("chatcmpl"),
|
|
222
|
+
object: "chat.completion",
|
|
223
|
+
created: Math.floor(Date.now() / 1000),
|
|
224
|
+
model,
|
|
225
|
+
choices: [{
|
|
226
|
+
index: 0,
|
|
227
|
+
message: result.message,
|
|
228
|
+
finish_reason: "tool_calls",
|
|
229
|
+
logprobs: null,
|
|
230
|
+
}],
|
|
231
|
+
usage: result.usage
|
|
232
|
+
? {
|
|
233
|
+
prompt_tokens: result.usage.promptTokens,
|
|
234
|
+
completion_tokens: result.usage.completionTokens,
|
|
235
|
+
total_tokens: result.usage.totalTokens,
|
|
236
|
+
}
|
|
237
|
+
: undefined,
|
|
238
|
+
gambit: { deckPath: deck.path, messages, runId },
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
// Execute only deck-defined tool calls.
|
|
242
|
+
for (const call of gambitCalls) {
|
|
243
|
+
const actionPath = gambit.actionPathByName.get(call.name);
|
|
244
|
+
if (!actionPath)
|
|
245
|
+
continue;
|
|
246
|
+
try {
|
|
247
|
+
const actionRef = deck.actionDecks.find((entry) => entry.name === call.name);
|
|
248
|
+
const actionPermissions = resolveEffectivePermissions({
|
|
249
|
+
baseDir: path.dirname(deck.path),
|
|
250
|
+
parent: rootPermissions.effective,
|
|
251
|
+
reference: actionRef?.permissions
|
|
252
|
+
? {
|
|
253
|
+
baseDir: path.dirname(deck.path),
|
|
254
|
+
permissions: actionRef.permissions,
|
|
255
|
+
}
|
|
256
|
+
: undefined,
|
|
257
|
+
});
|
|
258
|
+
args.trace?.({
|
|
259
|
+
type: "openai_compat.action.permissions",
|
|
260
|
+
permissions: actionPermissions.trace,
|
|
261
|
+
});
|
|
262
|
+
const childResult = await runDeck({
|
|
263
|
+
path: actionPath,
|
|
264
|
+
input: call.args,
|
|
265
|
+
modelProvider: args.modelProvider,
|
|
266
|
+
isRoot: false,
|
|
267
|
+
guardrails,
|
|
268
|
+
depth: 1,
|
|
269
|
+
parentActionCallId: call.id,
|
|
270
|
+
runId,
|
|
271
|
+
defaultModel: model,
|
|
272
|
+
modelOverride: undefined,
|
|
273
|
+
trace: undefined,
|
|
274
|
+
stream: Boolean(args.request.stream),
|
|
275
|
+
onStreamText: args.onStreamText,
|
|
276
|
+
inputProvided: true,
|
|
277
|
+
parentPermissions: rootPermissions.effective,
|
|
278
|
+
referencePermissions: actionRef?.permissions,
|
|
279
|
+
referencePermissionsBaseDir: path.dirname(deck.path),
|
|
280
|
+
workspacePermissions: args.workspacePermissions,
|
|
281
|
+
workspacePermissionsBaseDir: args.workspacePermissionsBaseDir,
|
|
282
|
+
sessionPermissions: args.sessionPermissions,
|
|
283
|
+
sessionPermissionsBaseDir: args.sessionPermissionsBaseDir,
|
|
284
|
+
workerSandbox: args.workerSandbox,
|
|
285
|
+
});
|
|
286
|
+
messages.push({
|
|
287
|
+
role: "tool",
|
|
288
|
+
name: call.name,
|
|
289
|
+
tool_call_id: call.id,
|
|
290
|
+
content: toolResultContent(childResult),
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
catch (err) {
|
|
294
|
+
messages.push({
|
|
295
|
+
role: "tool",
|
|
296
|
+
name: call.name,
|
|
297
|
+
tool_call_id: call.id,
|
|
298
|
+
content: JSON.stringify({ error: normalizeError(err) }),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (result.finishReason === "tool_calls") {
|
|
305
|
+
throw new Error("Model requested tool_calls but provided none");
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
id: randomId("chatcmpl"),
|
|
309
|
+
object: "chat.completion",
|
|
310
|
+
created: Math.floor(Date.now() / 1000),
|
|
311
|
+
model,
|
|
312
|
+
choices: [{
|
|
313
|
+
index: 0,
|
|
314
|
+
message: result.message,
|
|
315
|
+
finish_reason: result.finishReason,
|
|
316
|
+
logprobs: null,
|
|
317
|
+
}],
|
|
318
|
+
usage: result.usage
|
|
319
|
+
? {
|
|
320
|
+
prompt_tokens: result.usage.promptTokens,
|
|
321
|
+
completion_tokens: result.usage.completionTokens,
|
|
322
|
+
total_tokens: result.usage.totalTokens,
|
|
323
|
+
}
|
|
324
|
+
: undefined,
|
|
325
|
+
gambit: { deckPath: deck.path, messages, runId },
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
throw new Error("Max passes exceeded without completing");
|
|
329
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { PermissionDeclarationInput } from "@bolt-foundry/gambit-core";
|
|
2
|
+
export type WorkspaceConfig = {
|
|
3
|
+
decks?: string;
|
|
4
|
+
actions?: string;
|
|
5
|
+
graders?: string;
|
|
6
|
+
tests?: string;
|
|
7
|
+
schemas?: string;
|
|
8
|
+
permissions?: PermissionDeclarationInput;
|
|
9
|
+
};
|
|
10
|
+
export type ModelAliasConfig = {
|
|
11
|
+
model?: string | Array<string>;
|
|
12
|
+
description?: string;
|
|
13
|
+
params?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
export type GambitConfig = {
|
|
16
|
+
workspace?: WorkspaceConfig;
|
|
17
|
+
execution?: {
|
|
18
|
+
workerSandbox?: boolean;
|
|
19
|
+
worker_sandbox?: boolean;
|
|
20
|
+
legacyExec?: boolean;
|
|
21
|
+
legacy_exec?: boolean;
|
|
22
|
+
};
|
|
23
|
+
models?: {
|
|
24
|
+
aliases?: Record<string, ModelAliasConfig>;
|
|
25
|
+
};
|
|
26
|
+
providers?: {
|
|
27
|
+
fallback?: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export type LoadedProjectConfig = {
|
|
31
|
+
root: string;
|
|
32
|
+
path: string;
|
|
33
|
+
config: GambitConfig;
|
|
34
|
+
};
|
|
35
|
+
export declare function loadProjectConfig(startPath?: string): Promise<LoadedProjectConfig | null>;
|
|
36
|
+
export type ModelAliasResolution = {
|
|
37
|
+
model?: string | Array<string>;
|
|
38
|
+
params?: Record<string, unknown>;
|
|
39
|
+
alias?: string;
|
|
40
|
+
applied: boolean;
|
|
41
|
+
missingAlias?: boolean;
|
|
42
|
+
};
|
|
43
|
+
export type ModelAliasResolver = (model?: string) => ModelAliasResolution;
|
|
44
|
+
export declare function createModelAliasResolver(config?: GambitConfig | null): ModelAliasResolver;
|
|
45
|
+
export declare function resolveWorkspacePermissions(config?: GambitConfig | null): PermissionDeclarationInput | undefined;
|
|
46
|
+
export declare function resolveWorkerSandboxSetting(config?: GambitConfig | null): boolean | undefined;
|
|
47
|
+
//# sourceMappingURL=project_config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project_config.d.ts","sourceRoot":"","sources":["../../src/src/project_config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE5E,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,0BAA0B,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,SAAS,CAAC,EAAE;QACV,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;KAC5C,CAAC;IACF,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;CACtB,CAAC;AAsCF,wBAAsB,iBAAiB,CACrC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAiBrC;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,oBAAoB,CAAC;AAE1E,wBAAgB,wBAAwB,CACtC,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,GAC3B,kBAAkB,CA8CpB;AAED,wBAAgB,2BAA2B,CACzC,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,GAC3B,0BAA0B,GAAG,SAAS,CAIxC;AAOD,wBAAgB,2BAA2B,CACzC,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,GAC3B,OAAO,GAAG,SAAS,CAsBrB"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import * as dntShim from "../_dnt.shims.js";
|
|
2
|
+
import { parse as parseToml } from "../deps/jsr.io/@std/toml/1.0.11/mod.js";
|
|
3
|
+
import * as path from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
4
|
+
const CONFIG_FILENAME = "gambit.toml";
|
|
5
|
+
const configCache = new Map();
|
|
6
|
+
function isPlainObject(value) {
|
|
7
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
8
|
+
}
|
|
9
|
+
function resolveStartDir(target) {
|
|
10
|
+
if (!target)
|
|
11
|
+
return dntShim.Deno.cwd();
|
|
12
|
+
const resolved = path.resolve(target);
|
|
13
|
+
try {
|
|
14
|
+
const info = dntShim.Deno.statSync(resolved);
|
|
15
|
+
if (info.isDirectory)
|
|
16
|
+
return resolved;
|
|
17
|
+
return path.dirname(resolved);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return path.dirname(resolved);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function findConfigPath(startDir) {
|
|
24
|
+
let current = startDir;
|
|
25
|
+
while (true) {
|
|
26
|
+
const candidate = path.join(current, CONFIG_FILENAME);
|
|
27
|
+
try {
|
|
28
|
+
const info = dntShim.Deno.statSync(candidate);
|
|
29
|
+
if (info.isFile)
|
|
30
|
+
return candidate;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// ignore and continue walking up the tree
|
|
34
|
+
}
|
|
35
|
+
const parent = path.dirname(current);
|
|
36
|
+
if (parent === current)
|
|
37
|
+
break;
|
|
38
|
+
current = parent;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
export async function loadProjectConfig(startPath) {
|
|
43
|
+
const startDir = resolveStartDir(startPath);
|
|
44
|
+
const configPath = findConfigPath(startDir);
|
|
45
|
+
if (!configPath)
|
|
46
|
+
return null;
|
|
47
|
+
const cached = configCache.get(configPath);
|
|
48
|
+
if (cached !== undefined) {
|
|
49
|
+
return cached;
|
|
50
|
+
}
|
|
51
|
+
const text = await dntShim.Deno.readTextFile(configPath);
|
|
52
|
+
const parsed = parseToml(text);
|
|
53
|
+
const loaded = {
|
|
54
|
+
root: path.dirname(configPath),
|
|
55
|
+
path: configPath,
|
|
56
|
+
config: parsed ?? {},
|
|
57
|
+
};
|
|
58
|
+
configCache.set(configPath, loaded);
|
|
59
|
+
return loaded;
|
|
60
|
+
}
|
|
61
|
+
export function createModelAliasResolver(config) {
|
|
62
|
+
const resolved = new Map();
|
|
63
|
+
const aliases = config?.models?.aliases;
|
|
64
|
+
if (isPlainObject(aliases)) {
|
|
65
|
+
for (const [name, raw] of Object.entries(aliases)) {
|
|
66
|
+
if (!isPlainObject(raw))
|
|
67
|
+
continue;
|
|
68
|
+
let model;
|
|
69
|
+
if (typeof raw.model === "string") {
|
|
70
|
+
const trimmed = raw.model.trim();
|
|
71
|
+
if (trimmed)
|
|
72
|
+
model = trimmed;
|
|
73
|
+
}
|
|
74
|
+
else if (Array.isArray(raw.model)) {
|
|
75
|
+
const entries = raw.model
|
|
76
|
+
.map((entry) => (typeof entry === "string" ? entry.trim() : ""))
|
|
77
|
+
.filter(Boolean);
|
|
78
|
+
if (entries.length > 0)
|
|
79
|
+
model = entries;
|
|
80
|
+
}
|
|
81
|
+
if (!model)
|
|
82
|
+
continue;
|
|
83
|
+
const params = isPlainObject(raw.params)
|
|
84
|
+
? structuredClone(raw.params)
|
|
85
|
+
: undefined;
|
|
86
|
+
resolved.set(name, { model, params });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const hasAliases = resolved.size > 0;
|
|
90
|
+
return (model) => {
|
|
91
|
+
if (!model) {
|
|
92
|
+
return { model, applied: false };
|
|
93
|
+
}
|
|
94
|
+
const entry = resolved.get(model);
|
|
95
|
+
if (entry) {
|
|
96
|
+
return {
|
|
97
|
+
model: entry.model,
|
|
98
|
+
params: entry.params ? structuredClone(entry.params) : undefined,
|
|
99
|
+
alias: model,
|
|
100
|
+
applied: true,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const missingAlias = hasAliases && !model.includes("/");
|
|
104
|
+
return { model, applied: false, missingAlias };
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export function resolveWorkspacePermissions(config) {
|
|
108
|
+
const raw = config?.workspace?.permissions;
|
|
109
|
+
if (!isPlainObject(raw))
|
|
110
|
+
return undefined;
|
|
111
|
+
return raw;
|
|
112
|
+
}
|
|
113
|
+
function resolveBooleanField(value) {
|
|
114
|
+
if (typeof value === "boolean")
|
|
115
|
+
return value;
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
export function resolveWorkerSandboxSetting(config) {
|
|
119
|
+
const execution = config?.execution;
|
|
120
|
+
if (!isPlainObject(execution))
|
|
121
|
+
return undefined;
|
|
122
|
+
const workerSandbox = resolveBooleanField(execution.workerSandbox ?? execution.worker_sandbox);
|
|
123
|
+
const legacyExec = resolveBooleanField(execution.legacyExec ?? execution.legacy_exec);
|
|
124
|
+
if (workerSandbox !== undefined && legacyExec !== undefined) {
|
|
125
|
+
if (workerSandbox === legacyExec) {
|
|
126
|
+
throw new Error("gambit.toml execution config is conflicting: worker_sandbox and legacy_exec must be opposites when both are set.");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (workerSandbox !== undefined)
|
|
130
|
+
return workerSandbox;
|
|
131
|
+
if (legacyExec !== undefined)
|
|
132
|
+
return !legacyExec;
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|