web-presentation-cli 0.2.1__tar.gz → 0.3.1__tar.gz

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 (62) hide show
  1. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/PKG-INFO +35 -7
  2. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/README.md +34 -6
  3. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/catalog.toml +2 -2
  4. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/SKILL.md +3 -3
  5. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/cli-usage.md +30 -2
  6. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/component-standards.md +3 -2
  7. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/design-system-and-assets.md +7 -2
  8. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/page-generation.md +7 -5
  9. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/platform-model.md +2 -0
  10. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/platform-overview.md +4 -2
  11. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/route-and-navigation.md +1 -1
  12. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/source-standards.md +12 -0
  13. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/references/validation-and-delivery.md +15 -5
  14. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/pyproject.toml +1 -1
  15. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/__init__.py +1 -1
  16. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/cli.py +18 -2
  17. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/asset.py +9 -5
  18. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/common.py +5 -2
  19. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/component.py +36 -10
  20. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/page.py +15 -9
  21. web_presentation_cli-0.3.1/src/wp/commands/preview.py +69 -0
  22. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/project.py +14 -8
  23. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/skill.py +13 -9
  24. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/style.py +10 -9
  25. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/theme.py +4 -5
  26. web_presentation_cli-0.3.1/src/wp/output_fields.py +233 -0
  27. web_presentation_cli-0.3.1/src/wp/output_profiles.py +99 -0
  28. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/skills/targets.py +30 -5
  29. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp_api_client/client.py +30 -9
  30. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_cli_commands.py +64 -1
  31. web_presentation_cli-0.3.1/tests/test_output_profiles.py +172 -0
  32. web_presentation_cli-0.3.1/tests/test_preview_command.py +85 -0
  33. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_skill_management.py +33 -8
  34. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/.gitignore +0 -0
  35. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/_skill_sources/web-presentation/agents/openai.yaml +0 -0
  36. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/hatch_build.py +0 -0
  37. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/client.py +0 -0
  38. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/__init__.py +0 -0
  39. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/auth.py +0 -0
  40. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/catalog.py +0 -0
  41. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/doctor.py +0 -0
  42. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/job.py +0 -0
  43. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/profile.py +0 -0
  44. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/screenshot.py +0 -0
  45. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/system.py +0 -0
  46. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/commands/workspace.py +0 -0
  47. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/config.py +0 -0
  48. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/formatter.py +0 -0
  49. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/openapi_contracts.py +0 -0
  50. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/openapi_help.py +0 -0
  51. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/skills/__init__.py +0 -0
  52. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/skills/catalog.py +0 -0
  53. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp/skills/installer.py +0 -0
  54. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp_api_client/__init__.py +0 -0
  55. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/src/wp_api_client/openapi.py +0 -0
  56. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/conftest.py +0 -0
  57. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_backend_openapi_contract.py +0 -0
  58. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_capability_commands.py +0 -0
  59. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_openapi_help.py +0 -0
  60. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_openapi_strict.py +0 -0
  61. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/test_screenshot_command.py +0 -0
  62. {web_presentation_cli-0.2.1 → web_presentation_cli-0.3.1}/tests/verify_skill_distribution.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: web-presentation-cli
3
- Version: 0.2.1
3
+ Version: 0.3.1
4
4
  Summary: Web Presentation CLI - 面向 AI 演示文稿创作平台的命令行与 Agent 工具包
5
5
  Project-URL: Homepage, https://github.com/LLMxPM/web-presentation-agent-kit
6
6
  Project-URL: Repository, https://github.com/LLMxPM/web-presentation-agent-kit
@@ -66,14 +66,14 @@ wp profile use production
66
66
 
67
67
  ## Agent Skill 管理
68
68
 
69
- CLI 内置 `web-presentation` Skill,可离线安装到受支持 Agent。交互式终端省略参数时会按实际安装目录分组选择:共用 `.agents/skills` 的五个兼容 Agent 作为一组,Claude Code 和 Qoder 各自一组;脚本、管道或 JSON 模式必须显式传入参数。
69
+ CLI 内置 `web-presentation` Skill,可离线安装到受支持 Agent。交互式终端省略参数时会按实际安装目录分组选择:共用 `.agents/skills` 的兼容 Agent 作为一组,Claude Code、MiMo、WorkBuddy 各自一组;脚本、管道或 JSON 模式必须显式传入参数。
70
70
 
71
71
  ```bash
72
72
  # 当前用户全局安装
73
73
  wp skill install --scope global --agent all
74
74
 
75
75
  # 当前项目安装;默认解析 Git 根目录,也可用 --project-dir 指定
76
- wp skill install --scope project --agent codex --agent qoder
76
+ wp skill install --scope project --agent codex --agent mimo --agent workbuddy
77
77
 
78
78
  # 状态与卸载
79
79
  wp skill status --scope global --agent all
@@ -84,7 +84,26 @@ wp skill install --scope project --agent all --dry-run
84
84
  wp skill export web-presentation
85
85
  ```
86
86
 
87
- 首次使用建议进入智能体将要工作的项目目录,直接运行 `wp skill install`,然后选择 `2. 项目`。项目级安装会进入项目根目录的 `.agents/skills`、`.claude/skills` 或 `.qoder/skills`,不是安装到 Python 包目录。安装后重新加载智能体窗口或新建会话。
87
+ 获取短期预览地址:
88
+
89
+ ```bash
90
+ wp preview get --project-id <project_id>
91
+ wp preview get --project-id <project_id> --route /overview
92
+ wp preview get --page-id <page_id>
93
+ ```
94
+
95
+ 项目和页面目标共用同一个预览命令与 API Client 方法;页面模块入口由 Backend 解析。
96
+
97
+ JSON 输出模式:
98
+
99
+ ```bash
100
+ wp --json project list
101
+ wp --raw project list
102
+ ```
103
+
104
+ `--json` 输出面向 Agent 的稳定字段;`--raw` 输出 Backend 原始 JSON,二者不能同时使用。预览地址是短期 Preview Artifact 地址,不等同于正式发布地址。
105
+
106
+ 首次使用建议进入智能体将要工作的项目目录,直接运行 `wp skill install`,然后选择 `2. 项目`。项目级安装会进入项目根目录下对应 Agent 的 Skill 目录(如 `.agents/skills`、`.claude/skills`、`.mimocode/skills`、`.workbuddy/skills`),不是安装到 Python 包目录。安装后重新加载智能体窗口或新建会话。
88
107
 
