ccproxy-api 0.1.1__tar.gz → 0.1.2__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.
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/CHANGELOG.md +15 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/PKG-INFO +1 -1
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/_version.py +2 -2
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/dependencies.py +3 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/claude_sdk/converter.py +1 -1
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/claude_sdk/options.py +23 -1
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/commands/__init__.py +2 -1
- ccproxy_api-0.1.2/ccproxy/cli/commands/permission.py +128 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/commands/serve.py +22 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/main.py +1 -1
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/options/claude_options.py +22 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/settings.py +2 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/models/responses.py +36 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/claude_sdk_service.py +5 -1
- ccproxy_api-0.1.2/docs/examples.md +384 -0
- ccproxy_api-0.1.2/docs/index.md +279 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/pyproject.toml +1 -0
- ccproxy_api-0.1.1/docs/examples.md +0 -114
- ccproxy_api-0.1.1/docs/index.md +0 -175
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.env.example +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.github/workflows/backend.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.github/workflows/build.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.github/workflows/ci.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.github/workflows/docs.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.github/workflows/frontend.yml.disabled +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.github/workflows/release.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.gitignore +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.pre-commit-config.yaml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/.python-version +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/CONTRIBUTING.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/CONVENTIONS.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/Dockerfile +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/LICENSE +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/Makefile +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/README.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/TESTING.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/__main__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/adapters/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/adapters/base.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/adapters/openai/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/adapters/openai/adapter.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/adapters/openai/models.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/adapters/openai/streaming.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/app.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/auth.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/cors.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/errors.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/headers.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/logging.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/request_id.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/middleware/server_header.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/responses.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/routes/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/routes/claude.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/routes/health.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/routes/metrics.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/api/routes/proxy.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/bearer.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/conditional.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/credentials_adapter.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/dependencies.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/exceptions.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/manager.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/models.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/oauth/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/oauth/models.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/oauth/routes.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/oauth/storage.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/storage/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/storage/base.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/storage/json_file.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/auth/storage/keyring.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/claude_sdk/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/claude_sdk/client.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/commands/auth.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/commands/config/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/commands/config/commands.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/commands/config/schema_commands.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/docker/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/docker/adapter_factory.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/docker/params.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/helpers.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/options/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/options/core_options.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/options/security_options.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/cli/options/server_options.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/auth.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/claude.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/cors.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/discovery.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/docker_settings.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/loader.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/observability.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/pricing.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/reverse_proxy.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/scheduler.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/security.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/server.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/config/validators.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/async_utils.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/constants.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/errors.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/http.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/http_transformers.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/interfaces.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/logging.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/middleware.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/proxy.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/system.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/transformers.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/types.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/core/validators.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/adapter.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/docker_path.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/middleware.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/models.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/protocol.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/stream_process.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/docker/validators.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/models/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/models/errors.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/models/messages.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/models/requests.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/models/types.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/access_logger.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/context.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/metrics.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/pushgateway.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/sse_events.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/stats_printer.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/storage/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/storage/duckdb_simple.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/observability/storage/models.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/pricing/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/pricing/cache.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/pricing/loader.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/pricing/models.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/pricing/updater.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/scheduler/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/scheduler/core.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/scheduler/exceptions.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/scheduler/manager.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/scheduler/registry.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/scheduler/tasks.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/credentials/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/credentials/config.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/credentials/manager.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/credentials/oauth_client.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/services/proxy_service.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/static/.keep +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/testing/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/testing/config.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/testing/content_generation.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/testing/mock_responses.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/testing/response_handlers.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/testing/scenarios.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/utils/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/utils/cost_calculator.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/ccproxy/utils/streaming_metrics.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/data/metrics.db +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/devenv.lock +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/devenv.nix +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docker-compose.monitoring.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docker-compose.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/README.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/api-reference.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/assets/extra.css +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/assets/extra.js +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/contributing.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/development/debugging-with-proxy.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/gen_ref_pages.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/getting-started/configuration.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/getting-started/installation.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/getting-started/quickstart.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/metrics-api.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/observability.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/systemd-setup.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/api-usage.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/authentication.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/claude-code-options.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/claude-sdk-compatibility.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/mcp-integration.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/pool-configuration.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/docs/user-guide/understanding-pool-logs.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/README.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/README_chat_agent.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/ai_code_discussion_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/anthropic_streaming_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/anthropic_tools_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/client.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/common_utils.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/console_utils.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_anthropic_conversation_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_claude_code_options_example.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_json_object_example.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_json_schema_example.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_streaming_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_structured_response_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_thinking_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/openai_tools_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/project_code_access_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/simple_thinking_demo.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/examples/textual_chat_agent.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/mkdocs.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/monitoring/grafana/dashboards/ccproxy-dashboard.json +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/monitoring/grafana/provisioning/dashboards/dashboard.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/monitoring/grafana/provisioning/datasources/victoria-metrics.yml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/act-run.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/benchmark_startup_node.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/build-docs.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/entrypoint.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/format_version.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/serve-docs.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/setup-systemd.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/setup.sh +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/scripts/traffic_generator.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/systemd/ccproxy.service.template +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/test_config/test-config.toml +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/conftest.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/factories/MIGRATION_GUIDE.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/factories/README.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/factories/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/factories/fastapi_factory.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/MIGRATION_GUIDE.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/README.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/auth/MIGRATION_GUIDE.md +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/auth/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/auth/example_usage.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/claude_sdk/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/claude_sdk/internal_mocks.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/claude_sdk/responses.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/credentials.json +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/external_apis/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/external_apis/anthropic_api.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/proxy_service/__init__.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/proxy_service/oauth_mocks.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/fixtures/responses.json +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_access_logger_integration.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_adapters.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_api.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_auth.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_cli_auth_commands.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_cli_config.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_cli_serve.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_docker.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_duckdb_lifecycle.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_duckdb_settings_integration.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_fastapi_factory.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_http_transformers.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_metrics_api.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_observability.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_pricing.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_pushgateway_error_handling.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_queue_duckdb_storage.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_reset_endpoint.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_scheduler.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_scheduler_tasks.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_sse_events.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_sse_stream_filtering.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_stats_printer.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/tests/test_streaming.py +0 -0
- {ccproxy_api-0.1.1 → ccproxy_api-0.1.2}/uv.lock +0 -0
|
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.2] - 2025-07-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Permission Mode Support**: Restored `--permission-mode` option supporting default, acceptEdits, and bypassPermissions modes
|
|
12
|
+
- **Custom Permission Tool**: Restored `--permission-prompt-tool-name` option to specify custom permission tool names
|
|
13
|
+
- **Permission Response Models**: Added `PermissionToolAllowResponse` and `PermissionToolDenyResponse` models with proper JSON serialization
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **Message Formatting**: Modified `MessageConverter.combine_text_parts()` to join text parts with newlines instead of spaces, preserving formatting in multi-line content
|
|
17
|
+
- **Settings Integration**: Enhanced OptionsHandler to apply default Claude options from settings before API parameters
|
|
18
|
+
- **Configuration**: Extended settings to persist permission_mode and permission_prompt_tool_name
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- **Claude SDK Options**: Integrated Settings dependency into ClaudeSDKService to support configuration-based options
|
|
22
|
+
|
|
8
23
|
## [0.1.1] - 2025-07-22
|
|
9
24
|
|
|
10
25
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ccproxy-api
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: API server that provides an Anthropic and OpenAI compatible interface over Claude Code, allowing to use your Claude OAuth account or over the API.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -22,11 +22,13 @@ SettingsDep = Annotated[Settings, Depends(get_settings)]
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def get_claude_service(
|
|
25
|
+
settings: SettingsDep,
|
|
25
26
|
auth_manager: AuthManagerDep,
|
|
26
27
|
) -> ClaudeSDKService:
|
|
27
28
|
"""Get Claude SDK service instance.
|
|
28
29
|
|
|
29
30
|
Args:
|
|
31
|
+
settings: Application settings dependency
|
|
30
32
|
auth_manager: Authentication manager dependency
|
|
31
33
|
|
|
32
34
|
Returns:
|
|
@@ -39,6 +41,7 @@ def get_claude_service(
|
|
|
39
41
|
return ClaudeSDKService(
|
|
40
42
|
auth_manager=auth_manager,
|
|
41
43
|
metrics=metrics,
|
|
44
|
+
settings=settings,
|
|
42
45
|
)
|
|
43
46
|
|
|
44
47
|
|
|
@@ -109,7 +109,7 @@ class MessageConverter:
|
|
|
109
109
|
for block in contents:
|
|
110
110
|
text_parts.append(MessageConverter.extract_text_from_content(block))
|
|
111
111
|
|
|
112
|
-
return "
|
|
112
|
+
return "\n".join(text_parts)
|
|
113
113
|
|
|
114
114
|
@staticmethod
|
|
115
115
|
def convert_to_anthropic_response(
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
+
from ccproxy.config.settings import Settings
|
|
5
6
|
from ccproxy.core.async_utils import patched_typing
|
|
6
7
|
|
|
7
8
|
|
|
@@ -14,8 +15,17 @@ class OptionsHandler:
|
|
|
14
15
|
Handles creation and management of Claude SDK options.
|
|
15
16
|
"""
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
def __init__(self, settings: Settings | None = None) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Initialize options handler.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
settings: Application settings containing default Claude options
|
|
24
|
+
"""
|
|
25
|
+
self.settings = settings
|
|
26
|
+
|
|
18
27
|
def create_options(
|
|
28
|
+
self,
|
|
19
29
|
model: str,
|
|
20
30
|
temperature: float | None = None,
|
|
21
31
|
max_tokens: int | None = None,
|
|
@@ -37,6 +47,18 @@ class OptionsHandler:
|
|
|
37
47
|
"""
|
|
38
48
|
options = ClaudeCodeOptions(model=model)
|
|
39
49
|
|
|
50
|
+
# First apply settings from configuration if available
|
|
51
|
+
if self.settings and self.settings.claude.code_options:
|
|
52
|
+
code_opts = self.settings.claude.code_options
|
|
53
|
+
|
|
54
|
+
# Apply settings from configuration
|
|
55
|
+
for attr_name in dir(code_opts):
|
|
56
|
+
if not attr_name.startswith("_"):
|
|
57
|
+
value = getattr(code_opts, attr_name, None)
|
|
58
|
+
if value is not None and hasattr(options, attr_name):
|
|
59
|
+
setattr(options, attr_name, value)
|
|
60
|
+
|
|
61
|
+
# Then apply API parameters (these override settings)
|
|
40
62
|
if temperature is not None:
|
|
41
63
|
options.temperature = temperature # type: ignore[attr-defined]
|
|
42
64
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""MCP permission prompt tool for Claude Code SDK."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Annotated, Any, Optional
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from structlog import get_logger
|
|
9
|
+
|
|
10
|
+
from ccproxy.config.settings import config_manager
|
|
11
|
+
from ccproxy.models.responses import (
|
|
12
|
+
PermissionToolAllowResponse,
|
|
13
|
+
PermissionToolDenyResponse,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
app = typer.Typer(
|
|
18
|
+
rich_markup_mode="rich",
|
|
19
|
+
add_completion=False,
|
|
20
|
+
no_args_is_help=False,
|
|
21
|
+
pretty_exceptions_enable=False,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
logger = get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@app.command()
|
|
28
|
+
def permission_tool(
|
|
29
|
+
tool_name: Annotated[
|
|
30
|
+
str, typer.Argument(help="Name of the tool to check permissions for")
|
|
31
|
+
],
|
|
32
|
+
tool_input: Annotated[str, typer.Argument(help="JSON string of the tool input")],
|
|
33
|
+
config: Annotated[
|
|
34
|
+
Path | None,
|
|
35
|
+
typer.Option(
|
|
36
|
+
"--config",
|
|
37
|
+
"-c",
|
|
38
|
+
help="Path to configuration file (TOML, JSON, or YAML)",
|
|
39
|
+
exists=True,
|
|
40
|
+
file_okay=True,
|
|
41
|
+
dir_okay=False,
|
|
42
|
+
readable=True,
|
|
43
|
+
),
|
|
44
|
+
] = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
"""
|
|
47
|
+
MCP permission prompt tool for Claude Code SDK.
|
|
48
|
+
|
|
49
|
+
This tool is used by the Claude Code SDK to check permissions for tool calls.
|
|
50
|
+
It returns a JSON response indicating whether the tool call should be allowed or denied.
|
|
51
|
+
|
|
52
|
+
Response format:
|
|
53
|
+
- Allow: {"behavior": "allow", "updatedInput": {...}}
|
|
54
|
+
- Deny: {"behavior": "deny", "message": "reason"}
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
ccproxy-perm "bash" '{"command": "ls -la"}'
|
|
58
|
+
ccproxy-perm "edit_file" '{"path": "/etc/passwd", "content": "..."}'
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
# Parse the tool input JSON
|
|
63
|
+
try:
|
|
64
|
+
input_data = json.loads(tool_input)
|
|
65
|
+
except json.JSONDecodeError as e:
|
|
66
|
+
response = PermissionToolDenyResponse(message=f"Invalid JSON input: {e}")
|
|
67
|
+
print(response.model_dump_json(by_alias=True))
|
|
68
|
+
raise typer.Exit(1) from e
|
|
69
|
+
|
|
70
|
+
# Load settings to get permission configuration
|
|
71
|
+
settings = config_manager.load_settings(config_path=config)
|
|
72
|
+
|
|
73
|
+
# Basic permission checking logic
|
|
74
|
+
# This can be extended with more sophisticated rules
|
|
75
|
+
|
|
76
|
+
# Check for potentially dangerous commands
|
|
77
|
+
dangerous_patterns = [
|
|
78
|
+
"rm -rf",
|
|
79
|
+
"sudo",
|
|
80
|
+
"passwd",
|
|
81
|
+
"chmod 777",
|
|
82
|
+
"/etc/passwd",
|
|
83
|
+
"/etc/shadow",
|
|
84
|
+
"format",
|
|
85
|
+
"mkfs",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
# Convert input to string for pattern matching
|
|
89
|
+
input_str = json.dumps(input_data).lower()
|
|
90
|
+
|
|
91
|
+
# Check for dangerous patterns
|
|
92
|
+
for pattern in dangerous_patterns:
|
|
93
|
+
if pattern in input_str:
|
|
94
|
+
response = PermissionToolDenyResponse(
|
|
95
|
+
message=f"Tool call contains potentially dangerous pattern: {pattern}"
|
|
96
|
+
)
|
|
97
|
+
print(response.model_dump_json(by_alias=True))
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
# Check for specific tool restrictions
|
|
101
|
+
restricted_tools = {"exec", "system", "shell", "subprocess"}
|
|
102
|
+
|
|
103
|
+
if tool_name.lower() in restricted_tools:
|
|
104
|
+
response = PermissionToolDenyResponse(
|
|
105
|
+
message=f"Tool {tool_name} is restricted for security reasons"
|
|
106
|
+
)
|
|
107
|
+
print(response.model_dump_json(by_alias=True))
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
# Allow the tool call with original input
|
|
111
|
+
allow_response = PermissionToolAllowResponse(updated_input=input_data)
|
|
112
|
+
print(allow_response.model_dump_json(by_alias=True))
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
error_response = PermissionToolDenyResponse(
|
|
116
|
+
message=f"Error processing permission request: {e}"
|
|
117
|
+
)
|
|
118
|
+
print(error_response.model_dump_json(by_alias=True))
|
|
119
|
+
raise typer.Exit(1) from e
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main() -> None:
|
|
123
|
+
"""Entry point for ccproxy-perm command."""
|
|
124
|
+
app()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
main()
|
|
@@ -35,6 +35,7 @@ from ..options.claude_options import (
|
|
|
35
35
|
validate_cwd,
|
|
36
36
|
validate_max_thinking_tokens,
|
|
37
37
|
validate_max_turns,
|
|
38
|
+
validate_permission_mode,
|
|
38
39
|
)
|
|
39
40
|
from ..options.security_options import SecurityOptions, validate_auth_token
|
|
40
41
|
from ..options.server_options import (
|
|
@@ -393,6 +394,15 @@ def api(
|
|
|
393
394
|
rich_help_panel="Claude Settings",
|
|
394
395
|
),
|
|
395
396
|
] = None,
|
|
397
|
+
permission_mode: Annotated[
|
|
398
|
+
str | None,
|
|
399
|
+
typer.Option(
|
|
400
|
+
"--permission-mode",
|
|
401
|
+
help="Permission mode: default, acceptEdits, or bypassPermissions",
|
|
402
|
+
callback=validate_permission_mode,
|
|
403
|
+
rich_help_panel="Claude Settings",
|
|
404
|
+
),
|
|
405
|
+
] = None,
|
|
396
406
|
max_turns: Annotated[
|
|
397
407
|
int | None,
|
|
398
408
|
typer.Option(
|
|
@@ -411,6 +421,14 @@ def api(
|
|
|
411
421
|
rich_help_panel="Claude Settings",
|
|
412
422
|
),
|
|
413
423
|
] = None,
|
|
424
|
+
permission_prompt_tool_name: Annotated[
|
|
425
|
+
str | None,
|
|
426
|
+
typer.Option(
|
|
427
|
+
"--permission-prompt-tool-name",
|
|
428
|
+
help="Permission prompt tool name",
|
|
429
|
+
rich_help_panel="Claude Settings",
|
|
430
|
+
),
|
|
431
|
+
] = None,
|
|
414
432
|
# Core settings
|
|
415
433
|
docker: Annotated[
|
|
416
434
|
bool,
|
|
@@ -536,8 +554,10 @@ def api(
|
|
|
536
554
|
disallowed_tools=disallowed_tools,
|
|
537
555
|
claude_cli_path=claude_cli_path,
|
|
538
556
|
append_system_prompt=append_system_prompt,
|
|
557
|
+
permission_mode=permission_mode,
|
|
539
558
|
max_turns=max_turns,
|
|
540
559
|
cwd=cwd,
|
|
560
|
+
permission_prompt_tool_name=permission_prompt_tool_name,
|
|
541
561
|
)
|
|
542
562
|
|
|
543
563
|
security_options = SecurityOptions(auth_token=auth_token)
|
|
@@ -558,7 +578,9 @@ def api(
|
|
|
558
578
|
allowed_tools=claude_options.allowed_tools,
|
|
559
579
|
disallowed_tools=claude_options.disallowed_tools,
|
|
560
580
|
append_system_prompt=claude_options.append_system_prompt,
|
|
581
|
+
permission_mode=claude_options.permission_mode,
|
|
561
582
|
max_turns=claude_options.max_turns,
|
|
583
|
+
permission_prompt_tool_name=claude_options.permission_prompt_tool_name,
|
|
562
584
|
cwd=claude_options.cwd,
|
|
563
585
|
)
|
|
564
586
|
|
|
@@ -28,7 +28,7 @@ from ccproxy.core.logging import setup_logging
|
|
|
28
28
|
|
|
29
29
|
from .commands.auth import app as auth_app
|
|
30
30
|
from .commands.config import app as config_app
|
|
31
|
-
from .commands.serve import api
|
|
31
|
+
from .commands.serve import api
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def version_callback(value: bool) -> None:
|
|
@@ -32,6 +32,22 @@ def validate_max_turns(
|
|
|
32
32
|
return value
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def validate_permission_mode(
|
|
36
|
+
ctx: typer.Context, param: typer.CallbackParam, value: str | None
|
|
37
|
+
) -> str | None:
|
|
38
|
+
"""Validate permission mode."""
|
|
39
|
+
if value is None:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
valid_modes = {"default", "acceptEdits", "bypassPermissions"}
|
|
43
|
+
if value not in valid_modes:
|
|
44
|
+
raise typer.BadParameter(
|
|
45
|
+
f"Permission mode must be one of: {', '.join(valid_modes)}"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return value
|
|
49
|
+
|
|
50
|
+
|
|
35
51
|
def validate_claude_cli_path(
|
|
36
52
|
ctx: typer.Context, param: typer.CallbackParam, value: str | None
|
|
37
53
|
) -> str | None:
|
|
@@ -79,8 +95,10 @@ class ClaudeOptions:
|
|
|
79
95
|
disallowed_tools: str | None = None,
|
|
80
96
|
claude_cli_path: str | None = None,
|
|
81
97
|
append_system_prompt: str | None = None,
|
|
98
|
+
permission_mode: str | None = None,
|
|
82
99
|
max_turns: int | None = None,
|
|
83
100
|
cwd: str | None = None,
|
|
101
|
+
permission_prompt_tool_name: str | None = None,
|
|
84
102
|
):
|
|
85
103
|
"""Initialize Claude options.
|
|
86
104
|
|
|
@@ -90,13 +108,17 @@ class ClaudeOptions:
|
|
|
90
108
|
disallowed_tools: List of disallowed tools (comma-separated)
|
|
91
109
|
claude_cli_path: Path to Claude CLI executable
|
|
92
110
|
append_system_prompt: Additional system prompt to append
|
|
111
|
+
permission_mode: Permission mode
|
|
93
112
|
max_turns: Maximum conversation turns
|
|
94
113
|
cwd: Working directory path
|
|
114
|
+
permission_prompt_tool_name: Permission prompt tool name
|
|
95
115
|
"""
|
|
96
116
|
self.max_thinking_tokens = max_thinking_tokens
|
|
97
117
|
self.allowed_tools = allowed_tools
|
|
98
118
|
self.disallowed_tools = disallowed_tools
|
|
99
119
|
self.claude_cli_path = claude_cli_path
|
|
100
120
|
self.append_system_prompt = append_system_prompt
|
|
121
|
+
self.permission_mode = permission_mode
|
|
101
122
|
self.max_turns = max_turns
|
|
102
123
|
self.cwd = cwd
|
|
124
|
+
self.permission_prompt_tool_name = permission_prompt_tool_name
|
|
@@ -467,9 +467,11 @@ class ConfigurationManager:
|
|
|
467
467
|
claude_opts = {}
|
|
468
468
|
for key in [
|
|
469
469
|
"max_thinking_tokens",
|
|
470
|
+
"permission_mode",
|
|
470
471
|
"cwd",
|
|
471
472
|
"max_turns",
|
|
472
473
|
"append_system_prompt",
|
|
474
|
+
"permission_prompt_tool_name",
|
|
473
475
|
"continue_conversation",
|
|
474
476
|
]:
|
|
475
477
|
if cli_args.get(key) is not None:
|
|
@@ -143,6 +143,42 @@ class APIError(BaseModel):
|
|
|
143
143
|
)
|
|
144
144
|
|
|
145
145
|
|
|
146
|
+
class PermissionToolAllowResponse(BaseModel):
|
|
147
|
+
"""Response model for allowed permission tool requests."""
|
|
148
|
+
|
|
149
|
+
behavior: Annotated[Literal["allow"], Field(description="Permission behavior")] = (
|
|
150
|
+
"allow"
|
|
151
|
+
)
|
|
152
|
+
updated_input: Annotated[
|
|
153
|
+
dict[str, Any],
|
|
154
|
+
Field(
|
|
155
|
+
description="Updated input parameters for the tool, or original input if unchanged",
|
|
156
|
+
alias="updatedInput",
|
|
157
|
+
),
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
model_config = ConfigDict(extra="forbid", populate_by_name=True)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class PermissionToolDenyResponse(BaseModel):
|
|
164
|
+
"""Response model for denied permission tool requests."""
|
|
165
|
+
|
|
166
|
+
behavior: Annotated[Literal["deny"], Field(description="Permission behavior")] = (
|
|
167
|
+
"deny"
|
|
168
|
+
)
|
|
169
|
+
message: Annotated[
|
|
170
|
+
str,
|
|
171
|
+
Field(
|
|
172
|
+
description="Human-readable explanation of why the permission was denied"
|
|
173
|
+
),
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
model_config = ConfigDict(extra="forbid")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
PermissionToolResponse = PermissionToolAllowResponse | PermissionToolDenyResponse
|
|
180
|
+
|
|
181
|
+
|
|
146
182
|
class RateLimitError(APIError):
|
|
147
183
|
"""Rate limit error."""
|
|
148
184
|
|
|
@@ -18,6 +18,7 @@ from ccproxy.auth.manager import AuthManager
|
|
|
18
18
|
from ccproxy.claude_sdk.client import ClaudeSDKClient
|
|
19
19
|
from ccproxy.claude_sdk.converter import MessageConverter
|
|
20
20
|
from ccproxy.claude_sdk.options import OptionsHandler
|
|
21
|
+
from ccproxy.config.settings import Settings
|
|
21
22
|
from ccproxy.core.errors import (
|
|
22
23
|
ClaudeProxyError,
|
|
23
24
|
ServiceUnavailableError,
|
|
@@ -44,6 +45,7 @@ class ClaudeSDKService:
|
|
|
44
45
|
sdk_client: ClaudeSDKClient | None = None,
|
|
45
46
|
auth_manager: AuthManager | None = None,
|
|
46
47
|
metrics: PrometheusMetrics | None = None,
|
|
48
|
+
settings: Settings | None = None,
|
|
47
49
|
) -> None:
|
|
48
50
|
"""
|
|
49
51
|
Initialize Claude SDK service.
|
|
@@ -52,12 +54,14 @@ class ClaudeSDKService:
|
|
|
52
54
|
sdk_client: Claude SDK client instance
|
|
53
55
|
auth_manager: Authentication manager (optional)
|
|
54
56
|
metrics: Prometheus metrics instance (optional)
|
|
57
|
+
settings: Application settings (optional)
|
|
55
58
|
"""
|
|
56
59
|
self.sdk_client = sdk_client or ClaudeSDKClient()
|
|
57
60
|
self.auth_manager = auth_manager
|
|
58
61
|
self.metrics = metrics
|
|
62
|
+
self.settings = settings
|
|
59
63
|
self.message_converter = MessageConverter()
|
|
60
|
-
self.options_handler = OptionsHandler()
|
|
64
|
+
self.options_handler = OptionsHandler(settings=settings)
|
|
61
65
|
|
|
62
66
|
async def create_completion(
|
|
63
67
|
self,
|