diff --git a/cli/package.json b/cli/package.json index e5923d7b..3232a3f2 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "9router", - "version": "0.4.71", + "version": "0.4.73", "description": "9Router CLI - Start and manage 9Router server", "bin": { "9router": "./cli.js" diff --git a/open-sse/config/kiroConstants.js b/open-sse/config/kiroConstants.js index 03e64f3e..707e46db 100644 --- a/open-sse/config/kiroConstants.js +++ b/open-sse/config/kiroConstants.js @@ -18,6 +18,23 @@ export const KIRO_AGENTIC_SUFFIX = "-agentic"; export const KIRO_THINKING_SUFFIX = "-thinking"; +// Public default CodeWhisperer profile ARNs (us-east-1), keyed by auth method. +// Used when an account cannot resolve its own profileArn. Builder ID and social +// (Google/GitHub) sign-ins map to different shared profiles. +export const KIRO_DEFAULT_PROFILE_ARNS = { + "builder-id": "arn:aws:codewhisperer:us-east-1:638616132270:profile/AAAACCCCXXXX", + social: "arn:aws:codewhisperer:us-east-1:699475941385:profile/EHGA3GRVQMUK", +}; + +// Back-compat single default (Builder ID). +export const KIRO_DEFAULT_PROFILE_ARN = KIRO_DEFAULT_PROFILE_ARNS["builder-id"]; + +/** Resolve the shared default profileArn for a given auth method. */ +export function resolveDefaultProfileArn(authMethod) { + const social = authMethod === "google" || authMethod === "github"; + return social ? KIRO_DEFAULT_PROFILE_ARNS.social : KIRO_DEFAULT_PROFILE_ARNS["builder-id"]; +} + export const KIRO_THINKING_BUDGET_DEFAULT = 16000; export const KIRO_AGENTIC_SYSTEM_PROMPT = ` diff --git a/open-sse/services/tokenRefresh.js b/open-sse/services/tokenRefresh.js index 40643405..a9e69444 100644 --- a/open-sse/services/tokenRefresh.js +++ b/open-sse/services/tokenRefresh.js @@ -428,7 +428,7 @@ export async function refreshKiroToken(refreshToken, providerSpecificData, log, accessToken: tokens.accessToken, refreshToken: tokens.refreshToken || refreshToken, expiresIn: tokens.expiresIn, - ...(await resolveKiroProfileArnPatch(providerSpecificData, tokens.accessToken)), + ...(await resolveKiroProfileArnPatch(providerSpecificData, tokens.accessToken, tokens.profileArn)), }; } diff --git a/open-sse/services/usage.js b/open-sse/services/usage.js index 1441d2e3..0ca6b929 100644 --- a/open-sse/services/usage.js +++ b/open-sse/services/usage.js @@ -4,6 +4,7 @@ import { CLIENT_METADATA, getPlatformUserAgent } from "../config/appConstants.js"; import { proxyAwareFetch } from "../utils/proxyFetch.js"; +import { resolveDefaultProfileArn } from "../config/kiroConstants.js"; // GitHub API config const GITHUB_CONFIG = { @@ -753,10 +754,8 @@ function parseKiroQuotaData(data) { } async function getKiroUsage(accessToken, providerSpecificData, proxyOptions = null) { - // Default profileArn fallback - const DEFAULT_PROFILE_ARN = "arn:aws:codewhisperer:us-east-1:638616132270:profile/AAAACCCCXXXX"; - const profileArn = providerSpecificData?.profileArn || DEFAULT_PROFILE_ARN; const authMethod = providerSpecificData?.authMethod || "builder-id"; + const profileArn = providerSpecificData?.profileArn || resolveDefaultProfileArn(authMethod); const getUsageParams = new URLSearchParams({ isEmailRequired: "true", diff --git a/open-sse/translator/request/openai-to-gemini.js b/open-sse/translator/request/openai-to-gemini.js index b2043065..81d472b9 100644 --- a/open-sse/translator/request/openai-to-gemini.js +++ b/open-sse/translator/request/openai-to-gemini.js @@ -230,22 +230,21 @@ export function openaiToGeminiCLIRequest(model, body, stream) { const gemini = openaiToGeminiBase(model, body, stream, DEFAULT_THINKING_GEMINI_CLI_SIGNATURE); const isClaude = model.toLowerCase().includes("claude"); - // Add thinking config for CLI - if (body.reasoning_effort) { - const budgetMap = { low: 1024, medium: 8192, high: 32768 }; - const budget = budgetMap[body.reasoning_effort] || 8192; - gemini.generationConfig.thinkingConfig = { - thinkingBudget: budget, - include_thoughts: true - }; + // Map reasoning effort → thinkingConfig.thinkingLevel (gemini-3 enum: minimal|low|medium|high) + // Gemini 3 cannot fully disable thinking; "none"/"off" map to "minimal" (closest to no-thinking) + // Accept both OpenAI chat (reasoning_effort) and Responses (reasoning.effort) shapes + const reasoningEffort = body.reasoning_effort ?? body.reasoning?.effort; + if (reasoningEffort) { + const effort = String(reasoningEffort).toLowerCase().trim(); + const level = (effort === "none" || effort === "off") ? "minimal" : effort; + gemini.generationConfig.thinkingConfig = { thinkingLevel: level, includeThoughts: level !== "minimal" }; } - // Thinking config from Claude format - if (body.thinking?.type === "enabled" && body.thinking.budget_tokens) { - gemini.generationConfig.thinkingConfig = { - thinkingBudget: body.thinking.budget_tokens, - include_thoughts: true - }; + // Claude-format thinking: disabled → minimal, enabled → high + if (body.thinking?.type === "disabled") { + gemini.generationConfig.thinkingConfig = { thinkingLevel: "minimal", includeThoughts: false }; + } else if (body.thinking?.type === "enabled") { + gemini.generationConfig.thinkingConfig = { thinkingLevel: "high", includeThoughts: true }; } // Clean schema for tools diff --git a/open-sse/translator/request/openai-to-kiro.js b/open-sse/translator/request/openai-to-kiro.js index d3a502f3..49aa7f4f 100644 --- a/open-sse/translator/request/openai-to-kiro.js +++ b/open-sse/translator/request/openai-to-kiro.js @@ -9,7 +9,8 @@ import { resolveKiroModel, isThinkingEnabled, buildThinkingSystemPrefix, - KIRO_AGENTIC_SYSTEM_PROMPT + KIRO_AGENTIC_SYSTEM_PROMPT, + resolveDefaultProfileArn } from "../../config/kiroConstants.js"; /** Render a single tool call as a readable text line. */ @@ -520,7 +521,8 @@ export function buildKiroPayload(model, body, stream, credentials) { const { history, currentMessage } = convertMessages(messages, tools, upstreamModel); - const profileArn = credentials?.providerSpecificData?.profileArn || ""; + const profileArn = credentials?.providerSpecificData?.profileArn + || resolveDefaultProfileArn(credentials?.providerSpecificData?.authMethod); let finalContent = currentMessage?.userInputMessage?.content || ""; diff --git a/package.json b/package.json index f8539086..c648cdc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "9router-app", - "version": "0.4.71", + "version": "0.4.73", "description": "9Router web dashboard", "private": true, "scripts": { diff --git a/src/lib/oauth/services/kiro.js b/src/lib/oauth/services/kiro.js index 06231304..3c8f9905 100644 --- a/src/lib/oauth/services/kiro.js +++ b/src/lib/oauth/services/kiro.js @@ -200,6 +200,7 @@ export class KiroService { return { accessToken: data.accessToken, refreshToken: data.refreshToken || refreshToken, + profileArn: data.profileArn, expiresIn: data.expiresIn, }; }