89
108
  目录映射:
90
109
 
@@ -92,13 +111,14 @@ wp skill export web-presentation
92
111
  | --- | --- | --- |
93
112
  | Codex、Cursor、GitHub Copilot、Gemini CLI、OpenCode | `.agents/skills` | `~/.agents/skills` |
94
113
  | Claude Code | `.claude/skills` | `~/.claude/skills` |
95
- | Qoder | `.qoder/skills` | `~/.qoder/skills` |
114
+ | MiMo | `.mimocode/skills` | `~/.config/mimocode/skills` |
115
+ | WorkBuddy | `.workbuddy/skills` | `~/.workbuddy/skills` |
96
116
 
97
117
  Skill 与 CLI 一起发布,但使用独立版本。`wp skill status` 会识别缺失、过期、较新、不兼容、用户修改和未受管理等状态;普通升级不会覆盖用户修改,`--force` 会先保留同级备份。CLI 升级不会隐式改写已安装 Skill,需要重新运行 `wp skill install` 完成同步。
98
118
 
99
- 当前版本关系:CLI `0.2.1` 内置 `web-presentation` Skill `1.2.0`,Skill 声明的 CLI 兼容范围为 `>=0.2.1,<0.3.0`。构建时会把这组关系与规范化内容 SHA-256 写入 manifest。
119
+ 当前版本关系:CLI `0.3.1` 内置 `web-presentation` Skill `1.3.2`,Skill 声明的 CLI 兼容范围为 `>=0.3.0,<0.4.0`。构建时会把这组关系与规范化内容 SHA-256 写入 manifest。
100
120
 
101
- Windsurf 和 WorkBuddy 不属于本地目录安装目标。`wp skill export` 生成的标准 ZIP 可用于 WorkBuddy 等支持本地上传的产品;CLI 不从 URL 或第三方仓库下载 Skill。
121
+ Windsurf 不属于本地目录安装目标。`wp skill export` 生成的标准 ZIP 可用于支持本地上传的产品;CLI 不从 URL 或第三方仓库下载 Skill。
102
122
 
103
123
  ## 复制给智能体:安装 CLI 和 Skill
104
124
 
@@ -138,6 +158,14 @@ wp job wait <job_id>
138
158
  写入命令支持 `--idempotency-key <key>`;网络超时后需要重放同一业务请求时复用原 key,不要把同一个 key 用于不同请求。
139
159
 
140
160
 
161
+ ### 0.3.1 行为变更
162
+
163
+ `wp component list` 表格新增「引用路径」列,未发布组件显示 `未发布`;`--json` 的组件列表与建议组件投影新增 `import_path` 与 `import_statement` 字段,取自 Backend 返回,供页面源码直接拼接 `@workspace-components/<code>/v/<version_no>` 别名。内置 Skill `1.3.2` 同步补充工作空间组件的版本化引用契约,禁止引用草稿、自增 ID 或本地相对路径。
164
+
165
+ ### 0.3.0 行为变更
166
+
167
+ `--json` 现在输出面向 Agent 的稳定字段投影;`--raw` 输出完整 Backend 原始 JSON,二者不能同时使用。Project、Page、Component、Asset、Theme、Style、Validation 和 Preview 命令按场景区分列表、详情、源码和诊断字段;成功响应不再注入 `_client` 元数据。预览地址通过 `wp preview get` 获取,属于短期 Preview Artifact。
168
+
141
169
  ### 0.2.1 行为变更
142
170
 
143
171
  契约叶子帮助失败立即退出 1;`--json` 错误输出在 stderr。Doctor 独立检查全部已注册 OpenAPI 契约,存在 error 时退出 1,仅 warning 仍退出 0。自动化必须检查退出码。顶层与本地配置帮助仍可离线使用。
@@ -51,14 +51,14 @@ wp profile use production
51
51
 
52
52
  ## Agent Skill 管理
53
53
 
54
- CLI 内置 `web-presentation` Skill,可离线安装到受支持 Agent。交互式终端省略参数时会按实际安装目录分组选择:共用 `.agents/skills` 的五个兼容 Agent 作为一组,Claude Code 和 Qoder 各自一组;脚本、管道或 JSON 模式必须显式传入参数。
54
+ CLI 内置 `web-presentation` Skill,可离线安装到受支持 Agent。交互式终端省略参数时会按实际安装目录分组选择:共用 `.agents/skills` 的兼容 Agent 作为一组,Claude Code、MiMo、WorkBuddy 各自一组;脚本、管道或 JSON 模式必须显式传入参数。
55
55
 
56
56
  ```bash
57
57
  # 当前用户全局安装
58
58
  wp skill install --scope global --agent all
59
59
 
60
60
  # 当前项目安装;默认解析 Git 根目录,也可用 --project-dir 指定
61
- wp skill install --scope project --agent codex --agent qoder
61
+ wp skill install --scope project --agent codex --agent mimo --agent workbuddy
62
62
 
63
63
  # 状态与卸载
64
64
  wp skill status --scope global --agent all
@@ -69,7 +69,26 @@ wp skill install --scope project --agent all --dry-run
69
69
  wp skill export web-presentation
70
70
  ```
