siluzan-cso-cli 1.1.18-beta.4 → 1.1.18-beta.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/README.md +1 -1
- package/dist/index.js +124 -63
- package/dist/skill/SKILL.md +51 -44
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/rag.md +42 -22
- package/dist/skill/references/setup.md +13 -13
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ siluzan-cso init -d /path/to/skills # 写入自定义目录
|
|
|
54
54
|
siluzan-cso init --force # 强制覆盖已存在文件
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
> **注意**:当前为测试版(1.1.18-beta.
|
|
57
|
+
> **注意**:当前为测试版(1.1.18-beta.5),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-cso-cli`。
|
|
58
58
|
|
|
59
59
|
| 助手 | 建议 `--ai` |
|
|
60
60
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -1948,6 +1948,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
1948
1948
|
import * as fs2 from "fs";
|
|
1949
1949
|
import * as path2 from "path";
|
|
1950
1950
|
import { fileURLToPath } from "url";
|
|
1951
|
+
import { spawn } from "child_process";
|
|
1951
1952
|
import Table from "cli-table3";
|
|
1952
1953
|
var SILUZAN_DIR = path.join(os.homedir(), ".siluzan");
|
|
1953
1954
|
var CONFIG_FILE = path.join(SILUZAN_DIR, "config.json");
|
|
@@ -2226,11 +2227,7 @@ function rawRequest(url, options) {
|
|
|
2226
2227
|
error: "timeout"
|
|
2227
2228
|
});
|
|
2228
2229
|
}
|
|
2229
|
-
reject(
|
|
2230
|
-
new Error(
|
|
2231
|
-
`\u8BF7\u6C42\u8D85\u65F6\uFF08${(timeoutMs / 1e3).toFixed(0)} \u79D2\uFF09\uFF1A${method} ${url}`
|
|
2232
|
-
)
|
|
2233
|
-
);
|
|
2230
|
+
reject(new Error(`\u8BF7\u6C42\u8D85\u65F6\uFF08${(timeoutMs / 1e3).toFixed(0)} \u79D2\uFF09\uFF1A${method} ${url}`));
|
|
2234
2231
|
});
|
|
2235
2232
|
req.on("error", (err) => {
|
|
2236
2233
|
if (perfOn) {
|
|
@@ -2341,6 +2338,29 @@ async function fetchNpmVersion(pkgName, tag, timeoutMs = 4e3) {
|
|
|
2341
2338
|
return null;
|
|
2342
2339
|
}
|
|
2343
2340
|
}
|
|
2341
|
+
async function defaultRunMinRequiredGlobalInstall(ctx) {
|
|
2342
|
+
if (process.env.SILUZAN_SKIP_AUTO_GLOBAL_INSTALL === "1") {
|
|
2343
|
+
return { ok: false, stderr: "SILUZAN_SKIP_AUTO_GLOBAL_INSTALL=1" };
|
|
2344
|
+
}
|
|
2345
|
+
const spec = `${ctx.pkgName}@${ctx.tag}`;
|
|
2346
|
+
return await new Promise((resolve32) => {
|
|
2347
|
+
const child = spawn("npm", ["install", "-g", spec, "--no-fund", "--no-audit"], {
|
|
2348
|
+
stdio: "inherit",
|
|
2349
|
+
shell: true
|
|
2350
|
+
});
|
|
2351
|
+
child.on("error", (err) => {
|
|
2352
|
+
resolve32({ ok: false, stderr: err instanceof Error ? err.message : String(err) });
|
|
2353
|
+
});
|
|
2354
|
+
child.on("close", (code, signal) => {
|
|
2355
|
+
if (code === 0) {
|
|
2356
|
+
resolve32({ ok: true });
|
|
2357
|
+
} else {
|
|
2358
|
+
const sig = signal ? ` signal=${signal}` : "";
|
|
2359
|
+
resolve32({ ok: false, stderr: `exit code ${code}${sig}` });
|
|
2360
|
+
}
|
|
2361
|
+
});
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2344
2364
|
function createVersionNotifier(opts) {
|
|
2345
2365
|
const {
|
|
2346
2366
|
pkgName,
|
|
@@ -2349,27 +2369,33 @@ function createVersionNotifier(opts) {
|
|
|
2349
2369
|
resolveTag,
|
|
2350
2370
|
forceUpdateExtra = "",
|
|
2351
2371
|
updateAvailableExtra = "",
|
|
2372
|
+
runMinRequiredGlobalInstall = defaultRunMinRequiredGlobalInstall,
|
|
2352
2373
|
getCurrentVersion: getCurrentVersion22,
|
|
2353
2374
|
mergeWriteConfig,
|
|
2354
2375
|
readConfigRaw
|
|
2355
2376
|
} = opts;
|
|
2356
|
-
const KEY_LAST_CHECK = `${cachePrefix}LastVersionCheck`;
|
|
2357
2377
|
const KEY_LATEST_STABLE = `${cachePrefix}LatestStable`;
|
|
2358
2378
|
const KEY_LATEST_BETA = `${cachePrefix}LatestBeta`;
|
|
2359
2379
|
const KEY_MIN_STABLE = `${cachePrefix}MinRequiredStable`;
|
|
2360
2380
|
const KEY_MIN_BETA = `${cachePrefix}MinRequiredBeta`;
|
|
2361
2381
|
const KEY_LAST_NOTIFIED = `${cachePrefix}LastNotified`;
|
|
2382
|
+
const KEY_FETCH_AT_MAIN = `${cachePrefix}VersionFetchAtMain`;
|
|
2383
|
+
const KEY_FETCH_AT_MIN = `${cachePrefix}VersionFetchAtMin`;
|
|
2362
2384
|
const HOURS_24 = 24 * 60 * 60 * 1e3;
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2385
|
+
const TTL_MAIN_TAG_MS = 60 * 60 * 1e3;
|
|
2386
|
+
const TTL_MIN_REQUIRED_MS = HOURS_24;
|
|
2387
|
+
async function fetchVersionByTag(tag, cacheKey, fetchAtKey, cfg, maxAgeMs) {
|
|
2388
|
+
const lastAt = cfg[fetchAtKey];
|
|
2389
|
+
if (typeof lastAt === "string" && cacheKey in cfg) {
|
|
2390
|
+
const lastMs = new Date(lastAt).getTime();
|
|
2391
|
+
if (Date.now() - lastMs < maxAgeMs) {
|
|
2368
2392
|
const v = cfg[cacheKey];
|
|
2369
|
-
|
|
2393
|
+
const sv = typeof v === "string" && v ? v : null;
|
|
2394
|
+
return { version: sv, hitNetwork: false };
|
|
2370
2395
|
}
|
|
2371
2396
|
}
|
|
2372
|
-
|
|
2397
|
+
const version = await fetchNpmVersion(pkgName, tag);
|
|
2398
|
+
return { version, hitNetwork: true };
|
|
2373
2399
|
}
|
|
2374
2400
|
async function notifyIfOutdated2() {
|
|
2375
2401
|
try {
|
|
@@ -2380,15 +2406,20 @@ function createVersionNotifier(opts) {
|
|
|
2380
2406
|
const minCacheKey = isBeta ? KEY_MIN_BETA : KEY_MIN_STABLE;
|
|
2381
2407
|
const minTag = npmMinRequiredTagForBuildEnv(isBeta ? "test" : "production");
|
|
2382
2408
|
const cfg = readConfigRaw();
|
|
2383
|
-
const [
|
|
2384
|
-
fetchVersionByTag(tag, latestCacheKey, cfg),
|
|
2385
|
-
fetchVersionByTag(minTag, minCacheKey, cfg)
|
|
2409
|
+
const [mainRes, minRes] = await Promise.all([
|
|
2410
|
+
fetchVersionByTag(tag, latestCacheKey, KEY_FETCH_AT_MAIN, cfg, TTL_MAIN_TAG_MS),
|
|
2411
|
+
fetchVersionByTag(minTag, minCacheKey, KEY_FETCH_AT_MIN, cfg, TTL_MIN_REQUIRED_MS)
|
|
2386
2412
|
]);
|
|
2387
|
-
|
|
2388
|
-
|
|
2413
|
+
const latest = mainRes.version;
|
|
2414
|
+
const minRequired = minRes.version;
|
|
2415
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
2416
|
+
const cacheUpdates = {
|
|
2389
2417
|
[latestCacheKey]: latest ?? "",
|
|
2390
2418
|
[minCacheKey]: minRequired ?? ""
|
|
2391
|
-
}
|
|
2419
|
+
};
|
|
2420
|
+
if (mainRes.hitNetwork) cacheUpdates[KEY_FETCH_AT_MAIN] = nowIso;
|
|
2421
|
+
if (minRes.hitNetwork) cacheUpdates[KEY_FETCH_AT_MIN] = nowIso;
|
|
2422
|
+
await mergeWriteConfig(cacheUpdates);
|
|
2392
2423
|
const lastNotified = typeof cfg[KEY_LAST_NOTIFIED] === "string" ? new Date(cfg[KEY_LAST_NOTIFIED]).getTime() : 0;
|
|
2393
2424
|
if (Date.now() - lastNotified < HOURS_24) return;
|
|
2394
2425
|
const tagLabel = isBeta ? "\uFF08\u6D4B\u8BD5\u7248\uFF09" : "\uFF08\u6B63\u5F0F\u7248\uFF09";
|
|
@@ -2396,11 +2427,26 @@ function createVersionNotifier(opts) {
|
|
|
2396
2427
|
await mergeWriteConfig({ [KEY_LAST_NOTIFIED]: (/* @__PURE__ */ new Date()).toISOString() });
|
|
2397
2428
|
console.log(
|
|
2398
2429
|
`
|
|
2399
|
-
[SILUZAN_FORCE_UPDATE] \u5F53\u524D\u7248\u672C ${current} \u5DF2\
|
|
2400
|
-
\u26D4 \
|
|
2401
|
-
\u6216\u624B\u52A8\uFF1Anpm install -g ${pkgName}@${tag}
|
|
2430
|
+
[SILUZAN_FORCE_UPDATE] \u5F53\u524D\u7248\u672C ${current} \u5DF2\u4F4E\u4E8E\u6700\u4F4E\u8981\u6C42 ${minRequired}${tagLabel}
|
|
2431
|
+
\u26D4 \u6B63\u5728\u81EA\u52A8\u6267\u884C\uFF1Anpm install -g ${pkgName}@${tag}
|
|
2402
2432
|
` + (forceUpdateExtra ? forceUpdateExtra + "\n" : "")
|
|
2403
2433
|
);
|
|
2434
|
+
const installResult = await runMinRequiredGlobalInstall({ pkgName, tag });
|
|
2435
|
+
if (installResult.ok) {
|
|
2436
|
+
console.log(
|
|
2437
|
+
`
|
|
2438
|
+
[SILUZAN_AUTO_GLOBAL_INSTALL_OK] \u5168\u5C40\u5B89\u88C5\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u672C\u547D\u4EE4\u4EE5\u52A0\u8F7D\u65B0\u7248\u672C ${pkgName}@${tag}\u3002
|
|
2439
|
+
`
|
|
2440
|
+
);
|
|
2441
|
+
} else {
|
|
2442
|
+
console.log(
|
|
2443
|
+
`
|
|
2444
|
+
[SILUZAN_AUTO_GLOBAL_INSTALL_FAILED] \u81EA\u52A8\u5168\u5C40\u5B89\u88C5\u5931\u8D25\uFF1A${installResult.stderr ?? "unknown"}
|
|
2445
|
+
\u8BF7\u624B\u52A8\u6267\u884C\uFF1Anpm install -g ${pkgName}@${tag}
|
|
2446
|
+
\u6216\uFF1A${binName} update
|
|
2447
|
+
` + (forceUpdateExtra ? forceUpdateExtra + "\n" : "")
|
|
2448
|
+
);
|
|
2449
|
+
}
|
|
2404
2450
|
return;
|
|
2405
2451
|
}
|
|
2406
2452
|
if (latest && isNewer(current, latest)) {
|
|
@@ -2489,16 +2535,11 @@ function printAuthMissingHelp(binName) {
|
|
|
2489
2535
|
`
|
|
2490
2536
|
\u274C \u672A\u627E\u5230\u8BA4\u8BC1\u51ED\u636E\u3002\u8BF7\u9009\u62E9\u4EE5\u4E0B\u4EFB\u610F\u4E00\u79CD\u65B9\u5F0F\uFF1A
|
|
2491
2537
|
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
export SILUZAN_API_KEY=<YOUR_API_KEY>
|
|
2498
|
-
# \u6216 export SILUZAN_AUTH_TOKEN=<YOUR_TOKEN>
|
|
2499
|
-
|
|
2500
|
-
\u65B9\u5F0F\u4E09\uFF1AJWT Token
|
|
2501
|
-
${binName} login
|
|
2538
|
+
\u8BF7\u4F7F\u7528\u624B\u673A\u53F7\u91CD\u65B0\u767B\u5F55
|
|
2539
|
+
${binName} send-login-code --phone <YOUR_PHONE>
|
|
2540
|
+
`,
|
|
2541
|
+
`\u7136\u540E\u4F7F\u7528\u6536\u5230\u7684\u9A8C\u8BC1\u7801\u5B8C\u6210\u767B\u5F55
|
|
2542
|
+
${binName} login --phone <YOUR_PHONE> --code <YOUR_CODE>
|
|
2502
2543
|
`
|
|
2503
2544
|
);
|
|
2504
2545
|
process.exit(1);
|
|
@@ -3013,7 +3054,7 @@ import * as readline from "readline";
|
|
|
3013
3054
|
import * as os3 from "os";
|
|
3014
3055
|
function parseAllowedServices(raw) {
|
|
3015
3056
|
const allowed = ["CSO", "TSO", "CUT"];
|
|
3016
|
-
if (!raw) return ["CSO", "CUT"];
|
|
3057
|
+
if (!raw) return ["CSO", "TSO", "CUT"];
|
|
3017
3058
|
const parts = raw.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
|
|
3018
3059
|
const result = [];
|
|
3019
3060
|
for (const p of parts) {
|
|
@@ -3085,9 +3126,6 @@ async function runPhoneLogin(opts) {
|
|
|
3085
3126
|
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
3086
3127
|
console.log(` \u624B\u673A\u53F7 : ${phone}`);
|
|
3087
3128
|
console.log(` \u9A8C\u8BC1\u7801 : ${code}`);
|
|
3088
|
-
console.log(` SSO : ${ssoBaseUrl}`);
|
|
3089
|
-
console.log(` CSO API : ${csoBaseUrl}`);
|
|
3090
|
-
console.log(` \u670D\u52A1\u8303\u56F4 : ${allowedServices.join(", ")}`);
|
|
3091
3129
|
if (opts.expiresAt) {
|
|
3092
3130
|
console.log(` \u8FC7\u671F\u65F6\u95F4 : ${opts.expiresAt}`);
|
|
3093
3131
|
} else {
|
|
@@ -3139,12 +3177,8 @@ async function runPhoneLogin(opts) {
|
|
|
3139
3177
|
`
|
|
3140
3178
|
);
|
|
3141
3179
|
} else if (/验证码错误|验证码/.test(msg)) {
|
|
3142
|
-
console.error(
|
|
3143
|
-
|
|
3144
|
-
\u9A8C\u8BC1\u7801\u53EF\u80FD\u5DF2\u8FC7\u671F\u6216\u8F93\u9519\u3002\u8BF7\u91CD\u65B0\u53D1\u7801\u540E\u518D\u8BD5\uFF1A
|
|
3145
|
-
siluzan-cso send-login-code --phone ${phone}
|
|
3146
|
-
`
|
|
3147
|
-
);
|
|
3180
|
+
console.error(` siluzan-cso send-login-code --phone ${phone}
|
|
3181
|
+
`);
|
|
3148
3182
|
}
|
|
3149
3183
|
process.exit(1);
|
|
3150
3184
|
}
|
|
@@ -3688,7 +3722,11 @@ var register = defineCommand({
|
|
|
3688
3722
|
description: "\u5217\u51FA\u516C\u53F8\u6240\u6709\u6210\u5458\uFF0C\u663E\u793A\u7528\u6237ID\u4F9B list-accounts --owner \u4F7F\u7528",
|
|
3689
3723
|
options: [
|
|
3690
3724
|
{ flags: "-q, --query <keyword>", description: "\u6309\u59D3\u540D\u6216\u624B\u673A\u53F7\u6A21\u7CCA\u641C\u7D22" },
|
|
3691
|
-
{
|
|
3725
|
+
{
|
|
3726
|
+
flags: "--unicode",
|
|
3727
|
+
description: "\u4F7F\u7528 Unicode \u7EBF\u6846\u8868\u683C\uFF08\u9ED8\u8BA4 ASCII +-|\uFF09",
|
|
3728
|
+
defaultValue: false
|
|
3729
|
+
}
|
|
3692
3730
|
],
|
|
3693
3731
|
handler: async (opts) => {
|
|
3694
3732
|
await runListMembers({
|
|
@@ -5988,6 +6026,9 @@ function formatRagResultsMarkdown(query, items, subQueries) {
|
|
|
5988
6026
|
});
|
|
5989
6027
|
return parts.join("");
|
|
5990
6028
|
}
|
|
6029
|
+
function normalizeQueryPartition(p) {
|
|
6030
|
+
return p === "wiki" ? "wiki" : "default";
|
|
6031
|
+
}
|
|
5991
6032
|
function buildQueryKnowledgesSearchParams(options) {
|
|
5992
6033
|
const p = new URLSearchParams();
|
|
5993
6034
|
p.append("queryTxt", options.queryTxt);
|
|
@@ -6006,6 +6047,7 @@ function buildQueryKnowledgesSearchParams(options) {
|
|
|
6006
6047
|
for (const c of options.categories) {
|
|
6007
6048
|
p.append("category", c);
|
|
6008
6049
|
}
|
|
6050
|
+
p.append("partition", options.partition);
|
|
6009
6051
|
return p.toString();
|
|
6010
6052
|
}
|
|
6011
6053
|
async function runRagQuery(options) {
|
|
@@ -6042,6 +6084,12 @@ async function runRagQuery(options) {
|
|
|
6042
6084
|
}
|
|
6043
6085
|
const tagList = resolveTags(options.tags);
|
|
6044
6086
|
const categories = splitCsv(options.category);
|
|
6087
|
+
const rawPartition = options.partition?.trim();
|
|
6088
|
+
if (rawPartition && rawPartition !== "wiki" && rawPartition !== "default") {
|
|
6089
|
+
console.error("\n\u274C partition \u53EA\u80FD\u4E3A wiki \u6216 default\u3002");
|
|
6090
|
+
process.exit(1);
|
|
6091
|
+
}
|
|
6092
|
+
const partition = normalizeQueryPartition(rawPartition);
|
|
6045
6093
|
const baseSearch = {
|
|
6046
6094
|
belongTo,
|
|
6047
6095
|
belongToId,
|
|
@@ -6049,7 +6097,8 @@ async function runRagQuery(options) {
|
|
|
6049
6097
|
sourceIds,
|
|
6050
6098
|
folderIds,
|
|
6051
6099
|
tags: tagList,
|
|
6052
|
-
categories
|
|
6100
|
+
categories,
|
|
6101
|
+
partition
|
|
6053
6102
|
};
|
|
6054
6103
|
const verbose = Boolean(options.verbose);
|
|
6055
6104
|
async function fetchKnowledgesOne(queryPart) {
|
|
@@ -6101,7 +6150,8 @@ async function runRagQuery(options) {
|
|
|
6101
6150
|
belongToId,
|
|
6102
6151
|
tags: tagList,
|
|
6103
6152
|
topK: clamped,
|
|
6104
|
-
output
|
|
6153
|
+
output,
|
|
6154
|
+
partition
|
|
6105
6155
|
},
|
|
6106
6156
|
null,
|
|
6107
6157
|
2
|
|
@@ -6194,8 +6244,10 @@ async function runRagList(options) {
|
|
|
6194
6244
|
if (builtinRes.ok) {
|
|
6195
6245
|
folders = mergeFoldersByIdOrder(rootRes.folders, builtinRes.folders);
|
|
6196
6246
|
} else if (verbose) {
|
|
6197
|
-
console.error(
|
|
6198
|
-
|
|
6247
|
+
console.error(
|
|
6248
|
+
`
|
|
6249
|
+
\u26A0\uFE0F \u83B7\u53D6\u77E5\u8BC6\u5E93\u5217\u8868\u5931\u8D25\uFF08\u5185\u7F6E\u7236\u7EA7\uFF09\uFF1A${builtinRes.reason}\uFF08\u5DF2\u4EC5\u7528\u6839\u8282\u70B9\u6570\u636E\u5408\u5E76\u5C55\u793A\uFF09`
|
|
6250
|
+
);
|
|
6199
6251
|
}
|
|
6200
6252
|
if (options.ragOnly) {
|
|
6201
6253
|
folders = folders.filter((f) => f.ragStatus === true);
|
|
@@ -6490,7 +6542,11 @@ function registerCsoCommands(program2) {
|
|
|
6490
6542
|
});
|
|
6491
6543
|
}
|
|
6492
6544
|
);
|
|
6493
|
-
ragCmd.command("query").description("\u6309\u5173\u952E\u8BCD\u68C0\u7D22\u5DF2\u7EB3\u5165\u5411\u91CF\u7684\u77E5\u8BC6\u7247\u6BB5\uFF08GET cutapi/v1/material/queryknowledges\uFF09").requiredOption("-q, --query <text>", "\u68C0\u7D22\u5173\u952E\u8BCD\u6216\u95EE\u53E5").option("--belong-to-id <id>", "\u4F01\u4E1A ID\uFF1B\u4E0D\u4F20\u5219\u4ECE GET /query/account/me \u53D6 companyId").option("--source-id <ids>", "\u7D20\u6750\u6587\u4EF6 ID\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u53EF\u9009\uFF0Cqueryknowledges \u7684 sourceid\uFF09").option("--folder-id <ids>", "\u6587\u4EF6\u5939 ID\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u53EF\u9009\uFF0Ccomid\uFF09").option("--top-k <n>", "\u8FD4\u56DE\u6761\u6570\uFF0C3\u201330\uFF08\u9ED8\u8BA4 7\uFF09", "7").option("--belong-to <n>", "\u5F52\u5C5E\u7C7B\u578B\uFF08\u9ED8\u8BA4 0\uFF0C\u4F01\u4E1A\uFF09", "0").option("--tags <tags>", "\u6807\u7B7E\u8FC7\u6EE4\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u4E0D\u4F20\u5219\u4E0D\u8FC7\u6EE4\u6807\u7B7E\uFF08\u5168\u91CF\u68C0\u7D22\uFF09").option("--category <categories>", "\u5206\u7C7B\u8FC7\u6EE4\uFF0C\u9017\u53F7\u5206\u9694").option(
|
|
6545
|
+
ragCmd.command("query").description("\u6309\u5173\u952E\u8BCD\u68C0\u7D22\u5DF2\u7EB3\u5165\u5411\u91CF\u7684\u77E5\u8BC6\u7247\u6BB5\uFF08GET cutapi/v1/material/queryknowledges\uFF09").requiredOption("-q, --query <text>", "\u68C0\u7D22\u5173\u952E\u8BCD\u6216\u95EE\u53E5").option("--belong-to-id <id>", "\u4F01\u4E1A ID\uFF1B\u4E0D\u4F20\u5219\u4ECE GET /query/account/me \u53D6 companyId").option("--source-id <ids>", "\u7D20\u6750\u6587\u4EF6 ID\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u53EF\u9009\uFF0Cqueryknowledges \u7684 sourceid\uFF09").option("--folder-id <ids>", "\u6587\u4EF6\u5939 ID\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u53EF\u9009\uFF0Ccomid\uFF09").option("--top-k <n>", "\u8FD4\u56DE\u6761\u6570\uFF0C3\u201330\uFF08\u9ED8\u8BA4 7\uFF09", "7").option("--belong-to <n>", "\u5F52\u5C5E\u7C7B\u578B\uFF08\u9ED8\u8BA4 0\uFF0C\u4F01\u4E1A\uFF09", "0").option("--tags <tags>", "\u6807\u7B7E\u8FC7\u6EE4\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u4E0D\u4F20\u5219\u4E0D\u8FC7\u6EE4\u6807\u7B7E\uFF08\u5168\u91CF\u68C0\u7D22\uFF09").option("--category <categories>", "\u5206\u7C7B\u8FC7\u6EE4\uFF0C\u9017\u53F7\u5206\u9694").option(
|
|
6546
|
+
"--partition <wiki|default>",
|
|
6547
|
+
"\u68C0\u7D22\u5206\u533A\uFF08queryknowledges \u7684 partition\uFF0C\u9ED8\u8BA4 default\uFF09",
|
|
6548
|
+
"default"
|
|
6549
|
+
).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--json", "\u8F93\u51FA\u5B8C\u6574 JSON", false).option("--unicode", "\u4F7F\u7528 Unicode \u7EBF\u6846\u8868\u683C\uFF08\u9ED8\u8BA4 ASCII +-|\uFF09", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
6494
6550
|
async (opts) => {
|
|
6495
6551
|
await runRagQuery({
|
|
6496
6552
|
query: opts.query,
|
|
@@ -6501,6 +6557,7 @@ function registerCsoCommands(program2) {
|
|
|
6501
6557
|
belongTo: opts.belongTo !== void 0 ? parseInt(opts.belongTo, 10) : void 0,
|
|
6502
6558
|
tags: opts.tags,
|
|
6503
6559
|
category: opts.category,
|
|
6560
|
+
partition: opts.partition,
|
|
6504
6561
|
token: opts.token,
|
|
6505
6562
|
json: opts.json,
|
|
6506
6563
|
unicode: opts.unicode,
|
|
@@ -6508,9 +6565,7 @@ function registerCsoCommands(program2) {
|
|
|
6508
6565
|
});
|
|
6509
6566
|
}
|
|
6510
6567
|
);
|
|
6511
|
-
const REGISTRARS = [
|
|
6512
|
-
register
|
|
6513
|
-
];
|
|
6568
|
+
const REGISTRARS = [register];
|
|
6514
6569
|
for (const reg of REGISTRARS) reg(program2);
|
|
6515
6570
|
program2.command("upload").description("\u4E0A\u4F20\u672C\u5730\u89C6\u9891\u6216\u56FE\u7247\u5230 Siluzan \u7D20\u6750\u5E93\uFF0C\u8F93\u51FA\u53EF\u76F4\u63A5\u586B\u5165 publish-config.json \u7684\u5B57\u6BB5").requiredOption("-f, --file <path>", "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--kind <video|image>", "\u624B\u52A8\u6307\u5B9A\u6587\u4EF6\u7C7B\u578B\uFF08\u9ED8\u8BA4\u6309\u6269\u5C55\u540D\u81EA\u52A8\u5224\u65AD\uFF09").option("--cover <path>", "\u5C01\u9762\u56FE\u7247\u8DEF\u5F84\uFF08\u4E0A\u4F20\u89C6\u9891\u65F6\u5FC5\u987B\u63D0\u4F9B\uFF09").option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F\u53CA\u5B8C\u6574 URL\uFF08\u9ED8\u8BA4\u9690\u85CF\u542B\u7B7E\u540D URL\uFF09", false).action(
|
|
6516
6571
|
async (opts) => {
|
|
@@ -6539,7 +6594,9 @@ function registerCsoCommands(program2) {
|
|
|
6539
6594
|
const keys = Object.keys(PLATFORM_COVER_SPECS);
|
|
6540
6595
|
console.log("\n\u5404\u5E73\u53F0\u89C6\u9891\u5C01\u9762\u89C4\u683C\uFF1A\n");
|
|
6541
6596
|
const maxKeyLen = Math.max(...keys.map((k) => k.length));
|
|
6542
|
-
const maxNameLen = Math.max(
|
|
6597
|
+
const maxNameLen = Math.max(
|
|
6598
|
+
...keys.map((k) => PLATFORM_COVER_SPECS[k].displayName.length)
|
|
6599
|
+
);
|
|
6543
6600
|
console.log(
|
|
6544
6601
|
` ${"\u5E73\u53F0 ID".padEnd(maxKeyLen)} ${"\u5E73\u53F0\u540D\u79F0".padEnd(maxNameLen)} ${"\u5C3A\u5BF8".padEnd(12)} ${"\u6BD4\u4F8B".padEnd(6)} \u8BF4\u660E`
|
|
6545
6602
|
);
|
|
@@ -6564,14 +6621,16 @@ function registerCsoCommands(program2) {
|
|
|
6564
6621
|
});
|
|
6565
6622
|
}
|
|
6566
6623
|
);
|
|
6567
|
-
program2.command("publish").description("\u6309 JSON \u914D\u7F6E\u6587\u4EF6\u63D0\u4EA4\u53D1\u5E03\u4EFB\u52A1\u5230 CSO").requiredOption("-c, --config <path>", "\u53D1\u5E03\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08JSON\uFF09").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--dry-run", "\u4EC5\u9884\u89C8\u8BF7\u6C42\u4F53\uFF0C\u4E0D\u5B9E\u9645\u63D0\u4EA4", false).option("--verbose", "\u663E\u793A\u5B8C\u6574\u8BF7\u6C42\u4F53\u53CA\u8BE6\u7EC6\u9519\u8BEF\uFF08\u542B\u654F\u611F\u5B57\u6BB5\uFF0C\u9ED8\u8BA4\u8131\u654F\uFF09", false).action(
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6624
|
+
program2.command("publish").description("\u6309 JSON \u914D\u7F6E\u6587\u4EF6\u63D0\u4EA4\u53D1\u5E03\u4EFB\u52A1\u5230 CSO").requiredOption("-c, --config <path>", "\u53D1\u5E03\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08JSON\uFF09").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--dry-run", "\u4EC5\u9884\u89C8\u8BF7\u6C42\u4F53\uFF0C\u4E0D\u5B9E\u9645\u63D0\u4EA4", false).option("--verbose", "\u663E\u793A\u5B8C\u6574\u8BF7\u6C42\u4F53\u53CA\u8BE6\u7EC6\u9519\u8BEF\uFF08\u542B\u654F\u611F\u5B57\u6BB5\uFF0C\u9ED8\u8BA4\u8131\u654F\uFF09", false).action(
|
|
6625
|
+
async (opts) => {
|
|
6626
|
+
await runPublish({
|
|
6627
|
+
config: opts.config,
|
|
6628
|
+
token: opts.token,
|
|
6629
|
+
dryRun: opts.dryRun,
|
|
6630
|
+
verbose: opts.verbose
|
|
6631
|
+
});
|
|
6632
|
+
}
|
|
6633
|
+
);
|
|
6575
6634
|
const reportCmd = program2.command("report").description("\u8FD0\u8425\u62A5\u8868\uFF08table\uFF09\u76F8\u5173\u547D\u4EE4\uFF1A\u62C9\u53D6\u62A5\u8868\u6570\u636E\u3001\u67E5\u770B\u5BFC\u51FA\u8BB0\u5F55\u3001\u4E0B\u8F7D PDF");
|
|
6576
6635
|
reportCmd.command("fetch").description("\u6309\u5A92\u4F53/\u65E5\u671F\u62C9\u53D6\u8FD0\u8425\u62A5\u8868\u6A21\u5757\u6570\u636E\uFF08\u8986\u76D6 table \u9875\u4E3B\u8981\u67E5\u8BE2\u63A5\u53E3\uFF09").requiredOption(
|
|
6577
6636
|
"--media <mediaType>",
|
|
@@ -6671,9 +6730,11 @@ function registerCsoCommands(program2) {
|
|
|
6671
6730
|
taskCmd.command("delete").description("\u5220\u9664\u4EFB\u52A1\uFF08\u5BF9\u5E94 taskManage \u7684 deleteTask\uFF09").requiredOption("--publish-id <id>", "\u4EFB\u52A1 ID").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
|
|
6672
6731
|
await runTaskDelete(opts);
|
|
6673
6732
|
});
|
|
6674
|
-
taskCmd.command("rename").description("\u91CD\u547D\u540D\u4EFB\u52A1\uFF08\u5BF9\u5E94 taskManage \u7684 reName\uFF09").requiredOption("--publish-id <id>", "\u4EFB\u52A1 ID").requiredOption("--name <taskName>", "\u65B0\u4EFB\u52A1\u540D").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
6675
|
-
|
|
6676
|
-
|
|
6733
|
+
taskCmd.command("rename").description("\u91CD\u547D\u540D\u4EFB\u52A1\uFF08\u5BF9\u5E94 taskManage \u7684 reName\uFF09").requiredOption("--publish-id <id>", "\u4EFB\u52A1 ID").requiredOption("--name <taskName>", "\u65B0\u4EFB\u52A1\u540D").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
6734
|
+
async (opts) => {
|
|
6735
|
+
await runTaskRename(opts);
|
|
6736
|
+
}
|
|
6737
|
+
);
|
|
6677
6738
|
taskCmd.command("check-edit").description("\u68C0\u67E5\u4EFB\u52A1\u662F\u5426\u5141\u8BB8\u4FEE\u6539\uFF08\u5BF9\u5E94 checkAllowChange\uFF09").requiredOption("--publish-id <id>", "\u4EFB\u52A1 ID").option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF09").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
6678
6739
|
async (opts) => {
|
|
6679
6740
|
await runTaskCheckEdit(opts);
|
package/dist/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: siluzan-cso
|
|
3
|
-
description:
|
|
3
|
+
description: 内容运营平台,当用户提问的内容涉及以下三类业务时需加载此skill:(1) 内容文案生产:**口播脚本 / 公众号 / Blog 文章 / 外链文章 / 批量引流页**等多场景的文案撰写、选题、爆款拆解、人设卡生成与反推、改稿润色;(2) 多平台(仅支持:YouTube、TikTok、Instagram、LinkedIn、X、Facebook)内容发布与运营:平台账号绑定与 OAuth 授权、视频图文发布、任务管理与失败重试、播放粉丝绩效报表、**账号分组(本 skill 独有;广告账户体系不存在分组概念,用户只说"账号分组"也默认走本 skill,不要进 siluzan-tso)**、素材上传、封面截取、AI 内容规划;(3) RAG 知识库检索:品牌/产品知识库问答与文案事实依据(`rag list` 选库 + `rag query`;**`--partition wiki` / `default` 用法见 `references/rag.md`**)。**如涉及账号相关操作,若账号类型(广告账号/运营媒体账号)不明确,请先询问用户,仅当确认为"运营媒体账号"时,才可使用本 skill。**
|
|
4
4
|
compatibility: Requires siluzan-cso-cli installed and authenticated via `siluzan-cso login`
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -54,46 +54,46 @@ Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令
|
|
|
54
54
|
|
|
55
55
|
## 命令索引
|
|
56
56
|
|
|
57
|
-
| 命令 | 作用
|
|
58
|
-
| ---------------------------------------------------------------------------------- |
|
|
59
|
-
| `siluzan-cso login` | 登录 / 配置凭据
|
|
60
|
-
| `siluzan-cso config show/set/clear` | 查看 / 修改 / 清空本地配置
|
|
61
|
-
| `siluzan-cso init` | Skill 文件初始化(写入 AI 助手目录)
|
|
62
|
-
| `siluzan-cso update` | 更新 CLI 版本并刷新 Skill 文件
|
|
63
|
-
| `siluzan-cso authorize --media-type <平台>` | 发起媒体账号 OAuth 授权
|
|
64
|
-
| `siluzan-cso list-accounts` | 列出媒体账号,获取账号 ID / 数据总览
|
|
65
|
-
| `siluzan-cso persona list` | 拉取 CSO 人设列表(含 styleGuide Markdown)
|
|
66
|
-
| `siluzan-cso rag list` | 列出知识库文件夹;`--rag-only` 仅已建索引;`--folder-id` 查指定文件夹下的子库
|
|
67
|
-
| `siluzan-cso rag query` |
|
|
68
|
-
| `siluzan-cso account-group list/create/add-accounts/remove-accounts/update/delete` | 账号分组管理
|
|
69
|
-
| `siluzan-cso upload -f <file>` | 上传视频 / 图片到素材库
|
|
70
|
-
| `siluzan-cso extract-cover -f <video> -p <平台>` | 从视频截取封面帧
|
|
71
|
-
| `siluzan-cso publish -c config.json` | 提交多平台发布任务
|
|
72
|
-
| `siluzan-cso task list/detail/item` | 查看任务状态 / 处理失败 / 重试
|
|
73
|
-
| `siluzan-cso report fetch --media <平台>` | 运营报表(核心指标 / 视频排行 / 趋势)
|
|
74
|
-
| `siluzan-cso planning ...` | AI 内容规划:生成、监控、详情、导出
|
|
75
|
-
| —(网页端) | CSO web端全部页面 URL
|
|
57
|
+
| 命令 | 作用 | 详细文档 |
|
|
58
|
+
| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- |
|
|
59
|
+
| `siluzan-cso login` | 登录 / 配置凭据 | `references/setup.md` |
|
|
60
|
+
| `siluzan-cso config show/set/clear` | 查看 / 修改 / 清空本地配置 | `references/setup.md` |
|
|
61
|
+
| `siluzan-cso init` | Skill 文件初始化(写入 AI 助手目录) | `references/setup.md` |
|
|
62
|
+
| `siluzan-cso update` | 更新 CLI 版本并刷新 Skill 文件 | `references/setup.md` |
|
|
63
|
+
| `siluzan-cso authorize --media-type <平台>` | 发起媒体账号 OAuth 授权 | `references/authorize.md` |
|
|
64
|
+
| `siluzan-cso list-accounts` | 列出媒体账号,获取账号 ID / 数据总览 | `references/list-accounts.md` |
|
|
65
|
+
| `siluzan-cso persona list` | 拉取 CSO 人设列表(含 styleGuide Markdown) | `references/persona.md` |
|
|
66
|
+
| `siluzan-cso rag list` | 列出知识库文件夹;`--rag-only` 仅已建索引;`--folder-id` 查指定文件夹下的子库 | `references/rag.md` |
|
|
67
|
+
| `siluzan-cso rag query` | 知识库向量检索;**`--partition wiki` 或 `default`**(默认 `default`;写稿与须贴库作答时优先 **wiki**,不足再 **default**);`-q` 含空白时多词分检合并;`--folder-id` / `--tags` 见 `references/rag.md` | `references/rag.md` |
|
|
68
|
+
| `siluzan-cso account-group list/create/add-accounts/remove-accounts/update/delete` | 账号分组管理 | `references/account-group.md` |
|
|
69
|
+
| `siluzan-cso upload -f <file>` | 上传视频 / 图片到素材库 | `references/upload.md` |
|
|
70
|
+
| `siluzan-cso extract-cover -f <video> -p <平台>` | 从视频截取封面帧 | `references/extract-cover.md` |
|
|
71
|
+
| `siluzan-cso publish -c config.json` | 提交多平台发布任务 | `references/publish.md` |
|
|
72
|
+
| `siluzan-cso task list/detail/item` | 查看任务状态 / 处理失败 / 重试 | `references/task.md` |
|
|
73
|
+
| `siluzan-cso report fetch --media <平台>` | 运营报表(核心指标 / 视频排行 / 趋势) | `references/report.md` |
|
|
74
|
+
| `siluzan-cso planning ...` | AI 内容规划:生成、监控、详情、导出 | `references/planning.md` |
|
|
75
|
+
| —(网页端) | CSO web端全部页面 URL | `references/web-pages.md` |
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
79
|
## 常见业务场景 → 阅读哪个文件
|
|
80
80
|
|
|
81
|
-
| 用户在做什么 | 先阅读
|
|
82
|
-
| --------------------------------------------------------------- |
|
|
83
|
-
| 首次安装 / 登录 / 更新 | `references/setup.md`
|
|
84
|
-
| 发布视频或图文 | `references/publish.md`
|
|
85
|
-
| 上传素材 | `references/upload.md`
|
|
86
|
-
| 截取视频封面 | `references/extract-cover.md`
|
|
87
|
-
| 查发布记录 / 处理失败 | `references/task.md`
|
|
88
|
-
| 查账号数据 / 运营报表 | `references/report.md`
|
|
89
|
-
| 查找账号 ID 或账号详情 | `references/list-accounts.md`
|
|
90
|
-
| 账号 Token 失效 / 重新授权 | `references/authorize.md`
|
|
91
|
-
| 管理账号分组 | `references/account-group.md`
|
|
92
|
-
| AI 内容规划 | `references/planning.md`
|
|
93
|
-
| 需要给用户提供后台页面链接 | `references/web-pages.md`
|
|
94
|
-
| 拉取人设 / styleGuide(写稿前) | `references/persona.md`
|
|
95
|
-
| 写稿时检索素材库 RAG 片段(三库拆素材等) | `references/rag.md
|
|
96
|
-
| 选题 / 三库拆解 / 口播文案/其他文案 / 人设卡 / 代表作品反推人设 | `three-lib-content-workflow/content-writer.workflow.md`
|
|
81
|
+
| 用户在做什么 | 先阅读 |
|
|
82
|
+
| --------------------------------------------------------------- | ------------------------------------------------------- |
|
|
83
|
+
| 首次安装 / 登录 / 更新 | `references/setup.md` |
|
|
84
|
+
| 发布视频或图文 | `references/publish.md` |
|
|
85
|
+
| 上传素材 | `references/upload.md` |
|
|
86
|
+
| 截取视频封面 | `references/extract-cover.md` |
|
|
87
|
+
| 查发布记录 / 处理失败 | `references/task.md` |
|
|
88
|
+
| 查账号数据 / 运营报表 | `references/report.md` |
|
|
89
|
+
| 查找账号 ID 或账号详情 | `references/list-accounts.md` |
|
|
90
|
+
| 账号 Token 失效 / 重新授权 | `references/authorize.md` |
|
|
91
|
+
| 管理账号分组 | `references/account-group.md` |
|
|
92
|
+
| AI 内容规划 | `references/planning.md` |
|
|
93
|
+
| 需要给用户提供后台页面链接 | `references/web-pages.md` |
|
|
94
|
+
| 拉取人设 / styleGuide(写稿前) | `references/persona.md` |
|
|
95
|
+
| 写稿时检索素材库 RAG 片段(三库拆素材等) | `references/rag.md` |
|
|
96
|
+
| 选题 / 三库拆解 / 口播文案/其他文案 / 人设卡 / 代表作品反推人设 | `three-lib-content-workflow/content-writer.workflow.md` |
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
@@ -140,25 +140,32 @@ siluzan-cso rag list --folder-id <父文件夹id> --rag-only --json
|
|
|
140
140
|
- 多品牌 → `--folder-id id1,id2`(逗号分隔)
|
|
141
141
|
- 无明确品牌 → 不传 `--folder-id`(全库检索)
|
|
142
142
|
|
|
143
|
-
**Step 3 — 拆词检索**(2–5
|
|
143
|
+
**Step 3 — 拆词检索**(2–5 个短关键词;**`--partition`**)
|
|
144
|
+
|
|
145
|
+
- **首轮**:`--partition wiki`,`--top-k` 建议 **8–15**(常用 **12**)。写稿、须贴库作答、需要较长正文作依据时优先。
|
|
146
|
+
- **仍不足时**:同一 `-q` / `--folder-id` / `--tags` 下再跑 `--partition default`,`--top-k` **5–10**;两轮按片段 **id** 去重合并,**禁止编造**。
|
|
147
|
+
- 取值仅 **`wiki`** 或 **`default`**(小写);非法值 CLI 会报错。
|
|
144
148
|
|
|
145
149
|
```bash
|
|
146
150
|
# 默认不传 --tags = 全量检索(适用于绝大多数场景)
|
|
147
151
|
# 推荐:同一库、同一标签策略下,用空格一次传多词,CLI 会分检合并排序
|
|
148
|
-
siluzan-cso rag query -q "产品核心卖点 用户使用场景 品牌差异优势" --folder-id <id> --top-k
|
|
152
|
+
siluzan-cso rag query -q "产品核心卖点 用户使用场景 品牌差异优势" --folder-id <id> --partition wiki --top-k 12
|
|
153
|
+
|
|
154
|
+
# 证据仍不足时再补 default(按需执行)
|
|
155
|
+
# siluzan-cso rag query -q "产品核心卖点 用户使用场景 品牌差异优势" --folder-id <id> --partition default --top-k 8
|
|
149
156
|
|
|
150
157
|
# 仍可用多轮独立 -q(例如需要分步查看或参数不同)
|
|
151
|
-
# siluzan-cso rag query -q "产品核心卖点" --folder-id <id> --top-k
|
|
152
|
-
# siluzan-cso rag query -q "用户使用场景" --folder-id <id>
|
|
158
|
+
# siluzan-cso rag query -q "产品核心卖点" --folder-id <id> --partition wiki --top-k 12
|
|
159
|
+
# siluzan-cso rag query -q "用户使用场景" --folder-id <id> --partition wiki --top-k 12
|
|
153
160
|
|
|
154
|
-
# 仅当知识库已按标签打标,且需要精确筛选时才传 --tags
|
|
155
|
-
siluzan-cso rag query -q "抖音 爆款 钩子" --tags "流量因子库"
|
|
156
|
-
siluzan-cso rag query -q "产品 卖点 故事" --tags "产品资产库"
|
|
161
|
+
# 仅当知识库已按标签打标,且需要精确筛选时才传 --tags(不同标签需多条命令;`--partition` 规则同上)
|
|
162
|
+
siluzan-cso rag query -q "抖音 爆款 钩子" --tags "流量因子库" --partition wiki --top-k 12
|
|
163
|
+
siluzan-cso rag query -q "产品 卖点 故事" --tags "产品资产库" --partition wiki --top-k 12
|
|
157
164
|
```
|
|
158
165
|
|
|
159
166
|
**Step 4 — 合成使用**
|
|
160
167
|
|
|
161
|
-
合并后的结果中 **`score` 越大越相关**(CLI 已做 0–1
|
|
168
|
+
合并后的结果中 **`score` 越大越相关**(CLI 已做 0–1 归一化)。若执行了 **wiki + default** 两轮,按片段 **id** 去重后再合成。将片段作为写稿/回答的事实依据,重新组织表达(不直接粘贴原文);若执行了多条 `rag query`,再在对话侧对重复片段去重。
|
|
162
169
|
|
|
163
170
|
---
|
|
164
171
|
|
package/dist/skill/_meta.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "siluzan-cso",
|
|
3
|
-
"version": "1.1.18-beta.
|
|
4
|
-
"publishedAt":
|
|
3
|
+
"version": "1.1.18-beta.5",
|
|
4
|
+
"publishedAt": 1778666071422,
|
|
5
5
|
"homepage": "https://www.siluzan.com",
|
|
6
6
|
"source": "https://dev.azure.com/jack4it/Sammamish/_git/siluzan-skill",
|
|
7
7
|
"requiredBinaries": [
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
# rag:RAG 知识库检索
|
|
2
|
+
|
|
2
3
|
知识库管理页面在https://www-ci.siluzan.com/knowledge-base/
|
|
3
4
|
|
|
4
5
|
用于写稿、产品知识问答、三库素材提取等场景;凡回答依赖「本企业已入库素材」且不应凭模型记忆编造时,优先走 RAG。
|
|
5
6
|
|
|
6
7
|
## 业界检索共识与本 CLI 的对应关系(为何要靠「提示词」补效果)
|
|
7
8
|
|
|
8
|
-
生产级 RAG 常见组合是:**合理分块** + **混合检索(关键词 BM25 + 向量)** + **重排序**,并对用户问句做 **查询改写 / 多查询扩展 / 拆解**。本 CLI 调用的是平台侧
|
|
9
|
+
生产级 RAG 常见组合是:**合理分块** + **混合检索(关键词 BM25 + 向量)** + **重排序**,并对用户问句做 **查询改写 / 多查询扩展 / 拆解**。本 CLI 调用的是平台侧 **向量相似度检索**,AI 无法改分块、无法开关 BM25 或重排。要在当前架构下提高 **召回(命中率)** 与 **精确(噪声少)**,主要靠:
|
|
9
10
|
|
|
10
|
-
| 业界手段 | 在本项目中的落地方式
|
|
11
|
-
| ------------------ |
|
|
11
|
+
| 业界手段 | 在本项目中的落地方式 |
|
|
12
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
12
13
|
| 混合检索补「专名」 | 在 `-q` 中显式加入 **素材里更可能出现的词**:品牌全称、产品型号、**官网/画册里的英文类目**、行业术语,减少「口语 ↔ 正文」词面不一致 |
|
|
13
|
-
| 查询改写 | 先去掉寒暄与指代,把用户话改成 **2–8 字的检索型短语**;口语转书面、别名转正名
|
|
14
|
-
| 多查询 / 拆解 | 与 `-q` 内 **空格分检** 对齐:多角度短词并行检索再合并;避免一句长问塞满空格导致「词太碎」
|
|
15
|
-
| 元数据过滤 | 用 **`--folder-id` 锁定品牌库**、必要时 `--tags` 缩小类目标签,降低跨库噪声(全库时易混入其他客户素材)
|
|
16
|
-
| 提高候选再筛 | 适当 **`--top-k` 10–15**,在对话里按 `score` 与正文相关性丢弃明显跑题的片段
|
|
14
|
+
| 查询改写 | 先去掉寒暄与指代,把用户话改成 **2–8 字的检索型短语**;口语转书面、别名转正名 |
|
|
15
|
+
| 多查询 / 拆解 | 与 `-q` 内 **空格分检** 对齐:多角度短词并行检索再合并;避免一句长问塞满空格导致「词太碎」 |
|
|
16
|
+
| 元数据过滤 | 用 **`--folder-id` 锁定品牌库**、必要时 `--tags` 缩小类目标签,降低跨库噪声(全库时易混入其他客户素材) |
|
|
17
|
+
| 提高候选再筛 | 适当 **`--top-k` 10–15**,在对话里按 `score` 与正文相关性丢弃明显跑题的片段 |
|
|
17
18
|
|
|
18
19
|
以下「AI 检索策略」与「提示词规范」均按上表设计:**先锁范围、再改写、再拆词、最后控噪**。
|
|
19
20
|
|
|
@@ -23,20 +24,36 @@
|
|
|
23
24
|
# 第一步:列出所有已建索引的知识库(--rag-only 只显示可检索的)
|
|
24
25
|
siluzan-cso rag list --rag-only
|
|
25
26
|
|
|
26
|
-
#
|
|
27
|
+
# 第二步:按关键词检索(写稿 / 知识问答建议带 `--partition wiki`,见下文「检索分区」)
|
|
27
28
|
siluzan-cso rag query -q "<关键词>" --folder-id <id> --tags ""
|
|
28
|
-
siluzan-cso rag query -q "<关键词>"
|
|
29
|
+
siluzan-cso rag query -q "<关键词>" --partition wiki --top-k 12 --folder-id <id>
|
|
30
|
+
siluzan-cso rag query -q "<关键词>" # 全库;不传 --partition 时为 default
|
|
29
31
|
```
|
|
30
32
|
|
|
31
33
|
## 参数说明
|
|
32
34
|
|
|
33
|
-
| 选项
|
|
34
|
-
|
|
|
35
|
-
| `-q, --query`
|
|
36
|
-
| `--folder-id`
|
|
37
|
-
| `--tags`
|
|
38
|
-
| `--
|
|
39
|
-
| `--
|
|
35
|
+
| 选项 | 默认 | 说明 |
|
|
36
|
+
| ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `-q, --query` | 必填 | 检索词或短句。**若含空白**(如 `卖点 场景 优势`),CLI 会按空白拆成多个词**分别请求**,再按片段 id 去重、取最高相似度、排序后合并返回(`--json` 中含 `subQueries`);无空白时仍为单次检索 |
|
|
38
|
+
| `--folder-id` | 全库 | 指定一个或多个文件夹 ID(逗号分隔),锁定检索范围 |
|
|
39
|
+
| `--tags` | 不过滤 | 不传 = 全量检索(无标签限制);传具体标签 = 只返回含该标签的片段 |
|
|
40
|
+
| `--partition` | `default` | **检索分区**,仅允许 **`wiki`** 或 **`default`**(小写)。控制从哪一类索引里取向量检索结果;含义见下一节 **「检索分区」** |
|
|
41
|
+
| `--top-k` | 7 | 每个分检请求返回条数(3–30);多词合并后总条数上限为 `min(30, topK × 词数)` |
|
|
42
|
+
| `--json` | false | 输出完整 JSON(含本次生效的 `partition`),适合程序处理与对账 |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 检索分区(`--partition`:`wiki` 与 `default`)
|
|
47
|
+
|
|
48
|
+
**是什么**:`rag query` 多一个检索维度——在同一企业、同一 `-q` / 文件夹 / 标签条件下,从 **wiki** 或 **default** 分区取结果。两条取值互斥;**一次命令只能选一个**,需要两种分区各来一轮时,请**执行两次** `rag query`(改 `--partition` 即可)。
|
|
49
|
+
|
|
50
|
+
**怎么用(推荐习惯)**:
|
|
51
|
+
|
|
52
|
+
1. **首轮用 `wiki`**(多数问答、写稿、需要较长正文作依据时):`--partition wiki`,**`--top-k` 建议 8–15**(常用 **12**)。命中片段里常有更完整的正文;合成答案时以返回里的**正文**为主,不要只看一行摘要。
|
|
53
|
+
2. **仍缺原话、表格格内事实或关键信息时,再补一轮 `default`**:保持同一 `--folder-id` / `--tags`,`-q` 相同或略改写,`--partition default`,**`--top-k` 5–10**。**default 用来补漏**,wiki 已经够用就不必再跑 default。
|
|
54
|
+
3. **合并**:两轮结果在对话里按片段 **id**(必要时结合标题)去重后再用;说不清的地方如实说明缺口,**不要编造**。
|
|
55
|
+
|
|
56
|
+
**校验**:只允许 `wiki` 或 `default`;写错会报错。`--json` 里会带上本次实际使用的 `partition`,便于核对。
|
|
40
57
|
|
|
41
58
|
---
|
|
42
59
|
|
|
@@ -46,7 +63,7 @@ siluzan-cso rag query -q "<关键词>" # 全库 + 三
|
|
|
46
63
|
|
|
47
64
|
### 0. 提升命中率与准确率:给模型用的「检索提示词」规范(执行前自检)
|
|
48
65
|
|
|
49
|
-
在调用 `rag query` 前,先在对话内完成下面 **5 步**,再把产物填入 `-q` / `--folder-id` / `--tags` /
|
|
66
|
+
在调用 `rag query` 前,先在对话内完成下面 **5 步**,再把产物填入 `-q` / `--folder-id` / `--tags` / **`--partition`** / **`--top-k`**。这是本仓库在「仅向量检索、无 BM25/重排」约束下的最佳补偿流程。
|
|
50
67
|
|
|
51
68
|
**(1)意图归一(查询改写,Rewrite)**
|
|
52
69
|
|
|
@@ -83,9 +100,10 @@ siluzan-cso rag query -q "<关键词>" # 全库 + 三
|
|
|
83
100
|
```text
|
|
84
101
|
你是 RAG 检索规划器。目标:在 siluzan-cso rag query 约束下最大化命中与准确。
|
|
85
102
|
约束:仅向量检索;`-q` 中含空格会拆成多次检索再合并;folder-id 不传则全库。
|
|
86
|
-
要求:1) 输出 JSON 计划:folderIds(数组)、queries(字符串数组,每个元素将单独作为一次 -q,或合并为一个用空格连接的 -q)、tags
|
|
87
|
-
2)
|
|
88
|
-
3)
|
|
103
|
+
要求:1) 输出 JSON 计划:folderIds(数组)、queries(字符串数组,每个元素将单独作为一次 -q,或合并为一个用空格连接的 -q)、tags(可选)、**检索轮次 rounds**(数组;每项含 `partition`:`wiki` 或 `default`,及 `topK`;**第一轮建议 `wiki`**;证据不足时再加 `default`)、reason(简短中文)。
|
|
104
|
+
2) 默认至少一轮 `wiki`(topK 建议 10–12);若需补检再加一轮 `default`(topK 可略低于 wiki)。
|
|
105
|
+
3) 每个 query 为检索型短语文本:2–12 个汉字为宜,或短英文专名;避免空洞词与过长整句。
|
|
106
|
+
4) 先锁品牌文件夹;禁止在 query 中编造具体数字、证书号、未确认的产品型号。
|
|
89
107
|
```
|
|
90
108
|
|
|
91
109
|
### 1. 判断是否需要 RAG
|
|
@@ -216,8 +234,10 @@ siluzan-cso rag query -q "海科佳产品特点"
|
|
|
216
234
|
siluzan-cso rag list --rag-only --json
|
|
217
235
|
|
|
218
236
|
# Step 2: 假设找到 id=affe64c5...(不传 --tags,全量)
|
|
219
|
-
# 方式 A
|
|
220
|
-
siluzan-cso rag query -q "产品核心卖点 用户痛点 使用场景 品牌差异" --folder-id affe64c5-d3d4-4cec-ab33-196035916894 --top-k
|
|
237
|
+
# 方式 A:wiki 优先 + 一条命令空格分检合并(推荐)
|
|
238
|
+
siluzan-cso rag query -q "产品核心卖点 用户痛点 使用场景 品牌差异" --folder-id affe64c5-d3d4-4cec-ab33-196035916894 --partition wiki --top-k 12
|
|
239
|
+
# 若仍缺表格/原话级事实,再补一轮 default(同 -q 或略改写关键词)
|
|
240
|
+
# siluzan-cso rag query -q "产品核心卖点 用户痛点 使用场景 品牌差异" --folder-id affe64c5-d3d4-4cec-ab33-196035916894 --partition default --top-k 8
|
|
221
241
|
# 方式 B:仍可多轮独立 -q(适合想分步看结果时)
|
|
222
242
|
# siluzan-cso rag query -q "产品核心卖点" --folder-id affe64c5-... --top-k 10
|
|
223
243
|
# siluzan-cso rag query -q "用户痛点解决方案" --folder-id affe64c5-...
|
|
@@ -53,10 +53,10 @@ API Key 获取入口:`https://www-ci.siluzan.com/v3/foreign_trade/settings/api
|
|
|
53
53
|
**两段式调用**,专为 AI Agent 设计——任何一步都不会进入交互等待,绝不会卡住 stdout。
|
|
54
54
|
拆分后单一职责:第 1 步只发码;第 2 步只用 code 换 API Key。这样 Agent 不会因为"看到 stdout 卡住就重试"而触发短信轰炸。
|
|
55
55
|
|
|
56
|
-
| 步骤 | 命令
|
|
57
|
-
| ---- |
|
|
58
|
-
| 1
|
|
59
|
-
| 2
|
|
56
|
+
| 步骤 | 命令 | 说明 |
|
|
57
|
+
| ---- | ---------------------------------------------------- | ---------------------------------------------------------------- |
|
|
58
|
+
| 1 | `siluzan-cso send-login-code --phone <手机号>` | 仅向手机发送 6 位验证码,立即返回;**绝不创建 API Key** |
|
|
59
|
+
| 2 | `siluzan-cso login --phone <手机号> --code <验证码>` | 用 code 完成登录并自动签发 API Key 写入 `~/.siluzan/config.json` |
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
62
|
# 第 1 步:让用户报出手机号后,立刻发码(命令立即返回,不会等待输入)
|
|
@@ -72,15 +72,15 @@ siluzan-cso login --phone 13800138000 --code 123456 \
|
|
|
72
72
|
--services CSO,CUT
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
| 参数
|
|
76
|
-
|
|
|
77
|
-
| `--phone`
|
|
78
|
-
| `--code`
|
|
79
|
-
| `--name`
|
|
80
|
-
| `--valid-days` | 仅 `login`
|
|
81
|
-
| `--expires-at` | 仅 `login`
|
|
82
|
-
| `--services`
|
|
83
|
-
| `--verbose`
|
|
75
|
+
| 参数 | 命令 | 说明 | 默认值 |
|
|
76
|
+
| -------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
|
|
77
|
+
| `--phone` | 两个命令都需要 | 中国大陆手机号,可带或不带 +86(如 `13800138000` / `+8613800138000`);底层会自动补 `+86` 前缀;**手机号必须已在丝路赞网页端注册** | 必填 |
|
|
78
|
+
| `--code` | 仅 `login` | 6 位短信验证码(来自第 1 步发码后的短信);**login 命令必填**,未传会直接报错指引重新走两段式 | 必填(login 命令) |
|
|
79
|
+
| `--name` | 仅 `login` | 自动创建的 API Key 显示名称 | `CLI - <hostname> - <yyyy-MM-dd>` |
|
|
80
|
+
| `--valid-days` | 仅 `login` | API Key 有效期(天),与 `--expires-at` 二选一 | `90` |
|
|
81
|
+
| `--expires-at` | 仅 `login` | API Key 绝对过期时间(ISO 8601) | 不传则用 `--valid-days` |
|
|
82
|
+
| `--services` | 仅 `login` | 可访问的服务列表,逗号分隔;可选 `CSO`/`TSO`/`CUT` | `CSO,CUT`(内容发布 + 素材中心) |
|
|
83
|
+
| `--verbose` | 两个命令都支持 | 输出每次 HTTP 请求的 URL,便于排错 | 关闭 |
|
|
84
84
|
|
|
85
85
|
> **未注册手机号**:`login` 第 2 步会返回 `❌ 登录失败:手机未注册` 并附带网页注册地址,引导用户先去网页注册再回来重试两段式。
|
|
86
86
|
>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "siluzan-cso-cli",
|
|
3
|
-
"version": "1.1.18-beta.
|
|
3
|
+
"version": "1.1.18-beta.5",
|
|
4
4
|
"description": "Siluzan platform AI Skill CLI — multi-platform content publishing (video/image-text) for Cursor, Claude Code, and OpenClaw.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-skill",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@azure/storage-blob": "^12.31.0",
|
|
42
|
-
"proper-lockfile": "^4.1.2",
|
|
43
42
|
"cli-table3": "^0.6.5",
|
|
44
43
|
"commander": "^12.1.0",
|
|
45
|
-
"image-size": "^2.0.2"
|
|
44
|
+
"image-size": "^2.0.2",
|
|
45
|
+
"proper-lockfile": "^4.1.2"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.10.0",
|