fix(ci): allow third-party provider translator changes in PRs#418
fix(ci): allow third-party provider translator changes in PRs#418jc01rho wants to merge 210 commits intorouter-for-me:mainfrom
Conversation
- Add routing.mode field for key-based routing (ignore provider, use model-only key) - Add routing.fallback-models for specific model fallback on 429/401/5xx errors - Add routing.fallback-chain for general fallback chain with max-depth limit - Implement cycle detection to prevent infinite fallback loops - Support hot reload for all new routing configurations - Update config.example.yaml with documentation
- Add GET/PUT /routing/mode for routing mode configuration - Add GET/PUT /fallback/models for fallback model mappings - Add GET/PUT /fallback/chain for fallback provider chain - Include unit tests for all new handlers (6 tests, all passing) Closes gap between backend RoutingConfig fields and Management API
클라이언트 연결 끊김 또는 요청 취소(context.Canceled) 시 auth 상태가 error로 잘못 표시되는 문제 수정 - context.Canceled/DedlineExceeded 에러는 네트워크/클라이언트 문제이지 인증 문제가 아니므로 auth 상태를 변경하지 않아야 함 - MarkResult() 호출을 건너뛰고 에러를 그대로 반환 수정된 파일: - sdk/cliproxy/auth/conductor.go (8개소에서 체크 추가) 참고: 이 변경은 사용자가 연결을 끊었을 때 인증 키가 'error' 상태로 오인식되는 것을 방지합니다.
…onse API 응답에 auth 상태 관련 필드 추가: - quota: exceeded, reason, next_recover_at, backoff_level - last_error: code, message, retryable, http_status (있을 경우) - next_retry_after: 재시도 대기 시간 (설정된 경우) 프론트엔드에서 인증 키 상태를 시각적으로 표시하기 위한 준비
# Conflicts: # README.md # README_CN.md
- Add AntigravityProjectInfo struct with ProjectID, TierID, TierName, IsPaid fields - Implement extractTierInfo() helper with tier priority logic (paidTier > currentTier) - Rename fetchAntigravityProjectID() to fetchAntigravityProjectInfo() - Update FetchAntigravityProjectID() wrapper for backward compatibility - Store tier_id, tier_name, tier_is_paid in Auth.Metadata
- Add tier and tier_name fields to buildAuthFileEntry() for Antigravity provider - Extract tier info from Auth.Metadata with nil-safe type assertions
- Add Tier field to upstreamRequestLog struct - Extract tier from Auth.Metadata in antigravity executor - Include tier in formatAuthInfo() output
# Conflicts: # README.md # README_CN.md
…pro-high - Conditionally disable VALIDATED mode for gemini-3-pro-high (incompatible with reasoning output) Fixes: router-for-me#1113
- Save tier_id, tier_name, tier_is_paid before token refresh - Restore preserved tier info after metadata update - Applied to both antigravity_executor.go and api_tools.go
# Conflicts: # internal/runtime/executor/antigravity_executor.go
…avity - Add CleanJSONSchemaForGemini() function to remove unsupported keywords without placeholders - Apply Gemini schema cleaning for non-Claude models (rename parametersJsonSchema → parameters) - Preserve upstream toolConfig for non-Claude models - Force VALIDATED mode only for Claude models (not Gemini) - Remove nullable/title keywords and placeholder fields for Gemini Fixes malformed_function_call error with Gemini tool calling via Antigravity.
…avity - Add CleanJSONSchemaForGemini() function to remove unsupported keywords without placeholders - Apply Gemini schema cleaning for non-Claude models (rename parametersJsonSchema → parameters) - Preserve upstream toolConfig for non-Claude models - Force VALIDATED mode only for Claude models (not Gemini) - Remove nullable/title keywords and placeholder fields for Gemini - Merge conflict resolution with remote main branch Fixes malformed_function_call error with Gemini tool calling via Antigravity.
…router-for-me#1142) - Add web_search tool detection and googleSearch injection in request translators - Add extractWebSearchFromAntigravity() to parse groundingMetadata from responses - Add appendWebSearchBlocks() for streaming web search results - Add server_tool_use and web_search_tool_result blocks for non-streaming - Set model to gemini-2.5-flash and requestType to web_search when detected - Fix quota cooldown check for transient errors (PR router-for-me#1140)
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…r helpers) Merged from router-for-me/CLIProxyAPI@abfca6a Changes: - Reorder gemini schema cleaner helpers for better code organization - Add comments for cleanJSONSchema function - Improve toolConfig handling in antigravity executor - Various test and translator updates
Resolved conflict in antigravity_executor.go - kept local tool schema cleaning logic
…s, golang.org/x/sync dependency
…bypass - Improve User-Agent to iFlowCLI/0.5.14 (platform; arch) format - Increase OAuth state from 32 to 64 hex characters (32 bytes) - Reorder OAuth URL parameters to match iFlow CLI order - Add buildIFlowUserAgent() for dynamic platform detection
- Add automatic token refresh in ensureFreshAccessToken() - Add Cline source parity headers (X-CLIENT-TYPE, X-CORE-VERSION, etc.) - Add applyClineOpenRouterParity() for request payload modifications - Add HTTP-Referer and X-Title headers to auth endpoints - Handle workos: prefix in token auth value Note: 403 on chat/completions is account-level permission issue, not code bug
The theirs merge strategy removed clineCallbackPort=4237 constant. Re-added with port 1456 (next available after codexCallbackPort=1455).
Add SetProviderAuthInContext calls in three execution functions: - executeMixedOnce - executeCountMixedOnce - executeStreamMixedOnce This enables gin_logger.go to display which provider handled the request in the access log output.
Store the resolved model name (after alias resolution) in the request context so that gin_logger can display both the requested alias and the actual upstream model name in the log output. Changes: - Modified 3 execution paths in conductor.go to store fallback info when the model name differs after alias resolution - Existing gin_logger.go already supports displaying the mapping in format: 'alias → actual_model' Example log output: free-code → claude-sonnet-4-6 | claude:auth-label
Previously, 4xx and 5xx status codes were logged at Warn/Error level, making them less visible in log aggregation systems. Now all status codes are logged at Info level with consistent format.
The pr-path-guard workflow was blocking ALL translator changes, but this is the Plus version which accepts third-party provider support. This fix adds exclusions for third-party provider translators (kiro, antigravity, codex, gemini-cli) while still blocking changes to core translators (claude, openai, gemini). Fixes the CI failures seen in PR router-for-me#414 where Kiro translator changes were incorrectly blocked.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly expands the platform's capabilities by integrating new third-party AI providers, Kilocode and Cline, and enhancing existing authentication and routing mechanisms. It addresses a critical CI issue that was blocking legitimate third-party translator updates and introduces robust error handling, improved logging, and defensive programming practices across various API executors. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Pull request overview
Updates CI path-guard rules to allow third-party translator changes, while also introducing broad new functionality across auth/providers, routing behavior, logging, and executor request handling.
Changes:
- Adjust
translator-path-guardworkflow to exclude specific third-party translator subtrees from restriction checks. - Add new providers/auth flows (notably
clineandkilocode) plus related executor/model-registry support. - Extend routing configuration (mode + fallback settings) and enhance request/logging behavior (context metadata, API error logging, payload cloning).
Reviewed changes
Copilot reviewed 73 out of 77 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test/config_migration_test.go | Adds tests for legacy→new config migration behavior. |
| sdk/cliproxy/service.go | Updates routing selector on config reload; adds cline/kilocode model fetching and Kiro virtual models. |
| sdk/cliproxy/builder.go | Passes routing mode and fallback config into core manager at build time. |
| sdk/cliproxy/auth/selector.go | Adds Mode field to round-robin selector. |
| sdk/cliproxy/auth/oauth_model_alias.go | Adds extensive debug logging + expands supported channels list. |
| sdk/cliproxy/auth/conductor.go | Adds gin-context metadata helpers; adds fallback config storage; modifies execute paths. |
| sdk/cliproxy/auth/.tldrignore | Adds TLDR ignore patterns file. |
| sdk/auth/refresh_registry.go | Registers refresh leads for kilocode and cline. |
| sdk/auth/kilocode.go | Implements Kilocode device-flow login and auth record creation. |
| sdk/auth/kilo.go | Enhances Kilo login UX (browser open) and formatting. |
| sdk/auth/iflow.go | Adjusts refresh lead; adds refresh implementation; enriches auth timestamps/refresh scheduling. |
| sdk/auth/filestore.go | Computes NextRefreshAfter from additional metadata fields (incl. iFlow special-case). |
| sdk/auth/cline.go | Implements Cline OAuth login with local callback server + token parsing. |
| sdk/auth/antigravity.go | Reworks Antigravity OAuth flow and adds tier/project discovery helpers. |
| sdk/api/handlers/handlers.go | Clones request/response payload bytes to avoid mutation/aliasing; clones stored response bytes. |
| internal/watcher/synthesizer/file.go | Adds auth_kind=oauth attribute to synthesized auths. |
| internal/usage/logger_plugin.go | Adds failure counters to aggregated usage stats and snapshots. |
| internal/translator/kiro/openai/kiro_openai_request_test.go | Updates Kiro model IDs used in tests. |
| internal/translator/kiro/common/utils_test.go | Adds tests for tool-use-id sanitization/generation. |
| internal/translator/kiro/common/utils.go | Adds tool-use-id sanitization + deterministic generator. |
| internal/translator/kiro/claude/kiro_claude_tools.go | Uses shared tool-use-id generator; sanitizes toolUseId and drops invalid events. |
| internal/translator/kiro/claude/kiro_claude_stream.go | Removes hyphens from generated Claude message IDs. |
| internal/translator/kiro/claude/kiro_claude_response.go | Removes hyphens from generated Claude message IDs. |
| internal/translator/antigravity/claude/antigravity_claude_response.go | Adds web-search blocks extraction/emission for Claude formatted responses. |
| internal/thinking/apply.go | Clarifies Gemini thinking config precedence to avoid incompatible combinations. |
| internal/runtime/executor/qwen_executor.go | Clones payload before translation to avoid mutation/aliasing. |
| internal/runtime/executor/proxy_helpers.go | Adds streaming-safe transport defaults and transport-level timeouts. |
| internal/runtime/executor/openai_compat_executor.go | Clones payload before translation; centralizes detailed API error logging. |
| internal/runtime/executor/logging_helpers.go | Clones bodies before logging; adds tier field; adds detailed API error logger. |
| internal/runtime/executor/kilocode_executor.go | Adds Kilocode executor implementation for OpenRouter-like endpoint + SSE handling. |
| internal/runtime/executor/kilo_executor.go | Refactors/standardizes Kilo request headers; broadens token extraction keys. |
| internal/runtime/executor/iflow_executor.go | Clones payload before translation; improves error logging; updates UA/signature behavior; refresh scheduling. |
| internal/runtime/executor/gemini_vertex_executor.go | Clones payload before translation; uses detailed API error logging. |
| internal/runtime/executor/gemini_executor.go | Clones payload before translation; uses detailed API error logging. |
| internal/runtime/executor/gemini_cli_executor.go | Clones payload before translation; uses detailed API error logging; clones DONE marker. |
| internal/runtime/executor/claude_executor.go | Adds extra “external HTTP request” info logging. |
| internal/runtime/executor/antigravity_executor.go | Clones payload before translation; adds external request logging; adds tier logging; model resolution tweaks; schema cleaning. |
| internal/runtime/executor/aistudio_executor.go | Clones payload/response bytes through logging/translation path. |
| internal/registry/model_definitions_static_data.go | Adds gemini-3.1-pro-preview model definition. |
| internal/registry/model_definitions.go | Treats kilocode as alias for kilo in static model definitions. |
| internal/registry/kilocode_model_converter_test.go | Adds tests for Kilocode model alias resolution. |
| internal/registry/kilocode_model_converter.go | Adds Kilocode dynamic model conversion/filtering + static free models list + alias resolver. |
| internal/registry/cline_models.go | Adds static model list for Cline. |
| internal/misc/oauth.go | Increases OAuth state size to 32 bytes (64 hex chars). |
| internal/logging/gin_logger.go | Enhances Gin logging with request body/model/provider info and gin-context propagation. |
| internal/constant/constant.go | Adds constant for cline provider. |
| internal/config/routing_config_test.go | Adds tests for parsing new routing mode. |
| internal/config/config.go | Adds routing mode + fallback settings; adjusts OAuth model alias dedupe rules. |
| internal/cmd/kilocode_login.go | Adds CLI command helper for Kilocode login. |
| internal/cmd/cline_login.go | Adds CLI command helper for Cline login. |
| internal/cmd/auth_manager.go | Registers Cline authenticator in CLI auth manager. |
| internal/auth/kilocode/token.go | Adds Kilocode token storage file format. |
| internal/auth/kilocode/kilocode_auth.go | Implements Kilocode device-flow client and model fetching. |
| internal/auth/kilocode/errors.go | Adds Kilocode-specific auth error types and user-friendly messages. |
| internal/auth/iflow/iflow_auth.go | Adjusts auth URL param order; adds API-level error checks and response fields. |
| internal/auth/cline/cline_token.go | Adds Cline token storage format and helpers. |
| internal/auth/cline/cline_auth.go | Implements Cline WorkOS OAuth URL generation + token exchange/refresh. |
| internal/api/server.go | Adds management routes for routing mode + fallback config; adds auth-tier refresh + cline token route. |
| internal/api/handlers/management/config_routing_test.go | Adds tests for new management endpoints (routing mode/fallback). |
| internal/api/handlers/management/config_routing.go | Implements management endpoints for routing mode and fallback settings. |
| internal/api/handlers/management/config_lists.go | Ensures runtime auth manager receives updated OAuthModelAlias after persist. |
| internal/api/handlers/management/api_tools.go | Preserves tier metadata during Antigravity refresh flow. |
| internal/api/handlers/management/.tldrignore | Adds TLDR ignore patterns file. |
| internal/api/.tldrignore | Adds TLDR ignore patterns file. |
| go.sum | Reorders a couple of entries. |
| go.mod | Adds machineid dependency and reorders an indirect dependency line. |
| config.example.yaml | Documents routing mode and fallback configuration keys. |
| cmd/server/main.go | Adds CLI flags for kilocode-login and cline-login. |
| .tldrignore | Adds TLDR ignore patterns file. |
| .gitignore | Adjusts ignored binary path and adds broad ignore patterns (incl. *.json). |
| .github/workflows/release.yaml | Adds Discord webhook notification step on successful release job. |
| .github/workflows/pr-path-guard.yml | Allows translator changes for select third-party providers via negated patterns. |
| .github/workflows/docker-image.yml | Removes docker-image workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func (m *Manager) applyOAuthModelAlias(auth *Auth, requestedModel string) string { | ||
| channel := modelAliasChannel(auth) | ||
| log.Debugf("[DEBUG] applyOAuthModelAlias: provider=%s model=%s channel=%s auth_kind=%v", auth.Provider, requestedModel, channel, auth.Attributes) | ||
| upstreamModel := m.resolveOAuthUpstreamModel(auth, requestedModel) | ||
| if upstreamModel == "" { | ||
| log.Debugf("[DEBUG] applyOAuthModelAlias: no alias found, returning original model=%s", requestedModel) |
There was a problem hiding this comment.
This debug log prints auth.Attributes (auth_kind and potentially other fields). In this codebase, Attributes can contain secrets (e.g., API keys/tokens), so logging the full map risks credential leakage even at debug level. Log only non-sensitive fields (e.g., provider/auth kind/channel) and avoid dumping the full attributes map.
| const ( | ||
| antigravityClientID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com" | ||
| antigravityClientSecret = "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" | ||
| antigravityCallbackPort = 51121 | ||
| ) |
There was a problem hiding this comment.
Hardcoding the OAuth client secret in the repository is a security risk (secrets can be harvested from git history). Move this secret to a secure configuration mechanism (environment variable / secrets manager) or switch to a public client flow that does not require embedding a client secret.
|
|
||
| require ( | ||
| github.com/andybalholm/brotli v1.0.6 | ||
| github.com/denisbrodbeck/machineid v1.0.1 |
There was a problem hiding this comment.
This PR adds github.com/denisbrodbeck/machineid to go.mod, but there are no references to it in the Go codebase. Please remove the dependency (or add the missing usage) to avoid unnecessary supply-chain surface area and keep go.mod tidy.
| github.com/denisbrodbeck/machineid v1.0.1 |
| - name: Detect internal/translator changes | ||
| id: changed-files | ||
| uses: tj-actions/changed-files@v45 | ||
| with: | ||
| files: | | ||
| internal/translator/** |
There was a problem hiding this comment.
The PR title/description indicates this change is only about pr-path-guard.yml, but this PR also introduces substantial new functionality (new providers, auth flows, routing mode/fallback, logging changes, etc.). Please update the PR description/title to reflect the full scope or split this into smaller PRs so review/rollback risk is manageable.
| entry := log.WithField("request_id", requestID) | ||
|
|
||
| switch { | ||
| log.WithField("request_id", requestID).Info(logLine) | ||
| case statusCode >= http.StatusInternalServerError: | ||
| entry.Error(logLine) |
There was a problem hiding this comment.
The logging branch selection is syntactically broken: the case ... clauses appear without a surrounding switch statement, which will prevent the project from compiling. Restore the switch { ... } (or equivalent if/else) around the status-code severity logic and remove the unconditional Info(logLine) call if the switch is meant to control the log level.
| execReq := req | ||
| execReq.Model = rewriteModelForAuth(routeModel, auth) | ||
| execReq.Model = m.applyAPIKeyModelAlias(auth, execReq.Model) | ||
| // Store actual model name in context for logging |
There was a problem hiding this comment.
executeCountMixedOnce no longer rewrites the model per-auth (it uses req.Model directly), unlike executeMixedOnce/executeStreamMixedOnce which call rewriteModelForAuth(routeModel, auth) first. This can cause CountTokens to use the wrong upstream model for auths that need model rewriting. Align the model rewrite/alias order with the Execute/Stream paths (start from routeModel + rewriteModelForAuth).
| execReq.Model = m.applyOAuthModelAlias(auth, execReq.Model) | ||
| execReq.Model = m.applyAPIKeyModelAlias(auth, execReq.Model) | ||
| // Store actual model name in context for logging | ||
| if execReq.Model != routeModel { | ||
| execCtx = SetFallbackInfoInContext(execCtx, routeModel, execReq.Model) | ||
| } |
There was a problem hiding this comment.
executeCountMixedOnce applies API-key model alias twice and sets fallback info twice (before and after OAuth alias). This is redundant and risks inconsistent behavior if aliasing is not strictly idempotent. Consider applying model rewrites/aliases once in a single, consistent order and only recording fallback info after the final model value is determined.
There was a problem hiding this comment.
Code Review
This pull request is described as a fix for the CI workflow, but it contains a substantial number of changes beyond that. It introduces support for new authentication providers (cline, kilocode), adds model fallback and advanced routing capabilities, and includes significant refactoring of authentication flows and logging. While the changes are generally positive, I've identified a few areas for improvement regarding code duplication and consistency. My feedback focuses on improving maintainability by refactoring duplicated logic and standardizing error logging.
Note: Security Review did not run due to the size of the PR.
| "state": state, | ||
| "grant_type": "authorization_code", | ||
| "client_id": clientID, | ||
| "redirect_uri": "http://localhost:54545/callback", |
There was a problem hiding this comment.
The redirect_uri is hardcoded. To improve maintainability and consistency, consider constructing it dynamically using the anthropicCallbackPort constant. This would make it easier to update the port in one place. Similar hardcoded URIs are present for the Gemini (line 1355) and Codex (line 1711) token request handlers in this file.
| httpClient := util.SetProxy(&h.cfg.SDKConfig, &http.Client{}) | ||
| req, _ := http.NewRequestWithContext(ctx, "POST", "https://console.anthropic.com/v1/oauth/token", strings.NewReader(string(bodyJSON))) | ||
| req.Header.Set("Content-Type", "application/json") | ||
| req.Header.Set("Accept", "application/json") | ||
| resp, errDo := httpClient.Do(req) | ||
| if errDo != nil { | ||
| authErr := claude.NewAuthenticationError(claude.ErrCodeExchangeFailed, errDo) | ||
| log.Errorf("Failed to exchange authorization code for tokens: %v", authErr) | ||
| SetOAuthSessionError(state, "Failed to exchange authorization code for tokens") | ||
| return | ||
| } | ||
| defer func() { | ||
| if errClose := resp.Body.Close(); errClose != nil { | ||
| log.Errorf("failed to close response body: %v", errClose) | ||
| } | ||
| }() | ||
| respBody, _ := io.ReadAll(resp.Body) | ||
| if resp.StatusCode != http.StatusOK { | ||
| log.Errorf("token exchange failed with status %d: %s", resp.StatusCode, string(respBody)) | ||
| SetOAuthSessionError(state, fmt.Sprintf("token exchange failed with status %d", resp.StatusCode)) | ||
| return | ||
| } |
There was a problem hiding this comment.
The logic for exchanging an authorization code for a token is very similar across RequestAnthropicToken, RequestCodexToken, and RequestAntigravityToken. Consider refactoring this into a shared helper function to reduce code duplication and improve maintainability. The helper could handle creating the HTTP client, making the request, and processing the response, while the calling functions would just prepare the specific URL, body, and headers for each provider.
| b, _ := io.ReadAll(httpResp.Body) | ||
| appendAPIResponseChunk(ctx, e.cfg, b) | ||
| logWithRequestID(ctx).Debugf("request error, error status: %d error message: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b)) | ||
| log.Debugf("iflow request error: status %d body %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b)) |
There was a problem hiding this comment.
This log message for a request error is missing the request ID, which is valuable for debugging. Other executors in this PR have been updated to use a new logDetailedAPIError helper which provides richer error logging, including the request ID. Consider using that helper here for consistency and better debuggability.
| log.Debugf("iflow request error: status %d body %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b)) | |
| logDetailedAPIError(ctx, e.Identifier(), url, httpResp.StatusCode, httpResp.Header.Get("Content-Type"), b) |
| err = statusErr{code: httpResp.StatusCode, msg: string(data)} | ||
| bodyStr := string(data) | ||
| summary := summarizeErrorBody(httpResp.Header.Get("Content-Type"), data) | ||
| log.Errorf("iflow streaming error: status %d, summary: %s, full body: %s", httpResp.StatusCode, summary, bodyStr) |
There was a problem hiding this comment.
Similar to the non-streaming case, this error log for streaming requests is missing the request ID. Using the new logDetailedAPIError helper function introduced in this PR would provide more consistent and context-rich logging.
| log.Errorf("iflow streaming error: status %d, summary: %s, full body: %s", httpResp.StatusCode, summary, bodyStr) | |
| logDetailedAPIError(ctx, e.Identifier(), url, httpResp.StatusCode, httpResp.Header.Get("Content-Type"), data) |
The case statements were used without a switch block, causing syntax error. Now uses proper switch statement for log level based on status code.
Summary
pr-path-guard.ymlworkflow to allow third-party provider translator changesProblem
The
pr-path-guard.ymlworkflow was blocking ALL translator changes underinternal/translator/**. However, this is the Plus version which accepts third-party provider support. This caused CI failures in PR #414 where Kiro translator changes were incorrectly blocked.Solution
Updated the workflow to use negative patterns (exclusions) for third-party provider translators:
This allows:
Test Plan
internal/translator/kiro/**translator-path-guardworkflow passesinternal/translator/claude/**translator-path-guardworkflow fails as expected