71
71
 
72
- 首次使用建议进入智能体将要工作的项目目录,直接运行 `wp skill install`,然后选择 `2. 项目`。项目级安装会进入项目根目录的 `.agents/skills`、`.claude/skills` 或 `.qoder/skills`,不是安装到 Python 包目录。安装后重新加载智能体窗口或新建会话。
72
+ 获取短期预览地址:
73
+
74
+ ```bash
75
+ wp preview get --project-id <project_id>
76
+ wp preview get --project-id <project_id> --route /overview
77
+ wp preview get --page-id <page_id>
78
+ ```
79
+
80
+ 项目和页面目标共用同一个预览命令与 API Client 方法;页面模块入口由 Backend 解析。
81
+
82
+ JSON 输出模式:
83
+
84
+ ```bash
85
+ wp --json project list
86
+ wp --raw project list
87
+ ```
88
+
89
+ `--json` 输出面向 Agent 的稳定字段;`--raw` 输出 Backend 原始 JSON,二者不能同时使用。预览地址是短期 Preview Artifact 地址,不等同于正式发布地址。
90
+
91
+ 首次使用建议进入智能体将要工作的项目目录,直接运行 `wp skill install`,然后选择 `2. 项目`。项目级安装会进入项目根目录下对应 Agent 的 Skill 目录(如 `.agents/skills`、`.claude/skills`、`.mimocode/skills`、`.workbuddy/skills`),不是安装到 Python 包目录。安装后重新加载智能体窗口或新建会话。
73
92
 
74
93
  目录映射:
75
94
 
@@ -77,13 +96,14 @@ wp skill export web-presentation
77
96
  | --- | --- | --- |
78
97
  | Codex、Cursor、GitHub Copilot、Gemini CLI、OpenCode | `.agents/skills` | `~/.agents/skills` |
79
98
  | Claude Code | `.claude/skills` | `~/.claude/skills` |
80
- | Qoder | `.qoder/skills` | `~/.qoder/skills` |
99
+ | MiMo | `.mimocode/skills` | `~/.config/mimocode/skills` |
100
+ | WorkBuddy | `.workbuddy/skills` | `~/.workbuddy/skills` |
81
101
 
82
102
  Skill 与 CLI 一起发布,但使用独立版本。`wp skill status` 会识别缺失、过期、较新、不兼容、用户修改和未受管理等状态;普通升级不会覆盖用户修改,`--force` 会先保留同级备份。CLI 升级不会隐式改写已安装 Skill,需要重新运行 `wp skill install` 完成同步。
83
103
 
84
- 当前版本关系:CLI `0.2.1` 内置 `web-presentation` Skill `1.2.0`,Skill 声明的 CLI 兼容范围为 `>=0.2.1,<0.3.0`。构建时会把这组关系与规范化内容 SHA-256 写入 manifest。
104
+ 当前版本关系:CLI `0.3.1` 内置 `web-presentation` Skill `1.3.2`,Skill 声明的 CLI 兼容范围为 `>=0.3.0,<0.4.0`。构建时会把这组关系与规范化内容 SHA-256 写入 manifest。
85
105
 
86
- Windsurf 和 WorkBuddy 不属于本地目录安装目标。`wp skill export` 生成的标准 ZIP 可用于 WorkBuddy 等支持本地上传的产品;CLI 不从 URL 或第三方仓库下载 Skill。
106
+ Windsurf 不属于本地目录安装目标。`wp skill export` 生成的标准 ZIP 可用于支持本地上传的产品;CLI 不从 URL 或第三方仓库下载 Skill。
87
107
 
88
108
  ## 复制给智能体:安装 CLI 和 Skill
89
109
 
@@ -123,6 +143,14 @@ wp job wait <job_id>
123
143
  写入命令支持 `--idempotency-key <key>`;网络超时后需要重放同一业务请求时复用原 key,不要把同一个 key 用于不同请求。
124
144
 
125
145
 
146
+ ### 0.3.1 行为变更
147
+
148
+ `wp component list` 表格新增「引用路径」列,未发布组件显示 `未发布`;`--json` 的组件列表与建议组件投影新增 `import_path` 与 `import_statement` 字段,取自 Backend 返回,供页面源码直接拼接 `@workspace-components/<code>/v/<version_no>` 别名。内置 Skill `1.3.2` 同步补充工作空间组件的版本化引用契约,禁止引用草稿、自增 ID 或本地相对路径。
149
+
150
+ ### 0.3.0 行为变更
151
+
152
+ `--json` 现在输出面向 Agent 的稳定字段投影;`--raw` 输出完整 Backend 原始 JSON,二者不能同时使用。Project、Page、Component、Asset、Theme、Style、Validation 和 Preview 命令按场景区分列表、详情、源码和诊断字段;成功响应不再注入 `_client` 元数据。预览地址通过 `wp preview get` 获取,属于短期 Preview Artifact。
153
+
126
154
  ### 0.2.1 行为变更
127
155
 
128
156
  契约叶子帮助失败立即退出 1;`--json` 错误输出在 stderr。Doctor 独立检查全部已注册 OpenAPI 契约,存在 error 时退出 1,仅 warning 仍退出 0。自动化必须检查退出码。顶层与本地配置帮助仍可离线使用。
@@ -2,6 +2,6 @@ schema_version = 1
2
2
 
3
3
  [[skills]]
4
4
  name = "web-presentation"
5
- version = "1.2.0"
5
+ version = "1.3.2"
6
6
  path = "web-presentation"
7
- requires_cli = ">=0.2.1,<0.3.0"
7
+ requires_cli = ">=0.3.0,<0.4.0"
@@ -5,7 +5,7 @@ description: Use the wp CLI to configure Web Presentation access and create or r
5
5
 
