chatlas 0.11.1__tar.gz → 0.15.0__tar.gz
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.
- chatlas-0.15.0/.claude/settings.local.json +15 -0
- chatlas-0.15.0/.github/workflows/check-vcr-secrets.yml +43 -0
- chatlas-0.15.0/.github/workflows/test-live.yml +66 -0
- chatlas-0.15.0/.github/workflows/test.yml +46 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/.gitignore +1 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/.vscode/settings.json +9 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/CHANGELOG.md +122 -6
- {chatlas-0.11.1 → chatlas-0.15.0}/CLAUDE.md +78 -6
- {chatlas-0.11.1 → chatlas-0.15.0}/Makefile +10 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/PKG-INFO +10 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/__init__.py +28 -9
- chatlas-0.15.0/chatlas/_auto.py +298 -0
- chatlas-0.15.0/chatlas/_batch_chat.py +211 -0
- chatlas-0.15.0/chatlas/_batch_job.py +236 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_chat.py +748 -197
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_content.py +226 -141
- chatlas-0.15.0/chatlas/_content_expand.py +104 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_content_pdf.py +32 -7
- chatlas-0.15.0/chatlas/_inspect.py +250 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_mcp_manager.py +5 -5
- chatlas-0.15.0/chatlas/_parallel.py +717 -0
- chatlas-0.15.0/chatlas/_progress.py +61 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider.py +136 -12
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_anthropic.py +433 -88
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_cloudflare.py +3 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_databricks.py +10 -4
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_deepseek.py +4 -4
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_github.py +6 -5
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_google.py +132 -58
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_groq.py +4 -4
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_huggingface.py +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_mistral.py +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_ollama.py +4 -3
- chatlas-0.15.0/chatlas/_provider_openai.py +569 -0
- chatlas-0.15.0/chatlas/_provider_openai_azure.py +221 -0
- chatlas-0.15.0/chatlas/_provider_openai_completions.py +464 -0
- chatlas-0.15.0/chatlas/_provider_openai_generic.py +301 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_openrouter.py +3 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_perplexity.py +3 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_portkey.py +4 -4
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_provider_snowflake.py +49 -30
- chatlas-0.15.0/chatlas/_repr.py +17 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_tokens.py +82 -35
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_tools.py +127 -26
- chatlas-0.15.0/chatlas/_tools_builtin.py +627 -0
- chatlas-0.15.0/chatlas/_turn.py +409 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_version.py +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/data/prices.json +2282 -623
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/__init__.py +10 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/anthropic/_client.py +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/anthropic/_submit.py +17 -16
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/openai/__init__.py +2 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/openai/_client.py +3 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/openai/_client_azure.py +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/openai/_submit.py +44 -33
- chatlas-0.15.0/chatlas/types/openai/_submit_responses.py +261 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/_quarto.yml +33 -7
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/_sidebar.yml +18 -4
- chatlas-0.15.0/docs/dev/vcr-tests.md +263 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/chat.qmd +1 -1
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/chatbots.qmd +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/models.qmd +31 -9
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/structured-data.qmd +12 -22
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/tools.qmd +59 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/misc/RAG.qmd +2 -2
- chatlas-0.15.0/docs/misc/evals.qmd +297 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/misc/mcp-tools.qmd +74 -48
- chatlas-0.15.0/docs/scale.qmd +13 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/structured-data/article-summary.qmd +3 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/structured-data/classification.qmd +5 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/structured-data/entity-recognition.qmd +3 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/structured-data/multi-modal.qmd +4 -3
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/structured-data/sentiment-analysis.qmd +2 -2
- {chatlas-0.11.1 → chatlas-0.15.0}/pyproject.toml +14 -5
- chatlas-0.15.0/pytest.ini +3 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/scripts/_generate_openai_types.py +28 -3
- chatlas-0.15.0/scripts/check_vcr_secrets.py +143 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/__snapshots__/test_chat.ambr +18 -10
- chatlas-0.15.0/tests/_vcr/.gitkeep +0 -0
- chatlas-0.15.0/tests/_vcr/test_batch_chat/test_can_submit_anthropic_batch.yaml +66 -0
- chatlas-0.15.0/tests/_vcr/test_batch_chat/test_can_submit_openai_batch.yaml +141 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_chat_callbacks.yaml +337 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_chat_structured.yaml +101 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_chat_structured_async.yaml +101 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_chat_tool_request_reject.yaml +315 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_chat_tool_request_reject2.yaml +315 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_deepcopy_chat.yaml +191 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_json_serialize.yaml +95 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_last_turn_retrieval.yaml +85 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_simple_async_batch_chat.yaml +103 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_simple_batch_chat.yaml +103 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_simple_streaming_chat.yaml +174 -0
- chatlas-0.15.0/tests/_vcr/test_chat/test_simple_streaming_chat_async.yaml +174 -0
- chatlas-0.15.0/tests/_vcr/test_chat_dangling_tools/TestDanglingToolRequests.test_can_resume_chat_after_dangling_tool_requests.yaml +263 -0
- chatlas-0.15.0/tests/_vcr/test_inspect/TestInspectIntegration.test_basic_eval.yaml +467 -0
- chatlas-0.15.0/tests/_vcr/test_inspect/TestInspectIntegration.test_existing_turns.yaml +453 -0
- chatlas-0.15.0/tests/_vcr/test_inspect/TestInspectIntegration.test_system_prompt_override.yaml +1150 -0
- chatlas-0.15.0/tests/_vcr/test_inspect/TestInspectIntegration.test_tool_calling.yaml +440 -0
- chatlas-0.15.0/tests/_vcr/test_mcp_client/test_call_http_mcp_tool.yaml +472 -0
- chatlas-0.15.0/tests/_vcr/test_mcp_client/test_call_stdio_mcp_tool.yaml +238 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat/test_parallel_chat_basic.yaml +372 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat/test_parallel_chat_structured.yaml +202 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat/test_parallel_chat_tools.yaml +402 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat/test_parallel_chat_tools_uneven.yaml +598 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_errors/test_parallel_chat_error_continue_mode.yaml +191 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_errors/test_parallel_chat_error_return_mode.yaml +63 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_errors/test_parallel_chat_error_stop_mode.yaml +62 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_errors/test_parallel_chat_structured_error_handling.yaml +66 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_errors/test_parallel_chat_text_error_handling.yaml +63 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_chained_tool_calls.yaml +541 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_mixed_tools_and_no_tools.yaml +500 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_multi_turn_tools.yaml +462 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_no_tools_registered.yaml +275 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_ordering_preserved.yaml +617 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_structured_basic.yaml +306 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_structured_tool_ordering.yaml +680 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_structured_with_tools.yaml +466 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_improved/test_parallel_chat_tool_ordering_with_rate_limiting.yaml +2073 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_ordering/test_parallel_chat_mixed_tools_and_no_tools.yaml +512 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_ordering/test_parallel_chat_no_tools.yaml +272 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_ordering/test_parallel_chat_tool_ordering_basic.yaml +617 -0
- chatlas-0.15.0/tests/_vcr/test_parallel_chat_ordering/test_parallel_chat_tool_ordering_multiple_tools_per_prompt.yaml +426 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_empty_response.yaml +238 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_image_tool.yaml +756 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_images.yaml +803 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_list_models.yaml +62 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_nested_data_model_extraction.yaml +96 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_pdfs.yaml +327 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_respects_turns_interface.yaml +391 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_simple_request.yaml +115 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_simple_streaming_request.yaml +115 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_tool_variations.yaml +1131 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_tool_variations_async.yaml +493 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_tool_variations_parallel.yaml +320 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_web_fetch.yaml +415 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_web_search.yaml +287 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_anthropic_web_search_citations.yaml +125 -0
- chatlas-0.15.0/tests/_vcr/test_provider_anthropic/test_data_extraction.yaml +421 -0
- chatlas-0.15.0/tests/_vcr/test_provider_azure/test_azure_simple_request.yaml +102 -0
- chatlas-0.15.0/tests/_vcr/test_provider_azure/test_azure_simple_request_async.yaml +102 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_images.yaml +199 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_models.yaml +578 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_respects_turns_interface.yaml +276 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_simple_request.yaml +142 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_simple_streaming_request.yaml +80 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_tool_variations.yaml +854 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_anthropic_tool_variations_async.yaml +342 -0
- chatlas-0.15.0/tests/_vcr/test_provider_bedrock/test_data_extraction.yaml +273 -0
- chatlas-0.15.0/tests/_vcr/test_provider_cloudflare/test_cloudflare_data_extraction.yaml +291 -0
- chatlas-0.15.0/tests/_vcr/test_provider_cloudflare/test_cloudflare_respects_turns_interface.yaml +204 -0
- chatlas-0.15.0/tests/_vcr/test_provider_cloudflare/test_cloudflare_simple_request.yaml +67 -0
- chatlas-0.15.0/tests/_vcr/test_provider_cloudflare/test_cloudflare_simple_streaming_request.yaml +67 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_data_extraction.yaml +362 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_empty_response.yaml +160 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_images.yaml +107 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_respects_turns_interface.yaml +250 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_simple_request.yaml +80 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_simple_streaming_request.yaml +80 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_tool_variations.yaml +377 -0
- chatlas-0.15.0/tests/_vcr/test_provider_databricks/test_databricks_tool_variations_async.yaml +360 -0
- chatlas-0.15.0/tests/_vcr/test_provider_deepseek/test_deepseek_list_models.yaml +54 -0
- chatlas-0.15.0/tests/_vcr/test_provider_deepseek/test_deepseek_respects_turns_interface.yaml +274 -0
- chatlas-0.15.0/tests/_vcr/test_provider_deepseek/test_deepseek_simple_request.yaml +74 -0
- chatlas-0.15.0/tests/_vcr/test_provider_deepseek/test_deepseek_simple_streaming_request.yaml +74 -0
- chatlas-0.15.0/tests/_vcr/test_provider_deepseek/test_deepseek_tool_variations.yaml +385 -0
- chatlas-0.15.0/tests/_vcr/test_provider_deepseek/test_deepseek_tool_variations_async.yaml +346 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_data_extraction.yaml +466 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_images.yaml +589 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_list_models.yaml +201 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_logprobs.yaml +130 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_respects_turns_interface.yaml +329 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_simple_request.yaml +95 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_simple_streaming_request.yaml +95 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_tool_variations.yaml +1226 -0
- chatlas-0.15.0/tests/_vcr/test_provider_github/test_github_tool_variations_async.yaml +422 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_data_extraction.yaml +267 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_list_models.yaml +416 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_pdfs.yaml +121 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_respects_turns_interface.yaml +231 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_simple_request.yaml +58 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_simple_streaming_request.yaml +49 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_web_fetch.yaml +148 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_google_web_search.yaml +189 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_images_inline.yaml +62 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_tools_parallel.yaml +132 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_tools_sequential.yaml +205 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_tools_simple.yaml +260 -0
- chatlas-0.15.0/tests/_vcr/test_provider_google/test_tools_simple_stream_content.yaml +128 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_data_extraction.yaml +392 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_images.yaml +587 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_model_list.yaml +58 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_respects_turns_interface.yaml +297 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_simple_request.yaml +99 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_simple_streaming_request.yaml +99 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_tools.yaml +103 -0
- chatlas-0.15.0/tests/_vcr/test_provider_huggingface/test_huggingface_tools_async.yaml +103 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_data_extraction.yaml +368 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_huggingface_model_list.yaml +130 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_mistral_images.yaml +272 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_mistral_model_list.yaml +130 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_mistral_respects_turns_interface.yaml +248 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_mistral_simple_request.yaml +76 -0
- chatlas-0.15.0/tests/_vcr/test_provider_mistral/test_mistral_simple_streaming_request.yaml +76 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_data_extraction.yaml +514 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_images.yaml +876 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_list_models.yaml +280 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_logprobs.yaml +113 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_pdf.yaml +306 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_respects_turns_interface.yaml +438 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_service_tier_affects_pricing.yaml +146 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_simple_request.yaml +104 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_simple_streaming_request.yaml +104 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_tool_variations.yaml +1385 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_tool_variations_async.yaml +476 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai/test_openai_web_search.yaml +330 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_data_extraction.yaml +392 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_images.yaml +439 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_list_models.yaml +280 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_logprobs.yaml +94 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_pdf.yaml +270 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_respects_turns_interface.yaml +348 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_simple_request.yaml +90 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_simple_streaming_request.yaml +90 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_tool_variations.yaml +1124 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openai_completions/test_openai_tool_variations_async.yaml +408 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openrouter/test_data_extraction.yaml +325 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openrouter/test_openrouter_images.yaml +474 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openrouter/test_openrouter_list_models.yaml +2866 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openrouter/test_openrouter_simple_request.yaml +80 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openrouter/test_openrouter_simple_streaming_request.yaml +77 -0
- chatlas-0.15.0/tests/_vcr/test_provider_openrouter/test_openrouter_tool_variations.yaml +380 -0
- chatlas-0.15.0/tests/_vcr/test_tokens/test_token_count_method.yaml +323 -0
- chatlas-0.15.0/tests/_vcr_helpers_aws.py +86 -0
- chatlas-0.15.0/tests/batch/country-capitals-structured.json +235 -0
- chatlas-0.15.0/tests/batch/country-capitals.json +205 -0
- chatlas-0.15.0/tests/conftest.py +520 -0
- chatlas-0.15.0/tests/images/red_test.png +0 -0
- chatlas-0.15.0/tests/test_auto.py +266 -0
- chatlas-0.15.0/tests/test_batch_chat.py +218 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_callbacks.py +9 -4
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_chat.py +193 -35
- chatlas-0.15.0/tests/test_chat_dangling_tools.py +107 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_content_html.py +4 -51
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_content_pdf.py +2 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_content_tools.py +92 -0
- chatlas-0.15.0/tests/test_inspect.py +688 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_mcp_client.py +14 -8
- chatlas-0.15.0/tests/test_parallel_chat.py +166 -0
- chatlas-0.15.0/tests/test_parallel_chat_errors.py +145 -0
- chatlas-0.15.0/tests/test_parallel_chat_improved.py +339 -0
- chatlas-0.15.0/tests/test_parallel_chat_ordering.py +132 -0
- chatlas-0.15.0/tests/test_provider_anthropic.py +257 -0
- chatlas-0.15.0/tests/test_provider_azure.py +45 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_bedrock.py +19 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_cloudflare.py +20 -20
- chatlas-0.15.0/tests/test_provider_databricks.py +108 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_deepseek.py +6 -7
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_github.py +10 -11
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_google.py +47 -24
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_huggingface.py +25 -28
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_mistral.py +14 -11
- chatlas-0.15.0/tests/test_provider_openai.py +180 -0
- chatlas-0.11.1/tests/test_provider_openai.py → chatlas-0.15.0/tests/test_provider_openai_completions.py +29 -23
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_openrouter.py +6 -9
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_portkey.py +7 -6
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_provider_snowflake.py +19 -26
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_register_tool_models.py +4 -4
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_set_model_params.py +22 -54
- chatlas-0.15.0/tests/test_tokens.py +270 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_tool_from_mcp.py +13 -47
- chatlas-0.15.0/tests/test_tools_builtin.py +332 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_tools_enhanced.py +368 -40
- chatlas-0.15.0/tests/test_turn_expand.py +258 -0
- chatlas-0.15.0/tests/test_turns.py +349 -0
- chatlas-0.11.1/.github/workflows/test.yml +0 -77
- chatlas-0.11.1/chatlas/_auto.py +0 -178
- chatlas-0.11.1/chatlas/_provider_openai.py +0 -783
- chatlas-0.11.1/chatlas/_turn.py +0 -136
- chatlas-0.11.1/pytest.ini +0 -3
- chatlas-0.11.1/tests/conftest.py +0 -295
- chatlas-0.11.1/tests/test_auto.py +0 -109
- chatlas-0.11.1/tests/test_provider_anthropic.py +0 -134
- chatlas-0.11.1/tests/test_provider_azure.py +0 -41
- chatlas-0.11.1/tests/test_provider_databricks.py +0 -84
- chatlas-0.11.1/tests/test_tokens.py +0 -158
- chatlas-0.11.1/tests/test_turns.py +0 -92
- {chatlas-0.11.1 → chatlas-0.15.0}/.github/workflows/check-update-types.yml +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/.github/workflows/docs-publish.yml +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/.github/workflows/release.yml +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/.github/workflows/update-pricing.yml +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/.vscode/extensions.json +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/LICENSE +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/README.md +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_callbacks.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_content_image.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_display.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_interpolate.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_live_render.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_logging.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_merge.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_tokens_old.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_typing_extensions.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/_utils.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/py.typed +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/anthropic/__init__.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/anthropic/_client_bedrock.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/google/__init__.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/google/_client.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/chatlas/types/google/_submit.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/.gitignore +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/_extensions/machow/interlinks/.gitignore +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/_extensions/machow/interlinks/_extension.yml +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/_extensions/machow/interlinks/interlinks.lua +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/congressional-assets.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/async.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/debug.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/monitor.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/parameters.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/stream.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/get-started/system-prompt.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chat-app.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chat-console.mp4 +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chat-console.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chat-notebook.mp4 +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chat-parameters.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chatbot-gradio.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chatbot-shiny.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chatbot-streamlit.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chatbot-textual.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/chatlas-hello.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/client-parameters.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/congressional-assets.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/hello-chat-console.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/model-parameters.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/model-type-hints.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/posit-logo.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/shiny-mcp-run-python.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/shiny-tool-call-display.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/shiny-tool-call-map.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/tool-calling-right.svg +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/images/tool-calling-wrong.svg +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/index.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/logos/hero/hero-old.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/logos/hero/hero.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/logos/hex/logo.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/logos/small/logo.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/misc/examples.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/misc/vocabulary.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/styles.scss +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/tool-calling/approval.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/tool-calling/displays.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/tool-calling/how-it-works.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/docs/why-chatlas.qmd +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/scripts/_generate_anthropic_types.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/scripts/_generate_google_types.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/scripts/_utils.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/scripts/main.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/__init__.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/apples.pdf +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/images/dice.png +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/mcp_servers/http_add.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/mcp_servers/http_current_date.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/mcp_servers/stdio_current_date.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/mcp_servers/stdio_subtract_multiply.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_content.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_content_image.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_interpolate.py +0 -0
- {chatlas-0.11.1 → chatlas-0.15.0}/tests/test_utils_merge.py +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(gh issue view:*)",
|
|
5
|
+
"Bash(gh pr view:*)",
|
|
6
|
+
"Bash(gh pr diff:*)",
|
|
7
|
+
"Bash(uv run:*)",
|
|
8
|
+
"Bash(make:*)",
|
|
9
|
+
"Bash(uv sync:*)",
|
|
10
|
+
"Bash(TEST_OPENAI=false uv run python -m pytest:*)"
|
|
11
|
+
],
|
|
12
|
+
"deny": [],
|
|
13
|
+
"ask": []
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Check VCR Secrets
|
|
2
|
+
|
|
3
|
+
# Scan VCR cassettes for leaked secrets when they change.
|
|
4
|
+
# Uses Claude for thorough analysis of potential credential leaks.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
paths:
|
|
9
|
+
- "tests/_vcr/**"
|
|
10
|
+
push:
|
|
11
|
+
branches: ["main"]
|
|
12
|
+
paths:
|
|
13
|
+
- "tests/_vcr/**"
|
|
14
|
+
workflow_dispatch: # Allow manual trigger
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
check-secrets:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v3
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
run: uv python install 3.12
|
|
31
|
+
|
|
32
|
+
- name: Install the project
|
|
33
|
+
run: uv sync --python 3.12 --all-extras
|
|
34
|
+
|
|
35
|
+
- name: Scan for secrets with Claude
|
|
36
|
+
env:
|
|
37
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
38
|
+
run: |
|
|
39
|
+
if [ -z "$ANTHROPIC_API_KEY" ]; then
|
|
40
|
+
echo "::warning::ANTHROPIC_API_KEY not set, skipping secret scan"
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
make check-vcr-secrets
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Test (Live API)
|
|
2
|
+
|
|
3
|
+
# This workflow runs tests against live APIs to verify VCR cassettes are up-to-date.
|
|
4
|
+
# It requires API keys and runs less frequently than the main test workflow.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
push:
|
|
9
|
+
branches: ["main"]
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: ["main"]
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test-live:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
|
|
20
|
+
env:
|
|
21
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
22
|
+
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
|
23
|
+
CLOUDFLARE_API_KEY: ${{ secrets.CLOUDFLARE_API_KEY }}
|
|
24
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
25
|
+
DATABRICKS_HOST: ${{ secrets.DATABRICKS_HOST }}
|
|
26
|
+
DATABRICKS_TOKEN: ${{ secrets.DATABRICKS_TOKEN }}
|
|
27
|
+
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
28
|
+
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
29
|
+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
|
30
|
+
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
|
31
|
+
HUGGINGFACE_API_KEY: ${{ secrets.HUGGINGFACE_API_KEY }}
|
|
32
|
+
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
|
|
33
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
34
|
+
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
|
|
38
|
+
- name: Install uv
|
|
39
|
+
uses: astral-sh/setup-uv@v3
|
|
40
|
+
|
|
41
|
+
- name: Set up Python
|
|
42
|
+
run: uv python install 3.12
|
|
43
|
+
|
|
44
|
+
- name: Install the project
|
|
45
|
+
run: uv sync --python 3.12 --all-extras
|
|
46
|
+
|
|
47
|
+
- name: Create Snowflake connections.toml file
|
|
48
|
+
run: |
|
|
49
|
+
mkdir -p ~/.ssh
|
|
50
|
+
echo '${{ secrets.SNOWFLAKE_SSH_PUBLIC_KEY }}' > ~/.ssh/snowflake_key.pub
|
|
51
|
+
echo '${{ secrets.SNOWFLAKE_SSH_PRIVATE_KEY }}' > ~/.ssh/snowflake_key.p8
|
|
52
|
+
chmod 644 ~/.ssh/snowflake_key.pub
|
|
53
|
+
chmod 600 ~/.ssh/snowflake_key.p8
|
|
54
|
+
chmod 700 ~/.ssh
|
|
55
|
+
|
|
56
|
+
mkdir -p ~/.snowflake
|
|
57
|
+
cat > ~/.snowflake/connections.toml << 'EOF'
|
|
58
|
+
[posit]
|
|
59
|
+
account="duloftf-posit-software-pbc-dev"
|
|
60
|
+
user="carson@posit.co"
|
|
61
|
+
private_key_file="/home/runner/.ssh/snowflake_key.p8"
|
|
62
|
+
private_key_file_pwd="${{ secrets.SNOWFLAKE_SSH_PRIVATE_KEY_PASSWORD }}"
|
|
63
|
+
EOF
|
|
64
|
+
|
|
65
|
+
- name: Check tests
|
|
66
|
+
run: make check-tests
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches: ["main", "rc-*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
9
|
+
release:
|
|
10
|
+
types: [published]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
|
|
19
|
+
strategy:
|
|
20
|
+
matrix:
|
|
21
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
22
|
+
|
|
23
|
+
# Note: Dummy API keys for VCR replay testing are set in the Makefile.
|
|
24
|
+
# This workflow will not make any live API calls; those are reserved for
|
|
25
|
+
# the test-live.yml workflow.
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@v3
|
|
32
|
+
|
|
33
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
34
|
+
run: uv python install ${{ matrix.python-version }}
|
|
35
|
+
|
|
36
|
+
- name: Install the project
|
|
37
|
+
run: uv sync --python ${{ matrix.python-version }} --all-extras
|
|
38
|
+
|
|
39
|
+
- name: Check tests
|
|
40
|
+
run: make check-tests
|
|
41
|
+
|
|
42
|
+
- name: Check types
|
|
43
|
+
run: make check-types
|
|
44
|
+
|
|
45
|
+
- name: Check formatting
|
|
46
|
+
run: make check-format
|
|
@@ -7,5 +7,12 @@
|
|
|
7
7
|
},
|
|
8
8
|
"editor.defaultFormatter": "charliermarsh.ruff",
|
|
9
9
|
},
|
|
10
|
-
"flake8.args": [
|
|
11
|
-
|
|
10
|
+
"flake8.args": [
|
|
11
|
+
"--max-line-length=120"
|
|
12
|
+
],
|
|
13
|
+
"python.testing.pytestArgs": [
|
|
14
|
+
"tests"
|
|
15
|
+
],
|
|
16
|
+
"python.testing.unittestEnabled": false,
|
|
17
|
+
"python.testing.pytestEnabled": true
|
|
18
|
+
}
|
|
@@ -7,6 +7,123 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
7
7
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
-->
|
|
9
9
|
|
|
10
|
+
## [0.15.0] - 2026-01-06
|
|
11
|
+
|
|
12
|
+
### New features
|
|
13
|
+
|
|
14
|
+
* `ChatOpenAI()`, `ChatAnthropic()`, and `ChatGoogle()` gain a new `reasoning` parameter to easily opt-into, and fully customize, reasoning capabilities. (#202, #260)
|
|
15
|
+
* A new `ContentThinking` content type was added and captures the "thinking" portion of a reasoning model. (#192)
|
|
16
|
+
* Added "built-in" web search and URL fetch tools `tool_web_search()` and `tool_web_fetch()`:
|
|
17
|
+
* `tool_web_search()` is supported by OpenAI, Claude (Anthropic), and Google (Gemini).
|
|
18
|
+
* `tool_web_fetch()` is supported by Claude (requires beta header) and Google.
|
|
19
|
+
* New content types `ContentToolRequestSearch`, `ContentToolResponseSearch`, `ContentToolRequestFetch`, and `ContentToolResponseFetch` capture web tool interactions.
|
|
20
|
+
* Added `ToolBuiltIn` class to assist with specifying provider-specific built-in tools. This enables provider-specific functionality like OpenAI's image generation to be registered and used as tools. Built-in tools pass raw provider definitions directly to the API rather than wrapping Python functions. (#214)
|
|
21
|
+
* `ChatOpenAI()` and `ChatAzureOpenAI()` gain a new `service_tier` parameter to request a specific service tier (e.g., `"flex"` for slower/cheaper or `"priority"` for faster/more expensive). (#204)
|
|
22
|
+
* `ChatAuto()` now accepts `"claude"` as an alias for `"anthropic"`, reflecting Anthropic's rebranding of developer tools under the Claude name. (#239)
|
|
23
|
+
|
|
24
|
+
### Changes
|
|
25
|
+
|
|
26
|
+
* `repr()` now generally gives the same result as `str()` for many classes (`Chat`, `Turn`, `Content`, etc). This leads to a more human-readable result (and is closer to the result that gets `echo`ed by `.chat()`). (#245)
|
|
27
|
+
* The `Chat.get_cost()` method's `options` parameter was renamed to `include`. (#244)
|
|
28
|
+
* When supplying a `model` to `.register_tool(tool_func, model=ToolModel)`, the defaults for the `model` must match the `tool_func` defaults. Previously, if `tool_func` had defaults, but `ToolModel` didn't, those defaults would get silently ignored. (#253)
|
|
29
|
+
|
|
30
|
+
### Improvements
|
|
31
|
+
|
|
32
|
+
* `Chat` and `Turn` now have a `_repr_markdown_` method and an overall improved `repr()` experience. (#245)
|
|
33
|
+
* `ChatSnowflake()` now sets the `application` config parameter for partner identification. Defaults to `"py_chatlas"` but can be overridden via the `SF_PARTNER` environment variable. (#209)
|
|
34
|
+
|
|
35
|
+
### Bug fixes
|
|
36
|
+
|
|
37
|
+
* Fixed structured data extraction with `ChatAnthropic()` failing for Pydantic models containing nested types (e.g., `list[NestedModel]`). The issue was that `$defs` (containing nested type definitions) was incorrectly placed inside the schema, breaking JSON `$ref` pointer references. (#100)
|
|
38
|
+
* Fixed MCP tools failing with OpenAI providers due to strict mode schema validation. OpenAI's strict mode rejects standard JSON Schema features like `format: "uri"` and requires all properties in the `required` array. MCP tools now set `strict=false` to use standard JSON Schema conventions. (#255)
|
|
39
|
+
* Fixed MCP tools not working with `ChatGoogle()`. (#257)
|
|
40
|
+
* Tool functions parameters that are `typing.Annotated` with a `pydantic.Field` (e.g., `def add(x: Annotated[int, Field(description="First number")])`) are now handled correctly. (#251)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## [0.14.0] - 2025-12-09
|
|
44
|
+
|
|
45
|
+
### New features
|
|
46
|
+
|
|
47
|
+
* `ChatOpenAI()` (and `ChatAzureOpenAI()`) gain access to latest models, built-in tools, etc. as a result of moving to the new [Responses API](https://platform.openai.com/docs/api-reference/responses). (#192)
|
|
48
|
+
* Added new family of functions (`parallel_chat()`, `parallel_chat_text()`, and `parallel_chat_structured()`) for submitting multiple prompts at once with some basic rate limiting toggles. (#188)
|
|
49
|
+
* Tools can now return image or PDF content types, with `content_image_file()` or `content_pdf_file()` (#231).
|
|
50
|
+
* As a result, the experimental `ContentToolResultImage` and `ContentToolResultResource` were removed since this new support for generally supporting `ContentImage` and `ContentPDF` renders those content types redundant.
|
|
51
|
+
* Added support for systematic evaluation via [Inspect AI](https://inspect.aisi.org.uk/). This includes:
|
|
52
|
+
* A new `.export_eval()` method for exporting conversation history as an Inspect eval dataset sample. This supports multi-turn conversations, tool calls, images, PDFs, and structured data.
|
|
53
|
+
* A new `.to_solver()` method for translating chat instances into Inspect solvers that can be used with Inspect's evaluation framework.
|
|
54
|
+
* A new `Turn.to_inspect_messages()` method for converting turns to Inspect's message format.
|
|
55
|
+
* Comprehensive documentation in the [Evals guide](https://posit-dev.github.io/chatlas/misc/evals.html).
|
|
56
|
+
* `ChatAnthropic()` and `ChatBedrockAnthropic()` gain new `cache` parameter to control caching. For `ChatAnthropic()`, it defaults to `"5m"`, which should (on average) reduce the cost of your chats. For `ChatBedrockAnthropic()`, it defaults to `"none"`, since caching isn't guaranteed to be widely supported (#215)
|
|
57
|
+
* Added rudimentary support for a new `ContentThinking` type. (#192)
|
|
58
|
+
|
|
59
|
+
### Changes
|
|
60
|
+
|
|
61
|
+
* `ChatOpenAI()` (and `ChatAzureOpenAI()`) move from OpenAI's Completions API to [Responses API](https://platform.openai.com/docs/api-reference/responses). If this happens to break behavior, change `ChatOpenAI()` -> `ChatOpenAICompletions()` (or `ChatAzureOpenAI()` -> `ChatAzureOpenAICompletions()`). (#192)
|
|
62
|
+
* The `Turn` class is now a base class with three specialized subclasses: `UserTurn`, `AssistantTurn`, and `SystemTurn`. Use these new classes to construct turns by hand. (#224)
|
|
63
|
+
* The `.set_model_params()` method no longer accepts `kwargs`. Instead, use the new `chat.kwargs_chat` attribute to set chat input parameters that persist across the chat session. (#212)
|
|
64
|
+
* `Provider` implementations now require an additional `.value_tokens()` method. Previously, it was assumed that token info was logged and attached to the `Turn` as part of the `.value_turn()` method. The logging and attaching is now handled automatically. (#194)
|
|
65
|
+
|
|
66
|
+
### Improvements
|
|
67
|
+
|
|
68
|
+
* `ChatAnthropic()` and `ChatBedrockAnthropic()` now default to Claude Sonnet 4.5.
|
|
69
|
+
* `ChatGroq()` now defaults to llama-3.1-8b-instant.
|
|
70
|
+
* `Chat.chat()`, `Chat.stream()`, and related methods now automatically complete dangling tool requests when a chat is interrupted during a tool call loop, allowing the conversation to be resumed without causing API errors (#230).
|
|
71
|
+
* `content_pdf_file()` and `content_pdf_url()` now include relevant `filename` information. (#199)
|
|
72
|
+
|
|
73
|
+
### Bug fixes
|
|
74
|
+
|
|
75
|
+
* `.set_model_params()` now works correctly for `.*_async()` methods. (#198)
|
|
76
|
+
* `.chat_structured()` results are now included correctly into the multi-turn conversation history. (#203)
|
|
77
|
+
* `ChatAnthropic()` now drops empty assistant turns to avoid API errors when tools return side-effect only results. (#226)
|
|
78
|
+
|
|
79
|
+
## [0.13.2] - 2025-10-02
|
|
80
|
+
|
|
81
|
+
### Improvements
|
|
82
|
+
|
|
83
|
+
* `ContentToolResult`'s `.get_model_value()` method now calls `.to_json(orient="record")` (instead of `.to_json()`) when relevant. As a result, if a tool call returns a Pandas `DataFrame` (or similar), the model now receives a less confusing (and smaller) JSON format. (#183)
|
|
84
|
+
|
|
85
|
+
### Bug fixes
|
|
86
|
+
|
|
87
|
+
* `ChatAzureOpenAI()` and `ChatDatabricks()` now work as expected when a `OPENAI_API_KEY` environment variable isn't present. (#185)
|
|
88
|
+
|
|
89
|
+
## [0.13.1] - 2025-09-18
|
|
90
|
+
|
|
91
|
+
### Bug fixes
|
|
92
|
+
|
|
93
|
+
* `ChatGithub()` once again uses the appropriate `base_url` when generating reponses (problem introduced in v0.11.0). (#182)
|
|
94
|
+
|
|
95
|
+
## [0.13.0] - 2025-09-10
|
|
96
|
+
|
|
97
|
+
### New features
|
|
98
|
+
|
|
99
|
+
* Added support for submitting multiple chats in one batch. With batch submission, results can take up to 24 hours to complete, but in return you pay ~50% less than usual. For more, see the [reference](https://posit-dev.github.io/chatlas/reference/) for `batch_chat()`, `batch_chat_text()`, `batch_chat_structured()` and `batch_chat_completed()`. (#177)
|
|
100
|
+
* The `Chat` class gains new `.chat_structured()` (and `.chat_structured_async()`) methods. These methods supersede the now deprecated `.extract_data()` (and `.extract_data_async()`). The only difference is that the new methods return a `BaseModel` instance (instead of a `dict()`), leading to a better type hinting/checking experience. (#175)
|
|
101
|
+
* The `.get_turns()` method gains a `tool_result_role` parameter. Set `tool_result_role="assistant"` to collect tool result content (plus the surrounding assistant turn contents) into a single assistant turn. This is convenient for display purposes and more generally if you want the tool calling loop to be contained in a single turn. (#179)
|
|
102
|
+
|
|
103
|
+
### Improvements
|
|
104
|
+
|
|
105
|
+
* The `.app()` method now:
|
|
106
|
+
* Enables bookmarking by default (i.e., chat session survives page reload). (#179)
|
|
107
|
+
* Correctly renders pre-existing turns that contain tool calls. (#179)
|
|
108
|
+
|
|
109
|
+
## [0.12.0] - 2025-09-08
|
|
110
|
+
|
|
111
|
+
### Breaking changes
|
|
112
|
+
|
|
113
|
+
* `ChatAuto()`'s first (optional) positional parameter has changed from `system_prompt` to `provider_model`, and `system_prompt` is now a keyword parameter. As a result, you may need to change `ChatAuto("[system prompt]")` -> `ChatAuto(system_prompt="[system prompt]")`. In addition, the `provider` and `model` keyword arguments are now deprecated, but continue to work with a warning, as are the previous `CHATLAS_CHAT_PROVIDER` and `CHATLAS_CHAT_MODEL` environment variables. (#159)
|
|
114
|
+
|
|
115
|
+
### New features
|
|
116
|
+
|
|
117
|
+
* `ChatAuto()`'s new `provider_model` takes both provider and model in a single string in the format `"{provider}/{model}"`, e.g. `"openai/gpt-5"`. If not provided, `ChatAuto()` looks for the `CHATLAS_CHAT_PROVIDER_MODEL` environment variable, defaulting to `"openai"` if neither are provided. Unlike previous versions of `ChatAuto()`, the environment variables are now used *only if function arguments are not provided*. In other words, if `provider_model` is given, the `CHATLAS_CHAT_PROVIDER_MODEL` environment variable is ignored. Similarly, `CHATLAS_CHAT_ARGS` are only used if no `kwargs` are provided. This improves interactive use cases, makes it easier to introduce application-specific environment variables, and puts more control in the hands of the developer. (#159)
|
|
118
|
+
* The `.register_tool()` method now:
|
|
119
|
+
* Accepts a `Tool` instance as input. This is primarily useful for binding things like `annotations` to the `Tool` in one place, and registering it in another. (#172)
|
|
120
|
+
* Supports function parameter names that start with an underscore. (#174)
|
|
121
|
+
* The `ToolAnnotations` type gains an `extra` key field -- providing a place for providing additional information that other consumers of tool annotations (e.g., [shinychat](https://posit-dev.github.io/shinychat/)) may make use of.
|
|
122
|
+
|
|
123
|
+
### Bug fixes
|
|
124
|
+
|
|
125
|
+
* `ChatAuto()` now supports recently added providers such as `ChatCloudflare()`, `ChatDeepseek()`, `ChatHuggingFace()`, etc. (#159)
|
|
126
|
+
|
|
10
127
|
## [0.11.1] - 2025-08-29
|
|
11
128
|
|
|
12
129
|
### New features
|
|
@@ -22,7 +139,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
22
139
|
|
|
23
140
|
* `.register_tool(annotations=annotations)` drops support for `mcp.types.ToolAnnotations()` and instead expects a dictionary of the same info. (#164)
|
|
24
141
|
|
|
25
|
-
|
|
26
142
|
## [0.11.0] - 2025-08-26
|
|
27
143
|
|
|
28
144
|
### New features
|
|
@@ -42,7 +158,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
42
158
|
|
|
43
159
|
### New features
|
|
44
160
|
|
|
45
|
-
* Added `ChatCloudflare()` for chatting via [Cloudflare AI](https://developers.cloudflare.com/workers-ai/get-started/rest-api/). (#150)
|
|
161
|
+
* Added `ChatCloudflare()` for chatting via [Cloudflare AI](https://developers.cloudflare.com/workers-ai/get-started/rest-api/). (#150)
|
|
46
162
|
* Added `ChatDeepSeek()` for chatting via [DeepSeek](https://www.deepseek.com/). (#147)
|
|
47
163
|
* Added `ChatOpenRouter()` for chatting via [Open Router](https://openrouter.ai/). (#148)
|
|
48
164
|
* Added `ChatHuggingFace()` for chatting via [Hugging Face](https://huggingface.co/). (#144)
|
|
@@ -78,7 +194,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
78
194
|
|
|
79
195
|
### New features
|
|
80
196
|
|
|
81
|
-
* `Chat` gains a handful of new methods:
|
|
197
|
+
* `Chat` gains a handful of new methods:
|
|
82
198
|
* `.register_mcp_tools_http_stream_async()` and `.register_mcp_tools_stdio_async()`: for registering tools from a [MCP server](https://modelcontextprotocol.io/). (#39)
|
|
83
199
|
* `.get_tools()` and `.set_tools()`: for fine-grained control over registered tools. (#39)
|
|
84
200
|
* `.set_model_params()`: for setting common LLM parameters in a model-agnostic fashion. (#127)
|
|
@@ -87,7 +203,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
87
203
|
* Tool functions passed to `.register_tool()` can now `yield` numerous results. (#39)
|
|
88
204
|
* A `ContentToolResultImage` content class was added for returning images from tools. It is currently only works with `ChatAnthropic`. (#39)
|
|
89
205
|
* A `Tool` can now be constructed from a pre-existing tool schema (via a new `__init__` method). (#39)
|
|
90
|
-
* The `Chat.app()` method gains a `host` parameter. (#122)
|
|
206
|
+
* The `Chat.app()` method gains a `host` parameter. (#122)
|
|
91
207
|
* `ChatGithub()` now supports the more standard `GITHUB_TOKEN` environment variable for storing the API key. (#123)
|
|
92
208
|
|
|
93
209
|
### Changes
|
|
@@ -149,7 +265,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
149
265
|
|
|
150
266
|
## [0.7.1] - 2025-05-10
|
|
151
267
|
|
|
152
|
-
* Added `openai` as a hard dependency, making installation easier for a wide range of use cases. (#91)
|
|
268
|
+
* Added `openai` as a hard dependency, making installation easier for a wide range of use cases. (#91)
|
|
153
269
|
|
|
154
270
|
## [0.7.0] - 2025-04-22
|
|
155
271
|
|
|
@@ -159,7 +275,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
159
275
|
* `.stream()` and `.stream_async()` gain a `content` argument. Set this to `"all"` to include `ContentToolResult`/`ContentToolRequest` objects in the stream. (#75)
|
|
160
276
|
* `ContentToolResult`/`ContentToolRequest` are now exported to `chatlas` namespace. (#75)
|
|
161
277
|
* `ContentToolResult`/`ContentToolRequest` gain a `.tagify()` method so they render sensibly in a Shiny app. (#75)
|
|
162
|
-
* A tool can now return a `ContentToolResult`. This is useful for:
|
|
278
|
+
* A tool can now return a `ContentToolResult`. This is useful for:
|
|
163
279
|
* Specifying the format used for sending the tool result to the chat model (`model_format`). (#87)
|
|
164
280
|
* Custom rendering of the tool result (by overriding relevant methods in a subclass). (#75)
|
|
165
281
|
* `Chat` gains a new `.current_display` property. When a `.chat()` or `.stream()` is currently active, this property returns an object with a `.echo()` method (to echo new content to the display). This is primarily useful for displaying custom content during a tool call. (#79)
|
|
@@ -7,13 +7,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
7
7
|
The project uses `uv` for package management and Make for common tasks:
|
|
8
8
|
|
|
9
9
|
- **Setup environment**: `make setup` (installs all dependencies with `uv sync --all-extras`)
|
|
10
|
-
- **Run tests**: `make check-tests` or `uv run pytest`
|
|
10
|
+
- **Run tests**: `make check-tests` or `uv run pytest` (uses VCR cassettes by default)
|
|
11
11
|
- **Type checking**: `make check-types` or `uv run pyright`
|
|
12
12
|
- **Linting/formatting**: `make check-format` (check) or `make format` (fix)
|
|
13
13
|
- **Full checks**: `make check` (runs format, type, and test checks)
|
|
14
14
|
- **Build package**: `make build` (creates dist/ with built package)
|
|
15
15
|
- **Run single test**: `uv run pytest tests/test_specific_file.py::TestClass::test_method -v`
|
|
16
16
|
- **Update snapshots**: `make update-snaps` (for syrupy snapshot tests)
|
|
17
|
+
- **Update VCR cassettes**: `make update-snaps-vcr` (re-records HTTP interactions, requires API keys)
|
|
18
|
+
- **Check VCR secrets**: `make check-vcr-secrets` (scans cassettes for leaked credentials)
|
|
17
19
|
- **Documentation**: `make docs` (build) or `make docs-preview` (serve locally)
|
|
18
20
|
|
|
19
21
|
## Project Architecture
|
|
@@ -49,6 +51,14 @@ The project uses `uv` for package management and Make for common tasks:
|
|
|
49
51
|
4. **Content-Based Messaging**: All communication uses structured `Content` objects rather than raw strings
|
|
50
52
|
5. **Tool Integration**: Seamless function calling with automatic JSON schema generation from Python type hints
|
|
51
53
|
|
|
54
|
+
### Typing Best Practices
|
|
55
|
+
|
|
56
|
+
This project prioritizes strong typing that leverages provider SDK types directly:
|
|
57
|
+
|
|
58
|
+
- **Use provider SDK types**: Import and use types from `openai.types`, `anthropic.types`, `google.genai.types`, etc. rather than creating custom TypedDicts or dataclasses that mirror them. This ensures compatibility with SDK updates and provides better IDE support.
|
|
59
|
+
- **Use `@overload` for provider-specific returns**: When a method returns different types based on a provider argument, use `@overload` with `Literal` types to give callers precise return type information.
|
|
60
|
+
- **Explore SDK types interactively**: Use `python -c "from <sdk>.types import <Type>; print(<Type>.__annotations__)"` to inspect available fields and nested types when implementing provider-specific features.
|
|
61
|
+
|
|
52
62
|
### Testing Structure
|
|
53
63
|
|
|
54
64
|
- Tests are organized by component (e.g., `test_provider_openai.py`, `test_tools.py`)
|
|
@@ -56,6 +66,46 @@ The project uses `uv` for package management and Make for common tasks:
|
|
|
56
66
|
- MCP server tests use local test servers in `tests/mcp_servers/`
|
|
57
67
|
- Async tests configured via `pytest.ini` with `asyncio_mode=strict`
|
|
58
68
|
|
|
69
|
+
### VCR Testing (HTTP Recording/Replay)
|
|
70
|
+
|
|
71
|
+
Tests use [pytest-recording](https://github.com/kiwicom/pytest-recording) (wrapping vcrpy) to record and replay HTTP interactions:
|
|
72
|
+
|
|
73
|
+
- **Cassettes**: YAML files stored in `tests/_vcr/` organized by test module
|
|
74
|
+
- **Default mode**: Tests replay cassettes without making live API calls
|
|
75
|
+
- **Recording**: Use `make update-snaps-vcr` or `uv run pytest --record-mode=rewrite` (requires real API keys)
|
|
76
|
+
- **Dummy credentials**: Auto-set by `conftest.py` when env vars are missing, enabling VCR replay without secrets
|
|
77
|
+
|
|
78
|
+
**Adding VCR to tests**:
|
|
79
|
+
```python
|
|
80
|
+
from .conftest import make_vcr_config, VCR_MATCH_ON_WITHOUT_BODY
|
|
81
|
+
|
|
82
|
+
# Most tests use default config (matches on request body)
|
|
83
|
+
@pytest.mark.vcr
|
|
84
|
+
def test_provider_simple():
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
# For tests with dynamic request bodies (temp files, generated IDs)
|
|
88
|
+
@pytest.fixture(scope="module")
|
|
89
|
+
def vcr_config():
|
|
90
|
+
return make_vcr_config(match_on=VCR_MATCH_ON_WITHOUT_BODY)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Tests requiring live API** (skip in VCR mode):
|
|
94
|
+
```python
|
|
95
|
+
from .conftest import is_dummy_credential
|
|
96
|
+
|
|
97
|
+
@pytest.mark.skipif(
|
|
98
|
+
is_dummy_credential("ANTHROPIC_API_KEY"),
|
|
99
|
+
reason="This test requires live API calls",
|
|
100
|
+
)
|
|
101
|
+
def test_multi_sample():
|
|
102
|
+
...
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Providers incompatible with VCR**: Bedrock and Snowflake require live API tests due to auth mechanisms.
|
|
106
|
+
|
|
107
|
+
See `docs/dev/vcr-tests.md` for comprehensive documentation.
|
|
108
|
+
|
|
59
109
|
### Documentation
|
|
60
110
|
|
|
61
111
|
Documentation is built with Quarto and quartodoc:
|
|
@@ -112,18 +162,31 @@ When implementing a new LLM provider, follow this systematic approach:
|
|
|
112
162
|
```python
|
|
113
163
|
import os
|
|
114
164
|
import pytest
|
|
115
|
-
|
|
165
|
+
|
|
116
166
|
do_test = os.getenv("TEST_[NAME]", "true")
|
|
117
167
|
if do_test.lower() == "false":
|
|
118
168
|
pytest.skip("Skipping [Name] tests", allow_module_level=True)
|
|
119
169
|
```
|
|
120
|
-
3. **
|
|
170
|
+
3. **Add VCR support** (for most providers):
|
|
171
|
+
```python
|
|
172
|
+
@pytest.mark.vcr
|
|
173
|
+
def test_[name]_simple_request():
|
|
174
|
+
...
|
|
175
|
+
```
|
|
176
|
+
For async tests, put `@pytest.mark.vcr` before `@pytest.mark.asyncio`.
|
|
177
|
+
4. **Use standard test patterns**:
|
|
121
178
|
- `test_[name]_simple_request()`
|
|
122
|
-
- `test_[name]_simple_streaming_request()`
|
|
179
|
+
- `test_[name]_simple_streaming_request()`
|
|
123
180
|
- `test_[name]_respects_turns_interface()`
|
|
124
181
|
- `test_[name]_tool_variations()` (if supported)
|
|
125
182
|
- `test_data_extraction()`
|
|
126
183
|
- `test_[name]_images()` (if vision supported)
|
|
184
|
+
5. **Record VCR cassettes**:
|
|
185
|
+
```bash
|
|
186
|
+
# Set real API key, then record
|
|
187
|
+
export [PROVIDER]_API_KEY="..."
|
|
188
|
+
uv run pytest tests/test_provider_[name].py -v --record-mode=rewrite
|
|
189
|
+
```
|
|
127
190
|
|
|
128
191
|
### 4. Package Integration
|
|
129
192
|
1. **Update `chatlas/__init__.py`**:
|
|
@@ -133,8 +196,9 @@ When implementing a new LLM provider, follow this systematic approach:
|
|
|
133
196
|
2. **Run validation**:
|
|
134
197
|
```bash
|
|
135
198
|
uv run pyright chatlas/_provider_[name].py
|
|
136
|
-
|
|
199
|
+
uv run pytest tests/test_provider_[name].py -v # Replays VCR cassettes
|
|
137
200
|
uv run python -c "from chatlas import Chat[Name]; print('Import successful')"
|
|
201
|
+
make check-vcr-secrets # Ensure no secrets leaked in cassettes
|
|
138
202
|
```
|
|
139
203
|
|
|
140
204
|
### 5. Provider-Specific Customizations
|
|
@@ -164,4 +228,12 @@ When implementing a new LLM provider, follow this systematic approach:
|
|
|
164
228
|
|
|
165
229
|
## Connections to ellmer
|
|
166
230
|
|
|
167
|
-
This project is the Python equivalent of the R package ellmer. The source code for ellmer is available in a sibling directory to this project. Before implementing new features or bug fixes in chatlas, it may be useful to consult the ellmer codebase to: (1) check whether the feature/fix already exists on the R side and (2) make sure the projects are aligned in terms of stylistic approaches. Note also that ellmer itself has a CLAUDE.md file which has a useful overview of the project.
|
|
231
|
+
This project is the Python equivalent of the R package ellmer. The source code for ellmer is available in a sibling directory to this project. Before implementing new features or bug fixes in chatlas, it may be useful to consult the ellmer codebase to: (1) check whether the feature/fix already exists on the R side and (2) make sure the projects are aligned in terms of stylistic approaches. Note also that ellmer itself has a CLAUDE.md file which has a useful overview of the project.
|
|
232
|
+
|
|
233
|
+
## Differences from ellmer
|
|
234
|
+
|
|
235
|
+
One important difference to note is that in `ellmer::chat_openai()` uses the completions API, while `chatlas.ChatOpenAI()` uses the responses API. Look to `ellmer::chat_openai_responses()` and `chatlas.ChatOpenAICompletions()` for the "non-default" API.
|
|
236
|
+
|
|
237
|
+
## Access to gh CLI
|
|
238
|
+
|
|
239
|
+
If ellmer or chatlas issues or PRs are referenced, try using the `gh` CLI tool to gain necessary context. They live at `tidyverse/ellmer` and `posit-dev/chatlas`
|
|
@@ -66,6 +66,16 @@ update-snaps:
|
|
|
66
66
|
@echo "📸 Updating pytest snapshots"
|
|
67
67
|
uv run pytest --snapshot-update
|
|
68
68
|
|
|
69
|
+
.PHONY: update-snaps-vcr
|
|
70
|
+
update-snaps-vcr:
|
|
71
|
+
@echo "📼 Updating VCR cassettes"
|
|
72
|
+
uv run pytest --record-mode=rewrite
|
|
73
|
+
|
|
74
|
+
.PHONY: check-vcr-secrets
|
|
75
|
+
check-vcr-secrets: ## [py] Scan VCR cassettes for leaked secrets using Claude
|
|
76
|
+
@echo "🤖 Running Claude-based secret scan..."
|
|
77
|
+
uv run python scripts/check_vcr_secrets.py
|
|
78
|
+
|
|
69
79
|
.PHONY: update-types
|
|
70
80
|
update-types:
|
|
71
81
|
@echo "📝 Updating chat provider types"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chatlas
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: A simple and consistent interface for chatting with LLMs
|
|
5
5
|
Project-URL: Homepage, https://posit-dev.github.io/chatlas
|
|
6
6
|
Project-URL: Documentation, https://posit-dev.github.io/chatlas
|
|
@@ -13,11 +13,11 @@ License-File: LICENSE
|
|
|
13
13
|
Classifier: Development Status :: 4 - Beta
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
21
|
Requires-Python: >=3.9
|
|
22
22
|
Requires-Dist: jinja2
|
|
23
23
|
Requires-Dist: openai
|
|
@@ -38,12 +38,16 @@ Requires-Dist: databricks-sdk; extra == 'dev'
|
|
|
38
38
|
Requires-Dist: google-genai>=1.14.0; extra == 'dev'
|
|
39
39
|
Requires-Dist: htmltools; extra == 'dev'
|
|
40
40
|
Requires-Dist: matplotlib; extra == 'dev'
|
|
41
|
+
Requires-Dist: narwhals; extra == 'dev'
|
|
41
42
|
Requires-Dist: numpy>1.24.4; extra == 'dev'
|
|
42
43
|
Requires-Dist: openai; extra == 'dev'
|
|
44
|
+
Requires-Dist: pandas; extra == 'dev'
|
|
43
45
|
Requires-Dist: pillow; extra == 'dev'
|
|
46
|
+
Requires-Dist: polars; extra == 'dev'
|
|
44
47
|
Requires-Dist: python-dotenv; extra == 'dev'
|
|
45
48
|
Requires-Dist: ruff>=0.6.5; extra == 'dev'
|
|
46
49
|
Requires-Dist: shiny; extra == 'dev'
|
|
50
|
+
Requires-Dist: shinychat; extra == 'dev'
|
|
47
51
|
Requires-Dist: snowflake-ml-python>=1.8.4; extra == 'dev'
|
|
48
52
|
Requires-Dist: tenacity; extra == 'dev'
|
|
49
53
|
Requires-Dist: tiktoken; extra == 'dev'
|
|
@@ -59,6 +63,8 @@ Requires-Dist: pandas; extra == 'docs'
|
|
|
59
63
|
Requires-Dist: pyyaml; extra == 'docs'
|
|
60
64
|
Requires-Dist: quartodoc>=0.7; extra == 'docs'
|
|
61
65
|
Requires-Dist: sentence-transformers; extra == 'docs'
|
|
66
|
+
Provides-Extra: eval
|
|
67
|
+
Requires-Dist: inspect-ai; (python_version >= '3.10') and extra == 'eval'
|
|
62
68
|
Provides-Extra: github
|
|
63
69
|
Provides-Extra: google
|
|
64
70
|
Requires-Dist: google-genai>=1.14.0; extra == 'google'
|
|
@@ -73,8 +79,10 @@ Requires-Dist: snowflake-ml-python<=1.9.0; extra == 'snowflake'
|
|
|
73
79
|
Provides-Extra: test
|
|
74
80
|
Requires-Dist: pyright>=1.1.379; extra == 'test'
|
|
75
81
|
Requires-Dist: pytest-asyncio; extra == 'test'
|
|
82
|
+
Requires-Dist: pytest-recording>=0.13; extra == 'test'
|
|
76
83
|
Requires-Dist: pytest>=8.3.2; extra == 'test'
|
|
77
84
|
Requires-Dist: syrupy>=4; extra == 'test'
|
|
85
|
+
Requires-Dist: vcrpy>=6.0.0; extra == 'test'
|
|
78
86
|
Provides-Extra: vertex
|
|
79
87
|
Requires-Dist: google-genai>=1.14.0; extra == 'vertex'
|
|
80
88
|
Description-Content-Type: text/markdown
|