infographic-gen 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ <img src="https://gw.alipayobjects.com/zos/antfincdn/R8sN%24GNdh6/language.svg" width="18"> [简体中文](./README.zh-CN.md) | English
2
+
1
3
  # infographic-gen
2
4
 
3
5
  AI-powered CLI tool to generate [AntV Infographic](https://infographic.antv.vision/) SVGs from natural language prompts.
@@ -12,6 +14,8 @@ Transform your ideas into beautiful, data-driven infographics in seconds using t
12
14
  - **AI-Powered Generation** — Uses OpenAI, DeepSeek, or other LLM providers via OpenAI SDK
13
15
  - **Professional Templates** — 60+ pre-designed AntV Infographic templates (lists, sequences, hierarchies, comparisons, charts, relations, etc.)
14
16
  - **Self-Correcting** — Automatically retries with error feedback if generation fails (up to 3 attempts)
17
+ - **DSL Export** — Optional `--dsl` flag to save raw syntax for debugging and fine-tuning
18
+ - **Error Auto-Dump** — Automatically saves problematic DSL to `error-dump.txt` when rendering fails
15
19
  - **Persistent Config** — Save API keys and settings locally for repeat use
16
20
  - **Automated Sync** — Weekly checks for upstream Infographic updates via GitHub Actions
17
21
  - **Fully Tested** — 131 comprehensive tests covering all features
@@ -47,12 +51,25 @@ npm start # Run built CLI
47
51
 
48
52
  ## 🚀 Quick Start
49
53
 
54
+ ### Command Aliases
55
+
56
+ For convenience, the CLI supports multiple shortcuts:
57
+
58
+ ```bash
59
+ infographic-gen # Full command
60
+ info-gen # Short alias
61
+ ig-gen # Shortest alias (recommended)
62
+ ```
63
+
64
+ All examples below use `ig-gen` (can be replaced with any alias above).
65
+
50
66
  ### 1. Configure Your LLM Provider
51
67
 
52
68
  ```bash
53
- infographic-gen config set apiKey sk-xxxx123
54
- infographic-gen config set baseUrl https://api.openai.com/v1 # Optional
55
- infographic-gen config set modelName gpt-4o # Optional
69
+ ig-gen config set apiKey sk-xxxx123
70
+ ig-gen config set baseUrl https://api.openai.com/v1 # Optional
71
+ ig-gen config set modelName gpt-4o # Optional
72
+ ig-gen config set defaultOutputDir ~/my-infographics # Optional: default output directory
56
73
  ```
57
74
 
58
75
  **Supported Providers:**
@@ -65,30 +82,53 @@ infographic-gen config set modelName gpt-4o # Optional
65
82
  View your config:
66
83
 
67
84
  ```bash
68
- infographic-gen config list
69
- infographic-gen config path # Show config file location
85
+ ig-gen config list
86
+ ig-gen config path # Show config file location
70
87
  ```
71
88
 
72
89
  ### 2. Generate an Infographic
73
90
 
74
91
  ```bash
75
- infographic-gen generate "A comparison of frontend frameworks"
92
+ # generate is the default command, so these are equivalent:
93
+ ig-gen "A comparison of frontend frameworks"
94
+ ig-gen generate "A comparison of frontend frameworks"
95
+ ig-gen g "A comparison of frontend frameworks" # Using 'g' alias
76
96
  ```
77
97
 
78
- Output: `infographic-output.svg` (in current directory)
98
+ Output: `infographic-output.svg` (in default output directory or current directory)
79
99
 
80
100
  Specify output path:
81
101
 
82
102
  ```bash
83
- infographic-gen gen "Data visualization trends" --output my-chart.svg
103
+ ig-gen "Data visualization trends" --output my-chart.svg
104
+ ```
105
+
106
+ ### 3. Save DSL Syntax (Optional)
107
+
108
+ The `--dsl` option allows you to save the raw DSL syntax generated by the AI to a text file. This is useful for:
109
+
110
+ - **Debugging** — Inspect what the LLM generated if rendering fails
111
+ - **Fine-tuning** — Manually edit the DSL to adjust the infographic
112
+ - **Learning** — Understand the DSL syntax for future manual creation
113
+
114
+ ```bash
115
+ # Generate SVG and save DSL syntax
116
+ ig-gen "Compare React vs Vue" -o frameworks.svg --dsl frameworks.txt
117
+
118
+ # The command will create:
119
+ # - frameworks.svg (rendered infographic)
120
+ # - frameworks.txt (raw DSL syntax)
84
121
  ```
85
122
 
86
- ### 3. Get Help
123
+ **Error Auto-Dump:**
124
+ If rendering fails after 3 self-correction attempts, the problematic DSL is automatically saved to `error-dump.txt` for debugging.
125
+
126
+ ### 4. Get Help
87
127
 
88
128
  ```bash
89
- infographic-gen --help
90
- infographic-gen config --help
91
- infographic-gen generate --help
129
+ ig-gen --help
130
+ ig-gen config --help
131
+ ig-gen --version
92
132
  ```
93
133
 
94
134
  ---
@@ -98,7 +138,7 @@ infographic-gen generate --help
98
138
  ### Example 1: Technology Timeline
99
139
 
100
140
  ```bash
101
- infographic-gen gen "A timeline showing the evolution of web technologies from HTTP/1.0 to HTTP/3"
141
+ ig-gen "A timeline showing the evolution of web technologies from HTTP/1.0 to HTTP/3"
102
142
  ```
103
143
 
104
144
  Will generate a timeline with key milestones, automatically selecting an appropriate template.
@@ -106,7 +146,7 @@ Will generate a timeline with key milestones, automatically selecting an appropr
106
146
  ### Example 2: Comparison Matrix
107
147
 
108
148
  ```bash
109
- infographic-gen gen "Compare the pros and cons of monolithic vs microservices architecture"
149
+ ig-gen "Compare the pros and cons of monolithic vs microservices architecture"
110
150
  ```
111
151
 
112
152
  Generates a comparison infographic with Strengths and Weaknesses categories.
@@ -114,11 +154,24 @@ Generates a comparison infographic with Strengths and Weaknesses categories.
114
154
  ### Example 3: Data Chart
115
155
 
116
156
  ```bash
117
- infographic-gen gen "Show the distribution of programming languages by usage: Python 35%, JavaScript 28%, Java 20%, C++ 12%, Other 5%"
157
+ ig-gen "Show the distribution of programming languages by usage: Python 35%, JavaScript 28%, Java 20%, C++ 12%, Other 5%"
118
158
  ```
119
159
 
120
160
  Creates a pie/bar chart with the provided data.
121
161
 
162
+ ### Example 4: Debug with DSL Export
163
+
164
+ ```bash
165
+ ig-gen "Compare React, Vue, and Angular pros and cons" -o frameworks.svg --dsl frameworks-dsl.txt
166
+ ```
167
+
168
+ This will generate:
169
+
170
+ - `frameworks.svg` — The rendered infographic
171
+ - `frameworks-dsl.txt` — The raw DSL syntax
172
+
173
+ You can then inspect or manually edit the DSL file to fine-tune the output. If rendering fails, check `error-dump.txt` for the problematic syntax.
174
+
122
175
  ---
123
176
 
124
177
  ## 🛠️ Development
@@ -189,31 +242,34 @@ Config is stored in:
189
242
 
190
243
  ### Configurable Keys
191
244
 
192
- | Key | Type | Example | Notes |
193
- | ----------- | ------ | --------------------------- | ------------------------------------------- |
194
- | `apiKey` | string | `sk-...` | Your LLM API key |
195
- | `baseUrl` | string | `https://api.openai.com/v1` | LLM endpoint (optional) |
196
- | `modelName` | string | `gpt-4o` | Model to use (optional, defaults to gpt-4o) |
197
- | `provider` | string | `openai` | For reference only |
245
+ | Key | Type | Example | Notes |
246
+ | ------------------ | ------ | --------------------------- | ---------------------------------------------------- |
247
+ | `apiKey` | string | `sk-...` | Your LLM API key |
248
+ | `baseUrl` | string | `https://api.openai.com/v1` | LLM endpoint (optional) |
249
+ | `modelName` | string | `gpt-4o` | Model to use (optional, defaults to gpt-4o) |
250
+ | `defaultOutputDir` | string | `~/infographics` or `.` | Default output directory (optional, defaults to `.`) |
198
251
 
199
252
  Manage config via CLI:
200
253
 
201
254
  ```bash
202
255
  # Set
203
- infographic-gen config set apiKey sk-...
204
- infographic-gen config set baseUrl https://api.deepseek.com
256
+ ig-gen config set apiKey sk-...
257
+ ig-gen config set baseUrl https://api.deepseek.com
258
+ ig-gen config set defaultOutputDir ~/my-infographics
205
259
 
206
260
  # Get
207
- infographic-gen config get apiKey
261
+ ig-gen config get apiKey
262
+ ig-gen c get defaultOutputDir # Using 'c' alias
208
263
 
209
264
  # List all
210
- infographic-gen config list
265
+ ig-gen config list
266
+ ig-gen c list # Using 'c' alias
211
267
 
212
268
  # Delete
213
- infographic-gen config delete baseUrl
269
+ ig-gen config delete baseUrl
214
270
 
215
271
  # Show config file path
216
- infographic-gen config path
272
+ ig-gen config path
217
273
  ```
218
274
 
219
275
  ---
package/README.zh-CN.md CHANGED
@@ -12,6 +12,9 @@
12
12
  - **AI 驱动生成** — 支持 OpenAI、DeepSeek 或其他兼容 OpenAI SDK 的 LLM 服务
13
13
  - **专业模板库** — 60+ 预设设计的 AntV Infographic 模板(列表、流程、层级、对比、图表、关系等)
14
14
  - **自动纠错** — 生成失败时自动重试并反馈错误信息(最多 3 次尝试)
15
+ - **DSL 导出** — 可选的 `--dsl` 参数保存原始语法,用于调试和微调
16
+ - **错误自动转储** — 渲染失败时自动保存有问题的 DSL 到 `error-dump.txt`
17
+ - **多语言支持** — CLI 输出支持英文/中文切换(默认英文)
15
18
  - **本地配置存储** — API Key 和设置永久保存,无需重复输入
16
19
  - **上游自动同步** — 每周自动检测 @antv/infographic 更新,通过 GitHub Actions 创建 PR
17
20
  - **全面的测试覆盖** — 131 个综合测试,覆盖所有功能
@@ -47,44 +50,100 @@ npm start # 运行构建后的 CLI
47
50
 
48
51
  ## 🚀 快速开始
49
52
 
50
- ### 1. 配置 LLM 服务
53
+ ### 命令别名
54
+
55
+ 为了方便使用,CLI 提供了多个快捷别名:
56
+
57
+ ```bash
58
+ infographic-gen # 完整命令
59
+ info-gen # 短别名
60
+ ig-gen # 最短别名(推荐)
61
+ ```
62
+
63
+ 下面的所有示例均使用 `ig-gen`(可替换为任何上述别名)。
64
+
65
+ ### 1. 配置 LLM 服务和语言
51
66
 
52
67
  ```bash
53
- infographic-gen config set apiKey sk-xxxx123
54
- infographic-gen config set baseUrl https://api.openai.com/v1 # 可选
55
- infographic-gen config set modelName gpt-4o # 可选
68
+ ig-gen config set apiKey sk-xxxx123
69
+ ig-gen config set baseUrl https://api.openai.com/v1 # 可选
70
+ ig-gen config set modelName gpt-4o # 可选
71
+ ig-gen config set defaultOutputDir ~/my-infographics # 可选
72
+ ig-gen config set locale zh-CN # 可选:切换界面语言为中文
56
73
  ```
57
74
 
58
75
  **支持的服务提供商:**
76
+
59
77
  - **OpenAI** ← 默认
60
78
  - **DeepSeek** — 设置 `baseUrl` 为 `https://api.deepseek.com`
61
79
  - **阿里云 DashScope** — 设置对应的端点
62
80
  - 任何兼容 OpenAI API 的服务
63
81
 
64
82
  查看配置:
83
+
65
84
  ```bash
66
- infographic-gen config list
67
- infographic-gen config path # 显示配置文件位置
85
+ ig-gen config list
86
+ ig-gen config path # 显示配置文件位置
68
87
  ```
69
88
 
70
89
  ### 2. 生成信息图
71
90
 
72
91
  ```bash
73
- infographic-gen generate "对比前端框架的优缺点"
92
+ # generate 是默认命令,所以这些都是等效的:
93
+ ig-gen "对比前端框架的优缺点"
94
+ ig-gen generate "对比前端框架的优缺点"
95
+ ig-gen g "对比前端框架的优缺点" # 使用 g 别名
74
96
  ```
75
97
 
76
- 输出:`infographic-output.svg`(当前目录)
98
+ 输出:`infographic-output.svg`(在默认输出目录或当前目录)
77
99
 
78
100
  指定输出路径:
101
+
79
102
  ```bash
80
- infographic-gen gen "数据可视化趋势分析" --output my-chart.svg
103
+ ig-gen "数据可视化趋势分析" --output my-chart.svg
81
104
  ```
82
105
 
83
- ### 3. 获取帮助
106
+ ### 3. 保存 DSL 语法(可选)
107
+
108
+ `--dsl` 选项允许你将 AI 生成的原始 DSL 语法保存到文本文件。适用于:
109
+
110
+ - **调试** — 检查 LLM 生成的内容,排查渲染失败原因
111
+ - **微调** — 手动编辑 DSL 以调整信息图细节
112
+ - **学习** — 了解 DSL 语法,为未来手动创建做准备
84
113
 
85
114
  ```bash
86
- infographic-gen --help
87
- infographic-gen config --help
115
+ # 同时生成 SVG 和保存 DSL 语法
116
+ ig-gen "对比 React 和 Vue" -o frameworks.svg --dsl frameworks.txt
117
+
118
+ # 该命令会创建:
119
+ # - frameworks.svg (渲染后的信息图)
120
+ # - frameworks.txt (原始 DSL 语法)
121
+ ```
122
+
123
+ **错误自动保存:**
124
+ 如果经过 3 次自我修正后渲染仍然失败,有问题的 DSL 会自动保存到 `error-dump.txt` 以便调试。
125
+
126
+ ### 4. 切换界面语言
127
+
128
+ 默认情况下,CLI 输出为英文。如需切换为中文:
129
+
130
+ ```bash
131
+ # 切换为中文
132
+ ig-gen config set locale zh-CN
133
+
134
+ # 切换回英文
135
+ ig-gen config set locale en
136
+
137
+ # 查看当前语言设置
138
+ ig-gen config get locale
139
+ ```
140
+
141
+ ### 5. 获取帮助
142
+
143
+ ```bash
144
+ ig-gen --help
145
+ ig-gen config --help
146
+ ig-gen --version
88
147
  infographic-gen generate --help
89
148
  infographic-gen gen -h # gen 是 generate 的别名
90
149
  ```
@@ -96,7 +155,7 @@ infographic-gen gen -h # gen 是 generate 的别名
96
155
  ### 示例 1:技术演进时间线
97
156
 
98
157
  ```bash
99
- infographic-gen gen "展示 Web 技术演进:从 HTTP/1.0 到 HTTP/3"
158
+ ig-gen "展示 Web 技术演进:从 HTTP/1.0 到 HTTP/3"
100
159
  ```
101
160
 
102
161
  自动生成时间线,展示关键里程碑。
@@ -104,7 +163,7 @@ infographic-gen gen "展示 Web 技术演进:从 HTTP/1.0 到 HTTP/3"
104
163
  ### 示例 2:对比矩阵
105
164
 
106
165
  ```bash
107
- infographic-gen gen "对比单体架构和微服务架构的优缺点"
166
+ ig-gen "对比单体架构和微服务架构的优缺点"
108
167
  ```
109
168
 
110
169
  生成包含优势和劣势的对比信息图。
@@ -112,11 +171,24 @@ infographic-gen gen "对比单体架构和微服务架构的优缺点"
112
171
  ### 示例 3:数据图表
113
172
 
114
173
  ```bash
115
- infographic-gen gen "编程语言使用分布:Python 35%、JavaScript 28%、Java 20%、C++ 12%、其他 5%"
174
+ ig-gen "编程语言使用分布:Python 35%、JavaScript 28%、Java 20%、C++ 12%、其他 5%"
116
175
  ```
117
176
 
118
177
  自动创建饼图或柱状图。
119
178
 
179
+ ### 示例 4:导出 DSL 用于调试
180
+
181
+ ```bash
182
+ ig-gen "对比 React、Vue 和 Angular 的优缺点" -o frameworks.svg --dsl frameworks-dsl.txt
183
+ ```
184
+
185
+ 该命令会生成:
186
+
187
+ - `frameworks.svg` — 渲染后的信息图
188
+ - `frameworks-dsl.txt` — 原始 DSL 语法
189
+
190
+ 你可以检查或手动编辑 DSL 文件来微调输出结果。如果渲染失败,可以检查 `error-dump.txt` 中的问题语法。
191
+
120
192
  ---
121
193
 
122
194
  ## 🛠️ 开发
@@ -131,15 +203,15 @@ npm install
131
203
 
132
204
  ### 常用命令
133
205
 
134
- | 命令 | 说明 |
135
- |------|------|
136
- | `npm run build` | 构建 CLI 到 `dist/index.js` |
137
- | `npm run dev` | Watch 模式(文件变化自动重建) |
138
- | `npm start` | 运行已构建的 CLI |
139
- | `npm test` | 运行全部测试 (vitest) |
140
- | `npm run test:watch` | Watch 模式测试 |
141
- | `npm run sync` | 检查并更新上游 @antv/infographic |
142
- | `npm run sync:check` | 仅检测,不更新(干运行) |
206
+ | 命令 | 说明 |
207
+ | -------------------- | -------------------------------- |
208
+ | `npm run build` | 构建 CLI 到 `dist/index.js` |
209
+ | `npm run dev` | Watch 模式(文件变化自动重建) |
210
+ | `npm start` | 运行已构建的 CLI |
211
+ | `npm test` | 运行全部测试 (vitest) |
212
+ | `npm run test:watch` | Watch 模式测试 |
213
+ | `npm run sync` | 检查并更新上游 @antv/infographic |
214
+ | `npm run sync:check` | 仅检测,不更新(干运行) |
143
215
 
144
216
  ### 项目结构
145
217
 
@@ -177,36 +249,43 @@ infographic-gen/
177
249
  ## 📋 配置管理
178
250
 
179
251
  配置文件存储位置:
252
+
180
253
  - **macOS/Linux** — `~/.config/infographic-gen/config.json`
181
254
  - **Windows** — `%APPDATA%\infographic-gen\config.json`
182
255
 
183
256
  ### 可配置的字段
184
257
 
185
- | 字段 | 类型 | 示例 | 说明 |
186
- |------|------|------|------|
187
- | `apiKey` | string | `sk-...` | LLM API 密钥 |
188
- | `baseUrl` | string | `https://api.openai.com/v1` | LLM 服务端点(可选) |
189
- | `modelName` | string | `gpt-4o` | 使用的模型(可选,默认 gpt-4o) |
190
- | `provider` | string | `openai` | 服务提供商标识 |
258
+ | 字段 | 类型 | 示例 | 说明 |
259
+ | ------------------ | ------ | --------------------------- | ---------------------------------- |
260
+ | `apiKey` | string | `sk-...` | LLM API 密钥 |
261
+ | `baseUrl` | string | `https://api.openai.com/v1` | LLM 服务端点(可选) |
262
+ | `modelName` | string | `gpt-4o` | 使用的模型(可选,默认 gpt-4o) |
263
+ | `defaultOutputDir` | string | `~/infographics` 或 `.` | 默认输出目录(可选,默认当前目录) |
264
+ | `locale` | string | `en` 或 `zh-CN` | CLI 界面语言(可选,默认 `en`) |
191
265
 
192
266
  ### 通过 CLI 管理配置
193
267
 
194
268
  ```bash
195
269
  # 设置
196
- infographic-gen config set apiKey sk-...
197
- infographic-gen config set baseUrl https://api.deepseek.com
270
+ ig-gen config set apiKey sk-...
271
+ ig-gen config set baseUrl https://api.deepseek.com
272
+ ig-gen config set defaultOutputDir ~/my-infographics
273
+ ig-gen config set locale zh-CN # 切换界面语言为中文
198
274
 
199
275
  # 读取
200
- infographic-gen config get apiKey
276
+ ig-gen config get apiKey
277
+ ig-gen config get locale # 查看当前语言设置
278
+ ig-gen c get defaultOutputDir # 使用 c 别名
201
279
 
202
280
  # 列出所有配置
203
- infographic-gen config list
281
+ ig-gen config list
282
+ ig-gen c list # 使用 c 别名
204
283
 
205
284
  # 删除
206
- infographic-gen config delete baseUrl
285
+ ig-gen config delete baseUrl
207
286
 
208
287
  # 显示配置文件路径
209
- infographic-gen config path
288
+ ig-gen config path
210
289
  ```
211
290
 
212
291
  ---
@@ -247,6 +326,7 @@ npm run sync
247
326
  推送 git tag 后,GitHub Actions 会自动发布到 npm:
248
327
 
249
328
  1. **创建版本 tag**(遵循语义化版本):
329
+
250
330
  ```bash
251
331
  npm version patch # 1.0.0 → 1.0.1 (bug 修复)
252
332
  npm version minor # 1.0.0 → 1.1.0 (新功能)
@@ -296,6 +376,7 @@ npm publish # 需要先运行 npm login
296
376
  ```
297
377
 
298
378
  发布时:
379
+
299
380
  - 仅包含 `dist/` 文件夹(通过 `"files"` 字段)
300
381
  - 创建全局 `infographic-gen` 命令
301
382
  - 仅支持 ESM,需要 Node.js 18+
@@ -307,13 +388,15 @@ npm publish # 需要先运行 npm login
307
388
  已配置两个自动化工作流:
308
389
 
309
390
  ### 1. `sync-upstream.yml` — 上游变更检测
391
+
310
392
  - 每周运行(周一 08:00 UTC)
311
393
  - 检测 `@antv/infographic` 版本更新
312
394
  - 检查 SKILL.md 变更
313
395
  - 有变更时自动创建 PR
314
396
 
315
397
  ### 2. `publish.yml` — 发布到 npm
316
- - 当推送 git tag 时触发(格式:v*.*.*)
398
+
399
+ - 当推送 git tag 时触发(格式:v*.*.\*)
317
400
  - 自动构建和测试
318
401
  - 发布到 npm
319
402
  - 创建 GitHub Release
@@ -330,6 +413,7 @@ npm run test:watch # Watch 模式
330
413
  ```
331
414
 
332
415
  测试覆盖:
416
+
333
417
  - **131 个测试**分布在 7 个测试文件
334
418
  - 配置管理(持久化存储)
335
419
  - 日志和加载动画工具
@@ -413,7 +497,7 @@ LLM 可能建议了你的 @antv/infographic 版本中不存在的模板。尝试
413
497
  ---
414
498
 
415
499
  更多信息请查看:
500
+
416
501
  - [README.md](README.md) — 英文版本
417
502
  - [PUBLISHING.md](PUBLISHING.md) — 详细发布指南
418
503
  - [QUICK_START.md](QUICK_START.md) — 快速参考卡片
419
-
package/dist/index.js CHANGED
@@ -125,19 +125,25 @@ var CONFIG_KEYS = [
125
125
  "apiKey",
126
126
  "baseUrl",
127
127
  "provider",
128
- "modelName"
128
+ "modelName",
129
+ "defaultOutputDir",
130
+ "locale"
129
131
  ];
130
132
  var CONFIG_LABELS = {
131
133
  apiKey: "API Key",
132
134
  baseUrl: "Base URL",
133
135
  provider: "Provider",
134
- modelName: "Model Name"
136
+ modelName: "Model Name",
137
+ defaultOutputDir: "Default Output Directory",
138
+ locale: "Language"
135
139
  };
136
140
  var DEFAULTS = {
137
141
  apiKey: "",
138
142
  baseUrl: "https://api.openai.com/v1",
139
143
  provider: "openai",
140
- modelName: "gpt-4o"
144
+ modelName: "gpt-4o",
145
+ defaultOutputDir: ".",
146
+ locale: "en"
141
147
  };
142
148
  var store = new Conf({
143
149
  projectName: "infographic-gen",
@@ -165,7 +171,9 @@ function getAllConfig() {
165
171
  apiKey: getConfig("apiKey"),
166
172
  baseUrl: getConfig("baseUrl"),
167
173
  provider: getConfig("provider"),
168
- modelName: getConfig("modelName")
174
+ modelName: getConfig("modelName"),
175
+ defaultOutputDir: getConfig("defaultOutputDir"),
176
+ locale: getConfig("locale")
169
177
  };
170
178
  }
171
179
  function isValidConfigKey(key) {
@@ -197,49 +205,168 @@ function label(key, value) {
197
205
  console.error(` ${import_picocolors.default.cyan(key)}: ${value}`);
198
206
  }
199
207
 
208
+ // src/utils/i18n.ts
209
+ init_esm_shims();
210
+ var translations = {
211
+ en: {
212
+ // Main program
213
+ programDesc: "AI-powered CLI to generate AntV Infographic SVGs from natural language prompts",
214
+ versionFlag: "Display version number",
215
+ // Config command
216
+ configDesc: "Manage configuration (API Key, Base URL, Provider, Model, Output Directory)",
217
+ configSetDesc: "Set a configuration value",
218
+ configGetDesc: "Get a single configuration value",
219
+ configListDesc: "List all configuration values",
220
+ configDeleteDesc: "Delete a configuration value (reset to default)",
221
+ configPathDesc: "Show configuration file path",
222
+ configInvalidKey: 'Invalid config key "{key}". Available: {keys}',
223
+ configSetSuccess: "{label} set successfully",
224
+ configNotSet: "{label} not set",
225
+ configCurrent: "Current configuration:",
226
+ configFileLocation: " Config file location: {path}",
227
+ configResetSuccess: "{label} reset to default",
228
+ configNotSetValue: "(not set)",
229
+ // Generate command
230
+ generateDesc: "Generate an SVG infographic from natural language (default command)",
231
+ generatePromptArg: "Describe the infographic you want to create",
232
+ generateOutputOpt: "Output SVG file path (default: infographic-output.svg in default output directory)",
233
+ generateDslOpt: "Save raw DSL syntax to a text file (optional, for debugging or fine-tuning)",
234
+ outputTarget: "Output target: {path}",
235
+ callingAI: "Calling AI to generate infographic syntax...",
236
+ renderingSVG: "Rendering SVG...",
237
+ reRenderingSVG: "Re-rendering SVG...",
238
+ aiCallFailed: "AI call failed",
239
+ renderingFailed: "Rendering failed",
240
+ renderFailedAfterRetries: "Failed to generate renderable infographic after {retries} self-correction attempts.",
241
+ lastError: "Last error: {error}",
242
+ dslAutoSaved: "\u274C Problematic DSL syntax auto-saved to: {path}",
243
+ dslAutoSaveHint: "You can inspect this file to debug the LLM output or refine your prompt.",
244
+ dslForDebug: "Generated DSL syntax (for debugging reference):",
245
+ fileWriteFailed: "File write failed",
246
+ dslSaved: "DSL syntax saved to: {path}",
247
+ dslWriteFailed: "DSL file write failed (does not affect main functionality):",
248
+ infographicGenerated: "Infographic generated!",
249
+ svgSaved: "SVG saved to: {path}",
250
+ openInBrowser: "You can open the SVG file directly in a browser to view it.",
251
+ selfCorrecting: "AI self-correcting (attempt {attempt}/{max})...",
252
+ selfCorrectionFailed: "Self-correction failed",
253
+ renderFailedRetrying: "Render failed, auto-correcting (attempt {attempt}/{max})...",
254
+ // AI errors
255
+ apiKeyNotConfigured: "API Key not configured. Please run: infographic-gen config set apiKey <YOUR_KEY>",
256
+ llmEmptyContent: "LLM returned empty content",
257
+ failedAfterRetries: "Failed to generate renderable infographic after {retries} retries. Last error: {error}"
258
+ },
259
+ "zh-CN": {
260
+ // Main program
261
+ programDesc: "AI \u9A71\u52A8\u7684\u4FE1\u606F\u56FE\u751F\u6210 CLI \u2014\u2014 \u8F93\u5165\u81EA\u7136\u8BED\u8A00\uFF0C\u8F93\u51FA\u7CBE\u7F8E SVG \u4FE1\u606F\u56FE",
262
+ versionFlag: "\u663E\u793A\u7248\u672C\u53F7",
263
+ // Config command
264
+ configDesc: "\u7BA1\u7406\u914D\u7F6E\uFF08API Key\u3001Base URL\u3001Provider\u3001Model\u3001\u8F93\u51FA\u76EE\u5F55\uFF09",
265
+ configSetDesc: "\u8BBE\u7F6E\u914D\u7F6E\u9879",
266
+ configGetDesc: "\u67E5\u770B\u5355\u4E2A\u914D\u7F6E\u9879",
267
+ configListDesc: "\u5217\u51FA\u6240\u6709\u914D\u7F6E\u9879",
268
+ configDeleteDesc: "\u5220\u9664\u914D\u7F6E\u9879\uFF08\u6062\u590D\u9ED8\u8BA4\u503C\uFF09",
269
+ configPathDesc: "\u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",
270
+ configInvalidKey: '\u65E0\u6548\u7684\u914D\u7F6E\u9879 "{key}"\uFF0C\u53EF\u9009\u9879\uFF1A{keys}',
271
+ configSetSuccess: "{label} \u5DF2\u8BBE\u7F6E",
272
+ configNotSet: "{label} \u5C1A\u672A\u8BBE\u7F6E",
273
+ configCurrent: "\u5F53\u524D\u914D\u7F6E\uFF1A",
274
+ configFileLocation: " \u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E: {path}",
275
+ configResetSuccess: "{label} \u5DF2\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u503C",
276
+ configNotSetValue: "(\u672A\u8BBE\u7F6E)",
277
+ // Generate command
278
+ generateDesc: "\u6839\u636E\u81EA\u7136\u8BED\u8A00\u63CF\u8FF0\u751F\u6210 SVG \u4FE1\u606F\u56FE\uFF08\u9ED8\u8BA4\u547D\u4EE4\uFF09",
279
+ generatePromptArg: "\u63CF\u8FF0\u4F60\u60F3\u8981\u751F\u6210\u7684\u4FE1\u606F\u56FE\u5185\u5BB9",
280
+ generateOutputOpt: "\u8F93\u51FA SVG \u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\uFF1A\u9ED8\u8BA4\u8F93\u51FA\u76EE\u5F55\u4E2D\u7684 infographic-output.svg\uFF09",
281
+ generateDslOpt: "\u5C06\u539F\u59CB DSL \u8BED\u6CD5\u4FDD\u5B58\u5230\u6307\u5B9A\u6587\u672C\u6587\u4EF6\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u8C03\u8BD5\u6216\u5FAE\u8C03\uFF09",
282
+ outputTarget: "\u76EE\u6807\u8F93\u51FA\uFF1A{path}",
283
+ callingAI: "\u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4FE1\u606F\u56FE\u8BED\u6CD5...",
284
+ renderingSVG: "\u6B63\u5728\u6E32\u67D3 SVG...",
285
+ reRenderingSVG: "\u6B63\u5728\u91CD\u65B0\u6E32\u67D3 SVG...",
286
+ aiCallFailed: "AI \u8C03\u7528\u5931\u8D25",
287
+ renderingFailed: "\u6E32\u67D3\u6700\u7EC8\u5931\u8D25",
288
+ renderFailedAfterRetries: "\u7ECF\u8FC7 {retries} \u6B21\u81EA\u6211\u4FEE\u6B63\u4ECD\u65E0\u6CD5\u751F\u6210\u53EF\u6E32\u67D3\u7684\u4FE1\u606F\u56FE\u3002",
289
+ lastError: "\u6700\u540E\u4E00\u6B21\u9519\u8BEF\uFF1A{error}",
290
+ dslAutoSaved: "\u274C \u6709\u95EE\u9898\u7684 DSL \u8BED\u6CD5\u5DF2\u81EA\u52A8\u4FDD\u5B58\u81F3\uFF1A{path}",
291
+ dslAutoSaveHint: "\u4F60\u53EF\u4EE5\u68C0\u67E5\u6B64\u6587\u4EF6\u4EE5\u6392\u67E5\u5927\u6A21\u578B\u751F\u6210\u7684\u95EE\u9898\uFF0C\u6216\u7528\u4E8E\u8C03\u8BD5 Prompt\u3002",
292
+ dslForDebug: "\u751F\u6210\u7684 DSL \u8BED\u6CD5\u5982\u4E0B\uFF08\u4F9B debug \u53C2\u8003\uFF09\uFF1A",
293
+ fileWriteFailed: "\u6587\u4EF6\u5199\u5165\u5931\u8D25",
294
+ dslSaved: "DSL \u8BED\u6CD5\u5DF2\u4FDD\u5B58\u81F3\uFF1A{path}",
295
+ dslWriteFailed: "DSL \u6587\u4EF6\u5199\u5165\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u4E3B\u8981\u529F\u80FD\uFF09\uFF1A",
296
+ infographicGenerated: "\u4FE1\u606F\u56FE\u5DF2\u751F\u6210\uFF01",
297
+ svgSaved: "SVG \u5DF2\u4FDD\u5B58\u81F3\uFF1A{path}",
298
+ openInBrowser: "\u53EF\u76F4\u63A5\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00 SVG \u6587\u4EF6\u67E5\u770B\u6548\u679C\u3002",
299
+ selfCorrecting: "AI \u6B63\u5728\u81EA\u6211\u4FEE\u6B63\uFF08\u7B2C {attempt}/{max} \u6B21\uFF09...",
300
+ selfCorrectionFailed: "\u81EA\u6211\u4FEE\u6B63\u5931\u8D25",
301
+ renderFailedRetrying: "\u6E32\u67D3\u5931\u8D25\uFF0C\u6B63\u5728\u81EA\u52A8\u4FEE\u6B63\uFF08\u7B2C {attempt}/{max} \u6B21\uFF09...",
302
+ // AI errors
303
+ apiKeyNotConfigured: "\u5C1A\u672A\u914D\u7F6E API Key\u3002\u8BF7\u5148\u8FD0\u884C\uFF1Ainfographic-gen config set apiKey <YOUR_KEY>",
304
+ llmEmptyContent: "LLM \u8FD4\u56DE\u4E86\u7A7A\u5185\u5BB9",
305
+ failedAfterRetries: "\u5DF2\u91CD\u8BD5 {retries} \u6B21\u4ECD\u7136\u65E0\u6CD5\u751F\u6210\u53EF\u6E32\u67D3\u7684\u4FE1\u606F\u56FE\u3002\u6700\u540E\u4E00\u6B21\u9519\u8BEF\uFF1A{error}"
306
+ }
307
+ };
308
+ function getLocale() {
309
+ const locale = getConfig("locale");
310
+ return locale === "zh-CN" ? "zh-CN" : "en";
311
+ }
312
+ function t(key, params) {
313
+ const locale = getLocale();
314
+ let text = translations[locale][key];
315
+ if (params) {
316
+ Object.entries(params).forEach(([paramKey, value]) => {
317
+ text = text.replace(`{${paramKey}}`, String(value));
318
+ });
319
+ }
320
+ return text;
321
+ }
322
+
200
323
  // src/commands/config.ts
201
324
  function registerConfigCommand(program2) {
202
- const configCmd = program2.command("config").description("\u7BA1\u7406 LLM \u914D\u7F6E\uFF08API Key\u3001Base URL\u3001Provider\u3001Model\uFF09");
203
- configCmd.command("set <key> <value>").description("\u8BBE\u7F6E\u914D\u7F6E\u9879").action((key, value) => {
325
+ const configCmd = program2.command("config").alias("c").description(
326
+ "Manage configuration (API Key, Base URL, Provider, Model, Output Directory)"
327
+ );
328
+ configCmd.command("set <key> <value>").description(t("configSetDesc")).action((key, value) => {
204
329
  if (!isValidConfigKey(key)) {
205
- error(`\u65E0\u6548\u7684\u914D\u7F6E\u9879 "${key}"\uFF0C\u53EF\u9009\u9879\uFF1A${CONFIG_KEYS.join(", ")}`);
330
+ error(t("configInvalidKey", { key, keys: CONFIG_KEYS.join(", ") }));
206
331
  process.exit(1);
207
332
  }
208
333
  setConfig(key, value);
209
- success(`${CONFIG_LABELS[key]} \u5DF2\u8BBE\u7F6E`);
334
+ success(t("configSetSuccess", { label: CONFIG_LABELS[key] }));
210
335
  });
211
- configCmd.command("get <key>").description("\u67E5\u770B\u5355\u4E2A\u914D\u7F6E\u9879").action((key) => {
336
+ configCmd.command("get <key>").description(t("configGetDesc")).action((key) => {
212
337
  if (!isValidConfigKey(key)) {
213
- error(`\u65E0\u6548\u7684\u914D\u7F6E\u9879 "${key}"\uFF0C\u53EF\u9009\u9879\uFF1A${CONFIG_KEYS.join(", ")}`);
338
+ error(t("configInvalidKey", { key, keys: CONFIG_KEYS.join(", ") }));
214
339
  process.exit(1);
215
340
  }
216
341
  const val = getConfig(key);
217
342
  if (!val) {
218
- warn(`${CONFIG_LABELS[key]} \u5C1A\u672A\u8BBE\u7F6E`);
343
+ warn(t("configNotSet", { label: CONFIG_LABELS[key] }));
219
344
  } else {
220
345
  const display = key === "apiKey" ? maskApiKey(val) : val;
221
346
  label(CONFIG_LABELS[key], display);
222
347
  }
223
348
  });
224
- configCmd.command("list").description("\u5217\u51FA\u6240\u6709\u914D\u7F6E\u9879").action(() => {
349
+ configCmd.command("list").description(t("configListDesc")).action(() => {
225
350
  const all = getAllConfig();
226
- info("\u5F53\u524D\u914D\u7F6E\uFF1A");
351
+ info(t("configCurrent"));
227
352
  for (const k of CONFIG_KEYS) {
228
353
  const val = all[k];
229
- const display = k === "apiKey" && val ? maskApiKey(val) : val || "(\u672A\u8BBE\u7F6E)";
354
+ const display = k === "apiKey" && val ? maskApiKey(val) : val || t("configNotSetValue");
230
355
  label(CONFIG_LABELS[k], display);
231
356
  }
232
- dim(` \u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E: ${getConfigPath()}`);
357
+ dim(t("configFileLocation", { path: getConfigPath() }));
233
358
  });
234
- configCmd.command("delete <key>").description("\u5220\u9664\u914D\u7F6E\u9879\uFF08\u6062\u590D\u9ED8\u8BA4\u503C\uFF09").action((key) => {
359
+ configCmd.command("delete <key>").description(t("configDeleteDesc")).action((key) => {
235
360
  if (!isValidConfigKey(key)) {
236
- error(`\u65E0\u6548\u7684\u914D\u7F6E\u9879 "${key}"\uFF0C\u53EF\u9009\u9879\uFF1A${CONFIG_KEYS.join(", ")}`);
361
+ error(t("configInvalidKey", { key, keys: CONFIG_KEYS.join(", ") }));
237
362
  process.exit(1);
238
363
  }
239
364
  deleteConfig(key);
240
- success(`${CONFIG_LABELS[key]} \u5DF2\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u503C`);
365
+ success(
366
+ t("configResetSuccess", { label: CONFIG_LABELS[key] })
367
+ );
241
368
  });
242
- configCmd.command("path").description("\u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(() => {
369
+ configCmd.command("path").description(t("configPathDesc")).action(() => {
243
370
  console.log(getConfigPath());
244
371
  });
245
372
  }
@@ -622,9 +749,7 @@ var MAX_RETRIES = 3;
622
749
  function createClient() {
623
750
  const { apiKey, baseUrl } = getLLMConfig();
624
751
  if (!apiKey) {
625
- throw new Error(
626
- "\u5C1A\u672A\u914D\u7F6E API Key\u3002\u8BF7\u5148\u8FD0\u884C\uFF1Ainfographic-gen config set apiKey <YOUR_KEY>"
627
- );
752
+ throw new Error(t("apiKeyNotConfigured"));
628
753
  }
629
754
  return new OpenAI({
630
755
  apiKey,
@@ -640,7 +765,7 @@ async function callLLM(client, model, messages) {
640
765
  });
641
766
  const content = response.choices[0]?.message?.content;
642
767
  if (!content) {
643
- throw new Error("LLM \u8FD4\u56DE\u4E86\u7A7A\u5185\u5BB9");
768
+ throw new Error(t("llmEmptyContent"));
644
769
  }
645
770
  return cleanDSL(content);
646
771
  }
@@ -668,11 +793,21 @@ async function generateInfographicDSL(userPrompt) {
668
793
  async function retryWithCorrection(originalSyntax, errorMessage, userPrompt, attempt) {
669
794
  if (attempt > MAX_RETRIES) {
670
795
  throw new Error(
671
- `\u5DF2\u91CD\u8BD5 ${MAX_RETRIES} \u6B21\u4ECD\u7136\u65E0\u6CD5\u751F\u6210\u53EF\u6E32\u67D3\u7684\u4FE1\u606F\u56FE\u3002\u6700\u540E\u4E00\u6B21\u9519\u8BEF\uFF1A${errorMessage}`
796
+ t("failedAfterRetries", {
797
+ retries: String(MAX_RETRIES),
798
+ error: errorMessage
799
+ })
672
800
  );
673
801
  }
674
- updateSpinner(`AI \u6B63\u5728\u81EA\u6211\u4FEE\u6B63\uFF08\u7B2C ${attempt}/${MAX_RETRIES} \u6B21\uFF09...`);
675
- warn(`\u6E32\u67D3\u5931\u8D25\uFF0C\u6B63\u5728\u81EA\u52A8\u4FEE\u6B63\uFF08\u7B2C ${attempt}/${MAX_RETRIES} \u6B21\uFF09...`);
802
+ updateSpinner(
803
+ t("selfCorrecting", { attempt: String(attempt), max: String(MAX_RETRIES) })
804
+ );
805
+ warn(
806
+ t("renderFailedRetrying", {
807
+ attempt: String(attempt),
808
+ max: String(MAX_RETRIES)
809
+ })
810
+ );
676
811
  const client = createClient();
677
812
  const { modelName } = getLLMConfig();
678
813
  const correctionMessage = SELF_CORRECTION_PROMPT_TEMPLATE.replace(
@@ -711,35 +846,43 @@ async function writeSVGFile(outputPath, svgContent) {
711
846
  await fs.mkdir(dir, { recursive: true });
712
847
  await fs.writeFile(absolutePath, svgContent, "utf-8");
713
848
  }
849
+ async function writeDSLFile(outputPath, dslContent) {
850
+ const absolutePath = path2.resolve(outputPath);
851
+ const dir = path2.dirname(absolutePath);
852
+ await fs.mkdir(dir, { recursive: true });
853
+ await fs.writeFile(absolutePath, dslContent, "utf-8");
854
+ }
714
855
  function resolveOutputPath(userOutput) {
856
+ const defaultDir = getConfig("defaultOutputDir") || ".";
715
857
  if (userOutput) {
716
- if (!userOutput.endsWith(".svg")) {
717
- return userOutput + ".svg";
858
+ const withExt = userOutput.endsWith(".svg") ? userOutput : userOutput + ".svg";
859
+ if (path2.isAbsolute(withExt)) {
860
+ return withExt;
718
861
  }
719
- return userOutput;
862
+ return path2.resolve(defaultDir, withExt);
720
863
  }
721
- return path2.resolve(process.cwd(), "infographic-output.svg");
864
+ return path2.resolve(defaultDir, "infographic-output.svg");
722
865
  }
723
866
 
724
867
  // src/commands/generate.ts
725
868
  function registerGenerateCommand(program2) {
726
- program2.command("generate").alias("gen").description("\u6839\u636E\u81EA\u7136\u8BED\u8A00\u63CF\u8FF0\u751F\u6210 SVG \u4FE1\u606F\u56FE").argument("<prompt>", "\u63CF\u8FF0\u4F60\u60F3\u8981\u751F\u6210\u7684\u4FE1\u606F\u56FE\u5185\u5BB9").option("-o, --output <path>", "\u8F93\u51FA SVG \u6587\u4EF6\u8DEF\u5F84", "infographic-output.svg").action(async (prompt, opts) => {
727
- await handleGenerate(prompt, opts.output);
869
+ program2.command("generate", { isDefault: true }).alias("g").description(t("generateDesc")).argument("<prompt>", t("generatePromptArg")).option("-o, --output <path>", t("generateOutputOpt")).option("--dsl <path>", t("generateDslOpt")).action(async (prompt, opts) => {
870
+ await handleGenerate(prompt, opts.output, opts.dsl);
728
871
  });
729
872
  }
730
- async function handleGenerate(prompt, outputOption) {
873
+ async function handleGenerate(prompt, outputOption, dslOption) {
731
874
  const outputPath = resolveOutputPath(outputOption);
732
- info(`\u76EE\u6807\u8F93\u51FA\uFF1A${path3.resolve(outputPath)}`);
733
- startSpinner("\u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4FE1\u606F\u56FE\u8BED\u6CD5...");
875
+ info(t("outputTarget", { path: path3.resolve(outputPath) }));
876
+ startSpinner(t("callingAI"));
734
877
  let syntax;
735
878
  try {
736
879
  syntax = await generateInfographicDSL(prompt);
737
880
  } catch (err) {
738
- failSpinner("AI \u8C03\u7528\u5931\u8D25");
881
+ failSpinner(t("aiCallFailed"));
739
882
  error(err instanceof Error ? err.message : String(err));
740
883
  process.exit(1);
741
884
  }
742
- updateSpinner("\u6B63\u5728\u6E32\u67D3 SVG...");
885
+ updateSpinner(t("renderingSVG"));
743
886
  let svgContent = null;
744
887
  let lastError = "";
745
888
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
@@ -750,40 +893,69 @@ async function handleGenerate(prompt, outputOption) {
750
893
  lastError = err instanceof Error ? err.message : String(err);
751
894
  if (attempt < MAX_RETRIES) {
752
895
  try {
753
- syntax = await retryWithCorrection(syntax, lastError, prompt, attempt + 1);
754
- updateSpinner("\u6B63\u5728\u91CD\u65B0\u6E32\u67D3 SVG...");
896
+ syntax = await retryWithCorrection(
897
+ syntax,
898
+ lastError,
899
+ prompt,
900
+ attempt + 1
901
+ );
902
+ updateSpinner(t("reRenderingSVG"));
755
903
  } catch (retryErr) {
756
- failSpinner("\u81EA\u6211\u4FEE\u6B63\u5931\u8D25");
757
- error(retryErr instanceof Error ? retryErr.message : String(retryErr));
904
+ failSpinner(t("selfCorrectionFailed"));
905
+ error(
906
+ retryErr instanceof Error ? retryErr.message : String(retryErr)
907
+ );
758
908
  process.exit(1);
759
909
  }
760
910
  }
761
911
  }
762
912
  }
763
913
  if (!svgContent) {
764
- failSpinner("\u6E32\u67D3\u6700\u7EC8\u5931\u8D25");
765
- error(`\u7ECF\u8FC7 ${MAX_RETRIES} \u6B21\u81EA\u6211\u4FEE\u6B63\u4ECD\u65E0\u6CD5\u751F\u6210\u53EF\u6E32\u67D3\u7684\u4FE1\u606F\u56FE\u3002`);
766
- error(`\u6700\u540E\u4E00\u6B21\u9519\u8BEF\uFF1A${lastError}`);
767
- dim("\u751F\u6210\u7684 DSL \u8BED\u6CD5\u5982\u4E0B\uFF08\u4F9B debug \u53C2\u8003\uFF09\uFF1A");
768
- console.error(syntax);
914
+ failSpinner(t("renderingFailed"));
915
+ error(t("renderFailedAfterRetries", { retries: String(MAX_RETRIES) }));
916
+ error(t("lastError", { error: lastError }));
917
+ const errorDumpPath = "error-dump.txt";
918
+ try {
919
+ await writeDSLFile(errorDumpPath, syntax);
920
+ warn(t("dslAutoSaved", { path: path3.resolve(errorDumpPath) }));
921
+ dim(t("dslAutoSaveHint"));
922
+ } catch (writeErr) {
923
+ dim(t("dslForDebug"));
924
+ console.error(syntax);
925
+ }
769
926
  process.exit(1);
770
927
  }
771
928
  try {
772
929
  await writeSVGFile(outputPath, svgContent);
773
930
  } catch (err) {
774
- failSpinner("\u6587\u4EF6\u5199\u5165\u5931\u8D25");
931
+ failSpinner(t("fileWriteFailed"));
775
932
  error(err instanceof Error ? err.message : String(err));
776
933
  process.exit(1);
777
934
  }
778
- succeedSpinner(`\u4FE1\u606F\u56FE\u5DF2\u751F\u6210\uFF01`);
779
- success(`SVG \u5DF2\u4FDD\u5B58\u81F3\uFF1A${path3.resolve(outputPath)}`);
780
- dim("\u53EF\u76F4\u63A5\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00 SVG \u6587\u4EF6\u67E5\u770B\u6548\u679C\u3002");
935
+ if (dslOption) {
936
+ try {
937
+ await writeDSLFile(dslOption, syntax);
938
+ success(t("dslSaved", { path: path3.resolve(dslOption) }));
939
+ } catch (err) {
940
+ warn(t("dslWriteFailed"));
941
+ warn(err instanceof Error ? err.message : String(err));
942
+ }
943
+ }
944
+ succeedSpinner(t("infographicGenerated"));
945
+ success(t("svgSaved", { path: path3.resolve(outputPath) }));
946
+ dim(t("openInBrowser"));
781
947
  }
782
948
 
783
949
  // src/index.ts
784
- var VERSION = "1.0.0";
950
+ import { readFileSync } from "fs";
951
+ import { fileURLToPath as fileURLToPath2 } from "url";
952
+ import { dirname, join } from "path";
953
+ var __dirname2 = dirname(fileURLToPath2(import.meta.url));
954
+ var packageJsonPath = join(__dirname2, "../package.json");
955
+ var packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
956
+ var VERSION = packageJson.version;
785
957
  var program = new Command();
786
- program.name("infographic-gen").description("AI \u9A71\u52A8\u7684\u4FE1\u606F\u56FE\u751F\u6210 CLI \u2014\u2014 \u8F93\u5165\u81EA\u7136\u8BED\u8A00\uFF0C\u8F93\u51FA\u7CBE\u7F8E SVG \u4FE1\u606F\u56FE").version(VERSION, "-v, --version", "\u663E\u793A\u7248\u672C\u53F7");
958
+ program.name("infographic-gen").description(t("programDesc")).version(VERSION, "-v, --version", t("versionFlag"));
787
959
  registerConfigCommand(program);
788
960
  registerGenerateCommand(program);
789
961
  program.parse(process.argv);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../node_modules/picocolors/picocolors.js","../src/index.ts","../src/commands/config.ts","../src/config/index.ts","../src/utils/logger.ts","../src/commands/generate.ts","../src/core/ai.ts","../src/core/prompts.ts","../src/utils/spinner.ts","../src/core/render.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","let p = process || {}, argv = p.argv || [], env = p.env || {}\nlet isColorSupported =\n\t!(!!env.NO_COLOR || argv.includes(\"--no-color\")) &&\n\t(!!env.FORCE_COLOR || argv.includes(\"--color\") || p.platform === \"win32\" || ((p.stdout || {}).isTTY && env.TERM !== \"dumb\") || !!env.CI)\n\nlet formatter = (open, close, replace = open) =>\n\tinput => {\n\t\tlet string = \"\" + input, index = string.indexOf(close, open.length)\n\t\treturn ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close\n\t}\n\nlet replaceClose = (string, close, replace, index) => {\n\tlet result = \"\", cursor = 0\n\tdo {\n\t\tresult += string.substring(cursor, index) + replace\n\t\tcursor = index + close.length\n\t\tindex = string.indexOf(close, cursor)\n\t} while (~index)\n\treturn result + string.substring(cursor)\n}\n\nlet createColors = (enabled = isColorSupported) => {\n\tlet f = enabled ? formatter : () => String\n\treturn {\n\t\tisColorSupported: enabled,\n\t\treset: f(\"\\x1b[0m\", \"\\x1b[0m\"),\n\t\tbold: f(\"\\x1b[1m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[1m\"),\n\t\tdim: f(\"\\x1b[2m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[2m\"),\n\t\titalic: f(\"\\x1b[3m\", \"\\x1b[23m\"),\n\t\tunderline: f(\"\\x1b[4m\", \"\\x1b[24m\"),\n\t\tinverse: f(\"\\x1b[7m\", \"\\x1b[27m\"),\n\t\thidden: f(\"\\x1b[8m\", \"\\x1b[28m\"),\n\t\tstrikethrough: f(\"\\x1b[9m\", \"\\x1b[29m\"),\n\n\t\tblack: f(\"\\x1b[30m\", \"\\x1b[39m\"),\n\t\tred: f(\"\\x1b[31m\", \"\\x1b[39m\"),\n\t\tgreen: f(\"\\x1b[32m\", \"\\x1b[39m\"),\n\t\tyellow: f(\"\\x1b[33m\", \"\\x1b[39m\"),\n\t\tblue: f(\"\\x1b[34m\", \"\\x1b[39m\"),\n\t\tmagenta: f(\"\\x1b[35m\", \"\\x1b[39m\"),\n\t\tcyan: f(\"\\x1b[36m\", \"\\x1b[39m\"),\n\t\twhite: f(\"\\x1b[37m\", \"\\x1b[39m\"),\n\t\tgray: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\n\t\tbgBlack: f(\"\\x1b[40m\", \"\\x1b[49m\"),\n\t\tbgRed: f(\"\\x1b[41m\", \"\\x1b[49m\"),\n\t\tbgGreen: f(\"\\x1b[42m\", \"\\x1b[49m\"),\n\t\tbgYellow: f(\"\\x1b[43m\", \"\\x1b[49m\"),\n\t\tbgBlue: f(\"\\x1b[44m\", \"\\x1b[49m\"),\n\t\tbgMagenta: f(\"\\x1b[45m\", \"\\x1b[49m\"),\n\t\tbgCyan: f(\"\\x1b[46m\", \"\\x1b[49m\"),\n\t\tbgWhite: f(\"\\x1b[47m\", \"\\x1b[49m\"),\n\n\t\tblackBright: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\t\tredBright: f(\"\\x1b[91m\", \"\\x1b[39m\"),\n\t\tgreenBright: f(\"\\x1b[92m\", \"\\x1b[39m\"),\n\t\tyellowBright: f(\"\\x1b[93m\", \"\\x1b[39m\"),\n\t\tblueBright: f(\"\\x1b[94m\", \"\\x1b[39m\"),\n\t\tmagentaBright: f(\"\\x1b[95m\", \"\\x1b[39m\"),\n\t\tcyanBright: f(\"\\x1b[96m\", \"\\x1b[39m\"),\n\t\twhiteBright: f(\"\\x1b[97m\", \"\\x1b[39m\"),\n\n\t\tbgBlackBright: f(\"\\x1b[100m\", \"\\x1b[49m\"),\n\t\tbgRedBright: f(\"\\x1b[101m\", \"\\x1b[49m\"),\n\t\tbgGreenBright: f(\"\\x1b[102m\", \"\\x1b[49m\"),\n\t\tbgYellowBright: f(\"\\x1b[103m\", \"\\x1b[49m\"),\n\t\tbgBlueBright: f(\"\\x1b[104m\", \"\\x1b[49m\"),\n\t\tbgMagentaBright: f(\"\\x1b[105m\", \"\\x1b[49m\"),\n\t\tbgCyanBright: f(\"\\x1b[106m\", \"\\x1b[49m\"),\n\t\tbgWhiteBright: f(\"\\x1b[107m\", \"\\x1b[49m\"),\n\t}\n}\n\nmodule.exports = createColors()\nmodule.exports.createColors = createColors\n","import { Command } from \"commander\";\nimport { registerConfigCommand } from \"./commands/config.js\";\nimport { registerGenerateCommand } from \"./commands/generate.js\";\n\nconst VERSION = \"1.0.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"infographic-gen\")\n .description(\"AI 驱动的信息图生成 CLI —— 输入自然语言,输出精美 SVG 信息图\")\n .version(VERSION, \"-v, --version\", \"显示版本号\");\n\n// 注册子命令\nregisterConfigCommand(program);\nregisterGenerateCommand(program);\n\n// 解析命令行参数\nprogram.parse(process.argv);\n","import { Command } from \"commander\";\nimport {\n getAllConfig,\n getConfig,\n setConfig,\n deleteConfig,\n isValidConfigKey,\n getConfigPath,\n CONFIG_KEYS,\n CONFIG_LABELS,\n type ConfigKey,\n} from \"../config/index.js\";\nimport * as log from \"../utils/logger.js\";\n\n/**\n * 注册 `config` 子命令,支持以下操作:\n * config set <key> <value> — 设置配置项\n * config get <key> — 查看单个配置项\n * config list — 列出所有配置\n * config delete <key> — 删除(重置)配置项\n * config path — 打印配置文件路径\n */\nexport function registerConfigCommand(program: Command): void {\n const configCmd = program\n .command(\"config\")\n .description(\"管理 LLM 配置(API Key、Base URL、Provider、Model)\");\n\n // ---------- config set ----------\n configCmd\n .command(\"set <key> <value>\")\n .description(\"设置配置项\")\n .action((key: string, value: string) => {\n if (!isValidConfigKey(key)) {\n log.error(`无效的配置项 \"${key}\",可选项:${CONFIG_KEYS.join(\", \")}`);\n process.exit(1);\n }\n setConfig(key, value);\n log.success(`${CONFIG_LABELS[key]} 已设置`);\n });\n\n // ---------- config get ----------\n configCmd\n .command(\"get <key>\")\n .description(\"查看单个配置项\")\n .action((key: string) => {\n if (!isValidConfigKey(key)) {\n log.error(`无效的配置项 \"${key}\",可选项:${CONFIG_KEYS.join(\", \")}`);\n process.exit(1);\n }\n const val = getConfig(key);\n if (!val) {\n log.warn(`${CONFIG_LABELS[key]} 尚未设置`);\n } else {\n // 对 apiKey 做脱敏显示\n const display = key === \"apiKey\" ? maskApiKey(val) : val;\n log.label(CONFIG_LABELS[key], display);\n }\n });\n\n // ---------- config list ----------\n configCmd\n .command(\"list\")\n .description(\"列出所有配置项\")\n .action(() => {\n const all = getAllConfig();\n log.info(\"当前配置:\");\n for (const k of CONFIG_KEYS) {\n const val = all[k];\n const display =\n k === \"apiKey\" && val ? maskApiKey(val) : val || \"(未设置)\";\n log.label(CONFIG_LABELS[k], display);\n }\n log.dim(` 配置文件位置: ${getConfigPath()}`);\n });\n\n // ---------- config delete ----------\n configCmd\n .command(\"delete <key>\")\n .description(\"删除配置项(恢复默认值)\")\n .action((key: string) => {\n if (!isValidConfigKey(key)) {\n log.error(`无效的配置项 \"${key}\",可选项:${CONFIG_KEYS.join(\", \")}`);\n process.exit(1);\n }\n deleteConfig(key as ConfigKey);\n log.success(`${CONFIG_LABELS[key as ConfigKey]} 已重置为默认值`);\n });\n\n // ---------- config path ----------\n configCmd\n .command(\"path\")\n .description(\"显示配置文件路径\")\n .action(() => {\n console.log(getConfigPath());\n });\n}\n\n// ---- helpers ----\n\n/** 对 API Key 做脱敏处理:只显示前 4 位和后 4 位 */\nfunction maskApiKey(key: string): string {\n if (key.length <= 8) return \"****\";\n return key.slice(0, 4) + \"****\" + key.slice(-4);\n}\n","import Conf from \"conf\";\n\n/**\n * 用户可配置的 LLM 字段\n */\nexport interface LLMConfig {\n apiKey: string;\n baseUrl: string;\n provider: string;\n modelName: string;\n}\n\n/**\n * 配置 schema 的完整类型\n */\ninterface ConfigSchema {\n apiKey: string;\n baseUrl: string;\n provider: string;\n modelName: string;\n}\n\n/** 所有可配置的 key */\nexport const CONFIG_KEYS = [\n \"apiKey\",\n \"baseUrl\",\n \"provider\",\n \"modelName\",\n] as const;\nexport type ConfigKey = (typeof CONFIG_KEYS)[number];\n\n/** 配置项的人类可读标签 */\nexport const CONFIG_LABELS: Record<ConfigKey, string> = {\n apiKey: \"API Key\",\n baseUrl: \"Base URL\",\n provider: \"Provider\",\n modelName: \"Model Name\",\n};\n\n/** 默认值 */\nconst DEFAULTS: ConfigSchema = {\n apiKey: \"\",\n baseUrl: \"https://api.openai.com/v1\",\n provider: \"openai\",\n modelName: \"gpt-4o\",\n};\n\n/**\n * 基于 conf 的本地持久化配置管理器(单例)\n */\nconst store = new Conf<ConfigSchema>({\n projectName: \"infographic-gen\",\n defaults: DEFAULTS,\n});\n\n/** 读取单个配置值 */\nexport function getConfig<K extends ConfigKey>(key: K): string {\n return store.get(key) as string;\n}\n\n/** 写入单个配置值 */\nexport function setConfig<K extends ConfigKey>(key: K, value: string): void {\n store.set(key, value);\n}\n\n/** 删除单个配置值(恢复为默认) */\nexport function deleteConfig<K extends ConfigKey>(key: K): void {\n store.delete(key);\n}\n\n/** 读取完整 LLM 配置(用于创建 OpenAI 客户端) */\nexport function getLLMConfig(): LLMConfig {\n return {\n apiKey: getConfig(\"apiKey\"),\n baseUrl: getConfig(\"baseUrl\"),\n provider: getConfig(\"provider\"),\n modelName: getConfig(\"modelName\"),\n };\n}\n\n/** 返回所有配置项的 KV 对象(用于 `config list`) */\nexport function getAllConfig(): Record<ConfigKey, string> {\n return {\n apiKey: getConfig(\"apiKey\"),\n baseUrl: getConfig(\"baseUrl\"),\n provider: getConfig(\"provider\"),\n modelName: getConfig(\"modelName\"),\n };\n}\n\n/** 判断某个 key 是否为合法配置项 */\nexport function isValidConfigKey(key: string): key is ConfigKey {\n return CONFIG_KEYS.includes(key as ConfigKey);\n}\n\n/** 返回配置文件在磁盘上的路径(用于 debug) */\nexport function getConfigPath(): string {\n return store.path;\n}\n","import pc from \"picocolors\";\n\n/**\n * 统一的控制台日志工具,基于 picocolors 着色。\n * 所有输出走 stderr,stdout 留给管道场景。\n */\n\nexport function info(msg: string): void {\n console.error(pc.blue(\"ℹ\") + \" \" + msg);\n}\n\nexport function success(msg: string): void {\n console.error(pc.green(\"✔\") + \" \" + msg);\n}\n\nexport function warn(msg: string): void {\n console.error(pc.yellow(\"⚠\") + \" \" + pc.yellow(msg));\n}\n\nexport function error(msg: string): void {\n console.error(pc.red(\"✖\") + \" \" + pc.red(msg));\n}\n\nexport function dim(msg: string): void {\n console.error(pc.dim(msg));\n}\n\nexport function bold(msg: string): string {\n return pc.bold(msg);\n}\n\nexport function label(key: string, value: string): void {\n console.error(` ${pc.cyan(key)}: ${value}`);\n}\n","import path from 'node:path';\nimport { Command } from 'commander';\nimport { generateInfographicDSL, retryWithCorrection, MAX_RETRIES } from '../core/ai.js';\nimport { renderDSLToSVG, writeSVGFile, resolveOutputPath } from '../core/render.js';\nimport * as log from '../utils/logger.js';\nimport {\n startSpinner,\n succeedSpinner,\n failSpinner,\n updateSpinner,\n} from '../utils/spinner.js';\n\n/**\n * 注册 `generate` 子命令。\n *\n * 用法示例:\n * infographic-gen generate \"帮我画一个软件开发流程图\" -o result.svg\n */\nexport function registerGenerateCommand(program: Command): void {\n program\n .command('generate')\n .alias('gen')\n .description('根据自然语言描述生成 SVG 信息图')\n .argument('<prompt>', '描述你想要生成的信息图内容')\n .option('-o, --output <path>', '输出 SVG 文件路径', 'infographic-output.svg')\n .action(async (prompt: string, opts: { output: string }) => {\n await handleGenerate(prompt, opts.output);\n });\n}\n\n/**\n * 生成命令的核心处理逻辑。\n *\n * 流程:\n * 1. 调用 LLM 生成 DSL\n * 2. 调用 SSR 渲染为 SVG\n * 3. 如果渲染失败,自动进入自我修正循环(最多 MAX_RETRIES 次)\n * 4. 写入 SVG 文件\n */\nasync function handleGenerate(prompt: string, outputOption: string): Promise<void> {\n const outputPath = resolveOutputPath(outputOption);\n\n log.info(`目标输出:${path.resolve(outputPath)}`);\n startSpinner('正在调用 AI 生成信息图语法...');\n\n let syntax: string;\n try {\n syntax = await generateInfographicDSL(prompt);\n } catch (err) {\n failSpinner('AI 调用失败');\n log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n updateSpinner('正在渲染 SVG...');\n\n // ─── 渲染 + 自我修正循环 ───────────────────────────────────────────\n let svgContent: string | null = null;\n let lastError = '';\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n svgContent = await renderDSLToSVG(syntax);\n break; // 渲染成功,跳出循环\n } catch (err) {\n lastError = err instanceof Error ? err.message : String(err);\n\n if (attempt < MAX_RETRIES) {\n // 还有重试机会 → 自我修正\n try {\n syntax = await retryWithCorrection(syntax, lastError, prompt, attempt + 1);\n updateSpinner('正在重新渲染 SVG...');\n } catch (retryErr) {\n failSpinner('自我修正失败');\n log.error(retryErr instanceof Error ? retryErr.message : String(retryErr));\n process.exit(1);\n }\n }\n }\n }\n\n if (!svgContent) {\n failSpinner('渲染最终失败');\n log.error(`经过 ${MAX_RETRIES} 次自我修正仍无法生成可渲染的信息图。`);\n log.error(`最后一次错误:${lastError}`);\n log.dim('生成的 DSL 语法如下(供 debug 参考):');\n console.error(syntax);\n process.exit(1);\n }\n\n // ─── 渲染成功,写入文件 ─────────────────────────────────────────────\n try {\n await writeSVGFile(outputPath, svgContent);\n } catch (err) {\n failSpinner('文件写入失败');\n log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n succeedSpinner(`信息图已生成!`);\n log.success(`SVG 已保存至:${path.resolve(outputPath)}`);\n log.dim('可直接在浏览器中打开 SVG 文件查看效果。');\n}\n","import OpenAI from \"openai\";\nimport { getLLMConfig } from \"../config/index.js\";\nimport {\n INFOGRAPHIC_CREATOR_SYSTEM_PROMPT,\n SELF_CORRECTION_PROMPT_TEMPLATE,\n} from \"./prompts.js\";\nimport * as log from \"../utils/logger.js\";\nimport { updateSpinner } from \"../utils/spinner.js\";\n\n/** LLM 请求返回的结果 */\nexport interface LLMResult {\n /** 生成的 DSL 语法文本 */\n syntax: string;\n /** 总共重试了几次(0 = 一次成功) */\n attempts: number;\n}\n\n/** 最大自我修正重试次数 */\nconst MAX_RETRIES = 3;\n\n/**\n * 创建一个懒初始化的 OpenAI 客户端。\n * 通过覆盖 baseURL / apiKey 兼容 DeepSeek、阿里云百炼等平台。\n */\nfunction createClient(): OpenAI {\n const { apiKey, baseUrl } = getLLMConfig();\n\n if (!apiKey) {\n throw new Error(\n \"尚未配置 API Key。请先运行:infographic-gen config set apiKey <YOUR_KEY>\",\n );\n }\n\n return new OpenAI({\n apiKey,\n baseURL: baseUrl,\n });\n}\n\n/**\n * 向 LLM 发送请求,获取信息图 DSL。\n *\n * @param userPrompt 用户的自然语言描述\n * @returns LLM 返回的纯 DSL 文本\n */\nasync function callLLM(\n client: OpenAI,\n model: string,\n messages: OpenAI.ChatCompletionMessageParam[],\n): Promise<string> {\n const response = await client.chat.completions.create({\n model,\n messages,\n temperature: 0.7,\n max_tokens: 4096,\n });\n\n const content = response.choices[0]?.message?.content;\n if (!content) {\n throw new Error(\"LLM 返回了空内容\");\n }\n\n return cleanDSL(content);\n}\n\n/**\n * 清理 LLM 返回的文本,去除可能的 Markdown 代码块标记等噪声。\n */\nfunction cleanDSL(raw: string): string {\n let cleaned = raw.trim();\n\n // 去掉可能包裹的 ```xxx ... ``` 代码块\n const codeBlockMatch = cleaned.match(/^```[\\w]*\\n?([\\s\\S]*?)```$/);\n if (codeBlockMatch) {\n cleaned = codeBlockMatch[1].trim();\n }\n\n // 确保以 infographic 开头\n const infographicIndex = cleaned.indexOf(\"infographic \");\n if (infographicIndex > 0) {\n cleaned = cleaned.slice(infographicIndex);\n }\n\n return cleaned;\n}\n\n/**\n * 带自我修正机制的 AI 生成入口。\n *\n * 流程:\n * 1. 将用户 Prompt + 系统提示词发给 LLM,获取 DSL。\n * 2. 调用方(generate 命令)会尝试渲染。如果渲染失败,调用 retryWithCorrection。\n * 3. 最多重试 MAX_RETRIES 次。\n *\n * @param userPrompt 用户输入的自然语言\n * @returns 生成的 DSL 语法\n */\nexport async function generateInfographicDSL(\n userPrompt: string,\n): Promise<string> {\n const client = createClient();\n const { modelName } = getLLMConfig();\n\n const messages: OpenAI.ChatCompletionMessageParam[] = [\n { role: \"system\", content: INFOGRAPHIC_CREATOR_SYSTEM_PROMPT },\n { role: \"user\", content: userPrompt },\n ];\n\n return callLLM(client, modelName, messages);\n}\n\n/**\n * 自我修正:当 DSL 渲染失败时,把错误信息反馈给 LLM 要求修正。\n *\n * @param originalSyntax 上一次生成的 DSL\n * @param errorMessage 渲染报错信息\n * @param userPrompt 用户原始需求\n * @param attempt 当前第几次重试(从 1 开始)\n * @returns 修正后的 DSL\n */\nexport async function retryWithCorrection(\n originalSyntax: string,\n errorMessage: string,\n userPrompt: string,\n attempt: number,\n): Promise<string> {\n if (attempt > MAX_RETRIES) {\n throw new Error(\n `已重试 ${MAX_RETRIES} 次仍然无法生成可渲染的信息图。最后一次错误:${errorMessage}`,\n );\n }\n\n updateSpinner(`AI 正在自我修正(第 ${attempt}/${MAX_RETRIES} 次)...`);\n log.warn(`渲染失败,正在自动修正(第 ${attempt}/${MAX_RETRIES} 次)...`);\n\n const client = createClient();\n const { modelName } = getLLMConfig();\n\n const correctionMessage = SELF_CORRECTION_PROMPT_TEMPLATE.replace(\n \"{error}\",\n errorMessage,\n ).replace(\"{syntax}\", originalSyntax);\n\n const messages: OpenAI.ChatCompletionMessageParam[] = [\n { role: \"system\", content: INFOGRAPHIC_CREATOR_SYSTEM_PROMPT },\n { role: \"user\", content: userPrompt },\n { role: \"assistant\", content: originalSyntax },\n { role: \"user\", content: correctionMessage },\n ];\n\n return callLLM(client, modelName, messages);\n}\n\n/** 导出最大重试次数常量供外部使用 */\nexport { MAX_RETRIES };\n","/**\n * ⭐ 硬编码的系统提示词常量。\n *\n * 直接内嵌在代码中,确保 CLI 开箱即用,无需读取本地磁盘文件。\n * 内容基于 @antv/infographic 的 .skills/infographic-creator/SKILL.md 整理。\n */\n\n// ─── 公共:AntV Infographic 语法规范 ────────────────────────────────\n\nconst SYNTAX_SPEC = `\n## AntV Infographic 语法\n\nAntV Infographic 语法是一种自定义的 DSL,用于描述信息图渲染配置。它使用缩进描述信息,具有较强鲁棒性,便于 AI 流式输出并渲染信息图。主要包含以下信息:\n\n1. template:用模板表达文字信息结构。\n2. data:信息图数据,包含 title、desc、数据项等。数据项通常包含 label、desc、icon 等字段。\n3. theme:主题包含 palette、font 等样式配置。\n\n例如:\n\\`\\`\\`\ninfographic list-row-horizontal-icon-arrow\ndata\n title Title\n desc Description\n lists\n - label Label\n value 12.5\n desc Explanation\n icon document text\ntheme\n palette #3b82f6 #8b5cf6 #f97316\n\\`\\`\\`\n\n### 语法规范\n\n• 第一行必须是 \\`infographic <template-name>\\`,模板从下方可用模板列表中选择。\n• 使用 \\`data\\` / \\`theme\\` 块,块内用两个空格缩进。\n• 键值对使用「键 空格 值」;数组使用 \\`-\\` 作为条目前缀。\n• icon 使用图标关键词(如 \\`star fill\\`)。\n• \\`data\\` 应包含 title/desc + 模板对应的主数据字段(不一定是 \\`items\\`)。\n• 主数据字段选择(只用一个,避免混用):\n - \\`list-*\\` → \\`lists\\`\n - \\`sequence-*\\` → \\`sequences\\`(可选 \\`order asc|desc\\`)\n - \\`compare-*\\` → \\`compares\\`(支持 \\`children\\` 分组对比),可包含多个对比项\n - \\`hierarchy-structure\\` → \\`items\\`(每一项对应一个独立层级,每一层级可以包含子项,最多可嵌套 3 层)\n - \\`hierarchy-*\\` → 单一 \\`root\\`(树结构,通过 \\`children\\` 嵌套)\n - \\`relation-*\\` → \\`nodes\\` + \\`relations\\`;简单关系图可省略 \\`nodes\\`,在 relations 中用箭头语法\n - \\`chart-*\\` → \\`values\\`(数值统计,可选 \\`category\\`)\n - 不确定时再用 \\`items\\` 兜底\n\n• \\`compare-binary-*\\` / \\`compare-hierarchy-left-right-*\\` 二元模板:必须两个根节点,所有对比项挂在这两个根节点的 children\n• \\`hierarchy-*\\`:使用单一 \\`root\\`,通过 \\`children\\` 嵌套(不要重复 \\`root\\`)\n• \\`theme\\` 用于自定义主题(palette、font 等)\n\n例如:暗色主题 + 自定义配色\n\\`\\`\\`\ninfographic list-row-simple-horizontal-arrow\ntheme dark\n palette\n - #61DDAA\n - #F6BD16\n - #F08BB4\n\\`\\`\\`\n\n• 使用 \\`theme.base.text.font-family\\` 指定字体,如手写风格 \\`851tegakizatsu\\`\n• 使用 \\`theme.stylize\\` 选择内置风格并传参。常见风格:\n - \\`rough\\`:手绘效果\n - \\`pattern\\`:图案填充\n - \\`linear-gradient\\` / \\`radial-gradient\\`:线性/径向渐变\n\n例如:手绘风格(rough)\n\\`\\`\\`\ninfographic list-row-simple-horizontal-arrow\ntheme\n stylize rough\n base\n text\n font-family 851tegakizatsu\n\\`\\`\\`\n`.trim();\n\n// ─── 数据语法示例 ───────────────────────────────────────────────────\n\nconst DATA_EXAMPLES = `\n### 数据语法示例\n\n• list-* 模版\n\\`\\`\\`\ninfographic list-grid-badge-card\ndata\n title Feature List\n lists\n - label Fast\n icon flash fast\n - label Secure\n icon secure shield check\n\\`\\`\\`\n\n• sequence-* 模版\n\\`\\`\\`\ninfographic sequence-steps-simple\ndata\n sequences\n - label Step 1\n - label Step 2\n - label Step 3\n order asc\n\\`\\`\\`\n\n• hierarchy-* 模版\n\\`\\`\\`\ninfographic hierarchy-structure\ndata\n root\n label Company\n children\n - label Dept A\n - label Dept B\n\\`\\`\\`\n\n• compare-* 模版\n\\`\\`\\`\ninfographic compare-swot\ndata\n compares\n - label Strengths\n children\n - label Strong brand\n - label Loyal users\n - label Weaknesses\n children\n - label High cost\n - label Slow release\n\\`\\`\\`\n\n四象限图\n\\`\\`\\`\ninfographic compare-quadrant-quarter-simple-card\ndata\n compares\n - label High Impact & Low Effort\n - label High Impact & High Effort\n - label Low Impact & Low Effort\n - label Low Impact & High Effort\n\\`\\`\\`\n\n• chart-* 模版\n\\`\\`\\`\ninfographic chart-column-simple\ndata\n values\n - label Visits\n value 1280\n - label Conversion\n value 12.4\n\\`\\`\\`\n\n• relation-* 模版\n边标签写法:A -label-> B 或 A -->|label| B\n\\`\\`\\`\ninfographic relation-dagre-flow-tb-simple-circle-node\ndata\n nodes\n - id A\n label Node A\n - id B\n label Node B\n relations\n A - approves -> B\n A -->|blocks| B\n\\`\\`\\`\n\n• 兜底 items 示例\n\\`\\`\\`\ninfographic list-row-horizontal-icon-arrow\ndata\n items\n - label Item A\n desc Description\n icon sun\n - label Item B\n desc Description\n icon moon\n\\`\\`\\`\n`.trim();\n\n// ─── 可用模板列表 ───────────────────────────────────────────────────\n\nconst AVAILABLE_TEMPLATES = `\n### 可用模板\n\n• chart-bar-plain-text\n• chart-column-simple\n• chart-line-plain-text\n• chart-pie-compact-card\n• chart-pie-donut-pill-badge\n• chart-pie-donut-plain-text\n• chart-pie-plain-text\n• chart-wordcloud\n• compare-binary-horizontal-badge-card-arrow\n• compare-binary-horizontal-simple-fold\n• compare-binary-horizontal-underline-text-vs\n• compare-hierarchy-left-right-circle-node-pill-badge\n• compare-quadrant-quarter-circular\n• compare-quadrant-quarter-simple-card\n• compare-swot\n• hierarchy-mindmap-branch-gradient-capsule-item\n• hierarchy-mindmap-level-gradient-compact-card\n• hierarchy-structure\n• hierarchy-tree-curved-line-rounded-rect-node\n• hierarchy-tree-tech-style-badge-card\n• hierarchy-tree-tech-style-capsule-item\n• list-column-done-list\n• list-column-simple-vertical-arrow\n• list-column-vertical-icon-arrow\n• list-grid-badge-card\n• list-grid-candy-card-lite\n• list-grid-ribbon-card\n• list-row-horizontal-icon-arrow\n• list-sector-plain-text\n• list-waterfall-badge-card\n• list-waterfall-compact-card\n• list-zigzag-down-compact-card\n• list-zigzag-down-simple\n• list-zigzag-up-compact-card\n• list-zigzag-up-simple\n• relation-dagre-flow-tb-animated-badge-card\n• relation-dagre-flow-tb-animated-simple-circle-node\n• relation-dagre-flow-tb-badge-card\n• relation-dagre-flow-tb-simple-circle-node\n• sequence-ascending-stairs-3d-underline-text\n• sequence-ascending-steps\n• sequence-circular-simple\n• sequence-color-snake-steps-horizontal-icon-line\n• sequence-cylinders-3d-simple\n• sequence-filter-mesh-simple\n• sequence-funnel-simple\n• sequence-horizontal-zigzag-underline-text\n• sequence-mountain-underline-text\n• sequence-pyramid-simple\n• sequence-roadmap-vertical-plain-text\n• sequence-roadmap-vertical-simple\n• sequence-snake-steps-compact-card\n• sequence-snake-steps-simple\n• sequence-snake-steps-underline-text\n• sequence-stairs-front-compact-card\n• sequence-stairs-front-pill-badge\n• sequence-timeline-rounded-rect-node\n• sequence-timeline-simple\n• sequence-zigzag-pucks-3d-simple\n• sequence-zigzag-steps-underline-text\n\n模板选择建议:\n• 严格顺序(流程/步骤/发展趋势)→ sequence-*\n - 时间线 → sequence-timeline-*\n - 阶梯图 → sequence-stairs-*\n - 路线图 → sequence-roadmap-vertical-*\n - 折线路径 → sequence-zigzag-*\n - 环形进度 → sequence-circular-simple\n - 彩色蛇形步骤 → sequence-color-snake-steps-*\n - 金字塔 → sequence-pyramid-simple\n• 观点列举 → list-row-* 或 list-column-*\n• 二元对比(利弊)→ compare-binary-*\n• SWOT → compare-swot\n• 层级结构(树图)→ hierarchy-tree-*\n• 数据图表 → chart-*\n• 象限分析 → quadrant-*\n• 网格列表(要点)→ list-grid-*\n• 关系展示 → relation-*\n• 词云 → chart-wordcloud\n• 思维导图 → hierarchy-mindmap-*\n`.trim();\n\n// ─── 完整示例 ───────────────────────────────────────────────────────\n\nconst FULL_EXAMPLE = `\n### 完整示例\n\n绘制互联网技术演进信息图:\n\\`\\`\\`\ninfographic list-row-horizontal-icon-arrow\ndata\n title Internet Technology Evolution\n desc From Web 1.0 to AI era, key milestones\n lists\n - time 1991\n label Web 1.0\n desc Tim Berners-Lee published the first website, opening the Internet era\n icon web\n - time 2004\n label Web 2.0\n desc Social media and user-generated content become mainstream\n icon account multiple\n - time 2007\n label Mobile\n desc iPhone released, smartphone changes the world\n icon cellphone\n - time 2015\n label Cloud Native\n desc Containerization and microservices architecture are widely used\n icon cloud\n - time 2020\n label Low Code\n desc Visual development lowers the technology threshold\n icon application brackets\n - time 2023\n label AI Large Model\n desc ChatGPT ignites the generative AI revolution\n icon brain\n\\`\\`\\`\n`.trim();\n\n// ─── 导出:信息图创建者系统提示词 ───────────────────────────────────\n\n/**\n * 信息图创建者的完整 System Prompt。\n * 用于指导 LLM 根据用户自然语言需求,生成合法的 AntV Infographic DSL 语法。\n */\nexport const INFOGRAPHIC_CREATOR_SYSTEM_PROMPT = `\n你是一位专业的信息图设计专家。你的任务是根据用户的需求,生成 AntV Infographic DSL 语法来创建精美的信息图。\n\n信息图(Infographic)将数据、信息与知识转化为可感知的视觉语言。它结合视觉设计与数据可视化,用直观符号压缩复杂信息,帮助受众快速理解并记住要点。\n\nInfographic = Information Structure + Visual Expression\n\n你需要严格遵守以下规范来生成 AntV Infographic 语法:\n\n${SYNTAX_SPEC}\n\n${DATA_EXAMPLES}\n\n${AVAILABLE_TEMPLATES}\n\n${FULL_EXAMPLE}\n\n## 重要约束\n\n1. **只输出纯 DSL 语法**:不要输出任何 Markdown 代码块标记(如 \\\\\\`\\\\\\`\\\\\\`)、解释性文字、JSON 或其他格式。直接输出以 \\`infographic <template-name>\\` 开头的 DSL 文本。\n2. **必须尊重用户输入语言**:如果用户使用中文描述需求,DSL 中所有文本内容(title、desc、label 等)也必须使用中文。\n3. **选择最合适的模板**:根据用户需求的信息结构(列表、流程、对比、层级等)选择最匹配的模板。\n4. **数据完整性**:确保生成的数据结构完整,包含 title、desc 以及与模板匹配的主数据字段。\n5. **配色和主题**:除非用户特别要求,否则使用一组美观且协调的默认配色。\n`.trim();\n\n/**\n * 自我修正提示词模板。\n * 当 SSR 渲染失败时,将报错信息注入后发给 LLM 进行修正。\n */\nexport const SELF_CORRECTION_PROMPT_TEMPLATE = `\n之前你生成的 AntV Infographic DSL 语法在渲染时出错了。\n\n报错信息:\n{error}\n\n之前生成的语法:\n{syntax}\n\n请修正语法并重新输出。要求:\n1. 只输出修正后的纯 DSL 语法,不要添加任何解释或 Markdown 格式。\n2. 确保第一行是 \\`infographic <template-name>\\`。\n3. 确保数据结构符合所选模板的规范。\n4. 修复导致错误的具体问题。\n`.trim();\n","import ora, { type Ora } from \"ora\";\n\n/**\n * 终端 Loading 动画封装。\n * 提供 start / succeed / fail / update 等便捷方法。\n */\n\nlet currentSpinner: Ora | null = null;\n\nexport function startSpinner(text: string): Ora {\n // 如果之前有未关闭的 spinner,先停掉\n if (currentSpinner?.isSpinning) {\n currentSpinner.stop();\n }\n currentSpinner = ora({ text, stream: process.stderr }).start();\n return currentSpinner;\n}\n\nexport function succeedSpinner(text?: string): void {\n currentSpinner?.succeed(text);\n currentSpinner = null;\n}\n\nexport function failSpinner(text?: string): void {\n currentSpinner?.fail(text);\n currentSpinner = null;\n}\n\nexport function updateSpinner(text: string): void {\n if (currentSpinner) {\n currentSpinner.text = text;\n }\n}\n\nexport function stopSpinner(): void {\n currentSpinner?.stop();\n currentSpinner = null;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { renderToString } from \"@antv/infographic/ssr\";\n\n/**\n * 渲染结果\n */\nexport interface RenderResult {\n /** 生成的 SVG 字符串 */\n svg: string;\n}\n\n/**\n * 使用 @antv/infographic SSR 将 DSL 语法渲染为 SVG 字符串。\n *\n * @param syntax AntV Infographic DSL 语法文本\n * @returns SVG 字符串\n * @throws 渲染失败时抛出带有详细错误信息的 Error\n */\nexport async function renderDSLToSVG(syntax: string): Promise<string> {\n try {\n const svgString = await renderToString(syntax);\n if (!svgString || svgString.trim().length === 0) {\n throw new Error(\"renderToString 返回了空的 SVG 内容\");\n }\n return svgString;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`SSR 渲染失败: ${message}`);\n }\n}\n\n/**\n * 将 SVG 字符串写入指定路径。\n * 自动创建所需的中间目录。\n *\n * @param outputPath 输出文件路径\n * @param svgContent SVG 字符串内容\n */\nexport async function writeSVGFile(\n outputPath: string,\n svgContent: string,\n): Promise<void> {\n const absolutePath = path.resolve(outputPath);\n const dir = path.dirname(absolutePath);\n\n // 确保输出目录存在\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absolutePath, svgContent, \"utf-8\");\n}\n\n/**\n * 根据用户输入的输出路径,补全默认值。\n * 如果用户未指定,默认为当前目录下的 infographic-output.svg。\n */\nexport function resolveOutputPath(userOutput?: string): string {\n if (userOutput) {\n // 确保扩展名是 .svg\n if (!userOutput.endsWith(\".svg\")) {\n return userOutput + \".svg\";\n }\n return userOutput;\n }\n return path.resolve(process.cwd(), \"infographic-output.svg\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAF9B;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA,QAAI,IAAI,WAAW,CAAC;AAApB,QAAuB,OAAO,EAAE,QAAQ,CAAC;AAAzC,QAA4C,MAAM,EAAE,OAAO,CAAC;AAC5D,QAAI,mBACH,EAAE,CAAC,CAAC,IAAI,YAAY,KAAK,SAAS,YAAY,OAC7C,CAAC,CAAC,IAAI,eAAe,KAAK,SAAS,SAAS,KAAK,EAAE,aAAa,YAAa,EAAE,UAAU,CAAC,GAAG,SAAS,IAAI,SAAS,UAAW,CAAC,CAAC,IAAI;AAEtI,QAAI,YAAY,CAAC,MAAM,OAAO,UAAU,SACvC,WAAS;AACR,UAAI,SAAS,KAAK,OAAO,QAAQ,OAAO,QAAQ,OAAO,KAAK,MAAM;AAClE,aAAO,CAAC,QAAQ,OAAO,aAAa,QAAQ,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,SAAS;AAAA,IAC9F;AAED,QAAI,eAAe,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrD,UAAI,SAAS,IAAI,SAAS;AAC1B,SAAG;AACF,kBAAU,OAAO,UAAU,QAAQ,KAAK,IAAI;AAC5C,iBAAS,QAAQ,MAAM;AACvB,gBAAQ,OAAO,QAAQ,OAAO,MAAM;AAAA,MACrC,SAAS,CAAC;AACV,aAAO,SAAS,OAAO,UAAU,MAAM;AAAA,IACxC;AAEA,QAAI,eAAe,CAAC,UAAU,qBAAqB;AAClD,UAAI,IAAI,UAAU,YAAY,MAAM;AACpC,aAAO;AAAA,QACN,kBAAkB;AAAA,QAClB,OAAO,EAAE,WAAW,SAAS;AAAA,QAC7B,MAAM,EAAE,WAAW,YAAY,iBAAiB;AAAA,QAChD,KAAK,EAAE,WAAW,YAAY,iBAAiB;AAAA,QAC/C,QAAQ,EAAE,WAAW,UAAU;AAAA,QAC/B,WAAW,EAAE,WAAW,UAAU;AAAA,QAClC,SAAS,EAAE,WAAW,UAAU;AAAA,QAChC,QAAQ,EAAE,WAAW,UAAU;AAAA,QAC/B,eAAe,EAAE,WAAW,UAAU;AAAA,QAEtC,OAAO,EAAE,YAAY,UAAU;AAAA,QAC/B,KAAK,EAAE,YAAY,UAAU;AAAA,QAC7B,OAAO,EAAE,YAAY,UAAU;AAAA,QAC/B,QAAQ,EAAE,YAAY,UAAU;AAAA,QAChC,MAAM,EAAE,YAAY,UAAU;AAAA,QAC9B,SAAS,EAAE,YAAY,UAAU;AAAA,QACjC,MAAM,EAAE,YAAY,UAAU;AAAA,QAC9B,OAAO,EAAE,YAAY,UAAU;AAAA,QAC/B,MAAM,EAAE,YAAY,UAAU;AAAA,QAE9B,SAAS,EAAE,YAAY,UAAU;AAAA,QACjC,OAAO,EAAE,YAAY,UAAU;AAAA,QAC/B,SAAS,EAAE,YAAY,UAAU;AAAA,QACjC,UAAU,EAAE,YAAY,UAAU;AAAA,QAClC,QAAQ,EAAE,YAAY,UAAU;AAAA,QAChC,WAAW,EAAE,YAAY,UAAU;AAAA,QACnC,QAAQ,EAAE,YAAY,UAAU;AAAA,QAChC,SAAS,EAAE,YAAY,UAAU;AAAA,QAEjC,aAAa,EAAE,YAAY,UAAU;AAAA,QACrC,WAAW,EAAE,YAAY,UAAU;AAAA,QACnC,aAAa,EAAE,YAAY,UAAU;AAAA,QACrC,cAAc,EAAE,YAAY,UAAU;AAAA,QACtC,YAAY,EAAE,YAAY,UAAU;AAAA,QACpC,eAAe,EAAE,YAAY,UAAU;AAAA,QACvC,YAAY,EAAE,YAAY,UAAU;AAAA,QACpC,aAAa,EAAE,YAAY,UAAU;AAAA,QAErC,eAAe,EAAE,aAAa,UAAU;AAAA,QACxC,aAAa,EAAE,aAAa,UAAU;AAAA,QACtC,eAAe,EAAE,aAAa,UAAU;AAAA,QACxC,gBAAgB,EAAE,aAAa,UAAU;AAAA,QACzC,cAAc,EAAE,aAAa,UAAU;AAAA,QACvC,iBAAiB,EAAE,aAAa,UAAU;AAAA,QAC1C,cAAc,EAAE,aAAa,UAAU;AAAA,QACvC,eAAe,EAAE,aAAa,UAAU;AAAA,MACzC;AAAA,IACD;AAEA,WAAO,UAAU,aAAa;AAC9B,WAAO,QAAQ,eAAe;AAAA;AAAA;;;AC1E9B;AAAA,SAAS,eAAe;;;ACAxB;;;ACAA;AAAA,OAAO,UAAU;AAuBV,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,gBAA2C;AAAA,EACtD,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AACb;AAGA,IAAM,WAAyB;AAAA,EAC7B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AACb;AAKA,IAAM,QAAQ,IAAI,KAAmB;AAAA,EACnC,aAAa;AAAA,EACb,UAAU;AACZ,CAAC;AAGM,SAAS,UAA+B,KAAgB;AAC7D,SAAO,MAAM,IAAI,GAAG;AACtB;AAGO,SAAS,UAA+B,KAAQ,OAAqB;AAC1E,QAAM,IAAI,KAAK,KAAK;AACtB;AAGO,SAAS,aAAkC,KAAc;AAC9D,QAAM,OAAO,GAAG;AAClB;AAGO,SAAS,eAA0B;AACxC,SAAO;AAAA,IACL,QAAQ,UAAU,QAAQ;AAAA,IAC1B,SAAS,UAAU,SAAS;AAAA,IAC5B,UAAU,UAAU,UAAU;AAAA,IAC9B,WAAW,UAAU,WAAW;AAAA,EAClC;AACF;AAGO,SAAS,eAA0C;AACxD,SAAO;AAAA,IACL,QAAQ,UAAU,QAAQ;AAAA,IAC1B,SAAS,UAAU,SAAS;AAAA,IAC5B,UAAU,UAAU,UAAU;AAAA,IAC9B,WAAW,UAAU,WAAW;AAAA,EAClC;AACF;AAGO,SAAS,iBAAiB,KAA+B;AAC9D,SAAO,YAAY,SAAS,GAAgB;AAC9C;AAGO,SAAS,gBAAwB;AACtC,SAAO,MAAM;AACf;;;AClGA;AAAA,wBAAe;AAOR,SAAS,KAAK,KAAmB;AACtC,UAAQ,MAAM,kBAAAA,QAAG,KAAK,QAAG,IAAI,MAAM,GAAG;AACxC;AAEO,SAAS,QAAQ,KAAmB;AACzC,UAAQ,MAAM,kBAAAA,QAAG,MAAM,QAAG,IAAI,MAAM,GAAG;AACzC;AAEO,SAAS,KAAK,KAAmB;AACtC,UAAQ,MAAM,kBAAAA,QAAG,OAAO,QAAG,IAAI,MAAM,kBAAAA,QAAG,OAAO,GAAG,CAAC;AACrD;AAEO,SAAS,MAAM,KAAmB;AACvC,UAAQ,MAAM,kBAAAA,QAAG,IAAI,QAAG,IAAI,MAAM,kBAAAA,QAAG,IAAI,GAAG,CAAC;AAC/C;AAEO,SAAS,IAAI,KAAmB;AACrC,UAAQ,MAAM,kBAAAA,QAAG,IAAI,GAAG,CAAC;AAC3B;AAMO,SAAS,MAAM,KAAa,OAAqB;AACtD,UAAQ,MAAM,KAAK,kBAAAC,QAAG,KAAK,GAAG,CAAC,KAAK,KAAK,EAAE;AAC7C;;;AFXO,SAAS,sBAAsBC,UAAwB;AAC5D,QAAM,YAAYA,SACf,QAAQ,QAAQ,EAChB,YAAY,yFAA4C;AAG3D,YACG,QAAQ,mBAAmB,EAC3B,YAAY,gCAAO,EACnB,OAAO,CAAC,KAAa,UAAkB;AACtC,QAAI,CAAC,iBAAiB,GAAG,GAAG;AAC1B,MAAI,MAAM,yCAAW,GAAG,kCAAS,YAAY,KAAK,IAAI,CAAC,EAAE;AACzD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,cAAU,KAAK,KAAK;AACpB,IAAI,QAAQ,GAAG,cAAc,GAAG,CAAC,qBAAM;AAAA,EACzC,CAAC;AAGH,YACG,QAAQ,WAAW,EACnB,YAAY,4CAAS,EACrB,OAAO,CAAC,QAAgB;AACvB,QAAI,CAAC,iBAAiB,GAAG,GAAG;AAC1B,MAAI,MAAM,yCAAW,GAAG,kCAAS,YAAY,KAAK,IAAI,CAAC,EAAE;AACzD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,MAAM,UAAU,GAAG;AACzB,QAAI,CAAC,KAAK;AACR,MAAI,KAAK,GAAG,cAAc,GAAG,CAAC,2BAAO;AAAA,IACvC,OAAO;AAEL,YAAM,UAAU,QAAQ,WAAW,WAAW,GAAG,IAAI;AACrD,MAAI,MAAM,cAAc,GAAG,GAAG,OAAO;AAAA,IACvC;AAAA,EACF,CAAC;AAGH,YACG,QAAQ,MAAM,EACd,YAAY,4CAAS,EACrB,OAAO,MAAM;AACZ,UAAM,MAAM,aAAa;AACzB,IAAI,KAAK,gCAAO;AAChB,eAAW,KAAK,aAAa;AAC3B,YAAM,MAAM,IAAI,CAAC;AACjB,YAAM,UACJ,MAAM,YAAY,MAAM,WAAW,GAAG,IAAI,OAAO;AACnD,MAAI,MAAM,cAAc,CAAC,GAAG,OAAO;AAAA,IACrC;AACA,IAAI,IAAI,2CAAa,cAAc,CAAC,EAAE;AAAA,EACxC,CAAC;AAGH,YACG,QAAQ,cAAc,EACtB,YAAY,0EAAc,EAC1B,OAAO,CAAC,QAAgB;AACvB,QAAI,CAAC,iBAAiB,GAAG,GAAG;AAC1B,MAAI,MAAM,yCAAW,GAAG,kCAAS,YAAY,KAAK,IAAI,CAAC,EAAE;AACzD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,iBAAa,GAAgB;AAC7B,IAAI,QAAQ,GAAG,cAAc,GAAgB,CAAC,6CAAU;AAAA,EAC1D,CAAC;AAGH,YACG,QAAQ,MAAM,EACd,YAAY,kDAAU,EACtB,OAAO,MAAM;AACZ,YAAQ,IAAI,cAAc,CAAC;AAAA,EAC7B,CAAC;AACL;AAKA,SAAS,WAAW,KAAqB;AACvC,MAAI,IAAI,UAAU,EAAG,QAAO;AAC5B,SAAO,IAAI,MAAM,GAAG,CAAC,IAAI,SAAS,IAAI,MAAM,EAAE;AAChD;;;AGvGA;AAAA,OAAOC,WAAU;;;ACAjB;AAAA,OAAO,YAAY;;;ACAnB;AASA,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsElB,KAAK;AAIP,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqGpB,KAAK;AAIP,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmF1B,KAAK;AAIP,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCnB,KAAK;AAQA,IAAM,oCAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS/C,WAAW;AAAA;AAAA,EAEX,aAAa;AAAA;AAAA,EAEb,mBAAmB;AAAA;AAAA,EAEnB,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASZ,KAAK;AAMA,IAAM,kCAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc7C,KAAK;;;AC1WP;AAAA,OAAO,SAAuB;AAO9B,IAAI,iBAA6B;AAE1B,SAAS,aAAa,MAAmB;AAE9C,MAAI,gBAAgB,YAAY;AAC9B,mBAAe,KAAK;AAAA,EACtB;AACA,mBAAiB,IAAI,EAAE,MAAM,QAAQ,QAAQ,OAAO,CAAC,EAAE,MAAM;AAC7D,SAAO;AACT;AAEO,SAAS,eAAe,MAAqB;AAClD,kBAAgB,QAAQ,IAAI;AAC5B,mBAAiB;AACnB;AAEO,SAAS,YAAY,MAAqB;AAC/C,kBAAgB,KAAK,IAAI;AACzB,mBAAiB;AACnB;AAEO,SAAS,cAAc,MAAoB;AAChD,MAAI,gBAAgB;AAClB,mBAAe,OAAO;AAAA,EACxB;AACF;;;AFdA,IAAM,cAAc;AAMpB,SAAS,eAAuB;AAC9B,QAAM,EAAE,QAAQ,QAAQ,IAAI,aAAa;AAEzC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,IAAI,OAAO;AAAA,IAChB;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AACH;AAQA,eAAe,QACb,QACA,OACA,UACiB;AACjB,QAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IACpD;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,EACd,CAAC;AAED,QAAM,UAAU,SAAS,QAAQ,CAAC,GAAG,SAAS;AAC9C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,0CAAY;AAAA,EAC9B;AAEA,SAAO,SAAS,OAAO;AACzB;AAKA,SAAS,SAAS,KAAqB;AACrC,MAAI,UAAU,IAAI,KAAK;AAGvB,QAAM,iBAAiB,QAAQ,MAAM,4BAA4B;AACjE,MAAI,gBAAgB;AAClB,cAAU,eAAe,CAAC,EAAE,KAAK;AAAA,EACnC;AAGA,QAAM,mBAAmB,QAAQ,QAAQ,cAAc;AACvD,MAAI,mBAAmB,GAAG;AACxB,cAAU,QAAQ,MAAM,gBAAgB;AAAA,EAC1C;AAEA,SAAO;AACT;AAaA,eAAsB,uBACpB,YACiB;AACjB,QAAM,SAAS,aAAa;AAC5B,QAAM,EAAE,UAAU,IAAI,aAAa;AAEnC,QAAM,WAAgD;AAAA,IACpD,EAAE,MAAM,UAAU,SAAS,kCAAkC;AAAA,IAC7D,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,EACtC;AAEA,SAAO,QAAQ,QAAQ,WAAW,QAAQ;AAC5C;AAWA,eAAsB,oBACpB,gBACA,cACA,YACA,SACiB;AACjB,MAAI,UAAU,aAAa;AACzB,UAAM,IAAI;AAAA,MACR,sBAAO,WAAW,wIAA0B,YAAY;AAAA,IAC1D;AAAA,EACF;AAEA,gBAAc,uDAAe,OAAO,IAAI,WAAW,kBAAQ;AAC3D,EAAI,KAAK,kFAAiB,OAAO,IAAI,WAAW,kBAAQ;AAExD,QAAM,SAAS,aAAa;AAC5B,QAAM,EAAE,UAAU,IAAI,aAAa;AAEnC,QAAM,oBAAoB,gCAAgC;AAAA,IACxD;AAAA,IACA;AAAA,EACF,EAAE,QAAQ,YAAY,cAAc;AAEpC,QAAM,WAAgD;AAAA,IACpD,EAAE,MAAM,UAAU,SAAS,kCAAkC;AAAA,IAC7D,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,IACpC,EAAE,MAAM,aAAa,SAAS,eAAe;AAAA,IAC7C,EAAE,MAAM,QAAQ,SAAS,kBAAkB;AAAA,EAC7C;AAEA,SAAO,QAAQ,QAAQ,WAAW,QAAQ;AAC5C;;;AGvJA;AAAA,OAAO,QAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,sBAAsB;AAiB/B,eAAsB,eAAe,QAAiC;AACpE,MAAI;AACF,UAAM,YAAY,MAAM,eAAe,MAAM;AAC7C,QAAI,CAAC,aAAa,UAAU,KAAK,EAAE,WAAW,GAAG;AAC/C,YAAM,IAAI,MAAM,gEAA6B;AAAA,IAC/C;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,IAAI,MAAM,iCAAa,OAAO,EAAE;AAAA,EACxC;AACF;AASA,eAAsB,aACpB,YACA,YACe;AACf,QAAM,eAAeA,MAAK,QAAQ,UAAU;AAC5C,QAAM,MAAMA,MAAK,QAAQ,YAAY;AAGrC,QAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,GAAG,UAAU,cAAc,YAAY,OAAO;AACtD;AAMO,SAAS,kBAAkB,YAA6B;AAC7D,MAAI,YAAY;AAEd,QAAI,CAAC,WAAW,SAAS,MAAM,GAAG;AAChC,aAAO,aAAa;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AACA,SAAOA,MAAK,QAAQ,QAAQ,IAAI,GAAG,wBAAwB;AAC7D;;;AJ9CO,SAAS,wBAAwBC,UAAwB;AAC9D,EAAAA,SACG,QAAQ,UAAU,EAClB,MAAM,KAAK,EACX,YAAY,qFAAoB,EAChC,SAAS,YAAY,gFAAe,EACpC,OAAO,uBAAuB,6CAAe,wBAAwB,EACrE,OAAO,OAAO,QAAgB,SAA6B;AAC1D,UAAM,eAAe,QAAQ,KAAK,MAAM;AAAA,EAC1C,CAAC;AACL;AAWA,eAAe,eAAe,QAAgB,cAAqC;AACjF,QAAM,aAAa,kBAAkB,YAAY;AAEjD,EAAI,KAAK,iCAAQC,MAAK,QAAQ,UAAU,CAAC,EAAE;AAC3C,eAAa,2EAAoB;AAEjC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,uBAAuB,MAAM;AAAA,EAC9C,SAAS,KAAK;AACZ,gBAAY,6BAAS;AACrB,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC1D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,gBAAc,iCAAa;AAG3B,MAAI,aAA4B;AAChC,MAAI,YAAY;AAEhB,WAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,QAAI;AACF,mBAAa,MAAM,eAAe,MAAM;AACxC;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE3D,UAAI,UAAU,aAAa;AAEzB,YAAI;AACF,mBAAS,MAAM,oBAAoB,QAAQ,WAAW,QAAQ,UAAU,CAAC;AACzE,wBAAc,6CAAe;AAAA,QAC/B,SAAS,UAAU;AACjB,sBAAY,sCAAQ;AACpB,UAAI,MAAM,oBAAoB,QAAQ,SAAS,UAAU,OAAO,QAAQ,CAAC;AACzE,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,YAAY;AACf,gBAAY,sCAAQ;AACpB,IAAI,MAAM,gBAAM,WAAW,+GAAqB;AAChD,IAAI,MAAM,6CAAU,SAAS,EAAE;AAC/B,IAAI,IAAI,4FAA2B;AACnC,YAAQ,MAAM,MAAM;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI;AACF,UAAM,aAAa,YAAY,UAAU;AAAA,EAC3C,SAAS,KAAK;AACZ,gBAAY,sCAAQ;AACpB,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC1D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,iBAAe,4CAAS;AACxB,EAAI,QAAQ,qCAAYA,MAAK,QAAQ,UAAU,CAAC,EAAE;AAClD,EAAI,IAAI,6GAAwB;AAClC;;;AJlGA,IAAM,UAAU;AAEhB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,iBAAiB,EACtB,YAAY,gKAAwC,EACpD,QAAQ,SAAS,iBAAiB,gCAAO;AAG5C,sBAAsB,OAAO;AAC7B,wBAAwB,OAAO;AAG/B,QAAQ,MAAM,QAAQ,IAAI;","names":["pc","pc","program","path","path","program","path"]}
