@fnnas-labs/fnos-cli 0.0.0-stage → 0.2.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -2
  3. package/THIRD_PARTY_NOTICES.txt +38904 -0
  4. package/cordis.patch.yml +3 -0
  5. package/npm/README.dsh.md +49 -0
  6. package/npm/acceptance-report.cjs +53 -0
  7. package/npm/dsh-integration.mjs +159 -0
  8. package/npm/dsh-test-support.mjs +55 -0
  9. package/npm/dsh.mjs +31 -0
  10. package/npm/install.cjs +140 -0
  11. package/npm/package-lib.cjs +274 -0
  12. package/npm/run.cjs +39 -0
  13. package/package.json +46 -4
  14. package/skill/LICENSE +21 -0
  15. package/skill/SKILL.md +143 -0
  16. package/skill/THIRD_PARTY_NOTICES.txt +38904 -0
  17. package/skill/bin/trim-cli-darwin-arm64 +0 -0
  18. package/skill/bin/trim-cli-darwin-x64 +0 -0
  19. package/skill/bin/trim-cli-linux-arm64 +0 -0
  20. package/skill/bin/trim-cli-linux-x64 +0 -0
  21. package/skill/bin/trim-cli-windows-arm64.exe +0 -0
  22. package/skill/bin/trim-cli-windows-x64.exe +0 -0
  23. package/skill/build-provenance.json +44 -0
  24. package/skill/entries/trim-app.md +63 -0
  25. package/skill/entries/trim-baidu-netdisk.md +42 -0
  26. package/skill/entries/trim-docker.md +35 -0
  27. package/skill/entries/trim-download.md +38 -0
  28. package/skill/entries/trim-file.md +30 -0
  29. package/skill/entries/trim-log.md +32 -0
  30. package/skill/entries/trim-monitor.md +41 -0
  31. package/skill/entries/trim-network.md +22 -0
  32. package/skill/entries/trim-photos.md +32 -0
  33. package/skill/entries/trim-shared.md +54 -0
  34. package/skill/entries/trim-storage.md +34 -0
  35. package/skill/entries/trim-system.md +59 -0
  36. package/skill/entries/trim-user.md +28 -0
  37. package/skill/manifest.json +43 -0
  38. package/skill/reference/_conventions.md +76 -0
  39. package/skill/reference/_index.md +78 -0
  40. package/skill/reference/app-center.md +234 -0
  41. package/skill/reference/baidu-netdisk.md +221 -0
  42. package/skill/reference/dockermgr.md +244 -0
  43. package/skill/reference/download.md +357 -0
  44. package/skill/reference/file.md +752 -0
  45. package/skill/reference/log.md +224 -0
  46. package/skill/reference/network.md +41 -0
  47. package/skill/reference/oauth.md +51 -0
  48. package/skill/reference/photos.md +158 -0
  49. package/skill/reference/power.md +34 -0
  50. package/skill/reference/resmon.md +160 -0
  51. package/skill/reference/stor.md +525 -0
  52. package/skill/reference/sysinfo.md +133 -0
  53. package/skill/reference/user.md +139 -0
  54. package/skill/reference/workflows/device-validation.md +66 -0
  55. package/skill/reference/workflows/file-routing.md +44 -0
  56. package/skill/reference/workflows/file-upload-validation.md +63 -0
  57. package/skill/reference/workflows/photos-routing.md +83 -0
  58. package/skill/reference/workflows/storage-dangerous-ops.md +53 -0
  59. package/skill/scripts/fnos-cli +63 -0
  60. package/skill/scripts/fnos-cli.cmd +36 -0
  61. package/skill/scripts/fnos-cli.ps1 +31 -0
  62. package/skill/scripts/trim-cli +63 -0
  63. package/skill/scripts/trim-cli.cmd +36 -0
  64. package/skill/scripts/trim-cli.ps1 +31 -0
