@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 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.76",
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"
@@ -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
- return;
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
- return;
297
+ } else if (copyFromEnv()) {
298
+ // Local binary installed.
299
+ } else {
300
+ await downloadAndInstall();
276
301
  }
277
302
 
278
- if (copyFromEnv()) return;
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"