@yosai/cli 0.2.1-test.7 → 0.2.1-test.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 CHANGED
@@ -10,7 +10,7 @@ YOS 能力的 Agent 执行入口:终端直调 YOS 工具 + 知识库文件上
10
10
  ## 快速开始
11
11
 
12
12
  ```bash
13
- yos login # 配置访问令牌(客户端「个人设置-访问令牌」页创建并复制)与服务环境
13
+ yos login # 配置访问令牌(客户端「个人设置-访问令牌」页创建并复制)
14
14
  yos doctor # 诊断配置与连通(显示当前身份)
15
15
  yos ping # 探活:连接与令牌有效性(退出码即结论,客户端对接用)
16
16
  yos kb list # 我的知识库
@@ -27,7 +27,7 @@ yos tool list # 底层工具通道(领域命令未覆盖
27
27
 
28
28
  | 命令 | 说明 |
29
29
  |---|---|
30
- | `yos login` | 配置访问令牌与服务环境(校验身份后保存) |
30
+ | `yos login` | 配置访问令牌(校验身份后保存) |
31
31
  | `yos doctor` | 诊断配置、访问令牌、连通、Skill 状态与 CLI 版本 |
32
32
  | `yos ping` | 探活:检查连接是否成功、令牌是否有效(退出码 0/2/3/4 即结论,客户端检测对接用) |
33
33
  | `yos kb <动作>` | 知识库:`list` / `detail` / `update` / `upload`(建库、删库请到 YOS 客户端) |
@@ -37,7 +37,7 @@ yos tool list # 底层工具通道(领域命令未覆盖
37
37
  | `yos transcript <动作>` | 转写:`list` / `detail` |
38
38
  | `yos tool list` / `schema` / `call` | 底层工具通道(领域命令未覆盖时兜底) |
39
39
  | `yos version [--check]` | CLI 版本(`--check` 比对对应通道最新版) |
40
- | `yos update [--check]` | 手动升级到对应通道最新版并自动重同步 Skill(平时后台自动更新,一般无需执行) |
40
+ | `yos update [--check]` | 升级到对应通道最新版并自动重同步 Skill(命令执行后检测到新版本会有升级提示,照提示执行即可) |
41
41
  | `yos skill install [--target <dir>]` | 安装内置 Skill |
42
42
 
43
43
  所有命令支持 `--json` 输出与统一退出码(0 成功 / 1 业务失败 / 2 参数错误 / 3 网络 / 4 鉴权 / 5 版本过低)。
@@ -56,8 +56,8 @@ yos skill install # 安装 7 个内置 Skill(总入口 + 领域 + 安装
56
56
 
57
57
  - 配置文件:`~/.config/yos/config.json`(权限 0600;目录可用 `YOS_CONFIG_DIR` 覆盖)
58
58
  - 环境变量(均优先于配置文件,适合 CI/容器场景):`YOS_API_KEY` 访问令牌、`YOS_ENV` 服务环境(prod / test / dev)
59
- - 自动更新:命令执行后会在后台检查对应通道并静默更新到最新版(下次运行生效,自动重同步 Skill);升级通道跟随服务环境——测试环境跟随 test 通道,dev 不自动更新;设置 `YOS_NO_AUTO_UPDATE=1` 可关闭
60
- - 服务环境:缺省生产;`yos login --env test` 切到测试环境,`--env dev` 指向本机开发服务(http://localhost:8080);`yos doctor` 显示当前生效环境及其来源
59
+ - 版本检查:命令执行后会在后台检查对应通道最新版,落后时以 stderr 提示「请先执行 yos update 升级再继续任务」;升级通道自动跟随服务环境(测试环境跟 test 通道)。CLI 不静默安装,升级由用户或 Agent 按提示显式执行
60
+ - 服务环境(测试/开发用):`yos login --env test` 切到测试环境,`--env dev` 指向本机开发服务(http://localhost:8080)
61
61
 
62
62
  ## 故障排查
63
63
 
package/dist/cli.js CHANGED
@@ -187,6 +187,6 @@ export async function dispatch(argv) {
187
187
  return EXIT.BUSINESS;
188
188
  }
189
189
  finally {
190
- handleUpdateNotice(argv, command.name);
190
+ handleUpdateNotice(command.name);
191
191
  }
192
192
  }
@@ -1,6 +1,6 @@
1
1
  import { register } from '../cli.js';
2
2
  import { loadConfig, maskKey, resolveEnv, resolveKey } from '../config.js';
3
- import { endpointOfEnv, envLabel } from '../endpoints.js';
3
+ import { DEFAULT_ENV, endpointOfEnv, envLabel } from '../endpoints.js';
4
4
  import { CliError, EXIT } from '../errors.js';
5
5
  import { formatIdentity, OpenApisClient } from '../openapis-client.js';
6
6
  import { print, printJson } from '../output.js';
@@ -23,11 +23,13 @@ register({
23
23
  ok: config !== null,
24
24
  detail: config ? '已找到' : '未找到,请执行 yos login',
25
25
  });
26
- checks.push({
27
- name: '服务环境',
28
- ok: true,
29
- detail: `${envLabel(env)}(来自 ${endpointSource(config)})`,
30
- });
26
+ if (env !== DEFAULT_ENV) {
27
+ checks.push({
28
+ name: '服务环境',
29
+ ok: true,
30
+ detail: `${envLabel(env)}(来自 ${endpointSource(config)})`,
31
+ });
32
+ }
31
33
  let key = null;
32
34
  try {
33
35
  key = resolveKey(config);
@@ -58,10 +60,11 @@ register({
58
60
  detail: skillDirs.length > 0 ? skillDirs.join(', ') : '尚未安装,执行 yos skill install',
59
61
  });
60
62
  const meta = readPackageMeta();
63
+ const envNote = env === DEFAULT_ENV ? '' : `(环境=${envLabel(env)})`;
61
64
  checks.push({
62
65
  name: 'CLI 版本',
63
66
  ok: meta !== null,
64
- detail: meta ? `${meta.version}(环境=${envLabel(env)})` : 'unknown(未找到 package.json)',
67
+ detail: meta ? `${meta.version}${envNote}` : 'unknown(未找到 package.json)',
65
68
  });
66
69
  const state = loadVersionState();
67
70
  checks.push({
@@ -1,6 +1,6 @@
1
1
  import { register } from '../cli.js';
2
2
  import { loadConfig, maskKey, resolveEnv, saveConfig } from '../config.js';
3
- import { endpointOfEnv, envLabel } from '../endpoints.js';
3
+ import { DEFAULT_ENV, endpointOfEnv, envLabel } from '../endpoints.js';
4
4
  import { UsageError } from '../errors.js';
5
5
  import { formatIdentity, OpenApisClient } from '../openapis-client.js';
6
6
  import { print } from '../output.js';
@@ -30,6 +30,7 @@ register({
30
30
  }
31
31
  const identity = await new OpenApisClient(`${endpoint}/open-apis`, key).whoami();
32
32
  saveConfig({ ...config, env, apiKey: key });
33
- print(`已保存配置:环境=${envLabel(env)},key=${maskKey(key)},身份 ${formatIdentity(identity)}`);
33
+ const envNote = env === DEFAULT_ENV ? '' : `环境=${envLabel(env)},`;
34
+ print(`已保存配置:${envNote}key=${maskKey(key)},身份 ${formatIdentity(identity)}`);
34
35
  },
35
36
  });
@@ -24,19 +24,28 @@ export const DOMAIN_COMMANDS = [
24
24
  },
25
25
  { flag: 'keyword', param: 'keyword', kind: 'string', description: '名称关键词(仅匹配库名,不搜正文)' },
26
26
  { flag: 'page', param: 'page', kind: 'number', description: '页码(缺省 1)', min: 1 },
27
- { flag: 'size', param: 'size', kind: 'number', description: '每页条数(缺省 10,上限 50)', min: 1, max: 50 },
27
+ { flag: 'size', param: 'size', kind: 'number', description: '每页条数(缺省 50)', min: 1, max: 50, defaultValue: 50 },
28
28
  ],
29
29
  render: (result) => {
30
30
  const data = parseToolJson(result);
31
31
  const records = data.records ?? [];
32
+ const total = data.total ?? records.length;
33
+ const page = data.page ?? 1;
32
34
  if (records.length === 0) {
33
- print('(无知识库)');
35
+ print(total > 0 ? `(本页无数据:共 ${total} 条,--page ${page} 超出范围)` : '(无知识库)');
34
36
  return;
35
37
  }
36
38
  print(renderRows(records.map((r) => [
37
39
  String(r.kbCode ?? r.kb_code ?? ''),
38
40
  String(r.kbName ?? r.kb_name ?? r.name ?? ''),
39
41
  ])));
42
+ const shown = (page - 1) * (data.size ?? records.length) + records.length;
43
+ if (shown < total) {
44
+ print(`(共 ${total} 条,还有 ${total - shown} 条;翻页加 --page ${page + 1})`);
45
+ }
46
+ else if (page > 1) {
47
+ print(`(共 ${total} 条,已到末页)`);
48
+ }
40
49
  },
41
50
  },
42
51
  {
@@ -116,7 +125,7 @@ export const DOMAIN_COMMANDS = [
116
125
  {
117
126
  flag: 'type', param: 'doc_type', kind: 'string',
118
127
  description: '文档类型(缺省 md):md=Markdown 文本 / cloud=云文档 / sheet=表格;'
119
- + 'cloud 与 sheet 的正文须为对应草稿 JSON,一般场景一律用 md',
128
+ + 'cloud 与 sheet 的正文为对应草稿 JSON(结构见 yos-doc-sheet 技能),一般场景一律用 md',
120
129
  values: ['md', 'cloud', 'sheet'],
121
130
  },
122
131
  { flag: 'content', param: 'content', kind: 'string', description: '正文文本(与 --file 二选一)' },
@@ -154,7 +163,7 @@ export const DOMAIN_COMMANDS = [
154
163
  flags: [
155
164
  { flag: 'title', param: 'title', kind: 'string', description: '新标题' },
156
165
  { flag: 'content', param: 'content', kind: 'string', description: '新正文,整体覆盖原正文(与 --file 二选一)' },
157
- { flag: 'file', param: 'content', kind: 'string', description: '新正文文件路径,整体覆盖原正文(与 --content 二选一)' },
166
+ { flag: 'file', param: 'content', kind: 'string', description: '新正文文件路径,整体覆盖原正文(与 --content 二选一);云文档/云表格节点传对应草稿 JSON(结构见 yos-doc-sheet 技能)' },
158
167
  { flag: 'description', param: 'description', kind: 'string', description: '新简介(≤100 字)' },
159
168
  ],
160
169
  buildArgs: (context) => {
@@ -35,6 +35,9 @@ function buildDeclaredArgs(spec, context) {
35
35
  if (flag.required) {
36
36
  throw new UsageError(`缺少 --${flag.flag}`, `用法: ${buildUsageForSpec(spec)}`);
37
37
  }
38
+ if (flag.defaultValue !== undefined) {
39
+ args[flag.param] = flag.defaultValue;
40
+ }
38
41
  continue;
39
42
  }
40
43
  const values = Array.isArray(raw) ? raw : [raw];
package/dist/endpoints.js CHANGED
@@ -22,12 +22,12 @@ export function channelOfEnv(env) {
22
22
  export function envLabel(env) {
23
23
  return ENVIRONMENTS[env]?.label ?? env;
24
24
  }
25
- export function labelOfEndpoint(endpoint) {
25
+ export function envNoteOfEndpoint(endpoint) {
26
26
  const normalized = endpoint.replace(/\/+$/, '');
27
- for (const env of Object.values(ENVIRONMENTS)) {
27
+ for (const [name, env] of Object.entries(ENVIRONMENTS)) {
28
28
  if (env.url === normalized) {
29
- return env.label;
29
+ return name === DEFAULT_ENV ? '' : `(${env.label})`;
30
30
  }
31
31
  }
32
- return endpoint;
32
+ return `(${normalized})`;
33
33
  }
@@ -1,6 +1,6 @@
1
1
  import { readFile, stat } from 'node:fs/promises';
2
2
  import { basename } from 'node:path';
3
- import { labelOfEndpoint } from './endpoints.js';
3
+ import { envNoteOfEndpoint } from './endpoints.js';
4
4
  import { AuthError, BusinessError, NetworkError, UpgradeError } from './errors.js';
5
5
  import { getCliVersion } from './npm-meta.js';
6
6
  export const MAX_UPLOAD_SIZE_BYTES = 20 * 1024 * 1024;
@@ -42,13 +42,13 @@ export class OpenApisClient {
42
42
  });
43
43
  }
44
44
  catch (e) {
45
- throw new NetworkError(`无法连接 YOS 服务(${envLabelOfBase(this.base)}),原因:${e.message}`);
45
+ throw new NetworkError(`无法连接 YOS 服务${envNoteOfBase(this.base)},原因:${e.message}`);
46
46
  }
47
47
  return parseEnvelope(response);
48
48
  }
49
49
  }
50
- function envLabelOfBase(base) {
51
- return labelOfEndpoint(base.replace(/\/open-apis$/, ''));
50
+ function envNoteOfBase(base) {
51
+ return envNoteOfEndpoint(base.replace(/\/open-apis$/, ''));
52
52
  }
53
53
  async function parseEnvelope(response) {
54
54
  if (response.status === 401) {
@@ -129,7 +129,7 @@ export async function uploadKnowledgeFile(endpoint, apiKey, filePath, kbCode, pa
129
129
  });
130
130
  }
131
131
  catch (e) {
132
- throw new NetworkError(`无法连接 YOS 服务(${labelOfEndpoint(endpoint)}),原因:${e.message}`);
132
+ throw new NetworkError(`无法连接 YOS 服务${envNoteOfEndpoint(endpoint)},原因:${e.message}`);
133
133
  }
134
134
  return parseEnvelope(response);
135
135
  }
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url';
5
5
  import { readPackageMeta } from './npm-meta.js';
6
6
  import { updateConfig } from './config.js';
7
7
  import { saveVersionState } from './version-state.js';
8
- export const BUILTIN_SKILLS = ['yos', 'yos-shared', 'yos-knowledge', 'yos-retrieval', 'yos-transcript', 'yos-support', 'yos-install'];
8
+ export const BUILTIN_SKILLS = ['yos', 'yos-shared', 'yos-knowledge', 'yos-doc-sheet', 'yos-retrieval', 'yos-transcript', 'yos-support', 'yos-install'];
9
9
  const AGENT_SKILL_DIRS = ['.claude/skills', '.workbuddy/skills', '.cursor/skills', '.codex/skills', '.qoder/skills', '.qoder-cn/skills', '.agents/skills'];
10
10
  export function skillsSourceDir() {
11
11
  const here = dirname(fileURLToPath(import.meta.url));
@@ -1,22 +1,22 @@
1
1
  ---
2
2
  name: yos
3
- description: YOS 企业 AI 能力总入口:公司知识库检索、文档管理、录音转写、帮助手册、客户端升级与反馈。用户问公司制度/流程/资料、要查或整理知识库文档、要看会议录音转写、需要 YOS 客户端帮助时使用;不确定该用哪个 YOS 能力时先读本文件
3
+ description: YOS 企业 AI 能力总入口:公司/部门/工作/个人等各类知识的检索与文档管理、录音转写、帮助手册、客户端升级与反馈。用户提到 yos/YOS/小y 即使用本技能;用户问制度/流程/规范、要查或整理资料文档、要看会议录音转写、需要 YOS 客户端帮助时使用;不确定该用哪个 YOS 能力时先读本文件
4
4
  ---
5
5
 
6
6
  # YOS 能力总入口
7
7
 
8
- YOS 是企业 AI 底座:公司知识、会议录音、帮助手册等能力都可通过本机 `yos` 命令查询与操作。本文件只做**路由与前置判断**,每个命令的参数、返回字段、报错都在对应领域 skill 里,执行前务必读那一本。
8
+ YOS 是企业 AI 底座:公司知识、会议录音、帮助手册等能力都可通过本机 `yos` 命令查询与操作(呼出别名「小y」,用户提 yos / 小y 均指本能力)。本文件只做**路由与前置判断**,每个命令的参数、返回字段、报错都在对应领域 skill 里,执行前务必读那一本。
9
9
 
10
10
  ## 0. 开工前先确认环境(30 秒)
11
11
 
12
12
  ```bash