6
6
  # Web Presentation Agent
7
7
 
8
- Web Presentation 是面向 AI 的演示内容创作平台,不是单文件幻灯片生成器。通过 `wp` CLI 操作 Backend 中的真实平台对象:演示内容组织在项目和路由中,每一页是 Backend 保存、Runtime 在固定画布编译渲染的 Vue SFC;组件、资源、主题、样式和字体在工作空间内复用。临时 JSON、Vue 和截图文件只是 CLI 的输入输出载体,不是平台内容的事实源。
8
+ Web Presentation 是面向 AI 的演示内容创作平台,不是单文件幻灯片生成器。通过 `wp` CLI 操作 Backend 中的真实平台对象:演示内容组织在项目和路由中,每一页是 Backend 保存、Runtime 在固定画布编译渲染的 Vue SFC;组件、资源、主题、样式和字体在工作空间内复用。临时 JSON、Vue 和截图文件只是 CLI 的输入输出载体,不是平台内容的事实源;统一放在当前工作目录下的 `.tmp/web-presentation/`(截图用其 `shot/` 子目录),见 [CLI 工作流](./references/cli-usage.md)。
9
9
 
10
10
  ## 先理解平台再操作
11
11
 
@@ -16,7 +16,7 @@ Web Presentation 是面向 AI 的演示内容创作平台,不是单文件幻
16
16
  - 交付目标:新建一组演示页面、补充/修改现有页面、统一视觉体系,还是只做分析或截图;
17
17
  - 对象落点:目标工作空间、项目、页面及是否涉及路由和共享资产;
18
18
  - 运行基线:项目画布与样式配置、当前版本、可复用组件、资源和 Runtime Kit 能力;
19
- - 完成证据:Backend 成功响应、Mutation Job 终态、最新对象版本和必要的截图复核。
19
+ - 完成证据:Backend 成功响应、Mutation Job 终态、最新对象版本;用户要求交付链接时还要包含短期预览地址,视觉任务再进行截图复核。
20
20
 
21
21
  ## 按任务加载参考
22
22
 
@@ -38,7 +38,7 @@ Web Presentation 是面向 AI 的演示内容创作平台,不是单文件幻
38
38
  2. 确认 Profile、工作空间和目标对象的真实 ID,读取最新 configuration、路由、源码、版本、draft hash、依赖及必要资产。
39
39
  3. 把内容目标转换成页面 brief 和固定画布构图,再选择满足目标的最小对象变更;不凭名称或记忆猜字段、资源和 import path。
40
40
  4. 轻量字段使用对应 update,页面/组件创建和源码编辑走 Mutation 命令;写入使用幂等键和最新版本基线。
41
- 5. 等待任务终态。成功后重新读取对象并按需截图;失败时依据错误码和诊断修正,不盲目重试。
41
+ 5. 等待任务终态。成功后重新读取对象;用户要求查看效果或交付链接时获取短期预览地址,视觉任务再按需截图;失败时依据错误码和诊断修正,不盲目重试。
42
42
  6. 汇报真实 ID、版本、Job、校验、截图和未完成事项;没有成功响应不得声称已写入或验证通过。
43
43
 
44
44
  ## 不可越过的边界
@@ -49,7 +49,35 @@ wp component update --help
49
49
 
50
50
  契约失败先运行 `wp doctor`,区分健康、契约和认证结果;任一 error 使 doctor 退出 1。HTML 响应应检查网关是否返回前端入口,路径/方法/引用缺失应检查服务端与 CLI 契约。修复后重新读取帮助,不猜字段、不以试探写入寻找 Schema,也不读取内部源码绕过公开契约。没有缓存、离线 Schema 或自动重试。
51
51
 
52
- `--json` 用于稳定解析表格型输出,复杂响应默认已经是 JSON。不要解析 Rich 表格文案来获取 ID、版本或状态。
52
+ `--json` 用于稳定解析面向 Agent 的精简业务字段,复杂响应默认已经是 JSON。`--raw` 输出 Backend 原始 JSON,并自动启用 JSON 输出;二者不能同时使用。不要解析 Rich 表格文案来获取 ID、版本或状态。
53
+
54
+ ## 获取短期预览地址
55
+
56
+ 用户要求查看效果、交付链接或最终汇报时,先确认目标对象已成功写入并重新读取最新版本,再按目标调用:
57
+
58
+ ```bash
59
+ wp --json preview get --project-id <project_id>
60
+ wp --json preview get --project-id <project_id> --route /overview
61
+ wp --json preview get --page-id <page_id>
62
+ ```
63
+
64
+ 项目预览支持 `--route`,页面预览不支持 `--route`;项目和页面目标只能选择一种。响应中的 `preview_url` 是短期 Preview Artifact 地址,不是正式发布地址。
65
+
66
+ ## 临时文件目录
67
+
68
+ 本地 JSON、Vue SFC 和截图只是 CLI 的输入输出载体,不是平台内容的事实源。统一写在当前会话工作目录下,不要写入 Skill 安装目录、Python 包目录或其它系统路径:
69
+
70
+ ```text
71
+ .tmp/web-presentation/
72
+ .tmp/web-presentation/shot/
73
+ ```
74
+
75
+ 约定:
76
+
77
+ - 输入载体(payload、edits、候选/写出的 SFC、route tree、资源文本与元数据)写在 `.tmp/web-presentation/` 下;文件名尽量带对象类型与 ID,例如 `page-42.vue`、`edits-42.json`、`component-7.vue`、`route-tree.json`、`asset.json`;
78
+ - 截图等输出证据写在 `.tmp/web-presentation/shot/`,例如 `shot/page-42.png`;
79
+ - 用户提供的原始素材保持其真实路径;智能体自行生成或落盘的中间文件一律进入上述目录;
80
+ - 汇报时给出相对路径即可;这些文件可随时删除,交付事实以 Backend 对象、Job 终态和重新读取结果为准。
53
81
 
