@ziniao-open/cli 0.1.0-beta.76 → 0.1.0-beta.82
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/README.md +20 -0
- package/package.json +4 -2
- package/scripts/install.js +31 -8
- package/scripts/setup-ziniao-cli.ps1 +131 -0
- package/scripts/setup-ziniao-cli.sh +189 -0
package/README.md
CHANGED
|
@@ -10,6 +10,26 @@
|
|
|
10
10
|
npm install -g @ziniao-open/cli
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
紫鸟客户端自带的 `ziniao` CLI 需要同步到 AppCache 并加入 PATH。执行 `npm install -g @ziniao-open/cli` 时会自动尝试同步;安装紫鸟客户端后,也可以手动执行以下命令:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
source "$(npm root -g)/@ziniao-open/cli/scripts/setup-ziniao-cli.sh"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Windows PowerShell 执行:
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
. "$(npm root -g)\@ziniao-open\cli\scripts\setup-ziniao-cli.ps1"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
也可以在安装后手动修复:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
ziniao-cli doctor fix-path
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
脚本只探测 `ziniao.app` / `ziniao` 的安装目录;它会在 AppCache `cli` 目录缺少 CLI 或文件内容发生变化时,从紫鸟安装目录的 `envkit/cli` 同步最新文件,并注册当前用户 PATH。找不到源文件时只提示并继续,不阻断 PATH 配置。若安装目录无法自动探测,可设置 `ZINIAO_INSTALL_DIR`;若 AppCache 位置不同,可设置 `ZINIAO_APP_CACHE_DIR`。
|
|
32
|
+
|
|
13
33
|
安装时会自动下载当前平台对应的预编译二进制(支持 macOS / Linux / Windows × amd64 / arm64),并做 SHA-256 校验。
|
|
14
34
|
|
|
15
35
|
## 快速开始
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziniao-open/cli",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.82",
|
|
4
4
|
"description": "紫鸟开放平台命令行工具,为开发者和 AI Agent 提供统一的接口调用入口。",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"scripts/install.js",
|
|
15
|
-
"scripts/run.js"
|
|
15
|
+
"scripts/run.js",
|
|
16
|
+
"scripts/setup-ziniao-cli.sh",
|
|
17
|
+
"scripts/setup-ziniao-cli.ps1"
|
|
16
18
|
],
|
|
17
19
|
"engines": {
|
|
18
20
|
"node": ">=18"
|
package/scripts/install.js
CHANGED
|
@@ -197,6 +197,31 @@ function findBinaryIn(dir, name) {
|
|
|
197
197
|
return null;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
function runDesktopCliSetup() {
|
|
201
|
+
const scriptName = IS_WIN ? "setup-ziniao-cli.ps1" : "setup-ziniao-cli.sh";
|
|
202
|
+
const scriptPath = join(__dirname, scriptName);
|
|
203
|
+
if (!existsSync(scriptPath)) {
|
|
204
|
+
warn(`desktop CLI PATH setup script is missing: ${scriptPath}`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const result = IS_WIN
|
|
209
|
+
? spawnSync("powershell.exe", [
|
|
210
|
+
"-NoProfile",
|
|
211
|
+
"-NonInteractive",
|
|
212
|
+
"-ExecutionPolicy",
|
|
213
|
+
"Bypass",
|
|
214
|
+
"-File",
|
|
215
|
+
scriptPath,
|
|
216
|
+
], { stdio: "inherit" })
|
|
217
|
+
: spawnSync("sh", [scriptPath], { stdio: "inherit" });
|
|
218
|
+
if (result.error) {
|
|
219
|
+
warn(`desktop CLI PATH setup skipped: ${result.error.message}`);
|
|
220
|
+
} else if (result.status !== 0) {
|
|
221
|
+
warn(`desktop CLI PATH setup exited with code ${result.status}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
200
225
|
async function downloadAndInstall() {
|
|
201
226
|
const version = PKG.version;
|
|
202
227
|
if (!DOWNLOAD_BASE) {
|
|
@@ -266,18 +291,16 @@ async function main() {
|
|
|
266
291
|
if (PKG.version === "0.0.0") {
|
|
267
292
|
warn("package.json version is 0.0.0; skipping binary install (developer mode).");
|
|
268
293
|
warn("Set ZINIAO_CLI_BINARY=/path/to/binary or run `make build` to use a local build.");
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (existsSync(TARGET_PATH)) {
|
|
294
|
+
} else if (existsSync(TARGET_PATH)) {
|
|
273
295
|
makeExecutable(TARGET_PATH);
|
|
274
296
|
log(`binary already present at ${TARGET_PATH}, skipping download`);
|
|
275
|
-
|
|
297
|
+
} else if (copyFromEnv()) {
|
|
298
|
+
// Local binary installed.
|
|
299
|
+
} else {
|
|
300
|
+
await downloadAndInstall();
|
|
276
301
|
}
|
|
277
302
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
await downloadAndInstall();
|
|
303
|
+
runDesktopCliSetup();
|
|
281
304
|
}
|
|
282
305
|
|
|
283
306
|
main().catch((err) => fail(err.stack || err.message || String(err)));
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Synchronize the Ziniao desktop CLI into the per-user AppCache and register
|
|
2
|
+
# that directory in the current user's PATH.
|
|
3
|
+
#
|
|
4
|
+
# Use `. .\scripts\setup-ziniao-cli.ps1` to refresh the current PowerShell.
|
|
5
|
+
# A normal invocation persists PATH but cannot modify its parent PowerShell.
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
$isDotSourced = $MyInvocation.InvocationName -eq "."
|
|
9
|
+
|
|
10
|
+
function Write-Log([string]$Message) {
|
|
11
|
+
Write-Output "[ziniao-cli-path] $Message"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
$arch = if ([Environment]::Is64BitOperatingSystem) {
|
|
15
|
+
if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE }
|
|
16
|
+
} else { $env:PROCESSOR_ARCHITECTURE }
|
|
17
|
+
switch ($arch.ToLowerInvariant()) {
|
|
18
|
+
"amd64" { $archDir = "x64" }
|
|
19
|
+
"x86_64" { $archDir = "x64" }
|
|
20
|
+
"arm64" { $archDir = "arm64" }
|
|
21
|
+
default { throw "不支持的 CPU 架构: $arch" }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
$sourceName = "ziniao.exe"
|
|
25
|
+
$sourceRelative = Join-Path "envkit\cli\win32\$archDir" $sourceName
|
|
26
|
+
$homeDir = [Environment]::GetFolderPath("UserProfile")
|
|
27
|
+
|
|
28
|
+
function Get-FirstExistingDirectory([string[]]$Candidates) {
|
|
29
|
+
foreach ($candidate in $Candidates) {
|
|
30
|
+
if ($candidate -and (Test-Path -LiteralPath $candidate -PathType Container)) { return $candidate }
|
|
31
|
+
}
|
|
32
|
+
return $null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
$sourcePath = $null
|
|
36
|
+
if ($env:ZINIAO_CLI_SOURCE -and (Test-Path -LiteralPath $env:ZINIAO_CLI_SOURCE -PathType Leaf)) {
|
|
37
|
+
$sourcePath = $env:ZINIAO_CLI_SOURCE
|
|
38
|
+
}
|
|
39
|
+
if (-not $sourcePath -and $env:ZINIAO_INSTALL_DIR) {
|
|
40
|
+
$candidate = Join-Path $env:ZINIAO_INSTALL_DIR $sourceRelative
|
|
41
|
+
if (Test-Path -LiteralPath $candidate -PathType Leaf) { $sourcePath = $candidate }
|
|
42
|
+
}
|
|
43
|
+
if (-not $sourcePath) {
|
|
44
|
+
$installRoots = @(
|
|
45
|
+
(Join-Path $env:LOCALAPPDATA "Programs\ziniao\resources\app.asar.unpacked"),
|
|
46
|
+
(Join-Path $env:ProgramFiles "Ziniao\resources\app.asar.unpacked"),
|
|
47
|
+
(Join-Path $env:APPDATA "ziniao\resources\app.asar.unpacked")
|
|
48
|
+
)
|
|
49
|
+
foreach ($root in $installRoots) {
|
|
50
|
+
$candidate = Join-Path $root $sourceRelative
|
|
51
|
+
if (Test-Path -LiteralPath $candidate -PathType Leaf) { $sourcePath = $candidate; break }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if ($env:ZINIAO_APP_CACHE_DIR) {
|
|
55
|
+
$appCacheDir = $env:ZINIAO_APP_CACHE_DIR
|
|
56
|
+
} else {
|
|
57
|
+
$appCacheDir = Get-FirstExistingDirectory @(
|
|
58
|
+
(Join-Path $env:APPDATA "ziniao"),
|
|
59
|
+
(Join-Path $env:LOCALAPPDATA "ziniao")
|
|
60
|
+
)
|
|
61
|
+
if (-not $appCacheDir) { $appCacheDir = Join-Path $env:APPDATA "ziniao" }
|
|
62
|
+
$appCacheDir = Join-Path $appCacheDir "app-cache"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
$targetDir = Join-Path $appCacheDir "cli"
|
|
66
|
+
$targetPath = Join-Path $targetDir $sourceName
|
|
67
|
+
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
|
|
68
|
+
|
|
69
|
+
if (-not $sourcePath) {
|
|
70
|
+
if (Test-Path -LiteralPath $targetPath -PathType Leaf) {
|
|
71
|
+
Write-Log "未找到安装目录中的 CLI 源文件,保留现有 AppCache CLI: $targetPath"
|
|
72
|
+
} else {
|
|
73
|
+
Write-Log "WARN: 未找到安装目录中的 ${sourceName},跳过复制;可设置 `$env:ZINIAO_INSTALL_DIR 或 `$env:ZINIAO_CLI_SOURCE。"
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
$needsCopy = -not (Test-Path -LiteralPath $targetPath -PathType Leaf)
|
|
77
|
+
if (-not $needsCopy) {
|
|
78
|
+
$needsCopy = (Get-FileHash -LiteralPath $sourcePath -Algorithm SHA256).Hash -ne (Get-FileHash -LiteralPath $targetPath -Algorithm SHA256).Hash
|
|
79
|
+
}
|
|
80
|
+
if ($needsCopy) {
|
|
81
|
+
Copy-Item -LiteralPath $sourcePath -Destination $targetPath -Force
|
|
82
|
+
Write-Log "已同步 CLI: $sourcePath -> $targetPath"
|
|
83
|
+
} else {
|
|
84
|
+
Write-Log "AppCache CLI 已是最新: $targetPath"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function Install-PathShim {
|
|
89
|
+
if (-not (Test-Path -LiteralPath $targetPath -PathType Leaf)) { return }
|
|
90
|
+
foreach ($pathEntry in @($env:Path -split ";" | Where-Object { $_ })) {
|
|
91
|
+
if ($pathEntry.TrimEnd('\') -ieq $targetDir.TrimEnd('\')) {
|
|
92
|
+
$script:shimInstalled = $true
|
|
93
|
+
Write-Log "当前 PATH 已包含 AppCache CLI 目录: $targetDir"
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
$shimPath = Join-Path $pathEntry $sourceName
|
|
97
|
+
if (Test-Path -LiteralPath $shimPath -PathType Leaf) { continue }
|
|
98
|
+
try {
|
|
99
|
+
Copy-Item -LiteralPath $targetPath -Destination $shimPath -Force -ErrorAction Stop
|
|
100
|
+
$script:shimInstalled = $true
|
|
101
|
+
Write-Log "已在现有 PATH 中创建 CLI shim: $shimPath"
|
|
102
|
+
return
|
|
103
|
+
} catch {
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
Write-Log "WARN: 没有可写的现有 PATH 目录,无法立即提供 ziniao 命令。"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
$shimInstalled = $false
|
|
111
|
+
Install-PathShim
|
|
112
|
+
|
|
113
|
+
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
|
114
|
+
$entries = @($userPath -split ";" | Where-Object { $_ })
|
|
115
|
+
if (-not ($entries | Where-Object { $_.TrimEnd('\') -ieq $targetDir.TrimEnd('\') })) {
|
|
116
|
+
[Environment]::SetEnvironmentVariable("Path", (($entries + $targetDir) -join ";"), "User")
|
|
117
|
+
Write-Log "已写入用户 PATH: $targetDir"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
$currentEntries = @($env:Path -split ";" | Where-Object { $_ })
|
|
121
|
+
if (-not ($currentEntries | Where-Object { $_.TrimEnd('\') -ieq $targetDir.TrimEnd('\') })) {
|
|
122
|
+
$env:Path = "$targetDir;$env:Path"
|
|
123
|
+
}
|
|
124
|
+
if ($shimInstalled) {
|
|
125
|
+
Write-Log "CLI 已位于当前 PATH,当前 PowerShell 无需刷新 PATH"
|
|
126
|
+
} elseif ($isDotSourced) {
|
|
127
|
+
Write-Log "当前 PowerShell PATH 已刷新"
|
|
128
|
+
} else {
|
|
129
|
+
Write-Log "当前进程 PATH 已刷新;父级 PowerShell 请执行 dot-source 或重新打开 terminal"
|
|
130
|
+
}
|
|
131
|
+
Write-Log "验证命令: Get-Command ziniao"
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Synchronize the Ziniao desktop CLI into the per-user AppCache and register
|
|
3
|
+
# that directory in the current user's shell PATH.
|
|
4
|
+
#
|
|
5
|
+
# Use `source scripts/setup-ziniao-cli.sh` when the current shell should be
|
|
6
|
+
# refreshed immediately. A normal execution can persist PATH but cannot modify
|
|
7
|
+
# its parent shell.
|
|
8
|
+
|
|
9
|
+
log() { printf '%s\n' "[ziniao-cli-path] $*"; }
|
|
10
|
+
fail() { printf '%s\n' "[ziniao-cli-path] ERROR: $*" >&2; return 1 2>/dev/null || exit 1; }
|
|
11
|
+
|
|
12
|
+
is_sourced=0
|
|
13
|
+
if [ -n "${BASH_VERSION:-}" ]; then
|
|
14
|
+
[ "${BASH_SOURCE[0]:-$0}" != "$0" ] && is_sourced=1
|
|
15
|
+
elif [ -n "${ZSH_EVAL_CONTEXT:-}" ]; then
|
|
16
|
+
case "$ZSH_EVAL_CONTEXT" in
|
|
17
|
+
*:file) is_sourced=1 ;;
|
|
18
|
+
esac
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
if [ "$is_sourced" -eq 0 ]; then
|
|
22
|
+
set -eu
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
platform="$(uname -s 2>/dev/null || printf 'unknown')"
|
|
26
|
+
machine="$(uname -m 2>/dev/null || printf 'unknown')"
|
|
27
|
+
|
|
28
|
+
case "$platform" in
|
|
29
|
+
Darwin) platform_dir="darwin"; source_name="ziniao"; ;;
|
|
30
|
+
Linux) platform_dir="linux"; source_name="ziniao"; ;;
|
|
31
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
32
|
+
fail "检测到 Windows shell,请改用 PowerShell: scripts/setup-ziniao-cli.ps1"
|
|
33
|
+
return 1 2>/dev/null || exit 1
|
|
34
|
+
;;
|
|
35
|
+
*) fail "不支持的操作系统: $platform"; return 1 2>/dev/null || exit 1 ;;
|
|
36
|
+
esac
|
|
37
|
+
|
|
38
|
+
case "$machine" in
|
|
39
|
+
arm64|aarch64) arch_dir="arm64" ;;
|
|
40
|
+
x86_64|amd64) arch_dir="x64" ;;
|
|
41
|
+
*) fail "不支持的 CPU 架构: $machine"; return 1 2>/dev/null || exit 1 ;;
|
|
42
|
+
esac
|
|
43
|
+
|
|
44
|
+
home_dir="${HOME:?无法确定当前用户 HOME}"
|
|
45
|
+
|
|
46
|
+
first_existing_dir() {
|
|
47
|
+
for candidate in "$@"; do
|
|
48
|
+
if [ -d "$candidate" ]; then
|
|
49
|
+
printf '%s\n' "$candidate"
|
|
50
|
+
return 0
|
|
51
|
+
fi
|
|
52
|
+
done
|
|
53
|
+
return 1
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
find_source() {
|
|
57
|
+
source_rel="envkit/cli/$platform_dir/$arch_dir/$source_name"
|
|
58
|
+
if [ -n "${ZINIAO_CLI_SOURCE:-}" ] && [ -f "$ZINIAO_CLI_SOURCE" ]; then
|
|
59
|
+
printf '%s\n' "$ZINIAO_CLI_SOURCE"
|
|
60
|
+
return 0
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [ -n "${ZINIAO_INSTALL_DIR:-}" ]; then
|
|
64
|
+
candidate="$ZINIAO_INSTALL_DIR/$source_rel"
|
|
65
|
+
if [ -f "$candidate" ]; then
|
|
66
|
+
printf '%s\n' "$candidate"
|
|
67
|
+
return 0
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
for install_root in \
|
|
72
|
+
"/Applications/ziniao.app/Contents/Resources/app.asar.unpacked" \
|
|
73
|
+
"$home_dir/Applications/ziniao.app/Contents/Resources/app.asar.unpacked" \
|
|
74
|
+
"$home_dir/Library/Application Support/ziniao/app.asar.unpacked" \
|
|
75
|
+
"/opt/ziniao/resources/app.asar.unpacked"; do
|
|
76
|
+
candidate="$install_root/$source_rel"
|
|
77
|
+
if [ -f "$candidate" ]; then
|
|
78
|
+
printf '%s\n' "$candidate"
|
|
79
|
+
return 0
|
|
80
|
+
fi
|
|
81
|
+
done
|
|
82
|
+
return 1
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if [ -n "${ZINIAO_APP_CACHE_DIR:-}" ]; then
|
|
86
|
+
app_cache_dir="$ZINIAO_APP_CACHE_DIR"
|
|
87
|
+
else
|
|
88
|
+
app_data_dir="$(first_existing_dir \
|
|
89
|
+
"$home_dir/Library/Application Support/ziniao" \
|
|
90
|
+
"$home_dir/.config/ziniao" \
|
|
91
|
+
"$home_dir/.local/share/ziniao" \
|
|
92
|
+
2>/dev/null || true)"
|
|
93
|
+
if [ -z "$app_data_dir" ]; then
|
|
94
|
+
case "$platform_dir" in
|
|
95
|
+
darwin) app_data_dir="$home_dir/Library/Application Support/ziniao" ;;
|
|
96
|
+
*) app_data_dir="$home_dir/.config/ziniao" ;;
|
|
97
|
+
esac
|
|
98
|
+
fi
|
|
99
|
+
app_cache_dir="$app_data_dir/app-cache"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
target_dir="$app_cache_dir/cli"
|
|
103
|
+
source_path="$(find_source || true)"
|
|
104
|
+
mkdir -p "$target_dir"
|
|
105
|
+
target_path="$target_dir/$source_name"
|
|
106
|
+
if [ -z "$source_path" ]; then
|
|
107
|
+
if [ -f "$target_path" ]; then
|
|
108
|
+
log "未找到安装目录中的 CLI 源文件,保留现有 AppCache CLI: $target_path"
|
|
109
|
+
else
|
|
110
|
+
log "WARN: 未找到安装目录中的 ${source_name},跳过复制;可设置 ZINIAO_INSTALL_DIR 或 ZINIAO_CLI_SOURCE。"
|
|
111
|
+
fi
|
|
112
|
+
elif [ ! -f "$target_path" ] || ! cmp -s "$source_path" "$target_path"; then
|
|
113
|
+
cp "$source_path" "$target_path"
|
|
114
|
+
chmod 755 "$target_path"
|
|
115
|
+
log "已同步 CLI: $source_path -> $target_path"
|
|
116
|
+
else
|
|
117
|
+
log "AppCache CLI 已是最新: $target_path"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
shim_installed=0
|
|
121
|
+
install_path_shim() {
|
|
122
|
+
[ -f "$target_path" ] || return 0
|
|
123
|
+
old_ifs="$IFS"
|
|
124
|
+
IFS=:
|
|
125
|
+
for path_entry in ${PATH:-}; do
|
|
126
|
+
[ -d "$path_entry" ] || continue
|
|
127
|
+
[ -w "$path_entry" ] || continue
|
|
128
|
+
if [ "$path_entry" = "$target_dir" ]; then
|
|
129
|
+
shim_installed=1
|
|
130
|
+
log "当前 PATH 已包含 AppCache CLI 目录: $target_dir"
|
|
131
|
+
IFS="$old_ifs"
|
|
132
|
+
return 0
|
|
133
|
+
fi
|
|
134
|
+
shim_path="$path_entry/$source_name"
|
|
135
|
+
if [ -e "$shim_path" ] || [ -L "$shim_path" ]; then
|
|
136
|
+
if [ -L "$shim_path" ] && [ "$(readlink "$shim_path" 2>/dev/null || true)" = "$target_path" ]; then
|
|
137
|
+
log "现有 PATH 已包含 CLI shim: $shim_path"
|
|
138
|
+
shim_installed=1
|
|
139
|
+
IFS="$old_ifs"
|
|
140
|
+
return 0
|
|
141
|
+
fi
|
|
142
|
+
continue
|
|
143
|
+
fi
|
|
144
|
+
if ln -s "$target_path" "$shim_path" 2>/dev/null; then
|
|
145
|
+
log "已在现有 PATH 中创建 CLI shim: $shim_path"
|
|
146
|
+
shim_installed=1
|
|
147
|
+
IFS="$old_ifs"
|
|
148
|
+
return 0
|
|
149
|
+
fi
|
|
150
|
+
done
|
|
151
|
+
IFS="$old_ifs"
|
|
152
|
+
log "WARN: 没有可写的现有 PATH 目录,无法立即提供 ziniao 命令。"
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
install_path_shim
|
|
156
|
+
|
|
157
|
+
export PATH="$target_dir${PATH:+:$PATH}"
|
|
158
|
+
|
|
159
|
+
profile=""
|
|
160
|
+
case "${SHELL:-}" in
|
|
161
|
+
*/zsh) profile="$home_dir/.zshrc" ;;
|
|
162
|
+
*/bash) profile="$home_dir/.bashrc" ;;
|
|
163
|
+
esac
|
|
164
|
+
if [ -z "$profile" ]; then
|
|
165
|
+
case "$platform_dir" in
|
|
166
|
+
darwin) profile="$home_dir/.zshrc" ;;
|
|
167
|
+
*) profile="$home_dir/.profile" ;;
|
|
168
|
+
esac
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
marker="# ziniao-cli: AppCache CLI PATH"
|
|
172
|
+
path_line="export PATH=\"$target_dir:\$PATH\""
|
|
173
|
+
if ! grep -Fqx "$marker" "$profile" 2>/dev/null; then
|
|
174
|
+
mkdir -p "$(dirname "$profile")"
|
|
175
|
+
printf '\n%s\n' "$marker" >> "$profile"
|
|
176
|
+
log "已写入 shell 配置: $profile"
|
|
177
|
+
fi
|
|
178
|
+
if ! grep -Fqx "$path_line" "$profile" 2>/dev/null; then
|
|
179
|
+
printf '%s\n' "$path_line" >> "$profile"
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
if [ "$shim_installed" -eq 1 ]; then
|
|
183
|
+
log "CLI 已位于当前 PATH,当前 terminal 无需刷新 PATH"
|
|
184
|
+
elif [ "$is_sourced" -eq 1 ]; then
|
|
185
|
+
log "当前 shell PATH 已刷新"
|
|
186
|
+
else
|
|
187
|
+
log "当前进程 PATH 已刷新;父级 terminal 请执行: source \"$profile\""
|
|
188
|
+
fi
|
|
189
|
+
log "验证命令: command -v $source_name"
|