@vibeapi/api-helper 0.0.148 → 0.0.149

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.
@@ -0,0 +1,157 @@
1
+ {
2
+ "schema": 1,
3
+ "about": "Components VibeCLI installs and upgrades (vibecli list / install / upgrade). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
+ "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
5
+ "components": [
6
+ {
7
+ "id": "node",
8
+ "name": "Node.js",
9
+ "category": "runtime",
10
+ "aliases": ["nodejs"],
11
+ "platforms": ["darwin", "linux", "win32"],
12
+ "detect": { "command": "node", "pattern": "v(\\d+\\.\\d+\\.\\d+)" },
13
+ "latest": { "type": "node-lts", "url": "https://registry.npmmirror.com/-/binary/node/index.json" },
14
+ "sources": {
15
+ "all": "fnm({devtools})+ Node 镜像 https://npmmirror.com/mirrors/node"
16
+ },
17
+ "verify": { "checksum": "fnm:SHA256SUMS;Node:fnm 下载时核对官方 SHASUMS256.txt", "signature": "—" },
18
+ "install": { "type": "script", "script": "node", "forceEnv": { "NODE_INSTALL_FORCE": "1" } },
19
+ "upgrade": { "managedBy": "fnm", "migrateGlobalPackages": true },
20
+ "check": ["node", "--version"],
21
+ "requires": []
22
+ },
23
+ {
24
+ "id": "git",
25
+ "name": "Git",
26
+ "category": "runtime",
27
+ "platforms": ["darwin", "linux", "win32"],
28
+ "detect": { "command": "git", "pattern": "git version (\\d+\\.\\d+\\.\\d+)" },
29
+ "latest": { "type": "devtools", "key": "git", "platforms": ["win32"] },
30
+ "sources": {
31
+ "darwin": "苹果命令行工具(xcode-select)",
32
+ "linux": "系统包管理器(apt、dnf、yum、zypper、pacman、apk)",
33
+ "win32": "Git for Windows({devtools})"
34
+ },
35
+ "verify": {
36
+ "checksum": "Windows:SHA256SUMS(取自 GitHub 公布的 digest)",
37
+ "signature": "macOS / Linux:系统包管理器自己的签名"
38
+ },
39
+ "install": { "type": "script", "script": "git", "forceEnv": { "GIT_INSTALL_FORCE": "1" } },
40
+ "upgrade": { "managedBy": "git-for-windows-user" },
41
+ "check": ["git", "--version"],
42
+ "requires": []
43
+ },
44
+ {
45
+ "id": "uv",
46
+ "name": "uv",
47
+ "category": "runtime",
48
+ "aliases": ["python-uv"],
49
+ "platforms": ["darwin", "linux", "win32"],
50
+ "detect": { "command": "uv", "pattern": "uv (\\d+\\.\\d+\\.\\d+)" },
51
+ "latest": { "type": "devtools", "key": "uv" },
52
+ "sources": {
53
+ "all": "uv 官方程序({devtools});Python 从 npmmirror 的 python-build-standalone 镜像、包从阿里云 PyPI 镜像"
54
+ },
55
+ "verify": { "checksum": "SHA256SUMS", "signature": "—" },
56
+ "install": { "type": "script", "script": "uv", "forceEnv": { "UV_INSTALL_FORCE": "1" } },
57
+ "upgrade": { "managedBy": "uv-standalone" },
58
+ "check": ["uv", "--version"],
59
+ "requires": []
60
+ },
61
+ {
62
+ "id": "claude-code",
63
+ "name": "Claude Code",
64
+ "category": "cli",
65
+ "aliases": ["claude"],
66
+ "platforms": ["darwin", "linux", "win32"],
67
+ "adapter": "claude-code",
68
+ "latest": { "type": "npm", "package": "@anthropic-ai/claude-code" },
69
+ "sources": {
70
+ "all": "npmmirror 的 @anthropic-ai/claude-code-<平台>(与 downloads.claude.ai 同一文件),按官方原生布局安装({scripts}/claude-code.sh / .ps1)"
71
+ },
72
+ "verify": { "checksum": "npm sha512;连得上时再核对 Anthropic 发布清单的 sha256", "signature": "—" },
73
+ "install": { "type": "adapter" },
74
+ "check": ["claude", "--version"],
75
+ "requires": []
76
+ },
77
+ {
78
+ "id": "codex",
79
+ "name": "Codex",
80
+ "category": "cli",
81
+ "platforms": ["darwin", "linux", "win32"],
82
+ "adapter": "codex",
83
+ "latest": { "type": "npm", "package": "@openai/codex" },
84
+ "sources": {
85
+ "all": "npmmirror 的 @openai/codex(vendor 目录与官方 codex-package 逐文件相同),按官方原生布局安装({scripts}/codex.sh / .ps1)"
86
+ },
87
+ "verify": { "checksum": "npm sha512", "signature": "—" },
88
+ "install": { "type": "adapter" },
89
+ "check": ["codex", "--version"],
90
+ "requires": []
91
+ },
92
+ {
93
+ "id": "grok",
94
+ "name": "Grok Build",
95
+ "category": "cli",
96
+ "platforms": ["darwin", "linux", "win32"],
97
+ "adapter": "grok",
98
+ "latest": { "type": "npm", "package": "@xai-official/grok", "staleTag": true },
99
+ "sources": { "all": "npmmirror 的 @xai-official/grok-<平台>({scripts}/grok.sh / .ps1)" },
100
+ "verify": { "checksum": "npm sha512", "signature": "—" },
101
+ "install": { "type": "adapter" },
102
+ "check": ["grok", "--version"],
103
+ "requires": []
104
+ },
105
+ {
106
+ "id": "agy",
107
+ "name": "Antigravity CLI",
108
+ "category": "cli",
109
+ "aliases": ["antigravity"],
110
+ "platforms": ["darwin", "linux", "win32"],
111
+ "adapter": "agy",
112
+ "latest": { "type": "version-file", "url": "{agy}/version.txt" },
113
+ "sources": { "all": "高速下载站 {agy}(每小时同步官方)" },
114
+ "verify": { "checksum": "官方清单的 sha512", "signature": "—" },
115
+ "install": { "type": "adapter" },
116
+ "check": ["agy", "--version"],
117
+ "requires": []
118
+ },
119
+ {
120
+ "id": "claude-desktop",
121
+ "name": "Claude Desktop",
122
+ "category": "app",
123
+ "platforms": ["darwin", "win32"],
124
+ "app": "claude-desktop",
125
+ "latest": { "type": "app" },
126
+ "sources": {
127
+ "darwin": "高速下载站 lib/claude-desktop(官方 dmg)",
128
+ "win32": "高速下载站 lib/claude-desktop(官方 MSIX)"
129
+ },
130
+ "verify": {
131
+ "checksum": "SHA256SUMS",
132
+ "signature": "macOS:Team ID Q6L2SF6YDW + 公证;Windows:Authenticode O=Anthropic, PBC"
133
+ },
134
+ "install": { "type": "app" },
135
+ "requires": []
136
+ },
137
+ {
138
+ "id": "chatgpt",
139
+ "name": "ChatGPT",
140
+ "category": "app",
141
+ "aliases": ["chatgpt-desktop", "codex-desktop", "codex-app"],
142
+ "platforms": ["darwin", "win32"],
143
+ "app": "chatgpt",
144
+ "latest": { "type": "app" },
145
+ "sources": {
146
+ "darwin": "高速下载站 lib/chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
+ "win32": "高速下载站 lib/chatgpt-desktop(Microsoft Store 同一个 MSIX)"
148
+ },
149
+ "verify": {
150
+ "checksum": "SHA256SUMS",
151
+ "signature": "macOS:Team ID 2DC432GLL2 + 公证;Windows:Microsoft Store 签名(OpenAI 发布者)"
152
+ },
153
+ "install": { "type": "app" },
154
+ "requires": []
155
+ }
156
+ ]
157
+ }
@@ -0,0 +1,26 @@
1
+ import { type ComponentResult, type ComponentSpec } from '../lib/components.js';
2
+ /** Names → components (ids or aliases), with the components they require put first; unknown names are reported. */
3
+ export declare function resolveTargets(names: string[]): {
4
+ specs: ComponentSpec[];
5
+ unknown: string[];
6
+ };
7
+ /**
8
+ * `vibecli list`: every component, whether it is installed, which version, the newest one and where it comes
9
+ * from. Latest versions are cached an hour (`--refresh` reads them again). `--json`: `{ components: [...] }`.
10
+ */
11
+ export declare function listCommand(options?: {
12
+ refresh?: boolean;
13
+ }): Promise<void>;
14
+ /** One component, the way `install` (missing → install, there → report) or `upgrade` treats it. */
15
+ export declare function installComponent(spec: ComponentSpec, force: boolean): Promise<ComponentResult>;
16
+ /**
17
+ * `vibecli install <component...>`: installs the missing ones from China-reachable mirrors (checksums and, for
18
+ * desktop apps, the vendor's signature checked). One that is already installed is only reported, with the
19
+ * upgrade command when it is behind (user, 11-01); `--force` reinstalls. Exit code 1 when any of them didn't
20
+ * end up installed. `--json`: `{ components: [{ tool, category, current, latest, result, version_after, ok }] }`.
21
+ */
22
+ export declare function installCommand(names: string[], options?: {
23
+ force?: boolean;
24
+ }): Promise<void>;
25
+ /** Runtimes behind their latest (cached versions only, no network): one line each after a plain `vibecli upgrade`. */
26
+ export declare function outdatedRuntimeHints(): Promise<string[]>;
@@ -0,0 +1 @@
1
+ import t from"chalk";import{appUpgradeCommand as e,upgradeApp as n}from"../lib/app-update.js";import{CLI_NAME as o}from"../lib/brand.js";import{componentStatus as r,listComponents as a,prefetchLatest as l,resolveComponent as s,runRuntime as i,upgradeAdvice as c}from"../lib/components.js";import{i18n as u}from"../lib/i18n.js";import{emitJson as d,isJsonMode as p,progressToStderr as m}from"../lib/runtime-options.js";import{mirrorInstall as f,upgradeTool as g}from"../lib/tool-upgrade.js";import{getAdapter as _}from"../lib/tools/registry.js";import{findInstallsIncludingNative as y,forgetInstalls as b}from"../lib/tools/tool-installs.js";function h(t){p()?process.stderr.write(t+"\n"):console.log(t)}function w(t){let e=0;for(const n of t)e+=/[ᄀ-ᅟ⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/.test(n)?2:1;return e}function k(t,e){return t+" ".repeat(Math.max(0,e-w(t)))}export function resolveTargets(t){const e=[],n=[],o=(t,e)=>{if(!n.includes(t)&&!e.includes(t.id)){for(const n of t.requires){const r=s(n);r&&o(r,[...e,t.id])}n.push(t)}};for(const n of t){const t=s(n);t?o(t,[]):e.push(n)}return{specs:n,unknown:e}}function v(e){return e.supported?!e.installed&&e.blocker?t.gray(function(t){for(const e of[`components.reason_${t}`,`app_update.reason_${t}`]){const t=u.t(e);if(t!==e)return t}return t}(e.blocker)):e.installed?e.outdated?t.yellow(e.auto_upgrade?u.t("components.state.outdated_auto",{command:`${o} upgrade ${e.id}`}):u.t("components.state.outdated_manual",{how:e.hint??u.t(`components.how_${e.managed_by??"other"}`,{tool:e.name})})):e.latest?t.green(u.t("components.state.latest")):t.gray(u.t("components.state.unknown_latest")):t.gray(u.t("components.state.missing",{command:`${o} install ${e.id}`})):t.gray(u.t("components.state.unsupported"))}export async function listCommand(e={}){const n=a(),o=await l(n,{refresh:e.refresh}),s=[];for(const t of n)s.push(await r(t,{latest:o.get(t.id)}));if(p())return void d({components:s});const i=s.map(t=>({s:t,cells:[t.name,t.installed?t.current??"?":"—",t.latest??"—",t.installed?u.t(`components.by.${t.managed_by??"other"}`):"—"]})),c=[u.t("components.col.name"),u.t("components.col.current"),u.t("components.col.latest"),u.t("components.col.managed")],m=c.map((t,e)=>Math.max(w(t),...i.map(t=>w(t.cells[e])))+2);for(const e of["runtime","cli","app"]){const n=i.filter(t=>t.s.category===e);if(n.length){console.log(t.bold(`\n${u.t(`components.category.${e}`)}`)),console.log(t.gray(" "+c.map((t,e)=>k(t,m[e])).join("")+u.t("components.col.state")));for(const{s:e,cells:o}of n)console.log(" "+o.map((t,e)=>k(t,m[e])).join("")+v(e)),e.source&&e.supported&&console.log(t.gray(" "+u.t("components.source",{source:e.source})))}}const f=s.filter(t=>t.error&&!t.latest);f.length&&console.log(t.yellow("\n ! "+u.t("components.latest_unknown",{tools:f.map(t=>t.name).join("、")})))}export async function installComponent(o,a){return p()||console.log(t.bold(`\n${o.name}`)),"runtime"===o.category?i(o,"install",{force:a}):"cli"===o.category?async function(e,n){const o=_(e.adapter),a=await r(e,{refresh:!0}),l={tool:e.id,category:"cli",current:a.current,latest:a.latest,version_after:null};if(!o?.installSpec)return{...l,result:"unavailable",ok:!1,reason:"no_install_spec"};if(a.blocker)return h(t.yellow(" ! "+u.t(`components.blocked_${a.blocker}`,{tool:e.name}))),{...l,result:"unavailable",ok:!1,reason:a.blocker};if(a.installed&&!n){const n=t.gray(`(${a.path})`);return a.outdated?(h(t.green(" √ "+u.t("components.already_installed",{tool:e.name,current:a.current??"?"}))+n),h(t.yellow(" ! "+c(a))),{...l,result:"already_installed",ok:!0,hint:c(a)}):(h(t.green(" √ "+u.t(a.latest?"components.up_to_date":"components.already_installed",{tool:e.name,current:a.current??"?"}))+n),{...l,result:"already_installed",ok:!0})}let s;a.installed?(h(t.yellow(" ! "+u.t("components.reinstalling",{tool:e.name,current:a.current??"?"}))),s=await f(o.installSpec)):s=await g(o.name),b();const i=y(o.installSpec)[0];a.installed&&s&&h(t.green(" √ "+u.t("components.reinstalled",{tool:e.name,version:i?.version??"?"})));const d=s&&i?a.installed?"reinstalled":"installed":"failed";return{...l,result:d,ok:"failed"!==d,version_after:i?.version??null}}(o,a):async function(o,a){const l=await r(o,{refresh:!0});if(l.installed&&!a){const n={tool:o.id,category:"app",current:l.current,latest:l.latest,version_after:null};if(l.outdated){h(t.green(" √ "+u.t("components.already_installed",{tool:o.name,current:l.current??"?"})));const r=u.t("app_update.upgrade_hint",{tool:o.name,current:l.current??"?",latest:l.latest??"?",command:e(o.app)});return h(t.yellow(" ! "+r)),{...n,result:"already_installed",ok:!0,hint:r}}return h(t.green(" √ "+u.t(l.latest?"components.up_to_date":"components.already_installed",{tool:o.name,current:l.current??"?"}))),{...n,result:"already_installed",ok:!0}}return function(t,e){const n={installed:"installed",upgraded:e.current&&e.latest&&e.current===e.version_after?"reinstalled":"upgraded",up_to_date:"up_to_date",declined:"manual",offered:"already_installed",left_running:"manual",not_installed:"unavailable",unavailable:"unavailable",failed:"failed"}[e.result]??"failed";return{tool:t.id,category:"app",current:e.current,latest:e.latest,result:n,version_after:e.version_after,ok:["installed","upgraded","reinstalled","up_to_date","already_installed"].includes(n),...e.reason?{reason:e.reason}:{}}}(o,await n(o.app,{install:!0,force:a}))}(o,a)}export async function installCommand(e,n={}){const{specs:o,unknown:r}=resolveTargets(e);if(r.length||!o.length)return console.error(t.red(u.t("components.unknown",{names:r.join(", ")||"—"}))),console.error(u.t("components.known",{ids:a().map(t=>t.id).join(" / ")})),void(process.exitCode=1);const l=[];for(const t of o)l.push(await m(()=>installComponent(t,Boolean(n.force))));p()&&d({components:l}),l.some(t=>!t.ok)&&(process.exitCode=1)}export async function outdatedRuntimeHints(){const t=a().filter(t=>"runtime"===t.category);return(await Promise.all(t.map(t=>r(t,{offline:!0})))).filter(t=>t.installed&&t.outdated).map(t=>c(t))}
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * `vibecli upgrade [tool...]`: no argument = every installed tool vibecli knows how to upgrade (CLIs with an
3
- * `installSpec`, GUI apps with an `appInstaller` that this machine can serve). An app named explicitly is installed
4
- * when missing; `--force` reinstalls an app that is already the latest. `--json` prints `{ tools: [...] }`: per app its current / latest version and whether it was upgraded.
3
+ * `installSpec`, GUI apps with an `appInstaller` that this machine can serve), then one line per runtime that is
4
+ * behind (`vibecli upgrade node`). Named: CLIs, apps and runtimes (node, git, uv; components.json, aliases too). A
5
+ * tool or app named explicitly is installed when missing; `--force` reinstalls an app or runtime that is already
6
+ * the latest. `--json` prints `{ tools: [...] }`: per entry its current / latest version and whether it was upgraded.
5
7
  */