54
82
  ## 文件参数
55
83
 
@@ -62,7 +90,7 @@ wp component update --help
62
90
  - `--route-file`:完整路由树 JSON;
63
91
  - `--ids-file`:只含正整数的 JSON 数组。
64
92
 
65
- 具体根节点、字段、枚举和参数组合只以对应命令 `--help` 中的当前 OpenAPI Schema 为准。
93
+ 具体根节点、字段、枚举和参数组合只以对应命令 `--help` 中的当前 OpenAPI Schema 为准。示例路径默认相对于 `.tmp/web-presentation/`。
66
94
 
67
95
  ## 写入、幂等与任务
68
96
 
@@ -28,6 +28,7 @@
28
28
  - `props` 字段与 `defineProps` 一致,字段的 `type`、`label`、`default` 和 `options` 必须真实可用;预览值不要放在 Schema 根节点。
29
29
  - 支持的 prop 类型以当前平台规范为准,常见为 `string`、`textarea`、`number`、`boolean`、`select`、`json`。
30
30
  - `slots` 使用声明式 `text`、`html`、`component` 节点;slot component 只能引用版本化 Runtime Kit 或已发布工作空间组件,不能引用 Runtime 私有路径或动态 import。
31
+ - 引用工作空间组件(作为 slot component 或在组件源码中引用子组件)时,必须使用 `@workspace-components/<component_code>/v/<version_no>`,且被引用组件必须为已发布的正式版本(`current_version_no > 0`),禁止引用草稿或使用自增主键 ID。
31
32
  - `mocks` 只保存 JSON/文本级静态值,不放函数、表达式、HTTP 请求或 component-preview 内部能力。
32
33
  - `presets` 只写覆盖值;key 稳定、label 清晰,优先提供 2~3 个高质量真实场景。
33
34
  - 资源名、默认值和 mock 数据必须来自真实工具结果;没有资源时使用空值或明确占位,不编造名称。
@@ -37,11 +38,11 @@
37
38
  ```bash
38
39
  wp component get <component_id>
39
40
  wp component dependencies <component_id>
40
- wp component validate <component_id> --mode content --source-file ./Component.vue
41
+ wp component validate <component_id> --mode content --source-file .tmp/web-presentation/component-<component_id>.vue
41
42
  wp component edit <component_id> \
42
43
  --base-version-no <base_version_no> \
43
44
  --base-draft-hash <draft_hash> \
44
- --edits-file ./edits.json \
45
+ --edits-file .tmp/web-presentation/edits-<component_id>.json \
45
46
  --idempotency-key <key>
46
47
  wp component publish <component_id> --idempotency-key <key>
47
48
  ```
@@ -29,10 +29,15 @@
29
29
 
30
30
  ```bash
31
31
  wp --json asset list
32
- wp asset create --payload-file ./asset.json --content-file ./asset-content.txt --idempotency-key <key>
33
- wp asset upload ./image.png --type image --name hero-image --idempotency-key <key>
32
+ wp asset create \
33
+ --payload-file .tmp/web-presentation/asset.json \
34
+ --content-file .tmp/web-presentation/asset-content.txt \
35
+ --idempotency-key <key>
36
+ wp asset upload .tmp/web-presentation/hero-image.png --type image --name hero-image --idempotency-key <key>
34
37
  ```
35
38
 
39
+ 用户直接提供的原始文件保持其真实路径;智能体生成或落盘的 payload、文本和待上传文件写入 `.tmp/web-presentation/`。
40
+
36
41
  文本资源创建前查询是否已有 active 同名资源。可创建的文本类型包括 SVG 图标/图片、Draw.io、Mermaid、Chart 和 Formula;内容必须是完整 UTF-8 文本,并按命令帮助和 Backend Schema 满足扩展名及安全约束。图标 SVG 不得包含 script、事件属性、`foreignObject` 或远程引用,优先使用 `currentColor`。
37
42
 
38
43
  非 SVG 位图、video、font 等使用 `asset upload`;不要用 `asset create` 伪造二进制内容,也不要把 URL、本地路径或 base64 当成可信上传附件参数。生成或上传后用返回的真实 name/ID 和 render_type。
@@ -88,19 +88,21 @@ import DefaultContainer from '@runtime-kit/public/components/page/layout/Default
88
88
  修改已有页面时,先读取最新源码并生成基于真实片段的结构化 edits,再使用当前版本:
89
89
 
90
90
  ```bash
91
- wp page validate <page_id> --mode content --source-file ./Page.vue
91
+ wp page validate <page_id> --mode content --source-file .tmp/web-presentation/page-<page_id>.vue
92
92
  wp page edit <page_id> \
93
93
  --base-version-no <current_version_no> \
94
- --edits-file ./edits.json \
94
+ --edits-file .tmp/web-presentation/edits-<page_id>.json \
95
95
  --idempotency-key <key>
96
96
  ```
97
97
 
98
- `edits.json` 必须使用当前 `wp page edit --help` 显示的结构化编辑 Schema;匹配片段来自最新源码且必须唯一命中。
98
+ `edits-<page_id>.json` 必须使用当前 `wp page edit --help` 显示的结构化编辑 Schema;匹配片段来自最新源码且必须唯一命中。
99
99
 
100
100
  新建页面使用完整 SFC:
101
101
 
102
102
  ```bash
103
- wp page create --project-id <project_id> --name "核心结论" --file ./Page.vue --idempotency-key <key>
103
+ wp page create --project-id <project_id> --name "核心结论" \
104
+ --file .tmp/web-presentation/page-new.vue \
105
+ --idempotency-key <key>
104
106
  ```
105
107
 
