dgxay-code-cli 1.0.0 → 1.1.0
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-zh.md +50 -8
- package/README.md +50 -9
- package/package.json +1 -1
- package/src/cli/ansi.js +38 -8
- package/src/cli/approval.js +11 -11
- package/src/cli/editor.js +456 -202
- package/src/cli/i18n.js +276 -0
- package/src/cli/index.js +34 -34
- package/src/cli/print.js +5 -5
- package/src/cli/render.js +147 -76
- package/src/cli/repl.js +205 -141
- package/src/cli/slash.js +29 -28
- package/src/cli/ui.js +8 -8
- package/src/commands/chat.js +45 -45
- package/src/commands/config.js +81 -81
- package/src/commands/context.js +5 -5
- package/src/commands/doctor.js +34 -34
- package/src/commands/export.js +13 -13
- package/src/commands/mcp.js +51 -51
- package/src/commands/model.js +38 -38
- package/src/commands/oauth.js +61 -61
- package/src/commands/permission.js +19 -19
- package/src/commands/provider.js +70 -70
- package/src/commands/run.js +20 -20
- package/src/commands/skill.js +15 -15
- package/src/commands/workspace.js +18 -18
- package/src/core/agent.js +19 -18
- package/src/core/llm.js +10 -10
- package/src/core/mcp.js +5 -5
- package/src/core/oauth.js +36 -36
- package/src/core/prompt.js +46 -46
- package/src/core/sessions.js +7 -7
- package/src/core/tools.js +24 -24
- package/src/services/input.js +1 -1
- package/src/services/settings.js +28 -28
- package/src/services/skills.js +1 -1
- package/src/services/terminal.js +3 -3
package/src/cli/i18n.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 界面文案:默认英文,可用 DGXAY_LANG=zh 切回中文。
|
|
5
|
+
*
|
|
6
|
+
* 只负责「界面」文字;AI 回复语言由系统提示决定(见 core/prompt.js)。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const EN = {
|
|
10
|
+
// 启动 / 横幅
|
|
11
|
+
tagline: 'multi-protocol AI coding assistant',
|
|
12
|
+
hint_start: 'Type / for commands · ! for shell · ↑ history · Ctrl+C to interrupt · Ctrl+D to exit',
|
|
13
|
+
|
|
14
|
+
// 状态行
|
|
15
|
+
status_model: 'model',
|
|
16
|
+
status_workspace: 'workspace',
|
|
17
|
+
status_permission: 'permission',
|
|
18
|
+
status_mode: 'mode',
|
|
19
|
+
mode_chat: 'chat',
|
|
20
|
+
mode_work: 'work',
|
|
21
|
+
|
|
22
|
+
// 权限
|
|
23
|
+
perm_none: 'no permission',
|
|
24
|
+
perm_normal: 'normal',
|
|
25
|
+
perm_auto: 'auto review',
|
|
26
|
+
perm_full: 'full access',
|
|
27
|
+
|
|
28
|
+
// 对话
|
|
29
|
+
you: 'You',
|
|
30
|
+
assistant: 'DgxayCode',
|
|
31
|
+
thinking: 'Thinking',
|
|
32
|
+
thought_for: 'Thought for',
|
|
33
|
+
thinking_now: 'Thinking…',
|
|
34
|
+
tokens: 'tokens',
|
|
35
|
+
in_out: 'in /',
|
|
36
|
+
out: 'out',
|
|
37
|
+
no_content: '(the model returned nothing)',
|
|
38
|
+
generation_error: 'Error',
|
|
39
|
+
stopped: 'Stopped',
|
|
40
|
+
interrupted: 'Interrupting…',
|
|
41
|
+
waiting_confirm: 'waiting for your confirmation',
|
|
42
|
+
reviewing: 'auto-reviewing',
|
|
43
|
+
review_allow: 'auto-review allowed',
|
|
44
|
+
review_suspect: 'auto-review flagged this, asking you',
|
|
45
|
+
empty_input: 'Nothing to send',
|
|
46
|
+
|
|
47
|
+
// 授权
|
|
48
|
+
approval_title: 'Permission required',
|
|
49
|
+
approval_tool: 'AI wants to run a tool',
|
|
50
|
+
approval_terminal: 'AI wants to run a shell command',
|
|
51
|
+
approval_op: 'operation',
|
|
52
|
+
approval_ask: 'Allow this?',
|
|
53
|
+
approval_yes: '[y] yes',
|
|
54
|
+
approval_no: '[n] no',
|
|
55
|
+
approval_allowed: 'allowed',
|
|
56
|
+
approval_denied: 'denied',
|
|
57
|
+
approval_timeout: 'timed out',
|
|
58
|
+
approval_noninteractive: 'not an interactive terminal, denied automatically',
|
|
59
|
+
|
|
60
|
+
// 输入框
|
|
61
|
+
box_placeholder: 'Ask anything…',
|
|
62
|
+
box_hint: 'Enter to send · \\ to continue · Tab to complete · ↑ history',
|
|
63
|
+
|
|
64
|
+
// 斜杠命令菜单
|
|
65
|
+
menu_title: 'Commands',
|
|
66
|
+
menu_hint: '↑↓ select · Tab complete · Enter run · Esc close',
|
|
67
|
+
|
|
68
|
+
// 文件 / 工具
|
|
69
|
+
tool_list: 'List',
|
|
70
|
+
tool_read: 'Read',
|
|
71
|
+
tool_write: 'Write',
|
|
72
|
+
tool_mkdir: 'Create dir',
|
|
73
|
+
tool_delete: 'Delete',
|
|
74
|
+
tool_command: 'Run',
|
|
75
|
+
tool_fetch: 'Fetch',
|
|
76
|
+
tool_mcp: 'Install MCP',
|
|
77
|
+
file_created: 'created',
|
|
78
|
+
file_updated: 'updated',
|
|
79
|
+
file_deleted: 'deleted',
|
|
80
|
+
chars: 'chars',
|
|
81
|
+
lines: 'lines',
|
|
82
|
+
items: 'items',
|
|
83
|
+
exit_code: 'exit code',
|
|
84
|
+
no_output: 'no output',
|
|
85
|
+
|
|
86
|
+
// 斜杠命令输出
|
|
87
|
+
cmd_unknown: 'Unknown command',
|
|
88
|
+
cmd_help_hint: 'Type /help to list all commands',
|
|
89
|
+
new_chat: 'Started a new conversation',
|
|
90
|
+
restored: 'Restored',
|
|
91
|
+
messages: 'messages',
|
|
92
|
+
deleted: 'Deleted',
|
|
93
|
+
renamed: 'Renamed to',
|
|
94
|
+
no_chats: 'No saved conversations yet',
|
|
95
|
+
compressed: 'Context compressed',
|
|
96
|
+
compress_failed: 'Compression failed',
|
|
97
|
+
compress_running: 'Compressing context…',
|
|
98
|
+
compress_nothing: 'Nothing to compress in this conversation',
|
|
99
|
+
wait_current: 'Please wait for the current reply to finish',
|
|
100
|
+
no_model: 'No model configured. Run dgxay config init',
|
|
101
|
+
model_switched: 'Switched to',
|
|
102
|
+
provider_switched: 'Switched to',
|
|
103
|
+
skill_enabled: 'Skill enabled for this conversation',
|
|
104
|
+
skill_none: 'No skills installed. Put a name.md or <dir>/SKILL.md into ~/.dcb/skills',
|
|
105
|
+
skill_not_found: 'Skill not found',
|
|
106
|
+
skills_off: 'Skill disabled',
|
|
107
|
+
perms_title: 'Permissions',
|
|
108
|
+
perm_set: 'Permission set to',
|
|
109
|
+
perm_auto_unavailable: 'Auto review unavailable: no review model configured',
|
|
110
|
+
perm_full_warning: 'Full access lets the AI run any command and write any file without asking',
|
|
111
|
+
mode_set: 'Mode set to',
|
|
112
|
+
workspace_set: 'Workspace',
|
|
113
|
+
dir_not_found: 'Directory not found',
|
|
114
|
+
not_a_dir: 'Not a directory',
|
|
115
|
+
no_workspace: 'no workspace selected',
|
|
116
|
+
context_title: 'Context',
|
|
117
|
+
used: 'used',
|
|
118
|
+
remaining: 'remaining',
|
|
119
|
+
context_note: 'Estimated from character count; real usage is reported by the model.',
|
|
120
|
+
mcp_title: 'MCP servers',
|
|
121
|
+
mcp_none: 'No MCP servers. Add one with dgxay mcp add',
|
|
122
|
+
mcp_unknown: 'Unknown /mcp action',
|
|
123
|
+
bye: 'Bye. Run dgxay -c to continue the last conversation.',
|
|
124
|
+
cancelled: 'Cancelled',
|
|
125
|
+
session_not_found: 'Conversation not found',
|
|
126
|
+
delete_confirm: 'Delete this conversation?',
|
|
127
|
+
terminal_running: 'A command is already running',
|
|
128
|
+
command_empty: 'Enter a command first',
|
|
129
|
+
perm_denied_terminal: 'No permission to run shell commands',
|
|
130
|
+
model_list_title: 'Models',
|
|
131
|
+
provider_list_title: 'Providers',
|
|
132
|
+
current: 'current',
|
|
133
|
+
|
|
134
|
+
// 键盘提示
|
|
135
|
+
key_hint_and: 'and',
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
// 错误
|
|
139
|
+
err_title: 'Error',
|
|
140
|
+
err_network: 'Network error',
|
|
141
|
+
err_unauthorized: 'Unauthorized: check your API key or reconnect the account'
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const ZH = {
|
|
145
|
+
tagline: '多协议 AI 编码助手',
|
|
146
|
+
hint_start: '输入 / 查看命令 · ! 执行终端 · ↑ 历史 · Ctrl+C 中断 · Ctrl+D 退出',
|
|
147
|
+
status_model: '模型',
|
|
148
|
+
status_workspace: '工作空间',
|
|
149
|
+
status_permission: '权限',
|
|
150
|
+
status_mode: '模式',
|
|
151
|
+
mode_chat: '对话',
|
|
152
|
+
mode_work: '工作',
|
|
153
|
+
perm_none: '无权限',
|
|
154
|
+
perm_normal: '普通权限',
|
|
155
|
+
perm_auto: '自动审查',
|
|
156
|
+
perm_full: '完全权限',
|
|
157
|
+
you: '你',
|
|
158
|
+
assistant: 'DgxayCode',
|
|
159
|
+
thinking: '思考',
|
|
160
|
+
thought_for: '已思考',
|
|
161
|
+
thinking_now: '思考中…',
|
|
162
|
+
tokens: 'tokens',
|
|
163
|
+
in_out: 'in /',
|
|
164
|
+
out: 'out',
|
|
165
|
+
no_content: '(模型没有返回内容)',
|
|
166
|
+
generation_error: '出错了',
|
|
167
|
+
stopped: '已停止',
|
|
168
|
+
interrupted: '正在中断…',
|
|
169
|
+
waiting_confirm: '等待确认',
|
|
170
|
+
reviewing: '正在自动审查',
|
|
171
|
+
review_allow: '自动审查放行',
|
|
172
|
+
review_suspect: '自动审查判定可疑,转交确认',
|
|
173
|
+
empty_input: '没有可发送的内容',
|
|
174
|
+
approval_title: '需要授权',
|
|
175
|
+
approval_tool: 'AI 请求执行操作',
|
|
176
|
+
approval_terminal: 'AI 请求执行终端命令',
|
|
177
|
+
approval_op: '操作',
|
|
178
|
+
approval_ask: '允许执行吗?',
|
|
179
|
+
approval_yes: '[y] 允许',
|
|
180
|
+
approval_no: '[n] 拒绝',
|
|
181
|
+
approval_allowed: '允许',
|
|
182
|
+
approval_denied: '已拒绝',
|
|
183
|
+
approval_timeout: '等待超时,已拒绝',
|
|
184
|
+
approval_noninteractive: '当前不是交互终端,已自动拒绝',
|
|
185
|
+
box_placeholder: '问点什么…',
|
|
186
|
+
box_hint: 'Enter 发送 · \\ 续行 · Tab 补全 · ↑ 历史',
|
|
187
|
+
menu_title: '斜杠命令',
|
|
188
|
+
menu_hint: '↑↓ 选择 · Tab 补全 · Enter 执行 · Esc 关闭',
|
|
189
|
+
tool_list: '列出目录',
|
|
190
|
+
tool_read: '读取文件',
|
|
191
|
+
tool_write: '写入文件',
|
|
192
|
+
tool_mkdir: '创建目录',
|
|
193
|
+
tool_delete: '删除',
|
|
194
|
+
tool_command: '执行命令',
|
|
195
|
+
tool_fetch: '访问网络',
|
|
196
|
+
tool_mcp: '安装 MCP',
|
|
197
|
+
file_created: '创建',
|
|
198
|
+
file_updated: '更新',
|
|
199
|
+
file_deleted: '删除',
|
|
200
|
+
chars: '字符',
|
|
201
|
+
lines: '行',
|
|
202
|
+
items: '项',
|
|
203
|
+
exit_code: '退出码',
|
|
204
|
+
no_output: '无输出',
|
|
205
|
+
cmd_unknown: '未知命令',
|
|
206
|
+
cmd_help_hint: '输入 /help 查看全部命令',
|
|
207
|
+
new_chat: '已开始新对话',
|
|
208
|
+
restored: '已恢复',
|
|
209
|
+
messages: '条消息',
|
|
210
|
+
deleted: '已删除',
|
|
211
|
+
renamed: '已重命名为',
|
|
212
|
+
no_chats: '还没有历史对话',
|
|
213
|
+
compressed: '上下文已压缩',
|
|
214
|
+
compress_failed: '压缩失败',
|
|
215
|
+
compress_running: '正在压缩上下文…',
|
|
216
|
+
compress_nothing: '当前对话还没有可压缩的内容',
|
|
217
|
+
wait_current: '请等待当前回复结束',
|
|
218
|
+
no_model: '还没有可用模型,运行 dgxay config init',
|
|
219
|
+
model_switched: '已切换到',
|
|
220
|
+
provider_switched: '已切换到',
|
|
221
|
+
skill_enabled: '已在本次对话启用技能',
|
|
222
|
+
skill_none: '还没有安装技能。把 name.md 或 <目录>/SKILL.md 放到 ~/.dcb/skills',
|
|
223
|
+
skill_not_found: '未找到该技能',
|
|
224
|
+
skills_off: '已关闭技能',
|
|
225
|
+
perms_title: '权限',
|
|
226
|
+
perm_set: '权限已切换为',
|
|
227
|
+
perm_auto_unavailable: '自动审查不可用:尚未配置审查模型',
|
|
228
|
+
perm_full_warning: '完全权限下 AI 可以执行任意命令、读写任意文件,且不会询问',
|
|
229
|
+
mode_set: '模式已切换为',
|
|
230
|
+
workspace_set: '工作空间',
|
|
231
|
+
dir_not_found: '目录不存在',
|
|
232
|
+
not_a_dir: '不是文件夹',
|
|
233
|
+
no_workspace: '未选择工作空间',
|
|
234
|
+
context_title: '上下文',
|
|
235
|
+
used: '已用',
|
|
236
|
+
remaining: '剩余',
|
|
237
|
+
context_note: '按字符启发式估算,实际 token 以模型 usage 为准。',
|
|
238
|
+
mcp_title: 'MCP Server',
|
|
239
|
+
mcp_none: '还没有 MCP Server,用 dgxay mcp add 添加',
|
|
240
|
+
mcp_unknown: '未知的 /mcp 子命令',
|
|
241
|
+
bye: '再见。用 dgxay -c 继续上一次对话。',
|
|
242
|
+
cancelled: '已取消',
|
|
243
|
+
session_not_found: '找不到会话',
|
|
244
|
+
delete_confirm: '删除这段对话?',
|
|
245
|
+
terminal_running: '已有命令正在执行',
|
|
246
|
+
command_empty: '请输入要执行的终端命令',
|
|
247
|
+
perm_denied_terminal: '无权限模式禁止执行终端命令',
|
|
248
|
+
model_list_title: '模型',
|
|
249
|
+
provider_list_title: '供应商',
|
|
250
|
+
current: '当前',
|
|
251
|
+
key_hint_and: '与',
|
|
252
|
+
err_title: '出错了',
|
|
253
|
+
err_network: '网络错误',
|
|
254
|
+
err_unauthorized: '未授权:检查 API Key 或重新连接账户'
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const LANG = String(process.env.DGXAY_LANG || process.env.DGXAY_LANGUAGE || 'en').toLowerCase();
|
|
258
|
+
const TABLE = LANG.startsWith('zh') || LANG === 'cn' ? ZH : EN;
|
|
259
|
+
|
|
260
|
+
const LANGUAGES = { en: EN, zh: ZH };
|
|
261
|
+
|
|
262
|
+
/** 取文案;缺失时回退英文,再回退 key 本身(避免界面出现 undefined) */
|
|
263
|
+
function t(key, ...args) {
|
|
264
|
+
const table = TABLE[key] !== undefined ? TABLE : EN;
|
|
265
|
+
const raw = table[key] !== undefined ? table[key] : key;
|
|
266
|
+
return String(raw).replace(/\{(\d+)\}/g, (m, index) => {
|
|
267
|
+
const value = args[Number(index)];
|
|
268
|
+
return value === undefined ? m : String(value);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function lang() {
|
|
273
|
+
return TABLE === ZH ? 'zh' : 'en';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
module.exports = { t, lang, LANGUAGES, EN, ZH };
|
package/src/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* CLI 调度入口:全局选项 → 子命令分发 →
|
|
4
|
+
* CLI 调度入口:全局选项 → 子命令分发 → 无参数时Start the interactive shell。
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { COLORS } = require('./ansi');
|
|
@@ -11,23 +11,23 @@ const print = require('./print');
|
|
|
11
11
|
const { VERSION, BIN } = require('../services/version');
|
|
12
12
|
|
|
13
13
|
const GLOBAL_OPTIONS = [
|
|
14
|
-
{ name: 'help', alias: 'h', type: 'boolean', desc: '
|
|
15
|
-
{ name: 'version', alias: 'v', type: 'boolean', desc: '
|
|
16
|
-
{ name: 'home', type: 'string', valueName: 'dir', desc: '
|
|
17
|
-
{ name: 'debug', type: 'boolean', desc: '
|
|
18
|
-
{ name: 'no-color', type: 'boolean', desc: '
|
|
19
|
-
{ name: 'print', alias: 'p', type: 'boolean', desc: '
|
|
20
|
-
{ name: 'prompt', type: 'string', valueName: 'text', desc: '
|
|
21
|
-
{ name: 'output', alias: 'o', type: 'string', valueName: 'format', desc: '
|
|
22
|
-
{ name: 'mode', alias: 'm', type: 'string', valueName: 'mode', desc: '
|
|
23
|
-
{ name: 'permission', type: 'string', valueName: 'level', desc: '
|
|
24
|
-
{ name: 'workspace', alias: 'C', type: 'string', valueName: 'dir', desc: '
|
|
25
|
-
{ name: 'model', type: 'string', valueName: 'id', desc: '
|
|
26
|
-
{ name: 'provider', type: 'string', valueName: 'name', desc: '
|
|
27
|
-
{ name: 'skill', type: 'string', valueName: 'name', desc: '
|
|
28
|
-
{ name: 'resume', alias: 'r', type: 'string', valueName: 'id|index', desc: '
|
|
29
|
-
{ name: 'continue', alias: 'c', type: 'boolean', desc: '
|
|
30
|
-
{ name: 'yes', alias: 'y', type: 'boolean', desc: '
|
|
14
|
+
{ name: 'help', alias: 'h', type: 'boolean', desc: 'Show help' },
|
|
15
|
+
{ name: 'version', alias: 'v', type: 'boolean', desc: 'Show version' },
|
|
16
|
+
{ name: 'home', type: 'string', valueName: 'dir', desc: 'Override the data directory (default ~/.dcb)' },
|
|
17
|
+
{ name: 'debug', type: 'boolean', desc: 'Print debug information and stack traces' },
|
|
18
|
+
{ name: 'no-color', type: 'boolean', desc: 'Disable colors (same as NO_COLOR=1)' },
|
|
19
|
+
{ name: 'print', alias: 'p', type: 'boolean', desc: 'One-shot: send a prompt, print the reply, exit' },
|
|
20
|
+
{ name: 'prompt', type: 'string', valueName: 'text', desc: 'Prompt for the one-shot run' },
|
|
21
|
+
{ name: 'output', alias: 'o', type: 'string', valueName: 'format', desc: 'Output format: text / json' },
|
|
22
|
+
{ name: 'mode', alias: 'm', type: 'string', valueName: 'mode', desc: 'Mode: chat / work' },
|
|
23
|
+
{ name: 'permission', type: 'string', valueName: 'level', desc: 'Permission: none / normal / auto / full' },
|
|
24
|
+
{ name: 'workspace', alias: 'C', type: 'string', valueName: 'dir', desc: 'Workspace directory' },
|
|
25
|
+
{ name: 'model', type: 'string', valueName: 'id', desc: 'Model id' },
|
|
26
|
+
{ name: 'provider', type: 'string', valueName: 'name', desc: 'Provider id or name' },
|
|
27
|
+
{ name: 'skill', type: 'string', valueName: 'name', desc: 'Skill to enable for this run' },
|
|
28
|
+
{ name: 'resume', alias: 'r', type: 'string', valueName: 'id|index', desc: 'Resume a conversation by index or id' },
|
|
29
|
+
{ name: 'continue', alias: 'c', type: 'boolean', desc: 'Resume the most recent conversation' },
|
|
30
|
+
{ name: 'yes', alias: 'y', type: 'boolean', desc: 'Auto-approve all permission requests (one-shot only)' }
|
|
31
31
|
];
|
|
32
32
|
|
|
33
33
|
const LOGO = [
|
|
@@ -42,33 +42,33 @@ const LOGO = [
|
|
|
42
42
|
function showBanner() {
|
|
43
43
|
for (const line of LOGO) process.stdout.write(`${COLORS.accent(line)}\n`);
|
|
44
44
|
process.stdout.write(
|
|
45
|
-
`${COLORS.faint(` v${VERSION} ·
|
|
45
|
+
`${COLORS.faint(` v${VERSION} · multi-protocol AI coding assistant · /help for commands · Ctrl+C to exit`)}\n\n`
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function showHelp() {
|
|
50
|
-
process.stdout.write(`\n${COLORS.bold(`${BIN} — DgxayCode
|
|
51
|
-
process.stdout.write(`${COLORS.faint('
|
|
52
|
-
process.stdout.write(`${COLORS.faint('
|
|
50
|
+
process.stdout.write(`\n${COLORS.bold(`${BIN} — DgxayCode CLI`)} ${COLORS.faint(`v${VERSION}`)}\n\n`);
|
|
51
|
+
process.stdout.write(`${COLORS.faint('Usage')}\n ${BIN} [options] [command] [args...]\n\n`);
|
|
52
|
+
process.stdout.write(`${COLORS.faint('Quick start')}\n`);
|
|
53
53
|
const rows = [
|
|
54
|
-
[`${BIN}`, '
|
|
55
|
-
[`${BIN} "
|
|
56
|
-
[`${BIN} run -p "..." -C ./project`, '
|
|
57
|
-
[`${BIN} config init`, '
|
|
58
|
-
[`${BIN} doctor`, '
|
|
59
|
-
[`${BIN}
|
|
54
|
+
[`${BIN}`, 'Start the interactive shell'],
|
|
55
|
+
[`${BIN} "write a python script"`, 'Ask once and exit'],
|
|
56
|
+
[`${BIN} run -p "..." -C ./project`, 'One-shot with a workspace'],
|
|
57
|
+
[`${BIN} config init`, 'First-time setup (provider + API key)'],
|
|
58
|
+
[`${BIN} doctor`, 'Self-check: config, paths, connectivity'],
|
|
59
|
+
[`${BIN} <command> --help`, 'Show detailed usage for a command']
|
|
60
60
|
];
|
|
61
61
|
const width = Math.max(...rows.map(([cmd]) => cmd.length));
|
|
62
62
|
for (const [cmd, desc] of rows) {
|
|
63
63
|
process.stdout.write(` ${COLORS.cyan(cmd.padEnd(width))} ${COLORS.faint(desc)}\n`);
|
|
64
64
|
}
|
|
65
|
-
process.stdout.write(`\n${COLORS.faint('
|
|
65
|
+
process.stdout.write(`\n${COLORS.faint('Commands')}\n`);
|
|
66
66
|
const nameWidth = Math.max(...COMMANDS.map((cmd) => cmd.name.length));
|
|
67
67
|
for (const cmd of COMMANDS) {
|
|
68
68
|
const aliases = cmd.aliases?.length ? COLORS.faint(` (${cmd.aliases.join(', ')})`) : '';
|
|
69
69
|
process.stdout.write(` ${COLORS.accent(cmd.name.padEnd(nameWidth))} ${cmd.summary || ''}${aliases}\n`);
|
|
70
70
|
}
|
|
71
|
-
process.stdout.write(`\n${COLORS.faint('
|
|
71
|
+
process.stdout.write(`\n${COLORS.faint('Global options')}\n`);
|
|
72
72
|
const flags = GLOBAL_OPTIONS.map((opt) => {
|
|
73
73
|
const alias = opt.alias ? `-${opt.alias}, ` : ' ';
|
|
74
74
|
const value = opt.type !== 'boolean' ? ` <${opt.valueName || opt.type}>` : '';
|
|
@@ -79,9 +79,9 @@ function showHelp() {
|
|
|
79
79
|
process.stdout.write(` ${COLORS.cyan(flag.padEnd(flagWidth))} ${COLORS.faint(desc)}\n`);
|
|
80
80
|
}
|
|
81
81
|
process.stdout.write(
|
|
82
|
-
`\n${COLORS.faint('
|
|
82
|
+
`\n${COLORS.faint('Notes')} Configuration and conversations live in ${COLORS.faint('~/.dcb')} (override with DGXAY_HOME). Run ${COLORS.faint(
|
|
83
83
|
`${BIN} config path`
|
|
84
|
-
)}
|
|
84
|
+
)} to see the paths.\n\n`
|
|
85
85
|
);
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -194,7 +194,7 @@ async function main(argv) {
|
|
|
194
194
|
} catch (err) {
|
|
195
195
|
if (err?.userError) {
|
|
196
196
|
print.fail(err.message);
|
|
197
|
-
print.hint(
|
|
197
|
+
print.hint(`Run ${BIN} ${command.name} --help for usage`);
|
|
198
198
|
return 2;
|
|
199
199
|
}
|
|
200
200
|
print.fail(err?.message || String(err));
|
|
@@ -203,7 +203,7 @@ async function main(argv) {
|
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
//
|
|
206
|
+
// 不是子命令:整串参数当作单次运行的提示词;否则Start the interactive shell
|
|
207
207
|
const prompt = parsed.positionals.join(' ').trim();
|
|
208
208
|
const repl = require('./repl');
|
|
209
209
|
try {
|
package/src/cli/print.js
CHANGED
|
@@ -103,29 +103,29 @@ function usage(command) {
|
|
|
103
103
|
write(`${COLORS.bold(`dgxay ${command.name}`)}${command.summary ? COLORS.faint(` — ${command.summary}`) : ''}`);
|
|
104
104
|
if (command.usage) {
|
|
105
105
|
blank();
|
|
106
|
-
write(COLORS.faint('
|
|
106
|
+
write(COLORS.faint('Usage'));
|
|
107
107
|
write(` ${command.usage}`);
|
|
108
108
|
}
|
|
109
109
|
if (command.examples?.length) {
|
|
110
110
|
blank();
|
|
111
|
-
write(COLORS.faint('
|
|
111
|
+
write(COLORS.faint('Examples'));
|
|
112
112
|
for (const example of command.examples) write(` ${COLORS.cyan(example)}`);
|
|
113
113
|
}
|
|
114
114
|
if (command.options?.length) {
|
|
115
115
|
blank();
|
|
116
|
-
write(COLORS.faint('
|
|
116
|
+
write(COLORS.faint('Options'));
|
|
117
117
|
const rows = command.options.map((opt) => {
|
|
118
118
|
const alias = opt.alias ? [].concat(opt.alias).map((a) => (a.length === 1 ? `-${a}` : a)).join(', ') : '';
|
|
119
119
|
const name = `--${opt.name}${opt.type && opt.type !== 'boolean' ? ` <${opt.valueName || opt.type}>` : ''}`;
|
|
120
120
|
return [alias ? `${alias}, ${name}` : name, opt.desc || ''];
|
|
121
121
|
});
|
|
122
|
-
rows.push(['-h, --help', '
|
|
122
|
+
rows.push(['-h, --help', 'Show help']);
|
|
123
123
|
const width = Math.max(...rows.map(([flag]) => displayWidth(flag)));
|
|
124
124
|
for (const [flag, desc] of rows) write(` ${COLORS.cyan(padWidth(flag, width))} ${COLORS.faint(desc)}`);
|
|
125
125
|
}
|
|
126
126
|
if (command.subcommands?.length) {
|
|
127
127
|
blank();
|
|
128
|
-
write(COLORS.faint('
|
|
128
|
+
write(COLORS.faint('Commands'));
|
|
129
129
|
const width = Math.max(...command.subcommands.map(([, name]) => displayWidth(name)));
|
|
130
130
|
for (const [name, desc] of command.subcommands) write(` ${COLORS.accent(padWidth(name, width))} ${desc}`);
|
|
131
131
|
}
|