claudish 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -56261,6 +56261,9 @@ function getModelPricing(provider, modelName) {
56261
56261
  case "google":
56262
56262
  pricingTable = GEMINI_PRICING;
56263
56263
  break;
56264
+ case "vertex":
56265
+ pricingTable = VERTEX_PRICING;
56266
+ break;
56264
56267
  case "openai":
56265
56268
  case "oai":
56266
56269
  pricingTable = OPENAI_PRICING;
@@ -56290,7 +56293,7 @@ function getModelPricing(provider, modelName) {
56290
56293
  }
56291
56294
  return pricingTable.default;
56292
56295
  }
56293
- var GEMINI_PRICING, OPENAI_PRICING, MINIMAX_PRICING, KIMI_PRICING, GLM_PRICING;
56296
+ var GEMINI_PRICING, OPENAI_PRICING, MINIMAX_PRICING, KIMI_PRICING, GLM_PRICING, VERTEX_PRICING;
56294
56297
  var init_remote_provider_types = __esm(() => {
56295
56298
  GEMINI_PRICING = {
56296
56299
  "gemini-2.5-flash": { inputCostPer1M: 0.15, outputCostPer1M: 0.6 },
@@ -56361,6 +56364,17 @@ var init_remote_provider_types = __esm(() => {
56361
56364
  "glm-4-plus": { inputCostPer1M: 0.5, outputCostPer1M: 2 },
56362
56365
  default: { inputCostPer1M: 0.16, outputCostPer1M: 0.8, isEstimate: true }
56363
56366
  };
56367
+ VERTEX_PRICING = {
56368
+ "gemini-2.5-flash": { inputCostPer1M: 0.15, outputCostPer1M: 0.6 },
56369
+ "gemini-2.5-flash-preview-05-20": { inputCostPer1M: 0.15, outputCostPer1M: 0.6 },
56370
+ "gemini-2.5-pro": { inputCostPer1M: 1.25, outputCostPer1M: 10 },
56371
+ "gemini-2.5-pro-preview-05-06": { inputCostPer1M: 1.25, outputCostPer1M: 10 },
56372
+ "gemini-3-pro-preview": { inputCostPer1M: 2.5, outputCostPer1M: 10 },
56373
+ "gemini-3.0-flash": { inputCostPer1M: 0.1, outputCostPer1M: 0.4 },
56374
+ "gemini-2.0-flash": { inputCostPer1M: 0.1, outputCostPer1M: 0.4 },
56375
+ "gemini-2.0-flash-thinking": { inputCostPer1M: 0.1, outputCostPer1M: 0.4 },
56376
+ default: { inputCostPer1M: 0.5, outputCostPer1M: 2, isEstimate: true }
56377
+ };
56364
56378
  });
56365
56379
 
56366
56380
  // ../core/dist/handlers/gemini-handler.js
@@ -57712,161 +57726,1070 @@ var init_anthropic_compat_handler = __esm(() => {
57712
57726
  init_remote_provider_types();
57713
57727
  });
57714
57728
 
57715
- // ../core/dist/providers/provider-registry.js
57716
- function getRegisteredProviders() {
57717
- return getProviders();
57718
- }
57719
- function resolveProvider(modelId) {
57720
- const providers = getProviders();
57721
- for (const provider of providers) {
57722
- for (const prefix of provider.prefixes) {
57723
- if (modelId.startsWith(prefix)) {
57724
- return {
57725
- provider,
57726
- modelName: modelId.slice(prefix.length)
57727
- };
57728
- }
57729
+ // ../core/dist/auth/vertex-auth.js
57730
+ import { exec as exec2 } from "node:child_process";
57731
+ import { promisify } from "node:util";
57732
+ import { existsSync as existsSync6 } from "node:fs";
57733
+ import { homedir as homedir7 } from "node:os";
57734
+ import { join as join11 } from "node:path";
57735
+
57736
+ class VertexAuthManager {
57737
+ cachedToken = null;
57738
+ refreshPromise = null;
57739
+ tokenRefreshMargin = 5 * 60 * 1000;
57740
+ async getAccessToken() {
57741
+ if (this.refreshPromise) {
57742
+ log("[VertexAuth] Waiting for in-progress refresh");
57743
+ return this.refreshPromise;
57744
+ }
57745
+ if (this.isTokenValid()) {
57746
+ return this.cachedToken.token;
57747
+ }
57748
+ this.refreshPromise = this.doRefresh();
57749
+ try {
57750
+ const token = await this.refreshPromise;
57751
+ return token;
57752
+ } finally {
57753
+ this.refreshPromise = null;
57729
57754
  }
57730
57755
  }
57731
- return null;
57732
- }
57733
- function isLocalProvider(modelId) {
57734
- if (resolveProvider(modelId) !== null) {
57735
- return true;
57756
+ async refreshToken() {
57757
+ this.cachedToken = null;
57758
+ await this.getAccessToken();
57736
57759
  }
57737
- if (parseUrlModel(modelId) !== null) {
57738
- return true;
57760
+ isTokenValid() {
57761
+ if (!this.cachedToken)
57762
+ return false;
57763
+ return Date.now() < this.cachedToken.expiresAt - this.tokenRefreshMargin;
57764
+ }
57765
+ async doRefresh() {
57766
+ log("[VertexAuth] Refreshing token");
57767
+ const adcToken = await this.tryADC();
57768
+ if (adcToken) {
57769
+ this.cachedToken = adcToken;
57770
+ log(`[VertexAuth] ADC token valid until ${new Date(adcToken.expiresAt).toISOString()}`);
57771
+ return adcToken.token;
57772
+ }
57773
+ const saToken = await this.tryServiceAccount();
57774
+ if (saToken) {
57775
+ this.cachedToken = saToken;
57776
+ log(`[VertexAuth] Service account token valid until ${new Date(saToken.expiresAt).toISOString()}`);
57777
+ return saToken.token;
57778
+ }
57779
+ throw new Error(`Failed to authenticate with Vertex AI.
57780
+
57781
+ ` + `Options:
57782
+ ` + `1. Run: gcloud auth application-default login
57783
+ ` + `2. Set: export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service-account.json'
57784
+ `);
57739
57785
  }
57740
- return false;
57741
- }
57742
- function parseUrlModel(modelId) {
57743
- if (!modelId.startsWith("http://") && !modelId.startsWith("https://")) {
57744
- return null;
57786
+ async tryADC() {
57787
+ try {
57788
+ const adcPath = join11(homedir7(), ".config/gcloud/application_default_credentials.json");
57789
+ if (!existsSync6(adcPath)) {
57790
+ log("[VertexAuth] ADC credentials file not found");
57791
+ return null;
57792
+ }
57793
+ const { stdout } = await execAsync("gcloud auth application-default print-access-token", {
57794
+ timeout: 1e4
57795
+ });
57796
+ const token = stdout.trim();
57797
+ if (!token) {
57798
+ log("[VertexAuth] ADC returned empty token");
57799
+ return null;
57800
+ }
57801
+ const expiresAt = Date.now() + 55 * 60 * 1000;
57802
+ return { token, expiresAt };
57803
+ } catch (e) {
57804
+ log(`[VertexAuth] ADC failed: ${e.message}`);
57805
+ return null;
57806
+ }
57745
57807
  }
57746
- try {
57747
- const url2 = new URL(modelId);
57748
- const pathParts = url2.pathname.split("/").filter(Boolean);
57749
- if (pathParts.length === 0) {
57808
+ async tryServiceAccount() {
57809
+ const credPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
57810
+ if (!credPath) {
57750
57811
  return null;
57751
57812
  }
57752
- const modelName = pathParts[pathParts.length - 1];
57753
- let basePath = "";
57754
- if (pathParts.length > 1) {
57755
- const prefix = pathParts.slice(0, -1).join("/");
57756
- if (prefix)
57757
- basePath = "/" + prefix;
57813
+ if (!existsSync6(credPath)) {
57814
+ throw new Error(`Service account file not found: ${credPath}
57815
+
57816
+ Check GOOGLE_APPLICATION_CREDENTIALS path.`);
57817
+ }
57818
+ try {
57819
+ const { stdout } = await execAsync(`gcloud auth print-access-token --credential-file-override="${credPath}"`, { timeout: 1e4 });
57820
+ const token = stdout.trim();
57821
+ if (!token) {
57822
+ log("[VertexAuth] Service account returned empty token");
57823
+ return null;
57824
+ }
57825
+ const expiresAt = Date.now() + 55 * 60 * 1000;
57826
+ return { token, expiresAt };
57827
+ } catch (e) {
57828
+ log(`[VertexAuth] Service account auth failed: ${e.message}`);
57829
+ return null;
57758
57830
  }
57759
- const baseUrl = `${url2.protocol}//${url2.host}${basePath}`;
57760
- return {
57761
- baseUrl,
57762
- modelName
57763
- };
57764
- } catch {
57765
- return null;
57766
57831
  }
57767
57832
  }
57768
- function createUrlProvider(parsed) {
57833
+ function getVertexConfig() {
57834
+ const projectId = process.env.VERTEX_PROJECT || process.env.GOOGLE_CLOUD_PROJECT;
57835
+ if (!projectId) {
57836
+ return null;
57837
+ }
57769
57838
  return {
57770
- name: "custom-url",
57771
- baseUrl: parsed.baseUrl,
57772
- apiPath: "/v1/chat/completions",
57773
- envVar: "",
57774
- prefixes: [],
57775
- capabilities: {
57776
- supportsTools: true,
57777
- supportsVision: false,
57778
- supportsStreaming: true,
57779
- supportsJsonMode: true
57780
- }
57839
+ projectId,
57840
+ location: process.env.VERTEX_LOCATION || "us-central1"
57781
57841
  };
57782
57842
  }
57783
- var getProviders = () => [
57784
- {
57785
- name: "ollama",
57786
- baseUrl: process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434",
57787
- apiPath: "/v1/chat/completions",
57788
- envVar: "OLLAMA_BASE_URL",
57789
- prefixes: ["ollama/", "ollama:"],
57790
- capabilities: {
57791
- supportsTools: true,
57792
- supportsVision: false,
57793
- supportsStreaming: true,
57794
- supportsJsonMode: true
57795
- }
57796
- },
57797
- {
57798
- name: "lmstudio",
57799
- baseUrl: process.env.LMSTUDIO_BASE_URL || "http://localhost:1234",
57800
- apiPath: "/v1/chat/completions",
57801
- envVar: "LMSTUDIO_BASE_URL",
57802
- prefixes: ["lmstudio/", "lmstudio:", "mlstudio/", "mlstudio:"],
57803
- capabilities: {
57804
- supportsTools: true,
57805
- supportsVision: false,
57806
- supportsStreaming: true,
57807
- supportsJsonMode: true
57843
+ function validateVertexOAuthConfig() {
57844
+ const config3 = getVertexConfig();
57845
+ if (!config3) {
57846
+ return `Missing VERTEX_PROJECT environment variable.
57847
+
57848
+ ` + `Set it with:
57849
+ ` + ` export VERTEX_PROJECT='your-gcp-project-id'
57850
+ ` + " export VERTEX_LOCATION='us-central1' # optional";
57851
+ }
57852
+ const adcPath = join11(homedir7(), ".config/gcloud/application_default_credentials.json");
57853
+ const hasADC = existsSync6(adcPath);
57854
+ const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
57855
+ if (!hasADC && !hasServiceAccount) {
57856
+ return `No Vertex AI credentials found.
57857
+
57858
+ ` + `Options:
57859
+ ` + `1. Run: gcloud auth application-default login
57860
+ ` + "2. Set: export GOOGLE_APPLICATION_CREDENTIALS='/path/to/service-account.json'";
57861
+ }
57862
+ return null;
57863
+ }
57864
+ function buildVertexOAuthEndpoint(config3, publisher, model, streaming = true) {
57865
+ const method = streaming ? "streamGenerateContent" : "generateContent";
57866
+ if (publisher === "google") {
57867
+ const sseParam = streaming ? "?alt=sse" : "";
57868
+ return `https://${config3.location}-aiplatform.googleapis.com/v1/` + `projects/${config3.projectId}/locations/${config3.location}/` + `publishers/${publisher}/models/${model}:${method}${sseParam}`;
57869
+ } else if (publisher === "mistralai") {
57870
+ const mistralMethod = streaming ? "streamRawPredict" : "rawPredict";
57871
+ return `https://${config3.location}-aiplatform.googleapis.com/v1/` + `projects/${config3.projectId}/locations/${config3.location}/` + `publishers/mistralai/models/${model}:${mistralMethod}`;
57872
+ } else {
57873
+ return `https://aiplatform.googleapis.com/v1/` + `projects/${config3.projectId}/locations/global/` + `endpoints/openapi/chat/completions`;
57874
+ }
57875
+ }
57876
+ function getVertexAuthManager() {
57877
+ if (!authManagerInstance) {
57878
+ authManagerInstance = new VertexAuthManager;
57879
+ }
57880
+ return authManagerInstance;
57881
+ }
57882
+ var execAsync, authManagerInstance = null;
57883
+ var init_vertex_auth = __esm(() => {
57884
+ init_logger();
57885
+ execAsync = promisify(exec2);
57886
+ });
57887
+
57888
+ // ../core/dist/handlers/vertex-oauth-handler.js
57889
+ import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync8 } from "node:fs";
57890
+ import { homedir as homedir8 } from "node:os";
57891
+ import { join as join12 } from "node:path";
57892
+ function parseVertexModel(modelId) {
57893
+ const parts = modelId.split("/");
57894
+ if (parts.length === 1) {
57895
+ return { publisher: "google", model: parts[0] };
57896
+ }
57897
+ return { publisher: parts[0], model: parts.slice(1).join("/") };
57898
+ }
57899
+
57900
+ class VertexOAuthHandler {
57901
+ modelName;
57902
+ port;
57903
+ config;
57904
+ parsed;
57905
+ adapterManager;
57906
+ middlewareManager;
57907
+ sessionTotalCost = 0;
57908
+ sessionInputTokens = 0;
57909
+ sessionOutputTokens = 0;
57910
+ contextWindow = 1e6;
57911
+ toolCallMap = new Map;
57912
+ constructor(modelName, port) {
57913
+ this.modelName = modelName;
57914
+ this.port = port;
57915
+ this.config = getVertexConfig();
57916
+ this.parsed = parseVertexModel(modelName);
57917
+ this.adapterManager = new AdapterManager(`vertex/${modelName}`);
57918
+ this.middlewareManager = new MiddlewareManager;
57919
+ if (this.parsed.publisher === "google") {
57920
+ this.middlewareManager.register(new GeminiThoughtSignatureMiddleware);
57808
57921
  }
57809
- },
57810
- {
57811
- name: "vllm",
57812
- baseUrl: process.env.VLLM_BASE_URL || "http://localhost:8000",
57813
- apiPath: "/v1/chat/completions",
57814
- envVar: "VLLM_BASE_URL",
57815
- prefixes: ["vllm/", "vllm:"],
57816
- capabilities: {
57817
- supportsTools: true,
57818
- supportsVision: false,
57819
- supportsStreaming: true,
57820
- supportsJsonMode: true
57922
+ this.middlewareManager.initialize().catch((err) => log(`[VertexOAuth:${modelName}] Middleware init error: ${err}`));
57923
+ }
57924
+ getPricing() {
57925
+ return getModelPricing("vertex", this.parsed.model);
57926
+ }
57927
+ getApiEndpoint() {
57928
+ return buildVertexOAuthEndpoint(this.config, this.parsed.publisher, this.parsed.model, true);
57929
+ }
57930
+ writeTokenFile(input, output) {
57931
+ try {
57932
+ const total = input + output;
57933
+ const leftPct = this.contextWindow > 0 ? Math.max(0, Math.min(100, Math.round((this.contextWindow - total) / this.contextWindow * 100))) : 100;
57934
+ const data = {
57935
+ input_tokens: input,
57936
+ output_tokens: output,
57937
+ total_tokens: total,
57938
+ total_cost: this.sessionTotalCost,
57939
+ context_window: this.contextWindow,
57940
+ context_left_percent: leftPct,
57941
+ updated_at: Date.now()
57942
+ };
57943
+ const claudishDir = join12(homedir8(), ".claudish");
57944
+ mkdirSync8(claudishDir, { recursive: true });
57945
+ writeFileSync10(join12(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
57946
+ } catch (e) {
57947
+ log(`[VertexOAuth] Error writing token file: ${e}`);
57821
57948
  }
57822
- },
57823
- {
57824
- name: "mlx",
57825
- baseUrl: process.env.MLX_BASE_URL || "http://127.0.0.1:8080",
57826
- apiPath: "/v1/chat/completions",
57827
- envVar: "MLX_BASE_URL",
57828
- prefixes: ["mlx/", "mlx:"],
57829
- capabilities: {
57830
- supportsTools: true,
57831
- supportsVision: false,
57832
- supportsStreaming: true,
57833
- supportsJsonMode: true
57949
+ }
57950
+ updateTokenTracking(inputTokens, outputTokens) {
57951
+ this.sessionInputTokens = inputTokens;
57952
+ this.sessionOutputTokens += outputTokens;
57953
+ const pricing = this.getPricing();
57954
+ const cost = inputTokens / 1e6 * pricing.inputCostPer1M + outputTokens / 1e6 * pricing.outputCostPer1M;
57955
+ this.sessionTotalCost += cost;
57956
+ this.writeTokenFile(inputTokens, this.sessionOutputTokens);
57957
+ }
57958
+ buildPayload(claudeRequest) {
57959
+ if (this.parsed.publisher === "google") {
57960
+ return this.buildGeminiPayload(claudeRequest);
57961
+ } else if (this.parsed.publisher === "anthropic") {
57962
+ return this.buildAnthropicPayload(claudeRequest);
57963
+ } else if (this.parsed.publisher === "mistralai" || this.parsed.publisher === "meta") {
57964
+ return this.buildOpenAIPayload(claudeRequest);
57965
+ } else {
57966
+ return this.buildOpenAIPayload(claudeRequest);
57834
57967
  }
57835
57968
  }
57836
- ];
57969
+ buildGeminiPayload(claudeRequest) {
57970
+ const contents = this.convertToGeminiMessages(claudeRequest);
57971
+ const payload = {
57972
+ contents,
57973
+ generationConfig: {
57974
+ temperature: claudeRequest.temperature ?? 1,
57975
+ maxOutputTokens: claudeRequest.max_tokens
57976
+ }
57977
+ };
57978
+ if (claudeRequest.system) {
57979
+ let systemContent = Array.isArray(claudeRequest.system) ? claudeRequest.system.map((i) => i.text || i).join(`
57837
57980
 
57838
- // ../core/dist/providers/remote-provider-registry.js
57839
- function resolveRemoteProvider(modelId) {
57840
- const providers = getRemoteProviders();
57841
- for (const provider of providers) {
57842
- for (const prefix of provider.prefixes) {
57843
- if (modelId.startsWith(prefix)) {
57844
- return {
57845
- provider,
57846
- modelName: modelId.slice(prefix.length)
57981
+ `) : claudeRequest.system;
57982
+ systemContent = filterIdentity(systemContent);
57983
+ payload.systemInstruction = { parts: [{ text: systemContent }] };
57984
+ }
57985
+ const tools = this.convertToGeminiTools(claudeRequest);
57986
+ if (tools) {
57987
+ payload.tools = tools;
57988
+ }
57989
+ if (claudeRequest.thinking) {
57990
+ const { budget_tokens } = claudeRequest.thinking;
57991
+ if (this.parsed.model.includes("gemini-3")) {
57992
+ payload.generationConfig.thinkingConfig = {
57993
+ thinkingLevel: budget_tokens >= 16000 ? "high" : "low"
57994
+ };
57995
+ } else {
57996
+ const MAX_GEMINI_BUDGET = 24576;
57997
+ payload.generationConfig.thinkingConfig = {
57998
+ thinkingBudget: Math.min(budget_tokens, MAX_GEMINI_BUDGET)
57847
57999
  };
57848
58000
  }
57849
58001
  }
58002
+ return payload;
57850
58003
  }
57851
- return null;
57852
- }
57853
- function validateRemoteProviderApiKey(provider) {
57854
- const apiKey = process.env[provider.apiKeyEnvVar];
57855
- if (!apiKey) {
57856
- const examples = {
57857
- GEMINI_API_KEY: "export GEMINI_API_KEY='your-key' (get from https://aistudio.google.com/app/apikey)",
57858
- OPENAI_API_KEY: "export OPENAI_API_KEY='sk-...' (get from https://platform.openai.com/api-keys)",
57859
- OPENROUTER_API_KEY: "export OPENROUTER_API_KEY='sk-or-...' (get from https://openrouter.ai/keys)",
57860
- MINIMAX_API_KEY: "export MINIMAX_API_KEY='your-key' (get from https://www.minimaxi.com/)",
57861
- MOONSHOT_API_KEY: "export MOONSHOT_API_KEY='your-key' (get from https://platform.moonshot.cn/)",
57862
- ZHIPU_API_KEY: "export ZHIPU_API_KEY='your-key' (get from https://open.bigmodel.cn/)"
58004
+ buildAnthropicPayload(claudeRequest) {
58005
+ const payload = {
58006
+ anthropic_version: "vertex-2023-10-16",
58007
+ messages: claudeRequest.messages,
58008
+ max_tokens: claudeRequest.max_tokens || 4096,
58009
+ stream: true
57863
58010
  };
57864
- const example = examples[provider.apiKeyEnvVar] || `export ${provider.apiKeyEnvVar}='your-key'`;
57865
- return `Missing ${provider.apiKeyEnvVar} environment variable.
58011
+ if (claudeRequest.system) {
58012
+ payload.system = Array.isArray(claudeRequest.system) ? claudeRequest.system.map((i) => i.text || i).join(`
57866
58013
 
57867
- Set it with:
57868
- ${example}`;
57869
- }
58014
+ `) : claudeRequest.system;
58015
+ }
58016
+ if (claudeRequest.temperature !== undefined) {
58017
+ payload.temperature = claudeRequest.temperature;
58018
+ }
58019
+ if (claudeRequest.tools && claudeRequest.tools.length > 0) {
58020
+ payload.tools = claudeRequest.tools;
58021
+ }
58022
+ return payload;
58023
+ }
58024
+ buildOpenAIPayload(claudeRequest) {
58025
+ const messages = [];
58026
+ if (claudeRequest.system) {
58027
+ const systemContent = Array.isArray(claudeRequest.system) ? claudeRequest.system.map((i) => i.text || i).join(`
58028
+
58029
+ `) : claudeRequest.system;
58030
+ messages.push({ role: "system", content: filterIdentity(systemContent) });
58031
+ }
58032
+ if (claudeRequest.messages) {
58033
+ for (const msg of claudeRequest.messages) {
58034
+ if (msg.role === "user") {
58035
+ const content = this.convertClaudeContentToOpenAI(msg.content);
58036
+ messages.push({ role: "user", content });
58037
+ } else if (msg.role === "assistant") {
58038
+ const content = this.convertClaudeContentToOpenAI(msg.content);
58039
+ messages.push({ role: "assistant", content });
58040
+ }
58041
+ }
58042
+ }
58043
+ const modelId = this.parsed.publisher === "mistralai" ? this.parsed.model : `${this.parsed.publisher}/${this.parsed.model}`;
58044
+ const payload = {
58045
+ model: modelId,
58046
+ messages,
58047
+ max_tokens: claudeRequest.max_tokens || 4096,
58048
+ stream: true
58049
+ };
58050
+ if (claudeRequest.temperature !== undefined) {
58051
+ payload.temperature = claudeRequest.temperature;
58052
+ }
58053
+ if (claudeRequest.tools && claudeRequest.tools.length > 0) {
58054
+ payload.tools = claudeRequest.tools.map((tool) => ({
58055
+ type: "function",
58056
+ function: {
58057
+ name: tool.name,
58058
+ description: tool.description,
58059
+ parameters: tool.input_schema
58060
+ }
58061
+ }));
58062
+ }
58063
+ return payload;
58064
+ }
58065
+ convertClaudeContentToOpenAI(content) {
58066
+ if (typeof content === "string") {
58067
+ return content;
58068
+ }
58069
+ if (Array.isArray(content)) {
58070
+ return content.filter((block) => block.type === "text").map((block) => block.text).join(`
58071
+ `);
58072
+ }
58073
+ return "";
58074
+ }
58075
+ convertToGeminiMessages(claudeRequest) {
58076
+ const messages = [];
58077
+ if (claudeRequest.messages) {
58078
+ for (const msg of claudeRequest.messages) {
58079
+ if (msg.role === "user") {
58080
+ const parts = this.convertUserMessageParts(msg);
58081
+ if (parts.length > 0) {
58082
+ messages.push({ role: "user", parts });
58083
+ }
58084
+ } else if (msg.role === "assistant") {
58085
+ const parts = this.convertAssistantMessageParts(msg);
58086
+ if (parts.length > 0) {
58087
+ messages.push({ role: "model", parts });
58088
+ }
58089
+ }
58090
+ }
58091
+ }
58092
+ return messages;
58093
+ }
58094
+ convertUserMessageParts(msg) {
58095
+ const parts = [];
58096
+ if (Array.isArray(msg.content)) {
58097
+ for (const block of msg.content) {
58098
+ if (block.type === "text") {
58099
+ parts.push({ text: block.text });
58100
+ } else if (block.type === "image") {
58101
+ parts.push({
58102
+ inlineData: {
58103
+ mimeType: block.source.media_type,
58104
+ data: block.source.data
58105
+ }
58106
+ });
58107
+ } else if (block.type === "tool_result") {
58108
+ const toolInfo = this.toolCallMap.get(block.tool_use_id);
58109
+ if (toolInfo) {
58110
+ parts.push({
58111
+ functionResponse: {
58112
+ name: toolInfo.name,
58113
+ response: {
58114
+ content: typeof block.content === "string" ? block.content : JSON.stringify(block.content)
58115
+ }
58116
+ }
58117
+ });
58118
+ }
58119
+ }
58120
+ }
58121
+ } else if (typeof msg.content === "string") {
58122
+ parts.push({ text: msg.content });
58123
+ }
58124
+ return parts;
58125
+ }
58126
+ convertAssistantMessageParts(msg) {
58127
+ const parts = [];
58128
+ if (Array.isArray(msg.content)) {
58129
+ for (const block of msg.content) {
58130
+ if (block.type === "text") {
58131
+ parts.push({ text: block.text });
58132
+ } else if (block.type === "tool_use") {
58133
+ const toolInfo = this.toolCallMap.get(block.id);
58134
+ let thoughtSignature = toolInfo?.thoughtSignature || "skip_thought_signature_validator";
58135
+ const functionCallPart = {
58136
+ functionCall: {
58137
+ name: block.name,
58138
+ args: block.input
58139
+ }
58140
+ };
58141
+ if (thoughtSignature) {
58142
+ functionCallPart.thoughtSignature = thoughtSignature;
58143
+ }
58144
+ parts.push(functionCallPart);
58145
+ }
58146
+ }
58147
+ } else if (typeof msg.content === "string") {
58148
+ parts.push({ text: msg.content });
58149
+ }
58150
+ return parts;
58151
+ }
58152
+ convertToGeminiTools(claudeRequest) {
58153
+ if (!claudeRequest.tools || claudeRequest.tools.length === 0) {
58154
+ return;
58155
+ }
58156
+ const functionDeclarations = claudeRequest.tools.map((tool) => ({
58157
+ name: tool.name,
58158
+ description: tool.description,
58159
+ parameters: this.sanitizeSchemaForGemini(tool.input_schema)
58160
+ }));
58161
+ return [{ functionDeclarations }];
58162
+ }
58163
+ sanitizeSchemaForGemini(schema) {
58164
+ if (!schema || typeof schema !== "object")
58165
+ return schema;
58166
+ if (Array.isArray(schema))
58167
+ return schema.map((item) => this.sanitizeSchemaForGemini(item));
58168
+ const result = {};
58169
+ const normalizedType = Array.isArray(schema.type) ? schema.type.filter((t) => t !== "null")[0] || "string" : schema.type || "string";
58170
+ result.type = normalizedType;
58171
+ if (schema.description)
58172
+ result.description = schema.description;
58173
+ if (Array.isArray(schema.enum))
58174
+ result.enum = schema.enum;
58175
+ if (Array.isArray(schema.required))
58176
+ result.required = schema.required;
58177
+ if (schema.properties) {
58178
+ result.properties = {};
58179
+ for (const [key, value] of Object.entries(schema.properties)) {
58180
+ if (value && typeof value === "object") {
58181
+ result.properties[key] = this.sanitizeSchemaForGemini(value);
58182
+ }
58183
+ }
58184
+ }
58185
+ if (schema.items) {
58186
+ result.items = this.sanitizeSchemaForGemini(Array.isArray(schema.items) ? schema.items[0] : schema.items);
58187
+ }
58188
+ return result;
58189
+ }
58190
+ handleGeminiStreamingResponse(c, response) {
58191
+ let isClosed = false;
58192
+ let ping2 = null;
58193
+ const encoder = new TextEncoder;
58194
+ const decoder = new TextDecoder;
58195
+ const toolCallMap = this.toolCallMap;
58196
+ const modelName = this.modelName;
58197
+ return c.body(new ReadableStream({
58198
+ start: async (controller) => {
58199
+ const send = (e, d) => {
58200
+ if (!isClosed) {
58201
+ controller.enqueue(encoder.encode(`event: ${e}
58202
+ data: ${JSON.stringify(d)}
58203
+
58204
+ `));
58205
+ }
58206
+ };
58207
+ const msgId = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`;
58208
+ let usage = null;
58209
+ let finalized = false;
58210
+ let textStarted = false;
58211
+ let textIdx = -1;
58212
+ let thinkingStarted = false;
58213
+ let thinkingIdx = -1;
58214
+ let curIdx = 0;
58215
+ const tools = new Map;
58216
+ let lastActivity = Date.now();
58217
+ send("message_start", {
58218
+ type: "message_start",
58219
+ message: {
58220
+ id: msgId,
58221
+ type: "message",
58222
+ role: "assistant",
58223
+ content: [],
58224
+ model: `vertex/${this.modelName}`,
58225
+ stop_reason: null,
58226
+ stop_sequence: null,
58227
+ usage: { input_tokens: 100, output_tokens: 1 }
58228
+ }
58229
+ });
58230
+ ping2 = setInterval(() => {
58231
+ if (!isClosed && Date.now() - lastActivity > 1000) {
58232
+ send("ping", { type: "ping" });
58233
+ }
58234
+ }, 1000);
58235
+ const finalize = async (reason, err) => {
58236
+ if (finalized)
58237
+ return;
58238
+ finalized = true;
58239
+ if (thinkingStarted)
58240
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
58241
+ if (textStarted)
58242
+ send("content_block_stop", { type: "content_block_stop", index: textIdx });
58243
+ for (const t of Array.from(tools.values())) {
58244
+ if (t.started && !t.closed) {
58245
+ send("content_block_stop", { type: "content_block_stop", index: t.blockIndex });
58246
+ t.closed = true;
58247
+ }
58248
+ }
58249
+ if (usage) {
58250
+ this.updateTokenTracking(usage.promptTokenCount || 0, usage.candidatesTokenCount || 0);
58251
+ }
58252
+ if (reason === "error") {
58253
+ send("error", { type: "error", error: { type: "api_error", message: err } });
58254
+ } else {
58255
+ const hasToolCalls = tools.size > 0;
58256
+ send("message_delta", {
58257
+ type: "message_delta",
58258
+ delta: { stop_reason: hasToolCalls ? "tool_use" : "end_turn", stop_sequence: null },
58259
+ usage: { output_tokens: usage?.candidatesTokenCount || 0 }
58260
+ });
58261
+ send("message_stop", { type: "message_stop" });
58262
+ }
58263
+ if (!isClosed) {
58264
+ try {
58265
+ controller.enqueue(encoder.encode(`data: [DONE]
58266
+
58267
+
58268
+ `));
58269
+ } catch {}
58270
+ controller.close();
58271
+ isClosed = true;
58272
+ if (ping2)
58273
+ clearInterval(ping2);
58274
+ }
58275
+ };
58276
+ try {
58277
+ const reader = response.body.getReader();
58278
+ let buffer = "";
58279
+ while (true) {
58280
+ const { done, value } = await reader.read();
58281
+ if (done)
58282
+ break;
58283
+ buffer += decoder.decode(value, { stream: true });
58284
+ const lines = buffer.split(`
58285
+ `);
58286
+ buffer = lines.pop() || "";
58287
+ for (const line of lines) {
58288
+ if (!line.trim() || !line.startsWith("data: "))
58289
+ continue;
58290
+ const dataStr = line.slice(6);
58291
+ if (dataStr === "[DONE]") {
58292
+ await finalize("done");
58293
+ return;
58294
+ }
58295
+ try {
58296
+ const chunk = JSON.parse(dataStr);
58297
+ if (chunk.usageMetadata)
58298
+ usage = chunk.usageMetadata;
58299
+ const candidate = chunk.candidates?.[0];
58300
+ if (candidate?.content?.parts) {
58301
+ for (const part of candidate.content.parts) {
58302
+ lastActivity = Date.now();
58303
+ if (part.thought || part.thoughtText) {
58304
+ const thinkingContent = part.thought || part.thoughtText;
58305
+ if (!thinkingStarted) {
58306
+ thinkingIdx = curIdx++;
58307
+ send("content_block_start", {
58308
+ type: "content_block_start",
58309
+ index: thinkingIdx,
58310
+ content_block: { type: "thinking", thinking: "" }
58311
+ });
58312
+ thinkingStarted = true;
58313
+ }
58314
+ send("content_block_delta", {
58315
+ type: "content_block_delta",
58316
+ index: thinkingIdx,
58317
+ delta: { type: "thinking_delta", thinking: thinkingContent }
58318
+ });
58319
+ }
58320
+ if (part.text) {
58321
+ if (thinkingStarted) {
58322
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
58323
+ thinkingStarted = false;
58324
+ }
58325
+ if (!textStarted) {
58326
+ textIdx = curIdx++;
58327
+ send("content_block_start", {
58328
+ type: "content_block_start",
58329
+ index: textIdx,
58330
+ content_block: { type: "text", text: "" }
58331
+ });
58332
+ textStarted = true;
58333
+ }
58334
+ send("content_block_delta", {
58335
+ type: "content_block_delta",
58336
+ index: textIdx,
58337
+ delta: { type: "text_delta", text: part.text }
58338
+ });
58339
+ }
58340
+ if (part.functionCall) {
58341
+ if (thinkingStarted) {
58342
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
58343
+ thinkingStarted = false;
58344
+ }
58345
+ if (textStarted) {
58346
+ send("content_block_stop", { type: "content_block_stop", index: textIdx });
58347
+ textStarted = false;
58348
+ }
58349
+ const toolIdx = tools.size;
58350
+ const toolId = `tool_${Date.now()}_${toolIdx}`;
58351
+ const t = {
58352
+ id: toolId,
58353
+ name: part.functionCall.name,
58354
+ blockIndex: curIdx++,
58355
+ started: true,
58356
+ closed: false,
58357
+ arguments: JSON.stringify(part.functionCall.args || {})
58358
+ };
58359
+ tools.set(toolIdx, t);
58360
+ const thoughtSignature = part.thoughtSignature;
58361
+ toolCallMap.set(t.id, { name: t.name, thoughtSignature });
58362
+ send("content_block_start", {
58363
+ type: "content_block_start",
58364
+ index: t.blockIndex,
58365
+ content_block: { type: "tool_use", id: t.id, name: t.name }
58366
+ });
58367
+ send("content_block_delta", {
58368
+ type: "content_block_delta",
58369
+ index: t.blockIndex,
58370
+ delta: { type: "input_json_delta", partial_json: t.arguments }
58371
+ });
58372
+ send("content_block_stop", { type: "content_block_stop", index: t.blockIndex });
58373
+ t.closed = true;
58374
+ }
58375
+ }
58376
+ }
58377
+ if (candidate?.finishReason === "STOP" || candidate?.finishReason === "MAX_TOKENS") {
58378
+ await finalize("done");
58379
+ return;
58380
+ }
58381
+ } catch {}
58382
+ }
58383
+ }
58384
+ await finalize("unexpected");
58385
+ } catch (e) {
58386
+ await finalize("error", String(e));
58387
+ }
58388
+ },
58389
+ cancel() {
58390
+ isClosed = true;
58391
+ if (ping2)
58392
+ clearInterval(ping2);
58393
+ }
58394
+ }), {
58395
+ headers: {
58396
+ "Content-Type": "text/event-stream",
58397
+ "Cache-Control": "no-cache",
58398
+ Connection: "keep-alive"
58399
+ }
58400
+ });
58401
+ }
58402
+ handleAnthropicStreamingResponse(_c, response) {
58403
+ return new Response(response.body, {
58404
+ headers: {
58405
+ "Content-Type": "text/event-stream",
58406
+ "Cache-Control": "no-cache",
58407
+ Connection: "keep-alive"
58408
+ }
58409
+ });
58410
+ }
58411
+ handleOpenAIStreamingResponse(c, response) {
58412
+ let isClosed = false;
58413
+ let ping2 = null;
58414
+ const encoder = new TextEncoder;
58415
+ const decoder = new TextDecoder;
58416
+ return c.body(new ReadableStream({
58417
+ start: async (controller) => {
58418
+ const send = (e, d) => {
58419
+ if (!isClosed) {
58420
+ controller.enqueue(encoder.encode(`event: ${e}
58421
+ data: ${JSON.stringify(d)}
58422
+
58423
+ `));
58424
+ }
58425
+ };
58426
+ const msgId = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`;
58427
+ let finalized = false;
58428
+ let textStarted = false;
58429
+ let textIdx = 0;
58430
+ let lastActivity = Date.now();
58431
+ send("message_start", {
58432
+ type: "message_start",
58433
+ message: {
58434
+ id: msgId,
58435
+ type: "message",
58436
+ role: "assistant",
58437
+ content: [],
58438
+ model: `vertex/${this.modelName}`,
58439
+ stop_reason: null,
58440
+ stop_sequence: null,
58441
+ usage: { input_tokens: 100, output_tokens: 1 }
58442
+ }
58443
+ });
58444
+ ping2 = setInterval(() => {
58445
+ if (!isClosed && Date.now() - lastActivity > 1000) {
58446
+ send("ping", { type: "ping" });
58447
+ }
58448
+ }, 1000);
58449
+ const finalize = async (reason, err) => {
58450
+ if (finalized)
58451
+ return;
58452
+ finalized = true;
58453
+ if (textStarted) {
58454
+ send("content_block_stop", { type: "content_block_stop", index: textIdx });
58455
+ }
58456
+ if (reason === "error") {
58457
+ send("error", { type: "error", error: { type: "api_error", message: err } });
58458
+ } else {
58459
+ send("message_delta", {
58460
+ type: "message_delta",
58461
+ delta: { stop_reason: "end_turn", stop_sequence: null },
58462
+ usage: { output_tokens: 100 }
58463
+ });
58464
+ send("message_stop", { type: "message_stop" });
58465
+ }
58466
+ if (!isClosed) {
58467
+ try {
58468
+ controller.enqueue(encoder.encode(`data: [DONE]
58469
+
58470
+
58471
+ `));
58472
+ } catch {}
58473
+ controller.close();
58474
+ isClosed = true;
58475
+ if (ping2)
58476
+ clearInterval(ping2);
58477
+ }
58478
+ };
58479
+ try {
58480
+ const reader = response.body.getReader();
58481
+ let buffer = "";
58482
+ while (true) {
58483
+ const { done, value } = await reader.read();
58484
+ if (done)
58485
+ break;
58486
+ buffer += decoder.decode(value, { stream: true });
58487
+ const lines = buffer.split(`
58488
+ `);
58489
+ buffer = lines.pop() || "";
58490
+ for (const line of lines) {
58491
+ if (!line.trim() || !line.startsWith("data: "))
58492
+ continue;
58493
+ const dataStr = line.slice(6);
58494
+ if (dataStr === "[DONE]") {
58495
+ await finalize("done");
58496
+ return;
58497
+ }
58498
+ try {
58499
+ const chunk = JSON.parse(dataStr);
58500
+ const choice = chunk.choices?.[0];
58501
+ if (choice?.delta?.content) {
58502
+ lastActivity = Date.now();
58503
+ if (!textStarted) {
58504
+ send("content_block_start", {
58505
+ type: "content_block_start",
58506
+ index: textIdx,
58507
+ content_block: { type: "text", text: "" }
58508
+ });
58509
+ textStarted = true;
58510
+ }
58511
+ send("content_block_delta", {
58512
+ type: "content_block_delta",
58513
+ index: textIdx,
58514
+ delta: { type: "text_delta", text: choice.delta.content }
58515
+ });
58516
+ }
58517
+ if (choice?.finish_reason) {
58518
+ await finalize("done");
58519
+ return;
58520
+ }
58521
+ } catch {}
58522
+ }
58523
+ }
58524
+ await finalize("done");
58525
+ } catch (e) {
58526
+ await finalize("error", String(e));
58527
+ }
58528
+ },
58529
+ cancel() {
58530
+ isClosed = true;
58531
+ if (ping2)
58532
+ clearInterval(ping2);
58533
+ }
58534
+ }), {
58535
+ headers: {
58536
+ "Content-Type": "text/event-stream",
58537
+ "Cache-Control": "no-cache",
58538
+ Connection: "keep-alive"
58539
+ }
58540
+ });
58541
+ }
58542
+ async handle(c, payload) {
58543
+ const { claudeRequest, droppedParams } = transformOpenAIToClaude(payload);
58544
+ logStructured("Vertex OAuth Request", {
58545
+ targetModel: `vertex/${this.modelName}`,
58546
+ publisher: this.parsed.publisher,
58547
+ model: this.parsed.model,
58548
+ project: this.config.projectId,
58549
+ location: this.config.location,
58550
+ messageCount: claudeRequest.messages?.length || 0,
58551
+ toolCount: claudeRequest.tools?.length || 0
58552
+ });
58553
+ const authManager = getVertexAuthManager();
58554
+ let accessToken;
58555
+ try {
58556
+ accessToken = await authManager.getAccessToken();
58557
+ } catch (e) {
58558
+ log(`[VertexOAuth] Auth failed: ${e.message}`);
58559
+ return c.json({
58560
+ error: {
58561
+ type: "authentication_error",
58562
+ message: e.message
58563
+ }
58564
+ }, 401);
58565
+ }
58566
+ const requestPayload = this.buildPayload(claudeRequest);
58567
+ const endpoint = this.getApiEndpoint();
58568
+ log(`[VertexOAuth] Calling API: ${endpoint}`);
58569
+ const controller = new AbortController;
58570
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
58571
+ let response;
58572
+ try {
58573
+ response = await fetch(endpoint, {
58574
+ method: "POST",
58575
+ headers: {
58576
+ "Content-Type": "application/json",
58577
+ Authorization: `Bearer ${accessToken}`
58578
+ },
58579
+ body: JSON.stringify(requestPayload),
58580
+ signal: controller.signal
58581
+ });
58582
+ } catch (fetchError) {
58583
+ clearTimeout(timeoutId);
58584
+ if (fetchError.name === "AbortError") {
58585
+ return c.json({ error: { type: "timeout_error", message: "Request timed out" } }, 504);
58586
+ }
58587
+ return c.json({ error: { type: "network_error", message: fetchError.message } }, 503);
58588
+ } finally {
58589
+ clearTimeout(timeoutId);
58590
+ }
58591
+ log(`[VertexOAuth] Response status: ${response.status}`);
58592
+ if (response.status === 401) {
58593
+ log("[VertexOAuth] Got 401, refreshing token and retrying");
58594
+ await authManager.refreshToken();
58595
+ const newToken = await authManager.getAccessToken();
58596
+ response = await fetch(endpoint, {
58597
+ method: "POST",
58598
+ headers: {
58599
+ "Content-Type": "application/json",
58600
+ Authorization: `Bearer ${newToken}`
58601
+ },
58602
+ body: JSON.stringify(requestPayload)
58603
+ });
58604
+ if (!response.ok) {
58605
+ const errorText = await response.text();
58606
+ return c.json({ error: errorText }, response.status);
58607
+ }
58608
+ }
58609
+ if (!response.ok) {
58610
+ const errorText = await response.text();
58611
+ log(`[VertexOAuth] Error: ${errorText}`);
58612
+ return c.json({ error: errorText }, response.status);
58613
+ }
58614
+ if (droppedParams.length > 0) {
58615
+ c.header("X-Dropped-Params", droppedParams.join(", "));
58616
+ }
58617
+ if (this.parsed.publisher === "google") {
58618
+ return this.handleGeminiStreamingResponse(c, response);
58619
+ } else if (this.parsed.publisher === "anthropic") {
58620
+ return this.handleAnthropicStreamingResponse(c, response);
58621
+ } else {
58622
+ return this.handleOpenAIStreamingResponse(c, response);
58623
+ }
58624
+ }
58625
+ async shutdown() {}
58626
+ }
58627
+ var init_vertex_oauth_handler = __esm(() => {
58628
+ init_adapter_manager();
58629
+ init_middleware();
58630
+ init_transform();
58631
+ init_logger();
58632
+ init_openai_compat();
58633
+ init_remote_provider_types();
58634
+ init_vertex_auth();
58635
+ });
58636
+
58637
+ // ../core/dist/providers/provider-registry.js
58638
+ function getRegisteredProviders() {
58639
+ return getProviders();
58640
+ }
58641
+ function resolveProvider(modelId) {
58642
+ const providers = getProviders();
58643
+ for (const provider of providers) {
58644
+ for (const prefix of provider.prefixes) {
58645
+ if (modelId.startsWith(prefix)) {
58646
+ return {
58647
+ provider,
58648
+ modelName: modelId.slice(prefix.length)
58649
+ };
58650
+ }
58651
+ }
58652
+ }
58653
+ return null;
58654
+ }
58655
+ function isLocalProvider(modelId) {
58656
+ if (resolveProvider(modelId) !== null) {
58657
+ return true;
58658
+ }
58659
+ if (parseUrlModel(modelId) !== null) {
58660
+ return true;
58661
+ }
58662
+ return false;
58663
+ }
58664
+ function parseUrlModel(modelId) {
58665
+ if (!modelId.startsWith("http://") && !modelId.startsWith("https://")) {
58666
+ return null;
58667
+ }
58668
+ try {
58669
+ const url2 = new URL(modelId);
58670
+ const pathParts = url2.pathname.split("/").filter(Boolean);
58671
+ if (pathParts.length === 0) {
58672
+ return null;
58673
+ }
58674
+ const modelName = pathParts[pathParts.length - 1];
58675
+ let basePath = "";
58676
+ if (pathParts.length > 1) {
58677
+ const prefix = pathParts.slice(0, -1).join("/");
58678
+ if (prefix)
58679
+ basePath = "/" + prefix;
58680
+ }
58681
+ const baseUrl = `${url2.protocol}//${url2.host}${basePath}`;
58682
+ return {
58683
+ baseUrl,
58684
+ modelName
58685
+ };
58686
+ } catch {
58687
+ return null;
58688
+ }
58689
+ }
58690
+ function createUrlProvider(parsed) {
58691
+ return {
58692
+ name: "custom-url",
58693
+ baseUrl: parsed.baseUrl,
58694
+ apiPath: "/v1/chat/completions",
58695
+ envVar: "",
58696
+ prefixes: [],
58697
+ capabilities: {
58698
+ supportsTools: true,
58699
+ supportsVision: false,
58700
+ supportsStreaming: true,
58701
+ supportsJsonMode: true
58702
+ }
58703
+ };
58704
+ }
58705
+ var getProviders = () => [
58706
+ {
58707
+ name: "ollama",
58708
+ baseUrl: process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434",
58709
+ apiPath: "/v1/chat/completions",
58710
+ envVar: "OLLAMA_BASE_URL",
58711
+ prefixes: ["ollama/", "ollama:"],
58712
+ capabilities: {
58713
+ supportsTools: true,
58714
+ supportsVision: false,
58715
+ supportsStreaming: true,
58716
+ supportsJsonMode: true
58717
+ }
58718
+ },
58719
+ {
58720
+ name: "lmstudio",
58721
+ baseUrl: process.env.LMSTUDIO_BASE_URL || "http://localhost:1234",
58722
+ apiPath: "/v1/chat/completions",
58723
+ envVar: "LMSTUDIO_BASE_URL",
58724
+ prefixes: ["lmstudio/", "lmstudio:", "mlstudio/", "mlstudio:"],
58725
+ capabilities: {
58726
+ supportsTools: true,
58727
+ supportsVision: false,
58728
+ supportsStreaming: true,
58729
+ supportsJsonMode: true
58730
+ }
58731
+ },
58732
+ {
58733
+ name: "vllm",
58734
+ baseUrl: process.env.VLLM_BASE_URL || "http://localhost:8000",
58735
+ apiPath: "/v1/chat/completions",
58736
+ envVar: "VLLM_BASE_URL",
58737
+ prefixes: ["vllm/", "vllm:"],
58738
+ capabilities: {
58739
+ supportsTools: true,
58740
+ supportsVision: false,
58741
+ supportsStreaming: true,
58742
+ supportsJsonMode: true
58743
+ }
58744
+ },
58745
+ {
58746
+ name: "mlx",
58747
+ baseUrl: process.env.MLX_BASE_URL || "http://127.0.0.1:8080",
58748
+ apiPath: "/v1/chat/completions",
58749
+ envVar: "MLX_BASE_URL",
58750
+ prefixes: ["mlx/", "mlx:"],
58751
+ capabilities: {
58752
+ supportsTools: true,
58753
+ supportsVision: false,
58754
+ supportsStreaming: true,
58755
+ supportsJsonMode: true
58756
+ }
58757
+ }
58758
+ ];
58759
+
58760
+ // ../core/dist/providers/remote-provider-registry.js
58761
+ function resolveRemoteProvider(modelId) {
58762
+ const providers = getRemoteProviders();
58763
+ for (const provider of providers) {
58764
+ for (const prefix of provider.prefixes) {
58765
+ if (modelId.startsWith(prefix)) {
58766
+ return {
58767
+ provider,
58768
+ modelName: modelId.slice(prefix.length)
58769
+ };
58770
+ }
58771
+ }
58772
+ }
58773
+ return null;
58774
+ }
58775
+ function validateRemoteProviderApiKey(provider) {
58776
+ const apiKey = process.env[provider.apiKeyEnvVar];
58777
+ if (!apiKey) {
58778
+ const examples = {
58779
+ GEMINI_API_KEY: "export GEMINI_API_KEY='your-key' (get from https://aistudio.google.com/app/apikey)",
58780
+ VERTEX_API_KEY: "export VERTEX_API_KEY='your-key' (get from Google Cloud Console)",
58781
+ OPENAI_API_KEY: "export OPENAI_API_KEY='sk-...' (get from https://platform.openai.com/api-keys)",
58782
+ OPENROUTER_API_KEY: "export OPENROUTER_API_KEY='sk-or-...' (get from https://openrouter.ai/keys)",
58783
+ MINIMAX_API_KEY: "export MINIMAX_API_KEY='your-key' (get from https://www.minimaxi.com/)",
58784
+ MOONSHOT_API_KEY: "export MOONSHOT_API_KEY='your-key' (get from https://platform.moonshot.cn/)",
58785
+ ZHIPU_API_KEY: "export ZHIPU_API_KEY='your-key' (get from https://open.bigmodel.cn/)"
58786
+ };
58787
+ const example = examples[provider.apiKeyEnvVar] || `export ${provider.apiKeyEnvVar}='your-key'`;
58788
+ return `Missing ${provider.apiKeyEnvVar} environment variable.
58789
+
58790
+ Set it with:
58791
+ ${example}`;
58792
+ }
57870
58793
  return null;
57871
58794
  }
57872
58795
  function getRegisteredRemoteProviders() {
@@ -57887,6 +58810,20 @@ var getRemoteProviders = () => [
57887
58810
  supportsReasoning: true
57888
58811
  }
57889
58812
  },
58813
+ {
58814
+ name: "vertex",
58815
+ baseUrl: process.env.VERTEX_BASE_URL || "https://aiplatform.googleapis.com",
58816
+ apiPath: "/v1/publishers/google/models/{model}:streamGenerateContent?alt=sse",
58817
+ apiKeyEnvVar: "VERTEX_API_KEY",
58818
+ prefixes: ["vertex/", "v/"],
58819
+ capabilities: {
58820
+ supportsTools: true,
58821
+ supportsVision: true,
58822
+ supportsStreaming: true,
58823
+ supportsJsonMode: false,
58824
+ supportsReasoning: true
58825
+ }
58826
+ },
57890
58827
  {
57891
58828
  name: "openai",
57892
58829
  baseUrl: process.env.OPENAI_BASE_URL || "https://api.openai.com",
@@ -58010,6 +58947,29 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
58010
58947
  if (resolved.provider.name === "openrouter") {
58011
58948
  return null;
58012
58949
  }
58950
+ if (resolved.provider.name === "vertex") {
58951
+ const hasApiKey = !!process.env.VERTEX_API_KEY;
58952
+ const vertexConfig = getVertexConfig();
58953
+ let handler2;
58954
+ if (hasApiKey) {
58955
+ const apiKey2 = process.env.VERTEX_API_KEY;
58956
+ handler2 = new GeminiHandler(resolved.provider, resolved.modelName, apiKey2, port);
58957
+ log(`[Proxy] Created Vertex AI Express handler: ${resolved.modelName}`);
58958
+ } else if (vertexConfig) {
58959
+ const oauthError = validateVertexOAuthConfig();
58960
+ if (oauthError) {
58961
+ log(`[Proxy] Vertex OAuth config error: ${oauthError}`);
58962
+ return null;
58963
+ }
58964
+ handler2 = new VertexOAuthHandler(resolved.modelName, port);
58965
+ log(`[Proxy] Created Vertex AI OAuth handler: ${resolved.modelName} (project: ${vertexConfig.projectId})`);
58966
+ } else {
58967
+ log(`[Proxy] Vertex AI requires either VERTEX_API_KEY or VERTEX_PROJECT`);
58968
+ return null;
58969
+ }
58970
+ remoteProviderHandlers.set(targetModel, handler2);
58971
+ return handler2;
58972
+ }
58013
58973
  const apiKeyError = validateRemoteProviderApiKey(resolved.provider);
58014
58974
  if (apiKeyError) {
58015
58975
  throw new Error(apiKeyError);
@@ -58125,6 +59085,8 @@ var init_proxy_server = __esm(() => {
58125
59085
  init_gemini_handler();
58126
59086
  init_openai_handler();
58127
59087
  init_anthropic_compat_handler();
59088
+ init_vertex_oauth_handler();
59089
+ init_vertex_auth();
58128
59090
  });
58129
59091
 
58130
59092
  // ../core/dist/index.js
@@ -58177,15 +59139,15 @@ var init_dist11 = __esm(() => {
58177
59139
  });
58178
59140
 
58179
59141
  // src/model-loader.ts
58180
- import { readFileSync as readFileSync5, existsSync as existsSync6 } from "node:fs";
58181
- import { join as join11, dirname as dirname4 } from "node:path";
59142
+ import { readFileSync as readFileSync5, existsSync as existsSync7 } from "node:fs";
59143
+ import { join as join13, dirname as dirname4 } from "node:path";
58182
59144
  import { fileURLToPath as fileURLToPath4 } from "node:url";
58183
59145
  function loadModelInfo2() {
58184
59146
  if (_cachedModelInfo2) {
58185
59147
  return _cachedModelInfo2;
58186
59148
  }
58187
- const jsonPath = join11(__dirname5, "../recommended-models.json");
58188
- if (existsSync6(jsonPath)) {
59149
+ const jsonPath = join13(__dirname5, "../recommended-models.json");
59150
+ if (existsSync7(jsonPath)) {
58189
59151
  try {
58190
59152
  const jsonContent = readFileSync5(jsonPath, "utf-8");
58191
59153
  const data = JSON.parse(jsonContent);
@@ -58217,8 +59179,8 @@ function getAvailableModels() {
58217
59179
  if (_cachedModelIds) {
58218
59180
  return _cachedModelIds;
58219
59181
  }
58220
- const jsonPath = join11(__dirname5, "../recommended-models.json");
58221
- if (existsSync6(jsonPath)) {
59182
+ const jsonPath = join13(__dirname5, "../recommended-models.json");
59183
+ if (existsSync7(jsonPath)) {
58222
59184
  try {
58223
59185
  const jsonContent = readFileSync5(jsonPath, "utf-8");
58224
59186
  const data = JSON.parse(jsonContent);
@@ -58280,9 +59242,9 @@ __export(exports_cli, {
58280
59242
  parseArgs: () => parseArgs,
58281
59243
  getVersion: () => getVersion
58282
59244
  });
58283
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync10, existsSync as existsSync7, mkdirSync as mkdirSync8, copyFileSync } from "node:fs";
59245
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync11, existsSync as existsSync8, mkdirSync as mkdirSync9, copyFileSync } from "node:fs";
58284
59246
  import { fileURLToPath as fileURLToPath5 } from "node:url";
58285
- import { dirname as dirname5, join as join12 } from "node:path";
59247
+ import { dirname as dirname5, join as join14 } from "node:path";
58286
59248
  function getVersion() {
58287
59249
  return VERSION;
58288
59250
  }
@@ -58555,7 +59517,7 @@ async function fetchOllamaModels() {
58555
59517
  }
58556
59518
  async function searchAndPrintModels(query, forceUpdate) {
58557
59519
  let models = [];
58558
- if (!forceUpdate && existsSync7(ALL_MODELS_JSON_PATH2)) {
59520
+ if (!forceUpdate && existsSync8(ALL_MODELS_JSON_PATH2)) {
58559
59521
  try {
58560
59522
  const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH2, "utf-8"));
58561
59523
  const lastUpdated = new Date(cacheData.lastUpdated);
@@ -58574,7 +59536,7 @@ async function searchAndPrintModels(query, forceUpdate) {
58574
59536
  throw new Error(`API returned ${response.status}`);
58575
59537
  const data = await response.json();
58576
59538
  models = data.data;
58577
- writeFileSync10(ALL_MODELS_JSON_PATH2, JSON.stringify({
59539
+ writeFileSync11(ALL_MODELS_JSON_PATH2, JSON.stringify({
58578
59540
  lastUpdated: new Date().toISOString(),
58579
59541
  models
58580
59542
  }), "utf-8");
@@ -58653,7 +59615,7 @@ Found ${results.length} matching models:
58653
59615
  async function printAllModels(jsonOutput, forceUpdate) {
58654
59616
  let models = [];
58655
59617
  const ollamaModels = await fetchOllamaModels();
58656
- if (!forceUpdate && existsSync7(ALL_MODELS_JSON_PATH2)) {
59618
+ if (!forceUpdate && existsSync8(ALL_MODELS_JSON_PATH2)) {
58657
59619
  try {
58658
59620
  const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH2, "utf-8"));
58659
59621
  const lastUpdated = new Date(cacheData.lastUpdated);
@@ -58675,7 +59637,7 @@ async function printAllModels(jsonOutput, forceUpdate) {
58675
59637
  throw new Error(`API returned ${response.status}`);
58676
59638
  const data = await response.json();
58677
59639
  models = data.data;
58678
- writeFileSync10(ALL_MODELS_JSON_PATH2, JSON.stringify({
59640
+ writeFileSync11(ALL_MODELS_JSON_PATH2, JSON.stringify({
58679
59641
  lastUpdated: new Date().toISOString(),
58680
59642
  models
58681
59643
  }), "utf-8");
@@ -58785,7 +59747,7 @@ async function printAllModels(jsonOutput, forceUpdate) {
58785
59747
  console.log("Top models: claudish --top-models");
58786
59748
  }
58787
59749
  function isCacheStale() {
58788
- if (!existsSync7(MODELS_JSON_PATH)) {
59750
+ if (!existsSync8(MODELS_JSON_PATH)) {
58789
59751
  return true;
58790
59752
  }
58791
59753
  try {
@@ -58884,7 +59846,7 @@ async function updateModelsFromOpenRouter() {
58884
59846
  providers.add(provider);
58885
59847
  }
58886
59848
  let version2 = "1.1.5";
58887
- if (existsSync7(MODELS_JSON_PATH)) {
59849
+ if (existsSync8(MODELS_JSON_PATH)) {
58888
59850
  try {
58889
59851
  const existing = JSON.parse(readFileSync6(MODELS_JSON_PATH, "utf-8"));
58890
59852
  version2 = existing.version || version2;
@@ -58896,7 +59858,7 @@ async function updateModelsFromOpenRouter() {
58896
59858
  source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
58897
59859
  models: recommendations
58898
59860
  };
58899
- writeFileSync10(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
59861
+ writeFileSync11(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
58900
59862
  console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
58901
59863
  } catch (error46) {
58902
59864
  console.error(`❌ Failed to update models: ${error46 instanceof Error ? error46.message : String(error46)}`);
@@ -58933,6 +59895,7 @@ USAGE:
58933
59895
  MODEL ROUTING (prefix-based):
58934
59896
  (no prefix) OpenRouter (default) claudish --model openai/gpt-5.2 "task"
58935
59897
  g/, gemini/ Google Gemini API claudish --model g/gemini-2.0-flash "task"
59898
+ v/, vertex/ Vertex AI (OAuth) claudish --model v/gemini-2.5-flash "task"
58936
59899
  oai/ OpenAI Direct API claudish --model oai/gpt-4o "task"
58937
59900
  mmax/, mm/ MiniMax Direct API claudish --model mmax/MiniMax-M2.1 "task"
58938
59901
  kimi/, moonshot/ Kimi Direct API claudish --model kimi/kimi-k2-thinking-turbo "task"
@@ -59009,6 +59972,9 @@ ENVIRONMENT VARIABLES:
59009
59972
  API Keys (at least one required for cloud models):
59010
59973
  OPENROUTER_API_KEY OpenRouter API key (default backend)
59011
59974
  GEMINI_API_KEY Google Gemini API key (for g/ prefix)
59975
+ VERTEX_API_KEY Vertex AI Express API key (for v/ prefix)
59976
+ VERTEX_PROJECT Vertex AI project ID (OAuth mode, for v/ prefix)
59977
+ VERTEX_LOCATION Vertex AI region (default: us-central1)
59012
59978
  OPENAI_API_KEY OpenAI API key (for oai/ prefix)
59013
59979
  MINIMAX_API_KEY MiniMax API key (for mmax/, mm/ prefix)
59014
59980
  MOONSHOT_API_KEY Kimi/Moonshot API key (for kimi/, moonshot/ prefix)
@@ -59060,6 +60026,15 @@ EXAMPLES:
59060
60026
  claudish --model g/gemini-2.0-flash "quick fix"
59061
60027
  claudish --model gemini/gemini-2.5-pro "complex analysis"
59062
60028
 
60029
+ # Vertex AI (Google Cloud - supports Google + partner models)
60030
+ # Express mode (API key):
60031
+ VERTEX_API_KEY=... claudish --model v/gemini-2.5-flash "task"
60032
+ # OAuth mode (gcloud auth):
60033
+ VERTEX_PROJECT=my-project claudish --model v/gemini-2.5-flash "task"
60034
+ # Partner models (MiniMax, Mistral on Vertex):
60035
+ claudish --model vertex/minimaxai/minimax-m2-maas "task"
60036
+ claudish --model vertex/mistralai/codestral-2 "write code"
60037
+
59063
60038
  # Direct OpenAI API
59064
60039
  claudish --model oai/gpt-4o "implement feature"
59065
60040
  claudish --model oai/o1 "complex reasoning"
@@ -59142,7 +60117,7 @@ MORE INFO:
59142
60117
  }
59143
60118
  function printAIAgentGuide() {
59144
60119
  try {
59145
- const guidePath = join12(__dirname6, "../AI_AGENT_GUIDE.md");
60120
+ const guidePath = join14(__dirname6, "../AI_AGENT_GUIDE.md");
59146
60121
  const guideContent = readFileSync6(guidePath, "utf-8");
59147
60122
  console.log(guideContent);
59148
60123
  } catch (error46) {
@@ -59159,19 +60134,19 @@ async function initializeClaudishSkill() {
59159
60134
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
59160
60135
  `);
59161
60136
  const cwd = process.cwd();
59162
- const claudeDir = join12(cwd, ".claude");
59163
- const skillsDir = join12(claudeDir, "skills");
59164
- const claudishSkillDir = join12(skillsDir, "claudish-usage");
59165
- const skillFile = join12(claudishSkillDir, "SKILL.md");
59166
- if (existsSync7(skillFile)) {
60137
+ const claudeDir = join14(cwd, ".claude");
60138
+ const skillsDir = join14(claudeDir, "skills");
60139
+ const claudishSkillDir = join14(skillsDir, "claudish-usage");
60140
+ const skillFile = join14(claudishSkillDir, "SKILL.md");
60141
+ if (existsSync8(skillFile)) {
59167
60142
  console.log("✅ Claudish skill already installed at:");
59168
60143
  console.log(` ${skillFile}
59169
60144
  `);
59170
60145
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
59171
60146
  return;
59172
60147
  }
59173
- const sourceSkillPath = join12(__dirname6, "../skills/claudish-usage/SKILL.md");
59174
- if (!existsSync7(sourceSkillPath)) {
60148
+ const sourceSkillPath = join14(__dirname6, "../skills/claudish-usage/SKILL.md");
60149
+ if (!existsSync8(sourceSkillPath)) {
59175
60150
  console.error("❌ Error: Claudish skill file not found in installation.");
59176
60151
  console.error(` Expected at: ${sourceSkillPath}`);
59177
60152
  console.error(`
@@ -59180,16 +60155,16 @@ async function initializeClaudishSkill() {
59180
60155
  process.exit(1);
59181
60156
  }
59182
60157
  try {
59183
- if (!existsSync7(claudeDir)) {
59184
- mkdirSync8(claudeDir, { recursive: true });
60158
+ if (!existsSync8(claudeDir)) {
60159
+ mkdirSync9(claudeDir, { recursive: true });
59185
60160
  console.log("\uD83D\uDCC1 Created .claude/ directory");
59186
60161
  }
59187
- if (!existsSync7(skillsDir)) {
59188
- mkdirSync8(skillsDir, { recursive: true });
60162
+ if (!existsSync8(skillsDir)) {
60163
+ mkdirSync9(skillsDir, { recursive: true });
59189
60164
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
59190
60165
  }
59191
- if (!existsSync7(claudishSkillDir)) {
59192
- mkdirSync8(claudishSkillDir, { recursive: true });
60166
+ if (!existsSync8(claudishSkillDir)) {
60167
+ mkdirSync9(claudishSkillDir, { recursive: true });
59193
60168
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
59194
60169
  }
59195
60170
  copyFileSync(sourceSkillPath, skillFile);
@@ -59231,7 +60206,7 @@ function printAvailableModels() {
59231
60206
  let lastUpdated = "unknown";
59232
60207
  let models = [];
59233
60208
  try {
59234
- if (existsSync7(MODELS_JSON_PATH)) {
60209
+ if (existsSync8(MODELS_JSON_PATH)) {
59235
60210
  const data = JSON.parse(readFileSync6(MODELS_JSON_PATH, "utf-8"));
59236
60211
  lastUpdated = data.lastUpdated || "unknown";
59237
60212
  models = data.models || [];
@@ -59283,7 +60258,7 @@ Force update: claudish --list-models --force-update
59283
60258
  `);
59284
60259
  }
59285
60260
  function printAvailableModelsJSON() {
59286
- const jsonPath = join12(__dirname6, "../recommended-models.json");
60261
+ const jsonPath = join14(__dirname6, "../recommended-models.json");
59287
60262
  try {
59288
60263
  const jsonContent = readFileSync6(jsonPath, "utf-8");
59289
60264
  const data = JSON.parse(jsonContent);
@@ -59309,7 +60284,7 @@ function printAvailableModelsJSON() {
59309
60284
  console.log(JSON.stringify(output, null, 2));
59310
60285
  }
59311
60286
  }
59312
- var __filename6, __dirname6, VERSION = "3.3.5", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, ALL_MODELS_JSON_PATH2;
60287
+ var __filename6, __dirname6, VERSION = "3.5.0", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, ALL_MODELS_JSON_PATH2;
59313
60288
  var init_cli = __esm(() => {
59314
60289
  init_dist11();
59315
60290
  init_model_loader2();
@@ -59317,11 +60292,11 @@ var init_cli = __esm(() => {
59317
60292
  __filename6 = fileURLToPath5(import.meta.url);
59318
60293
  __dirname6 = dirname5(__filename6);
59319
60294
  try {
59320
- const packageJson = JSON.parse(readFileSync6(join12(__dirname6, "../package.json"), "utf-8"));
60295
+ const packageJson = JSON.parse(readFileSync6(join14(__dirname6, "../package.json"), "utf-8"));
59321
60296
  VERSION = packageJson.version;
59322
60297
  } catch {}
59323
- MODELS_JSON_PATH = join12(__dirname6, "../recommended-models.json");
59324
- ALL_MODELS_JSON_PATH2 = join12(__dirname6, "../all-models.json");
60298
+ MODELS_JSON_PATH = join14(__dirname6, "../recommended-models.json");
60299
+ ALL_MODELS_JSON_PATH2 = join14(__dirname6, "../all-models.json");
59325
60300
  });
59326
60301
 
59327
60302
  // src/update-checker.ts
@@ -59333,31 +60308,31 @@ __export(exports_update_checker, {
59333
60308
  checkForUpdates: () => checkForUpdates
59334
60309
  });
59335
60310
  import { execSync } from "node:child_process";
59336
- import { existsSync as existsSync8, mkdirSync as mkdirSync9, readFileSync as readFileSync7, unlinkSync, writeFileSync as writeFileSync11 } from "node:fs";
59337
- import { homedir as homedir7, platform, tmpdir } from "node:os";
59338
- import { join as join13 } from "node:path";
60311
+ import { existsSync as existsSync9, mkdirSync as mkdirSync10, readFileSync as readFileSync7, unlinkSync, writeFileSync as writeFileSync12 } from "node:fs";
60312
+ import { homedir as homedir9, platform, tmpdir } from "node:os";
60313
+ import { join as join15 } from "node:path";
59339
60314
  import { createInterface as createInterface2 } from "node:readline";
59340
60315
  function getCacheFilePath() {
59341
60316
  let cacheDir;
59342
60317
  if (isWindows) {
59343
- const localAppData = process.env.LOCALAPPDATA || join13(homedir7(), "AppData", "Local");
59344
- cacheDir = join13(localAppData, "claudish");
60318
+ const localAppData = process.env.LOCALAPPDATA || join15(homedir9(), "AppData", "Local");
60319
+ cacheDir = join15(localAppData, "claudish");
59345
60320
  } else {
59346
- cacheDir = join13(homedir7(), ".cache", "claudish");
60321
+ cacheDir = join15(homedir9(), ".cache", "claudish");
59347
60322
  }
59348
60323
  try {
59349
- if (!existsSync8(cacheDir)) {
59350
- mkdirSync9(cacheDir, { recursive: true });
60324
+ if (!existsSync9(cacheDir)) {
60325
+ mkdirSync10(cacheDir, { recursive: true });
59351
60326
  }
59352
- return join13(cacheDir, "update-check.json");
60327
+ return join15(cacheDir, "update-check.json");
59353
60328
  } catch {
59354
- return join13(tmpdir(), "claudish-update-check.json");
60329
+ return join15(tmpdir(), "claudish-update-check.json");
59355
60330
  }
59356
60331
  }
59357
60332
  function readCache() {
59358
60333
  try {
59359
60334
  const cachePath = getCacheFilePath();
59360
- if (!existsSync8(cachePath)) {
60335
+ if (!existsSync9(cachePath)) {
59361
60336
  return null;
59362
60337
  }
59363
60338
  const data = JSON.parse(readFileSync7(cachePath, "utf-8"));
@@ -59373,7 +60348,7 @@ function writeCache(latestVersion) {
59373
60348
  lastCheck: Date.now(),
59374
60349
  latestVersion
59375
60350
  };
59376
- writeFileSync11(cachePath, JSON.stringify(data), "utf-8");
60351
+ writeFileSync12(cachePath, JSON.stringify(data), "utf-8");
59377
60352
  } catch {}
59378
60353
  }
59379
60354
  function isCacheValid(cache) {
@@ -59383,7 +60358,7 @@ function isCacheValid(cache) {
59383
60358
  function clearCache() {
59384
60359
  try {
59385
60360
  const cachePath = getCacheFilePath();
59386
- if (existsSync8(cachePath)) {
60361
+ if (existsSync9(cachePath)) {
59387
60362
  unlinkSync(cachePath);
59388
60363
  }
59389
60364
  } catch {}
@@ -59649,17 +60624,17 @@ __export(exports_claude_runner, {
59649
60624
  checkClaudeInstalled: () => checkClaudeInstalled
59650
60625
  });
59651
60626
  import { spawn } from "node:child_process";
59652
- import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync2, mkdirSync as mkdirSync10 } from "node:fs";
60627
+ import { writeFileSync as writeFileSync13, unlinkSync as unlinkSync2, mkdirSync as mkdirSync11 } from "node:fs";
59653
60628
  import { tmpdir as tmpdir2 } from "node:os";
59654
- import { join as join14 } from "node:path";
60629
+ import { join as join16 } from "node:path";
59655
60630
  function isWindows2() {
59656
60631
  return process.platform === "win32";
59657
60632
  }
59658
60633
  function createStatusLineScript(tokenFilePath) {
59659
60634
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
59660
- const claudishDir = join14(homeDir, ".claudish");
60635
+ const claudishDir = join16(homeDir, ".claudish");
59661
60636
  const timestamp = Date.now();
59662
- const scriptPath = join14(claudishDir, `status-${timestamp}.js`);
60637
+ const scriptPath = join16(claudishDir, `status-${timestamp}.js`);
59663
60638
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
59664
60639
  const script = `
59665
60640
  const fs = require('fs');
@@ -59703,18 +60678,18 @@ process.stdin.on('end', () => {
59703
60678
  }
59704
60679
  });
59705
60680
  `;
59706
- writeFileSync12(scriptPath, script, "utf-8");
60681
+ writeFileSync13(scriptPath, script, "utf-8");
59707
60682
  return scriptPath;
59708
60683
  }
59709
60684
  function createTempSettingsFile(modelDisplay, port) {
59710
60685
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
59711
- const claudishDir = join14(homeDir, ".claudish");
60686
+ const claudishDir = join16(homeDir, ".claudish");
59712
60687
  try {
59713
- mkdirSync10(claudishDir, { recursive: true });
60688
+ mkdirSync11(claudishDir, { recursive: true });
59714
60689
  } catch {}
59715
60690
  const timestamp = Date.now();
59716
- const tempPath = join14(claudishDir, `settings-${timestamp}.json`);
59717
- const tokenFilePath = join14(claudishDir, `tokens-${port}.json`);
60691
+ const tempPath = join16(claudishDir, `settings-${timestamp}.json`);
60692
+ const tokenFilePath = join16(claudishDir, `tokens-${port}.json`);
59718
60693
  let statusCommand;
59719
60694
  if (isWindows2()) {
59720
60695
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -59736,7 +60711,7 @@ function createTempSettingsFile(modelDisplay, port) {
59736
60711
  padding: 0
59737
60712
  }
59738
60713
  };
59739
- writeFileSync12(tempPath, JSON.stringify(settings, null, 2), "utf-8");
60714
+ writeFileSync13(tempPath, JSON.stringify(settings, null, 2), "utf-8");
59740
60715
  return tempPath;
59741
60716
  }
59742
60717
  async function runClaudeWithProxy(config3, proxyUrl) {