106
108
  页面标题、摘要、演讲者备注等轻量字段使用 `wp page update`;不要用 metadata 更新命令承载源码。页面创建和源码编辑会自动执行编译、渲染和布局校验;独立 `page validate` 用于候选预检或需要更多诊断,不是绕过平台写入校验的办法。
@@ -112,7 +114,7 @@ wp page create --project-id <project_id> --name "核心结论" --file ./Page.vue
112
114
  ```bash
113
115
  wp --json page get <page_id>
114
116
  wp --json page source <page_id>
115
- wp page screenshot <page_id> --output .tmp/page.png
117
+ wp page screenshot <page_id> --output .tmp/web-presentation/shot/page-<page_id>.png
116
118
  ```
117
119
 
118
120
  检查截图中的画布尺寸、底部裁切、文字换行、视觉重心、资源加载、空态/缺图和真实内容密度。发现问题时优先做局部 edits,不要无证据地重写整页。
@@ -17,6 +17,7 @@ Web Presentation 的核心边界是“当前工作空间”。所有资源归属
17
17
  | 字体 | 注册的字体族/字体文件声明 | 只读查询;先有资源,再由平台注册/下发 | `font list` |
18
18
  | Runtime Kit | 版本化公开运行时能力目录 | 不是工作空间资产,也不是通用 UI 库;只用真实返回的 `.vN` import path | `runtime-kit list/get` |
19
19
  | Mutation Job | 页面/组件重任务的持久化执行记录 | 状态是 `pending/running/succeeded/failed/canceled` | `job get/wait/cancel/retry` |
20
+ | Preview Artifact | 项目或页面的短期交互预览 | 必须基于成功写入后的最新对象创建;`preview_url` 不代表正式发布 | `preview get` |
20
21
 
21
22
  ## 归属、引用和快照不要混淆
22
23
 
@@ -26,6 +27,7 @@ Web Presentation 的核心边界是“当前工作空间”。所有资源归属
26
27
  - 页面/组件 `dependencies` 是当前版本源码真实依赖,不能用名称搜索结果替代。
27
28
  - 组件草稿不是稳定公共能力;引用前查询发布版本和真实 `import_path`。
28
29
  - 归档对象退出默认查询与操作边界;首版没有永久删除和 Restore。项目归档不会级联归档其页面、路由或共享资产。
30
+ - Preview Artifact 是临时交付证据,不是项目或页面的持久化发布版本;用户要求预览或交付链接时才创建,截图仍单独作为视觉验证证据。
29
31
 
30
32
  ## 读取基线
31
33
 
@@ -30,7 +30,9 @@ Backend Mutation Job(权限、版本、编译、渲染、布局校验)
30
30
  ↓
31
31
  Runtime 固定画布结果
32
32
  ↓
33
- 读取最新版本并截图复核,必要时局部修正
33
+ 读取最新版本
34
+ ↓
35
+ 按需获取短期预览地址并截图复核,必要时局部修正
34
36
  ```
35
37
 
36
38
  这条链路决定了操作顺序:先读上下文和配置,再构图和写源码;先等写入任务成功,再用截图评价视觉结果。不能只生成一份看似合理的 Vue 文件便声称页面已经完成。
@@ -92,7 +94,7 @@ Runtime Kit 提供页面容器、资源渲染、主题、页码、路由目录
92
94
  | “让整套页面风格一致” | 优先检查项目配置、主题和页面组件,再决定是否局部改页 | 配置快照、主题、样式、已发布页面组件、现有页面 |
93
95
  | “替换图片/图标/字体” | 查询或创建工作空间资源,再更新引用它的页面或组件 | 真实资源 name/ID、render type、依赖和目标源码 |
94
96
  | “做一个以后能复用的版式” | 创建或修改页面组件,维护 preview schema,并发布稳定版本 | 组件 standards、现有组件、草稿/发布版本、依赖 |
95
- | “看看效果/导出一张预览图” | 对已有成功版本发起截图并检查输出 | 目标页面 ID、最新版本与截图结果 |
97
+ | “看看效果/获取交互链接” | 对已有成功版本获取项目或页面短期预览地址,必要时再截图 | 目标项目/页面 ID、最新版本与预览响应 |
96
98
  | “只评估怎么做” | 只读查询并给出对象级方案,不提交写入 | 足以支撑结论的平台事实 |
97
99
 
98
100
  用户没有提供 ID 时,先通过列表和详情发现真实对象;名称不能唯一定位时再请用户选择。用户明确要求新建一套演示时,可以创建新项目和页面,但仍要先确认工作空间及现有资产,避免重复建设。
@@ -12,7 +12,7 @@
12
12
  {"routes":[{"route_type":"page","route":"cover","order":0,"hidden":false,"page_id":1},{"route_type":"group","route":"chapter-1","group_title":"第一章","order":1,"children":[{"route":"overview","order":0,"hidden":false,"page_id":2}]}]}
13
13
  ```
14
14
 
15
- `wp project route replace <project_id> --route-file ./route-tree.json --idempotency-key <key>` 是整树替换,遗漏的节点会被移除。GET 响应包含 id、page_code、display_title 等只读字段,不能原样回写;按当前写入 Schema 构造请求。
15
+ `wp project route replace <project_id> --route-file .tmp/web-presentation/route-tree.json --idempotency-key <key>` 是整树替换,遗漏的节点会被移除。GET 响应包含 id、page_code、display_title 等只读字段,不能原样回写;按当前写入 Schema 构造请求。
16
16
 
17
17
  替换前重新读取整树并保留任务范围外的节点。当前接口没有版本条件,读取后仍可能发生并发覆盖;幂等键不能解决并发冲突。不要并行修改同一项目路由,发现基线变化应重新协调,而非盲目覆盖。
18
18
 
