@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,139 @@
1
+ # 用户与认证参考
2
+
3
+ ## OAuth 登录
4
+
5
+ fnos-cli 使用 OAuth 2.0 Authorization Code + PKCE 建立代理 session,不使用 NAS 用户名密码、
6
+ 2FA 登录或旧 token 恢复链。CLI 按用户、文件读写、下载、应用中心、相册、系统、日志、存储和
7
+ Docker 模块申请 `trim.*` scope;完整列表见 `oauth.md`。
8
+
9
+ 生产环境只使用交互式登录:
10
+
11
+ ```bash
12
+ fnos-cli --profile home --host <host> --port <port> login
13
+ ```
14
+
15
+ CLI 输出授权链接并在当前 profile 保存一次性 PKCE verifier,然后保持运行并等待
16
+ `Authorization code`。用户自行在浏览器输入账号密码、确认授权、复制页面显示的 code,再粘贴
17
+ 到 CLI 提示。不要自动填写账号密码、点击授权或读取页面 code,也不要把 code 放进命令参数。
18
+ 无法自动打开浏览器时添加 `--no-open`。授权 URL 不包含 `redirect_uri`,不要自行追加;token
19
+ 交换成功后一次性 PKCE 文件会被删除。
20
+
21
+ Session 保存以下认证信息:
22
+
23
+ | Field | Meaning |
24
+ | --- | --- |
25
+ | `accessToken` | 代理业务请求的 Bearer token |
26
+ | `refreshToken` | access token 刷新凭据 |
27
+ | `accessTokenExpiresAt` | access token 的 Unix 秒过期时间 |
28
+ | `oauthClientId` | CLI 使用的 OAuth client id |
29
+ | `oauthDeviceId` | 本机持久化的 OAuth device id |
30
+ | `oauthScope` | 已授权 scope |
31
+
32
+ 普通已认证命令会在 access token 临近过期时自动调用 refresh。也可以显式执行:
33
+
34
+ ```bash
35
+ fnos-cli --profile home login --refresh
36
+ ```
37
+
38
+ refresh 响应没有返回新 refresh token 时,CLI 保留已有 refresh token。刷新前会先确认当前
39
+ profile 的 session 存储可写;预检失败时停止当前命令,不发送 refresh,也不静默切换到用户名
40
+ 密码登录。多个进程同时恢复时,CLI 会复用已写入的新 session,不覆盖较新的 token。
41
+
42
+ `logout` 只清除当前 profile 的本地 session,不表示服务端 token 已撤销:
43
+
44
+ ```bash
45
+ fnos-cli --profile home logout
46
+ ```
47
+
48
+ ## 当前用户与列表
49
+
50
+ ```bash
51
+ fnos-cli user info
52
+ fnos-cli user list
53
+ fnos-cli user list --mode group --group Users
54
+ fnos-cli user request user.list --json '{"limit":100,"offset":0}'
55
+ ```
56
+
57
+ | Command | Endpoint | Important output |
58
+ | --- | --- | --- |
59
+ | `user info` | `user.info` | `userInfo.user`、`uid`、`admin` |
60
+ | `user list` | `user.list` | 用户数组、总数和分页字段 |
61
+ | `user list --mode group` | `user.listUG` | 指定组中的用户 |
62
+
63
+ `user request` 的 endpoint 必须以 `user.` 开头;`--json` 必须是 JSON object,且不能手工提供
64
+ `req` 或 `reqid`。通用 `user request` 无法从 endpoint 名称可靠判断读写属性,因此默认要求确认;
65
+ 自动化时需明确传 `--yes`。已封装的 `user info`、`user list` 等专用只读命令不需要该参数。
66
+
67
+ ## 用户写操作
68
+
69
+ ```bash
70
+ fnos-cli user add <user> [--password <initial-password>] [--groups Users] [--set-admin] --yes
71
+ fnos-cli user mod <user> [--new-name <name>] [--password <new-password>] [--groups Users] --yes
72
+ fnos-cli user del <user> --yes
73
+ fnos-cli user change-password <user> --yes
74
+ fnos-cli user unfreeze <user> --yes
75
+ fnos-cli user set-admin <user> --admin true --yes
76
+ ```
77
+
78
+ | Command | Endpoint | Main request fields |
79
+ | --- | --- | --- |
80
+ | `user add` | `user.add` | `user`、`password`、`groups`、可选联系信息和管理员标记 |
81
+ | `user mod` | `user.mod` | `user` 加显式提供的变更字段 |
82
+ | `user del` | `user.del` | `user` |
83
+ | `user change-password` | `user.changePassword` | `user`、交互输入的新密码 |
84
+ | `user unfreeze` | `user.unfreeze` | `user` |
85
+ | `user set-admin` | `user.setAdmin` | `user`、`admin` |
86
+
87
+ 这里的 `--password` 是创建用户或修改目标用户密码,不是 CLI 登录凭据。不要把用户管理密码
88
+ 改写成登录参数。密码不要出现在回复、日志或长期保存的命令记录中;省略可交互输入的密码参数。
89
+
90
+ 删除用户、修改管理员权限、改密码和解冻属于写操作,未得到用户明确授权时不要执行。
91
+
92
+ ## 用户组
93
+
94
+ ```bash
95
+ fnos-cli user group list
96
+ fnos-cli user group info <group>
97
+ fnos-cli user group users <group>
98
+ fnos-cli user group add <group> [--comment <text>] --yes
99
+ fnos-cli user group mod <group> [--new-name <name>] [--comment <text>] --yes
100
+ fnos-cli user group del <group> --yes
101
+ fnos-cli user group set-users <group> --users <user> --yes
102
+ fnos-cli user group add-users <group> --users <user> --yes
103
+ fnos-cli user group del-users <group> --users <user> --yes
104
+ ```
105
+
106
+ | Command | Endpoint | Main request fields |
107
+ | --- | --- | --- |
108
+ | `group list` | `user.groupList` | 无 |
109
+ | `group info` | `user.groupInfo` | `group` |
110
+ | `group users` | `user.groupUsers` | `group` |
111
+ | `group add` | `user.groupAdd` | `group`、可选 `comment` |
112
+ | `group mod` | `user.groupMod` | `group`、可选新名称和备注 |
113
+ | `group del` | `user.groupDel` | `group` |
114
+ | `group set-users` | `user.groupSetUsers` | `group`、`users` |
115
+ | `group add-users` | `user.groupAddUsers` | `group`、`users` |
116
+ | `group del-users` | `user.groupDelUsers` | `group`、`users` |
117
+
118
+ `--users` 和 `--groups` 支持重复参数或逗号分隔值。空列表、控制字符和明显非法名称会在发请求
119
+ 前被拒绝。
120
+
121
+ ## 登录设备
122
+
123
+ ```bash
124
+ fnos-cli user login-devices
125
+ fnos-cli user request user.listLoginDevice
126
+ ```
127
+
128
+ 登录设备列表是用户管理数据,不参与 CLI 的 OAuth PKCE 登录。不要根据设备列表尝试旧的
129
+ trusted-device/2FA 登录流程。
130
+
131
+ ## 错误处理
132
+
133
+ - `saved proxy session is required`:先完成 OAuth 登录。
134
+ - OAuth pending 缺失或过期:重新运行完整的交互式 `login`,不要单独拼装兑换命令。
135
+ - refresh 失败或 refresh token 缺失:重新运行 OAuth 登录,不回退到账号密码。
136
+ - refresh 返回后 session 最终写入失败:不要盲目复用旧 refresh token;它可能已被轮换,应重新登录。
137
+ - 权限错误:先用 `user info` 确认 `admin`,不要自动提升权限。
138
+ - 写操作未确认:向用户说明目标和影响,得到授权后再传 `--yes`。
139
+ - 响应含业务错误码时原样报告错误语义,不要只依据 HTTP 状态判断成功。
@@ -0,0 +1,66 @@
1
+ # Device validation
2
+
3
+ Use this workflow for interactive OAuth, minimal probes and read-after-write verification.
4
+
5
+ ## 1. User authorization
6
+
7
+ Production validation uses interactive OAuth PKCE:
8
+
9
+ 1. The user runs `fnos-cli --profile <profile> --host <host> --port <port> login`
10
+ in their own interactive terminal.
11
+ 2. The CLI displays an authorization link and waits.
12
+ 3. The user opens the link, signs in and approves access in the browser.
13
+ 4. The user copies the one-time code into the CLI's `Authorization code` prompt.
14
+ 5. The CLI exchanges the code and saves the selected profile's session.
15
+
16
+ The Agent does not collect credentials, approve access, read browser codes or
17
+ pass codes as arguments. Add `--no-open` if the browser cannot open automatically;
18
+ the remaining steps are unchanged. Authorization URLs omit `redirect_uri`.
19
+
20
+ For DSH, the login terminal must share the DSH Host, system user, configuration
21
+ environment and `--profile`. Remote browsers, SSH shells and containers do not
22
+ automatically inherit that session. macOS background Keychain access may need
23
+ system approval.
24
+
25
+ ## 2. Minimal read-only probes
26
+
27
+ Before any write:
28
+
29
+ 1. Confirm interactive login established the intended profile's session; do not
30
+ preconfigure or rotate accounts as part of validation.
31
+ 2. Run one or two read-only commands for the target module to check connectivity
32
+ and permissions.
33
+ 3. For files, prefer `file ls` or a read-only search.
34
+ 4. For storage, use `storage pools` / `storage disks`.
35
+ 5. For Docker, use `docker stats` or `docker container ls`.
36
+
37
+ Confirm the device target, session and sufficient current-user permissions.
38
+
39
+ ## 3. Write sequence
40
+
41
+ 1. Probe the closest relevant read-only state.
42
+ 2. Perform one authorized, explainable and reversible write.
43
+ 3. Immediately read the resulting state.
44
+ 4. Clean up temporary resources when appropriate.
45
+
46
+ Keep unrelated writes out of the same validation run.
47
+
48
+ ## 4. Read-after-write verification
49
+
50
+ Use at least one relevant check:
51
+
52
+ - Files: `ls`, `search` or `share list`.
53
+ - Storage: `pools`, `disks` or `removable`.
54
+ - Docker: `image ls`, `container ls` or `compose ls`.
55
+ - Users: `user list` or `group list`.
56
+
57
+ Only claim success when the before/after states can be compared objectively.
58
+
59
+ ## 5. Stop and ask
60
+
61
+ Stop when OAuth or code exchange fails, the target host is missing, a write may
62
+ affect production data/services, or responses conflict with documented
63
+ constraints and suggest firmware differences.
64
+
65
+ Read the module reference once the command is selected. Resolve unknown
66
+ profiles, permissions and device state before proceeding.
@@ -0,0 +1,44 @@
1
+ # File paths and shared-directory routing
2
+
3
+ Select the command first, then read `../file.md` for field details.
4
+
5
+ ## 1. Match the intent
6
+
7
+ | Intent | Preferred command | Path and semantic rule |
8
+ | --- | --- | --- |
9
+ | List currently visible directories | `fnos-cli file ls` | Both no argument and `/` omit `path`; this does not promise all volumes |
10
+ | List a concrete directory | `fnos-cli file ls /vol{n}/...` | Keep aggregate roots separate from canonical paths |
11
+ | Search the current user's files | `fnos-cli file search <key>` | Let the CLI probe and derive the current-user directory |
12
+ | Search a specified directory | `fnos-cli file search <key> /vol{n}/...` | Use concrete canonical paths |
13
+ | Upload a local file | `fnos-cli file upload /vol{n}/... <localFile> --yes` | The remote argument is a directory, not a final filename |
14
+ | Search files shared with me | `fnos-cli file search-others <key>` | Distinct from shared-directory listing |
15
+ | Inspect a shared directory | `fnos-cli file share info <path>` | Not share-link management |
16
+ | List visible shared directories | `fnos-cli file share list [uid]` | Not file search |
17
+ | Inspect ACLs | `fnos-cli file acl get <path>` | Permission data, not shared-directory state |
18
+ | Create/delete/copy/move files | `file mkdir/rm/cp/mv` | Concrete paths and explicit `--yes` |
19
+
20
+ ## 2. Resolve paths
21
+
22
+ 1. Writes require concrete canonical `/vol{n}/...` paths.
23
+ 2. `file ls` and `file ls /` both omit `path`; neither explicitly requests aggregate root `/`.
24
+ 3. Search without a path lets the CLI probe the current-user directory via `file.ls`.
25
+ 4. Every explicit search path must be `/vol{n}/...`.
26
+ 5. For files shared by others, choose `search-others` or `share list-others` as appropriate.
27
+
28
+ ## 3. Important distinctions
29
+
30
+ - Shared directories use `file share.*`, not share links.
31
+ - `file search-others` returns matching files, not a shared-directory list.
32
+ - ACL queries report permissions, not share status.
33
+ - `file cp` / `file mv` take a destination directory, not a final filename.
34
+ - Upload `uploadName` is an HTTP upload/resume path, not necessarily the visible filename.
35
+
36
+ ## 4. Stop and ask
37
+
38
+ Clarify writes with only `/`, relative or ambiguous paths; requests for share
39
+ links when only shared-directory APIs are documented; mixed noncanonical search
40
+ paths; and assumptions that the current-user directory is a fixed value.
41
+
42
+ For fields read [file.md](../file.md). For uploads read
43
+ [file-upload-validation.md](file-upload-validation.md). Resolve path semantics
44
+ before constructing a payload.
@@ -0,0 +1,63 @@
1
+ # Upload validation
2
+
3
+ Verify small uploads, same-name policies and resumable large uploads.
4
+
5
+ ## 1. Prerequisites
6
+
7
+ - A signed-in target NAS.
8
+ - A confirmed writable `/vol{n}/...` directory.
9
+ - An existing local regular file.
10
+
11
+ ## 2. Small file
12
+
13
+ 1. Create a temporary subdirectory in the confirmed writable directory.
14
+ 2. Upload a local file smaller than 20 MiB:
15
+
16
+ ```bash
17
+ fnos-cli file upload /vol1/1000/tmp-upload ./demo.txt --overwrite rename --yes
18
+ ```
19
+
20
+ 3. List the temporary directory:
21
+
22
+ ```bash
23
+ fnos-cli file ls /vol1/1000/tmp-upload
24
+ ```
25
+
26
+ 4. Confirm the CLI reports the requested target path and the directory contains
27
+ the matching filename.
28
+
29
+ ## 3. Large file
30
+
31
+ 1. Prepare a local file of at least 20 MiB.
32
+ 2. Upload it:
33
+
34
+ ```bash
35
+ fnos-cli file upload /vol1/1000/tmp-upload ./large.bin --overwrite rename --yes
36
+ ```
37
+
38
+ 3. List the directory and confirm the original filename exists remotely.
39
+ 4. When diagnosing resume, inspect the upload cache in the local configuration
40
+ directory. Its `upload_path` is the backend's `.~#n` upload path, not the final filename.
41
+ 5. Resume only when endpoint, profile, signed-in user, remote target, size,
42
+ overwrite policy and local SHA-256 all match. A different same-size file at
43
+ the same local path must begin a new `check-upload`.
44
+ 6. Concurrent uploads to the same endpoint and remote target serialize across
45
+ processes; lock waiting does not by itself indicate corrupt cache.
46
+
47
+ ## 4. Cleanup
48
+
49
+ After verifying the exact temporary paths, remove the uploaded files and directory:
50
+
51
+ ```bash
52
+ fnos-cli file rm /vol1/1000/tmp-upload/demo.txt --yes
53
+ fnos-cli file rm /vol1/1000/tmp-upload/large.bin --yes
54
+ fnos-cli file rm /vol1/1000/tmp-upload --yes
55
+ ```
56
+
57
+ ## 5. Completion criteria
58
+
59
+ The successful output uses the requested path, and `file ls` shows the uploaded
60
+ file. Small files do not depend on resume cache. Large files may create cache;
61
+ cache paths support HTTP upload/resume and are not visible result paths.
62
+ Legacy caches, caches missing identity fields and local fingerprint mismatches
63
+ must not resume.
@@ -0,0 +1,83 @@
1
+ # Photo task routing
2
+
3
+ Use for library statistics, filtered search, AI semantic search and sampled previews.
4
+ Read the Photos reference after selecting a command.
5
+
6
+ ## 1. Authentication
7
+
8
+ Photos reuses the current profile's proxy session. Without a valid session, the
9
+ user runs interactive `fnos-cli login`, opens the link, signs in, authorizes
10
+ and pastes the one-time code into the CLI. The Agent does not enter credentials,
11
+ approve access or read browser codes.
12
+
13
+ For multiple devices, select `--profile`, `--host` and `--port` explicitly.
14
+ Sessions are not interchangeable across devices.
15
+
16
+ ## 2. Scenarios
17
+
18
+ ### Library scope and size
19
+
20
+ ```bash
21
+ fnos-cli photos folders
22
+ ```
23
+
24
+ Summarize returned photo/video counts per scanned folder. Photos indexes only
25
+ folders added to scanning; filesystem image counts are not library index counts.
26
+
27
+ ### Filtered search and counts
28
+
29
+ ```bash
30
+ fnos-cli photos search Beijing --limit 20
31
+ fnos-cli photos search IMG --filter file_type=photo --limit 20
32
+ ```
33
+
34
+ Report the response's `total` as the full match count; `list` is the returned
35
+ sample. For previews, choose a few representative results and call
36
+ `photos preview <id> --size m`, rather than fetching every original.
37
+
38
+ ### Natural-language AI search
39
+
40
+ Check readiness before searching:
41
+
42
+ ```bash
43
+ fnos-cli photos request post /api/v1/magic-search/ready --yes
44
+ fnos-cli photos request post /api/v1/magic-search/do \
45
+ --json '{"keyword":"sunset at the beach","antiFilters":[]}' --yes
46
+ ```
47
+
48
+ AI search is a separate endpoint from filtered `photos search`. It usually
49
+ returns `response.data.list` without a stable `total`; report only the number
50
+ returned. If the model is missing, not ready or incompatible with the query
51
+ language, report the business error. A filename-search fallback is not an AI result.
52
+
53
+ `photos request` preserves the raw envelope and can exit 0 even when
54
+ `response.code != 0`. Both calls require `httpStatus` in `200..299` and
55
+ `response.code == 0`. Select result IDs from `response.data.list` for previews.
56
+
57
+ ### Sampled previews
58
+
59
+ ```bash
60
+ fnos-cli photos preview <id> --size m
61
+ fnos-cli photos preview <id> --size o
62
+ ```
63
+
64
+ Prefer medium previews; use `--size o` only when the user asks for originals.
65
+
66
+ ## 3. Counts and links
67
+
68
+ | Result | Meaning | Caveat |
69
+ | --- | --- | --- |
70
+ | Filtered search `total` | All matches | Not the current `list` length |
71
+ | AI `list` length | Returned count | Not an exact total without `total` |
72
+ | `previewUrl` | Thumbnail, original or video preview | Browser usually needs a signed-in fnOS cookie |
73
+
74
+ Keep secure-store tokens private and preserve the CLI's sensitive-URI redaction.
75
+
76
+ ## 4. Stop and clarify
77
+
78
+ Clarify exact-count requests when AI results lack `total`, public-preview
79
+ requests without browser authentication, and preview-only tasks that would
80
+ fetch every original. Stop on non-2xx `httpStatus` or nonzero `response.code`.
81
+
82
+ Read [photos.md](../photos.md) for fields/filters/AI endpoints and
83
+ [device-validation.md](device-validation.md) for device differences.
@@ -0,0 +1,53 @@
1
+ # High-risk storage operations
2
+
3
+ Probe read-only state before deciding whether a storage write can proceed.
4
+
5
+ ## 1. Identify high-risk writes
6
+
7
+ Use this workflow before `storage umount/create/stop/add-disk/remove-disk/replace-disk/resize/extend/format/eject/disk-mount/disk-umount`,
8
+ and before `storage request` unless the endpoint is confirmed read-only.
9
+
10
+ `storage mount` is lower risk but still requires the pool identifier and current
11
+ state. Removable-disk mount/unmount operations require the exact disk target.
12
+
13
+ ## 2. Read-only probes
14
+
15
+ 1. `fnos-cli storage pools`.
16
+ 2. `fnos-cli storage disks`.
17
+ 3. Before pool creation, `fnos-cli storage free-disks`.
18
+ 4. As needed, `fnos-cli storage health <disk>` or `storage smart <disk>`.
19
+ 5. For removable devices, `storage removable` and `storage disk-info <disk>`.
20
+
21
+ Confirm whether the target is a pool UUID/`trim_*` identifier or plain disk
22
+ name, its state and removability. For remaining space on a system disk, use the
23
+ returned `part`, not whole-disk `name`. Keep disk and pool operations distinct.
24
+
25
+ ## 3. Password and confirmation policy
26
+
27
+ | Policy | Commands |
28
+ | --- | --- |
29
+ | Verify and forward password | `umount`, `create`, `stop`, `add-disk`, `remove-disk`, `replace-disk`, `resize` |
30
+ | Verify without forwarding | `extend`, `format`, `eject` |
31
+ | Confirmation without password verification | `mount`, `disk-mount`, `disk-umount` |
32
+ | Generic request | `request` requires confirmation; explicit `--password` is verified and forwarded |
33
+
34
+ Agent/noninteractive writes explicitly pass `--yes`. For the first two rows,
35
+ stop if the required password is unavailable; there is no assumed default.
36
+ Treat potentially mutating `stor.*` requests as high risk.
37
+
38
+ ## 4. Distinctions
39
+
40
+ - `mount` is not the inverse of `stop`; check pool state.
41
+ - `extend` and `resize` are different operations.
42
+ - `format` / `eject` target removable devices, not ordinary pools.
43
+ - Pools use UUIDs or `trim_*`, not legacy `name`.
44
+ - Disks use plain names such as `sda` or `nvme0n1`, not `/dev/sda`.
45
+
46
+ ## 5. Stop and clarify
47
+
48
+ Stop for ambiguous pool/disk targets, probe results inconsistent with the user's
49
+ description, unavailable required passwords, or stopped/unmounted/non-expandable
50
+ targets and standby/abnormal disks.
51
+
52
+ Once target and order are confirmed, read [stor.md](../stor.md). Otherwise remain
53
+ at the read-only probe stage.
@@ -0,0 +1,63 @@
1
+ #!/bin/sh
2
+
3
+ set -eu
4
+
5
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
6
+ BIN_DIR="$SCRIPT_DIR/../bin"
7
+
8
+ reject_media_command() {
9
+ skip_value=0
10
+ for arg in "$@"; do
11
+ if [ "$skip_value" -eq 1 ]; then
12
+ skip_value=0
13
+ continue
14
+ fi
15
+ case "$arg" in
16
+ --host|--port|--profile|--scheme)
17
+ skip_value=1
18
+ ;;
19
+ --host=*|--port=*|--profile=*|--scheme=*|--allow-insecure-http|--tls-insecure)
20
+ ;;
21
+ --*)
22
+ ;;
23
+ media)
24
+ echo "Media commands are not available in this skill package." >&2
25
+ exit 2
26
+ ;;
27
+ *)
28
+ return
29
+ ;;
30
+ esac
31
+ done
32
+ }
33
+
34
+ reject_media_command "$@"
35
+
36
+ OS=$(uname -s)
37
+ ARCH=$(uname -m)
38
+
39
+ case "$OS:$ARCH" in
40
+ Darwin:arm64)
41
+ TARGET="$BIN_DIR/trim-cli-darwin-arm64"
42
+ ;;
43
+ Darwin:x86_64)
44
+ TARGET="$BIN_DIR/trim-cli-darwin-x64"
45
+ ;;
46
+ Linux:x86_64)
47
+ TARGET="$BIN_DIR/trim-cli-linux-x64"
48
+ ;;
49
+ Linux:aarch64|Linux:arm64)
50
+ TARGET="$BIN_DIR/trim-cli-linux-arm64"
51
+ ;;
52
+ *)
53
+ echo "Unsupported platform for $0: $OS $ARCH" >&2
54
+ exit 1
55
+ ;;
56
+ esac
57
+
58
+ if [ ! -x "$TARGET" ]; then
59
+ echo "Missing packaged binary: $TARGET" >&2
60
+ exit 1
61
+ fi
62
+
63
+ exec "$TARGET" "$@"
@@ -0,0 +1,36 @@
1
+ @echo off
2
+ setlocal
3
+
4
+ call :reject_media %*
5
+ if errorlevel 1 exit /b %errorlevel%
6
+
7
+ set "SCRIPT_DIR=%~dp0"
8
+ set "ARCH=%PROCESSOR_ARCHITECTURE%"
9
+ if defined PROCESSOR_ARCHITEW6432 set "ARCH=%PROCESSOR_ARCHITEW6432%"
10
+ if /I "%ARCH%"=="ARM64" (
11
+ set "TARGET=%SCRIPT_DIR%..\bin\trim-cli-windows-arm64.exe"
12
+ ) else (
13
+ set "TARGET=%SCRIPT_DIR%..\bin\trim-cli-windows-x64.exe"
14
+ )
15
+
16
+ if not exist "%TARGET%" (
17
+ echo Missing packaged binary: %TARGET% 1>&2
18
+ exit /b 1
19
+ )
20
+
21
+ "%TARGET%" %*
22
+ exit /b %errorlevel%
23
+
24
+ :reject_media
25
+ if "%~1"=="" exit /b 0
26
+ set "ARG=%~1"
27
+ if /I "%ARG%"=="--host" shift&shift&goto reject_media
28
+ if /I "%ARG%"=="--port" shift&shift&goto reject_media
29
+ if /I "%ARG%"=="--profile" shift&shift&goto reject_media
30
+ if /I "%ARG%"=="--scheme" shift&shift&goto reject_media
31
+ if "%ARG:~0,1%"=="-" shift&goto reject_media
32
+ if /I "%ARG%"=="media" (
33
+ echo Media commands are not available in this skill package. 1>&2
34
+ exit /b 2
35
+ )
36
+ exit /b 0
@@ -0,0 +1,31 @@
1
+ $Architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()
2
+ $Platform = if ($Architecture -eq "Arm64") { "windows-arm64" } else { "windows-x64" }
3
+ $Target = Join-Path $PSScriptRoot "..\bin\trim-cli-$Platform.exe"
4
+
5
+ $SkipValue = $false
6
+ foreach ($Argument in $args) {
7
+ if ($SkipValue) {
8
+ $SkipValue = $false
9
+ continue
10
+ }
11
+ if ($Argument -in @("--host", "--port", "--profile", "--scheme")) {
12
+ $SkipValue = $true
13
+ continue
14
+ }
15
+ if ($Argument.StartsWith("-")) {
16
+ continue
17
+ }
18
+ if ($Argument -eq "media") {
19
+ Write-Error "Media commands are not available in this skill package."
20
+ exit 2
21
+ }
22
+ break
23
+ }
24
+
25
+ if (-not (Test-Path $Target)) {
26
+ Write-Error "Missing packaged binary: $Target"
27
+ exit 1
28
+ }
29
+
30
+ & $Target @args
31
+ exit $LASTEXITCODE
@@ -0,0 +1,63 @@
1
+ #!/bin/sh
2
+
3
+ set -eu
4
+
5
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
6
+ BIN_DIR="$SCRIPT_DIR/../bin"
7
+
8
+ reject_media_command() {
9
+ skip_value=0
10
+ for arg in "$@"; do
11
+ if [ "$skip_value" -eq 1 ]; then
12
+ skip_value=0
13
+ continue
14
+ fi
15
+ case "$arg" in
16
+ --host|--port|--profile|--scheme)
17
+ skip_value=1
18
+ ;;
19
+ --host=*|--port=*|--profile=*|--scheme=*|--allow-insecure-http|--tls-insecure)
20
+ ;;
21
+ --*)
22
+ ;;
23
+ media)
24
+ echo "Media commands are not available in this skill package." >&2
25
+ exit 2
26
+ ;;
27
+ *)
28
+ return
29
+ ;;
30
+ esac
31
+ done
32
+ }
33
+
34
+ reject_media_command "$@"
35
+
36
+ OS=$(uname -s)
37
+ ARCH=$(uname -m)
38
+
39
+ case "$OS:$ARCH" in
40
+ Darwin:arm64)
41
+ TARGET="$BIN_DIR/trim-cli-darwin-arm64"
42
+ ;;
43
+ Darwin:x86_64)
44
+ TARGET="$BIN_DIR/trim-cli-darwin-x64"
45
+ ;;
46
+ Linux:x86_64)
47
+ TARGET="$BIN_DIR/trim-cli-linux-x64"
48
+ ;;
49
+ Linux:aarch64|Linux:arm64)
50
+ TARGET="$BIN_DIR/trim-cli-linux-arm64"
51
+ ;;
52
+ *)
53
+ echo "Unsupported platform for $0: $OS $ARCH" >&2
54
+ exit 1
55
+ ;;
56
+ esac
57
+
58
+ if [ ! -x "$TARGET" ]; then
59
+ echo "Missing packaged binary: $TARGET" >&2
60
+ exit 1
61
+ fi
62
+
63
+ exec "$TARGET" "$@"
@@ -0,0 +1,36 @@
1
+ @echo off
2
+ setlocal
3
+
4
+ call :reject_media %*
5
+ if errorlevel 1 exit /b %errorlevel%
6
+
7
+ set "SCRIPT_DIR=%~dp0"
8
+ set "ARCH=%PROCESSOR_ARCHITECTURE%"
9
+ if defined PROCESSOR_ARCHITEW6432 set "ARCH=%PROCESSOR_ARCHITEW6432%"
10
+ if /I "%ARCH%"=="ARM64" (
11
+ set "TARGET=%SCRIPT_DIR%..\bin\trim-cli-windows-arm64.exe"
12
+ ) else (
13
+ set "TARGET=%SCRIPT_DIR%..\bin\trim-cli-windows-x64.exe"
14
+ )
15
+
16
+ if not exist "%TARGET%" (
17
+ echo Missing packaged binary: %TARGET% 1>&2
18
+ exit /b 1
19
+ )
20
+
21
+ "%TARGET%" %*
22
+ exit /b %errorlevel%
23
+
24
+ :reject_media
25
+ if "%~1"=="" exit /b 0
26
+ set "ARG=%~1"
27
+ if /I "%ARG%"=="--host" shift&shift&goto reject_media
28
+ if /I "%ARG%"=="--port" shift&shift&goto reject_media
29
+ if /I "%ARG%"=="--profile" shift&shift&goto reject_media
30
+ if /I "%ARG%"=="--scheme" shift&shift&goto reject_media
31
+ if "%ARG:~0,1%"=="-" shift&goto reject_media
32
+ if /I "%ARG%"=="media" (
33
+ echo Media commands are not available in this skill package. 1>&2
34
+ exit /b 2
35
+ )
36
+ exit /b 0