@@ -0,0 +1,224 @@
1
+ # log 模块
2
+
3
+ ## 模块概述
4
+ 日志中心模块,涵盖日志查询、模块枚举、日志清除、导出和归档策略管理。
5
+
6
+ ## 模块约定
7
+ - 操作日志、审计日志和日志服务控制应区分处理。
8
+ - 当前 fnos-cli 实现的端点属于 `appcgi.eventlogger.common.*` 命名空间。
9
+
10
+ ## 端点索引
11
+ - 已实现:
12
+ - `appcgi.eventlogger.common.list`
13
+ - `appcgi.eventlogger.common.moduleList`
14
+ - `appcgi.eventlogger.common.clear`
15
+ - `appcgi.eventlogger.common.export`
16
+ - `appcgi.eventlogger.common.archive`(设置归档策略)
17
+ - `appcgi.eventlogger.common.archive.get`(查询归档策略)
18
+ - `appcgi.eventlogger.debuglog.copyStart`(开始复制诊断日志)
19
+ - `appcgi.eventlogger.debuglog.copyStop`(取消复制诊断日志)
20
+ - 未实现:
21
+ - `log.*`(旧版日志查询家族)
22
+
23
+ ## 端点详情
24
+
25
+ ### appcgi.eventlogger.common.list
26
+
27
+ #### Endpoint
28
+ `appcgi.eventlogger.common.list`
29
+
30
+ #### Purpose
31
+ 按页查询日志中心记录,支持按级别和模块过滤。
32
+
33
+ #### Trim CLI Mapping
34
+ ```
35
+ fnos-cli logger list [--page <n>] [--page-size <n>] [--level <n>] [--module <n>] [--locale <locale>]
36
+ ```
37
+
38
+ #### Request
39
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
40
+ | --- | --- | --- | --- | --- | --- | --- |
41
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.common.list` |
42
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
43
+ | `pageSize` | body | no | number | 每页条数 | 正整数 | `50` |
44
+ | `page` | body | no | number | 页码 | 正整数 | `1` |
45
+ | `level` | body | no | number | 日志级别过滤 | 数值型级别标识 | `3` |
46
+ | `module` | body | no | number | 日志模块过滤 | 数值型模块标识 | `1` |
47
+ | `locale` | body | no | string | 语言/区域 | 影响返回文本的语言 | `zh-CN` |
48
+
49
+ #### Response
50
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
51
+ | --- | --- | --- | --- | --- | --- |
52
+ | `data` | no | object | 日志数据 | 包含日志条目和分页信息 | `{...}` |
53
+ | `result` | no | string | Terminal marker | `succ`/`fail` | `succ` |
54
+ | `errno` | no | number | 错误码 | 失败时出现 | `65534` |
55
+ | `errmsg` | no | string | 错误描述 | 失败时出现 | `invalid filter` |
56
+
57
+ ### appcgi.eventlogger.common.moduleList
58
+
59
+ #### Endpoint
60
+ `appcgi.eventlogger.common.moduleList`
61
+
62
+ #### Purpose
63
+ 列出可用的日志模块。
64
+
65
+ #### Trim CLI Mapping
66
+ ```
67
+ fnos-cli logger modules [--locale <locale>]
68
+ ```
69
+
70
+ #### Request
71
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
72
+ | --- | --- | --- | --- | --- | --- | --- |
73
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.common.moduleList` |
74
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
75
+ | `locale` | body | no | string | 语言/区域 | 影响模块名称的语言 | `zh-CN` |
76
+
77
+ ### appcgi.eventlogger.common.clear
78
+
79
+ #### Endpoint
80
+ `appcgi.eventlogger.common.clear`
81
+
82
+ #### Purpose
83
+ 按日志级别和模块清空日志记录。
84
+
85
+ #### Trim CLI Mapping
86
+ ```
87
+ fnos-cli logger clear --level <level> --module <module> --yes
88
+ ```
89
+
90
+ #### Request
91
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
92
+ | --- | --- | --- | --- | --- | --- | --- |
93
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.common.clear` |
94
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
95
+ | `level` | body | yes | number | 日志级别 | 必填 | `3` |
96
+ | `module` | body | yes | number | 日志模块 | 必填 | `1` |
97
+
98
+ ### appcgi.eventlogger.common.export
99
+
100
+ #### Endpoint
101
+ `appcgi.eventlogger.common.export`
102
+
103
+ #### Purpose
104
+ 按日志级别和模块导出日志记录。
105
+
106
+ #### Trim CLI Mapping
107
+ ```
108
+ fnos-cli logger export --level <level> --module <module> [--locale <locale>] --yes
109
+ ```
110
+
111
+ #### Request
112
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
113
+ | --- | --- | --- | --- | --- | --- | --- |
114
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.common.export` |
115
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
116
+ | `level` | body | yes | number | 日志级别 | 必填 | `3` |
117
+ | `module` | body | yes | number | 日志模块 | 必填 | `1` |
118
+ | `locale` | body | no | string | 语言/区域 | 影响导出内容的语言 | `zh-CN` |
119
+
120
+ ### appcgi.eventlogger.common.archive
121
+
122
+ #### Endpoint
123
+ `appcgi.eventlogger.common.archive`
124
+
125
+ #### Purpose
126
+ 设置日志归档策略。
127
+
128
+ #### Trim CLI Mapping
129
+ ```
130
+ fnos-cli logger archive set --switch <0|1> --file-path <path> [--size-gt <n>] [--date-unit <n>] [--date-before <n>] --yes
131
+ ```
132
+
133
+ #### Request
134
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
135
+ | --- | --- | --- | --- | --- | --- | --- |
136
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.common.archive` |
137
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
138
+ | `switch` | body | yes | number | 归档开关 | `0` 关闭,`1` 开启 | `1` |
139
+ | `filePath` | body | yes | string | 归档文件路径 | 禁用归档时可传空字符串 | `/vol1/logs` |
140
+ | `sizeGt` | body | no | number | 文件大小阈值 | 可选 | `1024` |
141
+ | `dateUnit` | body | no | number | 日期单位 | `0` 天,`1` 周,`2` 月,`3` 年 | `2` |
142
+ | `dateBefore` | body | no | number | 日期偏移量 | 可选 | `3` |
143
+
144
+ #### Field Semantics
145
+ - `switch` 为 `0` 时表示关闭归档,此时 `filePath` 可传空字符串。
146
+ - `dateUnit` 定义时间粒度:`0` 天、`1` 周、`2` 月、`3` 年。
147
+
148
+ ### appcgi.eventlogger.common.archive.get
149
+
150
+ #### Endpoint
151
+ `appcgi.eventlogger.common.archive.get`
152
+
153
+ #### Purpose
154
+ 查询当前日志归档配置。
155
+
156
+ #### Trim CLI Mapping
157
+ ```
158
+ fnos-cli logger archive query
159
+ ```
160
+
161
+ #### Protocol Notes
162
+ - 响应包含当前归档配置,CLI 直接打印后端返回的 payload。
163
+ - 响应中 `validPath` 字段(如存在)表示路径有效性状态。
164
+
165
+ ### appcgi.eventlogger.debuglog.copyStart
166
+
167
+ #### Endpoint
168
+ `appcgi.eventlogger.debuglog.copyStart`
169
+
170
+ #### Purpose
171
+ 复制后端诊断日志(Debug Log)到指定输出目录,并返回任务进度。
172
+
173
+ #### Trim CLI Mapping
174
+ ```
175
+ fnos-cli logger debuglog copy-start --output-dir <path> [--srv-type <0|1|2>]... --yes
176
+ fnos-cli diagnostic-log export --output-dir <path> [--srv-type <0|1|2>]... --yes
177
+ ```
178
+
179
+ #### Request
180
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
181
+ | --- | --- | --- | --- | --- | --- | --- |
182
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.debuglog.copyStart` |
183
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
184
+ | `outputDir` | body | yes | string | 输出目录 | CLI 要求已挂载存储空间或外挂盘路径,格式如 `/vol1/<dir>` 或 `/vol00/<mount>/<dir>`;不要使用系统目录如 `/tmp`、`/var/tmp`、`/home/...` | `/vol00/RemovableDisk/debug-log` |
185
+ | `srvType` | body | no | number[] | 复制类别 | `0` 系统,`1` 内置应用,`2` 内置服务;未传时后端按全部类别处理。CLI 支持重复传入或逗号分隔,并按顺序去重。 | `[0,1,2]` |
186
+
187
+ #### Response
188
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
189
+ | --- | --- | --- | --- | --- | --- |
190
+ | `taskId` | no | string | 复制任务 ID | doing/success 进度帧的 `data` 中返回 | `ftask_1` |
191
+ | `fileNumTotal` | no | number | 需要复制的文件总数 | 进度帧返回 | `51` |
192
+ | `fileNumDone` | no | number | 已复制文件数 | 进度帧返回 | `2` |
193
+
194
+ #### Protocol Notes
195
+ - 后端可能先返回 `result:"doing"` 进度帧,再返回终态帧。CLI 会优先展示带 `taskId` 的进度 payload,方便后续执行 `diagnostic-log stop`。
196
+ - `outputDir` 必须预先存在于设备侧已挂载的存储空间或外挂盘下。普通存储常见路径是 `/volN/<uid>/...`;外挂盘常见路径是 `/vol00/<mount-name>/...`。
197
+
198
+ #### Errors
199
+ - 常见错误包括缺少 `outputDir`、目录不存在、创建目录失败、目录不可写、磁盘空间不足、重复任务、任务不存在等。
200
+
201
+ ### appcgi.eventlogger.debuglog.copyStop
202
+
203
+ #### Endpoint
204
+ `appcgi.eventlogger.debuglog.copyStop`
205
+
206
+ #### Purpose
207
+ 取消正在进行的诊断日志复制任务。
208
+
209
+ #### Trim CLI Mapping
210
+ ```
211
+ fnos-cli logger debuglog copy-stop --task-id <taskId> --yes
212
+ fnos-cli diagnostic-log stop --task-id <taskId> --yes
213
+ ```
214
+
215
+ #### Request
216
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
217
+ | --- | --- | --- | --- | --- | --- | --- |
218
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.eventlogger.debuglog.copyStop` |
219
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
220
+ | `taskId` | body | yes | string | 复制任务 ID | CLI 要求非空且不包含空白字符 | `ftask_1` |
221
+
222
+ ## 注意事项
223
+ - 旧版 `log.*` 家族端点和当前 `appcgi.eventlogger.common.*` 端点可能在不同固件版本上共存。
224
+ - `logger debuglog copy-start` / `diagnostic-log export` 的 `outputDir` 需要选择已挂载存储空间或外挂盘路径;系统盘路径不是有效诊断日志导出目标。
@@ -0,0 +1,41 @@
1
+ # network 模块
2
+
3
+ ## 模块概述
4
+
5
+ 网络模块用于管理设备网络相关服务开关。当前 CLI 覆盖 SSH 服务开关。
6
+
7
+ ## 端点索引
8
+
9
+ - 已实现:
10
+ - `appcgi.network.ssh.switch`(开启或关闭 SSH 服务)
11
+
12
+ ## appcgi.network.ssh.switch
13
+
14
+ ### Endpoint
15
+
16
+ `appcgi.network.ssh.switch`
17
+
18
+ ### Purpose
19
+
20
+ 开启或关闭设备 SSH 服务。
21
+
22
+ ### Trim CLI Mapping
23
+
24
+ ```bash
25
+ fnos-cli network ssh switch --enable [--yes]
26
+ fnos-cli network ssh switch --disable [--yes]
27
+ ```
28
+
29
+ ### Request
30
+
31
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
32
+ | --- | --- | --- | --- | --- | --- | --- |
33
+ | `req` | body | yes | string | Endpoint selector | 固定值 | `appcgi.network.ssh.switch` |
34
+ | `reqid` | body | yes | string | Request correlation ID | 每次请求生成 | `69ba...` |
35
+ | `enable` | body | yes | boolean | 是否开启 SSH | `true` 开启,`false` 关闭 | `true` |
36
+
37
+ ### Notes
38
+
39
+ - `--enable` 与 `--disable` 必须二选一。
40
+ - 开启 SSH 是安全敏感操作,默认需要确认;用户明确授权后才使用 `--yes`。
41
+ - 命令需要已登录 session,并通过认证链执行。
@@ -0,0 +1,51 @@
1
+ # OAuth 参考
2
+
3
+ ## 固定参数
4
+
5
+ - `client_id`: `YJNMPJUGA9`
6
+ - `scope`: `trim.user.all trim.file.read trim.file.write trim.download.all trim.appcenter.all trim.photo.all trim.system.all trim.log.all trim.storage.all trim.docker.all`;产品专属 scope 见对应 reference
7
+ - `code_challenge_method`: `S256`
8
+ - device name/model: `trim-cli` / `CLI`
9
+ - 授权 code 有效期:5 分钟
10
+
11
+ ## 登录
12
+
13
+ ```bash
14
+ fnos-cli --profile home --host <host> --port <port> login
15
+ ```
16
+
17
+ 生产环境只使用这一条交互式流程:CLI 输出 `/signin` 授权链接并保持运行;用户自行在浏览器
18
+ 输入账号密码、确认授权、复制页面显示的一次性 code,再粘贴到 CLI 的
19
+ `Authorization code` 提示。CLI 随后完成 token 交换。
20
+
21
+ Agent 不代填账号密码、不自动点击授权、不读取页面 code,也不把 code 放进命令参数。CLI 无法
22
+ 自动打开浏览器时可添加 `--no-open`,但用户授权和交互式输入步骤不变。
23
+
24
+ 授权 URL 包含 PKCE challenge、client、scope 和 device 参数,不包含 `redirect_uri`。pending
25
+ verifier 按 profile 隔离,过期后必须重新运行完整的交互式 `login`。授权 code 只能交换一次。
26
+ `trim.basic` 不属于当前可申请列表,CLI 不显式申请。旧的 `file photo` scope 或缺少当前模块
27
+ 所需 scope 的 session 不再兼容,必须重新登录;refresh token 不能用来扩展原授权范围。
28
+
29
+ ## Refresh
30
+
31
+ ```bash
32
+ fnos-cli --profile home login --refresh
33
+ ```
34
+
35
+ 命令开始前 access token 在 60 秒内过期会自动 refresh。代理 `/ogh/ac/w` 或原生 HTTP
36
+ `/ogh/ac/h/*` 返回 401 时,CLI 按 profile 加锁 refresh 并只重试一次;第二次仍 401 时停止。
37
+ refresh 返回新 refresh token 时替换旧值,未返回时保留旧值。刷新前 CLI 会把当前 session 原值
38
+ 写回当前 profile,确认真实存储目标可写;预检失败时不会发送 refresh 请求,因此不会消耗可能轮换的 refresh token。
39
+ `ask-file` 的存储选择只会询问一次,并沿用到本次刷新提交。多进程获得锁后会重新读取 session,
40
+ 已被其他进程刷新时直接使用新 token,不覆盖较新的 session。
41
+
42
+ 存储仍可能在请求发出后失效。若 refresh 成功但最终 session 写入失败,不要反复使用旧 refresh
43
+ token;服务端可能已完成轮换,应重新执行交互式 OAuth 登录。
44
+
45
+ ## Session 与 logout
46
+
47
+ session 保存 access/refresh token、过期时间、OAuth client/device/scope 和用户摘要。
48
+ `logout` 清理当前 profile 的 session 和 pending 文件,不承诺远端撤销令牌。
49
+
50
+ 失败时重新执行交互式 OAuth 登录;不回退到 CLI 用户名密码、2FA 或旧 token 恢复流程。授权
51
+ code、code verifier、access token 和 refresh token 不应出现在命令参数、输出、日志或错误信息中。
@@ -0,0 +1,158 @@
1
+ # Photos reference
2
+
3
+ ## Authentication
4
+
5
+ Photos 使用当前 profile 的系统 access token,通过 `/ogh/ac/h/*uri` 调用原生 HTTP API。当前命令目标
6
+ 必须与该 profile 保存的 session 目标一致。没有有效 session 时先执行 OAuth `login`;Photos
7
+ 不需要额外的应用登录或独立签名。
8
+
9
+ ## Command index
10
+
11
+ | Command | Output |
12
+ | --- | --- |
13
+ | `photos folders` | 已加入相册扫描的目录、扫描状态和照片/视频数量 |
14
+ | `photos search <keyword>` | 条件搜索的匹配项、时间线和总数 |
15
+ | `photos info <id>` | 文件、拍摄、位置、标签和缩略图字段 |
16
+ | `photos preview <id>` | 指定尺寸的绝对预览地址 |
17
+ | `photos request <method> <path>` | 未封装端点的原始 HTTP 与业务响应 |
18
+
19
+ ## Response rules
20
+
21
+ 命名命令会检查 HTTP 状态和业务信封;HTTP 非 2xx、`code != 0` 或缺失 `data` 都会失败。
22
+ 命名搜索和详情还会把相对的 `*Url` 字段转换为绝对地址。
23
+
24
+ `photos request` 用于原始端点,不应用命名命令的业务信封检查,输出固定为:
25
+
26
+ ```json
27
+ {
28
+ "httpStatus": 200,
29
+ "response": { "code": 0, "msg": "", "data": {} }
30
+ }
31
+ ```
32
+
33
+ Agent 必须同时确认 `httpStatus` 位于 `200..299` 且 `response.code == 0`。不能只根据 CLI
34
+ 退出码判断通用请求成功。
35
+
36
+ ## Watched folders
37
+
38
+ ```bash
39
+ fnos-cli photos folders
40
+ ```
41
+
42
+ 请求 `GET /p/api/v1/photo/folder/list`,没有业务参数。输出 `list[]` 的主要字段:
43
+
44
+ | Field | Type | Meaning |
45
+ | --- | --- | --- |
46
+ | `folderId` | integer | Photos 扫描目录 ID |
47
+ | `folderPath` | string | fnOS 目录路径 |
48
+ | `photoCount` | integer | 当前索引中的照片数量 |
49
+ | `videoCount` | integer | 当前索引中的视频数量 |
50
+ | `status` | integer | `0` 扫描中,`1` 完成,`2` 目录异常,`4` 未知 |
51
+ | `disable` | integer | 目录是否允许从扫描范围移除 |
52
+ | `hasWriteAccess.hasWriteAccess` | boolean | 当前用户是否有写权限 |
53
+ | `hasWriteAccess.quotaCurr` | integer | 当前已用配额 |
54
+ | `hasWriteAccess.quotaMax` | integer | 最大配额 |
55
+ | `isDefault` | boolean | 是否为默认扫描目录 |
56
+
57
+ 目录处于扫描中时数量仍可能变化;目录异常时不要把当前计数表述为最终值。这里统计的是
58
+ Photos 索引范围,不等于文件系统中全部图片数量。
59
+
60
+ ## Conditional search
61
+
62
+ ```bash
63
+ fnos-cli photos search IMG --limit 20
64
+ fnos-cli photos search 北京 --filter file_type=photo
65
+ fnos-cli photos search 北京 --exclude-filter not_geo=1
66
+ ```
67
+
68
+ 请求 `POST /p/api/v2/search/results`。请求字段:
69
+
70
+ | Field | Required | Type | Meaning |
71
+ | --- | --- | --- | --- |
72
+ | `keyword` | yes | string | 条件搜索关键词;CLI 拒绝空字符串 |
73
+ | `limit` | yes | integer | 返回样本上限,CLI 接受 `1..200`,默认 `20` |
74
+ | `filters` | yes | array | 正向 `{filterName, filterValue}` 条件 |
75
+ | `antiFilters` | no | array | 排除 `{filterName, filterValue}` 条件 |
76
+
77
+ `--filter` 和 `--exclude-filter` 使用 `name=value`,可以重复。常见过滤名包括
78
+ `file_type`、`is_collect`、`person`、`photo_tag` 和 `file_dir`。`file_type` 常见值包括
79
+ `photo`、`video`、`live_photo`、`gif`、`raw`、`360`、`panorama` 和 `screenshot`;其他过滤值
80
+ 取决于设备上的 Photos 版本和索引内容。
81
+
82
+ 响应主要字段:
83
+
84
+ | Field | Type | Meaning |
85
+ | --- | --- | --- |
86
+ | `list[]` | array | 当前返回的照片/视频样本 |
87
+ | `timeline[]` | array | 按 `year`、`month`、`day` 聚合的 `itemCount` |
88
+ | `total` | integer | 服务端报告的全部匹配数量,不等于 `list` 长度 |
89
+ | `list[].id` | integer | 详情和预览命令使用的照片 ID |
90
+ | `list[].category` | string | `photo` 或 `video` |
91
+ | `list[].fileName` | string | 文件名 |
92
+ | `list[].filePath` | string | fnOS 文件路径 |
93
+ | `list[].photoUUID` | string | 照片流地址使用的 UUID |
94
+ | `list[].additional.thumbnail.*Url` | string | 已转换为绝对地址的各尺寸预览字段 |
95
+
96
+ ## Photo detail
97
+
98
+ ```bash
99
+ fnos-cli photos info <photoId>
100
+ ```
101
+
102
+ 请求 `GET /p/api/v1/gallery/getOne?id=<photoId>`。除搜索条目字段外,详情常见字段包括
103
+ `fileSize`、`width`、`height`、`description`、`photoDateTime`、`timeZoneOffset`、`make`、
104
+ `model`、`fumber`、`exposureTime`、`isoSpeedRatings`、`focalLength`、`latitude`、
105
+ `longitude`、`ownerId`、`ownerName`、`isCollect`、`isLive` 和标签。
106
+
107
+ ## Preview
108
+
109
+ ```bash
110
+ fnos-cli photos preview <photoId> --size m
111
+ fnos-cli photos preview <photoId> --size o --open
112
+ ```
113
+
114
+ 预览先读取 `gallery/getOne`,再从 `additional.thumbnail` 选择地址。尺寸支持 `xxs`、`xs`、
115
+ `s`、`m` 和 `o`;`o` 是原图。视频优先返回 `videoUrl`,缺失时回落到 `mUrl`。
116
+
117
+ 输出字段包括 `id`、`fileName`、`category`、`size`、`previewUrl`、`originalUrl`、
118
+ `videoUrl` 和 `requiresAuthenticatedBrowserSession`。地址是绝对 URL,但浏览器通常仍需有
119
+ 已登录 fnOS 的 cookie;不要把它描述为免登录公开链接。
120
+
121
+ ## AI semantic search
122
+
123
+ 先检查模型,再发起自然语言搜索:
124
+
125
+ ```bash
126
+ fnos-cli photos request post /api/v1/magic-search/ready --yes
127
+ fnos-cli photos request post /api/v1/magic-search/do \
128
+ --json '{"keyword":"海边日落","antiFilters":[]}' --yes
129
+ ```
130
+
131
+ | Endpoint | Request | Response |
132
+ | --- | --- | --- |
133
+ | `POST /p/api/v1/magic-search/ready` | 无请求体 | `code == 0` 表示当前模型可用 |
134
+ | `POST /p/api/v1/magic-search/do` | `keyword` 必填;`antiFilters` 可选 | `data.list[]` 为本次 AI 命中 |
135
+
136
+ 通用请求输出中的 AI 列表路径是 `response.data.list`。该接口没有稳定的 `total` 字段,
137
+ 因此 `list` 长度只能表述为本次返回条数,不能称为全库精确总数。要提供预览时,从 AI
138
+ 结果选择 `id`,再执行 `photos preview <id> --size m`;AI 原始响应中的相对 URL 不应直接
139
+ 当作可访问链接。
140
+
141
+ 已知业务码 `4044` 表示当前模型不支持当前语言,需要先切换模型。其他非零业务码也应
142
+ 原样报告并停止,不要回退到普通文件名搜索后仍声称是 AI 结果。
143
+
144
+ ## Generic request
145
+
146
+ ```bash
147
+ fnos-cli photos request get /api/v1/server/sys_info
148
+ fnos-cli photos request get /api/v1/gallery/getOne --query id=123
149
+ fnos-cli photos request post /api/v2/search/results \
150
+ --json '{"filters":[],"keyword":"IMG","limit":5}' --yes
151
+ ```
152
+
153
+ 路径只能是 `/api/...` 或 `/p/api/...`,不能包含 origin、查询串或 fragment。查询参数使用
154
+ 可重复的 `--query key=value`;请求体使用 JSON object 或 array。非 GET 请求需要交互确认
155
+ 或显式传 `--yes`。
156
+
157
+ 典型统计、AI 搜索和抽样预览流程见
158
+ [workflows/photos-routing.md](workflows/photos-routing.md)。
@@ -0,0 +1,34 @@
1
+ # Power Reference
2
+
3
+ 电源模块用于重启或关闭 NAS。两条命令都会中断当前设备服务和 CLI 连接,执行前必须确认目标地址、当前账号权限和业务影响。
4
+
5
+ ## Commands
6
+
7
+ | Command | Endpoint | Effect |
8
+ | --- | --- | --- |
9
+ | `fnos-cli power reboot --yes` | `power.reboot` | 请求重启 NAS |
10
+ | `fnos-cli power poweroff --yes` | `power.poweroff` | 请求关闭 NAS |
11
+
12
+ ## Confirmation
13
+
14
+ 默认会弹出交互确认。自动化场景或已经确认目标设备时传 `--yes` 跳过提示。
15
+
16
+ ```
17
+ fnos-cli --host <host> --port <port> power reboot --yes
18
+ fnos-cli --host <host> --port <port> power poweroff --yes
19
+ ```
20
+
21
+ ## Session Requirements
22
+
23
+ 执行前需要已经登录并保存 session。CLI 会使用保存的 session 完成签名认证后发送电源请求。
24
+
25
+ ## Output
26
+
27
+ 命令成功发送并被后端接受后输出简短成功信息:
28
+
29
+ ```
30
+ Reboot request accepted
31
+ Poweroff request accepted
32
+ ```
33
+
34
+ 后端接受请求通常表示重启或关机已经被安排,不表示设备已经完成重启或已经完全断电。
@@ -0,0 +1,160 @@
1
+ # resmon 模块
2
+
3
+ ## 模块概述
4
+ 资源监控模块,涵盖 CPU、内存、网络、GPU、磁盘、电池、系统风扇和进程/服务视图。
5
+
6
+ ## 模块约定
7
+ - 区分聚合指标(`gen`)和分类指标(`cpu`、`mem` 等)。
8
+ - 端点使用 `appcgi.resmon.*` 命名空间。
9
+
10
+ ## 端点索引
11
+ - 已实现:
12
+ - `appcgi.resmon.cpu`
13
+ - `appcgi.resmon.mem`
14
+ - `appcgi.resmon.gen`(聚合指标)
15
+ - `appcgi.resmon.net`(网络)
16
+ - `appcgi.resmon.disk`(磁盘)
17
+ - `appcgi.resmon.gpu`(GPU)
18
+ - `appcgi.resmon.npu`(NPU)
19
+ - `appcgi.resmon.proc.info`(进程详情)
20
+ - `appcgi.resmon.proc.list`(进程列表)
21
+ - `appcgi.resmon.proc.srv`(服务列表)
22
+ - `appcgi.resmon.sysWarn`(系统告警)
23
+ - `appcgi.resmon.battery`(电池)
24
+ - `appcgi.resmon.sysFan`(系统风扇)
25
+ - `appcgi.resmon.alert.getSupportedBeepEvents`(支持的蜂鸣器事件)
26
+ - `appcgi.resmon.alert.getBeepEvents`(已配置蜂鸣器事件)
27
+ - `appcgi.resmon.alert.getBeepReasons`(蜂鸣器触发原因)
28
+ - `appcgi.resmon.alert.muteBeeper`(静音蜂鸣器)
29
+ - `appcgi.resmon.*` 泛化请求(通过 `monitor request`)
30
+ - 未实现:
31
+ - 无独立命令的写操作端点;如需调用,使用 `monitor request` 并确认风险。
32
+
33
+ ## 端点详情
34
+
35
+ ### appcgi.resmon.cpu
36
+
37
+ #### Endpoint
38
+ `appcgi.resmon.cpu`
39
+
40
+ #### Purpose
41
+ 返回 CPU 监控指标。
42
+
43
+ #### Trim CLI Mapping
44
+ ```
45
+ fnos-cli monitor cpu
46
+ ```
47
+
48
+ CLI 行为:
49
+ - 复用 session 恢复流程。
50
+ - 将端点返回数据以 JSON 格式打印。
51
+
52
+ #### Request
53
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
54
+ | --- | --- | --- | --- | --- | --- | --- |
55
+ | `req` | body | yes | string | Endpoint selector | Fixed value `appcgi.resmon.cpu` | `appcgi.resmon.cpu` |
56
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
57
+
58
+ #### Response
59
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
60
+ | --- | --- | --- | --- | --- | --- |
61
+ | `data` | no | object | CPU 指标数据 | CLI 直接打印此对象 | `{"usage":37,"cores":4}` |
62
+ | `result` | no | string | Terminal marker | `succ`/`fail` | `succ` |
63
+ | `errno` | no | number | 错误码 | 失败时出现 | `5001` |
64
+ | `errmsg` | no | string | 错误描述 | 失败时出现 | `monitor backend unavailable` |
65
+
66
+ #### Protocol Notes
67
+ - 使用签名请求(当 session secret 可用时)。
68
+ - 签名格式遵循 `_conventions.md` 中定义的规范。
69
+
70
+ #### Field Semantics
71
+ - 返回数据结构由后端定义,CLI 不做字段重映射。
72
+
73
+ #### Errors
74
+ - 后端错误通过统一格式化器输出到 stderr,包含 errno。
75
+ - 命令以非零退出码退出。
76
+
77
+ ### appcgi.resmon.mem
78
+
79
+ #### Endpoint
80
+ `appcgi.resmon.mem`
81
+
82
+ #### Purpose
83
+ 返回内存监控指标。
84
+
85
+ #### Trim CLI Mapping
86
+ ```
87
+ fnos-cli monitor memory
88
+ ```
89
+
90
+ CLI 行为:
91
+ - 复用 session 恢复流程。
92
+ - 将端点返回数据以 JSON 格式打印。
93
+
94
+ #### Request
95
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
96
+ | --- | --- | --- | --- | --- | --- | --- |
97
+ | `req` | body | yes | string | Endpoint selector | Fixed value `appcgi.resmon.mem` | `appcgi.resmon.mem` |
98
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
99
+
100
+ #### Response
101
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
102
+ | --- | --- | --- | --- | --- | --- |
103
+ | `data` | no | object | 内存指标数据 | CLI 直接打印此对象 | `{"total":1024,"used":768}` |
104
+ | `result` | no | string | Terminal marker | `succ`/`fail` | `succ` |
105
+ | `errno` | no | number | 错误码 | 失败时出现 | `5001` |
106
+ | `errmsg` | no | string | 错误描述 | 失败时出现 | `monitor backend unavailable` |
107
+
108
+ #### Protocol Notes
109
+ - 使用签名请求(当 session secret 可用时)。
110
+ - 签名格式遵循 `_conventions.md` 中定义的规范。
111
+
112
+ #### Field Semantics
113
+ - 返回数据结构由后端定义,CLI 不做字段重映射。
114
+
115
+ #### Errors
116
+ - 后端错误通过统一格式化器输出到 stderr,包含 errno。
117
+ - 命令以非零退出码退出。
118
+
119
+ ### 其他只读端点
120
+
121
+ 以下端点均复用已保存 session,执行签名请求,并打印响应 `data` 对象。
122
+
123
+ | CLI 命令 | Endpoint | Request 参数 | 用途 |
124
+ | --- | --- | --- | --- |
125
+ | `fnos-cli monitor gen --item storeSpeed,netSpeed` | `appcgi.resmon.gen` | `item`: 仅支持 `storeSpeed`、`netSpeed`、`cpuBusy`、`memPercent`;可重复传 `--item` 或用逗号分隔 | 聚合指标查询 |
126
+ | `fnos-cli monitor net` | `appcgi.resmon.net` | 无 | 网络指标 |
127
+ | `fnos-cli monitor disk` | `appcgi.resmon.disk` | 无 | 磁盘指标 |
128
+ | `fnos-cli monitor gpu` | `appcgi.resmon.gpu` | 无 | GPU 指标 |
129
+ | `fnos-cli monitor npu` | `appcgi.resmon.npu` | 无 | NPU 指标 |
130
+ | `fnos-cli monitor proc-info --pids 123,456` | `appcgi.resmon.proc.info` | `pids`: 正整数数组 | 指定进程详情 |
131
+ | `fnos-cli monitor proc-list` | `appcgi.resmon.proc.list` | 无 | 进程列表;响应可能分批返回,CLI 会聚合完整列表 |
132
+ | `fnos-cli monitor proc-srv` | `appcgi.resmon.proc.srv` | 无 | 服务视图 |
133
+ | `fnos-cli monitor sys-warn` | `appcgi.resmon.sysWarn` | 无 | 系统告警 |
134
+ | `fnos-cli monitor battery` | `appcgi.resmon.battery` | 无 | 电池状态 |
135
+ | `fnos-cli monitor sys-fan` | `appcgi.resmon.sysFan` | 无 | 系统风扇 |
136
+ | `fnos-cli monitor beep-supported` | `appcgi.resmon.alert.getSupportedBeepEvents` | 无 | 可支持蜂鸣器事件 |
137
+ | `fnos-cli monitor beep-events` | `appcgi.resmon.alert.getBeepEvents` | 无 | 已配置蜂鸣器事件 |
138
+ | `fnos-cli monitor beep-reasons` | `appcgi.resmon.alert.getBeepReasons` | 无 | 当前或历史触发原因 |
139
+
140
+ 参数约束:
141
+ - `--item` 只支持 `storeSpeed`、`netSpeed`、`cpuBusy`、`memPercent`;空值会被忽略,非法指标会在发送请求前拒绝。
142
+ - `--pids` 只接受正整数,重复 PID 会自动去重。
143
+ - `beep-supported`、`beep-events`、`beep-reasons` 只适用于带蜂鸣器能力的 TRIM 机器。成功响应缺少 `data` 时,CLI 会检查机器类型与 `beep` 能力,仅在明确为非 TRIM 机器或 `beep: false` 时输出 `[]`;能力未知、`beep: true` 或其他 monitor 命令缺少 `data` 时仍报错。
144
+
145
+ ### 写操作和泛化请求
146
+
147
+ | CLI 命令 | Endpoint | Request 参数 | 风险控制 |
148
+ | --- | --- | --- | --- |
149
+ | `fnos-cli monitor mute-beeper` | `appcgi.resmon.alert.muteBeeper` | 无 | 默认需要确认;可用 `--yes` 跳过 |
150
+ | `fnos-cli monitor request appcgi.resmon.* --json '<object>'` | 用户指定的 `appcgi.resmon.*` 端点 | JSON 对象,不能包含 `req` 或 `reqid` | 默认需要确认;可用 `--yes` 跳过 |
151
+
152
+ 泛化请求约束:
153
+ - endpoint 必须以 `appcgi.resmon.` 开头。
154
+ - `--json` 必须是 JSON object。
155
+ - `req` 和 `reqid` 由 CLI 生成,用户 JSON 中禁止提供这两个字段。
156
+ - `monitor request` 是泛化入口,不区分读写端点,默认统一要求确认。
157
+
158
+ ## 注意事项
159
+ - 读取型命令不会修改设备状态。
160
+ - 写操作或泛化 request 在自动化场景中使用 `--yes` 前,应先明确 endpoint 语义和 JSON 内容。