@remixmate/cli 0.9.72 → 0.9.73

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 (179) hide show
  1. package/LICENSE +45 -21
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/dist/argv.js +1 -51
  5. package/dist/auth/auth-lock.js +1 -100
  6. package/dist/auth/auto-login.js +7 -75
  7. package/dist/auth/commands.js +40 -290
  8. package/dist/auth/credential-store.js +1 -143
  9. package/dist/auth/device-flow-runner.js +13 -110
  10. package/dist/auth/device-flow.js +1 -132
  11. package/dist/auth/ensure.js +1 -62
  12. package/dist/auth/environment.js +1 -69
  13. package/dist/auth/pending-store.js +1 -45
  14. package/dist/auth/resolve.js +1 -44
  15. package/dist/billing.js +3 -76
  16. package/dist/capabilities.js +1 -75
  17. package/dist/cli.js +39 -211
  18. package/dist/diagnostics.js +2 -70
  19. package/dist/doctor.js +9 -188
  20. package/dist/errors.js +1 -33
  21. package/dist/exec.js +4 -47
  22. package/dist/handlers/gen-digital-human.js +33 -264
  23. package/dist/handlers/gen-image.js +9 -113
  24. package/dist/handlers/gen-post.js +15 -192
  25. package/dist/handlers/gen-video.js +7 -185
  26. package/dist/handlers/gen-voice.js +19 -133
  27. package/dist/handlers/index.js +1 -20
  28. package/dist/handlers/shared.js +1 -66
  29. package/dist/handlers/template-init.js +1 -21
  30. package/dist/http.js +3 -155
  31. package/dist/index.js +1 -8
  32. package/dist/install.js +40 -448
  33. package/dist/manifest.json +44 -3
  34. package/dist/progress.js +2 -15
  35. package/dist/project/commands.js +34 -156
  36. package/dist/project/host.js +1 -151
  37. package/dist/project/resolve.js +1 -65
  38. package/dist/project/store.js +2 -97
  39. package/dist/project/take.js +1 -106
  40. package/dist/project/trace.js +5 -278
  41. package/dist/registry.js +3 -70
  42. package/dist/runner.js +7 -225
  43. package/dist/skill-schema.js +1 -194
  44. package/dist/template/args.js +1 -69
  45. package/dist/template/check.js +2 -30
  46. package/dist/template/commands.js +34 -163
  47. package/dist/template/constants.js +1 -46
  48. package/dist/template/init.js +5 -133
  49. package/dist/template/list.js +1 -46
  50. package/dist/template/preview.js +7 -318
  51. package/dist/template/proc.js +1 -43
  52. package/dist/template/project.js +6 -161
  53. package/dist/template/publish.js +5 -185
  54. package/dist/template/render-client.js +2 -79
  55. package/dist/template/upgrade.js +4 -123
  56. package/dist/text.js +1 -15
  57. package/package.json +2 -35
  58. package/skills/doc-parse/scripts/extract_via_render.py +32 -32
  59. package/skills/export-jianying/scripts/gen_jianying_draft.py +188 -188
  60. package/skills/gen-script/SKILL.md +23 -1
  61. package/skills/gen-script/scripts/gen_script.py +644 -551
  62. package/skills/gen-script/skill.json +12 -0
  63. package/skills/gen-script/version.json +1 -1
  64. package/skills/prepare-video-assets/scripts/prepare_video_assets.py +21 -21
  65. package/skills/render-video/scripts/_chrome_vendor.py +17 -17
  66. package/skills/render-video/scripts/_digital_human_segments.py +34 -34
  67. package/skills/render-video/scripts/_video_probe.py +33 -33
  68. package/skills/render-video/scripts/_vod_polling.py +13 -13
  69. package/skills/render-video/scripts/remote_renderer_client.py +42 -42
  70. package/skills/render-video/scripts/render_video.py +639 -639
  71. package/skills/render-video/scripts/required_props.py +37 -37
  72. package/skills/render-video/scripts/upload_video.py +35 -35
  73. package/skills/render-video/version.json +1 -1
  74. package/skills/template-registry/SKILL.md +16 -0
  75. package/skills/template-registry/scripts/countdown_spec.py +92 -92
  76. package/skills/template-registry/scripts/doc_extract.py +40 -40
  77. package/skills/template-registry/scripts/list_templates.py +303 -191
  78. package/skills/template-registry/scripts/log_diagnostics.py +1 -1
  79. package/skills/template-registry/scripts/match_template.py +87 -87
  80. package/skills/template-registry/scripts/payload_hydrator.py +89 -89
  81. package/skills/template-registry/scripts/registry_loader.py +159 -159
  82. package/skills/template-registry/scripts/render_job_client.py +75 -75
  83. package/skills/template-registry/scripts/showcase_loader.py +44 -44
  84. package/skills/template-registry/skill.json +4 -1
  85. package/skills/template-registry/version.json +1 -1
  86. package/skills/template-registry/video_dsl/runtime/__init__.py +8 -8
  87. package/skills/template-registry/video_dsl/runtime/dsl_validator.py +329 -329
  88. package/skills/template-registry/video_dsl/runtime/narration_budget.py +36 -36
  89. package/skills/template-registry/video_dsl/runtime/payload_contract.py +7 -7
  90. package/skills/template-registry/video_dsl/runtime/prompt_enhancer.py +98 -98
  91. package/skills/template-registry/video_dsl/runtime/timeline_compiler.py +127 -127
  92. package/skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json +14 -1
  93. package/skills/video-parser/scripts/analyze_video.py +173 -173
  94. package/skills/video-parser/scripts/deconstruct_video.py +91 -91
  95. package/skills/video-parser/scripts/parse_via_render.py +21 -21
  96. package/skills/web-screenshot/scripts/_media_screenshot/__init__.py +4 -4
  97. package/skills/web-screenshot/scripts/_media_screenshot/bootstrap.py +7 -7
  98. package/skills/web-screenshot/scripts/_media_screenshot/browser.py +4 -4
  99. package/skills/web-screenshot/scripts/_media_screenshot/cli_args.py +4 -4
  100. package/skills/web-screenshot/scripts/_media_screenshot/js_loader.py +2 -2
  101. package/skills/web-screenshot/scripts/_media_screenshot/overlay.py +1 -1
  102. package/skills/web-screenshot/scripts/_media_screenshot/reader.py +40 -40
  103. package/skills/web-screenshot/scripts/_media_screenshot/recording.py +11 -11
  104. package/skills/web-screenshot/scripts/_media_screenshot/scenes/__init__.py +8 -8
  105. package/skills/web-screenshot/scripts/_media_screenshot/scenes/arrow.py +2 -2
  106. package/skills/web-screenshot/scripts/_media_screenshot/scenes/caption.py +1 -1
  107. package/skills/web-screenshot/scripts/_media_screenshot/scenes/click.py +1 -1
  108. package/skills/web-screenshot/scripts/_media_screenshot/scenes/code_lines.py +5 -5
  109. package/skills/web-screenshot/scripts/_media_screenshot/scenes/focus.py +1 -1
  110. package/skills/web-screenshot/scripts/_media_screenshot/scenes/highlight.py +3 -3
  111. package/skills/web-screenshot/scripts/_media_screenshot/scenes/hover.py +1 -1
  112. package/skills/web-screenshot/scripts/_media_screenshot/scenes/redact.py +1 -1
  113. package/skills/web-screenshot/scripts/_media_screenshot/scenes/scroll.py +1 -1
  114. package/skills/web-screenshot/scripts/_media_screenshot/scenes/sequence.py +1 -1
  115. package/skills/web-screenshot/scripts/_media_screenshot/scenes/title_card.py +1 -1
  116. package/skills/web-screenshot/scripts/_media_screenshot/scenes/type.py +1 -1
  117. package/skills/web-screenshot/scripts/_media_screenshot/scenes/wait.py +1 -1
  118. package/skills/web-screenshot/scripts/_media_screenshot/scenes/zoom.py +2 -2
  119. package/skills/web-screenshot/scripts/_media_screenshot/screenshot.py +15 -15
  120. package/skills/web-screenshot/scripts/_media_screenshot/storyboard.py +2 -2
  121. package/skills/web-screenshot/scripts/_media_screenshot/template.py +11 -11
  122. package/skills/web-screenshot/scripts/_media_screenshot/trim.py +10 -10
  123. package/skills/web-screenshot/scripts/_media_screenshot/urlguard.py +22 -22
  124. package/skills/web-screenshot/scripts/_media_upload.py +33 -33
  125. package/skills/web-screenshot/scripts/read_page.py +15 -15
  126. package/skills/web-screenshot/scripts/record.py +26 -26
  127. package/skills/web-screenshot/scripts/screenshot.py +5 -5
  128. package/dist/argv.d.ts +0 -15
  129. package/dist/auth/auth-lock.d.ts +0 -26
  130. package/dist/auth/auto-login.d.ts +0 -20
  131. package/dist/auth/commands.d.ts +0 -8
  132. package/dist/auth/credential-store.d.ts +0 -60
  133. package/dist/auth/device-flow-runner.d.ts +0 -58
  134. package/dist/auth/device-flow.d.ts +0 -52
  135. package/dist/auth/ensure.d.ts +0 -55
  136. package/dist/auth/environment.d.ts +0 -38
  137. package/dist/auth/pending-store.d.ts +0 -33
  138. package/dist/auth/resolve.d.ts +0 -30
  139. package/dist/billing.d.ts +0 -44
  140. package/dist/capabilities.d.ts +0 -63
  141. package/dist/cli.d.ts +0 -13
  142. package/dist/diagnostics.d.ts +0 -24
  143. package/dist/doctor.d.ts +0 -22
  144. package/dist/errors.d.ts +0 -29
  145. package/dist/exec.d.ts +0 -18
  146. package/dist/handlers/gen-digital-human.d.ts +0 -17
  147. package/dist/handlers/gen-image.d.ts +0 -20
  148. package/dist/handlers/gen-post.d.ts +0 -22
  149. package/dist/handlers/gen-video.d.ts +0 -19
  150. package/dist/handlers/gen-voice.d.ts +0 -26
  151. package/dist/handlers/index.d.ts +0 -20
  152. package/dist/handlers/shared.d.ts +0 -26
  153. package/dist/handlers/template-init.d.ts +0 -10
  154. package/dist/http.d.ts +0 -72
  155. package/dist/index.d.ts +0 -9
  156. package/dist/install.d.ts +0 -71
  157. package/dist/progress.d.ts +0 -23
  158. package/dist/project/commands.d.ts +0 -19
  159. package/dist/project/host.d.ts +0 -91
  160. package/dist/project/resolve.d.ts +0 -43
  161. package/dist/project/store.d.ts +0 -31
  162. package/dist/project/take.d.ts +0 -50
  163. package/dist/project/trace.d.ts +0 -98
  164. package/dist/registry.d.ts +0 -30
  165. package/dist/runner.d.ts +0 -39
  166. package/dist/skill-schema.d.ts +0 -138
  167. package/dist/template/args.d.ts +0 -25
  168. package/dist/template/check.d.ts +0 -23
  169. package/dist/template/commands.d.ts +0 -25
  170. package/dist/template/constants.d.ts +0 -39
  171. package/dist/template/init.d.ts +0 -28
  172. package/dist/template/list.d.ts +0 -23
  173. package/dist/template/preview.d.ts +0 -60
  174. package/dist/template/proc.d.ts +0 -26
  175. package/dist/template/project.d.ts +0 -47
  176. package/dist/template/publish.d.ts +0 -43
  177. package/dist/template/render-client.d.ts +0 -39
  178. package/dist/template/upgrade.d.ts +0 -44
  179. package/dist/text.d.ts +0 -8