13
- yos doctor # 七项 ✓ 才继续:配置文件 / 服务环境 / 访问令牌 / 服务连通(回显身份)/ Skill 安装 / CLI 版本 / Skill 同步
13
+ yos doctor # 全部 ✓ 才继续:配置文件 / 访问令牌 / 服务连通(回显身份)/ Skill 安装 / CLI 版本 / Skill 同步
14
14
  yos ping # 只要探活,退出码即结论(0 通 / 3 网络 / 4 鉴权 / 5 版本过低)
15
15
  ```
16
16
 
17
17
  - `command not found: yos` 或 `yos doctor` 报「未找到配置文件」→ 按 `yos-install` skill 引导用户装 CLI 与登录,不要继续猜命令
18
- - 已装但七项没全 ✓ → 先修环境再执行任务;`yos doctor` 的失败项自带修复提示
19
- - 查版本用 `yos version`(或 `yos --version`);CLI 会后台自动更新(跟随当前环境通道,无需手动升级),需要立即升级用 `yos update`
18
+ - 已装但检查项没全 ✓ → 先修好再执行任务;`yos doctor` 的失败项自带修复提示
19
+ - 查版本用 `yos version`(或 `yos --version`);命令执行后 stderr 若出现「提示: 有新版本」,先执行 `yos update` 升级再继续任务(约定详见 yos-shared)
20
20
 
21
21
  ## 1. 意图路由
22
22
 
@@ -28,6 +28,7 @@ yos ping # 只要探活,退出码即结论(0 通 / 3 网络 / 4 鉴
28
28
  | 浏览/搜索自己的知识库与文档内容 | `kb list` `kb detail` `docs tree` `docs content` | yos-knowledge |
29
29
  | 把知识库里的上传文件取回本地 | `docs download <node_code> --out <路径>` | yos-knowledge |
30
30
  | 上传本地文件或目录、新建文档/文件夹、改名、移动、删除、回收站恢复 | `kb upload` `docs create` `docs mkdir` `docs update` `docs rename` `docs move` `docs delete` `docs restore` | yos-knowledge |
31
+ | 往知识库**写云文档/云表格**(在线文档、在线表格;非办公文件) | `docs create --type cloud/sheet`、`docs update` | **先读 yos-doc-sheet**(正文是结构化 JSON,结构与编写规范都在这本) |
31
32
  | 会议录音转写、纪要、逐句发言 | `transcript list` → `transcript detail` | yos-transcript |
32
33
  | 「YOS 怎么用」、客户端最新版本、提交问题反馈 | `support manual*` `support upgrade*` `support feedback` | yos-support |
33
34
  | 领域命令没覆盖的能力 | `tool list` → `tool schema <name>` → `tool call <name> --params '{...}'` | yos-shared |
@@ -50,8 +51,8 @@ yos ping # 只要探活,退出码即结论(0 通 / 3 网络 / 4 鉴
50
51
 
51
52
  1. 用户在 YOS 客户端「个人设置-访问令牌」页创建并复制令牌(40 位小写 hex)
52
53
  2. `yos login` 交互粘贴(不回显);Agent 代执行时用 `yos login --key <令牌>`
53
- 3. 配置文件 `~/.config/yos/config.json`(0600)。环境变量**优先于配置文件**:`YOS_CONFIG_DIR`(换配置目录)、`YOS_API_KEY`(换令牌)、`YOS_ENV`(换服务环境,如 test)
54
- 4. 服务环境缺省生产,切换用 `yos login --env test`(临时可用 `YOS_ENV=test`);开发者本地调试用 `--env dev`(指向本机 8080 起的服务);`yos doctor` 会显示当前生效环境及其来源
54
+ 3. 配置文件 `~/.config/yos/config.json`(0600)。环境变量**优先于配置文件**:`YOS_CONFIG_DIR`(换配置目录)、`YOS_API_KEY`(换令牌)、`YOS_ENV`(换服务环境)
55
+ 4. 切换服务环境(测试/开发用途):`yos login --env test`(临时可用 `YOS_ENV=test`),本地调试 `--env dev`(指向本机 8080 起的服务)
55
56
  5. 退出码 4 = 令牌无效/已吊销/已过期 → 引导重新 `yos login`,不要反复重试同一命令
56
57
 
57
58
  ## 4. 常用编排(已实测)
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: yos-doc-sheet
3
+ description: YOS 云文档与云表格的正文编写规范(DocDraft / SheetWorkbook JSON 数据结构)。用户提到 yos/YOS/小y 且要新建或修改知识库里的云文档、云表格(在线文档/在线表格,非办公文件;即 docs create --type cloud/sheet 与 docs update 改正文)时,先读本技能确定正文结构;上传办公文件(kb upload)与写 Markdown 文档(--type md)不需要本技能
4
+ ---
5
+
6
+ # YOS 云文档与云表格编写(DocDraft / SheetWorkbook)
7
+
8
+ **往 YOS 知识库写"云文档"或"云表格"的正文内容(新建或修改)前,必须先读本技能。** 两者的正文不是纯文本,而是结构化 JSON(不是 Markdown / HTML / CSV),且服务端**不做 schema 校验**(原样存储)——结构写错要到客户端打开时才暴露。
9
+
10
+ ## 0. 适用边界(先分清楚再动手)
11
+
12
+ | 场景 | 走哪个命令 | 用本技能? |
13
+ |---|---|---|
14
+ | 上传办公文件(docx/xlsx/pdf/png…) | `yos kb upload`(落库为 docType=file) | 否 |
15
+ | 写 Markdown 文档 | `yos docs create`(缺省 `--type md`) | 否 |
16
+ | **写云文档(在线文档)** | `yos docs create --type cloud`、`yos docs update` | **是,先读本技能** |
17
+ | **写云表格(在线表格)** | `yos docs create --type sheet`、`yos docs update` | **是,先读本技能** |
18
+ | 目录管理(建文件夹 / 改名 / 移动 / 删除 / 恢复) | `yos docs mkdir/rename/move/delete/restore` | 否(见 yos-knowledge) |
19
+
20
+ 判断一个已有节点属于哪类:`docs tree` / `docs content` 的 `docType` 字段——`cloud` = 云文档、`sheet` = 云表格、`md` = Markdown、`file` = 上传的办公文件。
21
+
22
+ ## 1. 三步流程
23
+
24
+ 1. **写 JSON 草稿**:云文档按 §2 的 DocDraft 结构;云表格按 §3 的 SheetWorkbook 结构。草稿一律落成本地文件(多行 JSON 不要用 `--content` 拼字符串)
25
+ 2. **上传**:
26
+
27
+ ```bash
28
+ # 新建(--parent 为目标文件夹编码,缺省库根;--kb 与 --parent 至少一个)
29
+ yos docs create "<标题>" --kb <kbCode> [--parent <folderCode>] --type cloud|sheet --file <草稿.json>
30
+
31
+ # 修改已有(正文整体覆盖:先读回完整正文,本地编辑后整体回传)
32
+ yos docs update <nodeCode> --title "<新标题>" --file <草稿.json>
33
+ ```
34
+
35
+ 3. **读回自查**:`yos docs content <nodeCode> --json` 确认 `docType`(cloud/sheet)与正文 JSON 完整落库、结构未变形
36
+
37
+ ## 2. 云文档(--type cloud)—— DocDraft JSON
38
+
39
+ 对齐编辑器:`@yos/doc-editor`。
40
+
41
+ ### 2.1 顶层结构
42
+
43
+ ```json
44
+ {
45
+ "title": "文档标题",
46
+ "attachments": [],
47
+ "content": { "type": "doc", "content": [] }
48
+ }
49
+ ```
50
+
51
+ - `title`:与 `docs create` 的标题参数保持一致
52
+ - `attachments`:必须为 `[]`(禁止非空、禁止编造 mediaId)
53
+ - `content`:TipTap 文档树,`type` 固定为 `doc`,节点放 `content` 数组
54
+
55
+ ### 2.2 常用节点(实测可正常落库)
56
+
57
+ 段落与文本(`attrs` 建议保留为下述形态):
58
+
59
+ ```json
60
+ {"type":"paragraph","attrs":{"indent":0,"textAlign":null},"content":[{"type":"text","text":"正文内容"}]}
61
+ ```
62
+
63
+ 标题(`level` 1~3):
64
+
65
+ ```json
66
+ {"type":"heading","attrs":{"level":2,"textAlign":null},"content":[{"type":"text","text":"小节标题"}]}
67
+ ```
68
+
69
+ 无序列表(`bulletList` → `listItem` → `paragraph`,可嵌套):
70
+
71
+ ```json
72
+ {"type":"bulletList","content":[
73
+ {"type":"listItem","content":[
74
+ {"type":"paragraph","attrs":{"indent":0,"textAlign":null},"content":[{"type":"text","text":"列表项"}]}
75
+ ]}
76
+ ]}
77
+ ```
78
+
79
+ 引用(`blockquote` 内放 `paragraph`):
80
+
81
+ ```json
82
+ {"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"textAlign":null},"content":[{"type":"text","text":"引用内容"}]}]}
83
+ ```
84
+
85
+ 代码块(换行用 `\n` 写在同一 `text` 内):
86
+
87
+ ```json
88
+ {"type":"codeBlock","attrs":{"language":null},"content":[{"type":"text","text":"yos kb list\nyos doctor"}]}
89
+ ```
90
+
91
+ 行内样式用 `marks`(可叠加,如加粗+斜体同放数组):
92
+
93
+ ```json
94
+ {"type":"text","marks":[{"type":"bold"}],"text":"加粗"}
95
+ {"type":"text","marks":[{"type":"italic"}],"text":"斜体"}
96
+ ```
97
+
98
+ ### 2.3 禁止与注意事项
99
+
100
+ - 禁止节点:`mindmap`、`flowchart`、`video`、`audio`、`file`、`glossaryTerm`
101
+ - 默认只写基础结构(tier A);分栏、外链图等高级布局(tier B)仅在用户明确要求时使用
102
+ - **不要以 Markdown 作为最终产物**:先定内容结构再落成上述节点 JSON;转换时逐段映射(标题→heading、列表→bulletList、引用→blockquote)
103
+
104
+ ## 3. 云表格(--type sheet)—— SheetWorkbook JSON
105
+
106
+ 对齐编辑器:`@yos/sheet-editor`。
107
+
108
+ ### 3.1 顶层结构
109
+
110
+ ```json
111
+ {
112
+ "id": "workbook-id",
113
+ "name": "工作簿名称",
114
+ "appVersion": "0.25.1",
115
+ "locale": "zhCN",
116
+ "sheetOrder": ["sheet-1"],
117
+ "sheets": {
118
+ "sheet-1": {
119
+ "id": "sheet-1",
120
+ "name": "Sheet1",
121
+ "rowCount": 100,
122
+ "columnCount": 20,
123
+ "cellData": {}
124
+ }
125
+ },
126
+ "resources": []
127
+ }
128
+ ```
129
+
130
+ - `name`:与 `docs create` 的标题参数保持一致;`id` 自拟唯一字符串即可
131
+ - `appVersion` 固定 `0.25.1`、`locale` 固定 `zhCN`
132
+ - `sheetOrder` 决定页签顺序;多页签时在 `sheets` 中并列多个表对象
133
+ - `resources` 必须为 `[]`
134
+
135
+ ### 3.2 cellData(Univer 结构)
136
+
137
+ `{ "行索引": { "列索引": { "v": 值 } } }`——行列索引从 `0` 起、以字符串作键,只写有值的单元格:
138
+
139
+ ```json
140
+ "cellData": {
141
+ "0": { "0": { "v": "项目" }, "1": { "v": "说明" } },
142
+ "1": { "0": { "v": "云文档" }, "1": { "v": "DocDraft JSON 存储" } }
143
+ }
144
+ ```
145
+
146
+ ### 3.3 约束
147
+
148
+ - 单元格只写 `v`(值),不写 `p` / `si` 等复杂字段;样式、合并、冻结等(tier B)仅在用户明确要求时使用
149
+ - `rowCount` ≤ 10000;按内容规模设置(简单表 100 行 × 20 列即可)
150
+ - 禁止非空 `resources`、禁止编造插件数据
151
+ - 纯空表格骨架(仅建空表时用):`{"id":"","sheetOrder":[],"sheets":{}}`
152
+
153
+ ## 4. 常见任务编排
154
+
155
+ **新建云文档并落到指定文件夹**
156
+
157
+ ```bash
158
+ yos kb list --keyword <库名> # 1. 拿 kbCode
159
+ yos docs tree KBxxxx --json # 2. 找目标文件夹 resourceCode(须 resourceType=folder)
160
+ # 3. 写草稿(§2 结构),如 draft.yosdoc.json
161
+ yos docs create "文档标题" --parent NDxxxx --type cloud --file draft.yosdoc.json
162
+ yos docs content NDyyyy --json # 4. 读回自查
163
+ ```
164
+
165
+ **修改已有云文档的正文**(整体覆盖,保留未改动部分)
166
+
167
+ ```bash
168
+ yos docs content NDyyyy --json # 1. 取回完整正文 content
169
+ # 2. 本地编辑目标段落,其余节点原样保留
170
+ yos docs update NDyyyy --title "标题" --file edited.yosdoc.json # 3. 整体回传
171
+ ```
172
+
173
+ **云表格**同理:草稿换成 §3 的 SheetWorkbook 结构、`--type sheet`;修改同样走 `docs update` 整体覆盖。
174
+
175
+ ## 5. 校验与避坑(实测)
176
+
177
+ - **没有在线校验**:CLI 与服务端都不校验正文 schema,写入即原样存储。自查手段:草稿先本地过 JSON 语法(如 `jq . draft.json`)→ 上传后 `docs content --json` 读回核对结构
178
+ - `docs content` 读回的 `content` 是 **JSON 字符串**,需对 `text` 再 `JSON.parse` 两次(外层信封 + content 字符串)
179
+ - `docs update` 的正文是**整体覆盖**不是局部替换——改一处也要先取全文再整体回传,否则其余内容会丢
180
+ - 渲染效果(尤其高级结构、代码块、表格样式)以 YOS 客户端打开为准;发现渲染异常先确认草稿结构,必要时用 `yos support feedback` 反馈
181
+ - 同一文件重复上传不会去重;同名云文档可并存,创建前可先 `docs tree` 看目标位置是否已有同名节点
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yos-install
3
- description: 引导用户在本机安装并配置 YOS CLI(环境检查 → npm 全局安装 → 登录访问令牌 → 安装内置 Skill → doctor 验证)。当 yos 命令不存在、yos doctor 未通过、用户说"帮我装 YOS CLI / 配置令牌 / 装不上"时使用。本文件自包含,可单独放到发布仓库供用户下载后完成引导
3
+ description: 引导用户在本机安装并配置 YOS CLI(环境检查 → npm 全局安装 → 登录访问令牌 → 安装内置 Skill → doctor 验证)。用户提到 yos/YOS/小y 且需要安装或修复 CLI 环境(yos 命令不存在、yos doctor 未通过、要装 CLI / 配置令牌 / 装不上)时使用。本文件自包含,可单独放到发布仓库供用户下载后完成引导
4
4
  ---
5
5
 
6
6
  # YOS CLI 安装与配置引导
@@ -60,13 +60,13 @@ yos login --key '<40 位令牌>'
60
60
  3. 成功输出(原样回给用户即可,`key` 已是掩码):
61
61
 
62
62
  ```
63
- 已保存配置:环境=生产,key=xxxxxxxx****xxxx,身份 张三(U00000001)
63
+ 已保存配置:key=xxxxxxxx****xxxx,身份 张三(U00000001)
64
64
  ```
65
65
 
66
66
  关键语义:
67
67
 
68
68
  - `login` 会**先调服务端校验身份再落盘**,校验失败不写配置 → 报网络或令牌错时无需清理"半成品"配置,改对参数重跑即可
69
- - 服务环境缺省为生产。切换环境用 `yos login --env test`(临时切换可先 `export YOS_ENV=test`);地址由 CLI 内置映射,无需关心。不指定时沿用已保存的环境
69
+ - 切换服务环境(测试/开发装机用):`yos login --env test`(临时切换可先 `export YOS_ENV=test`),本地服务 `--env dev`
70
70
  - 配置文件 `~/.config/yos/config.json`(目录 0700、文件 0600)
71
71
  - CI/容器可完全跳过 `login`:`export YOS_API_KEY=<令牌>`、`export YOS_ENV=test` 指定服务环境(两者都优先于配置文件);`YOS_CONFIG_DIR` 可换配置目录(多环境隔离用)
72
72
 
@@ -101,38 +101,37 @@ yos skill install
101
101
  ## 5. 验证
102
102
 
103
103
  ```bash
104
- yos doctor # 七项全 ✓ 才算装好
104
+ yos doctor # 全部 ✓ 才算装好
105
105
  yos doctor --json # 需要机器可读结果时({checks:[{name,ok,detail}]})
106
106
  yos kb list --json # 端到端实跑一条只读命令收尾
107
107
  ```
108
108
 
109
- `doctor` 七项与样例:
109
+ `doctor` 样例:
110
110
 
111
111
  ```
112
112
  ✓ 配置文件: 已找到
113
- ✓ 服务环境: 生产(来自 内置缺省)
114
113
  ✓ 访问令牌: xxxxxxxx****xxxx
115
114
  ✓ 服务连通: 身份 张三(U00000001)
116
115
  ✓ Skill 安装: ~/.claude/skills
117
- ✓ CLI 版本: 0.2.0(环境=生产)
116
+ ✓ CLI 版本: 0.2.0
118
117
  ✗ Skill 同步: 缺少版本状态(Skill 目录 1 个),执行 yos update 重同步
119
118
  ```
120
119
 
121
- - 退出码:七项全过 `0`;服务连通失败沿用底层错误(`3` 网络不可达 / `4` 鉴权失败);其余未通过项为 `2`
120
+ - 退出码:全部通过 `0`;服务连通失败沿用底层错误(`3` 网络不可达 / `4` 鉴权失败);其余未通过项为 `2`
122
121
  - 「Skill 同步」读的是版本状态文件与 CLI 版本是否一致:`yos update` 或 `yos skill install` 任一跑过即刷新,`✗` 时按 detail 提示执行 `yos update`
123
122
  - Skill 项判定读的是**配置里的安装记录**,不是磁盘探测:手工删过 Skill 目录时 `doctor` 仍显示 ✓,有疑问就 `ls ~/.claude/skills/yos/SKILL.md`
124
123
 
125
124
  ## 6. 升级与卸载
126
125
 
127
- CLI 平时无需手动升级:每次命令执行后会在后台自动检查对应通道并静默更新(升级后自动重同步 Skill),下次运行生效。升级通道跟随服务环境:生产跟 latest 正式版,测试环境(`login --env test`)自动跟 test 通道,dev 不自动更新。
126
+ CLI 平时无需手动检查升级:每次命令执行后会在后台检查对应通道最新版,落后时以 stderr 提示(Agent 按提示先执行 `yos update` 升级再继续任务)。升级通道自动跟随服务环境(测试环境跟 test 通道)。
128
127
 
129
128
  ```bash
130
- yos update # 需要立即升级时执行(到当前通道最新版并自动重同步 Skill)
129
+ yos update # 看到落后提示或需要立即升级时执行(到当前通道最新版并自动重同步 Skill)
131
130
  yos update --check # 只查是否有新版本,不安装
132
131
  npm install -g @yosai/cli@latest # 等价手动写法(正式版);走这条路后需再跑 yos skill install 刷新 Skill
133
132
  ```
134
133
 
135
- (0.2.0 之前的版本没有 `yos update`,直接用 `npm install -g @yosai/cli@latest` 升级;如需关闭后台自动更新,设置环境变量 `YOS_NO_AUTO_UPDATE=1`)
134
+ (0.2.0 之前的版本没有 `yos update`,直接用 `npm install -g @yosai/cli@latest` 升级)
136
135
 
137
136
  卸载(破坏性,逐项取得用户确认后再动手):
138
137
 
@@ -150,7 +149,7 @@ ls ~/.claude/skills | grep -E '^yos' # 先看要删哪些,
150
149
  | `npm error code E404` / `'@yosai/cli' is not in this registry` | 包名拼错、该版本尚未发布到 npmjs,或 npm 镜像未同步 | 核对包名 `@yosai/cli`;已发布仍 404 多为镜像未同步,加 `--registry=https://registry.npmjs.org` 重试;仍有问题联系维护者 |
151
150
  | `npm error code EACCES`(写全局目录失败) | npm 全局前缀指向了 root 目录 | 让用户同意后再改前缀:`npm config set prefix ~/.npm-global`,把 `~/.npm-global/bin` 加进 PATH,重开终端重装。**不要 sudo** |
152
151
  | `错误: 令牌格式不正确(应为 40 位小写 hex)` + `提示: 请在客户端「个人设置-访问令牌」页创建并复制完整令牌` | 令牌长度不对 / 大写 / 粘了空格或前缀 | 让用户重新整段复制(40 位、仅 `0-9a-f`);不要让用户逐字补 |
153
- | `错误: 无法连接 YOS 服务(生产),原因:fetch failed` | 服务不可达(环境选错、网络受限、服务异常) | 先 `yos doctor` 看「服务环境」项确认环境与来源;环境选错用 `yos login --env <环境>` 重配;网络问题找运维确认 |
152
+ | `错误: 无法连接 YOS 服务,原因:fetch failed` | 服务不可达(网络受限、服务异常;测试/开发装机也可能环境未切换) | 先 `yos ping` 复测并检查网络;测试/开发装机环境选错用 `yos login --env test` 重配;网络问题找运维确认 |
154
153
  | `未配置访问令牌` + `请执行 yos login 或设置环境变量 YOS_API_KEY` | 没配置也没 env | 回第 3 步 |
155
154
  | `错误: 未发现已安装的 Agent 技能目录` | 本机没有已知的 AI 工具 Skill 目录 | `yos skill install --target <该工具 skills 目录>`,见第 4 步 |
156
155
  | `yos --version` 无输出或报未知命令 | 装的是 0.2.0 之前的旧版本(旧版没有 version/update 命令) | 先 `npm install -g @yosai/cli@latest` 升到最新版(≥0.2.0),之后即可用 `yos version` / `yos update` |
@@ -159,7 +158,8 @@ ls ~/.claude/skills | grep -E '^yos' # 先看要删哪些,
159
158
  ## 8. 装好之后
160
159
 
161
160
  - 让用户从 `yos` skill(总入口)开始使用;命令细节看各领域 skill:`yos-knowledge`(知识库管理)、`yos-retrieval`(检索与引用)、`yos-transcript`(录音转写)、`yos-support`(帮助/版本/反馈)、`yos-shared`(共享约定)
161
+ - **呼出约定(务必转告用户)**:以后需要 YOS 能力时,在需求里带上「yos」或「小y」最稳(如「用 yos 查一下报销标准」「小y 帮我看看上周的会议纪要」);提到 yos 或小y 时 Agent 一定会走 YOS 技能,不提时可能不会主动使用
162
162
  - 本机可用能力:28 个领域命令(kb 4 / docs 11 / retrieve 5 / support 6 / transcript 2)+ `yos tool` 兜底通道,覆盖知识库检索与管理、文档上传下载、会议转写查询、帮助手册、客户端版本与反馈;新建与删除知识库不在 CLI 内,需到 YOS 客户端手动操作
163
163
  - 边界(别过度承诺):不能实时控制转写、不能申请/变更权限、反馈不带附件、只能看到当前令牌归属用户可见的数据
164
- - 排查建议:任何失败先跑 `yos doctor`;退出码 `4` 一律重新登录,`3` 先看「服务环境」项与网络
164
+ - 排查建议:任何失败先跑 `yos doctor`;退出码 `4` 一律重新登录,`3` 先复测网络连通
165
165
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yos-knowledge
3
- description: YOS 知识库与文档管理(kb list/detail/update/upload + docs tree/content/download/count/mkdir/create/update/rename/move/delete/restore)。用户要查资料在哪、上传或整理知识库文档、下载原文件、改名字/移动/删除/恢复时使用;含每条命令的参数、真实输出与报错修法
3
+ description: YOS 知识库与文档管理(kb list/detail/update/upload + docs tree/content/download/count/mkdir/create/update/rename/move/delete/restore)。用户提到 yos/YOS/小y 且要管理知识库与文档(查资料在哪、上传或整理文档、下载原文件、改名/移动/删除/恢复)时使用;含每条命令的参数、真实输出与报错修法
4
4
  ---
5
5
 
6
6
  # YOS 知识库与文档(kb / docs)
@@ -18,6 +18,7 @@ yos docs tree KB20260921000001 # → 节点的 resourceCode(形如 N
18
18
  - 编码规律:库 `KB`+yyyyMMdd+6 位序号,节点 `ND`+yyyyMMdd+6 位序号。示例里的 `KBxxx`/`NDxxx` 都是占位,真实调用必须来自上面三条命令
19
19
  - 写操作前先确认 `role`:`edit` 才能建/改内容与改名;`admin`/`owner` 才能移动、删除、恢复、改库名
20
20
  - `kb list` 不传 `--scope` 时返回**全部可见库**(含他人所有、自己只有 `read` 的库)。用户说「我的知识库」时要显式加 `--scope created`
21
+ - `kb list` 缺省一次返回 50 条;输出末尾若出现「(共 N 条,还有 M 条;翻页加 --page K)」尾注,说明未拿全,必须继续翻页(判据见 1.1「输出尾部语义」)
21
22
 
22
23
  ---
23
24
 
@@ -30,7 +31,7 @@ yos kb list # 全部可见(实测默认行
30
31
  yos kb list --scope created # 我创建的
31
32
  yos kb list --scope shared # 别人分享给我的
32
33
  yos kb list --keyword 公司资料 # 按名称过滤
33
- yos kb list --page 2 --size 20 # 翻页(size 上限 50)
34
+ yos kb list --page 2 --size 20 # 翻页(缺省一次拿 50 条,仅尾注提示还有更多时才需要)
34
35
  ```
35
36
 
36
37
  | flag | 工具参数 | 取值 | 缺省 |
@@ -38,7 +39,7 @@ yos kb list --page 2 --size 20 # 翻页(size 上限 50)
38
39
  | `--scope` | `range` | `created` \| `shared` \| `all` | `all` |
39
40
  | `--keyword` | `keyword` | 名称关键词 | 无 |
40
41
  | `--page` | `page` | ≥1 整数 | 1 |
41
- | `--size` | `size` | 每页条数,1~50 | 10 |
42
+ | `--size` | `size` | 每页条数,1~50 | 50 |
42
43
 
43
44
  非法值与越界值一律 exit=2 且不发请求:`--scope mine` → `错误: --scope 取值非法:mine` + `提示: 可选:created / shared / all`;`--size 1000` → `错误: --size 超过上限 50:1000` + `提示: 取值范围 1~50`。
44
45
 
@@ -50,12 +51,16 @@ KB20260928000003 AI智能研发部
50
51
  KB20260921000001 公司资料
51
52
  ```
52
53
 
53
- 空结果输出 `(无知识库)`,不是空行。
54
+ 输出尾部语义(防漏翻页,按此判断是否拿全):
55
+
56
+ - 出现「(共 N 条,还有 M 条;翻页加 --page K)」尾注 → **未拿全**,必须继续用提示的 `--page K` 翻页,直到出现「(共 N 条,已到末页)」
57
+ - 出现「(共 N 条,已到末页)」或无尾注(总数一页装下)→ 已拿全,可以下结论
58
+ - 空结果输出 `(无知识库)`(不是空行);页码超界输出「(本页无数据:共 N 条,--page X 超出范围)」——有库但页码太大,别当空库上报
54
59
 
55
60
  `--json` 结构(信封 `text` 需二次解析):
56
61
 
57
62
  ```json
58
- {"records":[{"kbCode":"...","kbName":"...","description":"...","coverType":"preset","coverValue":"cover-tone-5","coverUrl":null,"ownerName":"张三","memberCount":1,"docCount":null,"role":"owner","graphEnabled":true,"ownerUserId":"U00000001","createdBy":"...","createTime":"2026-10-09 09:45:07","updateTime":"...","editedBy":"...","editorName":"...","editedAt":"..."}],"total":16,"page":1,"size":10}
63
+ {"records":[{"kbCode":"...","kbName":"...","description":"...","coverType":"preset","coverValue":"cover-tone-5","coverUrl":null,"ownerName":"张三","memberCount":1,"docCount":null,"role":"owner","graphEnabled":true,"ownerUserId":"U00000001","createdBy":"...","createTime":"2026-10-09 09:45:07","updateTime":"...","editedBy":"...","editorName":"...","editedAt":"..."}],"total":15,"page":1,"size":50}
59
64
  ```
60
65
 
61
66
  **坑**:`records[].docCount` 在 list 里**恒为 `null`**(服务端只 detail 返回)。想知道各库文档数,逐库 `kb detail`,或直接说明拿不到;不要拿 `null` 当「空库」告诉用户。
@@ -270,7 +275,7 @@ yos docs create "方案" --parent ND20261010000028 --file ./plan.md
270
275
  | `<标题>` | `title` | 必填,≤128 字 |
271
276
  | `--content` / `--file` | `content` | **正文必填且不得为空白,两者互斥**。`--file` 读 UTF-8 文件内容;文件不存在 → `错误: 文件不存在或不可读:<路径>`(exit 2) |
272
277
  | `--kb` / `--parent` | `kb_code` / `parent_code` | 至少一个;都不传 → `错误: --kb、--parent 至少传一个`(exit 2) |
273
- | `--type` | `doc_type` | `md`(缺省)\| `cloud` \| `sheet`。`cloud`/`sheet` 的 `content` 要传对应草稿/快照 JSON,不是普通文本 |
278
+ | `--type` | `doc_type` | `md`(缺省)\| `cloud` \| `sheet`(后两者正文是结构化草稿 JSON,**先读 yos-doc-sheet 技能**) |
274
279
 
275
280
  成功:`文档创建成功,节点编码:ND20261010000030`
276
281
 
@@ -280,6 +285,12 @@ yos docs create "方案" --parent ND20261010000028 --file ./plan.md
280
285
 
281
286
  多行、含引号或 shell 特殊字符的正文一律写临时文件走 `--file`,不要用 `--content` 拼字符串。
282
287
 
288
+ **`--type cloud` / `--type sheet` 的正文是结构化 JSON,不是普通文本**:
289
+
290
+ - 正文内容(标题、段落、表格数据等)都编码在 JSON 里,只改外层 `--title` 不会改正文;反过来 JSON 结构错了服务端也照样存,**渲染成什么样以客户端打开为准**
291
+ - 编写规范、完整结构定义与真实可跑样例一律见 **`yos-doc-sheet` 技能**:新建(`docs create`)与修改(`docs update`)用的是同一份结构
292
+ - 一般场景的判定:用户上传的办公文件(`kb upload`)与 Markdown 文本(`--type md`)不需要本技能;**往知识库写「在线文档/在线表格」正文**才需要
293
+
283
294
  ### 2.7 `docs update` — 改标题/正文/简介
284
295
 
285
296
  ```bash
@@ -298,6 +309,8 @@ yos docs content ND20261010000030 --json # 1. 取当前完整正文
298
309
  yos docs update ND20261010000030 --file ./new.md # 3. 整体回传
299
310
  ```
300
311
 
312
+ 云文档/云表格节点(`docType=cloud`/`sheet`)的正文回传的是**对应草稿 JSON**(`docs content` 读回的 `content` 是 JSON 字符串,二次解析后修改再整体回传;结构与新建时相同,见 `yos-doc-sheet` 技能)。上传的办公文件(`docType=file`)没有内联正文,`docs update` 改不了其内容。
313
+
301
314
  改完会触发 cortex 重新解析,检索索引近实时(实测新文档写完即可被 `retrieve search` 命中并排到首位)。
302
315
 
303
316
  **文档改名只能用 `docs update --title`**;`docs rename` 只用于文件夹,对文档执行 → `工具执行失败:节点类型不符:ND20261010000018 实际是文档,本操作要求文件夹`(exit 1)。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yos-retrieval
3
- description: 用 yos retrieve 五命令检索 YOS 知识库并按带出处的原文作答(search 定位 → read 取原文 → grep/outline/neighbors 辅助,含 URN 规则、全参数表、实测报错)。用户问公司制度/流程/资料、要引用原文、要找某编号或条款、问有哪些文档时使用
3
+ description: 用 yos retrieve 五命令检索 YOS 知识库并按带出处的原文作答(search 定位 → read 取原文 → grep/outline/neighbors 辅助,含 URN 规则、全参数表、实测报错)。用户提到 yos/YOS/小y 且要检索知识库找答案(制度/流程/规范、部门/工作/个人资料、引用原文、找编号条款、问有哪些文档)时使用
4
4
  ---
5
5
 
6
6
  # YOS 知识检索(`yos retrieve`)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yos-shared
3
- description: YOS CLI 共享约定(登录配置、--json 双重解析、退出码、报错分类、通用参数规则、安全与权限)。使用任何 yos 命令前读本文件;遇到报错或不确定参数写法也查这里
3
+ description: YOS CLI 共享约定(登录配置、--json 双重解析、退出码、报错分类、通用参数规则、安全与权限)。用户提到 yos/YOS/小y 或使用任何 yos 命令前读本文件;遇到报错或不确定参数写法也查这里
4
4
  ---
5
5
 
6
6
  # YOS CLI 共享约定
@@ -10,18 +10,17 @@ description: YOS CLI 共享约定(登录配置、--json 双重解析、退出
10
10
  ## 1. 前置检查(会话内只做一次)
11
11
 
12
12
  ```bash
13
- yos doctor # 七项全 ✓ 才能继续;任一项 ✗ 按下方「未登录/连通失败」处理
13
+ yos doctor # 全部 ✓ 才能继续;任一项 ✗ 按下方「未登录/连通失败」处理
14
14
  ```
15
15
 
16
- `yos doctor` 真实输出(七项检查,退出码即结论):
16
+ `yos doctor` 真实输出(退出码即结论):
17
17
 
18
18
  ```
19
19
  ✓ 配置文件: 已找到
20
- ✓ 服务环境: 生产(来自 内置缺省)
21
20
  ✓ 访问令牌: xxxxxxxx****xxxx
22
21
  ✓ 服务连通: 身份 张三(U00000001)
23
22
  ✓ Skill 安装: ~/.claude/skills, ~/.qoder-cn/skills
24
- ✓ CLI 版本: 0.2.0(环境=生产)
23
+ ✓ CLI 版本: 0.2.0
25
24
  ✓ Skill 同步: 与 CLI 一致(2 个目录)
26
25
  ```
27
26
 
@@ -30,14 +29,14 @@ yos doctor # 七项全 ✓ 才能继续;任一项 ✗ 按下方「未登
30
29
  | `command not found: yos` | CLI 未安装或全局 bin 不在 PATH,按 `yos-install` skill 引导安装(`npm install -g @yosai/cli` → `yos login` → 验证),不要继续猜命令 |
31
30
  | `✗ 配置文件: 未找到,请执行 yos login` | 执行 `yos login --key <令牌>`(令牌由用户在 YOS 客户端「个人设置-访问令牌」页创建并复制,40 位小写 hex) |
32
31
  | `✗ 访问令牌: 未配置访问令牌` | 同上;CI/容器可改为设置环境变量 `YOS_API_KEY` |
33
- | `✗ 服务连通: ...` | 看错误类型:网络不可达(退出码 3)→ 检查服务环境与网络;鉴权失败(4)→ 令牌失效,重新 `yos login` |
32
+ | `✗ 服务连通: ...` | 看错误类型:网络不可达(退出码 3)→ 检查网络连通(测试/开发装机确认环境未选错);鉴权失败(4)→ 令牌失效,重新 `yos login` |
34
33
  | `✗ Skill 安装: 尚未安装,执行 yos skill install` | 执行 `yos skill install`,未探测到目录时 `--target ~/.claude/skills` |
35
34
 
36
35
  配置细节(排障时才需要):
37
36
 
38
37
  - 配置文件 `~/.config/yos/config.json`(目录 0700、文件 0600),字段 `{env, apiKey, installedSkillDirs}`
39
38
  - 环境变量优先级:`YOS_API_KEY` > 配置文件 `apiKey`;`YOS_ENV` > 配置文件 `env`;`YOS_CONFIG_DIR` 覆盖配置目录(测试隔离用)
40
- - 服务环境缺省生产,切换用 `yos login --env test`(临时用 `YOS_ENV=test`);开发者本地调试用 `--env dev`(指向本机 8080 起的服务);`yos doctor` 的「服务环境」项显示当前环境与来源
39
+ - 切换服务环境(测试/开发用):`yos login --env test`(临时用 `YOS_ENV=test`),本地调试 `--env dev`(指向本机 8080 起的服务)
41
40
  - 令牌格式先本地校验:`yos login` 粘贴了非 40 位小写 hex 会直接报 `错误: 令牌格式不正确(应为 40 位小写 hex)`,不会落盘
42
41
 
43
42
  **安全**:绝不把令牌写进命令历史可见的日志、代码仓库或对用户的回复里;`--key` 传令牌仅用于无交互场景,回复中一律用掩码形式(`xxxxxxxx****xxxx`)。
@@ -46,7 +45,7 @@ yos doctor # 七项全 ✓ 才能继续;任一项 ✗ 按下方「未登
46
45
 
47
46
  | 形态 | 实际内容 | 解析方式 |
48
47
  |---|---|---|
49
- | 默认(不加 `--json`) | 直接打印服务端返回文本:多数命令是**单行紧凑 JSON**,少数是纯文本提示;`kb list` 特化为两列表格(`KB编码 名称`) | 人读用;给程序处理请改用 `--json` |
48
+ | 默认(不加 `--json`) | 直接打印服务端返回文本:多数命令是**单行紧凑 JSON**,少数是纯文本提示;`kb list` 特化为两列表格(`KB编码 名称`),未拿全时末尾带「(共 N 条,还有 M 条;翻页加 --page K)」尾注 | 人读用;给程序处理请改用 `--json` |
50
49
  | `--json` | 固定信封 `{"text": "...", "isError": false}` | **需要二次解析**:`text` 是 JSON **字符串**,业务数据要再 `JSON.parse(text)`;`isError: true` 时 `text` 是错误文案(纯文本,不可 parse) |
51
50
 
52
51
  ```bash
@@ -86,7 +85,7 @@ CLI 对两套编码原样透出不做映射。遇到 cortex 侧编码时:可
86
85
  | 0 | 成功 | — | 继续 |
87
86
  | 1 | 业务失败(服务端拒绝/资源不存在) | `工具执行失败:知识库不存在:KB不存在`<br>`节点类型不符:ND... 实际是文档,本操作要求文件夹` | 按文案修参数,不要盲目重试 |
88
87
  | 2 | 参数/用法错误(CLI 本地拦截,未发请求) | `错误: 缺少 --kind`<br>`提示: 用法: yos retrieve neighbors <target> --kind <值> ...` | 照 `提示:` 里的用法改写 |
89
- | 3 | 网络错误/服务不可达 | `错误: 无法连接 YOS 服务(生产),原因:fetch failed` | 确认服务环境与网络连通,`yos ping` 复测 |
88
+ | 3 | 网络错误/服务不可达 | `错误: 无法连接 YOS 服务,原因:fetch failed` | 确认网络连通,`yos ping` 复测;测试/开发装机确认环境未选错 |
90
89
  | 4 | 鉴权失败 | `错误: 鉴权失败...`<br>`提示: 请执行 \`yos login\` 重新配置访问令牌` | 令牌无效/吊销/过期 → 让用户重新创建后 `yos login` |
91
90
  | 5 | 版本过低(服务端最低版本门槛拒绝,请求未生效) | `错误: CLI 版本过低(当前 0.2.0,最低要求 0.3.0),请升级后重试`<br>`提示: 执行 \`yos update\` 升级后重试` | 先执行 `yos update` 升级再原样重试;不要改参数反复试探 |
92
91
 
@@ -128,7 +127,7 @@ exit=1 的文案偶有服务端内部字段名(如 `kb_code`、`output_mode`
128
127
  不要凭记忆或猜测拼编码,按链路取真值:
129
128
 
130
129
  ```bash
131
- yos kb list # → kbCode(表格左列)
130
+ yos kb list # → kbCode(表格左列;末尾有「还有 M 条」尾注时须先翻页拿全)
132
131
  yos docs tree KB20260921000001 # → resourceCode(树里每个节点的编码)
133
132
  yos retrieve outline 'cortex://kb/KB20260921000001' # → 文档 URN(含行号,检索决策用)
134
133
  yos transcript list # → transcriptionUserId
@@ -176,11 +175,19 @@ yos tool call docs_tree --params '{"kb_code":"KB20260921000001"}'
176
175
  - 工具名容忍空格与连字符写法:`yos tool schema docs tree` / `support manual-read` 都会归一化为 `docs_tree` / `support_manual_read`
177
176
  - 域命令是工具的一一映射(`kb upload` 除外,走 multipart 直传),能用域命令就别用 `tool call`
178
177
 
179
- ## 9. 升级与重装
178
+ ## 9. 升级与版本更新约定
180
179
 
181
180
  ```bash
182
- npm install -g @yosai/cli # 公共 npmjs,需 Node >= 18(见 yos-install)
183
- yos skill install # 升级后必须重装 Skill,让 Agent 目录里的说明同步
181
+ yos update # 升到当前环境通道最新版(升级后自动重同步 Skill)
182
+ npm install -g @yosai/cli # 手动等价写法(公共 npmjs,需 Node >= 18,见 yos-install);走这条路后需 yos skill install 刷新 Skill
184
183
  ```
185
184
 
185
+ **版本提示约定(必须遵守)**:任何 yos 命令执行后,stderr 可能出现
186
+
187
+ ```
188
+ 提示: 有新版本 x.y.z(当前 a.b.c),请先执行 yos update 升级再继续任务
189
+ ```
190
+
191
+ 含义是本机 CLI 落后于当前升级通道(测试环境为 test 通道)的最新版。正确动作:先执行 `yos update`,完成后回到原任务继续(刚才的命令重试或接着做后续步骤)。`yos update` 失败(权限不足、网络不可达等)时向用户报告失败原因并继续原任务,不要反复重试升级。服务端强制的版本门槛表现为退出码 5(见第 3 节),同样需先升级再重试。
192
+
186
193
  `yos skill install` 会覆盖写入各 Agent 技能目录,装完需**重启 Agent 工具**才生效;`yos doctor` 的「Skill 安装」项可确认已安装目录。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yos-support
3
- description: YOS 帮助与支持(manual/manual-read/manual-search 帮助手册,upgrade/upgrade-log 客户端版本,feedback 提交反馈)。用户问 YOS 怎么用、要客户端最新版本、要报问题时使用
3
+ description: YOS 帮助与支持(manual/manual-read/manual-search 帮助手册,upgrade/upgrade-log 客户端版本,feedback 提交反馈)。用户提到 yos/YOS/小y 且要查 YOS 使用手册、客户端最新版本、提交反馈时使用
4
4
  ---
5
5
 
6
6
  # YOS 帮助与支持(support)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yos-transcript
3
- description: YOS 录音转写查询(transcript list 列表 / transcript detail 详情,含分段、纪要、思维导图、音频地址与字段坑)。用户想看会议录音转写、要纪要、查某次会议内容时使用
3
+ description: YOS 录音转写查询(transcript list 列表 / transcript detail 详情,含分段、纪要、思维导图、音频地址与字段坑)。用户提到 yos/YOS/小y 且要看会议录音转写、要纪要、查某次会议内容时使用
4
4
  ---
5
5
 
6
6
  # YOS 录音转写(transcript)
@@ -1,12 +1,8 @@
1
- import { mkdirSync, realpathSync, rmSync, statSync, writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
1
+ import { realpathSync } from 'node:fs';
3
2
  import { fileURLToPath } from 'node:url';
4
- import { configDir, loadConfig, resolveChannel } from './config.js';
5
- import { compareVersions, detectGlobalInstall, fetchLatestVersion, PUBLIC_REGISTRY, readPackageMeta, runNpm, } from './npm-meta.js';
6
- import { installSkillsTo } from './skill-sync.js';
3
+ import { loadConfig, resolveChannel } from './config.js';
4
+ import { fetchLatestVersion, readPackageMeta } from './npm-meta.js';
7
5
  import { saveCheckState } from './update-notice.js';
8
- import { saveVersionState } from './version-state.js';
9
- const LOCK_STALE_MS = 10 * 60 * 1000;
10
6
  export async function runUpdateCheck() {
11
7
  const meta = readPackageMeta();
12
8
  if (!meta) {
@@ -18,70 +14,11 @@ export async function runUpdateCheck() {
18
14
  }
19
15
  try {
20
16
  const latest = await fetchLatestVersion(meta.name, channel);
21
- if (compareVersions(meta.version, latest) < 0 && !autoUpdateDisabled() && acquireUpdateLock()) {
22
- try {
23
- await silentUpdate(meta, latest, channel);
24
- }
25
- finally {
26
- releaseUpdateLock();
27
- }
28
- }
29
17
  saveCheckState(latest, channel);
30
18
  }
31
19
  catch {
32
20
  }
33
21
  }
34
- async function silentUpdate(meta, latest, channel) {
35
- const shape = await detectGlobalInstall(meta);
36
- if (!shape.global) {
37
- return;
38
- }
39
- const install = await runNpm(['install', '-g', `${meta.name}@${channel}`, `--registry=${PUBLIC_REGISTRY}`]);
40
- if (!install.ok) {
41
- return;
42
- }
43
- const dirs = loadConfig()?.installedSkillDirs ?? [];
44
- if (dirs.length > 0) {
45
- installSkillsTo(dirs);
46
- }
47
- saveVersionState(latest);
48
- }
49
- function autoUpdateDisabled() {
50
- return Boolean(process.env.YOS_NO_AUTO_UPDATE);
51
- }
52
- function updateLockPath() {
53
- return join(configDir(), 'update.lock');
54
- }
55
- function acquireUpdateLock() {
56
- mkdirSync(configDir(), { recursive: true, mode: 0o700 });
57
- const path = updateLockPath();
58
- try {
59
- writeFileSync(path, `${Date.now()}`, { flag: 'wx', mode: 0o600 });
60
- return true;
61
- }
62
- catch (error) {
63
- if (error.code !== 'EEXIST') {
64
- return false;
65
- }
66
- }
67
- try {
68
- if (Date.now() - statSync(path).mtimeMs > LOCK_STALE_MS) {
69
- rmSync(path, { force: true });
70
- writeFileSync(path, `${Date.now()}`, { flag: 'wx', mode: 0o600 });
71
- return true;
72
- }
73
- }
74
- catch {
75
- }
76
- return false;
77
- }
78
- function releaseUpdateLock() {
79
- try {
80
- rmSync(updateLockPath(), { force: true });
81
- }
82
- catch {
83
- }
84
- }
85
22
  export function isDirectRun(argv1, moduleUrl) {
86
23
  if (!argv1) {
87
24
  return false;
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url';
5
5
  import { configDir, loadConfig, resolveChannel } from './config.js';
6
6
  import { compareVersions, getCliVersion } from './npm-meta.js';
7
7
  import { printErr } from './output.js';
8
- const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
8
+ const CACHE_TTL_MS = 2 * 60 * 60 * 1000;
9
9
  const SKIP_COMMANDS = new Set(['update', 'version']);
10
10
  function checkStatePath() {
11
11
  return join(configDir(), 'update-check.json');
@@ -45,9 +45,9 @@ export function evaluateNotice(input) {
45
45
  if (compareVersions(input.currentVersion, input.state.latest) >= 0) {
46
46
  return 'skip';
47
47
  }
48
- return input.tty && !input.argv.includes('--json') ? 'notify' : 'skip';
48
+ return 'notify';
49
49
  }
50
- export function handleUpdateNotice(argv, commandName) {
50
+ export function handleUpdateNotice(commandName) {
51
51
  try {
52
52
  const channel = resolveChannel(loadConfig());
53
53
  if (channel === null) {
@@ -56,10 +56,8 @@ export function handleUpdateNotice(argv, commandName) {
56
56
  const currentVersion = getCliVersion();
57
57
  const state = loadCheckState(channel);
58
58
  const decision = evaluateNotice({
59
- argv,
60
59
  commandName,
61
60
  state,
62
- tty: Boolean(process.stderr.isTTY),
63
61
  now: new Date(),
64
62
  currentVersion,
65
63
  });
@@ -68,7 +66,7 @@ export function handleUpdateNotice(argv, commandName) {
68
66
  return;
69
67
  }
70
68
  if (decision === 'notify' && state) {
71
- printErr(`提示: 有新版本 ${state.latest}(当前 ${currentVersion}),执行 yos update 升级`);
69
+ printErr(`提示: 有新版本 ${state.latest}(当前 ${currentVersion}),请先执行 yos update 升级再继续任务`);
72
70
  }
73
71
  }
74
72
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yosai/cli",
3
- "version": "0.2.1-test.7",
3
+ "version": "0.2.1-test.8",
4
4
  "description": "YOS 能力的 Agent 执行入口:工具调用、知识库管理与文件上传",
5
5
  "type": "module",
6
6
  "bin": {