@vibeapi/api-helper 0.0.92 → 0.0.95
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/client-config.snapshot.json +548 -0
- package/dist/client-config.snapshot.json +548 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +1 -1
- package/dist/commands/refresh.d.ts +5 -0
- package/dist/commands/refresh.js +1 -0
- package/dist/lib/api-validator.d.ts +6 -15
- package/dist/lib/api-validator.js +1 -1
- package/dist/lib/client-config-sync.d.ts +26 -0
- package/dist/lib/client-config-sync.js +1 -0
- package/dist/lib/client-config.d.ts +100 -0
- package/dist/lib/client-config.js +1 -0
- package/dist/lib/command.js +1 -1
- package/dist/lib/gateway-models.d.ts +1 -1
- package/dist/lib/gateway-models.js +1 -1
- package/dist/lib/model-refresh.d.ts +1 -0
- package/dist/lib/model-refresh.js +1 -1
- package/dist/lib/model-registry.d.ts +7 -0
- package/dist/lib/model-registry.js +1 -1
- package/dist/lib/program.js +1 -1
- package/dist/lib/tools/antigravity.js +1 -1
- package/dist/locales/en_US.json +28 -3
- package/dist/locales/zh_CN.json +28 -3
- package/dist/models.json +1 -1
- package/models.json +1 -1
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as e}from"../utils/logger.js";import{configManager as
|
|
1
|
+
import{logger as e}from"../utils/logger.js";import{configManager as r}from"./config.js";import{i18n as t}from"./i18n.js";import{rememberPublishedAddresses as o}from"./gateway-addresses.js";import{eligibleLists as a}from"./client-config.js";import{refreshClientConfig as n}from"./client-config-sync.js";const s=e=>new Promise(r=>setTimeout(r,e));async function i(e,o,a){const n=`${r.getBaseUrl()}/v1/models`,s=new AbortController,i=setTimeout(()=>s.abort(),o);try{const r=await a(n,{method:"GET",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},signal:s.signal});if(401===r.status)return{valid:!1,error:"invalid_api_key",message:"API Key is invalid or expired"};if(r.ok){try{const e=await r.json();if(e&&"list"===e.object)return{valid:!0}}catch{return{valid:!0}}return{valid:!0}}return{valid:!1,error:"unknown_error",message:`HTTP ${r.status}: ${r.statusText}`}}catch(e){return e instanceof Error&&"AbortError"===e.name?{valid:!1,error:"network_error",message:"Request timeout"}:function(e){const r=e?.cause?.code;return"string"==typeof r&&l.has(r)}(e)?{valid:!1,error:"network_error",message:t.t("messages.certificate_intercepted",{url:n})}:{valid:!1,error:"network_error",message:e instanceof Error?e.message:"Network connection failed"}}finally{clearTimeout(i)}}const l=new Set(["DEPTH_ZERO_SELF_SIGNED_CERT","SELF_SIGNED_CERT_IN_CHAIN","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED","ERR_TLS_CERT_ALTNAME_INVALID"]);export async function fetchModels(t,o={}){const{timeoutMs:a=3e4,fetchFn:n=fetch}=o,s=`${r.getBaseUrl()}/v1/models`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const e=await n(s,{method:"GET",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},signal:i.signal});if(!e.ok)return{ok:!1,models:[],error:`HTTP ${e.status}`};const r=await e.json();return{ok:!0,models:(Array.isArray(r?.data)?r.data:[]).map(e=>"string"==typeof e?e:e?.id).filter(e=>"string"==typeof e&&e.trim().length>0).map(e=>e.trim())}}catch(r){return e.logError("fetchModels",r),{ok:!1,models:[],error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}function c(e){return e.filter(e=>!!e&&"object"==typeof e&&"string"==typeof e.name).map(e=>({name:e.name.trim(),..."string"==typeof e.labelOverride?{labelOverride:e.labelOverride}:{},..."boolean"==typeof e.supports1m?{supports1m:e.supports1m}:{}})).filter(e=>e.name.length>0)}export async function fetchGatewayStatus(t={}){const{timeoutMs:a=15e3,fetchFn:n=fetch}=t,s=`${r.getBaseUrl()}/api/status`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const e=await n(s,{method:"GET",signal:i.signal});if(!e.ok)return{ok:!1,claudeDesktopGroupModels:{},error:`HTTP ${e.status}`};const t=await e.json();o(t?.data,r.getBaseUrl());let a=t?.data?.claude_desktop_group_models;if("string"==typeof a)try{a=JSON.parse(a)}catch{a=void 0}const l={};if(a&&"object"==typeof a&&!Array.isArray(a))for(const[e,r]of Object.entries(a))Array.isArray(r)&&(l[e]=c(r));return{ok:!0,claudeDesktopGroupModels:l}}catch(r){return e.logError("fetchGatewayStatus",r),{ok:!1,claudeDesktopGroupModels:{},error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}export async function fetchKeyGroupInfo(t,o={}){const{timeoutMs:a=1e4,fetchFn:n=fetch}=o,s=`${r.getBaseUrl()}/api/platform/vibecode/key`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const e=await n(s,{method:"GET",headers:{Authorization:`Bearer ${t}`},signal:i.signal});if(!e.ok)return null;const r=await e.json(),o=r?.data;if(!o||"string"!=typeof o.group||!Array.isArray(o.claude_desktop_models))return null;const a=Array.isArray(o.groups)?o.groups.filter(e=>"string"==typeof e&&!!e):[];return{group:o.group,groups:a.length>0?a:[o.group],claudeDesktopModels:c(o.claude_desktop_models)}}catch(r){return e.logError("fetchKeyGroupInfo",r),null}finally{clearTimeout(l)}}export async function fetchClientModelConfig(e={}){const r=await n(e);return r.config?a(r.config.models):null}export async function validateApiKey(r,t={}){const{timeoutMs:o=3e4,retries:a=2,backoffMs:n=500,fetchFn:l=fetch,sleepFn:c=s}=t;let u={valid:!1,error:"network_error",message:"Network connection failed"};for(let t=0;t<=a;t++){const s=await i(r,o,l);if(s.valid||"invalid_api_key"===s.error)return s.valid||e.logError("validateApiKey",new Error(s.message||"invalid_api_key")),s;u=s,t<a&&await c(n*Math.pow(2,t))}return e.logError("validateApiKey",new Error(u.message||"network_error")),u}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ClientConfig, type ClientConfigSource } from './client-config.js';
|
|
2
|
+
/** 两次联网检查的最小间隔;内容没变时服务端回 304,几乎不耗流量。 */
|
|
3
|
+
export declare const CLIENT_CONFIG_TTL_MS: number;
|
|
4
|
+
export interface ClientConfigStatus {
|
|
5
|
+
config: ClientConfig | null;
|
|
6
|
+
source: ClientConfigSource | null;
|
|
7
|
+
revision?: string;
|
|
8
|
+
fetchedAt?: number;
|
|
9
|
+
/** Why the latest cloud payload was not used (refused, unreachable). */
|
|
10
|
+
problem?: string;
|
|
11
|
+
}
|
|
12
|
+
/** The built-in addresses are one site (same server, same config); any other gateway is its own. */
|
|
13
|
+
export declare function clientConfigSite(baseUrl?: string): string;
|
|
14
|
+
/** What the last refresh in this process ended with (for `doctor`). */
|
|
15
|
+
export declare function lastClientConfigStatus(): ClientConfigStatus | null;
|
|
16
|
+
/**
|
|
17
|
+
* Bring the cached config up to date with the gateway: at most every five minutes unless
|
|
18
|
+
* `force`, with `If-None-Match`. A payload that fails validation (see `parseClientConfig`) is
|
|
19
|
+
* ignored and the last accepted copy stays; never throws, never blocks longer than the timeout.
|
|
20
|
+
*/
|
|
21
|
+
export declare function refreshClientConfig(options?: {
|
|
22
|
+
force?: boolean;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
fetchFn?: typeof fetch;
|
|
25
|
+
now?: number;
|
|
26
|
+
}): Promise<ClientConfigStatus>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{logger as e}from"../utils/logger.js";import{bundledClientConfig as t,parseClientConfig as n,readCachedClientConfig as o,setClientConfigSiteResolver as i,writeCachedClientConfig as r}from"./client-config.js";import{configManager as c}from"./config.js";import{getBuiltinGatewayAddresses as f,reloadRegistry as s}from"./model-registry.js";export const CLIENT_CONFIG_TTL_MS=3e5;function l(e){try{return new URL(e).origin}catch{return e.replace(/\/+$/,"")}}export function clientConfigSite(e=c.getBaseUrl()){const t=l(e);return f().some(e=>l(e.url)===t)?"vibeapi":t}i(()=>clientConfigSite());let a=null;export function lastClientConfigStatus(){return a}function g(e){const n=o();if(n&&n.site===clientConfigSite())return{config:n.config,source:"cache",revision:n.config.revision,fetchedAt:n.fetchedAt,problem:e};const i=t();return i?{config:i,source:"bundled",revision:i.revision,problem:e}:{config:null,source:null,problem:e}}export async function refreshClientConfig(i={}){const{force:f=!1,timeoutMs:l=8e3,fetchFn:u=fetch,now:d=Date.now()}=i;if("1"===process.env.VIBECLI_DISABLE_CLIENT_CONFIG_FETCH)return a=g(),a;const h=clientConfigSite(),m=o(),p=m&&m.site===h?m:null;if(!f&&p&&d-p.fetchedAt<3e5)return a={config:p.config,source:"cache",revision:p.config.revision,fetchedAt:p.fetchedAt},a;const C=p?.config??("vibeapi"===h?t():null),v=new AbortController,b=setTimeout(()=>v.abort(),l);try{const t={};p?.etag&&(t["If-None-Match"]=p.etag);const o=await u(`${c.getBaseUrl()}/api/platform/vibecode/config`,{method:"GET",headers:t,signal:v.signal});if(304===o.status&&p)return r({...p,fetchedAt:d}),a={config:p.config,source:"cloud",revision:p.config.revision,fetchedAt:d},a;if(!o.ok)return a=g(`HTTP ${o.status}`),a;const i=await o.json(),{config:f,problem:l}=n(i?.data,C);if(!f)return e.warn(`Gateway client config refused: ${l}`),a=g(`refused: ${l}`),a;l&&e.warn(`Gateway client config: ${l}`);const m=o.headers.get("etag")??void 0;return r({site:h,fetchedAt:d,config:f,...m?{etag:m}:{}}),s(),a={config:f,source:"cloud",revision:f.revision,fetchedAt:d,...l?{problem:l}:{}},a}catch(t){return e.logError("refreshClientConfig",t),a=g(t instanceof Error?t.message:String(t)),a}finally{clearTimeout(b)}}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 网关下发的客户端配置(`/api/platform/vibecode/config`,VibeCode 应用与 vibecli 共用)的
|
|
3
|
+
* 解析、校验与本地保底。云端为准,三层保底:
|
|
4
|
+
* 1. 云端这一次的回包——整份校验通过才用(格式、条目、缩水比例、vibecli 一节的字段);
|
|
5
|
+
* 2. 上一份通过校验的缓存 `~/.vibecli/client-config.json`;
|
|
6
|
+
* 3. 随包快照 `client-config.snapshot.json`(发版时 `pnpm sync:client-config` 从生产拉取)。
|
|
7
|
+
* 校验不过整份丢弃,不部分采用;云端某个列表比上一份少一半以上(或被清空)时拒收,除非服务端在
|
|
8
|
+
* 管理员确认过的强制保存里标了 `vibecli.accept_shrink`。
|
|
9
|
+
*
|
|
10
|
+
* 这个模块不依赖 config.ts(config.ts → model-registry.ts → 这里),联网刷新在 client-config-sync.ts。
|
|
11
|
+
*/
|
|
12
|
+
export declare const CLIENT_CONFIG_SCHEMA = 1;
|
|
13
|
+
/** One model row of a list (`models.<list>[]`), normalized. */
|
|
14
|
+
export interface GatewayClientModel {
|
|
15
|
+
id: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
contextWindow?: number;
|
|
19
|
+
autoCompactTokens?: number;
|
|
20
|
+
/** Taken off by the gateway: not listed, and keeps the built-in entry of the same id out too. */
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
/** Per-tool switches (`claude-code`, `codex`, `grok`): false keeps it out, true puts it in. */
|
|
23
|
+
clients?: Record<string, boolean>;
|
|
24
|
+
/** Only vibecli at or above this version sees the row. */
|
|
25
|
+
minVibecliVersion?: string;
|
|
26
|
+
/** Staged rollout 0–100 by install id; absent = everyone. */
|
|
27
|
+
rolloutPercent?: number;
|
|
28
|
+
}
|
|
29
|
+
/** vibecli 自己那一节(与 models.json 字段一一对应,snake_case)。 */
|
|
30
|
+
export interface VibecliSection {
|
|
31
|
+
minVersion?: string;
|
|
32
|
+
defaultModels?: Record<string, string>;
|
|
33
|
+
retiredDefaultModels?: Record<string, string[]>;
|
|
34
|
+
toolDefaults?: Record<string, string>;
|
|
35
|
+
tierChains?: Record<string, string[]>;
|
|
36
|
+
retiredModels?: string[];
|
|
37
|
+
toolMinVersions?: Record<string, string>;
|
|
38
|
+
agyModels?: string[];
|
|
39
|
+
oneMillionFallback?: string[];
|
|
40
|
+
acceptShrink?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface ClientConfig {
|
|
43
|
+
schema: number;
|
|
44
|
+
revision: string;
|
|
45
|
+
models: Record<string, GatewayClientModel[]>;
|
|
46
|
+
vibecli?: VibecliSection;
|
|
47
|
+
}
|
|
48
|
+
export type ClientConfigSource = 'cloud' | 'cache' | 'bundled';
|
|
49
|
+
export interface CachedClientConfig {
|
|
50
|
+
/** `vibeapi` for the built-in addresses (one site), else the gateway origin. */
|
|
51
|
+
site: string;
|
|
52
|
+
etag?: string;
|
|
53
|
+
fetchedAt: number;
|
|
54
|
+
config: ClientConfig;
|
|
55
|
+
}
|
|
56
|
+
type Dict = Record<string, unknown>;
|
|
57
|
+
export interface ParseResult {
|
|
58
|
+
config: ClientConfig | null;
|
|
59
|
+
/** Why the payload was refused (or why the vibecli section was dropped, with `config` still set). */
|
|
60
|
+
problem?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Parse and validate a payload (`data` of the API response, or a cached / bundled copy in the
|
|
64
|
+
* same snake_case shape). `reference` is the last accepted config for the same site: a list that
|
|
65
|
+
* shrinks to under half (or to nothing) refuses the whole payload unless `vibecli.accept_shrink`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseClientConfig(raw: unknown, reference?: ClientConfig | null): ParseResult;
|
|
68
|
+
/** Back to the wire shape, for the cache file. */
|
|
69
|
+
export declare function serializeClientConfig(config: ClientConfig): Dict;
|
|
70
|
+
export declare const cachePath: () => string;
|
|
71
|
+
/** Last accepted cloud config, re-validated (a hand-edited or truncated cache counts as none). */
|
|
72
|
+
export declare function readCachedClientConfig(): CachedClientConfig | null;
|
|
73
|
+
export declare function writeCachedClientConfig(entry: CachedClientConfig): void;
|
|
74
|
+
/** The snapshot shipped with the package (production config at release time). */
|
|
75
|
+
export declare function bundledClientConfig(): ClientConfig | null;
|
|
76
|
+
export declare function setClientConfigSiteResolver(resolver: (() => string) | null): void;
|
|
77
|
+
/**
|
|
78
|
+
* The config in effect without touching the network: the cache when it came from the current
|
|
79
|
+
* gateway's site, else the bundled snapshot. A cache from another gateway (the user switched
|
|
80
|
+
* addresses) never applies, and without a resolver the cache is not trusted at all.
|
|
81
|
+
*/
|
|
82
|
+
export declare function currentClientConfig(): {
|
|
83
|
+
config: ClientConfig;
|
|
84
|
+
source: ClientConfigSource;
|
|
85
|
+
fetchedAt?: number;
|
|
86
|
+
} | null;
|
|
87
|
+
/** Tests pin the client version and install id. */
|
|
88
|
+
export declare function setClientIdentityForTests(version: string | null, installId: string | null): void;
|
|
89
|
+
export declare const clientVersion: () => string;
|
|
90
|
+
/** Stable random id per install, for rollout buckets only (never sent anywhere). */
|
|
91
|
+
export declare function installId(): string;
|
|
92
|
+
/** 0–99, stable per install and model. */
|
|
93
|
+
export declare function rolloutBucket(modelId: string): number;
|
|
94
|
+
/** Whether this install sees the row (version gate and rollout share); hidden rows never count. */
|
|
95
|
+
export declare function isEligible(model: GatewayClientModel): boolean;
|
|
96
|
+
/** Rows this install may not see turn into `hidden` (so the built-in entry of the same id stays out too). */
|
|
97
|
+
export declare function eligibleLists(models: Record<string, GatewayClientModel[]>): Record<string, GatewayClientModel[]>;
|
|
98
|
+
/** The vibecli section when this client is new enough for it. */
|
|
99
|
+
export declare function usableVibecliSection(config: ClientConfig | null | undefined): VibecliSection | undefined;
|
|
100
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as e,randomUUID as t}from"crypto";import{existsSync as n,mkdirSync as i,readFileSync as o,renameSync as r,writeFileSync as s}from"fs";import{homedir as l}from"os";import{dirname as c,join as f}from"path";import{fileURLToPath as a}from"url";export const CLIENT_CONFIG_SCHEMA=1;const u=new Set(["haiku","sonnet","opus","fable"]),d=/^[A-Za-z0-9._:@/\-[\]]{1,200}$/,m=/^[a-z][a-z0-9-]{0,31}$/,p=/^\d+(\.\d+){0,3}$/,h=e=>!!e&&"object"==typeof e&&!Array.isArray(e),b=e=>"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):void 0;function g(e){if(!h(e)||"string"!=typeof e.id||!e.id.trim())return null;const t={id:e.id.trim()};if(!0===e.hidden)return{...t,hidden:!0};"string"==typeof e.name&&e.name.trim()&&(t.name=e.name.trim()),"string"==typeof e.description&&e.description.trim()&&(t.description=e.description.trim());const n=b(e.context_window);n&&(t.contextWindow=n);const i=b(e.auto_compact_tokens);if(i&&(t.autoCompactTokens=i),h(e.clients)){const n={};for(const[t,i]of Object.entries(e.clients))m.test(t)&&"boolean"==typeof i&&(n[t]=i);Object.keys(n).length>0&&(t.clients=n)}return"string"==typeof e.min_vibecli_version&&p.test(e.min_vibecli_version)&&(t.minVibecliVersion=e.min_vibecli_version),"number"==typeof e.rollout_percent&&e.rollout_percent>=0&&e.rollout_percent<=100&&(t.rolloutPercent=e.rollout_percent),t}function _(e,t,n,i){if(void 0===e)return{};if(!h(e))throw new Error(`vibecli.${i} must be an object`);const o={};for(const[r,s]of Object.entries(e)){if(!t.test(r)||"string"!=typeof s||!n(s))throw new Error(`vibecli.${i}.${r} is invalid`);o[r]=s}return o}function v(e,t,{nonEmpty:n=!1}={}){if(void 0===e)return[];if(!Array.isArray(e)||e.some(e=>"string"!=typeof e||!d.test(e)))throw new Error(`vibecli.${t} must be a list of model ids`);if(n&&0===e.length)throw new Error(`vibecli.${t} must not be empty`);return[...e]}function y(e,t,n){if(void 0===e)return{};if(!h(e))throw new Error(`vibecli.${t} must be an object`);const i={};for(const[o,r]of Object.entries(e)){if(!u.has(o))throw new Error(`vibecli.${t}.${o} is not a tier slot`);i[o]=v(r,`${t}.${o}`,{nonEmpty:n})}return i}const C=e=>(e??[]).filter(e=>!e.hidden).length;export function parseClientConfig(e,t){if(!h(e))return{config:null,problem:"not an object"};if(1!==e.schema)return{config:null,problem:`unsupported schema ${String(e.schema)}`};if(!h(e.models))return{config:null,problem:"models is not an object"};const n={};for(const[t,i]of Object.entries(e.models)){if(!Array.isArray(i))return{config:null,problem:`models.${t} is not a list`};const e=i.map(g);if(e.some(e=>null===e))return{config:null,problem:`models.${t} has a row without an id`};n[t]=e}let i,o;try{i=function(e){if(null==e)return;if(!h(e))throw new Error("vibecli must be an object");const t={};if(void 0!==e.min_version){if("string"!=typeof e.min_version||e.min_version&&!p.test(e.min_version))throw new Error("vibecli.min_version is invalid");e.min_version&&(t.minVersion=e.min_version)}const n=_(e.default_models,/^(haiku|sonnet|opus|fable)$/,e=>d.test(e),"default_models");Object.keys(n).length&&(t.defaultModels=n);const i=y(e.retired_default_models,"retired_default_models",!1);Object.keys(i).length&&(t.retiredDefaultModels=i);const o=_(e.tool_defaults,m,e=>""===e||d.test(e),"tool_defaults");Object.keys(o).length&&(t.toolDefaults=o);const r=y(e.tier_chains,"tier_chains",!0);Object.keys(r).length&&(t.tierChains=r);const s=v(e.retired_models,"retired_models");s.length&&(t.retiredModels=s);const l=_(e.tool_min_versions,m,e=>""===e||p.test(e),"tool_min_versions");Object.keys(l).length&&(t.toolMinVersions=l);const c=v(e.agy_models,"agy_models");c.length&&(t.agyModels=c);const f=v(e.one_million_fallback,"one_million_fallback");return f.length&&(t.oneMillionFallback=f),!0===e.accept_shrink&&(t.acceptShrink=!0),t}(e.vibecli)}catch(e){o=`vibecli section dropped: ${e instanceof Error?e.message:String(e)}`}if(t&&(!h(e.vibecli)||!0!==e.vibecli.accept_shrink))for(const[e,i]of Object.entries(t.models)){const t=C(i),o=C(n[e]);if(t>0&&0===o||t>=4&&2*o<t)return{config:null,problem:`models.${e} shrank from ${t} to ${o}`}}return{config:{schema:1,revision:"string"==typeof e.revision?e.revision:"",models:n,...i?{vibecli:i}:{}},problem:o}}export function serializeClientConfig(e){const t=Object.fromEntries(Object.entries(e.models).map(([e,t])=>[e,t.map(e=>({id:e.id,...e.hidden?{hidden:!0}:{},...e.name?{name:e.name}:{},...e.description?{description:e.description}:{},...e.contextWindow?{context_window:e.contextWindow}:{},...e.autoCompactTokens?{auto_compact_tokens:e.autoCompactTokens}:{},...e.clients?{clients:e.clients}:{},...e.minVibecliVersion?{min_vibecli_version:e.minVibecliVersion}:{},...void 0!==e.rolloutPercent?{rollout_percent:e.rolloutPercent}:{}}))])),n=e.vibecli,i=n?{...n.minVersion?{min_version:n.minVersion}:{},...n.defaultModels?{default_models:n.defaultModels}:{},...n.retiredDefaultModels?{retired_default_models:n.retiredDefaultModels}:{},...n.toolDefaults?{tool_defaults:n.toolDefaults}:{},...n.tierChains?{tier_chains:n.tierChains}:{},...n.retiredModels?{retired_models:n.retiredModels}:{},...n.toolMinVersions?{tool_min_versions:n.toolMinVersions}:{},...n.agyModels?{agy_models:n.agyModels}:{},...n.oneMillionFallback?{one_million_fallback:n.oneMillionFallback}:{},...n.acceptShrink?{accept_shrink:!0}:{}}:void 0;return{schema:e.schema,revision:e.revision,models:t,...i?{vibecli:i}:{}}}function k(){const e=process.env.VIBECLI_CONFIG_DIR?.trim();if(e)return e;const t=process.env.VIBECLI_TEST_HOME?.trim();return f(t||l(),".vibecli")}export const cachePath=()=>f(k(),"client-config.json");function w(e,t){i(c(e),{recursive:!0});const n=`${e}.${process.pid}.tmp`;s(n,t,"utf-8"),r(n,e)}export function readCachedClientConfig(){try{if(!n(cachePath()))return null;const e=JSON.parse(o(cachePath(),"utf-8"));if("string"!=typeof e.site||"number"!=typeof e.fetchedAt)return null;const{config:t}=parseClientConfig(e.config);return t?{site:e.site,fetchedAt:e.fetchedAt,config:t,..."string"==typeof e.etag?{etag:e.etag}:{}}:null}catch{return null}}export function writeCachedClientConfig(e){w(cachePath(),JSON.stringify({site:e.site,etag:e.etag,fetchedAt:e.fetchedAt,config:serializeClientConfig(e.config)},null,2)+"\n")}let j;export function bundledClientConfig(){if("1"===process.env.VIBECLI_NO_BUNDLED_CLIENT_CONFIG)return null;if(void 0!==j)return j;j=null;const e=c(a(import.meta.url));for(const t of[f(e,"..","..","client-config.snapshot.json"),f(e,"..","client-config.snapshot.json")])try{if(!n(t))continue;j=parseClientConfig(JSON.parse(o(t,"utf-8"))).config;break}catch{}return j}let E=null;export function setClientConfigSiteResolver(e){E=e}export function currentClientConfig(){const e=readCachedClientConfig();let t=null;try{t=E?E():null}catch{t=null}if(e&&null!==t&&e.site===t)return{config:e.config,source:"cache",fetchedAt:e.fetchedAt};const n=bundledClientConfig();return n?{config:n,source:"bundled"}:null}let V=null,$=null;export function setClientIdentityForTests(e,t){V=e,$=t}export const clientVersion=()=>V??function(){try{const e=c(a(import.meta.url));for(const t of[f(e,"..","..","package.json"),f(e,"..","package.json")])if(n(t))return String(JSON.parse(o(t,"utf-8")).version??"0.0.0")}catch{}return"0.0.0"}();function O(e,t){const n=e.split(".").map(e=>parseInt(e,10)||0),i=t.split(".").map(e=>parseInt(e,10)||0);for(let e=0;e<Math.max(n.length,i.length);e++){const t=(n[e]??0)-(i[e]??0);if(t)return t}return 0}export function installId(){if($)return $;const e=f(k(),"install-id");try{if(n(e)){const t=o(e,"utf-8").trim();if(t)return t}const i=t();return w(e,i+"\n"),i}catch{return"unknown"}}export function rolloutBucket(t){return e("sha256").update(`${installId()}:${t}`).digest().readUInt32BE(0)%100}export function isEligible(e){return!(e.minVibecliVersion&&O(clientVersion(),e.minVibecliVersion)<0||void 0!==e.rolloutPercent&&rolloutBucket(e.id)>=e.rolloutPercent)}export function eligibleLists(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,t.map(e=>e.hidden||isEligible(e)?e:{id:e.id,hidden:!0})]))}export function usableVibecliSection(e){const t=e?.vibecli;if(t&&!(t.minVersion&&O(clientVersion(),t.minVersion)<0))return t}
|
package/dist/lib/command.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i18n as n,detectSystemLang as r}from"./i18n.js";import{configManager as o}from"./config.js";import{runModelRefresh as e}from"./model-refresh.js";import{
|
|
1
|
+
import{i18n as n,detectSystemLang as r}from"./i18n.js";import{configManager as o}from"./config.js";import{runModelRefresh as e}from"./model-refresh.js";import{refreshClientConfig as t}from"./client-config-sync.js";import{normalizeBaseUrl as s}from"./gateway-addresses.js";import i from"chalk";import{setRuntimeOptions as m,detectColorPreferenceFromEnv as a,isColorEnabled as c,isJsonMode as g}from"./runtime-options.js";import{cleanupAnthropicEnvVars as l,machineEnvVarsLeft as u}from"./env-cleanup.js";import{runStartupUpdate as f}from"./auto-update.js";import{buildProgram as d}from"./program.js";import{firstCommandWord as p,isHelpRequest as h,renderHelpTopic as v}from"./cli-help.js";import{reportCliError as w,usageError as j,VibeCliError as _}from"./errors.js";export{buildProgram}from"./program.js";const y=new Set(["setup","init","auth","enter","config"]);export class Command{program;configuring=!1;constructor(){const e=o.isLangChosen()?o.getLang():r();n.loadFromConfig(e),this.program=d()}cleanupLeakedEnvVars(){const r=l();if(0===r.length||g())return;const o=n.t("messages.env_vars_cleared",{vars:r.join(", ")});console.log(c()?i.yellow(o):o);const e=u();if(e.length>0){const r=n.t("messages.env_vars_machine_left",{vars:e.join(", ")});console.log(c()?i.yellow(r):r)}}preflightArgs(n){const r=r=>n.includes(r),e=!r("--no-color")&&a();if(m({nonInteractive:r("--non-interactive"),json:r("--json"),yes:r("--yes")||r("-y"),dryRun:r("--dry-run"),color:e}),e||(i.level=0),this.configuring=!1,h(n))return;let t;for(let r=0;r<n.length;r+=1){const o=n[r];"--base"===o&&n[r+1]?(t=n[r+1],r+=1):o.startsWith("--base=")&&(t=o.slice(7))}const c=p(n),g=void 0===c&&!["--version","-v"].some(r);this.configuring=g||void 0!==c&&y.has(c),t&&o.setBaseUrl(s(t)??t,this.configuring)}async execute(n){try{if(this.preflightArgs(n),"help"===n[0]&&n[1]){const r=v(n[1]);if(r)return void process.stdout.write(r)}if(this.rejectUnknownCommand(n),!h(n)){if(this.configuring&&this.cleanupLeakedEnvVars(),(await f(n)).handled)return;this.configuring&&await t({timeoutMs:5e3}),await e(n)}await this.program.parseAsync(n,{from:"user"})}catch(r){if("commander.helpDisplayed"===r?.code||"commander.version"===r?.code)return;w(this.normalizeCommanderError(r,n))}}rejectUnknownCommand(r){const o=p(r);if(!o||"help"===o)return;if(this.program.commands.some(n=>n.name()===o))return;const e=this.suggestCommand(o),t=e?n.t("cli.unknown_hint_suggestion",{command:e}):n.t("cli.unknown_hint");throw j(n.t("cli.error_unknown",{command:o}),t,"unknown_command")}suggestCommand(n){const r=(n,r)=>{const o=Array.from({length:r.length+1},(n,r)=>r);for(let e=1;e<=n.length;e+=1){let t=o[0];o[0]=e;for(let s=1;s<=r.length;s+=1){const i=o[s];o[s]=Math.min(o[s]+1,o[s-1]+1,t+(n[e-1]===r[s-1]?0:1)),t=i}}return o[r.length]};return this.program.commands.map(n=>n.name()).map(o=>({name:o,score:r(n,o)})).filter(({score:r})=>r<=Math.max(2,Math.floor(n.length/2))).sort((n,r)=>n.score-r.score)[0]?.name}normalizeCommanderError(r,o){if(r instanceof _)return r;const e=r?.code,t=r instanceof Error?r.message:String(r);if("commander.unknownOption"===e||"commander.missingArgument"===e||"commander.missingMandatoryOption"===e||"commander.invalidArgument"===e){const r=p(o)??"vibecli",s=/'([^']+)'/.exec(t)?.[1]??"",i="commander.unknownOption"===e?"cli.err_unknown_option":"commander.missingArgument"===e?"cli.err_missing_argument":"commander.missingMandatoryOption"===e?"cli.err_missing_option":null,m=i&&s?n.t(i,{name:s}):t.replace(/^error:\s*/,"");return j(m,n.t("cli.unknown_option_hint",{command:r}),e)}return r}getProgram(){return this.program}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type GatewayModelSpec } from './model-registry.js';
|
|
2
|
-
import type { GatewayClientModel } from './
|
|
2
|
+
import type { GatewayClientModel } from './client-config.js';
|
|
3
3
|
/**
|
|
4
4
|
* Gateway models (Claude, GPT, Gemini, domestic, Grok) vibecli adds to the coding tools'
|
|
5
5
|
* model menus, and the shared context rules: each model compacts at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getGatewayModelRules as e}from"./model-registry.js";export function autoCompactTokens(t,i){return i&&i>0?Math.min(i,t):Math.floor(t*e().autoCompactRatio)}export function gatewayModelSpecs(t,i){const o=e().models,n=o.filter(e=>function(e,t){return"codex"===e?!1!==t.codex:"grok"===e?"grok"===modelFamily(t.id):!t.id.startsWith("claude-")&&!1!==t.claudeCode}(t,e));if(!i)return n;const d=new Set(Object.values(i).flat().filter(e=>e.hidden).map(e=>e.id)),r=Object.fromEntries(Object.entries(i).map(([e,t])=>[e,t.filter(e=>!e.hidden)])),s=new Map(("claude-code"===t?o:n).map(e=>[e.id,e])),l=(r.gemini??[]).filter(e
|
|
1
|
+
import{getGatewayModelRules as e}from"./model-registry.js";export function autoCompactTokens(t,i){return i&&i>0?Math.min(i,t):Math.floor(t*e().autoCompactRatio)}export function gatewayModelSpecs(t,i){const o=e().models,n=o.filter(e=>function(e,t){return"codex"===e?!1!==t.codex:"grok"===e?"grok"===modelFamily(t.id):!t.id.startsWith("claude-")&&!1!==t.claudeCode}(t,e));if(!i)return n;const d=new Set(Object.values(i).flat().filter(e=>e.hidden).map(e=>e.id)),r=Object.fromEntries(Object.entries(i).map(([e,t])=>[e,t.filter(e=>!e.hidden)])),s=new Map;for(const e of Object.values(r).flat()){const i=e.clients?.[t];void 0===i||s.has(e.id)||s.set(e.id,i)}for(const[e,t]of s)t||d.add(e);const c=new Map(("claude-code"===t?o:n).map(e=>[e.id,e])),l=(r.gemini??[]).filter(e=>s.get(e.id)??!1!==o.find(t=>t.id===e.id)?.codex),a=("grok"===t?r.grok??[]:"codex"===t?[...r.codex??[],...l,...(r.claude??[]).filter(e=>e.id.startsWith("claude-")&&(s.get(e.id)??c.has(e.id)))]:function(e,t){return[...(e.codex??[]).filter(e=>"gpt"===modelFamily(e.id)),...e.gemini??[],...e.grok??[],...(e.claude??[]).filter(e=>!e.id.startsWith("claude-"))].filter(e=>e.clients?.["claude-code"]??t.get(e.id)?.claudeCode??!0)}(r,c)).filter(e=>!(e=>!1===s.get(e.id))(e));if(0===a.length)return n.filter(e=>!d.has(e.id));const u=new Set,f=[];for(const e of a){if(u.has(e.id))continue;u.add(e.id);const{clients:t,minVibecliVersion:i,rolloutPercent:o,...n}=e,d={...c.get(e.id),...n};void 0!==t?.codex&&(d.codex=t.codex),void 0!==t?.["claude-code"]&&(d.claudeCode=t["claude-code"]),f.push(d)}return function(e,t,i){const o=[...e];return t.forEach((e,n)=>{if(i.has(e.id)||o.some(t=>t.id===e.id))return;const d=modelFamily(e.id),r=new Set(t.slice(n+1).filter(e=>modelFamily(e.id)===d).map(e=>e.id));let s=o.findIndex(e=>r.has(e.id));if(s<0){s=o.length;for(let e=o.length-1;e>=0;e--)if(modelFamily(o[e].id)===d){s=e+1;break}}o.splice(s,0,e)}),o}(f,n,d)}const t={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function modelBlurb(e,t={}){const i=[];for(const o of(e??"").split("|")){const e=o.trim();e&&(/\d\s*万?\s*输出|output\D*\d|\d\D*output/i.test(e)||(/[\d百千]\s*万?\s*上下文|context\D*\d|\d\D*context/i.test(e)?t.millionContext&&!i.includes("百万上下文")&&i.unshift("百万上下文"):i.push(e)))}return t.millionContext&&!i.includes("百万上下文")&&i.unshift("百万上下文"),i.length>0?i.join(" | "):void 0}export function prettyModelName(e){const i=e.replace(/^([a-z]+)(\d)/i,"$1 $2").split(/[-_\s]+/).filter(Boolean),o=[];for(const e of i){const i=o[o.length-1];if(/^\d+$/.test(e)&&i&&/^\d+$/.test(i)&&e.length<=2&&!/^\d{8}$/.test(e)){o[o.length-1]=`${i}.${e}`;continue}const n=e.toLowerCase();o.push(t[n]??(/^[a-z]\d/i.test(e)?e.toUpperCase():e[0].toUpperCase()+e.slice(1)))}return o.join(" ")}export function vendorNames(e){return[...new Set(e.map(e=>prettyModelName(e).split(" ")[0]))]}export function modelFamily(e){const t=e.toLowerCase();return t.startsWith("claude-")?"claude":t.startsWith("gemini")?"gemini":t.startsWith("grok")?"grok":/^(gpt|o\d|codex)/.test(t)?"gpt":"other"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,mkdirSync as o,readFileSync as
|
|
1
|
+
import{existsSync as e,mkdirSync as o,readFileSync as r,writeFileSync as t}from"fs";import{dirname as n,join as s}from"path";import i from"chalk";import{configManager as l}from"./config.js";import{i18n as f}from"./i18n.js";import{resolveModelCatalog as d}from"./model-catalog.js";import{listAdapters as c}from"./tools/registry.js";import{UserActionNeeded as a}from"./tools/types.js";import{logger as u}from"../utils/logger.js";import{resolveUpdateCachePath as m}from"./auto-update.js";import{isHelpRequest as h}from"./cli-help.js";export const MODEL_REFRESH_INTERVAL_MS=36e5;const p=new Set(["setup","init","config","auth","enter","completion","update","lang","logs","refresh"]),g=["--json","--dry-run","--help","-h","--version","-v"],M=[];export function shouldSkipModelRefresh(e,o=process.env){if("1"===o.VIBECLI_DISABLE_MODEL_REFRESH)return!0;if(g.some(o=>e.includes(o))||h(e))return!0;const r=e.find(e=>!e.startsWith("-"));return void 0!==r&&p.has(r)}export async function refreshModelMenus(){const e=new Map,o=[];M.length=0;for(const r of c())if(r.refreshModelMenu&&r.listedModels)try{const t=l.getApiKeyForTool(r.name);if(!t||r.detectCurrentConfig().apiKey!==t)continue;const n=r.listedModels();if(null===n)continue;e.has(t)||e.set(t,await d(t));const s=e.get(t);if(!s)continue;r.refreshModelMenu({apiKey:t,baseUrl:l.getBaseUrl(),models:l.getModelsForTool(r.name),settings:l.getToolSettings(r.name),catalog:s});const i=r.listedModels()??[],f=i.filter(e=>!n.includes(e)),c=n.filter(e=>!i.includes(e));(f.length>0||c.length>0)&&o.push({tool:r.displayName,added:f,removed:c})}catch(e){u.logError(`modelRefresh(${r.name})`,e),e instanceof a&&M.push(e.message)}return o}export async function runModelRefresh(l,d={}){const c=d.env??process.env,a=d.now??Date.now(),h=function(e){return s(n(m(e)),"model-refresh.json")}(c);if(!d.force){if(shouldSkipModelRefresh(l,c))return[];if(a-function(e){try{const o=JSON.parse(r(e,"utf-8")).refreshed_at;return"number"==typeof o?o:0}catch{return 0}}(h)<36e5)return[]}let p=[];try{p=await refreshModelMenus(),e(n(h))||o(n(h),{recursive:!0}),t(h,JSON.stringify({refreshed_at:a})+"\n")}catch(e){u.logError("runModelRefresh",e)}const g=d.output??(e=>console.log(i.gray(e)));for(const e of M)g(e);for(const e of p){const o=[e.added.length>0?f.t("model_refresh.added",{models:e.added.join(", ")}):"",e.removed.length>0?f.t("model_refresh.removed",{models:e.removed.join(", ")}):""].filter(Boolean);g(f.t("model_refresh.changed",{tool:e.tool,changes:o.join(";")}))}return p}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type VibecliSection } from './client-config.js';
|
|
1
2
|
export interface Models {
|
|
2
3
|
haiku: string;
|
|
3
4
|
sonnet: string;
|
|
@@ -94,6 +95,12 @@ export interface GatewayAddress {
|
|
|
94
95
|
url: string;
|
|
95
96
|
label: string;
|
|
96
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* The gateway's `vibecli` section (cached or bundled, see client-config.ts) over `models.json`:
|
|
100
|
+
* per-slot / per-tool values replace the built-in ones, the tombstone lists (retired defaults,
|
|
101
|
+
* retired models) are unions, the agy menu and the 1M fallback list are replaced when given.
|
|
102
|
+
*/
|
|
103
|
+
export declare function overlayVibecliSection(base: ModelRegistryData, v: VibecliSection | undefined): ModelRegistryData;
|
|
97
104
|
export declare function getDefaultModels(): Models;
|
|
98
105
|
/** Earlier default for this slot, saved into a profile by the wizard's prefilled inputs. */
|
|
99
106
|
export declare function isRetiredDefaultModel(slot: string, model: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dirname as e,join as
|
|
1
|
+
import{dirname as e,join as o}from"path";import{fileURLToPath as t}from"url";import{existsSync as l,readFileSync as n}from"fs";import{currentClientConfig as r,usableVibecliSection as s}from"./client-config.js";const a=e(t(import.meta.url)),i=(e=[],o=[])=>[...new Set([...e,...o])];export function overlayVibecliSection(e,o){if(!o)return e;const t={...e.retiredDefaultModels??{}};for(const[e,l]of Object.entries(o.retiredDefaultModels??{}))t[e]=i(t[e],l);return{...e,defaultModels:{...e.defaultModels,...o.defaultModels??{}},retiredDefaultModels:t,toolDefaults:{...e.toolDefaults??{},...o.toolDefaults??{}},claudeCode:o.tierChains?{...e.claudeCode??{},tierChains:{...e.claudeCode?.tierChains??{},...o.tierChains}}:e.claudeCode,claudeDesktop:o.oneMillionFallback?{...e.claudeDesktop??{},oneMillionFallback:[...o.oneMillionFallback]}:e.claudeDesktop,gatewayModels:o.retiredModels?{...e.gatewayModels??{},retired:i(e.gatewayModels?.retired,o.retiredModels)}:e.gatewayModels,toolMinVersions:{...e.toolMinVersions??{},...o.toolMinVersions??{}},agy:o.agyModels?{...e.agy??{},gatewayModels:[...o.agyModels]}:e.agy}}let d=null;function u(){return d||(d=overlayVibecliSection(function(){const e=[o(a,"..","..","models.json"),o(a,"..","models.json"),o(a,"models.json")];for(const o of e)if(l(o))return JSON.parse(n(o,"utf-8"));throw new Error(`models.json not found, searched: ${e.join(", ")}`)}(),s(r()?.config))),d}export function getDefaultModels(){return{...u().defaultModels}}export function isRetiredDefaultModel(e,o){return u().retiredDefaultModels?.[e]?.includes(o)??!1}export function getDefaultToolModel(){return u().defaultToolModel?.trim()||"gpt-5.5"}export function getToolDefaultModel(e){const o=u().toolDefaults;return o&&Object.prototype.hasOwnProperty.call(o,e)?(o[e]??"").trim():getDefaultToolModel()}export function getPresets(){return[...u().presets]}export function resolvePreset(e){return e.models?{...e.models}:e.model?{haiku:e.model,sonnet:e.model,opus:e.model,reasoning:e.model}:getDefaultModels()}export function getClaudeCodeTierChains(){const e=u().claudeCode?.tierChains??{};return Object.fromEntries(Object.entries(e).map(([e,o])=>[e,[...o]]))}export function getClaudeDesktopRules(){const e=u().claudeDesktop??{};return{oneMillionFallback:[...e.oneMillionFallback??[]],oneMillionExclusions:(e.oneMillionExclusions??[]).map(e=>({...e,models:[...e.models]}))}}export function getGatewayModelRules(){const e=u().gatewayModels??{};return{autoCompactRatio:e.autoCompactRatio??.8,models:(e.models??[]).map(e=>({...e})),retired:[...e.retired??[]]}}export function getBuiltinGatewayAddresses(){return(u().gatewayAddresses??[]).map(e=>({...e}))}export function getCodexRules(){return{standardContextWindow:u().codex?.standardContextWindow??272e3}}export function getAgyRules(){return{gatewayModels:[...u().agy?.gatewayModels??[]]}}export function compareVersions(e,o){const t=e.split(".").map(e=>parseInt(e,10)||0),l=o.split(".").map(e=>parseInt(e,10)||0);for(let e=0;e<Math.max(t.length,l.length);e++){const o=(t[e]??0)-(l[e]??0);if(0!==o)return o}return 0}export function getToolMinVersion(e){return u().toolMinVersions?.[e]?.trim()||null}export function reloadRegistry(){d=null}
|
package/dist/lib/program.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Command as e,Option as o}from"commander";import{readFileSync as t}from"fs";import{join as i,dirname as s}from"path";import{fileURLToPath as a}from"url";import{i18n as n}from"./i18n.js";import{wizard as c}from"./wizard.js";import{SUPPORTED_TOOLS as l}from"./tool-manager.js";import{DEFAULT_BASE_URL as r}from"./config.js";import{attachCommandHelp as p,helpConfiguration as u}from"./cli-help.js";import{langCommand as m,authCommand as d,doctorCommand as b,configCommand as g,statusCommand as f}from"../commands/index.js";import{logsCommand as v}from"../commands/logs.js";import{completionCommand as x}from"../commands/completion.js";import{benchCommand as y}from"../commands/bench.js";import{updateCommand as h}from"../commands/update.js";import{upgradeCommand as k}from"../commands/upgrade.js";import{codexSessionsCommand as _}from"../commands/codex-sessions.js";import{setupCommand as w,DEDICATED_KEYS as j}from"../commands/setup.js";import{baseCommand as O}from"../commands/base.js";import{usageError as S}from"./errors.js";function z(e,o){return n.t(`help.${e}`,o)}function C(e,o){return{command:e,note:z(o)}}function G(e){const o=z(e);return o===`help.${e}`?"":o}function $(e,o=[]){return{when:G(`${e}.when`),prerequisites:G(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>C(e,o))}}function R(e){return e.helpCommand("help [command]",z("help_command"))}export function buildProgram(){const G=new e;G.name("vibecli").summary(z("root.summary")).description(z("root.description")).configureHelp(u()).allowExcessArguments(!0).optionsGroup(z("group.global_options")).helpOption("-h, --help",z("global.help")).version(function(){try{const e=s(a(import.meta.url));return JSON.parse(t(i(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",z("global.version")).option("--base <url>",z("global.base")).option("--non-interactive",z("global.non_interactive")).option("--json",z("global.json")).option("-y, --yes",z("global.yes")).option("--dry-run",z("global.dry_run")).option("--no-color",z("global.no_color")),G.configureOutput({writeErr:()=>{},outputError:()=>{}}),G.showSuggestionAfterError(),G.exitOverride(e=>{throw e}),G.commandsGroup(z("group.configure"));const E=G.command("setup").summary(z("setup.summary")).description(z("setup.description")).option("--key <key>",z("setup.opt.key"));for(const e of j){const t=new o(`--${e.option} <key>`,z(`setup.opt.${e.option}`));e.hidden&&t.hideHelp(),E.addOption(t)}E.option("--1m",z("setup.opt.one_m")).option("--no-1m",z("setup.opt.no_one_m")).option("--claude-official <on|off>",z("setup.opt.claude_official")).option("--desktop-registry <on|off>",z("setup.opt.desktop_registry")).option("--force",z("setup.opt.force")).option("--all",z("setup.opt.all")).action(async e=>{const o=Boolean(e.key||j.some(o=>e[o.option])),t=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,i="zh_CN"===n.getLocale()?"<你的 Key>":"<your key>";if(!o&&!t)throw S(n.t("setup.usage"),`vibecli setup --key ${i}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw S(n.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),"vibecli setup --claude-official on|off","invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw S(n.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),"vibecli setup --desktop-registry on|off","invalid_value");await w({key:e.key,...Object.fromEntries(j.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force})}),p(E,{...$("setup",[["vibecli init","setup.alt.init"],["vibecli config <tool>","setup.alt.config"],["vibecli auth <key>","setup.alt.auth"]]),sections:[{title:z("setup.autodetect_title"),rows:[["Claude",z("setup.autodetect.claude")],["GPT",z("setup.autodetect.gpt")],["Grok",z("setup.autodetect.grok")],["Gemini",z("setup.autodetect.gemini")]]}],examples:[C("vibecli setup --key sk-xxx","setup.ex.key"),C("vibecli setup --claudekey sk-a --codexkey sk-b --agykey sk-g","setup.ex.split"),C("vibecli setup --desktopkey sk-d --claude-official off","setup.ex.desktop"),C("vibecli setup --key sk-xxx --force","setup.ex.force"),C("vibecli setup --key sk-xxx --base https://www.vibeapi.si","setup.ex.base")]});const L=G.command("init").summary(z("init.summary")).description(z("init.description")).action(async()=>{await c.runFirstTimeSetup()});p(L,{...$("init",[["vibecli setup --key <key>","init.alt.setup"],["vibecli","init.alt.menu"]]),examples:[C("vibecli init","init.ex.run"),C("vibecli init --base https://www.vibeapi.si","init.ex.base"),C("vibecli","init.ex.menu")]});const N=G.command("auth").summary(z("auth.summary")).description(z("auth.description")).argument("[token]",z("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});R(N);const A=N.command("revoke").description(z("auth.revoke")).action(async()=>{await d(["revoke"])});p(A,{examples:[C("vibecli auth revoke","auth.ex.revoke_ask"),C("vibecli auth revoke --yes","auth.ex.revoke")]});const B=N.command("reload <tool>").description(z("auth.reload")).action(async e=>{await d(["reload",e])});p(B,{examples:[C("vibecli auth reload claude-code","auth.ex.reload"),C("vibecli auth reload claude-code --json","auth.ex.reload_json")]}),p(N,{...$("auth",[["vibecli setup --key <key>","auth.alt.setup"]]),examples:[C("vibecli auth","auth.ex.prompt"),C("vibecli auth sk-xxx --non-interactive","auth.ex.save"),C("vibecli auth revoke --yes","auth.ex.revoke"),C("vibecli auth reload claude-code","auth.ex.reload")]});const H=G.command("config").summary(z("config.summary")).description(z("config.description")).argument("[args...]",z("config.arg.args")).option("-f, --force",z("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(H,{...$("config",[["vibecli setup --key <key> --force","config.alt.setup"],["vibecli status","config.alt.status"]]),sections:[{title:z("config.subcommands_title"),rows:[["<tool>",z("config.sub.tool")],["<tool> --force",z("config.sub.tool_force")],["<tool> --non-interactive",z("config.sub.tool_non_interactive")],["<tool> restore",z("config.sub.tool_restore")],["<tool> backups",z("config.sub.tool_backups")],["<tool> clear-model",z("config.sub.tool_clear_model")],["tool-model list",z("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",z("config.sub.tool_model_set")],["tool-model clear <tool>",z("config.sub.tool_model_clear")],["profile list",z("config.sub.profile_list")],["profile create <name>",z("config.sub.profile_create")],["profile use <name>",z("config.sub.profile_use")],["profile delete <name>",z("config.sub.profile_delete")],["preset list",z("config.sub.preset_list")],["preset save <name>",z("config.sub.preset_save")],["preset use <name>",z("config.sub.preset_use")],["preset delete <name>",z("config.sub.preset_delete")],["backup list",z("config.sub.backup_list")],["backup create [label]",z("config.sub.backup_create")],["backup restore <name>",z("config.sub.backup_restore")]]},{title:z("config.tools_title"),rows:Object.values(l).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[C("vibecli config codex","config.ex.menu"),C("vibecli config claude-code --force","config.ex.force"),C("vibecli config tool-model set codex gpt-6-astra","config.ex.tool_model"),C("vibecli config profile create work","config.ex.profile"),C("vibecli config backup create before-upgrade","config.ex.backup")]});const K=G.command("base").summary(z("base.summary")).description(z("base.description")).argument("[target]",z("base.arg.target")).action(async e=>{await O(e)});p(K,{...$("base",[["vibecli doctor","base.alt.doctor"],["vibecli bench","base.alt.bench"]]),sections:[{title:z("base.targets_title"),rows:[[z("base.target.none_term"),z("base.target.none")],[z("base.target.index_term"),z("base.target.index")],[z("base.target.url_term"),z("base.target.url")],["auto",z("base.target.auto")],["default",z("base.target.default",{url:r})]]}],examples:[C("vibecli base","base.ex.list"),C("vibecli base auto","base.ex.auto"),C("vibecli base 2","base.ex.index"),C("vibecli base https://www.vibeapi.si","base.ex.url"),C("vibecli base default","base.ex.default")]}),G.commandsGroup(z("group.diagnose"));const M=G.command("status").summary(z("status.summary")).description(z("status.description")).action(async()=>{await f()});p(M,{...$("status",[["vibecli doctor","status.alt.doctor"]]),examples:[C("vibecli status","status.ex.show"),C("vibecli status --json","status.ex.json")]});const P=G.command("doctor").summary(z("doctor.summary")).description(z("doctor.description")).option("--deep",z("doctor.opt.deep")).action(async e=>{await b({deep:e.deep})});p(P,{...$("doctor",[["vibecli base auto","doctor.alt.base"],["vibecli logs tail","doctor.alt.logs"]]),examples:[C("vibecli doctor","doctor.ex.run"),C("vibecli doctor --deep","doctor.ex.deep")]});const T=G.command("bench").summary(z("bench.summary")).description(z("bench.description")).option("--samples <n>",z("bench.opt.samples"),"5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await y(o)});p(T,{...$("bench",[["vibecli base","bench.alt.base"]]),examples:[C("vibecli bench","bench.ex.run"),C("vibecli bench --samples 3","bench.ex.samples"),C("vibecli bench --json","bench.ex.json")]});const U=G.command("logs").summary(z("logs.summary")).description(z("logs.description")).argument("[action]",z("logs.arg.action")).argument("[file]",z("logs.arg.file")).action(async(e,o)=>{const t=[];e&&t.push(e),o&&t.push(o),await v(t)});p(U,{...$("logs",[["vibecli doctor","logs.alt.doctor"]]),sections:[{title:z("logs.actions_title"),rows:[["list",z("logs.action.list")],["tail [file]",z("logs.action.tail")],["path",z("logs.action.path")]]}],examples:[C("vibecli logs","logs.ex.list"),C("vibecli logs tail","logs.ex.tail"),C("vibecli logs path","logs.ex.path")]}),G.commandsGroup(z("group.maintain"));const q=G.command("upgrade").summary(z("upgrade.summary")).description(z("upgrade.description")).argument("[tools...]",z("upgrade.arg.tools")).action(async(e=[])=>{await k(e)});p(q,{...$("upgrade",[["vibecli update","upgrade.alt.update"]]),examples:[C("vibecli upgrade","upgrade.ex.all"),C("vibecli upgrade claude-code","upgrade.ex.one"),C("vibecli upgrade codex agy","upgrade.ex.many")]});const F=G.command("update").summary(z("update.summary")).description(z("update.description")).action(async()=>{await h()});p(F,{...$("update",[["vibecli upgrade","update.alt.upgrade"]]),examples:[C("vibecli update","update.ex.check"),C("vibecli update --json","update.ex.json")]});const J=G.command("codex").summary(z("codex.summary")).description(z("codex.description"));R(J);const D=J.command("sessions").summary(z("codex_sessions.summary")).description(z("codex_sessions.description")).option("--to <provider>",z("codex_sessions.opt.to")).option("--undo <dir>",z("codex_sessions.opt.undo")).action(async e=>{await _(e)});p(J,{...$("codex"),examples:[C("vibecli codex sessions","codex_sessions.ex.move"),C("vibecli codex sessions --undo <dir>","codex_sessions.ex.undo")]}),p(D,{...$("codex_sessions",[["vibecli codex sessions --undo <dir>","codex_sessions.alt.undo"]]),examples:[C("vibecli codex sessions","codex_sessions.ex.move"),C("vibecli codex sessions --to custom","codex_sessions.ex.to"),C("vibecli codex sessions --undo <dir>","codex_sessions.ex.undo")]});const I=G.command("lang").summary(z("lang.summary")).description(z("lang.description"));R(I);const Q=I.command("show").description(z("lang.show")).action(async()=>{await m(["show"])}),V=I.command("set <locale>").description(z("lang.set")).action(async e=>{await m(["set",e])}),W=[C("vibecli lang show","lang.ex.show"),C("vibecli lang set en_US","lang.ex.set_en"),C("vibecli lang set zh_CN","lang.ex.set_zh")];p(I,{...$("lang",[["vibecli enter lang","lang.alt.enter"]]),examples:W}),p(Q,{examples:[W[0],C("vibecli lang show --json","lang.ex.show_json")]}),p(V,{examples:W.slice(1)});const X=G.command("completion").summary(z("completion.summary")).description(z("completion.description")).argument("<shell>",z("completion.arg.shell")).action(async e=>{await x([e])});p(X,{...$("completion"),examples:[C("vibecli completion bash > ~/.vibecli-completion.bash","completion.ex.bash"),C("vibecli completion zsh > ~/.vibecli-completion.zsh","completion.ex.zsh"),C("vibecli completion fish > ~/.config/fish/completions/vibecli.fish","completion.ex.fish")]});const Y=G.command("enter").summary(z("enter.summary")).description(z("enter.description")).argument("[option]",z("enter.arg.option")).action(async e=>{if(e)switch(e){case"lang":case"language":await c.configLanguage();break;case"apikey":case"api-key":await c.configApiKey();break;case"models":await c.configModels();break;default:await g([e])}else await c.run()});p(Y,{...$("enter",[["vibecli","enter.alt.menu"],["vibecli config <tool>","enter.alt.config"]]),sections:[{title:z("enter.options_title"),rows:[[z("enter.option.none_term"),z("enter.option.none")],["lang",z("enter.option.lang")],["apikey",z("enter.option.apikey")],["models",z("enter.option.models")],["<tool>",z("enter.option.tool")]]}],examples:[C("vibecli enter","enter.ex.menu"),C("vibecli enter models","enter.ex.models"),C("vibecli enter codex","enter.ex.tool")]}),R(G),G.action(async()=>{await c.run()}),p(G,{examples:[C("vibecli","root.ex.menu"),C("vibecli setup --key sk-xxx","root.ex.setup"),C("vibecli doctor","root.ex.doctor"),C("vibecli base auto","root.ex.base"),C("vibecli config codex","root.ex.config")]});const Z=e=>{for(const o of e.commands)o.helpOption("-h, --help",z("global.help")),Z(o)};return Z(G),G}
|
|
1
|
+
import{Command as e,Option as o}from"commander";import{readFileSync as t}from"fs";import{join as i,dirname as s}from"path";import{fileURLToPath as a}from"url";import{i18n as n}from"./i18n.js";import{wizard as c}from"./wizard.js";import{SUPPORTED_TOOLS as r}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as u}from"./cli-help.js";import{langCommand as m,authCommand as d,doctorCommand as b,configCommand as g,statusCommand as f,refreshCommand as v}from"../commands/index.js";import{logsCommand as x}from"../commands/logs.js";import{completionCommand as h}from"../commands/completion.js";import{benchCommand as y}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{codexSessionsCommand as w}from"../commands/codex-sessions.js";import{setupCommand as j,DEDICATED_KEYS as O}from"../commands/setup.js";import{baseCommand as S}from"../commands/base.js";import{usageError as z}from"./errors.js";function C(e,o){return n.t(`help.${e}`,o)}function G(e,o){return{command:e,note:C(o)}}function $(e){const o=C(e);return o===`help.${e}`?"":o}function R(e,o=[]){return{when:$(`${e}.when`),prerequisites:$(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>G(e,o))}}function E(e){return e.helpCommand("help [command]",C("help_command"))}export function buildProgram(){const $=new e;$.name("vibecli").summary(C("root.summary")).description(C("root.description")).configureHelp(u()).allowExcessArguments(!0).optionsGroup(C("group.global_options")).helpOption("-h, --help",C("global.help")).version(function(){try{const e=s(a(import.meta.url));return JSON.parse(t(i(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",C("global.version")).option("--base <url>",C("global.base")).option("--non-interactive",C("global.non_interactive")).option("--json",C("global.json")).option("-y, --yes",C("global.yes")).option("--dry-run",C("global.dry_run")).option("--no-color",C("global.no_color")),$.configureOutput({writeErr:()=>{},outputError:()=>{}}),$.showSuggestionAfterError(),$.exitOverride(e=>{throw e}),$.commandsGroup(C("group.configure"));const L=$.command("setup").summary(C("setup.summary")).description(C("setup.description")).option("--key <key>",C("setup.opt.key"));for(const e of O){const t=new o(`--${e.option} <key>`,C(`setup.opt.${e.option}`));e.hidden&&t.hideHelp(),L.addOption(t)}L.option("--1m",C("setup.opt.one_m")).option("--no-1m",C("setup.opt.no_one_m")).option("--claude-official <on|off>",C("setup.opt.claude_official")).option("--desktop-registry <on|off>",C("setup.opt.desktop_registry")).option("--force",C("setup.opt.force")).option("--all",C("setup.opt.all")).action(async e=>{const o=Boolean(e.key||O.some(o=>e[o.option])),t=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,i="zh_CN"===n.getLocale()?"<你的 Key>":"<your key>";if(!o&&!t)throw z(n.t("setup.usage"),`vibecli setup --key ${i}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw z(n.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),"vibecli setup --claude-official on|off","invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw z(n.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),"vibecli setup --desktop-registry on|off","invalid_value");await j({key:e.key,...Object.fromEntries(O.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force})}),p(L,{...R("setup",[["vibecli init","setup.alt.init"],["vibecli config <tool>","setup.alt.config"],["vibecli auth <key>","setup.alt.auth"]]),sections:[{title:C("setup.autodetect_title"),rows:[["Claude",C("setup.autodetect.claude")],["GPT",C("setup.autodetect.gpt")],["Grok",C("setup.autodetect.grok")],["Gemini",C("setup.autodetect.gemini")]]}],examples:[G("vibecli setup --key sk-xxx","setup.ex.key"),G("vibecli setup --claudekey sk-a --codexkey sk-b --agykey sk-g","setup.ex.split"),G("vibecli setup --desktopkey sk-d --claude-official off","setup.ex.desktop"),G("vibecli setup --key sk-xxx --force","setup.ex.force"),G("vibecli setup --key sk-xxx --base https://www.vibeapi.si","setup.ex.base")]});const N=$.command("init").summary(C("init.summary")).description(C("init.description")).action(async()=>{await c.runFirstTimeSetup()});p(N,{...R("init",[["vibecli setup --key <key>","init.alt.setup"],["vibecli","init.alt.menu"]]),examples:[G("vibecli init","init.ex.run"),G("vibecli init --base https://www.vibeapi.si","init.ex.base"),G("vibecli","init.ex.menu")]});const A=$.command("auth").summary(C("auth.summary")).description(C("auth.description")).argument("[token]",C("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});E(A);const K=A.command("revoke").description(C("auth.revoke")).action(async()=>{await d(["revoke"])});p(K,{examples:[G("vibecli auth revoke","auth.ex.revoke_ask"),G("vibecli auth revoke --yes","auth.ex.revoke")]});const B=A.command("reload <tool>").description(C("auth.reload")).action(async e=>{await d(["reload",e])});p(B,{examples:[G("vibecli auth reload claude-code","auth.ex.reload"),G("vibecli auth reload claude-code --json","auth.ex.reload_json")]}),p(A,{...R("auth",[["vibecli setup --key <key>","auth.alt.setup"]]),examples:[G("vibecli auth","auth.ex.prompt"),G("vibecli auth sk-xxx --non-interactive","auth.ex.save"),G("vibecli auth revoke --yes","auth.ex.revoke"),G("vibecli auth reload claude-code","auth.ex.reload")]});const H=$.command("config").summary(C("config.summary")).description(C("config.description")).argument("[args...]",C("config.arg.args")).option("-f, --force",C("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(H,{...R("config",[["vibecli setup --key <key> --force","config.alt.setup"],["vibecli status","config.alt.status"]]),sections:[{title:C("config.subcommands_title"),rows:[["<tool>",C("config.sub.tool")],["<tool> --force",C("config.sub.tool_force")],["<tool> --non-interactive",C("config.sub.tool_non_interactive")],["<tool> restore",C("config.sub.tool_restore")],["<tool> backups",C("config.sub.tool_backups")],["<tool> clear-model",C("config.sub.tool_clear_model")],["tool-model list",C("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",C("config.sub.tool_model_set")],["tool-model clear <tool>",C("config.sub.tool_model_clear")],["profile list",C("config.sub.profile_list")],["profile create <name>",C("config.sub.profile_create")],["profile use <name>",C("config.sub.profile_use")],["profile delete <name>",C("config.sub.profile_delete")],["preset list",C("config.sub.preset_list")],["preset save <name>",C("config.sub.preset_save")],["preset use <name>",C("config.sub.preset_use")],["preset delete <name>",C("config.sub.preset_delete")],["backup list",C("config.sub.backup_list")],["backup create [label]",C("config.sub.backup_create")],["backup restore <name>",C("config.sub.backup_restore")]]},{title:C("config.tools_title"),rows:Object.values(r).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[G("vibecli config codex","config.ex.menu"),G("vibecli config claude-code --force","config.ex.force"),G("vibecli config tool-model set codex gpt-6-astra","config.ex.tool_model"),G("vibecli config profile create work","config.ex.profile"),G("vibecli config backup create before-upgrade","config.ex.backup")]});const M=$.command("base").summary(C("base.summary")).description(C("base.description")).argument("[target]",C("base.arg.target")).action(async e=>{await S(e)});p(M,{...R("base",[["vibecli doctor","base.alt.doctor"],["vibecli bench","base.alt.bench"]]),sections:[{title:C("base.targets_title"),rows:[[C("base.target.none_term"),C("base.target.none")],[C("base.target.index_term"),C("base.target.index")],[C("base.target.url_term"),C("base.target.url")],["auto",C("base.target.auto")],["default",C("base.target.default",{url:l})]]}],examples:[G("vibecli base","base.ex.list"),G("vibecli base auto","base.ex.auto"),G("vibecli base 2","base.ex.index"),G("vibecli base https://www.vibeapi.si","base.ex.url"),G("vibecli base default","base.ex.default")]}),$.commandsGroup(C("group.diagnose"));const P=$.command("status").summary(C("status.summary")).description(C("status.description")).action(async()=>{await f()});p(P,{...R("status",[["vibecli doctor","status.alt.doctor"]]),examples:[G("vibecli status","status.ex.show"),G("vibecli status --json","status.ex.json")]});const T=$.command("doctor").summary(C("doctor.summary")).description(C("doctor.description")).option("--deep",C("doctor.opt.deep")).action(async e=>{await b({deep:e.deep})});p(T,{...R("doctor",[["vibecli base auto","doctor.alt.base"],["vibecli logs tail","doctor.alt.logs"]]),examples:[G("vibecli doctor","doctor.ex.run"),G("vibecli doctor --deep","doctor.ex.deep")]});const U=$.command("bench").summary(C("bench.summary")).description(C("bench.description")).option("--samples <n>",C("bench.opt.samples"),"5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await y(o)});p(U,{...R("bench",[["vibecli base","bench.alt.base"]]),examples:[G("vibecli bench","bench.ex.run"),G("vibecli bench --samples 3","bench.ex.samples"),G("vibecli bench --json","bench.ex.json")]});const q=$.command("logs").summary(C("logs.summary")).description(C("logs.description")).argument("[action]",C("logs.arg.action")).argument("[file]",C("logs.arg.file")).action(async(e,o)=>{const t=[];e&&t.push(e),o&&t.push(o),await x(t)});p(q,{...R("logs",[["vibecli doctor","logs.alt.doctor"]]),sections:[{title:C("logs.actions_title"),rows:[["list",C("logs.action.list")],["tail [file]",C("logs.action.tail")],["path",C("logs.action.path")]]}],examples:[G("vibecli logs","logs.ex.list"),G("vibecli logs tail","logs.ex.tail"),G("vibecli logs path","logs.ex.path")]}),$.commandsGroup(C("group.maintain"));const F=$.command("upgrade").summary(C("upgrade.summary")).description(C("upgrade.description")).argument("[tools...]",C("upgrade.arg.tools")).action(async(e=[])=>{await _(e)});p(F,{...R("upgrade",[["vibecli update","upgrade.alt.update"]]),examples:[G("vibecli upgrade","upgrade.ex.all"),G("vibecli upgrade claude-code","upgrade.ex.one"),G("vibecli upgrade codex agy","upgrade.ex.many")]});const J=$.command("refresh").summary(C("refresh.summary")).description(C("refresh.description")).action(async()=>{await v()});p(J,{...R("refresh",[["vibecli setup --key <你的 Key>","refresh.alt.setup"]]),examples:[G("vibecli refresh","refresh.ex.run"),G("vibecli refresh --base https://hk.vibeapi.cn","refresh.ex.base")]});const D=$.command("update").summary(C("update.summary")).description(C("update.description")).action(async()=>{await k()});p(D,{...R("update",[["vibecli upgrade","update.alt.upgrade"]]),examples:[G("vibecli update","update.ex.check"),G("vibecli update --json","update.ex.json")]});const I=$.command("codex").summary(C("codex.summary")).description(C("codex.description"));E(I);const Q=I.command("sessions").summary(C("codex_sessions.summary")).description(C("codex_sessions.description")).option("--to <provider>",C("codex_sessions.opt.to")).option("--undo <dir>",C("codex_sessions.opt.undo")).action(async e=>{await w(e)});p(I,{...R("codex"),examples:[G("vibecli codex sessions","codex_sessions.ex.move"),G("vibecli codex sessions --undo <dir>","codex_sessions.ex.undo")]}),p(Q,{...R("codex_sessions",[["vibecli codex sessions --undo <dir>","codex_sessions.alt.undo"]]),examples:[G("vibecli codex sessions","codex_sessions.ex.move"),G("vibecli codex sessions --to custom","codex_sessions.ex.to"),G("vibecli codex sessions --undo <dir>","codex_sessions.ex.undo")]});const V=$.command("lang").summary(C("lang.summary")).description(C("lang.description"));E(V);const W=V.command("show").description(C("lang.show")).action(async()=>{await m(["show"])}),X=V.command("set <locale>").description(C("lang.set")).action(async e=>{await m(["set",e])}),Y=[G("vibecli lang show","lang.ex.show"),G("vibecli lang set en_US","lang.ex.set_en"),G("vibecli lang set zh_CN","lang.ex.set_zh")];p(V,{...R("lang",[["vibecli enter lang","lang.alt.enter"]]),examples:Y}),p(W,{examples:[Y[0],G("vibecli lang show --json","lang.ex.show_json")]}),p(X,{examples:Y.slice(1)});const Z=$.command("completion").summary(C("completion.summary")).description(C("completion.description")).argument("<shell>",C("completion.arg.shell")).action(async e=>{await h([e])});p(Z,{...R("completion"),examples:[G("vibecli completion bash > ~/.vibecli-completion.bash","completion.ex.bash"),G("vibecli completion zsh > ~/.vibecli-completion.zsh","completion.ex.zsh"),G("vibecli completion fish > ~/.config/fish/completions/vibecli.fish","completion.ex.fish")]});const ee=$.command("enter").summary(C("enter.summary")).description(C("enter.description")).argument("[option]",C("enter.arg.option")).action(async e=>{if(e)switch(e){case"lang":case"language":await c.configLanguage();break;case"apikey":case"api-key":await c.configApiKey();break;case"models":await c.configModels();break;default:await g([e])}else await c.run()});p(ee,{...R("enter",[["vibecli","enter.alt.menu"],["vibecli config <tool>","enter.alt.config"]]),sections:[{title:C("enter.options_title"),rows:[[C("enter.option.none_term"),C("enter.option.none")],["lang",C("enter.option.lang")],["apikey",C("enter.option.apikey")],["models",C("enter.option.models")],["<tool>",C("enter.option.tool")]]}],examples:[G("vibecli enter","enter.ex.menu"),G("vibecli enter models","enter.ex.models"),G("vibecli enter codex","enter.ex.tool")]}),E($),$.action(async()=>{await c.run()}),p($,{examples:[G("vibecli","root.ex.menu"),G("vibecli setup --key sk-xxx","root.ex.setup"),G("vibecli doctor","root.ex.doctor"),G("vibecli base auto","root.ex.base"),G("vibecli config codex","root.ex.config")]});const oe=e=>{for(const o of e.commands)o.helpOption("-h, --help",C("global.help")),oe(o)};return oe($),$}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{chmodSync as t,existsSync as e,readFileSync as r}from"fs";import{join as n}from"path";import{i18n as o}from"../i18n.js";import{prettyModelName as i}from"../gateway-models.js";import{getAgyRules as a}from"../model-registry.js";import{logger as l}from"../../utils/logger.js";import{readPersistentEnvFile as s,removePersistentEnv as c,writePersistentEnv as u}from"../persistent-env.js";import{backupBeforeWrite as p,atomicWriteFile as d}from"./backup.js";import{mirrorInstallCommand as g}from"./tool-installs.js";import{toolHome as m}from"./types.js";const y="agy",f="AGY_LLM_GATEWAY_MODELS",v=["GEMINI_API_KEY","GOOGLE_GEMINI_BASE_URL","AGY_LLM_GATEWAY_URL","AGY_LLM_GATEWAY_API_KEY"],A="gemini",_=()=>n(m(),".gemini","antigravity-cli"),h=()=>n(_(),"settings.json"),E=()=>n(_(),"vibeapi.env"),j=()=>n(m(),".antigravity","settings.json"),b="https://cnb.cool/vibeapi/agy/-/releases/latest/download",w={command:"agy",native:{binDir:"win32"===process.platform?["AppData","Local","agy","bin"]:[".local","bin"],updateArgs:["update"],dataDirs:[]},mirrorScript:{sh:`${b}/install.sh`,ps1:`${b}/install.ps1`}};function I(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function K(t,n){if(!e(t))return{};const o=r(t,"utf-8");if(!o.trim())return{};try{const t=JSON.parse(o);if(!I(t))throw new Error(`${n} root must be an object`);return t}catch(t){throw new Error(`Existing ${n} cannot be parsed, back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}const P=()=>K(h(),"~/.gemini/antigravity-cli/settings.json"),G=()=>K(j(),"~/.antigravity/settings.json");function L(e,r,n){p(e),d(e,JSON.stringify(r,null,2)+"\n",n),void 0!==n&&t(e,n)}function M(t){return(t||"").replace(/\/+$/,"").replace(/\/v1(beta)?$/,"")}function C(t){const e=a().gatewayModels,r=t?e.filter(e=>t.models.includes(e)):[];return r.length>0?r:e}const N=t=>i(t.replace(/-preview$/,""));function S(t){const e=t.gateway;return I(e)&&!0===e.enabled&&"string"==typeof e.apiKey&&e.apiKey.trim()&&"string"==typeof e.url?{url:e.url,apiKey:e.apiKey}:null}function Y(t){const e=t.models;return I(e)&&Array.isArray(e.list)?e.list.map(t=>I(t)&&"string"==typeof t.modelId?t.modelId:"").filter(Boolean):[]}function $(){try{if(P().modelProvider!==A)return null}catch{return null}const t=s(E()),e=t.GEMINI_API_KEY;return e&&e.trim()?{apiKey:e,url:t.GOOGLE_GEMINI_BASE_URL??""}:null}function k(t,e,r){const n=P(),o=G();o.gateway={...I(o.gateway)?o.gateway:{},enabled:!0,url:e,apiKey:t,wireProtocol:"genai"},o.models={...I(o.models)?o.models:{},defaultModelId:r[0],list:r.map(t=>({modelId:t,displayName:N(t),supportsThinking:!0}))},L(j(),o,384),v.some(t=>void 0!==s(E())[t])&&c(y,E(),v);const i=u(y,E(),{[f]:r.join(",")}).rcFiles;for(const t of v)delete process.env[t];return n.modelProvider===A&&(delete n.modelProvider,L(h(),n)),i}let O=null,x=null;export const antigravityAdapter={name:"agy",displayName:"Antigravity CLI",command:"agy",installCommand:g(w),installSpec:w,configPath:j(),wantsModelCatalog:!0,loadPrivateConfig(t){P(),G();const e=C(t.catalog);O=k(t.apiKey,M(t.baseUrl),e),x=e},unloadPrivateConfig(){try{const t=G();S(t)&&(delete t.gateway,delete t.models,L(j(),t,384))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}try{const t=P();t.modelProvider===A&&(delete t.modelProvider,L(h(),t))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}c(y,E(),[f,...v])},detectCurrentConfig(){try{const t=S(G());if(t)return{apiKey:t.apiKey}}catch{return{apiKey:null}}return{apiKey:$()?.apiKey??null}},listedModels(){try{const t=G();if(S(t))return Y(t)}catch{return null}return $()?[]:null},refreshModelMenu(t){const e=G(),r=S(e)??$();if(!r)return;const n=C(t.catalog),o=r.url||M(t.baseUrl);null!==S(e)&&Y(e).join(",")===n.join(",")&&s(E())[f]===n.join(",")&&null===$()||k(r.apiKey,o,n)},getConfig(){try{return G()}catch(t){return l.logError("antigravityAdapter.getConfig",t),null}},applyNotes(){const t=[];if(x&&x.length>0){const e=x.map(N);t.push({kind:"summary",text:o.t("tools.agy.menu_written",{count:String(e.length),list:e.join(o.t("tools.grok.list_separator")),default:e[0]})})}return null===O||t.push({kind:"action",text:o.t("tools.agy.effort_after_reopen")}),t},backupPaths:()=>[j(),h(),E()],forceResetPaths:()=>[E()]};
|
package/dist/locales/en_US.json
CHANGED
|
@@ -208,7 +208,10 @@
|
|
|
208
208
|
"check_other_addresses": "Testing other gateway addresses",
|
|
209
209
|
"other_addresses": "Other gateway addresses",
|
|
210
210
|
"other_addresses_found": "These addresses work: {{urls}}. Run vibecli base auto to move every tool to one of them",
|
|
211
|
-
"other_addresses_none": "None of the other gateway addresses can be reached either; check your network or proxy"
|
|
211
|
+
"other_addresses_none": "None of the other gateway addresses can be reached either; check your network or proxy",
|
|
212
|
+
"check_client_config": "Checking the gateway model config...",
|
|
213
|
+
"client_config": "Gateway model config",
|
|
214
|
+
"client_config_revision": "revision {{revision}}"
|
|
212
215
|
},
|
|
213
216
|
"preset": {
|
|
214
217
|
"claude_mix": "Claude Mix",
|
|
@@ -367,8 +370,7 @@
|
|
|
367
370
|
"version_outdated": "version {{current}} is too old (needs {{min}} or later); upgrade with {{upgrade}}",
|
|
368
371
|
"agy": {
|
|
369
372
|
"menu_written": "{{count}} models in the menu ({{list}}), default {{default}}",
|
|
370
|
-
"
|
|
371
|
-
"reopen_terminal_windows": "Key and address were saved as user environment variables; reopen the terminal before running agy"
|
|
373
|
+
"effort_after_reopen": "agy works right away; in a new terminal the model menu also offers thinking levels (low / medium / high)"
|
|
372
374
|
},
|
|
373
375
|
"grok": {
|
|
374
376
|
"menu_written": "{{count}} models in the menu ({{list}}), default {{default}}",
|
|
@@ -787,6 +789,18 @@
|
|
|
787
789
|
"update": "Update VibeCLI itself"
|
|
788
790
|
}
|
|
789
791
|
},
|
|
792
|
+
"refresh": {
|
|
793
|
+
"summary": "Update the tools' model menus now",
|
|
794
|
+
"description": "Rewrites each tool's model menu from the gateway's current model config and the models your key can use now, without waiting for the hourly sync.",
|
|
795
|
+
"when": "After your key moved to another group, or the gateway added or removed models.",
|
|
796
|
+
"alt": {
|
|
797
|
+
"setup": "To change the key or configure tools again"
|
|
798
|
+
},
|
|
799
|
+
"ex": {
|
|
800
|
+
"run": "Update the model menus now",
|
|
801
|
+
"base": "Use another gateway address for this run only"
|
|
802
|
+
}
|
|
803
|
+
},
|
|
790
804
|
"update": {
|
|
791
805
|
"summary": "Check for a newer VibeCLI",
|
|
792
806
|
"description": "Checks CNB, npmjs, npmmirror and the Yarn registry in turn and prints the install command when a newer version exists.\nA global install also checks by itself at startup (every 6 hours).",
|
|
@@ -909,5 +923,16 @@
|
|
|
909
923
|
"title": "Environment variables",
|
|
910
924
|
"body": "VibeCLI reads these environment variables:\n VIBECLI_DISABLE_AUTO_UPDATE=1 disable the startup update check\n VIBECLI_DISABLE_MODEL_REFRESH=1 disable the startup model refresh\n VIBECLI_CONFIG_DIR=<directory> set the VibeCLI config directory\n VIBECLI_SKIP_AUTO_UPDATE=1 skip the update check for this run\n NO_COLOR=1 disable colors\n FORCE_COLOR=0 disable colors (FORCE_COLOR=false also works)"
|
|
911
925
|
}
|
|
926
|
+
},
|
|
927
|
+
"refresh": {
|
|
928
|
+
"config": "Model config: {{source}}, revision {{revision}}",
|
|
929
|
+
"problem": "({{problem}})",
|
|
930
|
+
"up_to_date": "All model menus are up to date",
|
|
931
|
+
"source": {
|
|
932
|
+
"cloud": "gateway",
|
|
933
|
+
"cache": "local cache",
|
|
934
|
+
"bundled": "bundled snapshot",
|
|
935
|
+
"none": "none (built-in list)"
|
|
936
|
+
}
|
|
912
937
|
}
|
|
913
938
|
}
|
package/dist/locales/zh_CN.json
CHANGED
|
@@ -208,7 +208,10 @@
|
|
|
208
208
|
"check_other_addresses": "测试其他接入地址",
|
|
209
209
|
"other_addresses": "其他接入地址",
|
|
210
210
|
"other_addresses_found": "这些地址能用:{{urls}}。运行 vibecli base auto,所有工具会一起换过去",
|
|
211
|
-
"other_addresses_none": "其他接入地址也都连不上,请检查网络或代理"
|
|
211
|
+
"other_addresses_none": "其他接入地址也都连不上,请检查网络或代理",
|
|
212
|
+
"check_client_config": "正在检查网关模型配置...",
|
|
213
|
+
"client_config": "网关模型配置",
|
|
214
|
+
"client_config_revision": "修订 {{revision}}"
|
|
212
215
|
},
|
|
213
216
|
"preset": {
|
|
214
217
|
"claude_mix": "Claude 混合",
|
|
@@ -367,8 +370,7 @@
|
|
|
367
370
|
"version_outdated": "版本 {{current}} 过旧,需要 {{min}} 及以上,运行 {{upgrade}} 升级",
|
|
368
371
|
"agy": {
|
|
369
372
|
"menu_written": "模型菜单 {{count}} 个({{list}}),默认 {{default}}",
|
|
370
|
-
"
|
|
371
|
-
"reopen_terminal_windows": "Key 与地址已写入用户环境变量,重新打开终端再运行 agy"
|
|
373
|
+
"effort_after_reopen": "现在就能运行 agy;新开的终端里模型菜单还会带思考档位(低 / 中 / 高)"
|
|
372
374
|
},
|
|
373
375
|
"grok": {
|
|
374
376
|
"menu_written": "模型菜单 {{count}} 个({{list}}),默认 {{default}}",
|
|
@@ -787,6 +789,18 @@
|
|
|
787
789
|
"update": "升级 VibeCLI 自己"
|
|
788
790
|
}
|
|
789
791
|
},
|
|
792
|
+
"refresh": {
|
|
793
|
+
"summary": "马上更新各工具的模型菜单",
|
|
794
|
+
"description": "按网关当前的模型配置和 Key 现在能用的模型,重写各工具的模型菜单,不等每小时一次的自动同步。",
|
|
795
|
+
"when": "Key 换了分组、能用的模型变了,或网关刚上新、下架模型时。",
|
|
796
|
+
"alt": {
|
|
797
|
+
"setup": "要换 Key 或重新配置工具"
|
|
798
|
+
},
|
|
799
|
+
"ex": {
|
|
800
|
+
"run": "马上更新模型菜单",
|
|
801
|
+
"base": "按另一个接入地址的配置更新(只对这一次生效)"
|
|
802
|
+
}
|
|
803
|
+
},
|
|
790
804
|
"update": {
|
|
791
805
|
"summary": "检查 VibeCLI 有没有新版本",
|
|
792
806
|
"description": "依次查 CNB、npmjs、npmmirror、Yarn 源,有新版时给出安装命令。\n全局安装的 VibeCLI 启动时也会自动检查(6 小时一次)。",
|
|
@@ -909,5 +923,16 @@
|
|
|
909
923
|
"title": "环境变量",
|
|
910
924
|
"body": "VibeCLI 会读取这些环境变量:\n VIBECLI_DISABLE_AUTO_UPDATE=1 禁用启动时自动更新检查\n VIBECLI_DISABLE_MODEL_REFRESH=1 禁用启动时模型菜单刷新\n VIBECLI_CONFIG_DIR=<目录> 指定 VibeCLI 配置目录\n VIBECLI_SKIP_AUTO_UPDATE=1 跳过本次自动更新检查\n NO_COLOR=1 禁用颜色\n FORCE_COLOR=0 禁用颜色(FORCE_COLOR=false 同样有效)"
|
|
911
925
|
}
|
|
926
|
+
},
|
|
927
|
+
"refresh": {
|
|
928
|
+
"config": "模型配置:{{source}},修订 {{revision}}",
|
|
929
|
+
"problem": "({{problem}})",
|
|
930
|
+
"up_to_date": "各工具的模型菜单已是最新",
|
|
931
|
+
"source": {
|
|
932
|
+
"cloud": "网关",
|
|
933
|
+
"cache": "本地缓存",
|
|
934
|
+
"bundled": "随包快照",
|
|
935
|
+
"none": "无(用内置清单)"
|
|
936
|
+
}
|
|
912
937
|
}
|
|
913
938
|
}
|
package/dist/models.json
CHANGED
package/models.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeapi/api-helper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.95",
|
|
4
4
|
"description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode, Grok Build) with one unified config",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"models.json",
|
|
19
|
+
"client-config.snapshot.json",
|
|
19
20
|
"settings-template.json",
|
|
20
21
|
"codex-base-instructions.md",
|
|
21
22
|
"THIRD_PARTY_NOTICES.md",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"test:coverage": "vitest run --coverage",
|
|
90
91
|
"typecheck": "tsc --noEmit",
|
|
91
92
|
"gen:docs": "tsx scripts/gen-command-docs.mjs",
|
|
93
|
+
"sync:client-config": "node scripts/sync-client-config.mjs",
|
|
92
94
|
"lint": "eslint .",
|
|
93
95
|
"lint:fix": "eslint . --fix",
|
|
94
96
|
"format": "prettier --write .",
|