@@ -10,6 +10,18 @@
10
10
  - 只能引用平台真实返回的版本化 Runtime Kit 能力、已发布工作空间组件、可见工作空间资源和自身代码。
11
11
  - Tailwind class 必须以完整静态字符串出现在模板、脚本常量或顶层枚举映射中;禁止 `text-${tone}`、`from-${color}` 等运行时拼接。Arbitrary value 也要以完整静态类出现在源码中。
12
12
 
13
+ ## 工作空间组件引用契约
14
+
15
+ - 页面源码引用工作空间组件时,统一使用已发布组件的版本化别名:
16
+ ```ts
17
+ import <ImportName> from '@workspace-components/<component_code>/v/<version_no>'
18
+ ```
19
+ - 约束说明:
20
+ - 路径中的编码必须是组件业务编码 `code`(如 `CMP20260503001`),不能使用自增 ID、本地相对路径或 `@/` 别名;
21
+ - 版本号必须是当前大于 0 的正式发布版本 `current_version_no`,未发布或草稿状态的组件不可在页面中引用;
22
+ - 导入标识符优先使用组件元数据中的 `import_name`(或展示名 PascalCase);
23
+ - 可直接通过 `wp component get <component_id>` 或 `wp component list` 查询已发布的 `import_path` 与 `import_statement`。
24
+
13
25
  ## 画布和布局
14
26
 
15
27
  - 页面根部优先使用项目建议的已发布页面组件,其次是工作空间已发布页面组件,最后才是版本化 `DefaultContainer`。
@@ -1,15 +1,15 @@
1
1
  # 校验与交付
2
2
 
3
- 页面和组件写入由 Backend 的 Mutation Job 负责编译、渲染和布局检查。外部 Agent 的职责是提交正确基线、等待终态、读取结果并用截图验证真实视觉。
3
+ 页面和组件写入由 Backend 的 Mutation Job 负责编译、渲染和布局检查。外部 Agent 的职责是提交正确基线、等待终态、重新读取最新对象;用户要求交付链接时获取短期预览地址,并用截图验证真实视觉。
4
4
 
5
5
  ## 候选校验和写入校验
6
6
 
7
7
  独立校验适用于:写入前检查一份候选 SFC、结构化 edits,或失败后请求详细诊断:
8
8
 
9
9
  ```bash
10
- wp --json page validate <page_id> --mode content --source-file ./Page.vue --detail
11
- wp --json page validate <page_id> --mode edits --edits-file ./edits.json --detail
12
- wp --json component validate <component_id> --mode content --source-file ./Component.vue --detail
10
+ wp --json page validate <page_id> --mode content --source-file .tmp/web-presentation/page-<page_id>.vue --detail
11
+ wp --json page validate <page_id> --mode edits --edits-file .tmp/web-presentation/edits-<page_id>.json --detail
12
+ wp --json component validate <component_id> --mode content --source-file .tmp/web-presentation/component-<component_id>.vue --detail
13
13
  ```
14
14
 
15
15
  `current` 检查当前内容,`content` 检查完整候选源码,`edits` 检查基于当前对象的结构化编辑;具体参数以命令帮助为准。校验不通过是诊断结果,不是写入成功。
@@ -31,10 +31,20 @@ wp --json job wait <job_id> --timeout 120
31
31
 
32
32
  ## 视觉复核
33
33
 
34
+ 用户要求查看可交互效果或交付链接时,获取短期预览地址:
35
+
36
+ ```bash
37
+ wp --json preview get --project-id <project_id>
38
+ wp --json preview get --project-id <project_id> --route /overview
39
+ wp --json preview get --page-id <page_id>
40
+ ```
41
+
42
+ `preview_url` 只用于当前 Preview Artifact 的短期访问,不代表正式发布;项目入口可通过 `--route` 指定,页面入口由 Backend 解析。预览地址用于交互检查,截图用于固定画布的视觉证据,两者不能互相替代。
43
+
34
44
  成功后获取最新截图:
35
45
 
36
46
  ```bash
37
- wp page screenshot <page_id> --output .tmp/page.png
47
+ wp page screenshot <page_id> --output .tmp/web-presentation/shot/page-<page_id>.png
38
48
  ```
39
49
 
40
50
  检查:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "web-presentation-cli"
7
- version = "0.2.1"
7
+ version = "0.3.1"
8
8
  description = "Web Presentation CLI - 面向 AI 演示文稿创作平台的命令行与 Agent 工具包"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -1,3 +1,3 @@
1
1
  """Web Presentation 官方命令行工具包。"""
2
2
 
3
- __version__ = "0.2.1"
3
+ __version__ = "0.3.1"
@@ -13,6 +13,7 @@ from wp.commands.doctor import doctor_cmd
13
13
  from wp.commands.job import job_group
14
14
  from wp.commands.page import page_group
15
15
  from wp.commands.profile import profile_group
16
+ from wp.commands.preview import preview_group
16
17
  from wp.commands.project import project_group
17
18
  from wp.commands.skill import skill_group
18
19
  from wp.commands.style import style_group
@@ -29,14 +30,28 @@ from wp.commands.system import standards_group, system_group
29
30
  is_flag=True,
30
31
  help="让支持表格视图的命令输出 JSON;复杂响应默认也输出 JSON。",
31
32
  )
33
+ @click.option(
34
+ "--raw",
35
+ is_flag=True,
36
+ help="输出 Backend 原始 JSON;与 --json 互斥,并自动启用 JSON 输出。",
37
+ )
32
38
  @click.option("--profile", help="指定使用的 Profile 名称 (默认 default)")
33
39
  @click.option("--workspace", "-w", "workspace_id", type=int, help="覆盖当前操作的目标工作空间 ID")
34
40
  @click.pass_context
