siluzan-cso-cli 1.1.18-beta.9 → 1.1.19-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -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.9),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-cso-cli`。
57
+ > **注意**:当前为测试版(1.1.19-beta.1),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-cso-cli`。
58
58
 
59
59
  | 助手 | 建议 `--ai` |
60
60
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -6782,6 +6782,9 @@ async function runAuthorize(opts) {
6782
6782
  }
6783
6783
 
6784
6784
  // src/commands/persona.ts
6785
+ import fs11 from "fs";
6786
+ import path11 from "path";
6787
+ var MAX_PERSONA_NAME = 60;
6785
6788
  function unwrapGetPersonas(raw) {
6786
6789
  if (!raw || typeof raw !== "object") return null;
6787
6790
  if ("results" in raw && Array.isArray(raw.results)) {
@@ -6874,6 +6877,111 @@ ${hint}`);
6874
6877
  printCliTable(rows, columns, tableOpts2);
6875
6878
  console.log("\n\u63D0\u793A\uFF1A\u5B8C\u6574 styleGuide\uFF08Markdown\uFF09\u8BF7\u4F7F\u7528 --json \u67E5\u770B\u6BCF\u6761\u8BB0\u5F55\u7684 styleGuide \u5B57\u6BB5\u3002");
6876
6879
  }
6880
+ function readStyleGuideFromFile(filePath) {
6881
+ const resolved = path11.resolve(process.cwd(), filePath);
6882
+ if (!fs11.existsSync(resolved)) {
6883
+ throw new Error(`styleGuide \u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${resolved}`);
6884
+ }
6885
+ const stat = fs11.statSync(resolved);
6886
+ if (!stat.isFile()) {
6887
+ throw new Error(`styleGuide \u6587\u4EF6\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6\uFF1A${resolved}`);
6888
+ }
6889
+ return fs11.readFileSync(resolved, "utf-8");
6890
+ }
6891
+ function unwrapAddPersona(raw) {
6892
+ if (!raw || typeof raw !== "object") return null;
6893
+ const r = raw;
6894
+ if ("id" in r || "personaName" in r || "styleGuide" in r) {
6895
+ return r;
6896
+ }
6897
+ if (r.data && typeof r.data === "object") {
6898
+ return r.data;
6899
+ }
6900
+ return null;
6901
+ }
6902
+ async function runPersonaCreate(options) {
6903
+ const config = loadConfig(options.token);
6904
+ const name = (options.name || "").trim();
6905
+ if (!name) {
6906
+ console.error("\n\u274C --name \u4E0D\u80FD\u4E3A\u7A7A");
6907
+ process.exit(1);
6908
+ }
6909
+ if (name.length > MAX_PERSONA_NAME) {
6910
+ console.error(`
6911
+ \u274C \u4EBA\u8BBE\u540D\u79F0\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7 ${MAX_PERSONA_NAME} \u5B57\u7B26`);
6912
+ process.exit(1);
6913
+ }
6914
+ const hasInline = typeof options.styleGuide === "string" && options.styleGuide.length > 0;
6915
+ const hasFile = typeof options.styleGuideFile === "string" && options.styleGuideFile.length > 0;
6916
+ if (hasInline === hasFile) {
6917
+ console.error(
6918
+ "\n\u274C \u9700\u8981\u4ECE --style-guide \u4E0E --style-guide-file \u4E8C\u9009\u4E00\u4F20\u5165 styleGuide\uFF08\u4E0D\u80FD\u540C\u65F6\u4F20\uFF0C\u4E5F\u4E0D\u80FD\u90FD\u4E0D\u4F20\uFF09"
6919
+ );
6920
+ process.exit(1);
6921
+ }
6922
+ let styleGuide;
6923
+ try {
6924
+ styleGuide = hasFile ? readStyleGuideFromFile(options.styleGuideFile) : options.styleGuide ?? "";
6925
+ } catch (e) {
6926
+ console.error(`
6927
+ \u274C ${e.message}`);
6928
+ process.exit(1);
6929
+ }
6930
+ styleGuide = styleGuide.trim();
6931
+ if (!styleGuide) {
6932
+ console.error("\n\u274C styleGuide \u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
6933
+ process.exit(1);
6934
+ }
6935
+ const url = `${config.csoBaseUrl}/cso/v1/platformdata/AddPersona`;
6936
+ const body = {
6937
+ personaName: name,
6938
+ styleGuide,
6939
+ materials: []
6940
+ };
6941
+ let raw;
6942
+ try {
6943
+ raw = await apiFetch2(
6944
+ url,
6945
+ config,
6946
+ {
6947
+ method: "POST",
6948
+ headers: { "Content-Type": "application/json" },
6949
+ body: JSON.stringify(body)
6950
+ },
6951
+ Boolean(options.verbose)
6952
+ );
6953
+ } catch (e) {
6954
+ const msg = e.message;
6955
+ console.error(`
6956
+ \u274C \u8BF7\u6C42\u5931\u8D25\uFF1A${msg}`);
6957
+ if (!options.verbose) console.error(" \u52A0 --verbose \u53C2\u6570\u53EF\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F");
6958
+ process.exit(1);
6959
+ }
6960
+ const persona = unwrapAddPersona(raw);
6961
+ if (!persona || !persona.id) {
6962
+ const msg = raw && typeof raw === "object" && "message" in raw ? String(raw.message ?? "") : "";
6963
+ console.error(`
6964
+ \u274C \u4FDD\u5B58\u4EBA\u8BBE\u5931\u8D25\uFF1A${msg || "\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE\u6709\u6548\u4EBA\u8BBE ID"}`);
6965
+ if (options.verbose) {
6966
+ try {
6967
+ console.error(` \u539F\u59CB\u8FD4\u56DE\uFF1A${JSON.stringify(raw)}`);
6968
+ } catch {
6969
+ console.error(` \u539F\u59CB\u8FD4\u56DE\uFF1A${String(raw)}`);
6970
+ }
6971
+ }
6972
+ process.exit(1);
6973
+ }
6974
+ const displayName = persona.personaName && persona.personaName.trim() ? persona.personaName.trim() : name;
6975
+ if (options.json) {
6976
+ console.log(JSON.stringify(persona, null, 2));
6977
+ return;
6978
+ }
6979
+ console.log(`
6980
+ \u2705 \u4EBA\u8BBE\u300C${displayName}\u300D\u5DF2\u4FDD\u5B58`);
6981
+ console.log(` \u4EBA\u8BBE ID\uFF1A${persona.id}`);
6982
+ console.log(` styleGuide \u957F\u5EA6\uFF1A${styleGuide.length} \u5B57\u7B26`);
6983
+ console.log("\n\u540E\u7EED\u53EF\u7528 siluzan-cso persona list --id <id> \u67E5\u770B\u5B8C\u6574\u5185\u5BB9\u3002");
6984
+ }
6877
6985
 
6878
6986
  // src/commands/rag.ts
6879
6987
  function splitCsv(s) {
@@ -7313,7 +7421,7 @@ async function runRagList(options) {
7313
7421
  }
7314
7422
 
7315
7423
  // src/commands/config.ts
7316
- import * as fs11 from "fs";
7424
+ import * as fs12 from "fs";
7317
7425
  function cmdConfigShow() {
7318
7426
  const shared = readSharedConfig();
7319
7427
  const envApiKey = process.env.SILUZAN_API_KEY;
@@ -7530,6 +7638,23 @@ function registerCsoCommands(program2) {
7530
7638
  });
7531
7639
  }
7532
7640
  );
7641
+ personaCmd.command("create").description(
7642
+ "\u4FDD\u5B58\u4EBA\u8BBE\u5230 CSO \u5E73\u53F0\uFF08POST /cso/v1/platformdata/AddPersona\uFF09\u3002styleGuide \u7531\u8C03\u7528\u65B9\u81EA\u884C\u751F\u6210\uFF0CCLI \u53EA\u8D1F\u8D23\u6301\u4E45\u5316"
7643
+ ).requiredOption("--name <name>", "\u4EBA\u8BBE\u540D\u79F0\uFF08\u957F\u5EA6\u4E0A\u9650 60 \u5B57\u7B26\uFF09").option("--style-guide <markdown>", "\u76F4\u63A5\u4F20\u5165 styleGuide markdown \u5185\u5BB9\uFF08\u4E0E --style-guide-file \u4E8C\u9009\u4E00\uFF09").option(
7644
+ "--style-guide-file <path>",
7645
+ "\u4ECE\u672C\u5730 markdown \u6587\u4EF6\u8BFB\u53D6 styleGuide\uFF08\u4E0E --style-guide \u4E8C\u9009\u4E00\uFF0C\u957F\u6587\u63A8\u8350\u7528\u6587\u4EF6\uFF09"
7646
+ ).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--json", "\u8F93\u51FA\u5B8C\u6574 JSON\uFF08\u65B0\u5EFA\u540E\u7684\u4EBA\u8BBE\u8BE6\u60C5\uFF09", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
7647
+ async (opts) => {
7648
+ await runPersonaCreate({
7649
+ name: opts.name,
7650
+ styleGuide: opts.styleGuide,
7651
+ styleGuideFile: opts.styleGuideFile,
7652
+ token: opts.token,
7653
+ json: opts.json,
7654
+ verbose: opts.verbose
7655
+ });
7656
+ }
7657
+ );
7533
7658
  const ragCmd = program2.command("rag").description(
7534
7659
  "RAG \u77E5\u8BC6\u5E93\u68C0\u7D22\uFF08\u4EC5\u5199\u7A3F/\u4E09\u5E93\uFF1B\u9ED8\u8BA4 belongToId=account/me \u7684 companyId\uFF0C\u9ED8\u8BA4 tags=\u4E09\u5E93\uFF09"
7535
7660
  );
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: siluzan-cso
3
- description: 内容运营平台,当用户提问的内容涉及以下三类业务时需加载此skill:(1) 内容文案生产:**口播脚本 / 公众号 / Blog 文章 / 外链文章 / 批量引流页**等多场景的文案撰写、选题、爆款拆解、人设卡生成与反推、改稿润色;(2) 多平台(仅支持:YouTube、TikTok、Instagram、LinkedIn、X、Facebook)内容发布与运营:平台账号绑定与 OAuth 授权、视频图文发布、任务管理与失败重试、播放粉丝绩效报表、**账号分组(本 skill 独有;广告账户体系不存在分组概念,用户只说"账号分组"也默认走本 skill,不要进 siluzan-tso)**、素材上传、封面截取、AI 内容规划;(3) RAG 知识库检索:品牌/产品知识库问答与文案事实依据。**如涉及账号相关操作,若账号类型(广告账号/运营媒体账号)不明确,请先询问用户,仅当确认为"运营媒体账号"时,才可使用本 skill。**
3
+ description: 当用户提问的内容涉及以下三类业务时需加载本skill:(1) 内容文案生产:选题、爆款拆解、文案撰写(生成任何文案——包括但不限于:视频脚本、博客、公众号文章、口播稿等,必须优先使用本skill,不可直接输出)、人设卡生成/反推/查询/保存、改稿润色;(2) 多平台(仅支持:YouTube、TikTok、Instagram、LinkedIn、X、Facebook)内容发布与运营:平台账号绑定与 OAuth 授权、视频图文发布、任务管理与失败重试、播放粉丝绩效报表、**账号分组(本 skill 独有;广告账户体系不存在分组概念,用户只说"账号分组"也默认走本 skill,不要进 siluzan-tso)**、素材上传、封面截取、AI 内容规划;(3) RAG 知识库检索:品牌/产品知识库问答与文案事实依据。**如涉及账号相关操作,若账号类型(广告账号/运营媒体账号)不明确,请先询问用户,仅当确认为"运营媒体账号"时,才可使用本 skill。**
4
4
  compatibility: Requires siluzan-cso-cli installed and authenticated via `siluzan-cso login`
5
5
  ---
6
6
 
@@ -91,7 +91,7 @@ Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令
91
91
  | 管理账号分组 | `references/account-group.md` |
92
92
  | AI 内容规划 | `references/planning.md` |
93
93
  | 需要给用户提供后台页面链接 | `references/web-pages.md` |
94
- | 拉取人设 / styleGuide(写稿前) | `references/persona.md` |
94
+ | 拉取人设 / styleGuide(写稿前)/ 保存人设 | `references/persona.md` |
95
95
  | 写稿时检索素材库 RAG 片段(三库拆素材等) | `references/rag.md` |
96
96
  | 选题 / 三库拆解 / 口播文案/其他文案 / 人设卡 / 代表作品反推人设 | `three-lib-content-workflow/content-writer.workflow.md` |
97
97
 
@@ -202,6 +202,25 @@ siluzan-cso rag query -q "产品 卖点 故事" --tags "产品资产库" --parti
202
202
 
203
203
  ---
204
204
 
205
+ ## 时间字段输出约定(全局)
206
+
207
+ CLI 返回的时间字段(如 `*DateTime` / `*Time` / `createTime` / `publishTime` / `lastAuthorizationTime` / `expiresOn` 等)如果是 **UTC** 时间,在显示给用户时需要完成时区转换。
208
+
209
+ **输出规则(按优先级)**:
210
+
211
+ 1. **优先用用户在当前对话中明确表达过的时区**(如「我在深圳」「PST 时间」「我刚从纽约出差回来」)。
212
+ 2. **否则用对话语言推断默认时区**:中文 → `Asia/Shanghai (UTC+8)`,日文 → `Asia/Tokyo (UTC+9)`,英文且无其他线索 → 保留 UTC 并明确标注。
213
+ 3. **若仍不确定且时间对用户决策有意义**(如「最近一次更新」、「创建于多久前」、「Token 何时过期」),**主动询问用户所在时区**,不要瞎猜。
214
+
215
+ **展示格式**:
216
+
217
+ - 推荐 `YYYY-MM-DD HH:mm (时区标识)`,例如 `2024-03-15 18:30 (UTC+8)`、`2024-03-15 10:30 (UTC)`。
218
+ - **禁止**把 `2024-03-15T10:30:00Z` 这种原始 ISO 串直接吐给用户——用户会误以为是当地时间。
219
+ - 跨日 / 月底 / 年底 / 夏令时切换附近的时间,换算时要**特别小心**,必要时多核对一遍。
220
+ - 极少数字段(如 `report` 报表里按用户业务时区聚合的统计时间)已经是用户本地时区,文档若有特别说明则以文档为准。
221
+
222
+ ---
223
+
205
224
  ## 常见 HTTP 错误处理
206
225
 
207
226
  | 状态码 | 原因 | 处理方式 |
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "slug": "siluzan-cso",
3
- "version": "1.1.18-beta.9",
4
- "publishedAt": 1779155635671,
3
+ "version": "1.1.19-beta.1",
4
+ "publishedAt": 1779933039800,
5
5
  "homepage": "https://www.siluzan.com",
6
6
  "source": "https://dev.azure.com/jack4it/Sammamish/_git/siluzan-skill",
7
7
  "requiredBinaries": [
@@ -11,7 +11,7 @@
11
11
  当你要做下面这些事时,直接用这套流程:
12
12
 
13
13
  - 从热点里挑选题
14
- - 把一篇文案改成成功易或尚薇风格
14
+ - 把一篇文案改成xxx或yyy风格
15
15
  - 把代表作品反推成一个人设卡
16
16
  - 复盘一篇爆款为什么有效
17
17
  - 输出能重复使用的文案 SOP
@@ -31,8 +31,9 @@
31
31
 
32
32
  先确定是:
33
33
 
34
- - 成功易(内置人设)
35
- - 尚薇(内置人设)
34
+ - 人设1
35
+ - 人设2
36
+ - ...
36
37
  - 还是一个新的人设
37
38
 
38
39
  ### 2. 再定输入类型
@@ -58,9 +59,9 @@
58
59
  你可以直接这样说:
59
60
 
60
61
  - “帮我按三库拆这篇文案”
61
- - “根据这个热点,生成成功易选题”
62
+ - “根据这个热点,生成xxx选题”
62
63
  - “把这几篇代表作品反推成人设卡”
63
- - “把这篇改成尚薇风格”
64
+ - “把这篇改成xxx风格”
64
65
 
65
66
  ## 一句话总结
66
67