@pikecode/api-key-manager 2.0.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/LICENSE +21 -0
- package/README.md +232 -0
- package/bin/akm.js +101 -0
- package/bin/cc.js +101 -0
- package/package.json +71 -0
- package/src/CommandRegistry.js +74 -0
- package/src/commands/BaseCommand.js +212 -0
- package/src/commands/add.js +514 -0
- package/src/commands/current.js +94 -0
- package/src/commands/edit.js +208 -0
- package/src/commands/list.js +122 -0
- package/src/commands/remove.js +150 -0
- package/src/commands/switch.js +1479 -0
- package/src/config.js +250 -0
- package/src/index.js +19 -0
- package/src/navigation/EscNavigationManager.js +213 -0
- package/src/utils/claude-settings.js +150 -0
- package/src/utils/config-opener.js +44 -0
- package/src/utils/env-launcher.js +80 -0
- package/src/utils/error-handler.js +53 -0
- package/src/utils/inquirer-setup.js +89 -0
- package/src/utils/logger.js +41 -0
- package/src/utils/provider-status-checker.js +210 -0
- package/src/utils/storage.js +55 -0
- package/src/utils/terminal-format.js +41 -0
- package/src/utils/ui-helper.js +227 -0
- package/src/utils/update-checker.js +121 -0
- package/src/utils/validator.js +157 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const { EscNavigationManager } = require('../navigation/EscNavigationManager');
|
|
4
|
+
const { Logger } = require('../utils/logger');
|
|
5
|
+
|
|
6
|
+
// 允许在 allowEmpty 启用时提交空字符串,而不是回退到默认值
|
|
7
|
+
const resolveInputPrompt = () => {
|
|
8
|
+
const promptFromModule = inquirer.prompt && inquirer.prompt.prompts && inquirer.prompt.prompts.input;
|
|
9
|
+
if (promptFromModule) {
|
|
10
|
+
return promptFromModule;
|
|
11
|
+
}
|
|
12
|
+
const promptFromRoot = inquirer.prompts && inquirer.prompts.input;
|
|
13
|
+
if (promptFromRoot) {
|
|
14
|
+
return promptFromRoot;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
return require('inquirer/lib/prompts/input');
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const InputPrompt = resolveInputPrompt();
|
|
24
|
+
if (InputPrompt && !InputPrompt.prototype.__allowEmptyPatched) {
|
|
25
|
+
const originalFilterInput = InputPrompt.prototype.filterInput;
|
|
26
|
+
const originalRun = InputPrompt.prototype._run;
|
|
27
|
+
|
|
28
|
+
InputPrompt.prototype.filterInput = function patchedFilterInput(input) {
|
|
29
|
+
if (this.opt && this.opt.allowEmpty && this.status === 'touched' && input === '') {
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
return originalFilterInput.call(this, input);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
InputPrompt.prototype._run = function patchedRun(cb) {
|
|
36
|
+
const result = originalRun.call(this, cb);
|
|
37
|
+
|
|
38
|
+
if (!this.__defaultPrefilled && this.opt && this.opt.prefillDefault) {
|
|
39
|
+
const defaultValue = this.opt.default;
|
|
40
|
+
if (defaultValue !== undefined && defaultValue !== null) {
|
|
41
|
+
const text = String(defaultValue);
|
|
42
|
+
if (text.length > 0) {
|
|
43
|
+
this.__defaultPrefilled = true;
|
|
44
|
+
this.status = 'touched';
|
|
45
|
+
this.rl.write(text);
|
|
46
|
+
this.rl.cursor = text.length;
|
|
47
|
+
this.render();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
InputPrompt.prototype.__allowEmptyPatched = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const ESC_CANCELLED_ERROR_CODE = 'ESC_CANCELLED';
|
|
59
|
+
|
|
60
|
+
class BaseCommand {
|
|
61
|
+
constructor(options = {}) {
|
|
62
|
+
const input = options.input || process.stdin;
|
|
63
|
+
this.escManager = new EscNavigationManager(input);
|
|
64
|
+
this.activePrompt = null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
isEscCancelled(error) {
|
|
68
|
+
return Boolean(error && error.code === ESC_CANCELLED_ERROR_CODE);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async prompt(questions) {
|
|
72
|
+
const promptPromise = inquirer.prompt(questions);
|
|
73
|
+
let settled = false;
|
|
74
|
+
|
|
75
|
+
return await new Promise((resolve, reject) => {
|
|
76
|
+
const cleanup = () => {
|
|
77
|
+
if (this.activePrompt && this.activePrompt.promise === promptPromise) {
|
|
78
|
+
this.activePrompt = null;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const cancel = () => {
|
|
83
|
+
if (settled) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
settled = true;
|
|
87
|
+
if (promptPromise.ui && typeof promptPromise.ui.close === 'function') {
|
|
88
|
+
promptPromise.ui.close();
|
|
89
|
+
}
|
|
90
|
+
cleanup();
|
|
91
|
+
const error = new Error('操作已通过 ESC 取消');
|
|
92
|
+
error.code = ESC_CANCELLED_ERROR_CODE;
|
|
93
|
+
reject(error);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
this.activePrompt = {
|
|
97
|
+
promise: promptPromise,
|
|
98
|
+
cancel
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
promptPromise
|
|
102
|
+
.then((answers) => {
|
|
103
|
+
if (settled) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
settled = true;
|
|
107
|
+
cleanup();
|
|
108
|
+
resolve(answers);
|
|
109
|
+
})
|
|
110
|
+
.catch((error) => {
|
|
111
|
+
if (settled) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
settled = true;
|
|
115
|
+
cleanup();
|
|
116
|
+
reject(error);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
cancelActivePrompt() {
|
|
122
|
+
if (this.activePrompt && typeof this.activePrompt.cancel === 'function') {
|
|
123
|
+
this.activePrompt.cancel();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
createESCListener(callback, returnMessage = '返回上级菜单', options = {}) {
|
|
128
|
+
if (!this.escManager || !this.escManager.isSupported()) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const handler = this.escManager.register({
|
|
133
|
+
once: options.once !== false,
|
|
134
|
+
postDelay: typeof options.postDelay === 'number' ? options.postDelay : undefined,
|
|
135
|
+
onTrigger: () => {
|
|
136
|
+
this.cancelActivePrompt();
|
|
137
|
+
this.clearScreen();
|
|
138
|
+
if (returnMessage) {
|
|
139
|
+
console.log(chalk.yellow(`🔙 ESC键 - ${returnMessage}`));
|
|
140
|
+
console.log();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (typeof callback === 'function') {
|
|
144
|
+
const delay = typeof options.callbackDelay === 'number' ? options.callbackDelay : 50;
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
try {
|
|
147
|
+
const result = callback();
|
|
148
|
+
if (result && typeof result.catch === 'function') {
|
|
149
|
+
result.catch((error) => {
|
|
150
|
+
if (!this.isEscCancelled(error)) {
|
|
151
|
+
Logger.error(`ESC回退回调执行失败: ${error.message}`);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (!this.isEscCancelled(error)) {
|
|
157
|
+
Logger.error(`ESC回退回调执行失败: ${error.message}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}, delay);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return handler;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
clearScreen() {
|
|
169
|
+
const clearSequence = process.platform === 'win32'
|
|
170
|
+
? '\x1b[3J\x1b[2J\x1b[0f'
|
|
171
|
+
: '\x1b[3J\x1b[2J\x1b[H';
|
|
172
|
+
process.stdout.write(clearSequence);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
removeESCListener(listener) {
|
|
176
|
+
if (!listener || !this.escManager) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
this.escManager.unregister(listener);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
cleanupAllListeners() {
|
|
184
|
+
if (this.escManager) {
|
|
185
|
+
this.escManager.reset();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async handleError(error, context) {
|
|
190
|
+
if (this.isEscCancelled(error)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
Logger.error(`${context}失败: ${error.message}`);
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async safeExecute(operation, context = '操作') {
|
|
198
|
+
try {
|
|
199
|
+
return await operation();
|
|
200
|
+
} catch (error) {
|
|
201
|
+
await this.handleError(error, context);
|
|
202
|
+
} finally {
|
|
203
|
+
this.cleanupAllListeners();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
destroy() {
|
|
208
|
+
this.cleanupAllListeners();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
module.exports = { BaseCommand, ESC_CANCELLED_ERROR_CODE };
|