35
- def main(ctx: click.Context, as_json: bool, profile: str | None, workspace_id: int | None) -> None:
41
+ def main(
42
+ ctx: click.Context,
43
+ as_json: bool,
44
+ raw: bool,
45
+ profile: str | None,
46
+ workspace_id: int | None,
47
+ ) -> None:
36
48
  """Web Presentation 官方命令行工具 (wp) - 面向 AI 演示文稿创作平台。"""
37
49
 
50
+ if as_json and raw:
51
+ raise click.UsageError("--json 与 --raw 不能同时使用。")
38
52
  ctx.ensure_object(dict)
39
- ctx.obj["as_json"] = as_json
53
+ ctx.obj["as_json"] = as_json or raw
54
+ ctx.obj["raw"] = raw
40
55
  ctx.obj["profile"] = profile
41
56
  ctx.obj["workspace_id"] = workspace_id
42
57
 
@@ -58,6 +73,7 @@ main.add_command(font_group)
58
73
  main.add_command(workspace_group)
59
74
  main.add_command(project_group)
60
75
  main.add_command(page_group)
76
+ main.add_command(preview_group)
61
77
  main.add_command(component_group)
62
78
  main.add_command(asset_group)
63
79
  main.add_command(theme_group)
@@ -43,7 +43,7 @@ def list_assets_cmd(ctx: click.Context, page: int, page_size: int, asset_type: s
43
43
  try:
44
44
  result = get_client(ctx).get("/assets", params={key: value for key, value in params.items() if value is not None})
45
45
  if ctx.obj.get("as_json"):
46
- output_result(ctx, result)
46
+ output_result(ctx, result, profile="asset_list")
47
47
  return
48
48
  rows = [[item.get("id"), item.get("name", "-"), item.get("asset_type", "-"), item.get("status", "-")] for item in result.get("items", [])]
49
49
  print_table("资源列表", ["ID", "名称", "类型", "状态"], rows)
@@ -58,7 +58,7 @@ def get_asset_cmd(ctx: click.Context, asset_id: int) -> None:
58
58
  """获取资源详情。"""
59
59
 
60
60
  try:
61
- output_result(ctx, get_client(ctx).get(f"/assets/{asset_id}"))
61
+ output_result(ctx, get_client(ctx).get(f"/assets/{asset_id}"), profile="asset_detail")
62
62
  except ApiClientError as err:
63
63
  handle_api_error("获取资源详情失败", err)
64
64
 
@@ -67,7 +67,9 @@ def get_asset_cmd(ctx: click.Context, asset_id: int) -> None:
67
67
  asset_group,
68
68
  "upload",
69
69
  contract("POST", "/api/v1/assets"),
70
- examples=("wp asset upload ./hero.png --type image --name hero-image --idempotency-key asset-hero-image",),
70
+ examples=(
71
+ "wp asset upload .tmp/web-presentation/hero-image.png --type image --name hero-image --idempotency-key asset-hero-image",
72
+ ),
71
73
  )
72
74
  @click.argument("file_path", type=click.Path(exists=True, dir_okay=False))
73
75
  @click.option("--type", "asset_type", type=click.Choice(ASSET_TYPES), required=True, help="上传资源类型")
@@ -95,7 +97,9 @@ def upload_asset_cmd(ctx: click.Context, file_path: str, asset_type: str, name:
95
97
  asset_group,
96
98
  "create",
97
99
  contract("POST", "/api/v1/assets/content"),
98
- examples=("wp asset create --payload-file ./asset.json --content-file ./diagram.mmd --idempotency-key asset-diagram",),
100
+ examples=(
101
+ "wp asset create --payload-file .tmp/web-presentation/asset.json --content-file .tmp/web-presentation/diagram.mmd --idempotency-key asset-diagram",
102
+ ),
99
103
  )
100
104
  @click.option("--payload-file", type=click.Path(exists=True, dir_okay=False), required=True, help="文本资源创建 JSON 请求体")
101
105
  @click.option("--content-file", type=click.Path(exists=True, dir_okay=False), help="覆盖 JSON 中 content 的文本文件")
@@ -223,7 +227,7 @@ def archive_asset_cmd(ctx: click.Context, asset_id: int | None, ids_file: str |
223
227
  if ids_file:
224
228
  ids = require_ids(read_json_file(ids_file, label="归档 ID"))
225
229
  confirm_archive(ids, yes=yes, label="资源")
226
- output_result(ctx, client.post("/assets/batch-archive", json_data={"ids": ids}))
230
+ output_result(ctx, client.post("/assets/batch-archive", json_data={"ids": ids}), profile="archive")
227
231
  return
228
232
  if asset_id is None:
229
233
  raise click.UsageError("必须提供 asset_id 或 --ids-file。")
@@ -11,6 +11,7 @@ import click
11
11
  from wp.client import ApiClient, ApiClientError
12
12
  from wp.config import get_profile, load_config
13
13
  from wp.formatter import print_error, print_json
14
+ from wp.output_profiles import project_response
14
15
 
15
16
 
16
17
  def get_client(ctx: click.Context) -> ApiClient:
@@ -101,9 +102,11 @@ def require_ids(value: Any, *, label: str = "ID 列表") -> list[int]:
101
102
  return items
102
103
 
103
104
 
104
- def output_result(ctx: click.Context, value: Any) -> None:
105
- """输出命令结果;复杂响应统一使用 JSON,保证 CLI 与 Agent 消费一致。"""
105
+ def output_result(ctx: click.Context, value: Any, *, profile: str | None = None, detail: bool = False) -> None:
106
+ """输出原始或稳定投影后的 JSON,保证 CLI 与 Agent 消费一致。"""
106
107
 
108
+ if profile and not ctx.obj.get("raw"):
109
+ value = project_response(value, profile, detail=detail)
107
110
  print_json(value)
108
111
 
109
112