1
+ {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../node_modules/picocolors/picocolors.js","../src/index.ts","../src/commands/config.ts","../src/config/index.ts","../src/utils/logger.ts","../src/utils/i18n.ts","../src/commands/generate.ts","../src/core/ai.ts","../src/core/prompts.ts","../src/utils/spinner.ts","../src/core/render.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","let p = process || {}, argv = p.argv || [], env = p.env || {}\nlet isColorSupported =\n\t!(!!env.NO_COLOR || argv.includes(\"--no-color\")) &&\n\t(!!env.FORCE_COLOR || argv.includes(\"--color\") || p.platform === \"win32\" || ((p.stdout || {}).isTTY && env.TERM !== \"dumb\") || !!env.CI)\n\nlet formatter = (open, close, replace = open) =>\n\tinput => {\n\t\tlet string = \"\" + input, index = string.indexOf(close, open.length)\n\t\treturn ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close\n\t}\n\nlet replaceClose = (string, close, replace, index) => {\n\tlet result = \"\", cursor = 0\n\tdo {\n\t\tresult += string.substring(cursor, index) + replace\n\t\tcursor = index + close.length\n\t\tindex = string.indexOf(close, cursor)\n\t} while (~index)\n\treturn result + string.substring(cursor)\n}\n\nlet createColors = (enabled = isColorSupported) => {\n\tlet f = enabled ? formatter : () => String\n\treturn {\n\t\tisColorSupported: enabled,\n\t\treset: f(\"\\x1b[0m\", \"\\x1b[0m\"),\n\t\tbold: f(\"\\x1b[1m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[1m\"),\n\t\tdim: f(\"\\x1b[2m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[2m\"),\n\t\titalic: f(\"\\x1b[3m\", \"\\x1b[23m\"),\n\t\tunderline: f(\"\\x1b[4m\", \"\\x1b[24m\"),\n\t\tinverse: f(\"\\x1b[7m\", \"\\x1b[27m\"),\n\t\thidden: f(\"\\x1b[8m\", \"\\x1b[28m\"),\n\t\tstrikethrough: f(\"\\x1b[9m\", \"\\x1b[29m\"),\n\n\t\tblack: f(\"\\x1b[30m\", \"\\x1b[39m\"),\n\t\tred: f(\"\\x1b[31m\", \"\\x1b[39m\"),\n\t\tgreen: f(\"\\x1b[32m\", \"\\x1b[39m\"),\n\t\tyellow: f(\"\\x1b[33m\", \"\\x1b[39m\"),\n\t\tblue: f(\"\\x1b[34m\", \"\\x1b[39m\"),\n\t\tmagenta: f(\"\\x1b[35m\", \"\\x1b[39m\"),\n\t\tcyan: f(\"\\x1b[36m\", \"\\x1b[39m\"),\n\t\twhite: f(\"\\x1b[37m\", \"\\x1b[39m\"),\n\t\tgray: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\n\t\tbgBlack: f(\"\\x1b[40m\", \"\\x1b[49m\"),\n\t\tbgRed: f(\"\\x1b[41m\", \"\\x1b[49m\"),\n\t\tbgGreen: f(\"\\x1b[42m\", \"\\x1b[49m\"),\n\t\tbgYellow: f(\"\\x1b[43m\", \"\\x1b[49m\"),\n\t\tbgBlue: f(\"\\x1b[44m\", \"\\x1b[49m\"),\n\t\tbgMagenta: f(\"\\x1b[45m\", \"\\x1b[49m\"),\n\t\tbgCyan: f(\"\\x1b[46m\", \"\\x1b[49m\"),\n\t\tbgWhite: f(\"\\x1b[47m\", \"\\x1b[49m\"),\n\n\t\tblackBright: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\t\tredBright: f(\"\\x1b[91m\", \"\\x1b[39m\"),\n\t\tgreenBright: f(\"\\x1b[92m\", \"\\x1b[39m\"),\n\t\tyellowBright: f(\"\\x1b[93m\", \"\\x1b[39m\"),\n\t\tblueBright: f(\"\\x1b[94m\", \"\\x1b[39m\"),\n\t\tmagentaBright: f(\"\\x1b[95m\", \"\\x1b[39m\"),\n\t\tcyanBright: f(\"\\x1b[96m\", \"\\x1b[39m\"),\n\t\twhiteBright: f(\"\\x1b[97m\", \"\\x1b[39m\"),\n\n\t\tbgBlackBright: f(\"\\x1b[100m\", \"\\x1b[49m\"),\n\t\tbgRedBright: f(\"\\x1b[101m\", \"\\x1b[49m\"),\n\t\tbgGreenBright: f(\"\\x1b[102m\", \"\\x1b[49m\"),\n\t\tbgYellowBright: f(\"\\x1b[103m\", \"\\x1b[49m\"),\n\t\tbgBlueBright: f(\"\\x1b[104m\", \"\\x1b[49m\"),\n\t\tbgMagentaBright: f(\"\\x1b[105m\", \"\\x1b[49m\"),\n\t\tbgCyanBright: f(\"\\x1b[106m\", \"\\x1b[49m\"),\n\t\tbgWhiteBright: f(\"\\x1b[107m\", \"\\x1b[49m\"),\n\t}\n}\n\nmodule.exports = createColors()\nmodule.exports.createColors = createColors\n","import { Command } from \"commander\";\nimport { registerConfigCommand } from \"./commands/config.js\";\nimport { registerGenerateCommand } from \"./commands/generate.js\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\nimport { t } from \"./utils/i18n.js\";\n\n// 从 package.json 中读取版本号\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJsonPath = join(__dirname, \"../package.json\");\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\nconst VERSION = packageJson.version;\n\nconst program = new Command();\n\nprogram\n .name(\"infographic-gen\")\n .description(t(\"programDesc\"))\n .version(VERSION, \"-v, --version\", t(\"versionFlag\"));\n\n// 注册子命令\nregisterConfigCommand(program);\nregisterGenerateCommand(program);\n\n// 解析命令行参数\nprogram.parse(process.argv);\n","import { Command } from \"commander\";\nimport {\n getAllConfig,\n getConfig,\n setConfig,\n deleteConfig,\n isValidConfigKey,\n getConfigPath,\n CONFIG_KEYS,\n CONFIG_LABELS,\n type ConfigKey,\n} from \"../config/index.js\";\nimport * as log from \"../utils/logger.js\";\nimport { t } from \"../utils/i18n.js\";\n\n/**\n * 注册 `config` 子命令,支持以下操作:\n * config set <key> <value> — 设置配置项\n * config get <key> — 查看单个配置项\n * config list — 列出所有配置\n * config delete <key> — 删除(重置)配置项\n * config path — 打印配置文件路径\n */\nexport function registerConfigCommand(program: Command): void {\n const configCmd = program\n .command(\"config\")\n .alias(\"c\")\n .description(\n \"Manage configuration (API Key, Base URL, Provider, Model, Output Directory)\",\n );\n\n // ---------- config set ----------\n configCmd\n .command(\"set <key> <value>\")\n .description(t(\"configSetDesc\"))\n .action((key: string, value: string) => {\n if (!isValidConfigKey(key)) {\n log.error(t(\"configInvalidKey\", { key, keys: CONFIG_KEYS.join(\", \") }));\n process.exit(1);\n }\n setConfig(key, value);\n log.success(t(\"configSetSuccess\", { label: CONFIG_LABELS[key] }));\n });\n\n // ---------- config get ----------\n configCmd\n .command(\"get <key>\")\n .description(t(\"configGetDesc\"))\n .action((key: string) => {\n if (!isValidConfigKey(key)) {\n log.error(t(\"configInvalidKey\", { key, keys: CONFIG_KEYS.join(\", \") }));\n process.exit(1);\n }\n const val = getConfig(key);\n if (!val) {\n log.warn(t(\"configNotSet\", { label: CONFIG_LABELS[key] }));\n } else {\n // Mask apiKey for security\n const display = key === \"apiKey\" ? maskApiKey(val) : val;\n log.label(CONFIG_LABELS[key], display);\n }\n });\n\n // ---------- config list ----------\n configCmd\n .command(\"list\")\n .description(t(\"configListDesc\"))\n .action(() => {\n const all = getAllConfig();\n log.info(t(\"configCurrent\"));\n for (const k of CONFIG_KEYS) {\n const val = all[k];\n const display =\n k === \"apiKey\" && val\n ? maskApiKey(val)\n : val || t(\"configNotSetValue\");\n log.label(CONFIG_LABELS[k], display);\n }\n log.dim(t(\"configFileLocation\", { path: getConfigPath() }));\n });\n\n // ---------- config delete ----------\n configCmd\n .command(\"delete <key>\")\n .description(t(\"configDeleteDesc\"))\n .action((key: string) => {\n if (!isValidConfigKey(key)) {\n log.error(t(\"configInvalidKey\", { key, keys: CONFIG_KEYS.join(\", \") }));\n process.exit(1);\n }\n deleteConfig(key as ConfigKey);\n log.success(\n t(\"configResetSuccess\", { label: CONFIG_LABELS[key as ConfigKey] }),\n );\n });\n\n // ---------- config path ----------\n configCmd\n .command(\"path\")\n .description(t(\"configPathDesc\"))\n .action(() => {\n console.log(getConfigPath());\n });\n}\n\n// ---- helpers ----\n\n/** 对 API Key 做脱敏处理:只显示前 4 位和后 4 位 */\nfunction maskApiKey(key: string): string {\n if (key.length <= 8) return \"****\";\n return key.slice(0, 4) + \"****\" + key.slice(-4);\n}\n","import Conf from \"conf\";\n\n/**\n * 用户可配置的 LLM 字段\n */\nexport interface LLMConfig {\n apiKey: string;\n baseUrl: string;\n provider: string;\n modelName: string;\n}\n\n/**\n * 配置 schema 的完整类型\n */\ninterface ConfigSchema {\n apiKey: string;\n baseUrl: string;\n provider: string;\n modelName: string;\n defaultOutputDir: string;\n locale: string;\n}\n\n/** 所有可配置的 key */\nexport const CONFIG_KEYS = [\n \"apiKey\",\n \"baseUrl\",\n \"provider\",\n \"modelName\",\n \"defaultOutputDir\",\n \"locale\",\n] as const;\nexport type ConfigKey = (typeof CONFIG_KEYS)[number];\n\n/** 配置项的人类可读标签 */\nexport const CONFIG_LABELS: Record<ConfigKey, string> = {\n apiKey: \"API Key\",\n baseUrl: \"Base URL\",\n provider: \"Provider\",\n modelName: \"Model Name\",\n defaultOutputDir: \"Default Output Directory\",\n locale: \"Language\",\n};\n\n/** 默认值 */\nconst DEFAULTS: ConfigSchema = {\n apiKey: \"\",\n baseUrl: \"https://api.openai.com/v1\",\n provider: \"openai\",\n modelName: \"gpt-4o\",\n defaultOutputDir: \".\",\n locale: \"en\",\n};\n\n/**\n * 基于 conf 的本地持久化配置管理器(单例)\n */\nconst store = new Conf<ConfigSchema>({\n projectName: \"infographic-gen\",\n defaults: DEFAULTS,\n});\n\n/** 读取单个配置值 */\nexport function getConfig<K extends ConfigKey>(key: K): string {\n return store.get(key) as string;\n}\n\n/** 写入单个配置值 */\nexport function setConfig<K extends ConfigKey>(key: K, value: string): void {\n store.set(key, value);\n}\n\n/** 删除单个配置值(恢复为默认) */\nexport function deleteConfig<K extends ConfigKey>(key: K): void {\n store.delete(key);\n}\n\n/** 读取完整 LLM 配置(用于创建 OpenAI 客户端) */\nexport function getLLMConfig(): LLMConfig {\n return {\n apiKey: getConfig(\"apiKey\"),\n baseUrl: getConfig(\"baseUrl\"),\n provider: getConfig(\"provider\"),\n modelName: getConfig(\"modelName\"),\n };\n}\n\n/** 返回所有配置项的 KV 对象(用于 `config list`) */\nexport function getAllConfig(): Record<ConfigKey, string> {\n return {\n apiKey: getConfig(\"apiKey\"),\n baseUrl: getConfig(\"baseUrl\"),\n provider: getConfig(\"provider\"),\n modelName: getConfig(\"modelName\"),\n defaultOutputDir: getConfig(\"defaultOutputDir\"),\n locale: getConfig(\"locale\"),\n };\n}\n\n/** 判断某个 key 是否为合法配置项 */\nexport function isValidConfigKey(key: string): key is ConfigKey {\n return CONFIG_KEYS.includes(key as ConfigKey);\n}\n\n/** 返回配置文件在磁盘上的路径(用于 debug) */\nexport function getConfigPath(): string {\n return store.path;\n}\n","import pc from \"picocolors\";\n\n/**\n * 统一的控制台日志工具,基于 picocolors 着色。\n * 所有输出走 stderr,stdout 留给管道场景。\n */\n\nexport function info(msg: string): void {\n console.error(pc.blue(\"ℹ\") + \" \" + msg);\n}\n\nexport function success(msg: string): void {\n console.error(pc.green(\"✔\") + \" \" + msg);\n}\n\nexport function warn(msg: string): void {\n console.error(pc.yellow(\"⚠\") + \" \" + pc.yellow(msg));\n}\n\nexport function error(msg: string): void {\n console.error(pc.red(\"✖\") + \" \" + pc.red(msg));\n}\n\nexport function dim(msg: string): void {\n console.error(pc.dim(msg));\n}\n\nexport function bold(msg: string): string {\n return pc.bold(msg);\n}\n\nexport function label(key: string, value: string): void {\n console.error(` ${pc.cyan(key)}: ${value}`);\n}\n","import { getConfig } from \"../config/index.js\";\n\nexport type Locale = \"en\" | \"zh-CN\";\n\n/**\n * 所有翻译文本的定义\n */\nconst translations = {\n en: {\n // Main program\n programDesc:\n \"AI-powered CLI to generate AntV Infographic SVGs from natural language prompts\",\n versionFlag: \"Display version number\",\n\n // Config command\n configDesc:\n \"Manage configuration (API Key, Base URL, Provider, Model, Output Directory)\",\n configSetDesc: \"Set a configuration value\",\n configGetDesc: \"Get a single configuration value\",\n configListDesc: \"List all configuration values\",\n configDeleteDesc: \"Delete a configuration value (reset to default)\",\n configPathDesc: \"Show configuration file path\",\n configInvalidKey: 'Invalid config key \"{key}\". Available: {keys}',\n configSetSuccess: \"{label} set successfully\",\n configNotSet: \"{label} not set\",\n configCurrent: \"Current configuration:\",\n configFileLocation: \" Config file location: {path}\",\n configResetSuccess: \"{label} reset to default\",\n configNotSetValue: \"(not set)\",\n\n // Generate command\n generateDesc:\n \"Generate an SVG infographic from natural language (default command)\",\n generatePromptArg: \"Describe the infographic you want to create\",\n generateOutputOpt:\n \"Output SVG file path (default: infographic-output.svg in default output directory)\",\n generateDslOpt:\n \"Save raw DSL syntax to a text file (optional, for debugging or fine-tuning)\",\n outputTarget: \"Output target: {path}\",\n callingAI: \"Calling AI to generate infographic syntax...\",\n renderingSVG: \"Rendering SVG...\",\n reRenderingSVG: \"Re-rendering SVG...\",\n aiCallFailed: \"AI call failed\",\n renderingFailed: \"Rendering failed\",\n renderFailedAfterRetries:\n \"Failed to generate renderable infographic after {retries} self-correction attempts.\",\n lastError: \"Last error: {error}\",\n dslAutoSaved: \"❌ Problematic DSL syntax auto-saved to: {path}\",\n dslAutoSaveHint:\n \"You can inspect this file to debug the LLM output or refine your prompt.\",\n dslForDebug: \"Generated DSL syntax (for debugging reference):\",\n fileWriteFailed: \"File write failed\",\n dslSaved: \"DSL syntax saved to: {path}\",\n dslWriteFailed:\n \"DSL file write failed (does not affect main functionality):\",\n infographicGenerated: \"Infographic generated!\",\n svgSaved: \"SVG saved to: {path}\",\n openInBrowser:\n \"You can open the SVG file directly in a browser to view it.\",\n selfCorrecting: \"AI self-correcting (attempt {attempt}/{max})...\",\n selfCorrectionFailed: \"Self-correction failed\",\n renderFailedRetrying:\n \"Render failed, auto-correcting (attempt {attempt}/{max})...\",\n\n // AI errors\n apiKeyNotConfigured:\n \"API Key not configured. Please run: infographic-gen config set apiKey <YOUR_KEY>\",\n llmEmptyContent: \"LLM returned empty content\",\n failedAfterRetries:\n \"Failed to generate renderable infographic after {retries} retries. Last error: {error}\",\n },\n \"zh-CN\": {\n // Main program\n programDesc: \"AI 驱动的信息图生成 CLI —— 输入自然语言,输出精美 SVG 信息图\",\n versionFlag: \"显示版本号\",\n\n // Config command\n configDesc: \"管理配置(API Key、Base URL、Provider、Model、输出目录)\",\n configSetDesc: \"设置配置项\",\n configGetDesc: \"查看单个配置项\",\n configListDesc: \"列出所有配置项\",\n configDeleteDesc: \"删除配置项(恢复默认值)\",\n configPathDesc: \"显示配置文件路径\",\n configInvalidKey: '无效的配置项 \"{key}\",可选项:{keys}',\n configSetSuccess: \"{label} 已设置\",\n configNotSet: \"{label} 尚未设置\",\n configCurrent: \"当前配置:\",\n configFileLocation: \" 配置文件位置: {path}\",\n configResetSuccess: \"{label} 已重置为默认值\",\n configNotSetValue: \"(未设置)\",\n\n // Generate command\n generateDesc: \"根据自然语言描述生成 SVG 信息图(默认命令)\",\n generatePromptArg: \"描述你想要生成的信息图内容\",\n generateOutputOpt:\n \"输出 SVG 文件路径(默认:默认输出目录中的 infographic-output.svg)\",\n generateDslOpt: \"将原始 DSL 语法保存到指定文本文件(可选,用于调试或微调)\",\n outputTarget: \"目标输出:{path}\",\n callingAI: \"正在调用 AI 生成信息图语法...\",\n renderingSVG: \"正在渲染 SVG...\",\n reRenderingSVG: \"正在重新渲染 SVG...\",\n aiCallFailed: \"AI 调用失败\",\n renderingFailed: \"渲染最终失败\",\n renderFailedAfterRetries:\n \"经过 {retries} 次自我修正仍无法生成可渲染的信息图。\",\n lastError: \"最后一次错误:{error}\",\n dslAutoSaved: \"❌ 有问题的 DSL 语法已自动保存至:{path}\",\n dslAutoSaveHint:\n \"你可以检查此文件以排查大模型生成的问题,或用于调试 Prompt。\",\n dslForDebug: \"生成的 DSL 语法如下(供 debug 参考):\",\n fileWriteFailed: \"文件写入失败\",\n dslSaved: \"DSL 语法已保存至:{path}\",\n dslWriteFailed: \"DSL 文件写入失败(不影响主要功能):\",\n infographicGenerated: \"信息图已生成!\",\n svgSaved: \"SVG 已保存至:{path}\",\n openInBrowser: \"可直接在浏览器中打开 SVG 文件查看效果。\",\n selfCorrecting: \"AI 正在自我修正(第 {attempt}/{max} 次)...\",\n selfCorrectionFailed: \"自我修正失败\",\n renderFailedRetrying: \"渲染失败,正在自动修正(第 {attempt}/{max} 次)...\",\n\n // AI errors\n apiKeyNotConfigured:\n \"尚未配置 API Key。请先运行:infographic-gen config set apiKey <YOUR_KEY>\",\n llmEmptyContent: \"LLM 返回了空内容\",\n failedAfterRetries:\n \"已重试 {retries} 次仍然无法生成可渲染的信息图。最后一次错误:{error}\",\n },\n} as const;\n\n/**\n * 获取当前配置的语言\n */\nexport function getLocale(): Locale {\n const locale = getConfig(\"locale\");\n return (locale === \"zh-CN\" ? \"zh-CN\" : \"en\") as Locale;\n}\n\n/**\n * 获取翻译文本\n * @param key 翻译键\n * @param params 插值参数\n */\nexport function t(\n key: keyof (typeof translations)[\"en\"],\n params?: Record<string, string | number>,\n): string {\n const locale = getLocale();\n let text: string = translations[locale][key];\n\n if (params) {\n Object.entries(params).forEach(([paramKey, value]) => {\n text = text.replace(`{${paramKey}}`, String(value));\n });\n }\n\n return text;\n}\n","import path from \"node:path\";\nimport { Command } from \"commander\";\nimport {\n generateInfographicDSL,\n retryWithCorrection,\n MAX_RETRIES,\n} from \"../core/ai.js\";\nimport {\n renderDSLToSVG,\n writeSVGFile,\n writeDSLFile,\n resolveOutputPath,\n} from \"../core/render.js\";\nimport * as log from \"../utils/logger.js\";\nimport {\n startSpinner,\n succeedSpinner,\n failSpinner,\n updateSpinner,\n} from \"../utils/spinner.js\";\nimport { t } from \"../utils/i18n.js\";\n\n/**\n * 注册 `generate` 子命令。\n *\n * 用法示例:\n * infographic-gen generate \"帮我画一个软件开发流程图\" -o result.svg\n * infographic-gen generate \"帮我画一个饼图\" -o chart.svg --dsl chart-syntax.txt\n */\nexport function registerGenerateCommand(program: Command): void {\n program\n .command(\"generate\", { isDefault: true })\n .alias(\"g\")\n .description(t(\"generateDesc\"))\n .argument(\"<prompt>\", t(\"generatePromptArg\"))\n .option(\"-o, --output <path>\", t(\"generateOutputOpt\"))\n .option(\"--dsl <path>\", t(\"generateDslOpt\"))\n .action(async (prompt: string, opts: { output?: string; dsl?: string }) => {\n await handleGenerate(prompt, opts.output, opts.dsl);\n });\n}\n\n/**\n * 生成命令的核心处理逻辑。\n *\n * 流程:\n * 1. 调用 LLM 生成 DSL\n * 2. 调用 SSR 渲染为 SVG\n * 3. 如果渲染失败,自动进入自我修正循环(最多 MAX_RETRIES 次)\n * 4. 写入 SVG 文件\n * 5. 如果用户指定了 --dsl,保存原始 DSL 语法\n */\nasync function handleGenerate(\n prompt: string,\n outputOption?: string,\n dslOption?: string,\n): Promise<void> {\n const outputPath = resolveOutputPath(outputOption);\n\n log.info(t(\"outputTarget\", { path: path.resolve(outputPath) }));\n startSpinner(t(\"callingAI\"));\n\n let syntax: string;\n try {\n syntax = await generateInfographicDSL(prompt);\n } catch (err) {\n failSpinner(t(\"aiCallFailed\"));\n log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n updateSpinner(t(\"renderingSVG\"));\n\n // ─── 渲染 + 自我修正循环 ───────────────────────────────────────────\n let svgContent: string | null = null;\n let lastError = \"\";\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n svgContent = await renderDSLToSVG(syntax);\n break; // Render successful, exit loop\n } catch (err) {\n lastError = err instanceof Error ? err.message : String(err);\n\n if (attempt < MAX_RETRIES) {\n // Retry available → self-correction\n try {\n syntax = await retryWithCorrection(\n syntax,\n lastError,\n prompt,\n attempt + 1,\n );\n updateSpinner(t(\"reRenderingSVG\"));\n } catch (retryErr) {\n failSpinner(t(\"selfCorrectionFailed\"));\n log.error(\n retryErr instanceof Error ? retryErr.message : String(retryErr),\n );\n process.exit(1);\n }\n }\n }\n }\n\n if (!svgContent) {\n failSpinner(t(\"renderingFailed\"));\n log.error(t(\"renderFailedAfterRetries\", { retries: String(MAX_RETRIES) }));\n log.error(t(\"lastError\", { error: lastError }));\n\n // Auto-save problematic DSL to error-dump.txt\n const errorDumpPath = \"error-dump.txt\";\n try {\n await writeDSLFile(errorDumpPath, syntax);\n log.warn(t(\"dslAutoSaved\", { path: path.resolve(errorDumpPath) }));\n log.dim(t(\"dslAutoSaveHint\"));\n } catch (writeErr) {\n log.dim(t(\"dslForDebug\"));\n console.error(syntax);\n }\n\n process.exit(1);\n }\n\n // ─── Render successful, write file ─────────────────────────────────────────────\n try {\n await writeSVGFile(outputPath, svgContent);\n } catch (err) {\n failSpinner(t(\"fileWriteFailed\"));\n log.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n\n // ─── If user specified --dsl, save raw DSL syntax ───────────────────────\n if (dslOption) {\n try {\n await writeDSLFile(dslOption, syntax);\n log.success(t(\"dslSaved\", { path: path.resolve(dslOption) }));\n } catch (err) {\n log.warn(t(\"dslWriteFailed\"));\n log.warn(err instanceof Error ? err.message : String(err));\n }\n }\n\n succeedSpinner(t(\"infographicGenerated\"));\n log.success(t(\"svgSaved\", { path: path.resolve(outputPath) }));\n log.dim(t(\"openInBrowser\"));\n}\n","import OpenAI from \"openai\";\nimport { getLLMConfig } from \"../config/index.js\";\nimport {\n INFOGRAPHIC_CREATOR_SYSTEM_PROMPT,\n SELF_CORRECTION_PROMPT_TEMPLATE,\n} from \"./prompts.js\";\nimport * as log from \"../utils/logger.js\";\nimport { updateSpinner } from \"../utils/spinner.js\";\nimport { t } from \"../utils/i18n.js\";\n\n/** LLM 请求返回的结果 */\nexport interface LLMResult {\n /** 生成的 DSL 语法文本 */\n syntax: string;\n /** 总共重试了几次(0 = 一次成功) */\n attempts: number;\n}\n\n/** 最大自我修正重试次数 */\nconst MAX_RETRIES = 3;\n\n/**\n * 创建一个懒初始化的 OpenAI 客户端。\n * 通过覆盖 baseURL / apiKey 兼容 DeepSeek、阿里云百炼等平台。\n */\nfunction createClient(): OpenAI {\n const { apiKey, baseUrl } = getLLMConfig();\n\n if (!apiKey) {\n throw new Error(t(\"apiKeyNotConfigured\"));\n }\n\n return new OpenAI({\n apiKey,\n baseURL: baseUrl,\n });\n}\n\n/**\n * 向 LLM 发送请求,获取信息图 DSL。\n *\n * @param userPrompt 用户的自然语言描述\n * @returns LLM 返回的纯 DSL 文本\n */\nasync function callLLM(\n client: OpenAI,\n model: string,\n messages: OpenAI.ChatCompletionMessageParam[],\n): Promise<string> {\n const response = await client.chat.completions.create({\n model,\n messages,\n temperature: 0.7,\n max_tokens: 4096,\n });\n\n const content = response.choices[0]?.message?.content;\n if (!content) {\n throw new Error(t(\"llmEmptyContent\"));\n }\n\n return cleanDSL(content);\n}\n\n/**\n * 清理 LLM 返回的文本,去除可能的 Markdown 代码块标记等噪声。\n */\nfunction cleanDSL(raw: string): string {\n let cleaned = raw.trim();\n\n // 去掉可能包裹的 ```xxx ... ``` 代码块\n const codeBlockMatch = cleaned.match(/^```[\\w]*\\n?([\\s\\S]*?)```$/);\n if (codeBlockMatch) {\n cleaned = codeBlockMatch[1].trim();\n }\n\n // 确保以 infographic 开头\n const infographicIndex = cleaned.indexOf(\"infographic \");\n if (infographicIndex > 0) {\n cleaned = cleaned.slice(infographicIndex);\n }\n\n return cleaned;\n}\n\n/**\n * 带自我修正机制的 AI 生成入口。\n *\n * 流程:\n * 1. 将用户 Prompt + 系统提示词发给 LLM,获取 DSL。\n * 2. 调用方(generate 命令)会尝试渲染。如果渲染失败,调用 retryWithCorrection。\n * 3. 最多重试 MAX_RETRIES 次。\n *\n * @param userPrompt 用户输入的自然语言\n * @returns 生成的 DSL 语法\n */\nexport async function generateInfographicDSL(\n userPrompt: string,\n): Promise<string> {\n const client = createClient();\n const { modelName } = getLLMConfig();\n\n const messages: OpenAI.ChatCompletionMessageParam[] = [\n { role: \"system\", content: INFOGRAPHIC_CREATOR_SYSTEM_PROMPT },\n { role: \"user\", content: userPrompt },\n ];\n\n return callLLM(client, modelName, messages);\n}\n\n/**\n * 自我修正:当 DSL 渲染失败时,把错误信息反馈给 LLM 要求修正。\n *\n * @param originalSyntax 上一次生成的 DSL\n * @param errorMessage 渲染报错信息\n * @param userPrompt 用户原始需求\n * @param attempt 当前第几次重试(从 1 开始)\n * @returns 修正后的 DSL\n */\nexport async function retryWithCorrection(\n originalSyntax: string,\n errorMessage: string,\n userPrompt: string,\n attempt: number,\n): Promise<string> {\n if (attempt > MAX_RETRIES) {\n throw new Error(\n t(\"failedAfterRetries\", {\n retries: String(MAX_RETRIES),\n error: errorMessage,\n }),\n );\n }\n\n updateSpinner(\n t(\"selfCorrecting\", { attempt: String(attempt), max: String(MAX_RETRIES) }),\n );\n log.warn(\n t(\"renderFailedRetrying\", {\n attempt: String(attempt),\n max: String(MAX_RETRIES),\n }),\n );\n\n const client = createClient();\n const { modelName } = getLLMConfig();\n\n const correctionMessage = SELF_CORRECTION_PROMPT_TEMPLATE.replace(\n \"{error}\",\n errorMessage,\n ).replace(\"{syntax}\", originalSyntax);\n\n const messages: OpenAI.ChatCompletionMessageParam[] = [\n { role: \"system\", content: INFOGRAPHIC_CREATOR_SYSTEM_PROMPT },\n { role: \"user\", content: userPrompt },\n { role: \"assistant\", content: originalSyntax },\n { role: \"user\", content: correctionMessage },\n ];\n\n return callLLM(client, modelName, messages);\n}\n\n/** 导出最大重试次数常量供外部使用 */\nexport { MAX_RETRIES };\n","/**\n * ⭐ 硬编码的系统提示词常量。\n *\n * 直接内嵌在代码中,确保 CLI 开箱即用,无需读取本地磁盘文件。\n * 内容基于 @antv/infographic 的 .skills/infographic-creator/SKILL.md 整理。\n */\n\n// ─── 公共:AntV Infographic 语法规范 ────────────────────────────────\n\nconst SYNTAX_SPEC = `\n## AntV Infographic 语法\n\nAntV Infographic 语法是一种自定义的 DSL,用于描述信息图渲染配置。它使用缩进描述信息,具有较强鲁棒性,便于 AI 流式输出并渲染信息图。主要包含以下信息:\n\n1. template:用模板表达文字信息结构。\n2. data:信息图数据,包含 title、desc、数据项等。数据项通常包含 label、desc、icon 等字段。\n3. theme:主题包含 palette、font 等样式配置。\n\n例如:\n\\`\\`\\`\ninfographic list-row-horizontal-icon-arrow\ndata\n title Title\n desc Description\n lists\n - label Label\n value 12.5\n desc Explanation\n icon document text\ntheme\n palette #3b82f6 #8b5cf6 #f97316\n\\`\\`\\`\n\n### 语法规范\n\n• 第一行必须是 \\`infographic <template-name>\\`,模板从下方可用模板列表中选择。\n• 使用 \\`data\\` / \\`theme\\` 块,块内用两个空格缩进。\n• 键值对使用「键 空格 值」;数组使用 \\`-\\` 作为条目前缀。\n• icon 使用图标关键词(如 \\`star fill\\`)。\n• \\`data\\` 应包含 title/desc + 模板对应的主数据字段(不一定是 \\`items\\`)。\n• 主数据字段选择(只用一个,避免混用):\n - \\`list-*\\` → \\`lists\\`\n - \\`sequence-*\\` → \\`sequences\\`(可选 \\`order asc|desc\\`)\n - \\`compare-*\\` → \\`compares\\`(支持 \\`children\\` 分组对比),可包含多个对比项\n - \\`hierarchy-structure\\` → \\`items\\`(每一项对应一个独立层级,每一层级可以包含子项,最多可嵌套 3 层)\n - \\`hierarchy-*\\` → 单一 \\`root\\`(树结构,通过 \\`children\\` 嵌套)\n - \\`relation-*\\` → \\`nodes\\` + \\`relations\\`;简单关系图可省略 \\`nodes\\`,在 relations 中用箭头语法\n - \\`chart-*\\` → \\`values\\`(数值统计,可选 \\`category\\`)\n - 不确定时再用 \\`items\\` 兜底\n\n• \\`compare-binary-*\\` / \\`compare-hierarchy-left-right-*\\` 二元模板:必须两个根节点,所有对比项挂在这两个根节点的 children\n• \\`hierarchy-*\\`:使用单一 \\`root\\`,通过 \\`children\\` 嵌套(不要重复 \\`root\\`)\n• \\`theme\\` 用于自定义主题(palette、font 等)\n\n例如:暗色主题 + 自定义配色\n\\`\\`\\`\ninfographic list-row-simple-horizontal-arrow\ntheme dark\n palette\n - #61DDAA\n - #F6BD16\n - #F08BB4\n\\`\\`\\`\n\n• 使用 \\`theme.base.text.font-family\\` 指定字体,如手写风格 \\`851tegakizatsu\\`\n• 使用 \\`theme.stylize\\` 选择内置风格并传参。常见风格:\n - \\`rough\\`:手绘效果\n - \\`pattern\\`:图案填充\n - \\`linear-gradient\\` / \\`radial-gradient\\`:线性/径向渐变\n\n例如:手绘风格(rough)\n\\`\\`\\`\ninfographic list-row-simple-horizontal-arrow\ntheme\n stylize rough\n base\n text\n font-family 851tegakizatsu\n\\`\\`\\`\n`.trim();\n\n// ─── 数据语法示例 ───────────────────────────────────────────────────\n\nconst DATA_EXAMPLES = `\n### 数据语法示例\n\n• list-* 模版\n\\`\\`\\`\ninfographic list-grid-badge-card\ndata\n title Feature List\n lists\n - label Fast\n icon flash fast\n - label Secure\n icon secure shield check\n\\`\\`\\`\n\n• sequence-* 模版\n\\`\\`\\`\ninfographic sequence-steps-simple\ndata\n sequences\n - label Step 1\n - label Step 2\n - label Step 3\n order asc\n\\`\\`\\`\n\n• hierarchy-* 模版\n\\`\\`\\`\ninfographic hierarchy-structure\ndata\n root\n label Company\n children\n - label Dept A\n - label Dept B\n\\`\\`\\`\n\n• compare-* 模版\n\\`\\`\\`\ninfographic compare-swot\ndata\n compares\n - label Strengths\n children\n - label Strong brand\n - label Loyal users\n - label Weaknesses\n children\n - label High cost\n - label Slow release\n\\`\\`\\`\n\n四象限图\n\\`\\`\\`\ninfographic compare-quadrant-quarter-simple-card\ndata\n compares\n - label High Impact & Low Effort\n - label High Impact & High Effort\n - label Low Impact & Low Effort\n - label Low Impact & High Effort\n\\`\\`\\`\n\n• chart-* 模版\n\\`\\`\\`\ninfographic chart-column-simple\ndata\n values\n - label Visits\n value 1280\n - label Conversion\n value 12.4\n\\`\\`\\`\n\n• relation-* 模版\n边标签写法:A -label-> B 或 A -->|label| B\n\\`\\`\\`\ninfographic relation-dagre-flow-tb-simple-circle-node\ndata\n nodes\n - id A\n label Node A\n - id B\n label Node B\n relations\n A - approves -> B\n A -->|blocks| B\n\\`\\`\\`\n\n• 兜底 items 示例\n\\`\\`\\`\ninfographic list-row-horizontal-icon-arrow\ndata\n items\n - label Item A\n desc Description\n icon sun\n - label Item B\n desc Description\n icon moon\n\\`\\`\\`\n`.trim();\n\n// ─── 可用模板列表 ───────────────────────────────────────────────────\n\nconst AVAILABLE_TEMPLATES = `\n### 可用模板\n\n• chart-bar-plain-text\n• chart-column-simple\n• chart-line-plain-text\n• chart-pie-compact-card\n• chart-pie-donut-pill-badge\n• chart-pie-donut-plain-text\n• chart-pie-plain-text\n• chart-wordcloud\n• compare-binary-horizontal-badge-card-arrow\n• compare-binary-horizontal-simple-fold\n• compare-binary-horizontal-underline-text-vs\n• compare-hierarchy-left-right-circle-node-pill-badge\n• compare-quadrant-quarter-circular\n• compare-quadrant-quarter-simple-card\n• compare-swot\n• hierarchy-mindmap-branch-gradient-capsule-item\n• hierarchy-mindmap-level-gradient-compact-card\n• hierarchy-structure\n• hierarchy-tree-curved-line-rounded-rect-node\n• hierarchy-tree-tech-style-badge-card\n• hierarchy-tree-tech-style-capsule-item\n• list-column-done-list\n• list-column-simple-vertical-arrow\n• list-column-vertical-icon-arrow\n• list-grid-badge-card\n• list-grid-candy-card-lite\n• list-grid-ribbon-card\n• list-row-horizontal-icon-arrow\n• list-sector-plain-text\n• list-waterfall-badge-card\n• list-waterfall-compact-card\n• list-zigzag-down-compact-card\n• list-zigzag-down-simple\n• list-zigzag-up-compact-card\n• list-zigzag-up-simple\n• relation-dagre-flow-tb-animated-badge-card\n• relation-dagre-flow-tb-animated-simple-circle-node\n• relation-dagre-flow-tb-badge-card\n• relation-dagre-flow-tb-simple-circle-node\n• sequence-ascending-stairs-3d-underline-text\n• sequence-ascending-steps\n• sequence-circular-simple\n• sequence-color-snake-steps-horizontal-icon-line\n• sequence-cylinders-3d-simple\n• sequence-filter-mesh-simple\n• sequence-funnel-simple\n• sequence-horizontal-zigzag-underline-text\n• sequence-mountain-underline-text\n• sequence-pyramid-simple\n• sequence-roadmap-vertical-plain-text\n• sequence-roadmap-vertical-simple\n• sequence-snake-steps-compact-card\n• sequence-snake-steps-simple\n• sequence-snake-steps-underline-text\n• sequence-stairs-front-compact-card\n• sequence-stairs-front-pill-badge\n• sequence-timeline-rounded-rect-node\n• sequence-timeline-simple\n• sequence-zigzag-pucks-3d-simple\n• sequence-zigzag-steps-underline-text\n\n模板选择建议:\n• 严格顺序(流程/步骤/发展趋势)→ sequence-*\n - 时间线 → sequence-timeline-*\n - 阶梯图 → sequence-stairs-*\n - 路线图 → sequence-roadmap-vertical-*\n - 折线路径 → sequence-zigzag-*\n - 环形进度 → sequence-circular-simple\n - 彩色蛇形步骤 → sequence-color-snake-steps-*\n - 金字塔 → sequence-pyramid-simple\n• 观点列举 → list-row-* 或 list-column-*\n• 二元对比(利弊)→ compare-binary-*\n• SWOT → compare-swot\n• 层级结构(树图)→ hierarchy-tree-*\n• 数据图表 → chart-*\n• 象限分析 → quadrant-*\n• 网格列表(要点)→ list-grid-*\n• 关系展示 → relation-*\n• 词云 → chart-wordcloud\n• 思维导图 → hierarchy-mindmap-*\n`.trim();\n\n// ─── 完整示例 ───────────────────────────────────────────────────────\n\nconst FULL_EXAMPLE = `\n### 完整示例\n\n绘制互联网技术演进信息图:\n\\`\\`\\`\ninfographic list-row-horizontal-icon-arrow\ndata\n title Internet Technology Evolution\n desc From Web 1.0 to AI era, key milestones\n lists\n - time 1991\n label Web 1.0\n desc Tim Berners-Lee published the first website, opening the Internet era\n icon web\n - time 2004\n label Web 2.0\n desc Social media and user-generated content become mainstream\n icon account multiple\n - time 2007\n label Mobile\n desc iPhone released, smartphone changes the world\n icon cellphone\n - time 2015\n label Cloud Native\n desc Containerization and microservices architecture are widely used\n icon cloud\n - time 2020\n label Low Code\n desc Visual development lowers the technology threshold\n icon application brackets\n - time 2023\n label AI Large Model\n desc ChatGPT ignites the generative AI revolution\n icon brain\n\\`\\`\\`\n`.trim();\n\n// ─── 导出:信息图创建者系统提示词 ───────────────────────────────────\n\n/**\n * 信息图创建者的完整 System Prompt。\n * 用于指导 LLM 根据用户自然语言需求,生成合法的 AntV Infographic DSL 语法。\n */\nexport const INFOGRAPHIC_CREATOR_SYSTEM_PROMPT = `\n你是一位专业的信息图设计专家。你的任务是根据用户的需求,生成 AntV Infographic DSL 语法来创建精美的信息图。\n\n信息图(Infographic)将数据、信息与知识转化为可感知的视觉语言。它结合视觉设计与数据可视化,用直观符号压缩复杂信息,帮助受众快速理解并记住要点。\n\nInfographic = Information Structure + Visual Expression\n\n你需要严格遵守以下规范来生成 AntV Infographic 语法:\n\n${SYNTAX_SPEC}\n\n${DATA_EXAMPLES}\n\n${AVAILABLE_TEMPLATES}\n\n${FULL_EXAMPLE}\n\n## 重要约束\n\n1. **只输出纯 DSL 语法**:不要输出任何 Markdown 代码块标记(如 \\\\\\`\\\\\\`\\\\\\`)、解释性文字、JSON 或其他格式。直接输出以 \\`infographic <template-name>\\` 开头的 DSL 文本。\n2. **必须尊重用户输入语言**:如果用户使用中文描述需求,DSL 中所有文本内容(title、desc、label 等)也必须使用中文。\n3. **选择最合适的模板**:根据用户需求的信息结构(列表、流程、对比、层级等)选择最匹配的模板。\n4. **数据完整性**:确保生成的数据结构完整,包含 title、desc 以及与模板匹配的主数据字段。\n5. **配色和主题**:除非用户特别要求,否则使用一组美观且协调的默认配色。\n`.trim();\n\n/**\n * 自我修正提示词模板。\n * 当 SSR 渲染失败时,将报错信息注入后发给 LLM 进行修正。\n */\nexport const SELF_CORRECTION_PROMPT_TEMPLATE = `\n之前你生成的 AntV Infographic DSL 语法在渲染时出错了。\n\n报错信息:\n{error}\n\n之前生成的语法:\n{syntax}\n\n请修正语法并重新输出。要求:\n1. 只输出修正后的纯 DSL 语法,不要添加任何解释或 Markdown 格式。\n2. 确保第一行是 \\`infographic <template-name>\\`。\n3. 确保数据结构符合所选模板的规范。\n4. 修复导致错误的具体问题。\n`.trim();\n","import ora, { type Ora } from \"ora\";\n\n/**\n * 终端 Loading 动画封装。\n * 提供 start / succeed / fail / update 等便捷方法。\n */\n\nlet currentSpinner: Ora | null = null;\n\nexport function startSpinner(text: string): Ora {\n // 如果之前有未关闭的 spinner,先停掉\n if (currentSpinner?.isSpinning) {\n currentSpinner.stop();\n }\n currentSpinner = ora({ text, stream: process.stderr }).start();\n return currentSpinner;\n}\n\nexport function succeedSpinner(text?: string): void {\n currentSpinner?.succeed(text);\n currentSpinner = null;\n}\n\nexport function failSpinner(text?: string): void {\n currentSpinner?.fail(text);\n currentSpinner = null;\n}\n\nexport function updateSpinner(text: string): void {\n if (currentSpinner) {\n currentSpinner.text = text;\n }\n}\n\nexport function stopSpinner(): void {\n currentSpinner?.stop();\n currentSpinner = null;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { renderToString } from \"@antv/infographic/ssr\";\nimport { getConfig } from \"../config/index.js\";\n\n/**\n * 渲染结果\n */\nexport interface RenderResult {\n /** 生成的 SVG 字符串 */\n svg: string;\n}\n\n/**\n * 使用 @antv/infographic SSR 将 DSL 语法渲染为 SVG 字符串。\n *\n * @param syntax AntV Infographic DSL 语法文本\n * @returns SVG 字符串\n * @throws 渲染失败时抛出带有详细错误信息的 Error\n */\nexport async function renderDSLToSVG(syntax: string): Promise<string> {\n try {\n const svgString = await renderToString(syntax);\n if (!svgString || svgString.trim().length === 0) {\n throw new Error(\"renderToString 返回了空的 SVG 内容\");\n }\n return svgString;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`SSR 渲染失败: ${message}`);\n }\n}\n\n/**\n * 将 SVG 字符串写入指定路径。\n * 自动创建所需的中间目录。\n *\n * @param outputPath 输出文件路径\n * @param svgContent SVG 字符串内容\n */\nexport async function writeSVGFile(\n outputPath: string,\n svgContent: string,\n): Promise<void> {\n const absolutePath = path.resolve(outputPath);\n const dir = path.dirname(absolutePath);\n\n // 确保输出目录存在\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absolutePath, svgContent, \"utf-8\");\n}\n\n/**\n * 将 DSL 语法文本写入指定路径。\n * 自动创建所需的中间目录。\n *\n * @param outputPath 输出文件路径\n * @param dslContent DSL 语法字符串\n */\nexport async function writeDSLFile(\n outputPath: string,\n dslContent: string,\n): Promise<void> {\n const absolutePath = path.resolve(outputPath);\n const dir = path.dirname(absolutePath);\n\n // 确保输出目录存在\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absolutePath, dslContent, \"utf-8\");\n}\n\n/**\n * 根据用户输入的输出路径,补全默认值。\n * 支持配置默认输出目录,如果用户未指定,默认为 defaultOutputDir 下的 infographic-output.svg。\n *\n * @param userOutput 用户指定的输出路径(可选)\n * @returns 完整的输出路径(绝对路径或相对路径)\n */\nexport function resolveOutputPath(userOutput?: string): string {\n const defaultDir = getConfig(\"defaultOutputDir\") || \".\";\n\n if (userOutput) {\n // 用户指定了输出路径\n // 确保扩展名是 .svg\n const withExt = userOutput.endsWith(\".svg\")\n ? userOutput\n : userOutput + \".svg\";\n\n // 如果是绝对路径,直接返回;否则相对于默认目录\n if (path.isAbsolute(withExt)) {\n return withExt;\n }\n return path.resolve(defaultDir, withExt);\n }\n\n // 用户未指定,使用默认输出目录 + 默认文件名\n return path.resolve(defaultDir, \"infographic-output.svg\");\n}\n"],"mappings":"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","names":["pc","pc","program","path","path","path","program","path","fileURLToPath","__dirname","fileURLToPath"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "infographic-gen",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "AI-powered CLI tool to generate AntV Infographic SVGs from natural language prompts",
5
5
  "license": "MIT",
6
6
  "author": "Your Name <your.email@example.com>",