package/dist/install.js CHANGED
@@ -1,448 +1,40 @@
1
- /**
2
- * `remixmate install` / `remixmate uninstall` — 把包内 skills/ 铺进 agent 宿主。
3
- *
4
- * 为什么需要一条命令,而不是让站点给出 `cp -R "$(npm root -g)/…/skills/." ~/.claude/skills/`:
5
- *
6
- * 1. 目标已经不止一个。Claude Code 与 Codex 现在用同一套 SKILL.md 格式
7
- * (Codex 装到 $CODEX_HOME/skills/<name>),手工 cp 的心智成本直接翻倍。
8
- * 2. 拷贝出去的副本没有主人。`npm update -g` 之后包升了级、副本停在旧版;
9
- * `npm uninstall -g` 之后副本原地变成孤儿。两种都是静默的 —— 本项目作者机器上
10
- * 就留着一批 5 月建的、指向早已不存在路径的 skill 目录,没有任何东西负责清理。
11
- *
12
- * 所以这里的安装是**受管**的:每个宿主的 skills 目录下写一份装机回执
13
- * (.remixmate-install.json),记下版本、来源与这次铺下去的 skill 名单。升级照名单
14
- * 覆盖、卸载照名单删除、doctor 照名单比对版本 —— 三件事都不靠猜目录里哪些是我们的。
15
- *
16
- * 刻意不做的两件事:
17
- * - 不挂 npm postinstall。`npm i -g` 时往 ~/.claude、~/.codex 写东西太越界,
18
- * 且 `--ignore-scripts` 下会静默失效。安装必须是用户显式发起的动作。
19
- * - 不用软链。指向 $(npm root -g) 看着优雅,但 node 版本管理器一切换路径就变,
20
- * 全部断掉且极难排查。拷贝 + 回执 + doctor 漂移检查更稳。
21
- */
22
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
23
- import os from 'node:os';
24
- import path from 'node:path';
25
- import { fileURLToPath } from 'node:url';
26
- import { SKILLS_DIR } from './registry.js';
27
- import { EXIT } from './errors.js';
28
- import { padDisplay } from './text.js';
29
- export const INSTALL_VERB = 'install';
30
- export const UNINSTALL_VERB = 'uninstall';
31
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
32
- const PKG_ROOT = path.resolve(__dirname, '..');
33
- /** 装机回执。升级 / 卸载 / 漂移检查都只认它。 */
34
- const RECEIPT = '.remixmate-install.json';
35
- const PACKAGE_NAME = '@remixmate/cli';
36
- /**
37
- * 支持的 agent 宿主。
38
- *
39
- * 共同点是 skill 的格式:`<某个目录>/skills/<name>/SKILL.md`,frontmatter 都是
40
- * name + description —— 一份 skills/ 能喂给所有宿主。这张表记的是各家把那个「某个
41
- * 目录」放在哪、能不能被环境变量改、有没有用户级 / 项目级。
42
- *
43
- * 每一条的依据:
44
- * - Claude Code / Codex:各自的官方安装位置(Codex 见其内置 skill-installer,
45
- * 原话是装到 $CODEX_HOME/skills)。
46
- * - WorkBuddy / CodeBuddy:WorkBuddy 内置的 find-skills skill 给了两条路径,
47
- * 它按 __CFBundleIdentifier 区分。这里不做那个区分 —— 检测到哪个装哪个,
48
- * 两个都在就都装,比猜「当前跑在哪个客户端里」稳。
49
- * - Trae:内置的 skill-creator skill 只给了一个位置 —— 工作区的
50
- * `.trae/skills/<name>/`。注意它的应用数据目录叫 ~/.trae-cn(国内版),
51
- * 跟 skill 目录名 .trae 不是一个东西,而且 ~/.trae-cn/skills 并不存在。
52
- * 没有任何证据表明存在用户级位置,所以 userDirName 留空:Trae 只能项目级装。
53
- */
54
- const HOSTS = [
55
- {
56
- id: 'claude',
57
- label: 'Claude Code',
58
- detectDirNames: ['.claude'],
59
- homeEnv: 'CLAUDE_CONFIG_DIR',
60
- userDirName: '.claude',
61
- projectDirName: '.claude',
62
- },
63
- {
64
- id: 'codex',
65
- label: 'Codex',
66
- detectDirNames: ['.codex'],
67
- homeEnv: 'CODEX_HOME',
68
- userDirName: '.codex',
69
- },
70
- {
71
- id: 'workbuddy',
72
- label: 'WorkBuddy',
73
- detectDirNames: ['.workbuddy'],
74
- userDirName: '.workbuddy',
75
- projectDirName: '.workbuddy',
76
- },
77
- {
78
- id: 'codebuddy',
79
- label: 'CodeBuddy',
80
- detectDirNames: ['.codebuddy'],
81
- userDirName: '.codebuddy',
82
- projectDirName: '.codebuddy',
83
- },
84
- {
85
- id: 'trae',
86
- // Trae CN 与 TraeWork CN(安装出来叫 TRAE SOLO CN.app,bundle id cn.trae.solo.app)
87
- // 共用 ~/.trae-cn —— 后者的内置 skill(dynamic-ui 等)就躺在那底下的
88
- // builtin/*/skills/,所以一条 host 覆盖两个客户端。
89
- label: 'Trae / TraeWork',
90
- detectDirNames: ['.trae-cn', '.trae'],
91
- projectDirName: '.trae',
92
- },
93
- ];
94
- const HOST_IDS = HOSTS.map((h) => h.id);
95
- function spec(id) {
96
- return HOSTS.find((h) => h.id === id);
97
- }
98
- /**
99
- * 用户级 skills 目录;宿主没有用户级位置时返回 null。声明了环境变量的宿主要跟着
100
- * 变量走 —— 否则把 CODEX_HOME 指到别处的用户会看到「未检测到 Codex」。
101
- */
102
- function userSkillsDir(id) {
103
- const h = spec(id);
104
- if (!h.userDirName)
105
- return null;
106
- const override = h.homeEnv ? process.env[h.homeEnv] : undefined;
107
- return path.join(override || path.join(os.homedir(), h.userDirName), 'skills');
108
- }
109
- /** 检测用的候选目录 —— 存在任意一个就算这台机器上装了这个 agent。 */
110
- function detectDirs(id) {
111
- const h = spec(id);
112
- const override = h.homeEnv ? process.env[h.homeEnv] : undefined;
113
- if (override)
114
- return [override];
115
- return h.detectDirNames.map((d) => path.join(os.homedir(), d));
116
- }
117
- function isInstalled(id) {
118
- return detectDirs(id).some((d) => existsSync(d));
119
- }
120
- function hostOf(id) {
121
- const dir = userSkillsDir(id);
122
- return dir ? { id, label: spec(id).label, skillsDir: dir } : null;
123
- }
124
- /** 项目级安装目标:当前目录下的 ./<projectDirName>/skills。 */
125
- function projectHostOf(id) {
126
- const h = spec(id);
127
- if (!h.projectDirName)
128
- return null;
129
- return {
130
- id,
131
- label: `${h.label}(项目级)`,
132
- skillsDir: path.join(process.cwd(), h.projectDirName, 'skills'),
133
- };
134
- }
135
- /** 已检测到、且**有用户级位置**的宿主。 */
136
- export function detectHosts() {
137
- return HOST_IDS.filter(isInstalled)
138
- .map(hostOf)
139
- .filter((h) => h !== null);
140
- }
141
- /**
142
- * 检测到了、但只能项目级安装的宿主(当前只有 Trae)。
143
- *
144
- * 单独拎出来是为了别把它们**静默**跳过:用户装了 Trae 却在全局 install 的输出里
145
- * 完全看不到它,只会以为这个 CLI 不支持 —— 正是这次 WorkBuddy 的翻车方式。
146
- */
147
- export function projectOnlyHosts() {
148
- return HOST_IDS.filter((id) => isInstalled(id) && !spec(id).userDirName);
149
- }
150
- export function packageVersion() {
151
- try {
152
- const raw = readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf-8');
153
- return JSON.parse(raw).version ?? 'unknown';
154
- }
155
- catch {
156
- return 'unknown';
157
- }
158
- }
159
- /**
160
- * 包内可安装的 skill 名单。
161
- *
162
- * 用 SKILLS_DIR 而不是 resolveBaseDir():install 铺的永远是**本包自带**的那份,
163
- * SKILL_BASE_DIR 是给 ab-agent 之类宿主在运行期改 skill 树用的,不该改变安装来源。
164
- */
165
- function bundledSkills() {
166
- if (!existsSync(SKILLS_DIR))
167
- return [];
168
- return readdirSync(SKILLS_DIR, { withFileTypes: true })
169
- .filter((e) => e.isDirectory() && existsSync(path.join(SKILLS_DIR, e.name, 'SKILL.md')))
170
- .map((e) => e.name)
171
- .sort();
172
- }
173
- function readReceipt(skillsDir) {
174
- const file = path.join(skillsDir, RECEIPT);
175
- if (!existsSync(file))
176
- return null;
177
- try {
178
- return JSON.parse(readFileSync(file, 'utf-8'));
179
- }
180
- catch {
181
- // 回执损坏时按「没装过」处理:那样只会退化成需要 --force,而不是把用户的目录删错。
182
- return null;
183
- }
184
- }
185
- const nonNull = (h) => h !== null;
186
- function parseArgs(argv, verb) {
187
- const out = { hosts: [], force: false, help: false };
188
- const picked = [];
189
- let all = false;
190
- let dir = '';
191
- let project = false;
192
- for (let i = 0; i < argv.length; i++) {
193
- const a = argv[i];
194
- const eq = a.indexOf('=');
195
- const key = eq > 0 ? a.slice(0, eq) : a;
196
- const inline = eq > 0 ? a.slice(eq + 1) : null;
197
- const next = () => inline ?? argv[++i] ?? '';
198
- switch (key) {
199
- case '--host': {
200
- const v = next();
201
- // `all` 是「所有**适用**的宿主」,不是「表里每一行」—— 展开成后者会让
202
- // `--host all` 撞上 Trae 这种只有项目级的宿主而整条命令失败。
203
- if (v === 'all')
204
- all = true;
205
- else if (HOST_IDS.includes(v))
206
- picked.push(v);
207
- else {
208
- out.error = `未知参数: --host ${v}`;
209
- return out;
210
- }
211
- break;
212
- }
213
- case '--dir':
214
- dir = next();
215
- break;
216
- case '--project':
217
- project = true;
218
- break;
219
- case '--force':
220
- out.force = true;
221
- break;
222
- case '-h':
223
- case '--help':
224
- out.help = true;
225
- return out;
226
- default:
227
- out.error = `未知参数: ${a}`;
228
- return out;
229
- }
230
- }
231
- if (dir) {
232
- out.hosts = [{ id: 'custom', label: '自定义目录', skillsDir: path.resolve(dir) }];
233
- return out;
234
- }
235
- if (project) {
236
- // Codex 的官方安装位置只有 $CODEX_HOME/skills(见其内置 skill-installer),
237
- // 没有项目级约定,不臆造一个 —— 点名 --host codex --project 直接报错,
238
- // 不声不响装到一个宿主永远不会读的目录才是最糟的。
239
- const chosen = all
240
- ? HOST_IDS.filter((id) => spec(id).projectDirName)
241
- : picked.length > 0
242
- ? [...new Set(picked)]
243
- : HOST_IDS.filter((id) => isInstalled(id) && spec(id).projectDirName);
244
- const unsupported = chosen.filter((id) => !spec(id).projectDirName);
245
- if (unsupported.length > 0) {
246
- out.error = `${unsupported.map((id) => spec(id).label).join('、')} 没有项目级 skill 目录,不能和 --project 一起用`;
247
- return out;
248
- }
249
- out.hosts = chosen.map(projectHostOf).filter(nonNull);
250
- return out;
251
- }
252
- if (all) {
253
- out.hosts = HOST_IDS.map(hostOf).filter(nonNull);
254
- return out;
255
- }
256
- if (picked.length > 0) {
257
- const chosen = [...new Set(picked)];
258
- // 点名了一个只有项目级的宿主(Trae)却没给 --project:报错而不是默默装到别处。
259
- const userless = chosen.filter((id) => !spec(id).userDirName);
260
- if (userless.length > 0) {
261
- out.error =
262
- `${userless.map((id) => spec(id).label).join('、')} 只有项目级 skill 目录 —— ` +
263
- '进到项目根目录后加 --project 重跑。';
264
- return out;
265
- }
266
- out.hosts = chosen.map(hostOf).filter(nonNull);
267
- }
268
- else {
269
- // 卸载时不做检测:配置目录可能已经随 agent 一起被删掉,而我们铺出去的副本还在。
270
- out.hosts = verb === UNINSTALL_VERB ? HOST_IDS.map(hostOf).filter(nonNull) : detectHosts();
271
- }
272
- return out;
273
- }
274
- export function installUsage() {
275
- process.stdout.write('Usage: remixmate install [options]\n' +
276
- '\n' +
277
- '把本包自带的 skill 装进已检测到的 agent 宿主,让它们能自动发现这些能力。\n' +
278
- '重复运行即升级。支持的宿主:\n' +
279
- HOSTS.map((h) => ` ${padDisplay(h.label, 14)}${h.userDirName ? `~/${h.userDirName}/skills` : '(仅项目级)'}${h.projectDirName ? ` 项目级 ./${h.projectDirName}/skills` : ''}\n`).join('') +
280
- '\n' +
281
- 'Options:\n' +
282
- ` --host <${HOST_IDS.join('|')}|all>\n` +
283
- ' 只装指定宿主(默认:装到所有检测到的宿主)\n' +
284
- ' --project 装到当前目录 ./<配置目录>/skills(Codex 不支持)\n' +
285
- ' --dir <path> 自定义 skills 父目录(覆盖上面两者)\n' +
286
- ' --force 覆盖同名的、非本 CLI 安装的 skill 目录\n');
287
- }
288
- export function uninstallUsage() {
289
- process.stdout.write('Usage: remixmate uninstall [options]\n' +
290
- '\n' +
291
- '按装机回执删除本 CLI 装过的 skill —— 只删回执里列出的目录,不碰其它 skill。\n' +
292
- '\n' +
293
- 'Options:\n' +
294
- ` --host <${HOST_IDS.join('|')}|all>\n` +
295
- ' 只卸载指定宿主(默认:所有宿主都查)\n' +
296
- ' --project 卸载当前目录 ./.claude/skills 下的安装\n' +
297
- ' --dir <path> 自定义 skills 父目录\n');
298
- }
299
- function installInto(host, names, version, force) {
300
- const prev = readReceipt(host.skillsDir);
301
- const owned = new Set(prev?.skills ?? []);
302
- // 目录已存在、又不在上一次的回执里 —— 那是别人的 skill(同名很容易撞:gen-image
303
- // 这种名字一点也不独特)。默认拒绝而不是覆盖,让用户显式 --force。
304
- const conflicts = names.filter((n) => existsSync(path.join(host.skillsDir, n)) && !owned.has(n));
305
- if (conflicts.length > 0 && !force) {
306
- return (`${host.skillsDir} 下已存在同名目录,且不是本 CLI 装的:${conflicts.join('、')}\n` +
307
- ' 确认可以覆盖后加 --force 重跑。');
308
- }
309
- mkdirSync(host.skillsDir, { recursive: true });
310
- // 上一版装过、这一版没有了的 skill(上游改名或下线)要一并清掉,否则宿主会一直
311
- // 加载一个已经没有后端支撑的 SKILL.md。
312
- for (const stale of owned) {
313
- if (!names.includes(stale))
314
- rmSync(path.join(host.skillsDir, stale), { recursive: true, force: true });
315
- }
316
- for (const name of names) {
317
- const dest = path.join(host.skillsDir, name);
318
- // 先删再拷:直接覆盖会把上一版多出来的文件留在原地,攒出一个既非旧版也非新版的目录。
319
- rmSync(dest, { recursive: true, force: true });
320
- cpSync(path.join(SKILLS_DIR, name), dest, { recursive: true });
321
- }
322
- const receipt = {
323
- package: PACKAGE_NAME,
324
- version,
325
- installedAt: new Date().toISOString(),
326
- source: SKILLS_DIR,
327
- skills: names,
328
- };
329
- writeFileSync(path.join(host.skillsDir, RECEIPT), JSON.stringify(receipt, null, 2) + '\n', 'utf-8');
330
- return null;
331
- }
332
- export function runInstall(argv) {
333
- const opts = parseArgs(argv, INSTALL_VERB);
334
- if (opts.help) {
335
- installUsage();
336
- return EXIT.OK;
337
- }
338
- if (opts.error) {
339
- process.stderr.write(`❌ ${opts.error}\n`);
340
- installUsage();
341
- return EXIT.USAGE;
342
- }
343
- const names = bundledSkills();
344
- if (names.length === 0) {
345
- process.stderr.write(`❌ 包内没有可安装的 skill(${SKILLS_DIR})\n`);
346
- return EXIT.ERROR;
347
- }
348
- const projectOnly = projectOnlyHosts();
349
- if (opts.hosts.length === 0) {
350
- // 只检测到项目级宿主(比如只装了 Trae)时,这不是「没检测到」,而是「装法不同」。
351
- if (projectOnly.length > 0) {
352
- process.stderr.write(`❌ 只检测到 ${projectOnly.map((id) => spec(id).label).join('、')},` +
353
- '它只有项目级 skill 目录。\n' +
354
- ' 进到项目根目录后运行:remixmate install --project\n');
355
- return EXIT.USAGE;
356
- }
357
- process.stderr.write('❌ 没有检测到任何 agent 宿主。找过这些位置:\n' +
358
- HOST_IDS.map((id) => ` ${padDisplay(spec(id).label, 14)}${detectDirs(id).join('、')}\n`).join('') +
359
- ' 先把 agent 装好再重跑,或用 --dir <path> 指定目录。\n');
360
- return EXIT.USAGE;
361
- }
362
- const version = packageVersion();
363
- let failures = 0;
364
- for (const host of opts.hosts) {
365
- const err = installInto(host, names, version, opts.force);
366
- if (err) {
367
- failures += 1;
368
- process.stderr.write(`❌ ${padDisplay(host.label, 16)}${err}\n`);
369
- continue;
370
- }
371
- process.stdout.write(`✅ ${padDisplay(host.label, 16)}${host.skillsDir}(${names.length} 个 skill,${version})\n`);
372
- }
373
- if (failures > 0)
374
- return EXIT.ERROR;
375
- // 检测到了但这一轮装不了的宿主要说出来 —— 静默跳过会让用户以为不支持。
376
- if (projectOnly.length > 0 && !opts.hosts.some((h) => projectOnly.includes(h.id))) {
377
- process.stdout.write(`\nℹ️ 还检测到 ${projectOnly.map((id) => spec(id).label).join('、')},` +
378
- '它只有项目级 skill 目录 —— 在项目根目录里运行 remixmate install --project 即可。\n');
379
- }
380
- process.stdout.write('\n重启 agent 后即可生效。升级后重跑 remixmate install 覆盖即可。\n');
381
- return EXIT.OK;
382
- }
383
- export function runUninstall(argv) {
384
- const opts = parseArgs(argv, UNINSTALL_VERB);
385
- if (opts.help) {
386
- uninstallUsage();
387
- return EXIT.OK;
388
- }
389
- if (opts.error) {
390
- process.stderr.write(`❌ ${opts.error}\n`);
391
- uninstallUsage();
392
- return EXIT.USAGE;
393
- }
394
- let removed = 0;
395
- for (const host of opts.hosts) {
396
- const receipt = readReceipt(host.skillsDir);
397
- if (!receipt)
398
- continue;
399
- for (const name of receipt.skills) {
400
- rmSync(path.join(host.skillsDir, name), { recursive: true, force: true });
401
- }
402
- rmSync(path.join(host.skillsDir, RECEIPT), { force: true });
403
- removed += 1;
404
- process.stdout.write(`✅ ${padDisplay(host.label, 16)}已移除 ${receipt.skills.length} 个 skill(${host.skillsDir})\n`);
405
- }
406
- if (removed === 0) {
407
- process.stdout.write('没有找到本 CLI 的装机记录,无需卸载。\n');
408
- }
409
- return EXIT.OK;
410
- }
411
- /**
412
- * 供 doctor 使用:每个宿主的安装状态。
413
- *
414
- * 漂移是这套方案唯一的静默失败模式 —— `npm update -g` 只动包,不动铺出去的副本,
415
- * 用户会拿着旧 SKILL.md 打新后端。doctor 是「为什么跑不起来」的统一入口,检查放这里。
416
- */
417
- export function installStates() {
418
- const current = packageVersion();
419
- return detectHosts().map((h) => {
420
- const receipt = readReceipt(h.skillsDir);
421
- return {
422
- label: h.label,
423
- skillsDir: h.skillsDir,
424
- installedVersion: receipt?.version ?? null,
425
- currentVersion: current,
426
- drifted: receipt != null && receipt.version !== current,
427
- };
428
- });
429
- }
430
- /**
431
- * 首次使用提示:检测到了宿主、但还没跑过 `remixmate install`(或装的是旧版)时返回一行提示,
432
- * 否则 null。
433
- *
434
- * 不用 postinstall 做这件事:npm 7+ 默认吞掉生命周期脚本的输出,而在安装期往用户家目录
435
- * 写文件太侵入。改为在用户/agent 一定会看到的地方(--list、--help 页脚、template init 的
436
- * 下一步、doctor)提示。纯本地读文件,不发网络请求。
437
- */
438
- export function skillInstallHint(states = installStates()) {
439
- const missing = states.filter((s) => s.installedVersion == null).map((s) => s.label);
440
- const drifted = states.filter((s) => s.drifted).map((s) => s.label);
441
- if (missing.length > 0) {
442
- return `💡 检测到 ${missing.join('、')},但还没装 skill → 运行 remixmate install,重启 agent 后它才能自动发现 RemixMate 的能力`;
443
- }
444
- if (drifted.length > 0) {
445
- return `💡 ${drifted.join('、')} 里的 skill 是旧版本 → 运行 remixmate install 覆盖`;
446
- }
447
- return null;
448
- }
1
+ var K=Object.defineProperty;var s=(e,r)=>K(e,"name",{value:r,configurable:!0});import{cpSync as G,existsSync as D,mkdirSync as H,readdirSync as V,readFileSync as O,rmSync as b,writeFileSync as B}from"node:fs";import v from"node:os";import c from"node:path";import{fileURLToPath as F}from"node:url";import{SKILLS_DIR as k}from"./registry.js";import{EXIT as d}from"./errors.js";import{padDisplay as j}from"./text.js";const P="install",E="uninstall",J=c.dirname(F(import.meta.url)),M=c.resolve(J,".."),S=".remixmate-install.json",W="@remixmate/cli",w=[{id:"claude",label:"Claude Code",detectDirNames:[".claude"],homeEnv:"CLAUDE_CONFIG_DIR",userDirName:".claude",projectDirName:".claude"},{id:"codex",label:"Codex",detectDirNames:[".codex"],homeEnv:"CODEX_HOME",userDirName:".codex"},{id:"workbuddy",label:"WorkBuddy",detectDirNames:[".workbuddy"],userDirName:".workbuddy",projectDirName:".workbuddy"},{id:"codebuddy",label:"CodeBuddy",detectDirNames:[".codebuddy"],userDirName:".codebuddy",projectDirName:".codebuddy"},{id:"trae",label:"Trae / TraeWork",detectDirNames:[".trae-cn",".trae"],projectDirName:".trae"}],m=w.map(e=>e.id);function u(e){return w.find(r=>r.id===e)}s(u,"spec");function X(e){const r=u(e);if(!r.userDirName)return null;const t=r.homeEnv?process.env[r.homeEnv]:void 0;return c.join(t||c.join(v.homedir(),r.userDirName),"skills")}s(X,"userSkillsDir");function I(e){const r=u(e),t=r.homeEnv?process.env[r.homeEnv]:void 0;return t?[t]:r.detectDirNames.map(n=>c.join(v.homedir(),n))}s(I,"detectDirs");function x(e){return I(e).some(r=>D(r))}s(x,"isInstalled");function N(e){const r=X(e);return r?{id:e,label:u(e).label,skillsDir:r}:null}s(N,"hostOf");function q(e){const r=u(e);return r.projectDirName?{id:e,label:`${r.label}(项目级)`,skillsDir:c.join(process.cwd(),r.projectDirName,"skills")}:null}s(q,"projectHostOf");function R(){return m.filter(x).map(N).filter(e=>e!==null)}s(R,"detectHosts");function z(){return m.filter(e=>x(e)&&!u(e).userDirName)}s(z,"projectOnlyHosts");function C(){try{const e=O(c.join(M,"package.json"),"utf-8");return JSON.parse(e).version??"unknown"}catch{return"unknown"}}s(C,"packageVersion");function Q(){return D(k)?V(k,{withFileTypes:!0}).filter(e=>e.isDirectory()&&D(c.join(k,e.name,"SKILL.md"))).map(e=>e.name).sort():[]}s(Q,"bundledSkills");function g(e){const r=c.join(e,S);if(!D(r))return null;try{return JSON.parse(O(r,"utf-8"))}catch{return null}}s(g,"readReceipt");const $=s(e=>e!==null,"nonNull");function L(e,r){const t={hosts:[],force:!1,help:!1},n=[];let f=!1,p="",o=!1;for(let a=0;a<e.length;a++){const i=e[a],l=i.indexOf("="),T=l>0?i.slice(0,l):i,_=l>0?i.slice(l+1):null,y=s(()=>_??e[++a]??"","next");switch(T){case"--host":{const h=y();if(h==="all")f=!0;else if(m.includes(h))n.push(h);else return t.error=`未知参数: --host ${h}`,t;break}case"--dir":p=y();break;case"--project":o=!0;break;case"--force":t.force=!0;break;case"-h":case"--help":return t.help=!0,t;default:return t.error=`未知参数: ${i}`,t}}if(p)return t.hosts=[{id:"custom",label:"自定义目录",skillsDir:c.resolve(p)}],t;if(o){const a=f?m.filter(l=>u(l).projectDirName):n.length>0?[...new Set(n)]:m.filter(l=>x(l)&&u(l).projectDirName),i=a.filter(l=>!u(l).projectDirName);return i.length>0?(t.error=`${i.map(l=>u(l).label).join("、")} 没有项目级 skill 目录,不能和 --project 一起用`,t):(t.hosts=a.map(q).filter($),t)}if(f)return t.hosts=m.map(N).filter($),t;if(n.length>0){const a=[...new Set(n)],i=a.filter(l=>!u(l).userDirName);if(i.length>0)return t.error=`${i.map(l=>u(l).label).join("、")} 只有项目级 skill 目录 —— 进到项目根目录后加 --project 重跑。`,t;t.hosts=a.map(N).filter($)}else t.hosts=r===E?m.map(N).filter($):R();return t}s(L,"parseArgs");function A(){process.stdout.write(`Usage: remixmate install [options]
2
+
3
+ 把本包自带的 skill 装进已检测到的 agent 宿主,让它们能自动发现这些能力。
4
+ 重复运行即升级。支持的宿主:
5
+ `+w.map(e=>` ${j(e.label,14)}${e.userDirName?`~/${e.userDirName}/skills`:"(仅项目级)"}${e.projectDirName?` 项目级 ./${e.projectDirName}/skills`:""}
6
+ `).join("")+`
7
+ Options:
8
+ --host <${m.join("|")}|all>
9
+ 只装指定宿主(默认:装到所有检测到的宿主)
10
+ --project 装到当前目录 ./<配置目录>/skills(Codex 不支持)
11
+ --dir <path> 自定义 skills 父目录(覆盖上面两者)
12
+ --force 覆盖同名的、非本 CLI 安装的 skill 目录
13
+ `)}s(A,"installUsage");function U(){process.stdout.write(`Usage: remixmate uninstall [options]
14
+
15
+ 按装机回执删除本 CLI 装过的 skill —— 只删回执里列出的目录,不碰其它 skill。
16
+
17
+ Options:
18
+ --host <${m.join("|")}|all>
19
+ 只卸载指定宿主(默认:所有宿主都查)
20
+ --project 卸载当前目录 ./.claude/skills 下的安装
21
+ --dir <path> 自定义 skills 父目录
22
+ `)}s(U,"uninstallUsage");function Y(e,r,t,n){const f=g(e.skillsDir),p=new Set(f?.skills??[]),o=r.filter(i=>D(c.join(e.skillsDir,i))&&!p.has(i));if(o.length>0&&!n)return`${e.skillsDir} 下已存在同名目录,且不是本 CLI 装的:${o.join("、")}
23
+ 确认可以覆盖后加 --force 重跑。`;H(e.skillsDir,{recursive:!0});for(const i of p)r.includes(i)||b(c.join(e.skillsDir,i),{recursive:!0,force:!0});for(const i of r){const l=c.join(e.skillsDir,i);b(l,{recursive:!0,force:!0}),G(c.join(k,i),l,{recursive:!0})}const a={package:W,version:t,installedAt:new Date().toISOString(),source:k,skills:r};return B(c.join(e.skillsDir,S),JSON.stringify(a,null,2)+`
24
+ `,"utf-8"),null}s(Y,"installInto");function ce(e){const r=L(e,P);if(r.help)return A(),d.OK;if(r.error)return process.stderr.write(`❌ ${r.error}
25
+ `),A(),d.USAGE;const t=Q();if(t.length===0)return process.stderr.write(`❌ 包内没有可安装的 skill(${k})
26
+ `),d.ERROR;const n=z();if(r.hosts.length===0)return n.length>0?(process.stderr.write(`❌ 只检测到 ${n.map(o=>u(o).label).join("、")},它只有项目级 skill 目录。
27
+ 进到项目根目录后运行:remixmate install --project
28
+ `),d.USAGE):(process.stderr.write(`❌ 没有检测到任何 agent 宿主。找过这些位置:
29
+ `+m.map(o=>` ${j(u(o).label,14)}${I(o).join("、")}
30
+ `).join("")+` 先把 agent 装好再重跑,或用 --dir <path> 指定目录。
31
+ `),d.USAGE);const f=C();let p=0;for(const o of r.hosts){const a=Y(o,t,f,r.force);if(a){p+=1,process.stderr.write(`❌ ${j(o.label,16)}${a}
32
+ `);continue}process.stdout.write(`✅ ${j(o.label,16)}${o.skillsDir}(${t.length} 个 skill,${f})
33
+ `)}return p>0?d.ERROR:(n.length>0&&!r.hosts.some(o=>n.includes(o.id))&&process.stdout.write(`
34
+ ℹ️ 还检测到 ${n.map(o=>u(o).label).join("、")},它只有项目级 skill 目录 —— 在项目根目录里运行 remixmate install --project 即可。
35
+ `),process.stdout.write(`
36
+ 重启 agent 后即可生效。升级后重跑 remixmate install 覆盖即可。
37
+ `),d.OK)}s(ce,"runInstall");function ae(e){const r=L(e,E);if(r.help)return U(),d.OK;if(r.error)return process.stderr.write(`❌ ${r.error}
38
+ `),U(),d.USAGE;let t=0;for(const n of r.hosts){const f=g(n.skillsDir);if(f){for(const p of f.skills)b(c.join(n.skillsDir,p),{recursive:!0,force:!0});b(c.join(n.skillsDir,S),{force:!0}),t+=1,process.stdout.write(`✅ ${j(n.label,16)}已移除 ${f.skills.length} 个 skill(${n.skillsDir})
39
+ `)}}return t===0&&process.stdout.write(`没有找到本 CLI 的装机记录,无需卸载。
40
+ `),d.OK}s(ae,"runUninstall");function Z(){const e=C();return R().map(r=>{const t=g(r.skillsDir);return{label:r.label,skillsDir:r.skillsDir,installedVersion:t?.version??null,currentVersion:e,drifted:t!=null&&t.version!==e}})}s(Z,"installStates");function ue(e=Z()){const r=e.filter(n=>n.installedVersion==null).map(n=>n.label),t=e.filter(n=>n.drifted).map(n=>n.label);return r.length>0?`💡 检测到 ${r.join("、")},但还没装 skill → 运行 remixmate install,重启 agent 后它才能自动发现 RemixMate 的能力`:t.length>0?`💡 ${t.join("、")} 里的 skill 是旧版本 → 运行 remixmate install 覆盖`:null}s(ue,"skillInstallHint");export{P as INSTALL_VERB,E as UNINSTALL_VERB,R as detectHosts,Z as installStates,A as installUsage,C as packageVersion,z as projectOnlyHosts,ce as runInstall,ae as runUninstall,ue as skillInstallHint,U as uninstallUsage};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.9.72",
4
- "generatedAt": "2026-10-08T04:30:08.225Z",
3
+ "version": "0.9.73",
4
+ "generatedAt": "2026-10-08T10:57:35.046Z",
5
5
  "skills": [
6
6
  {
7
7
  "id": "doc-parse",
@@ -594,6 +594,22 @@
594
594
  "type": "string",
595
595
  "description": "Template id (from template_registry). The template owns outputLanguage and may also declare a defaultVoiceId; both flow into the produced DSL."
596
596
  },
597
+ "template_source": {
598
+ "type": "string",
599
+ "enum": [
600
+ "user-explicit",
601
+ "user-confirmed",
602
+ "auto"
603
+ ],
604
+ "description": "How template_id was chosen; recorded at meta.templateSelection.source. **Always pass it with template_id.** `user-explicit`: the user named this template — its id or name, a pasted template detail-page prompt or link, or it was settled earlier in this conversation. `user-confirmed`: the user did not name one, you offered candidates and the user picked or approved this one in the chat. `auto`: you picked it yourself and the user has not confirmed — gen_script refuses, so instead of calling it, show the candidates and end the turn. Never mark a template user-confirmed that the user has not seen and approved."
605
+ },
606
+ "template_candidates": {
607
+ "type": "array",
608
+ "items": {
609
+ "type": "string"
610
+ },
611
+ "description": "The template ids you offered the user, recommended first; recorded at meta.templateSelection.candidates. Pass with template_source=user-confirmed — template_id must then be one of them (a template the user named outside the shortlist is user-explicit)."
612
+ },
597
613
  "source_document_url": {
598
614
  "type": "string",
599
615
  "description": "Source document URL (.pptx) for a template that builds its per-scene picture from that document (capabilities.payloadHydration). **Must** pass it for such a template: it is recorded at meta.sourceDocument, and prepare_video_assets then fetches the layout itself and fills the customPayload field the template declares (payloadHydration.payloadField) on every scene. Pass the same URL you gave doc_parse. You are NOT expected to author or even read that layout data — one page is hundreds of KB, so it never travels through the conversation; without this reference the DSL is rejected downstream after you have already written all the narration."
@@ -666,6 +682,8 @@
666
682
  "variant",
667
683
  "background_preset",
668
684
  "template_id",
685
+ "template_source",
686
+ "template_candidates",
669
687
  "source_document_url",
670
688
  "headline",
671
689
  "subheadline",
@@ -1157,13 +1175,33 @@
1157
1175
  "type": "string",
1158
1176
  "description": "Show only templates whose contentLanguage includes this code ('zh' or 'en'). Templates with no declared language are always shown (treated as language-agnostic)."
1159
1177
  },
1178
+ "user_media": {
1179
+ "type": "string",
1180
+ "enum": [
1181
+ "yes",
1182
+ "no"
1183
+ ],
1184
+ "description": "Shortlisting when the user named no template. 'yes' = the user handed over their own images/videos: drops templates with nowhere to put them. 'no' = they did not: drops templates that cannot run without them. Leave unset when it does not matter."
1185
+ },
1186
+ "source_doc": {
1187
+ "type": "string",
1188
+ "description": "Shortlisting: the user gave a source document of this kind (e.g. 'pptx') — keeps only templates that build their scenes from one. 'none' drops those templates. Leave unset otherwise."
1189
+ },
1190
+ "narration": {
1191
+ "type": "string",
1192
+ "enum": [
1193
+ "yes",
1194
+ "no"
1195
+ ],
1196
+ "description": "Shortlisting: 'yes' = the video needs voice-over (drops narration-free templates); 'no' = the user wants none (keeps only narration-free templates). Leave unset unless the user said so."
1197
+ },
1160
1198
  "include_beta": {
1161
1199
  "type": "boolean",
1162
1200
  "description": "Also list templates with status='beta'. Default off (only 'stable' shows). The ENABLE_BETA_TEMPLATES env var has the same effect process-wide."
1163
1201
  },
1164
1202
  "json_output": {
1165
1203
  "type": "boolean",
1166
- "description": "Emit a JSON result instead of the human-readable table: { templates: [...] } — summaries, or full definitions when template_id / full is set — or { examples: [...] }. List summaries carry pageUrl (the template's web detail page — show it to the user as a link) and, when the backend serves samples, showcases { count, pageUrl, items }; the template_id view carries top-level pageUrls / showcases maps."
1204
+ "description": "Emit a JSON result instead of the human-readable table: { templates: [...] } — summaries (each with notFor when the template declares which requests it is the wrong pick for), or full definitions when template_id / full is set — or { examples: [...] }. List summaries carry pageUrl (the template's web detail page — show it to the user as a link) and, when the backend serves samples, showcases { count, pageUrl, items }; the template_id view carries top-level pageUrls / showcases maps."
1167
1205
  },
1168
1206
  "open": {
1169
1207
  "type": "string",
@@ -1182,6 +1220,9 @@
1182
1220
  "filter_tag",
1183
1221
  "filter_aspect",
1184
1222
  "filter_language",
1223
+ "user_media",
1224
+ "source_doc",
1225
+ "narration",
1185
1226
  "include_beta",
1186
1227
  "json_output",
1187
1228
  "open"
package/dist/progress.js CHANGED
@@ -1,15 +1,2 @@
1
- /**
2
- * Progress reporting — emits __progress__ JSON lines that ab-agent's
3
- * executor parses (see apps/ab-agent/src/skills/executor.ts).
4
- *
5
- * Always writes to stdout because the consumer reads stdout line-by-line.
6
- * Each event is a single JSON object on its own line, with the marker
7
- * field `__progress__: true` so non-progress stdout content is ignored.
8
- *
9
- * The consumer flattens the entire parsed JSON into `extra`, so any
10
- * additional context (model id, generationId, ...) can be passed as
11
- * top-level keys and will reach the SSE client unchanged.
12
- */
13
- export function emitProgress(ev) {
14
- process.stdout.write(JSON.stringify({ __progress__: true, ...ev }) + '\n');
15
- }
1
+ var e=Object.defineProperty;var s=(r,t)=>e(r,"name",{value:t,configurable:!0});function i(r){process.stdout.write(JSON.stringify({__progress__:!0,...r})+`
2
+ `)}s(i,"emitProgress");export{i as emitProgress};