@9000ai/cli 0.5.4 → 0.5.5
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/CHANGELOG.md +7 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +19 -0
- package/dist/commands/monitor.js +2 -1
- package/dist/commands/search.js +4 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/skills/9000AI-hub/SKILL.md +2 -1
- package/skills/douyin-monitor/SKILL.md +6 -3
- package/skills/douyin-topic-discovery/SKILL.md +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## What's new in v0.5.5
|
|
2
|
+
|
|
3
|
+
- `--format csv` — search keyword, batch-result, monitor fetch 均支持 CSV 输出,省 token
|
|
4
|
+
- `--skills-path` — `config set --skills-path <dir>` 自定义 skills 安装路径
|
|
5
|
+
- `9000ai update --path <dir>` — 指定 skills 同步目标路径
|
|
6
|
+
- 统一字段名:monitor fetch 返回 `desc`/`create_time`(与 search 一致)
|
|
7
|
+
|
|
1
8
|
## What's new in v0.5.3
|
|
2
9
|
|
|
3
10
|
- `9000ai update` — sync skills after npm update, shows what changed
|
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -64,6 +64,25 @@ export async function pollUntilDone(path, opts) {
|
|
|
64
64
|
}
|
|
65
65
|
export function printJson(data, opts) {
|
|
66
66
|
let output = data;
|
|
67
|
+
// --format csv: extract items array, pick fields, output as CSV
|
|
68
|
+
if (opts?.format === "csv") {
|
|
69
|
+
const arr = extractArray(output);
|
|
70
|
+
if (arr && arr.length > 0) {
|
|
71
|
+
const fieldList = opts.fields
|
|
72
|
+
? opts.fields.split(",").map((f) => f.trim())
|
|
73
|
+
: Object.keys(arr[0]);
|
|
74
|
+
const picked = arr.map((item) => pick(item, fieldList));
|
|
75
|
+
const header = fieldList.join(",");
|
|
76
|
+
const lines = picked.map((row) => fieldList.map((k) => {
|
|
77
|
+
const v = String(row[k] ?? "");
|
|
78
|
+
return v.includes(",") || v.includes('"') || v.includes("\n")
|
|
79
|
+
? `"${v.replace(/"/g, '""')}"`
|
|
80
|
+
: v;
|
|
81
|
+
}).join(","));
|
|
82
|
+
console.log([header, ...lines].join("\n"));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
67
86
|
// --fields: extract specified fields from items/data
|
|
68
87
|
if (opts?.fields) {
|
|
69
88
|
const fieldList = opts.fields.split(",").map((f) => f.trim());
|
package/dist/commands/monitor.js
CHANGED
|
@@ -110,6 +110,7 @@ export function registerMonitorCommands(parent) {
|
|
|
110
110
|
.requiredOption("--sec-user <id>", "User sec_user_id or homepage URL")
|
|
111
111
|
.option("--count <n>", "Number of videos to fetch", "20")
|
|
112
112
|
.option("--sort <n>", "Sort: 0=newest 1=hottest", "0")
|
|
113
|
+
.option("--format <fmt>", "Output format: csv|json", "json")
|
|
113
114
|
.option("--fields <list>", "Comma-separated fields to extract")
|
|
114
115
|
.option("--compact", "One JSON object per line")
|
|
115
116
|
.action(async (opts) => {
|
|
@@ -119,6 +120,6 @@ export function registerMonitorCommands(parent) {
|
|
|
119
120
|
sort_type: opts.sort,
|
|
120
121
|
});
|
|
121
122
|
const data = await request({ method: "GET", path: `/api/v1/douyin/monitor/user-posts?${params}` });
|
|
122
|
-
printJson(data, { fields: opts.fields, compact: opts.compact });
|
|
123
|
+
printJson(data, { fields: opts.fields, compact: opts.compact, format: opts.format });
|
|
123
124
|
});
|
|
124
125
|
}
|
package/dist/commands/search.js
CHANGED
|
@@ -68,6 +68,7 @@ export function registerSearchCommands(parent) {
|
|
|
68
68
|
.option("--min-likes <n>", "Minimum likes", "0")
|
|
69
69
|
.option("--min-comments <n>", "Minimum comments", "0")
|
|
70
70
|
.option("--wait", "Poll until batch completes then print results")
|
|
71
|
+
.option("--format <fmt>", "Output format: csv|json", "json")
|
|
71
72
|
.option("--fields <list>", "Comma-separated fields to extract (used with --wait)")
|
|
72
73
|
.option("--compact", "One JSON object per line (used with --wait)")
|
|
73
74
|
.action(async (keywords, opts) => {
|
|
@@ -114,12 +115,13 @@ export function registerSearchCommands(parent) {
|
|
|
114
115
|
writeTsv(`latest_search_${slug}.tsv`, items);
|
|
115
116
|
console.error(`${items.length} items → output/latest_search.json`);
|
|
116
117
|
}
|
|
117
|
-
printJson(resultInner, { fields: opts.fields, compact: opts.compact });
|
|
118
|
+
printJson(resultInner, { fields: opts.fields, compact: opts.compact, format: opts.format });
|
|
118
119
|
});
|
|
119
120
|
cmd
|
|
120
121
|
.command("batch-result")
|
|
121
122
|
.description("Query async search batch results")
|
|
122
123
|
.requiredOption("--batch-id <id>", "Batch ID")
|
|
124
|
+
.option("--format <fmt>", "Output format: csv|json", "json")
|
|
123
125
|
.option("--fields <list>", "Comma-separated fields to extract (e.g. desc,author_name,likes,video_url)")
|
|
124
126
|
.option("--compact", "One JSON object per line, no indentation")
|
|
125
127
|
.action(async (opts) => {
|
|
@@ -138,7 +140,7 @@ export function registerSearchCommands(parent) {
|
|
|
138
140
|
writeTsv(`latest_search_${slug}.tsv`, items);
|
|
139
141
|
console.log(`${items.length} items → output/latest_search.json`);
|
|
140
142
|
}
|
|
141
|
-
printJson(inner, { fields: opts.fields, compact: opts.compact });
|
|
143
|
+
printJson(inner, { fields: opts.fields, compact: opts.compact, format: opts.format });
|
|
142
144
|
});
|
|
143
145
|
cmd
|
|
144
146
|
.command("zhihu-hot")
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ const program = new Command();
|
|
|
14
14
|
program
|
|
15
15
|
.name("9000ai")
|
|
16
16
|
.description("9000AI Toolbox CLI — unified interface for 9000AI platform")
|
|
17
|
-
.version("0.5.
|
|
17
|
+
.version("0.5.5");
|
|
18
18
|
registerConfigCommands(program);
|
|
19
19
|
registerAuthCommands(program);
|
|
20
20
|
registerSearchCommands(program);
|
package/package.json
CHANGED
|
@@ -25,10 +25,11 @@ output-format: routing-only
|
|
|
25
25
|
2. **异步任务用 `--wait`。** 搜索和转写加 `--wait`,一条命令拿到最终结果
|
|
26
26
|
3. **有依赖的操作串行。** 上一步输出是下一步输入时,必须等
|
|
27
27
|
4. **用 `--fields` 只取需要的字段。** 永远不要全量读取
|
|
28
|
+
5. **列表数据用 `--format csv`。** 比 JSON 省 token,适合视频列表、搜索结果等
|
|
28
29
|
|
|
29
30
|
```bash
|
|
30
31
|
# 单任务
|
|
31
|
-
9000ai search keyword "美食探店" --wait --fields desc,likes,author_name
|
|
32
|
+
9000ai search keyword "美食探店" --wait --format csv --fields desc,likes,author_name
|
|
32
33
|
|
|
33
34
|
# 多数据源并行
|
|
34
35
|
并行 {
|
|
@@ -99,7 +99,7 @@ output-format: task-oriented
|
|
|
99
99
|
9000ai config set --base-url http://127.0.0.1:8025 --api-key <key>
|
|
100
100
|
9000ai auth whoami
|
|
101
101
|
9000ai auth capabilities
|
|
102
|
-
9000ai monitor fetch --sec-user <sec_user_id> --fields
|
|
102
|
+
9000ai monitor fetch --sec-user <sec_user_id> --fields desc,likes,comments,plays
|
|
103
103
|
9000ai monitor list-creators
|
|
104
104
|
9000ai monitor create-creator --json-file creator.json
|
|
105
105
|
9000ai monitor update-creator --creator-id <creator_id> --json-file creator_update.json
|
|
@@ -118,7 +118,7 @@ output-format: task-oriented
|
|
|
118
118
|
|
|
119
119
|
### 数据精简
|
|
120
120
|
|
|
121
|
-
任务结果和监控详情都支持 `--fields` 和 `--
|
|
121
|
+
任务结果和监控详情都支持 `--fields`、`--compact` 和 `--format csv`。**默认必须用 `--fields` 只取需要的字段,禁止全量读取。**
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
# 错误 — 返回全量 JSON,浪费上下文
|
|
@@ -127,7 +127,10 @@ output-format: task-oriented
|
|
|
127
127
|
# 正确 — 只取监控摘要字段
|
|
128
128
|
9000ai task results --task-id <id> --fields desc,author_name,likes,comments,create_time
|
|
129
129
|
|
|
130
|
-
#
|
|
130
|
+
# CSV 格式 — 省 token,适合列表数据
|
|
131
|
+
9000ai monitor fetch --sec-user <id> --format csv --fields desc,likes,shares,create_time
|
|
132
|
+
|
|
133
|
+
# 更紧凑 — 每条一行 JSON
|
|
131
134
|
9000ai task results --task-id <id> --fields desc,author_name,likes --compact
|
|
132
135
|
```
|
|
133
136
|
|
|
@@ -145,7 +145,7 @@ output/
|
|
|
145
145
|
|
|
146
146
|
### 数据精简
|
|
147
147
|
|
|
148
|
-
搜索结果和任务结果都支持 `--fields` 和 `--
|
|
148
|
+
搜索结果和任务结果都支持 `--fields`、`--compact` 和 `--format csv`。**默认必须用 `--fields` 只取需要的字段,禁止全量读取。**
|
|
149
149
|
|
|
150
150
|
```bash
|
|
151
151
|
# 错误 — 返回全量 JSON,浪费上下文
|
|
@@ -154,7 +154,10 @@ output/
|
|
|
154
154
|
# 正确 — 只取选题需要的字段
|
|
155
155
|
9000ai search batch-result --batch-id <id> --fields desc,author_name,likes,duration
|
|
156
156
|
|
|
157
|
-
#
|
|
157
|
+
# CSV 格式 — 省 token,适合列表数据
|
|
158
|
+
9000ai search keyword "美食探店" --wait --format csv --fields desc,author_name,author_sec_uid,likes
|
|
159
|
+
|
|
160
|
+
# 更紧凑 — 每条一行 JSON
|
|
158
161
|
9000ai search batch-result --batch-id <id> --fields desc,author_name,likes --compact
|
|
159
162
|
```
|
|
160
163
|
|