@zhizai/cli 0.0.5 → 0.0.7
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 +14 -6
- package/bin/zhizai.js +22 -1
- package/package.json +4 -2
- package/scripts/postinstall.js +247 -26
- package/skills/zhizai-auth/SKILL.md +6 -1
- package/skills/zhizai-knowledge/SKILL.md +2 -1
- package/skills/zhizai-msg/SKILL.md +2 -1
- package/skills/zhizai-note/SKILL.md +19 -7
- package/skills/{zhiji-open-platform → zhizai-open-platform}/SKILL.md +1 -1
- package/skills/zhizai-scene/SKILL.md +2 -1
- package/skills/zhizai-team/SKILL.md +2 -1
- /package/skills/{zhiji-open-platform → zhizai-open-platform}/references/auth.md +0 -0
- /package/skills/{zhiji-open-platform → zhizai-open-platform}/references/knowledge.md +0 -0
- /package/skills/{zhiji-open-platform → zhizai-open-platform}/references/msg-device.md +0 -0
- /package/skills/{zhiji-open-platform → zhizai-open-platform}/references/note.md +0 -0
- /package/skills/{zhiji-open-platform → zhizai-open-platform}/references/scene.md +0 -0
- /package/skills/{zhiji-open-platform → zhizai-open-platform}/references/team.md +0 -0
package/README.md
CHANGED
|
@@ -82,12 +82,17 @@ zhizai note get <id> --field summary
|
|
|
82
82
|
|
|
83
83
|
### 4. 接入本机 AI
|
|
84
84
|
|
|
85
|
+
CLI 首次安装请用 npm(见上文「安装」)。`setup` 负责同步 Skills 与授权,**不会**在 CLI 已可用时重复 npm 重装。
|
|
86
|
+
|
|
85
87
|
```bash
|
|
86
88
|
# 预览将执行的操作
|
|
87
89
|
zhizai setup --dry-run -o json
|
|
88
90
|
|
|
89
|
-
#
|
|
91
|
+
# 同步 Skill 并引导授权(CLI 已就绪时跳过重装)
|
|
90
92
|
zhizai setup
|
|
93
|
+
|
|
94
|
+
# 升级或修复 CLI 二进制(显式触发 npm 重装)
|
|
95
|
+
zhizai setup --force-cli-install
|
|
91
96
|
```
|
|
92
97
|
|
|
93
98
|
`setup` 会把原子 Skill 安装到 Cursor、Claude Code、Codex 等本机 AI 环境,并引导完成授权。
|
|
@@ -109,18 +114,21 @@ zhizai setup
|
|
|
109
114
|
| `zhizai version` | 显示版本 |
|
|
110
115
|
| `zhizai notes [--limit\|--page\|--all]` | 笔记列表 |
|
|
111
116
|
| `zhizai note get <id> [--field ...]` | 笔记详情 |
|
|
117
|
+
| `zhizai note create --title/--content` | 创建文字笔记 |
|
|
118
|
+
| `zhizai note update <id> --title/--abstract/--summary` | 更新笔记 |
|
|
119
|
+
| `zhizai note delete <id> --yes` | 删除笔记 |
|
|
120
|
+
| `zhizai note status <id>` | 笔记处理进度 |
|
|
112
121
|
| `zhizai knowledge list [--received]` | 笔记集列表(我创建的 / 收到的) |
|
|
113
122
|
| `zhizai knowledge get <id>` | 笔记集详情 |
|
|
114
123
|
| `zhizai knowledge notes <id>` | 笔记集内笔记 |
|
|
115
|
-
| `zhizai setup [--dry-run]` |
|
|
124
|
+
| `zhizai setup [--dry-run] [--force-cli-install]` | 同步原子 Skill 并引导授权;CLI 已就绪时跳过重装 |
|
|
116
125
|
|
|
117
126
|
### 规划中
|
|
118
127
|
|
|
119
128
|
| 命令 | 说明 |
|
|
120
129
|
|------|------|
|
|
121
|
-
| `zhizai note create\|update\|delete\|status` | 笔记写入与状态 |
|
|
122
130
|
| `zhizai knowledge create` | 新建笔记集(后端接口待开放) |
|
|
123
|
-
| `zhizai file upload` |
|
|
131
|
+
| `zhizai file upload` | 文件上传(录音/文档等笔记类型依赖此项) |
|
|
124
132
|
| `zhizai ask "<问题>"` | 基于笔记的动态模版问答 / 总结 |
|
|
125
133
|
| `zhizai scene` | 场景与知识卡 |
|
|
126
134
|
| `zhizai team` | 团队与成员 |
|
|
@@ -172,13 +180,13 @@ OAuth 过期时 CLI 会自动用 `refresh_token` 刷新;也可手动 `zhizai a
|
|
|
172
180
|
| Skill | 职责 |
|
|
173
181
|
|-------|------|
|
|
174
182
|
| `zhizai-auth` | 安装、登录、诊断、升级 |
|
|
175
|
-
| `zhizai-note` |
|
|
183
|
+
| `zhizai-note` | 笔记列表、详情、文字创建、更新、删除、进度 |
|
|
176
184
|
| `zhizai-knowledge` | 笔记集 |
|
|
177
185
|
| `zhizai-scene` | 场景与知识卡 |
|
|
178
186
|
| `zhizai-team` | 团队与成员 |
|
|
179
187
|
| `zhizai-msg` | 消息与录音卡 |
|
|
180
188
|
|
|
181
|
-
另保留聚合 Skill `
|
|
189
|
+
另保留聚合 Skill `zhizai-open-platform`(含完整 OpenAPI 参考文档)。
|
|
182
190
|
|
|
183
191
|
原则:**Skill 只做意图路由,真实请求一律走 `zhizai` CLI**,不自行拼 OpenAPI。
|
|
184
192
|
|
package/bin/zhizai.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
const { spawn } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
7
8
|
const path = require('path');
|
|
8
9
|
const os = require('os');
|
|
9
10
|
|
|
@@ -11,9 +12,29 @@ const platform = os.platform();
|
|
|
11
12
|
const binaryName = platform === 'win32' ? 'zhizai.exe' : 'zhizai';
|
|
12
13
|
const binaryPath = path.join(__dirname, binaryName);
|
|
13
14
|
|
|
15
|
+
function failMissing() {
|
|
16
|
+
console.error('无法启动智在记录:CLI 可执行文件缺失。');
|
|
17
|
+
console.error('可能原因:安装中断或文件被移除。');
|
|
18
|
+
console.error('请重新执行: npm install -g @zhizai/cli@latest');
|
|
19
|
+
console.error('错误码:CLI_BINARY_MISSING');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!fs.existsSync(binaryPath)) {
|
|
24
|
+
failMissing();
|
|
25
|
+
}
|
|
26
|
+
|
|
14
27
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
15
28
|
stdio: 'inherit',
|
|
16
|
-
windowsHide: true
|
|
29
|
+
windowsHide: true,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
child.on('error', (err) => {
|
|
33
|
+
if (err && err.code === 'ENOENT') {
|
|
34
|
+
failMissing();
|
|
35
|
+
}
|
|
36
|
+
console.error('无法启动智在记录:', err.message);
|
|
37
|
+
process.exit(1);
|
|
17
38
|
});
|
|
18
39
|
|
|
19
40
|
child.on('exit', (code, signal) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhizai/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "CLI tool for 智在记录 — manage notes and knowledge from the terminal and AI agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zhizai",
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"postinstall": "node scripts/postinstall.js",
|
|
23
|
-
"release": "bash scripts/release.sh"
|
|
23
|
+
"release": "bash scripts/release.sh",
|
|
24
|
+
"publish:cli": "bash scripts/publish.sh",
|
|
25
|
+
"connector:zip": "bash scripts/pack-connector.sh"
|
|
24
26
|
},
|
|
25
27
|
"files": [
|
|
26
28
|
"bin/zhizai.js",
|
package/scripts/postinstall.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const os = require('os');
|
|
9
|
+
const http = require('http');
|
|
9
10
|
const https = require('https');
|
|
10
11
|
const crypto = require('crypto');
|
|
11
12
|
const { spawnSync } = require('child_process');
|
|
@@ -14,6 +15,34 @@ const pkg = require('../package.json');
|
|
|
14
15
|
const VERSION = pkg.version;
|
|
15
16
|
const REPO = 'BoteAI/zhizai-cli';
|
|
16
17
|
|
|
18
|
+
const DEFAULT_CONNECT_TIMEOUT_MS = 15000;
|
|
19
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 30000;
|
|
20
|
+
const DEFAULT_TOTAL_TIMEOUT_MS = 5 * 60 * 1000;
|
|
21
|
+
const DEFAULT_RETRIES = 3;
|
|
22
|
+
const RETRY_BACKOFF_MS = [500, 1000, 2000];
|
|
23
|
+
const NON_RETRYABLE_STATUS = new Set([401, 403, 404]);
|
|
24
|
+
|
|
25
|
+
function sleep(ms) {
|
|
26
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getProtocolModule(urlString) {
|
|
30
|
+
const protocol = new URL(urlString).protocol;
|
|
31
|
+
if (protocol === 'http:') return http;
|
|
32
|
+
if (protocol === 'https:') return https;
|
|
33
|
+
throw new Error(`Unsupported protocol: ${protocol}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function versionMatches(out, expected) {
|
|
37
|
+
const m = String(out).trim().match(/^zhizai version\s+v?(\S+)/i);
|
|
38
|
+
if (!m) return false;
|
|
39
|
+
return m[1] === String(expected).replace(/^v/, '');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseVersionFromOutput(out, expectedVersion) {
|
|
43
|
+
return versionMatches(out, expectedVersion);
|
|
44
|
+
}
|
|
45
|
+
|
|
17
46
|
function getPlatform() {
|
|
18
47
|
const platform = os.platform();
|
|
19
48
|
const arch = os.arch();
|
|
@@ -47,6 +76,209 @@ function getWindowsExtractArgs(archivePath, destinationPath) {
|
|
|
47
76
|
];
|
|
48
77
|
}
|
|
49
78
|
|
|
79
|
+
function unlinkQuiet(filePath) {
|
|
80
|
+
try { fs.unlinkSync(filePath); } catch (_) {}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function reportProgress(downloaded, contentLength, onProgress) {
|
|
84
|
+
if (contentLength != null) {
|
|
85
|
+
console.error(`Downloaded ${downloaded}/${contentLength} bytes`);
|
|
86
|
+
} else {
|
|
87
|
+
console.error(`Downloaded ${downloaded} bytes`);
|
|
88
|
+
}
|
|
89
|
+
if (onProgress) onProgress({ downloaded, contentLength });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function isNonRetryableError(err) {
|
|
93
|
+
const statusCode = err && err.statusCode;
|
|
94
|
+
if (statusCode != null && NON_RETRYABLE_STATUS.has(statusCode)) return true;
|
|
95
|
+
const message = String((err && err.message) || err);
|
|
96
|
+
return /HTTP (401|403|404)/.test(message);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function downloadOnce(url, destination, options, redirects = 0) {
|
|
100
|
+
if (redirects > 5) return Promise.reject(new Error('Too many redirects'));
|
|
101
|
+
|
|
102
|
+
const {
|
|
103
|
+
connectTimeoutMs,
|
|
104
|
+
idleTimeoutMs,
|
|
105
|
+
totalTimeoutMs,
|
|
106
|
+
onProgress,
|
|
107
|
+
} = options;
|
|
108
|
+
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
let request = null;
|
|
111
|
+
let response = null;
|
|
112
|
+
let output = null;
|
|
113
|
+
let connected = false;
|
|
114
|
+
let downloaded = 0;
|
|
115
|
+
let contentLength = null;
|
|
116
|
+
let lastProgressTime = 0;
|
|
117
|
+
let idleTimer = null;
|
|
118
|
+
let totalTimer = null;
|
|
119
|
+
let connectTimer = null;
|
|
120
|
+
let settled = false;
|
|
121
|
+
|
|
122
|
+
function finish(err, value) {
|
|
123
|
+
if (settled) return;
|
|
124
|
+
settled = true;
|
|
125
|
+
clearTimeout(idleTimer);
|
|
126
|
+
clearTimeout(totalTimer);
|
|
127
|
+
clearTimeout(connectTimer);
|
|
128
|
+
if (err) reject(err);
|
|
129
|
+
else resolve(value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function cleanupPartial() {
|
|
133
|
+
unlinkQuiet(destination);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function destroyStreams() {
|
|
137
|
+
if (response) {
|
|
138
|
+
try { response.destroy(); } catch (_) {}
|
|
139
|
+
}
|
|
140
|
+
if (request) {
|
|
141
|
+
try { request.destroy(); } catch (_) {}
|
|
142
|
+
}
|
|
143
|
+
if (output) {
|
|
144
|
+
try { output.destroy(); } catch (_) {}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function failTimeout(stage) {
|
|
149
|
+
destroyStreams();
|
|
150
|
+
cleanupPartial();
|
|
151
|
+
finish(new Error(`${stage} timeout`));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function resetIdleTimer() {
|
|
155
|
+
clearTimeout(idleTimer);
|
|
156
|
+
idleTimer = setTimeout(() => failTimeout('Idle'), idleTimeoutMs);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function maybeReportProgress(force = false) {
|
|
160
|
+
const now = Date.now();
|
|
161
|
+
if (!force && now - lastProgressTime < 500) return;
|
|
162
|
+
lastProgressTime = now;
|
|
163
|
+
reportProgress(downloaded, contentLength, onProgress);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
totalTimer = setTimeout(() => failTimeout('Total'), totalTimeoutMs);
|
|
167
|
+
|
|
168
|
+
const protocol = getProtocolModule(url);
|
|
169
|
+
request = protocol.get(url, { headers: { 'User-Agent': '@zhizai/cli installer' } }, res => {
|
|
170
|
+
connected = true;
|
|
171
|
+
clearTimeout(connectTimer);
|
|
172
|
+
response = res;
|
|
173
|
+
|
|
174
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
175
|
+
res.resume();
|
|
176
|
+
destroyStreams();
|
|
177
|
+
clearTimeout(idleTimer);
|
|
178
|
+
clearTimeout(totalTimer);
|
|
179
|
+
clearTimeout(connectTimer);
|
|
180
|
+
settled = true;
|
|
181
|
+
downloadOnce(new URL(res.headers.location, url).toString(), destination, options, redirects + 1)
|
|
182
|
+
.then(resolve, reject);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (res.statusCode !== 200) {
|
|
187
|
+
res.resume();
|
|
188
|
+
destroyStreams();
|
|
189
|
+
cleanupPartial();
|
|
190
|
+
const err = new Error(`HTTP ${res.statusCode}: ${url}`);
|
|
191
|
+
err.statusCode = res.statusCode;
|
|
192
|
+
finish(err);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const lengthHeader = res.headers['content-length'];
|
|
197
|
+
if (lengthHeader != null && lengthHeader !== '') {
|
|
198
|
+
const parsed = Number(lengthHeader);
|
|
199
|
+
if (!Number.isNaN(parsed)) contentLength = parsed;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
output = fs.createWriteStream(destination, { mode: 0o600 });
|
|
203
|
+
resetIdleTimer();
|
|
204
|
+
|
|
205
|
+
res.on('data', chunk => {
|
|
206
|
+
downloaded += chunk.length;
|
|
207
|
+
resetIdleTimer();
|
|
208
|
+
maybeReportProgress();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
res.pipe(output);
|
|
212
|
+
|
|
213
|
+
output.on('finish', () => {
|
|
214
|
+
output.close(() => {
|
|
215
|
+
maybeReportProgress(true);
|
|
216
|
+
finish(null, undefined);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
output.on('error', err => {
|
|
221
|
+
destroyStreams();
|
|
222
|
+
cleanupPartial();
|
|
223
|
+
finish(err);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
res.on('error', err => {
|
|
227
|
+
destroyStreams();
|
|
228
|
+
cleanupPartial();
|
|
229
|
+
finish(err);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
connectTimer = setTimeout(() => {
|
|
234
|
+
if (!connected) failTimeout('Connect');
|
|
235
|
+
}, connectTimeoutMs);
|
|
236
|
+
|
|
237
|
+
request.on('socket', socket => {
|
|
238
|
+
socket.once('connect', () => {
|
|
239
|
+
connected = true;
|
|
240
|
+
clearTimeout(connectTimer);
|
|
241
|
+
resetIdleTimer();
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
request.on('error', err => {
|
|
246
|
+
destroyStreams();
|
|
247
|
+
cleanupPartial();
|
|
248
|
+
finish(err);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function download(url, destination, options = {}, redirects = 0) {
|
|
254
|
+
const opts = {
|
|
255
|
+
connectTimeoutMs: DEFAULT_CONNECT_TIMEOUT_MS,
|
|
256
|
+
idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
|
|
257
|
+
totalTimeoutMs: DEFAULT_TOTAL_TIMEOUT_MS,
|
|
258
|
+
retries: DEFAULT_RETRIES,
|
|
259
|
+
onProgress: null,
|
|
260
|
+
...options,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
if (redirects > 5) throw new Error('Too many redirects');
|
|
264
|
+
|
|
265
|
+
const maxRetries = opts.retries;
|
|
266
|
+
let lastError;
|
|
267
|
+
|
|
268
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
269
|
+
try {
|
|
270
|
+
return await downloadOnce(url, destination, opts, redirects);
|
|
271
|
+
} catch (err) {
|
|
272
|
+
lastError = err;
|
|
273
|
+
if (isNonRetryableError(err) || attempt >= maxRetries) throw err;
|
|
274
|
+
const delay = RETRY_BACKOFF_MS[Math.min(attempt, RETRY_BACKOFF_MS.length - 1)];
|
|
275
|
+
await sleep(delay);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
throw lastError;
|
|
280
|
+
}
|
|
281
|
+
|
|
50
282
|
async function installArchive({ platform, binDir, binaryName, binaryPath, url, tmpFile }) {
|
|
51
283
|
try {
|
|
52
284
|
await download(url, tmpFile);
|
|
@@ -60,13 +292,12 @@ async function installArchive({ platform, binDir, binaryName, binaryPath, url, t
|
|
|
60
292
|
if (!fs.existsSync(binaryPath)) {
|
|
61
293
|
throw new Error(`Binary missing after extract: ${binaryPath}`);
|
|
62
294
|
}
|
|
63
|
-
// chmod is meaningful on Unix; Windows may not need it.
|
|
64
295
|
if (platform.platform !== 'windows') {
|
|
65
296
|
fs.chmodSync(binaryPath, 0o755);
|
|
66
297
|
}
|
|
67
298
|
console.log(`zhizai installed at ${binaryPath}`);
|
|
68
299
|
} finally {
|
|
69
|
-
|
|
300
|
+
unlinkQuiet(tmpFile);
|
|
70
301
|
}
|
|
71
302
|
}
|
|
72
303
|
|
|
@@ -76,7 +307,6 @@ async function main() {
|
|
|
76
307
|
const binaryName = getBinaryName(platform);
|
|
77
308
|
const binaryPath = path.join(binDir, binaryName);
|
|
78
309
|
const url = getDownloadURL(platform);
|
|
79
|
-
// Expand-Archive on Windows requires a .zip extension; tar.gz similarly.
|
|
80
310
|
const archiveExt = platform.platform === 'windows' ? '.zip' : '.tar.gz';
|
|
81
311
|
const tmpFile = path.join(os.tmpdir(), `zhizai-download-${Date.now()}${archiveExt}`);
|
|
82
312
|
|
|
@@ -84,7 +314,7 @@ async function main() {
|
|
|
84
314
|
try {
|
|
85
315
|
const result = spawnSync(binaryPath, ['version'], { encoding: 'utf8' });
|
|
86
316
|
const out = (result.stdout || '').trim();
|
|
87
|
-
if (result.status === 0 && out
|
|
317
|
+
if (result.status === 0 && versionMatches(out, VERSION)) {
|
|
88
318
|
console.log(`zhizai v${VERSION} already installed, skipping download.`);
|
|
89
319
|
return;
|
|
90
320
|
}
|
|
@@ -104,27 +334,6 @@ function run(command, args) {
|
|
|
104
334
|
if (result.status !== 0) throw new Error(`${command} exited with status ${result.status}`);
|
|
105
335
|
}
|
|
106
336
|
|
|
107
|
-
function download(url, destination, redirects = 0) {
|
|
108
|
-
if (redirects > 5) return Promise.reject(new Error('Too many redirects'));
|
|
109
|
-
return new Promise((resolve, reject) => {
|
|
110
|
-
const request = https.get(url, { headers: { 'User-Agent': '@zhizai/cli installer' } }, response => {
|
|
111
|
-
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
112
|
-
response.resume();
|
|
113
|
-
return resolve(download(new URL(response.headers.location, url).toString(), destination, redirects + 1));
|
|
114
|
-
}
|
|
115
|
-
if (response.statusCode !== 200) {
|
|
116
|
-
response.resume();
|
|
117
|
-
return reject(new Error(`HTTP ${response.statusCode}: ${url}`));
|
|
118
|
-
}
|
|
119
|
-
const output = fs.createWriteStream(destination, { mode: 0o600 });
|
|
120
|
-
response.pipe(output);
|
|
121
|
-
output.on('finish', () => output.close(resolve));
|
|
122
|
-
output.on('error', reject);
|
|
123
|
-
});
|
|
124
|
-
request.on('error', reject);
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
337
|
async function verifyChecksum(assetURL, assetName, archivePath) {
|
|
129
338
|
const checksumPath = `${archivePath}.checksums`;
|
|
130
339
|
try {
|
|
@@ -139,10 +348,22 @@ async function verifyChecksum(assetURL, assetName, archivePath) {
|
|
|
139
348
|
const actual = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
|
|
140
349
|
if (actual !== expected) throw new Error(`Checksum mismatch for ${assetName}`);
|
|
141
350
|
} finally {
|
|
142
|
-
|
|
351
|
+
unlinkQuiet(checksumPath);
|
|
143
352
|
}
|
|
144
353
|
}
|
|
145
354
|
|
|
355
|
+
module.exports = {
|
|
356
|
+
download,
|
|
357
|
+
downloadOnce,
|
|
358
|
+
versionMatches,
|
|
359
|
+
parseVersionFromOutput,
|
|
360
|
+
getPlatform,
|
|
361
|
+
getBinaryName,
|
|
362
|
+
getDownloadURL,
|
|
363
|
+
verifyChecksum,
|
|
364
|
+
installArchive,
|
|
365
|
+
};
|
|
366
|
+
|
|
146
367
|
if (require.main === module) {
|
|
147
368
|
main().catch(err => {
|
|
148
369
|
console.error('Failed to install zhizai:', err.message);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-auth
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: 安装和连接智在记录,完成网页授权登录、环境诊断与 CLI 升级。用户说安装、连接、登录、检查为什么不能用时使用。
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -7,16 +8,20 @@ description: 安装和连接智在记录,完成网页授权登录、环境诊
|
|
|
7
8
|
|
|
8
9
|
通过官方 `zhizai` CLI 完成真实操作。机器调用优先使用 `-o json`。
|
|
9
10
|
|
|
11
|
+
**安装与升级:** 首次安装 CLI 用 `npm install -g @zhizai/cli@latest`。`zhizai setup` 默认同步 Skills 并引导授权;CLI 已可用时**不会**重复 npm 重装。需要升级或修复二进制时用 `zhizai setup --force-cli-install`。
|
|
12
|
+
|
|
10
13
|
## 路由
|
|
11
14
|
|
|
12
15
|
| 意图 | 命令 |
|
|
13
16
|
|---|---|
|
|
17
|
+
| 首次安装 CLI | `npm install -g @zhizai/cli@latest` |
|
|
14
18
|
| 登录 | `zhizai auth login` |
|
|
15
19
|
| 无头/连接器登录 | `zhizai auth login --no-open` |
|
|
16
20
|
| 查看状态 | `zhizai auth status` |
|
|
17
21
|
| 退出 | `zhizai auth logout` |
|
|
18
22
|
| 诊断 | `zhizai doctor -o json` |
|
|
19
23
|
| 能力契约 | `zhizai capabilities -o json` |
|
|
20
|
-
|
|
|
24
|
+
| 同步 Skill / 授权 | `zhizai setup` |
|
|
25
|
+
| 升级或修复 CLI | `zhizai setup --force-cli-install` |
|
|
21
26
|
|
|
22
27
|
默认使用网页设备授权。`--no-open` 时不打开浏览器,打印 `[verify_url]` / `[device_code]` / `[expires_in]` / `[interval]` 供宿主展示,后台继续轮询。仅当网页授权失败时,再提示用户使用 `zhizai auth login --api-key <key>`。
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-knowledge
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: 查询和管理智在记录笔记集。
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -13,4 +14,4 @@ description: 查询和管理智在记录笔记集。
|
|
|
13
14
|
| 集内笔记 | `zhizai knowledge notes <id> -o json` |
|
|
14
15
|
| 新建笔记集 | `zhizai knowledge create --name <名称>`(后端待开放) |
|
|
15
16
|
|
|
16
|
-
字段说明见 `skills/
|
|
17
|
+
字段说明见 `skills/zhizai-open-platform/references/knowledge.md`。
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-msg
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: 发送消息与查询录音卡使用情况。
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -9,4 +10,4 @@ description: 发送消息与查询录音卡使用情况。
|
|
|
9
10
|
|---|---|
|
|
10
11
|
| 消息与录音卡 | `zhizai msg -o json` |
|
|
11
12
|
|
|
12
|
-
字段说明见 `skills/
|
|
13
|
+
字段说明见 `skills/zhizai-open-platform/references/msg-device.md`。
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-note
|
|
3
|
-
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: 使用智在记录 CLI 查询、创建(文字)、更新和删除笔记,并查看处理进度。
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# 智在记录笔记
|
|
7
8
|
|
|
8
|
-
通过官方 `zhizai` CLI 完成真实操作。参数与字段说明见仓库内 `skills/
|
|
9
|
+
通过官方 `zhizai` CLI 完成真实操作。参数与字段说明见仓库内 `skills/zhizai-open-platform/references/note.md`。
|
|
9
10
|
|
|
10
|
-
##
|
|
11
|
+
## 已可用
|
|
11
12
|
|
|
12
13
|
| 意图 | 命令 |
|
|
13
14
|
|---|---|
|
|
14
15
|
| 笔记列表 | `zhizai notes -o json` |
|
|
15
16
|
| 笔记详情 | `zhizai note get <id> -o json` |
|
|
16
|
-
|
|
|
17
|
-
| 更新笔记 | `zhizai note update` |
|
|
18
|
-
| 删除笔记 | `zhizai note delete` |
|
|
17
|
+
| 创建文字笔记 | `zhizai note create --title <标题> --content <正文> -o json` |
|
|
18
|
+
| 更新笔记 | `zhizai note update <id> --title/--abstract/--summary -o json` |
|
|
19
|
+
| 删除笔记 | `zhizai note delete <id> --yes -o json` |
|
|
19
20
|
| 处理进度 | `zhizai note status <id> -o json` |
|
|
21
|
+
|
|
22
|
+
说明:
|
|
23
|
+
|
|
24
|
+
- `create` 当前仅支持 `--type text`(默认)。录音/文档/图片/链接依赖 `file upload`,尚未开放。
|
|
25
|
+
- `delete` 必须带 `--yes`。
|
|
26
|
+
- `update` 的 `--abstract` 对应接口字段 `abstractContent`。
|
|
27
|
+
|
|
28
|
+
## 尚未实现(勿调用)
|
|
29
|
+
|
|
30
|
+
| 意图 | 命令 |
|
|
31
|
+
|---|---|
|
|
20
32
|
| 上传文件 | `zhizai file upload <path>` |
|
|
21
|
-
| 问答总结 | `zhizai ask "<问题>"
|
|
33
|
+
| 问答总结 | `zhizai ask "<问题>"` |
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-scene
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: 查询智在记录总结场景与知识卡。
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -9,4 +10,4 @@ description: 查询智在记录总结场景与知识卡。
|
|
|
9
10
|
|---|---|
|
|
10
11
|
| 场景与知识卡 | `zhizai scene -o json` |
|
|
11
12
|
|
|
12
|
-
字段说明见 `skills/
|
|
13
|
+
字段说明见 `skills/zhizai-open-platform/references/scene.md`。
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-team
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: 管理智在记录团队与成员。
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -9,4 +10,4 @@ description: 管理智在记录团队与成员。
|
|
|
9
10
|
|---|---|
|
|
10
11
|
| 团队操作 | `zhizai team -o json` |
|
|
11
12
|
|
|
12
|
-
危险操作须先确认。字段说明见 `skills/
|
|
13
|
+
危险操作须先确认。字段说明见 `skills/zhizai-open-platform/references/team.md`。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|