@zhizai/cli 0.0.6 → 0.0.8
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 +7 -2
- package/bin/zhizai.js +22 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +247 -26
- package/skills/zhizai-ask/SKILL.md +57 -0
- package/skills/zhizai-auth/SKILL.md +9 -3
- package/skills/zhizai-knowledge/SKILL.md +37 -11
- package/skills/zhizai-msg/SKILL.md +4 -2
- package/skills/zhizai-note/SKILL.md +98 -19
- package/skills/zhizai-scene/SKILL.md +22 -7
- package/skills/zhizai-team/SKILL.md +5 -3
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 环境,并引导完成授权。
|
|
@@ -116,7 +121,7 @@ zhizai setup
|
|
|
116
121
|
| `zhizai knowledge list [--received]` | 笔记集列表(我创建的 / 收到的) |
|
|
117
122
|
| `zhizai knowledge get <id>` | 笔记集详情 |
|
|
118
123
|
| `zhizai knowledge notes <id>` | 笔记集内笔记 |
|
|
119
|
-
| `zhizai setup [--dry-run]` |
|
|
124
|
+
| `zhizai setup [--dry-run] [--force-cli-install]` | 同步原子 Skill 并引导授权;CLI 已就绪时跳过重装 |
|
|
120
125
|
|
|
121
126
|
### 规划中
|
|
122
127
|
|
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
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);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zhizai-ask
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: |
|
|
5
|
+
用 zhizai CLI 问小智语义问答(ask):在全部笔记或指定笔记集/目录/笔记范围内提问、追问、带参考文档;动态模版成文(写周报/复盘);对一段文字流式总结(summarize);按标题时间查总结和录音(recordings,人资)。
|
|
6
|
+
用户说找找关于、在某某笔记集里问、待办有哪些、追问、写周报、按模版总结本周会议、给这段话出个总结、查这个月经营会的总结和录音时使用。
|
|
7
|
+
列表过滤(最近有哪些 / 标题带…)走 zhizai-note 的 notes;禁止用 notes --title 冒充语义搜索。
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 问小智与成文(ask / summarize / recordings)
|
|
11
|
+
|
|
12
|
+
机器调用加 `-o json`。雪花 ID 当字符串。语义搜索只走 `ask`。
|
|
13
|
+
|
|
14
|
+
## ask 执行约定
|
|
15
|
+
|
|
16
|
+
- `zhizai ask "问题" -o json`:对外一次闭环,**默认自动建会话**再流式问答;返回 `chatId` / `contextId` 供追问。
|
|
17
|
+
- 追问:已有 `chatId` 时 `zhizai ask "…" --chat-id <id> --context-id <id>`,不必再建会话;建议带同一批范围 ID。
|
|
18
|
+
- 负向:`--no-session` 且未提供 `--chat-id` 时失败「请先创建问小智会话」,不要偷偷建会话。
|
|
19
|
+
- 空问题:本地失败,不调命令。
|
|
20
|
+
- 范围内无内容(空笔记集/空目录):如实返回错误原文,不编造检索结果。
|
|
21
|
+
|
|
22
|
+
## 限定范围(名称必须先查 ID)
|
|
23
|
+
|
|
24
|
+
范围优先级:目录 > 笔记集 > 笔记 > 个人全部笔记。`--dir` 需同时带所属 `--kb`。
|
|
25
|
+
|
|
26
|
+
| 用户说法 | 顺序 |
|
|
27
|
+
|---|---|
|
|
28
|
+
| 找找关于支付的笔记(不限范围) | 单步:`zhizai ask "找找关于支付的笔记" -o json`(自动建会话) |
|
|
29
|
+
| 在工作笔记集里问… | ① `zhizai kb list` 匹配得 `knowledgeId` ② `zhizai ask "…" --kb <knowledgeId> -o json` |
|
|
30
|
+
| 只问某目录 | ① `kb list` 得 `knowledgeId` ② `kb catalog --kb <id>` 匹配得 `directoryId` ③ `ask "…" --kb <knowledgeId> --dir <directoryId>`(检索该目录及子目录) |
|
|
31
|
+
| 就那条某某纪要,待办有哪些 | ① `notes --title …` 得 `noteId`(会话已有则跳过)② `ask "待办有哪些" --note <noteId>` |
|
|
32
|
+
| 这几条一起问 | 每条先查真实 ID,再 `ask "…" --note <id1> --note <id2>`(或 `--note-ids <id1,id2>` / 多个 `--kb`) |
|
|
33
|
+
| 带参考文档 | `ask "…" --with-references`;引用详情用 `zhizai ask refs --doc-ids 1,2 --context-id <id>` |
|
|
34
|
+
|
|
35
|
+
查不到名称则停;禁止把名称当 `--kb` / `--dir` / `--note`。需要显式分步时:`ask session [--kb/--dir/--note]` 先建会话,再 `ask chat "…" --chat-id <id> --context-id <id>`。
|
|
36
|
+
|
|
37
|
+
## 动态模版成文(写周报 / 复盘)
|
|
38
|
+
|
|
39
|
+
「按周报结构总结本周会议」走模版管线,**不是问小智,也不是某条笔记的 summary**:
|
|
40
|
+
|
|
41
|
+
1. `zhizai ask template "生成周报" --with-notes --start "2026-09-21 00:00:00" --end "2026-09-27 23:59:59" -o json`
|
|
42
|
+
2. CLI 只返回模版与笔记 JSON,**不调用 LLM 成文**;由你按模版结构填真实笔记。
|
|
43
|
+
3. 模版要求但笔记里没有的字段标「未提及」,禁止编造。
|
|
44
|
+
|
|
45
|
+
## summarize(文字流式总结)
|
|
46
|
+
|
|
47
|
+
用户给了一段文字要总结(不是某条笔记、不是问答):
|
|
48
|
+
|
|
49
|
+
- `zhizai summarize --content "…" -o json`;点名场景时先查真实 `sceneId`(见 zhizai-scene)再加 `--scene-id`。
|
|
50
|
+
- 流式输出结束即完成。
|
|
51
|
+
|
|
52
|
+
## recordings(人资查询)
|
|
53
|
+
|
|
54
|
+
「查这个月经营会的总结和录音」:
|
|
55
|
+
|
|
56
|
+
- `zhizai recordings --title 经营 --start "2026-09-01 00:00:00" --end "2026-09-30 23:59:59" -o json`(`--from` / `--to` 为别名)。
|
|
57
|
+
- 返回笔记列表;用户要打开某一条时再 `note get <id>`(变成组合,见 zhizai-note)。
|
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-auth
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.1
|
|
4
4
|
description: 安装和连接智在记录,完成网页授权登录、环境诊断与 CLI 升级。用户说安装、连接、登录、检查为什么不能用时使用。
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# 智在记录连接与诊断
|
|
8
8
|
|
|
9
|
-
通过官方 `zhizai` CLI 完成真实操作。机器调用优先使用 `-o json
|
|
9
|
+
通过官方 `zhizai` CLI 完成真实操作。机器调用优先使用 `-o json`。登录后的业务操作(笔记/笔记集/场景/问小智)分别走 zhizai-note、zhizai-knowledge、zhizai-scene、zhizai-ask。
|
|
10
|
+
|
|
11
|
+
**安装与升级:** 首次安装 CLI 用 `npm install -g @zhizai/cli@latest`。`zhizai setup` 默认同步 Skills 并引导授权;CLI 已可用时**不会**重复 npm 重装。需要升级或修复二进制时用 `zhizai setup --force-cli-install`。
|
|
10
12
|
|
|
11
13
|
## 路由
|
|
12
14
|
|
|
13
15
|
| 意图 | 命令 |
|
|
14
16
|
|---|---|
|
|
17
|
+
| 首次安装 CLI | `npm install -g @zhizai/cli@latest` |
|
|
15
18
|
| 登录 | `zhizai auth login` |
|
|
16
19
|
| 无头/连接器登录 | `zhizai auth login --no-open` |
|
|
17
20
|
| 查看状态 | `zhizai auth status` |
|
|
18
21
|
| 退出 | `zhizai auth logout` |
|
|
19
22
|
| 诊断 | `zhizai doctor -o json` |
|
|
20
23
|
| 能力契约 | `zhizai capabilities -o json` |
|
|
21
|
-
|
|
|
24
|
+
| 同步 Skill / 授权 | `zhizai setup` |
|
|
25
|
+
| 升级或修复 CLI | `zhizai setup --force-cli-install` |
|
|
22
26
|
|
|
23
27
|
默认使用网页设备授权。`--no-open` 时不打开浏览器,打印 `[verify_url]` / `[device_code]` / `[expires_in]` / `[interval]` 供宿主展示,后台继续轮询。仅当网页授权失败时,再提示用户使用 `zhizai auth login --api-key <key>`。
|
|
28
|
+
|
|
29
|
+
未登录/未配置时:只提示登录或配置,不调业务命令;不要回显完整 Key。`zhizai doctor` 可探活连通性。
|
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-knowledge
|
|
3
|
-
version:
|
|
4
|
-
description:
|
|
3
|
+
version: 2.0.0
|
|
4
|
+
description: |
|
|
5
|
+
用 zhizai CLI 管理笔记集(knowledge,别名 kb):列出我创建的/收到的笔记集、打开笔记集与目录、新建笔记集、建目录、把笔记移入目录、删目录。
|
|
6
|
+
用户说我的笔记集、我收到的笔记集、打开某某笔记集、新建笔记集、建目录、把这条笔记放到某某笔记集、删掉目录时使用。
|
|
7
|
+
名称必须先查 ID 再操作;保存时归档(save --kb)见 zhizai-note。
|
|
5
8
|
---
|
|
6
9
|
|
|
7
|
-
#
|
|
10
|
+
# 智在记录笔记集(kb)
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|---|---|
|
|
11
|
-
| 我创建的笔记集 | `zhizai knowledge list -o json` |
|
|
12
|
-
| 我收到的笔记集 | `zhizai knowledge list --received -o json` |
|
|
13
|
-
| 笔记集详情 | `zhizai knowledge get <id> -o json` |
|
|
14
|
-
| 集内笔记 | `zhizai knowledge notes <id> -o json` |
|
|
15
|
-
| 新建笔记集 | `zhizai knowledge create --name <名称>`(后端待开放) |
|
|
12
|
+
`knowledge` 别名 `kb`,以下统一写 `kb`。机器调用加 `-o json`。雪花 ID 当字符串。
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
## 名称 → ID(写操作前必须完成)
|
|
15
|
+
|
|
16
|
+
| 用户说的 | 先执行 | 得到 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| 笔记集名称 | `zhizai kb list -o json`(别人分享的再 `kb shared`),按名称匹配 | `knowledgeId` |
|
|
19
|
+
| 目录名称 | 先有 `knowledgeId`,再 `zhizai kb catalog --kb <knowledgeId> -o json`,按目录名匹配 | `directoryId`(即 `catalogId`) |
|
|
20
|
+
|
|
21
|
+
零条停、多条让用户选。禁止把名称当 ID、禁止编造 ID。会话里本轮已拿到的 ID 可直接用。
|
|
22
|
+
|
|
23
|
+
## 命令与组合
|
|
24
|
+
|
|
25
|
+
| 用户说法 | 执行 | 顺序 |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| 我的笔记集 | 单步 | `zhizai kb list -o json`。空列表是成功 |
|
|
28
|
+
| 我收到的笔记集 | 单步 | `zhizai kb shared -o json`(等价 `kb list --received`) |
|
|
29
|
+
| 打开某某笔记集 | 组合 2 步 | ① `kb list` 匹配名称 ② `zhizai kb get <knowledgeId>` 或 `kb notes <knowledgeId>` |
|
|
30
|
+
| 看某目录里的笔记 | 组合 3 步 | ① `kb list` ② `kb catalog --kb <id>` 匹配目录 ③ `kb notes <id> --dir <directoryId>` |
|
|
31
|
+
| 新建笔记集 | 单步 | `zhizai kb create --name "工作笔记集" [--detail "…"]`,返回新 `knowledgeId` |
|
|
32
|
+
| 建目录 | 组合 2 步 | ① `kb list` 匹配笔记集 ② `zhizai kb mkdir --kb <knowledgeId> --name "三季度会议" [--parent <父目录Id>]`;不传 `--parent` 或传 `-1` 表示根层。父目录也是名称时先 `kb catalog` 匹配 |
|
|
33
|
+
| 移笔记到目录 | 组合 3~4 步 | ① 查 `noteId`(会话没有则 `notes --title`)② `kb list` 得 `knowledgeId` ③ 点目录则 `kb catalog` 得 `directoryId` ④ `zhizai kb add --kb <knowledgeId> --note-id <noteId> [--dir <directoryId>]` |
|
|
34
|
+
| 批量移笔记 | 组合 3~4 步 | 每条笔记都先查到真实 `noteId`,再一次 `kb add --kb <id> --note-ids <id1,id2> [--dir …]`;指定目录时只能对着一个笔记集 |
|
|
35
|
+
| 移到笔记集根层 | 组合 2~3 步 | ① 查 `noteId` ② 查 `knowledgeId` ③ `kb add --kb <knowledgeId> --note-id <noteId>`(不传 `--dir`) |
|
|
36
|
+
| 删目录 | 组合 2~3 步 | ① 不知在哪个集则 `kb list` 再 `kb catalog --kb <id>` 匹配目录 ② 用户确认 ③ `zhizai kb rmdir <directoryId> --yes` |
|
|
37
|
+
|
|
38
|
+
## 边界
|
|
39
|
+
|
|
40
|
+
- `kb add`:未入集则新增关联;已在集内则改目录;不删笔记正文。已在目标目录可能失败「没有需要添加的笔记」。
|
|
41
|
+
- `kb rmdir`:必须 `--yes`;级联去掉子目录与笔记**关联**,不删笔记正文。未确认不删。
|
|
42
|
+
- 目录不存在、父目录无效:如实报「目录不存在」类错误,不假装已建/已删。
|
|
43
|
+
- 保存时归档用 `save --kb [--dir]`(见 zhizai-note);`--kb` 无效时笔记可能已创建但未归档,须拆开说「已创建但未归档」。
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-msg
|
|
3
|
-
version: 1.0.
|
|
4
|
-
description:
|
|
3
|
+
version: 1.0.1
|
|
4
|
+
description: 发送消息与查询录音卡使用情况。注意:本次 CLI 场景测试不包含消息/录音卡能力,命令保留占位。
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# 智在记录消息与录音卡
|
|
8
8
|
|
|
9
|
+
> **范围说明:本次场景测试不包含团队/消息/录音卡用例。** 以下命令保留占位,场景测试中勿用;发消息前须确认,展示手机号须脱敏。
|
|
10
|
+
|
|
9
11
|
| 意图 | 命令 |
|
|
10
12
|
|---|---|
|
|
11
13
|
| 消息与录音卡 | `zhizai msg -o json` |
|
|
@@ -1,33 +1,112 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-note
|
|
3
|
-
version:
|
|
4
|
-
description:
|
|
3
|
+
version: 2.0.0
|
|
4
|
+
description: |
|
|
5
|
+
用 zhizai CLI 做笔记:把录音/文档/图片/链接/文字做成笔记(save 自动判型)、只上传文件、列表过滤、打开详情/纪要/原文、改标题/摘要/总结、删除、等处理完成、下载音频。
|
|
6
|
+
用户说做成笔记、记一条、收藏链接、上传文件、最近有哪些、打开这条、只要转写/纪要、改标题、删掉、等它处理完、下载音频时使用。
|
|
7
|
+
语义搜索「找找关于…」走 zhizai-ask;笔记集归档走 zhizai-knowledge;场景名查 ID 走 zhizai-scene。
|
|
5
8
|
---
|
|
6
9
|
|
|
7
|
-
#
|
|
10
|
+
# 智在记录笔记(save / file / notes / note)
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
只通过 `zhizai` CLI 操作,禁止直调开放 API。机器调用一律加 `-o json`。雪花 ID 全程当字符串传递。
|
|
10
13
|
|
|
11
|
-
##
|
|
14
|
+
## 执行约定(必须先读)
|
|
12
15
|
|
|
13
|
-
|
|
|
16
|
+
| 标记 | 怎么做 |
|
|
17
|
+
|---|---|
|
|
18
|
+
| 单步 | 一条 CLI 闭环(如 `notes`、`file upload`)。 |
|
|
19
|
+
| 单步(内部多接口) | 对外仍一条 `save`:内部上传+创建,`--wait` 再轮询。**不要**拆成 `file upload` + 创建 + `note wait` 三步。 |
|
|
20
|
+
| 组合 N 步 | 必须按 ①②③ 做完,缺一步即错;中途失败即停,不跳步、不猜 ID。 |
|
|
21
|
+
| 附加参数 | 不能单独执行,必须并进同一条 `save`。 |
|
|
22
|
+
|
|
23
|
+
**会话里已有的 ID 才能跳过查询。** 用户只说名称/标题而会话没有对应 ID,必须先查。禁止把名称当 ID,禁止编造雪花 ID。
|
|
24
|
+
|
|
25
|
+
名称 → ID:
|
|
26
|
+
|
|
27
|
+
| 用户说的 | 先执行 | 得到 |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| 笔记 / 「这条纪要」/ 标题 | `zhizai notes --title … -o json`,零条停、多条让用户选 | `noteId` |
|
|
30
|
+
| 笔记集名称 | `zhizai kb list`(别人分享的再 `kb shared`),按名称匹配 | `knowledgeId`(见 zhizai-knowledge) |
|
|
31
|
+
| 目录名称 | 先有 `knowledgeId`,再 `zhizai kb catalog --kb <id>` 按名称匹配 | `directoryId` |
|
|
32
|
+
| 总结场景名称 | `zhizai scene list` 或 `scene builtins`,按名称匹配 | `sceneId`(见 zhizai-scene) |
|
|
33
|
+
|
|
34
|
+
创建成功 ≠ 转写/总结完成。`save` 成功最低标准是非空 `noteId`;只有 `completed`(或用户明确说不用等)才能宣称完成。
|
|
35
|
+
|
|
36
|
+
## 意图分流(不要混用)
|
|
37
|
+
|
|
38
|
+
| 用户说法 | 走哪条 | 不要走 |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| 最近有哪些 / 我的录音 / 标题带经营分析 / 这个月的 | `notes` 列表过滤 | ask(列表过滤不是语义搜索) |
|
|
41
|
+
| 找找关于… / 待办有哪些(语义问答) | **zhizai-ask** 的 `ask` | 用 `notes --title` 冒充语义搜索 |
|
|
42
|
+
| 做成笔记 / 记一条 / 收藏链接 / 把文件生成笔记 | `save` 一条闭环 | 只 `file upload` 就停;追问「这是录音还是文档」 |
|
|
43
|
+
| 只上传、不做成笔记 | `file upload` | `save` |
|
|
44
|
+
| 打开这条 / 看纪要 / 只要原文 | 无 ID 先 `notes --title` 选定,再 `note get` | 把 summary 当原文 |
|
|
45
|
+
| 改标题/摘要/总结、删除、下载音频 | 无 ID 先查,再 `note update/delete/audio` | 没有 `noteId` 就调用 |
|
|
46
|
+
| 等它处理完 | `note wait`,仅 `completed` 后再 `note get` | 失败自动再 `save` |
|
|
47
|
+
| 给这段话出个总结(用户给了文字) | `zhizai summarize`(见 zhizai-ask) | ask;某条笔记的 `--field summary` |
|
|
48
|
+
|
|
49
|
+
## save 判型(用户没点名类型时必须用这套,不要追问)
|
|
50
|
+
|
|
51
|
+
| 用户给了什么 | 判定 | 命令 |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| 音频 mp3/wav/m4a/aac/ogg/flac/amr/opus | 录音 | `save <file> --wait`;途径默认 offlineImport,不要追问 |
|
|
54
|
+
| 图片 jpg/jpeg/png/gif/webp/bmp/heic | 图片 | 多图合成一条:`save a.jpg b.png --wait` |
|
|
55
|
+
| 文档 pdf/doc/docx/ppt/pptx/xls/xlsx/txt/md | 文档 | `save <file> --wait`;`--title` 优先于文件名 |
|
|
56
|
+
| `http(s)://` URL | 链接 | `save <url>` |
|
|
57
|
+
| 只有文字 | 文字 | `save --title … --content …`;长文用 `--content-file` / `--stdin` |
|
|
58
|
+
| 一份音频 + 若干图片且说「附图/一起保存」 | 录音带附图 | `save a.mp3 --image p1.jpg --image p2.png --wait` |
|
|
59
|
+
| 视频 mp4/mov/avi/mkv/webm/m4v | **不能做成笔记** | 停并说明;用户只要「上传」则 `file upload`。禁止当成录音 |
|
|
60
|
+
| 无法识别的扩展名 | 不创建 | 列出可支持格式(录音/文档/图片/链接/文字),不猜测 |
|
|
61
|
+
|
|
62
|
+
录音/图片/文档默认 `--wait`(已默认开启);用户说不用等则 `--no-wait`,立即返回 `noteId` 与 `note_state`,之后要结果再 `note wait`。
|
|
63
|
+
|
|
64
|
+
## save 附加参数(并进同一条 save,不单独执行)
|
|
65
|
+
|
|
66
|
+
| 用户说法 | 加进同一条 save |
|
|
14
67
|
|---|---|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
68
|
+
| 从 14:00 录到 14:30,时长 30 分钟 | `--start "2026-09-18 14:00:00" --end "2026-09-18 14:30:00" --duration 1800`(**录制**时间,不是会议排期) |
|
|
69
|
+
| 手机内录 / 实时录音 / 录音卡 | `--source phoneInternal\|realtime\|recordingCard`(仅用户明确指定才传,默认 offlineImport) |
|
|
70
|
+
| 定位在广州 | `--lat 23.1291 --lng 113.2644` |
|
|
71
|
+
| 再记一句备注 | `--text "会后跟进渠道下沉"`(随手备注,不等于 AI 总结) |
|
|
72
|
+
| 图片备注 | `--remark "白板"` |
|
|
73
|
+
| 已有 fileId 跳过上传 | `--file-id <fileId>`(单文件类型) |
|
|
74
|
+
| 用某某场景 | 先查 `sceneId`,再加 `--scene-id <id>` |
|
|
75
|
+
| 放到某笔记集/目录 | 先查 ID,再加 `--kb <knowledgeId> [--dir <directoryId>]` |
|
|
76
|
+
| 追加到刚才那条会 | 先定 `noteId`,再加 `--append-to <noteId>` |
|
|
21
77
|
|
|
22
|
-
|
|
78
|
+
## 哪些必须组合(缺步即错)
|
|
23
79
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
80
|
+
| 用户说法 | 顺序 |
|
|
81
|
+
|---|---|
|
|
82
|
+
| 用会议纪要场景做笔记 | ① `scene list`/`scene builtins` 查 `sceneId` ② `save … --scene-id --wait` |
|
|
83
|
+
| 放到工作笔记集再保存 | ① `kb list` 查 `knowledgeId`(② 点目录再 `kb catalog` 查 `directoryId`)③ `save … --kb [--dir] --wait` |
|
|
84
|
+
| 打开/纪要/原文/短链/改/删/下音频(没给 ID) | ① `notes --title` 选定 ② `note get/update/delete/audio …` |
|
|
85
|
+
| 改标题后再确认 | ① `note update <id> --title …` ② `note get <id>` 读回 |
|
|
86
|
+
| 追加到刚才那条会(无 noteId) | ① `notes --title` 选定 ② `save … --append-to <id> --wait`(不要另存新笔记) |
|
|
87
|
+
| 上次那条还在转,好了叫我 | ① `note wait <id>` ② 仅 `completed` 后 `note get <id>` |
|
|
27
88
|
|
|
28
|
-
##
|
|
89
|
+
## 命令速查
|
|
29
90
|
|
|
30
91
|
| 意图 | 命令 |
|
|
31
92
|
|---|---|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
93
|
+
| 做成笔记 | `zhizai save <文件\|URL>... [--title …] [--wait] -o json` |
|
|
94
|
+
| 文字笔记 | `zhizai save --title … --content …`(或 `note create --title … --content …`,仅 text) |
|
|
95
|
+
| 只上传 | `zhizai file upload <path> [--compress] -o json`(音频不建议 `--compress`) |
|
|
96
|
+
| 按 fileId 下载 | `zhizai file get <fileId> --out <path>`(`-o` 是输出格式,下载路径用 `--out`) |
|
|
97
|
+
| 列表 | `zhizai notes [--title/--type/--abstract/--summary/--content …] [--from … --to …] [--page --limit \| --all] [--with-content] [--with-short-url] -o json` |
|
|
98
|
+
| 详情 | `zhizai note get <id> [--field content\|summary\|abstract\|…] [--short-url] [--with-append]` |
|
|
99
|
+
| 进度 / 等待 | `zhizai note status <id>` / `zhizai note wait <id>` |
|
|
100
|
+
| 改 | `zhizai note update <id> [--title --abstract --summary]`(只改传入字段) |
|
|
101
|
+
| 删 | `zhizai note delete <id> --yes` |
|
|
102
|
+
| 下载录音 | `zhizai note audio <id> --out ./a.mp3`(非录音笔记会失败;只有 fileId 走 `file get`) |
|
|
103
|
+
|
|
104
|
+
## 错误边界
|
|
105
|
+
|
|
106
|
+
- 本地路径不存在:不执行 `save` / `file upload`。
|
|
107
|
+
- 空列表是成功:「没有符合条件的笔记」。
|
|
108
|
+
- 删除、覆盖性修改先确认;未 `--yes` 不删。无权限/不存在不能说已删。
|
|
109
|
+
- `note wait` 得到 `failed`:展示状态与原因,**禁止自动再 `save`**。
|
|
110
|
+
- `--kb` 无效:笔记可能已创建但未归档,必须拆开说「已创建但未归档」。
|
|
111
|
+
- 处理中(`recognizing`/`analyzing`)如实说明;不把 summary 冒充原文,不假装完成。
|
|
112
|
+
- 用户没要分享时,不主动加 `--short-url` / `--with-short-url`。
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-scene
|
|
3
|
-
version:
|
|
4
|
-
description:
|
|
3
|
+
version: 2.0.0
|
|
4
|
+
description: |
|
|
5
|
+
用 zhizai CLI 查询总结场景与知识卡:内置场景、我的场景(含共享)、我创建的知识卡。
|
|
6
|
+
用户说有哪些总结场景、我的场景、我的知识卡,或「用某某场景」做笔记/总结前需要查 sceneId 时使用。
|
|
5
7
|
---
|
|
6
8
|
|
|
7
|
-
#
|
|
9
|
+
# 智在记录场景与知识卡(scene / cards)
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|---|---|
|
|
11
|
-
| 场景与知识卡 | `zhizai scene -o json` |
|
|
11
|
+
机器调用加 `-o json`。`sceneId` 当字符串。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## 命令
|
|
14
|
+
|
|
15
|
+
| 用户说法 | 命令 | 说明 |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| 有哪些总结场景 | `zhizai scene builtins -o json` | 内置/平台场景。**返回是按分类分组的 Map**,必须遍历各分类数组取 `id` / `scene_name`,不要当普通 list(否则得到 0 条) |
|
|
18
|
+
| 我的场景 | `zhizai scene list -o json` | 默认含共享场景(`--include-shared=false` 关闭)。空列表是成功 |
|
|
19
|
+
| 我的知识卡 | `zhizai cards [--page 1 --limit 10] -o json` | 等价 `zhizai scene cards`。分页列表,空列表是成功 |
|
|
20
|
+
|
|
21
|
+
## 名称 → sceneId
|
|
22
|
+
|
|
23
|
+
用户说「用会议纪要场景…」时,场景名不能直接用:
|
|
24
|
+
|
|
25
|
+
1. `zhizai scene builtins -o json`(或 `scene list`)按名称匹配,得真实 `sceneId`。
|
|
26
|
+
2. 再把 `sceneId` 传给 `save --scene-id`(做成笔记,见 zhizai-note)或 `summarize --scene-id`(文字总结,见 zhizai-ask)。
|
|
27
|
+
|
|
28
|
+
禁止把场景名当 `--scene-id`;查不到则停,不要空传。无效场景会导致创建失败。
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zhizai-team
|
|
3
|
-
version: 1.0.
|
|
4
|
-
description:
|
|
3
|
+
version: 1.0.1
|
|
4
|
+
description: 管理智在记录团队与成员。注意:本次 CLI 场景测试不包含团队能力,命令保留占位。
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# 智在记录团队
|
|
8
8
|
|
|
9
|
+
> **范围说明:本次场景测试不包含团队/消息/录音卡用例。** 以下命令保留占位,场景测试中勿用;真实团队操作前须先确认。
|
|
10
|
+
|
|
9
11
|
| 意图 | 命令 |
|
|
10
12
|
|---|---|
|
|
11
13
|
| 团队操作 | `zhizai team -o json` |
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
危险操作(新建/改删团队)须先确认。字段说明见 `skills/zhizai-open-platform/references/team.md`。
|