6
8
  export declare function upgradeCommand(tools: string[], options?: {
7
9
  force?: boolean;
@@ -1 +1 @@
1
- import o from"chalk";import{appTools as t,getApp as e,upgradeApp as l}from"../lib/app-update.js";import{i18n as r}from"../lib/i18n.js";import{emitJson as n,isJsonMode as i}from"../lib/runtime-options.js";import{toolManager as s}from"../lib/tool-manager.js";import{listAdapters as a}from"../lib/tools/registry.js";import{upgradeTool as p}from"../lib/tool-upgrade.js";export async function upgradeCommand(d,c={}){const u=t(),m=[...a().filter(o=>o.installSpec).map(o=>o.name),...u],f=d.length>0?d:m.filter(o=>u.includes(o)?(o=>{const t=e(o)?.appInstaller;return Boolean(t&&!t.blocker()&&t.installedPath())})(o):s.isToolInstalled(o)),g=f.filter(o=>!m.includes(o));if(g.length>0)return console.error(o.red(r.t("upgrade.unsupported",{tool:g.join(", ")}))),console.error(r.t("upgrade.supported",{tools:m.join(" / ")})),void(process.exitCode=1);if(0===f.length)return void(i()?n({tools:[]}):console.log(r.t("upgrade.nothing_installed",{tools:m.join(" / ")})));let j=0;const b=[];for(const t of f){if(u.includes(t)){const r=e(t)?.displayName??t;i()||console.log(o.bold(`\n${r}`));const n=await l(t,{install:!0,force:c.force}),s=["installed","upgraded","up_to_date","declined"].includes(n.result);s||(j+=1),b.push({...n,ok:s});continue}const r=await p(t);r||(j+=1),b.push({tool:t,ok:r})}i()&&n({tools:b}),j>0&&(process.exitCode=1)}
1
+ import o from"chalk";import{appTools as t,getApp as e,upgradeApp as n}from"../lib/app-update.js";import{i18n as l}from"../lib/i18n.js";import{emitJson as r,isJsonMode as i,progressToStderr as s}from"../lib/runtime-options.js";import{toolManager as a}from"../lib/tool-manager.js";import{listAdapters as p}from"../lib/tools/registry.js";import{upgradeTool as c}from"../lib/tool-upgrade.js";import{listComponents as d,resolveComponent as m,runRuntime as u}from"../lib/components.js";import{outdatedRuntimeHints as f}from"./components.js";export async function upgradeCommand(g,h={}){const j=t(),b=new Set;g=g.map(o=>{const t=m(o);return t?("runtime"===t.category&&b.add(t.id),t.adapter??t.app??t.id):o});const w=[...p().filter(o=>o.installSpec).map(o=>o.name),...j,...b],y=g.length>0?g:w.filter(o=>j.includes(o)?(o=>{const t=e(o)?.appInstaller;return Boolean(t&&!t.blocker()&&t.installedPath())})(o):a.isToolInstalled(o)),k=y.filter(o=>!w.includes(o));if(k.length>0){console.error(o.red(l.t("upgrade.unsupported",{tool:k.join(", ")})));const t=d().filter(o=>"runtime"===o.category).map(o=>o.id);return console.error(l.t("upgrade.supported",{tools:[...new Set([...w,...t])].join(" / ")})),void(process.exitCode=1)}if(0===y.length)return void(i()?r({tools:[]}):console.log(l.t("upgrade.nothing_installed",{tools:w.join(" / ")})));let x=0;const C=[];for(const t of y){if(b.has(t)){const e=m(t);i()||console.log(o.bold(`\n${e.name}`));const n=await s(()=>u(e,"upgrade",{force:h.force}));n.ok||(x+=1),C.push(n);continue}if(j.includes(t)){const l=e(t)?.displayName??t;i()||console.log(o.bold(`\n${l}`));const r=await s(()=>n(t,{install:!0,force:h.force})),a=["installed","upgraded","up_to_date","declined"].includes(r.result);a||(x+=1),C.push({...r,ok:a});continue}const l=await s(()=>c(t));l||(x+=1),C.push({tool:t,ok:l})}if(i())r({tools:C});else if(0===g.length){const t=await f();t.length&&console.log("\n"+t.map(t=>o.yellow(" ! "+t)).join("\n"))}x>0&&(process.exitCode=1)}
@@ -0,0 +1,157 @@
1
+ {
2
+ "schema": 1,
3
+ "about": "Components VibeCLI installs and upgrades (vibecli list / install / upgrade). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
+ "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
5
+ "components": [
6
+ {
7
+ "id": "node",
8
+ "name": "Node.js",
9
+ "category": "runtime",
10
+ "aliases": ["nodejs"],
11
+ "platforms": ["darwin", "linux", "win32"],
12
+ "detect": { "command": "node", "pattern": "v(\\d+\\.\\d+\\.\\d+)" },
13
+ "latest": { "type": "node-lts", "url": "https://registry.npmmirror.com/-/binary/node/index.json" },
14
+ "sources": {
15
+ "all": "fnm({devtools})+ Node 镜像 https://npmmirror.com/mirrors/node"
16
+ },
17
+ "verify": { "checksum": "fnm:SHA256SUMS;Node:fnm 下载时核对官方 SHASUMS256.txt", "signature": "—" },
18
+ "install": { "type": "script", "script": "node", "forceEnv": { "NODE_INSTALL_FORCE": "1" } },
19
+ "upgrade": { "managedBy": "fnm", "migrateGlobalPackages": true },
20
+ "check": ["node", "--version"],
21
+ "requires": []
22
+ },
23
+ {
24
+ "id": "git",
25
+ "name": "Git",
26
+ "category": "runtime",
27
+ "platforms": ["darwin", "linux", "win32"],
28
+ "detect": { "command": "git", "pattern": "git version (\\d+\\.\\d+\\.\\d+)" },
29
+ "latest": { "type": "devtools", "key": "git", "platforms": ["win32"] },
30
+ "sources": {
31
+ "darwin": "苹果命令行工具(xcode-select)",
32
+ "linux": "系统包管理器(apt、dnf、yum、zypper、pacman、apk)",
33
+ "win32": "Git for Windows({devtools})"
34
+ },
35
+ "verify": {
36
+ "checksum": "Windows:SHA256SUMS(取自 GitHub 公布的 digest)",
37
+ "signature": "macOS / Linux:系统包管理器自己的签名"
38
+ },
39
+ "install": { "type": "script", "script": "git", "forceEnv": { "GIT_INSTALL_FORCE": "1" } },
40
+ "upgrade": { "managedBy": "git-for-windows-user" },
41
+ "check": ["git", "--version"],
42
+ "requires": []
43
+ },
44
+ {
45
+ "id": "uv",
46
+ "name": "uv",
47
+ "category": "runtime",
48
+ "aliases": ["python-uv"],
49
+ "platforms": ["darwin", "linux", "win32"],
50
+ "detect": { "command": "uv", "pattern": "uv (\\d+\\.\\d+\\.\\d+)" },
51
+ "latest": { "type": "devtools", "key": "uv" },
52
+ "sources": {
53
+ "all": "uv 官方程序({devtools});Python 从 npmmirror 的 python-build-standalone 镜像、包从阿里云 PyPI 镜像"
54
+ },
55
+ "verify": { "checksum": "SHA256SUMS", "signature": "—" },
56
+ "install": { "type": "script", "script": "uv", "forceEnv": { "UV_INSTALL_FORCE": "1" } },
57
+ "upgrade": { "managedBy": "uv-standalone" },
58
+ "check": ["uv", "--version"],
59
+ "requires": []
60
+ },
61
+ {
62
+ "id": "claude-code",
63
+ "name": "Claude Code",
64
+ "category": "cli",
65
+ "aliases": ["claude"],
66
+ "platforms": ["darwin", "linux", "win32"],
67
+ "adapter": "claude-code",
68
+ "latest": { "type": "npm", "package": "@anthropic-ai/claude-code" },
69
+ "sources": {
70
+ "all": "npmmirror 的 @anthropic-ai/claude-code-<平台>(与 downloads.claude.ai 同一文件),按官方原生布局安装({scripts}/claude-code.sh / .ps1)"
71
+ },
72
+ "verify": { "checksum": "npm sha512;连得上时再核对 Anthropic 发布清单的 sha256", "signature": "—" },
73
+ "install": { "type": "adapter" },
74
+ "check": ["claude", "--version"],
75
+ "requires": []
76
+ },
77
+ {
78
+ "id": "codex",
79
+ "name": "Codex",
80
+ "category": "cli",
81
+ "platforms": ["darwin", "linux", "win32"],
82
+ "adapter": "codex",
83
+ "latest": { "type": "npm", "package": "@openai/codex" },
84
+ "sources": {
85
+ "all": "npmmirror 的 @openai/codex(vendor 目录与官方 codex-package 逐文件相同),按官方原生布局安装({scripts}/codex.sh / .ps1)"
86
+ },
87
+ "verify": { "checksum": "npm sha512", "signature": "—" },
88
+ "install": { "type": "adapter" },
89
+ "check": ["codex", "--version"],
90
+ "requires": []
91
+ },
92
+ {
93
+ "id": "grok",
94
+ "name": "Grok Build",
95
+ "category": "cli",
96
+ "platforms": ["darwin", "linux", "win32"],
97
+ "adapter": "grok",
98
+ "latest": { "type": "npm", "package": "@xai-official/grok", "staleTag": true },
99
+ "sources": { "all": "npmmirror 的 @xai-official/grok-<平台>({scripts}/grok.sh / .ps1)" },
100
+ "verify": { "checksum": "npm sha512", "signature": "—" },
101
+ "install": { "type": "adapter" },
102
+ "check": ["grok", "--version"],
103
+ "requires": []
104
+ },
105
+ {
106
+ "id": "agy",
107
+ "name": "Antigravity CLI",
108
+ "category": "cli",
109
+ "aliases": ["antigravity"],
110
+ "platforms": ["darwin", "linux", "win32"],
111
+ "adapter": "agy",
112
+ "latest": { "type": "version-file", "url": "{agy}/version.txt" },
113
+ "sources": { "all": "高速下载站 {agy}(每小时同步官方)" },
114
+ "verify": { "checksum": "官方清单的 sha512", "signature": "—" },
115
+ "install": { "type": "adapter" },
116
+ "check": ["agy", "--version"],
117
+ "requires": []
118
+ },
119
+ {
120
+ "id": "claude-desktop",
121
+ "name": "Claude Desktop",
122
+ "category": "app",
123
+ "platforms": ["darwin", "win32"],
124
+ "app": "claude-desktop",
125
+ "latest": { "type": "app" },
126
+ "sources": {
127
+ "darwin": "高速下载站 lib/claude-desktop(官方 dmg)",
128
+ "win32": "高速下载站 lib/claude-desktop(官方 MSIX)"
129
+ },
130
+ "verify": {
131
+ "checksum": "SHA256SUMS",
132
+ "signature": "macOS:Team ID Q6L2SF6YDW + 公证;Windows:Authenticode O=Anthropic, PBC"
133
+ },
134
+ "install": { "type": "app" },
135
+ "requires": []
136
+ },
137
+ {
138
+ "id": "chatgpt",
139
+ "name": "ChatGPT",
140
+ "category": "app",
141
+ "aliases": ["chatgpt-desktop", "codex-desktop", "codex-app"],
142
+ "platforms": ["darwin", "win32"],
143
+ "app": "chatgpt",
144
+ "latest": { "type": "app" },
145
+ "sources": {
146
+ "darwin": "高速下载站 lib/chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
+ "win32": "高速下载站 lib/chatgpt-desktop(Microsoft Store 同一个 MSIX)"
148
+ },
149
+ "verify": {
150
+ "checksum": "SHA256SUMS",
151
+ "signature": "macOS:Team ID 2DC432GLL2 + 公证;Windows:Microsoft Store 签名(OpenAI 发布者)"
152
+ },
153
+ "install": { "type": "app" },
154
+ "requires": []
155
+ }
156
+ ]
157
+ }
@@ -42,15 +42,35 @@ export declare function appTools(): string[];
42
42
  export declare function getApp(name: string): AppEntry | undefined;
43
43
  /** Apps that go with these configured tools (Claude Desktop with itself, ChatGPT with codex). */
44
44
  export declare function appsForTools(tools: string[]): string[];
45
+ /**
46
+ * The mirror's latest version only (cached an hour, failures ten minutes; `refresh` reads it again), no local
47
+ * probing: callers that check several apps fetch first, then probe (on Windows the PowerShell probes are
48
+ * synchronous and would hold up the event loop past the fetch timeouts).
49
+ */
50
+ export declare function appLatest(tool: string, options?: {
51
+ refresh?: boolean;
52
+ }): Promise<{
53
+ version: string | null;
54
+ error?: string;
55
+ }>;
45
56
  /** Installed / latest versions; the latest is read from the mirror at most once an hour unless `refresh`. */
46
57
  export declare function appStatus(tool: string, options?: {
47
58
  refresh?: boolean;
48
59
  }): Promise<AppStatus>;
60
+ /** Local state with a latest version already fetched (`appLatest`). */
61
+ export declare function appStatusWith(tool: string, latest: {
62
+ version: string | null;
63
+ error?: string;
64
+ }): AppStatus;
49
65
  /** From the cache only (menus): no network. */
50
66
  export declare function cachedAppStatus(tool: string): AppStatus;
51
67
  /** "current x, y available" / "x (latest)" / "not installed"; empty when nothing is known. */
52
68
  export declare function appStatusText(status: AppStatus): string;
53
69
  export declare function appUpgradeCommand(tool: string): string;
70
+ export declare function setQuitWaitForTests(wait: {
71
+ totalMs: number;
72
+ stepMs: number;
73
+ }): void;
54
74
  export interface UpgradeAppOptions {
55
75
  /** Install the app when it isn't installed (`vibecli upgrade`, setup after consent). */
56
76
  install?: boolean;
@@ -1 +1 @@
1
- import t from"chalk";import e from"inquirer";import{existsSync as r,mkdirSync as n,readFileSync as a,writeFileSync as o}from"fs";import{join as l}from"path";import{CLI_NAME as p}from"./brand.js";import{configManager as i}from"./config.js";import{i18n as s}from"./i18n.js";import{canPrompt as u,hasExplicitYes as d,isJsonMode as c}from"./runtime-options.js";import{track as f}from"./telemetry.js";import{compareVersions as m}from"./model-registry.js";import{listAdapters as g}from"./tools/registry.js";import{logger as _}from"../utils/logger.js";function y(){return l(i.getConfigDir(),"app-releases.json")}function w(){try{if(!r(y()))return{};const t=JSON.parse(a(y(),"utf-8"));return t&&"object"==typeof t?t:{}}catch{return{}}}function h(t,e){try{n(i.getConfigDir(),{recursive:!0}),o(y(),JSON.stringify({...w(),[t]:e},null,2))}catch(t){_.logError("app-update.writeCache",t)}}function k(){return g().flatMap(t=>[...t.appInstaller?[{name:t.name,displayName:t.displayName,appInstaller:t.appInstaller,installedVersion:t.installedVersion,runningApp:t.runningApp,tool:t.name}]:[],...(t.companionApps??[]).map(e=>({...e,tool:t.name}))])}export function appTools(){return k().map(t=>t.name)}export function getApp(t){return k().find(e=>e.name===t)}export function appsForTools(t){return k().filter(e=>t.includes(e.tool)).map(t=>t.name)}function v(t){const e=getApp(t);if(!e)throw new Error(`no app installer for ${t}`);return e}function b(t,e,r){try{return e()}catch(e){return _.logError(`app-update.${t}`,e),r}}function C(t){const e=v(t),r=e.appInstaller,n=b("installedPath",()=>null!==r.installedPath(),!1);return{tool:t,name:e.displayName,installed:n,current:n?b("installedVersion",()=>e.installedVersion?.()??null,null):null,running:!!n&&b("isRunning",()=>e.runningApp?.isRunning()??!1,!1),blocker:b("blocker",()=>r.blocker(),"unsupported_platform")}}function U(t,e,r){const n=Boolean(t.installed&&t.current&&e&&m(t.current,e)<0);return{...t,latest:e,outdated:n,...r?{error:r}:{}}}export async function appStatus(t,e={}){const r=C(t);if(r.blocker&&"classic_install"!==r.blocker)return U(r,null);const n=w()[t],a=n&&Date.now()-n.checked_at<(n.version?36e5:6e5);if(n&&a&&!e.refresh)return U(r,n.version??null,n.error);try{const e=await v(t).appInstaller.latestVersion();return h(t,{version:e,checked_at:Date.now()}),U(r,e)}catch(e){const a=e instanceof Error?e.message:String(e);return _.logError(`app-update.latest(${t})`,e),h(t,{error:a,checked_at:Date.now()}),U(r,n?.version??null,a)}}export function cachedAppStatus(t){const e=C(t);return U(e,e.blocker&&"classic_install"!==e.blocker?null:w()[t]?.version??null)}export function appStatusText(t){return t.installed?t.outdated?s.t("app_update.outdated",{current:t.current,latest:t.latest}):t.current&&t.latest?s.t("app_update.up_to_date",{current:t.current}):t.current??"":t.latest?s.t("app_update.not_installed",{latest:t.latest}):""}export function appUpgradeCommand(t){return`${p} upgrade ${t}`}function A(t){c()?process.stderr.write(t+"\n"):console.log(t)}async function j(t,r=!0){const{ok:n}=await e.prompt([{type:"confirm",name:"ok",message:t,default:r}]);return n}export async function upgradeApp(e,r={}){const n=Date.now(),a=await appStatus(e,{refresh:r.refresh??!0}),o=a.name,l=(t,r={})=>{const o={...a,result:t,upgraded:"upgraded"===t||"installed"===t,version_after:null,...r};return["up_to_date","unavailable","not_installed","offered"].includes(t)||f(`app-upgrade:${e}`,"failed"===t?"fail":"ok",{duration_ms:Date.now()-n,detail:{result:t,current:a.current,latest:a.latest,...r.reason?{reason:r.reason}:{}}}),o};if(a.blocker)return!r.quiet&&a.installed&&a.outdated&&A(t.yellow(" ! "+s.t("app_update.outdated",{current:a.current,latest:a.latest}))),r.quiet||A(t.yellow(" ! "+s.t(`app_update.blocked_${a.blocker}`,{tool:o,url:v(e).appInstaller.downloadPage,command:appUpgradeCommand(e)}))),l("unavailable",{reason:a.blocker});if(!a.latest)return r.quiet||A(t.yellow(" ! "+s.t("app_update.latest_unknown",{tool:o,reason:a.error??""}))),l("unavailable",{reason:a.error});if(!a.installed&&!r.install)return l("not_installed");const p=Boolean(r.force&&a.installed&&!a.outdated);if(a.installed&&!a.outdated&&!p)return r.quiet||(A(t.green(" √ "+s.t("app_update.already_latest",{tool:o,current:a.current??a.latest}))),A(t.gray(" "+s.t("app_update.force_hint",{command:appUpgradeCommand(e)})))),l("up_to_date");if(p?A(t.yellow(" ! "+s.t("app_update.reinstalling",{tool:o,latest:a.latest,current:a.current??"?"}))):!a.installed||r.askBeforeUpgrade&&!a.running||A(t.yellow(` ! ${o} `+appStatusText(a))),a.installed&&r.askBeforeUpgrade&&!a.running){if(!u()||d())return A(t.gray(" "+s.t("app_update.upgrade_hint",{tool:o,current:a.current??"?",latest:a.latest,command:appUpgradeCommand(e)}))),l("offered");if(!await j(s.t("app_update.upgrade_offer",{tool:o,current:a.current??"?",latest:a.latest})))return A(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined")}let i=!1;if(a.running){if(!u()||d())return A(t.yellow(" ! "+s.t("app_update.running_hint",{tool:o,command:appUpgradeCommand(e)}))),l("left_running");if(!await j(s.t("app_update.offer_quit",{tool:o,latest:a.latest})))return A(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined");const r=v(e).runningApp;if(!r?.quit?.())return A(t.yellow(" ! "+s.t("app_update.quit_failed",{tool:o,command:appUpgradeCommand(e)}))),l("failed",{reason:"quit_failed"});i=!0}try{const{version:r}=await async function(e){const r=v(e).appInstaller,n=!c()&&Boolean(process.stdout.isTTY);let a=-1;try{return await r.install({downloading:n=>A(t.gray(" "+s.t("app_update.downloading",{tool:v(e).displayName,version:n,size:String(r.sizeMb())}))),percent:e=>{!n||e-a<5||(a=e,process.stdout.write(t.gray(`\r ${e}%`)),e>=100&&process.stdout.write("\n"))},verifying:()=>{n&&a>=0&&a<100&&process.stdout.write("\n"),a=100,A(t.gray(" "+s.t("app_update.verifying",{vendor:r.vendor})))},installing:()=>A(t.gray(" "+s.t("app_update.installing")))})}finally{n&&a>=0&&a<100&&process.stdout.write("\n")}}(e);return A(t.green(" √ "+(p?s.t("app_update.reinstalled",{tool:o,version:r}):a.installed?s.t("app_update.upgraded",{tool:o,from:a.current??"?",to:r}):s.t("app_update.installed",{tool:o,version:r})))),i&&!v(e).runningApp?.launch?.()&&A(t.yellow(" ! "+s.t("setup.reopen_hint",{tool:o}))),l(a.installed?"upgraded":"installed",{version_after:r,current:a.current})}catch(r){const n=r instanceof Error?r.message:String(r);return _.logError(`app-update.install(${e})`,r),A(t.yellow(" ! "+(a.installed?s.t("app_update.upgrade_failed",{tool:o,reason:n,current:a.current??"?",command:appUpgradeCommand(e)}):s.t("app_update.install_failed",{tool:o,reason:n,command:appUpgradeCommand(e)})))),i&&v(e).runningApp?.launch?.(),l("failed",{reason:n})}}
1
+ import t from"chalk";import e from"inquirer";import{existsSync as r,mkdirSync as n,readFileSync as a,writeFileSync as o}from"fs";import{join as l}from"path";import{CLI_NAME as p}from"./brand.js";import{configManager as i}from"./config.js";import{i18n as s}from"./i18n.js";import{canPrompt as u,hasExplicitYes as d,isJsonMode as c}from"./runtime-options.js";import{track as f}from"./telemetry.js";import{compareVersions as m}from"./model-registry.js";import{listAdapters as g}from"./tools/registry.js";import{logger as _}from"../utils/logger.js";function y(){return l(i.getConfigDir(),"app-releases.json")}function w(){try{if(!r(y()))return{};const t=JSON.parse(a(y(),"utf-8"));return t&&"object"==typeof t?t:{}}catch{return{}}}function h(t,e){try{n(i.getConfigDir(),{recursive:!0}),o(y(),JSON.stringify({...w(),[t]:e},null,2))}catch(t){_.logError("app-update.writeCache",t)}}function v(){return g().flatMap(t=>[...t.appInstaller?[{name:t.name,displayName:t.displayName,appInstaller:t.appInstaller,installedVersion:t.installedVersion,runningApp:t.runningApp,tool:t.name}]:[],...(t.companionApps??[]).map(e=>({...e,tool:t.name}))])}export function appTools(){return v().map(t=>t.name)}export function getApp(t){return v().find(e=>e.name===t)}export function appsForTools(t){return v().filter(e=>t.includes(e.tool)).map(t=>t.name)}function k(t){const e=getApp(t);if(!e)throw new Error(`no app installer for ${t}`);return e}function b(t,e,r){try{return e()}catch(e){return _.logError(`app-update.${t}`,e),r}}function q(t){const e=k(t),r=e.appInstaller,n=b("installedPath",()=>null!==r.installedPath(),!1);return{tool:t,name:e.displayName,installed:n,current:n?b("installedVersion",()=>e.installedVersion?.()??null,null):null,running:!!n&&b("isRunning",()=>e.runningApp?.isRunning()??!1,!1),blocker:b("blocker",()=>r.blocker(),"unsupported_platform")}}function x(t,e,r){const n=Boolean(t.installed&&t.current&&e&&m(t.current,e)<0);return{...t,latest:e,outdated:n,...r?{error:r}:{}}}export async function appLatest(t,e={}){const r=w()[t],n=r&&Date.now()-r.checked_at<(r.version?36e5:6e5);if(r&&n&&!e.refresh)return{version:r.version??null,...r.error?{error:r.error}:{}};try{const e=await k(t).appInstaller.latestVersion();return h(t,{version:e,checked_at:Date.now()}),{version:e}}catch(e){const n=e instanceof Error?e.message:String(e);return _.logError(`app-update.latest(${t})`,e),h(t,{error:n,checked_at:Date.now()}),{version:r?.version??null,error:n}}}export async function appStatus(t,e={}){const r=q(t);if(r.blocker&&"classic_install"!==r.blocker)return x(r,null);const{version:n,error:a}=await appLatest(t,e);return x(r,n,a)}export function appStatusWith(t,e){return x(q(t),e.version,e.error)}export function cachedAppStatus(t){const e=q(t);return x(e,e.blocker&&"classic_install"!==e.blocker?null:w()[t]?.version??null)}export function appStatusText(t){return t.installed?t.outdated?s.t("app_update.outdated",{current:t.current,latest:t.latest}):t.current&&t.latest?s.t("app_update.up_to_date",{current:t.current}):t.current??"":t.latest?s.t("app_update.not_installed",{latest:t.latest}):""}export function appUpgradeCommand(t){return`${p} upgrade ${t}`}function C(t){c()?process.stderr.write(t+"\n"):console.log(t)}async function S(t,r=!0){const{ok:n}=await e.prompt([{type:"confirm",name:"ok",message:t,default:r}]);return n}let U={totalMs:12e4,stepMs:1e3};export function setQuitWaitForTests(t){U=t}export async function upgradeApp(e,r={}){const n=Date.now(),a=await appStatus(e,{refresh:r.refresh??!0}),o=a.name,l=(t,r={})=>{const o={...a,result:t,upgraded:"upgraded"===t||"installed"===t,version_after:null,...r};return["up_to_date","unavailable","not_installed","offered"].includes(t)||f(`app-upgrade:${e}`,"failed"===t?"fail":"ok",{duration_ms:Date.now()-n,detail:{result:t,current:a.current,latest:a.latest,...r.reason?{reason:r.reason}:{}}}),o};if(a.blocker)return!r.quiet&&a.installed&&a.outdated&&C(t.yellow(" ! "+s.t("app_update.outdated",{current:a.current,latest:a.latest}))),r.quiet||C(t.yellow(" ! "+s.t(`app_update.blocked_${a.blocker}`,{tool:o,url:k(e).appInstaller.downloadPage,command:appUpgradeCommand(e)}))),l("unavailable",{reason:a.blocker});if(!a.latest)return r.quiet||C(t.yellow(" ! "+s.t("app_update.latest_unknown",{tool:o,reason:a.error??""}))),l("unavailable",{reason:a.error});if(!a.installed&&!r.install)return l("not_installed");const p=Boolean(r.force&&a.installed&&!a.outdated);if(a.installed&&!a.outdated&&!p)return r.quiet||(C(t.green(" √ "+s.t("app_update.already_latest",{tool:o,current:a.current??a.latest}))),C(t.gray(" "+s.t("app_update.force_hint",{command:appUpgradeCommand(e)})))),l("up_to_date");if(p?C(t.yellow(" ! "+s.t("app_update.reinstalling",{tool:o,latest:a.latest,current:a.current??"?"}))):!a.installed||r.askBeforeUpgrade&&!a.running||C(t.yellow(` ! ${o} `+appStatusText(a))),a.installed&&r.askBeforeUpgrade&&!a.running){if(!u()||d())return C(t.gray(" "+s.t("app_update.upgrade_hint",{tool:o,current:a.current??"?",latest:a.latest,command:appUpgradeCommand(e)}))),l("offered");if(!await S(s.t("app_update.upgrade_offer",{tool:o,current:a.current??"?",latest:a.latest})))return C(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined")}let i=!1;if(a.running){if(!u()||d())return C(t.yellow(" ! "+s.t("app_update.running_hint",{tool:o,command:appUpgradeCommand(e)}))),l("left_running");if(!await S(s.t("app_update.offer_quit",{tool:o,latest:a.latest})))return C(t.gray(" "+s.t("app_update.declined_hint",{command:appUpgradeCommand(e)}))),l("declined");const r=k(e).runningApp;if(r?.quit?.())i=!0;else{if(!r?.quitRefused?.()||!await async function(e,r){C(t.yellow(" ! "+s.t("app_update.quit_confirm_in_app",{tool:e,seconds:String(Math.round(U.totalMs/1e3))})));const n=Date.now()+U.totalMs;for(;Date.now()<n;)if(await new Promise(t=>setTimeout(t,U.stepMs)),!r.isRunning())return await new Promise(t=>setTimeout(t,Math.min(1e3,U.stepMs))),!0;return!1}(o,r)){const n=r?.quitRefused?.()?"app_update.quit_refused":"app_update.quit_failed";return C(t.yellow(" ! "+s.t(n,{tool:o,command:appUpgradeCommand(e)}))),l(r?.quitRefused?.()?"left_running":"failed",{reason:r?.quitRefused?.()?"quit_refused":"quit_failed"})}i=!0}}try{const{version:r}=await async function(e){const r=k(e).appInstaller,n=!c()&&Boolean(process.stdout.isTTY);let a=-1;try{return await r.install({downloading:n=>C(t.gray(" "+s.t("app_update.downloading",{tool:k(e).displayName,version:n,size:String(r.sizeMb())}))),percent:e=>{!n||e-a<5||(a=e,process.stdout.write(t.gray(`\r ${e}%`)),e>=100&&process.stdout.write("\n"))},verifying:()=>{n&&a>=0&&a<100&&process.stdout.write("\n"),a=100,C(t.gray(" "+s.t("app_update.verifying",{vendor:r.vendor})))},installing:()=>C(t.gray(" "+s.t("app_update.installing")))})}finally{n&&a>=0&&a<100&&process.stdout.write("\n")}}(e);return C(t.green(" √ "+(p?s.t("app_update.reinstalled",{tool:o,version:r}):a.installed?s.t("app_update.upgraded",{tool:o,from:a.current??"?",to:r}):s.t("app_update.installed",{tool:o,version:r})))),i&&!k(e).runningApp?.launch?.()&&C(t.yellow(" ! "+s.t("setup.reopen_hint",{tool:o}))),l(a.installed?"upgraded":"installed",{version_after:r,current:a.current})}catch(r){const n=r instanceof Error?r.message:String(r);return _.logError(`app-update.install(${e})`,r),C(t.yellow(" ! "+(a.installed?s.t("app_update.upgrade_failed",{tool:o,reason:n,current:a.current??"?",command:appUpgradeCommand(e)}):s.t("app_update.install_failed",{tool:o,reason:n,command:appUpgradeCommand(e)})))),i&&k(e).runningApp?.launch?.(),l("failed",{reason:n})}}
package/dist/lib/brand.js CHANGED
@@ -1 +1 @@
1
- import{existsSync as e,readdirSync as r,readFileSync as t}from"fs";import{dirname as n,join as o}from"path";import{fileURLToPath as a}from"url";const i=["id","displayName","productName","cliName","envPrefix","configDirName","providerKey","apiKeyEnv","desktopEntryName","packageName"];export const NEUTRAL_CLI_NAME="codekey";export function normalizeBrand(e){const r=e.cliName??e.shortName??"codekey";return{...e,cliName:r,envPrefix:e.envPrefix??r.toUpperCase().replace(/-/g,"_"),configDirName:e.configDirName??`.${r}`}}export function validateBrand(e,r="brand"){if(!e||"object"!=typeof e)throw new Error(`${r}: not an object`);const t=normalizeBrand(e);for(const e of i)if("string"!=typeof t[e]||!t[e].trim())throw new Error(`${r}: ${e} is required`);if(!/^[a-z][a-z0-9-]*$/.test(t.cliName))throw new Error(`${r}: cliName must be a lowercase command name`);if(!/^[A-Z][A-Z0-9_]*$/.test(t.envPrefix))throw new Error(`${r}: envPrefix must be UPPER_SNAKE`);if(!/^[a-z][a-z0-9-]*$/.test(t.providerKey))throw new Error(`${r}: providerKey must be lowercase`);const n=t.gatewayAddresses;if(!Array.isArray(n)||0===n.length||n.some(e=>!e||"string"!=typeof e.url||!/^https:\/\//.test(e.url)||"string"!=typeof e.label))throw new Error(`${r}: gatewayAddresses must be a non-empty list of { url: https://…, label }`);const o=t.links;if(!o||"string"!=typeof o.tokenPage)throw new Error(`${r}: links.tokenPage is required`);if(!Array.isArray(t.pluginMarketplaces))throw new Error(`${r}: pluginMarketplaces must be a list`);if(!Array.isArray(t.updateRegistries)||0===t.updateRegistries.length)throw new Error(`${r}: updateRegistries must be a non-empty list`);return t}export function loadBrandFile(e){return validateBrand(JSON.parse(t(e,"utf-8")),e)}let s=function(){const i=n(a(import.meta.url)),s=o(i,"..","brand.json");if(e(s))return loadBrandFile(s);const d=o(i,"..","..","brands");for(const n of e(d)?r(d).filter(e=>e.endsWith(".json")).sort():[]){const e=JSON.parse(t(o(d,n),"utf-8"));if(!0===e.default)return validateBrand(e,o(d,n))}throw new Error(`brand.json not found next to ${i}`)}();export function brand(){return s}export function setBrandForTests(e){const r=s;return s=e,()=>{s=r}}export function brandEnv(e){return process.env[brandEnvName(e)]}export function brandEnvName(e){return`${s.envPrefix}_${e}`}function d(e,r){return"zh_CN"===r?e.join("、"):e.length>1?`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`:e.join("")}export function brandTokens(e){const r=new URL(s.gatewayAddresses[0].url),t=s.gatewayAddresses[1]?.url??s.gatewayAddresses[0].url;return{brand:s.displayName,product:s.productName,cli:s.cliName,configDir:s.configDirName,envPrefix:s.envPrefix,siteHost:r.host,altSiteUrl:t,updateSources:d(s.updateRegistries.map(e=>e.label),e)}}export const BRAND_NAME=s.displayName;export const PROVIDER_KEY=s.providerKey;export const API_KEY_ENV=s.apiKeyEnv;export const CLI_NAME=s.cliName;
1
+ import{existsSync as e,readdirSync as r,readFileSync as t}from"fs";import{dirname as n,join as o}from"path";import{fileURLToPath as a}from"url";const i=["id","displayName","productName","cliName","envPrefix","configDirName","providerKey","apiKeyEnv","desktopEntryName","packageName"];export const NEUTRAL_CLI_NAME="codekey";export function normalizeBrand(e){const r=e.cliName??e.shortName??"codekey";return{...e,cliName:r,envPrefix:e.envPrefix??r.toUpperCase().replace(/-/g,"_"),configDirName:e.configDirName??`.${r}`}}export function validateBrand(e,r="brand"){if(!e||"object"!=typeof e)throw new Error(`${r}: not an object`);const t=normalizeBrand(e);for(const e of i)if("string"!=typeof t[e]||!t[e].trim())throw new Error(`${r}: ${e} is required`);if(!/^[a-z][a-z0-9-]*$/.test(t.cliName))throw new Error(`${r}: cliName must be a lowercase command name`);if(!/^[A-Z][A-Z0-9_]*$/.test(t.envPrefix))throw new Error(`${r}: envPrefix must be UPPER_SNAKE`);if(!/^[a-z][a-z0-9-]*$/.test(t.providerKey))throw new Error(`${r}: providerKey must be lowercase`);const n=t.gatewayAddresses;if(!Array.isArray(n)||0===n.length||n.some(e=>!e||"string"!=typeof e.url||!/^https:\/\//.test(e.url)||"string"!=typeof e.label))throw new Error(`${r}: gatewayAddresses must be a non-empty list of { url: https://…, label }`);const o=t.links;if(!o||"string"!=typeof o.tokenPage)throw new Error(`${r}: links.tokenPage is required`);if(!Array.isArray(t.pluginMarketplaces))throw new Error(`${r}: pluginMarketplaces must be a list`);if(!Array.isArray(t.updateRegistries)||0===t.updateRegistries.length)throw new Error(`${r}: updateRegistries must be a non-empty list`);return t}export function loadBrandFile(e){return validateBrand(JSON.parse(t(e,"utf-8")),e)}let s=function(){const i=n(a(import.meta.url)),s=o(i,"..","brand.json");if(e(s))return loadBrandFile(s);const c=o(i,"..","..","brands");for(const n of e(c)?r(c).filter(e=>e.endsWith(".json")).sort():[]){const e=JSON.parse(t(o(c,n),"utf-8"));if(!0===e.default)return validateBrand(e,o(c,n))}throw new Error(`brand.json not found next to ${i}`)}();export function brand(){return s}export function setBrandForTests(e){const r=s;return s=e,()=>{s=r}}export function brandEnv(e){return process.env[brandEnvName(e)]}export function brandEnvName(e){return`${s.envPrefix}_${e}`}function c(e,r){return"zh_CN"===r?e.join("、"):e.length>1?`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`:e.join("")}export function brandTokens(e){const r=new URL(s.gatewayAddresses[0].url),t=s.gatewayAddresses[1]?.url??s.gatewayAddresses[0].url;return{brand:s.displayName,product:s.productName,cli:s.cliName,package:s.packageName,configDir:s.configDirName,envPrefix:s.envPrefix,siteHost:r.host,altSiteUrl:t,updateSources:c(s.updateRegistries.map(e=>e.label),e)}}export const BRAND_NAME=s.displayName;export const PROVIDER_KEY=s.providerKey;export const API_KEY_ENV=s.apiKeyEnv;export const CLI_NAME=s.cliName;