archbyte 0.2.8 → 0.2.9
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/dist/cli/setup.js +80 -13
- package/package.json +1 -1
package/dist/cli/setup.js
CHANGED
|
@@ -11,7 +11,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
11
11
|
const __dirname = path.dirname(__filename);
|
|
12
12
|
const PROVIDERS = [
|
|
13
13
|
{ name: "anthropic", label: "Anthropic", hint: "Claude Sonnet / Opus" },
|
|
14
|
-
{ name: "openai", label: "OpenAI", hint: "
|
|
14
|
+
{ name: "openai", label: "OpenAI", hint: "GPT-5.2 / o4-mini" },
|
|
15
15
|
{ name: "google", label: "Google", hint: "Gemini Flash / Pro" },
|
|
16
16
|
];
|
|
17
17
|
const PROVIDER_MODELS = {
|
|
@@ -22,10 +22,9 @@ const PROVIDER_MODELS = {
|
|
|
22
22
|
{ id: "claude-opus-4-6", label: "Claude Opus 4.6", hint: "Most capable" },
|
|
23
23
|
],
|
|
24
24
|
openai: [
|
|
25
|
-
{ id: "", label: "Default (recommended)", hint: "
|
|
26
|
-
{ id: "gpt-5.2
|
|
27
|
-
{ id: "
|
|
28
|
-
{ id: "o3", label: "o3", hint: "Reasoning model" },
|
|
25
|
+
{ id: "", label: "Default (recommended)", hint: "GPT-5.2 for all agents" },
|
|
26
|
+
{ id: "gpt-5.2", label: "GPT-5.2", hint: "Latest flagship model" },
|
|
27
|
+
{ id: "o4-mini", label: "o4-mini", hint: "Fast reasoning model" },
|
|
29
28
|
],
|
|
30
29
|
google: [
|
|
31
30
|
{ id: "", label: "Default (recommended)", hint: "Flash for fast agents, Pro for connections" },
|
|
@@ -93,10 +92,47 @@ function askHidden(prompt) {
|
|
|
93
92
|
stdin.on("data", onData);
|
|
94
93
|
});
|
|
95
94
|
}
|
|
96
|
-
|
|
95
|
+
function askText(prompt) {
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
process.stdout.write(prompt);
|
|
98
|
+
const stdin = process.stdin;
|
|
99
|
+
const wasRaw = stdin.isRaw;
|
|
100
|
+
stdin.setRawMode(true);
|
|
101
|
+
stdin.resume();
|
|
102
|
+
stdin.setEncoding("utf8");
|
|
103
|
+
let input = "";
|
|
104
|
+
const onData = (data) => {
|
|
105
|
+
for (const ch of data) {
|
|
106
|
+
if (ch === "\n" || ch === "\r" || ch === "\u0004") {
|
|
107
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
108
|
+
stdin.pause();
|
|
109
|
+
stdin.removeListener("data", onData);
|
|
110
|
+
process.stdout.write("\n");
|
|
111
|
+
resolve(input);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
else if (ch === "\u0003") {
|
|
115
|
+
process.stdout.write("\n");
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
else if (ch === "\u007F" || ch === "\b") {
|
|
119
|
+
if (input.length > 0) {
|
|
120
|
+
input = input.slice(0, -1);
|
|
121
|
+
process.stdout.write("\b \b");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
input += ch;
|
|
126
|
+
process.stdout.write(ch);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
stdin.on("data", onData);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async function validateProviderSilent(providerName, apiKey, model) {
|
|
97
134
|
try {
|
|
98
135
|
const provider = createProvider({ provider: providerName, apiKey });
|
|
99
|
-
const model = resolveModel(providerName, "fast");
|
|
100
136
|
await provider.chat({
|
|
101
137
|
model,
|
|
102
138
|
system: "Reply with 'ok'.",
|
|
@@ -105,7 +141,11 @@ async function validateProviderSilent(providerName, apiKey) {
|
|
|
105
141
|
});
|
|
106
142
|
return true;
|
|
107
143
|
}
|
|
108
|
-
catch {
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (process.env.ARCHBYTE_DEBUG) {
|
|
146
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
147
|
+
console.log(chalk.red(`\n Validation error: ${msg}`));
|
|
148
|
+
}
|
|
109
149
|
return false;
|
|
110
150
|
}
|
|
111
151
|
}
|
|
@@ -163,7 +203,8 @@ export async function handleSetup() {
|
|
|
163
203
|
for (const p of configured) {
|
|
164
204
|
const active = p === config.provider ? chalk.green(" (active)") : "";
|
|
165
205
|
const model = profiles[p].model ? chalk.gray(` model: ${profiles[p].model}`) : "";
|
|
166
|
-
|
|
206
|
+
const email = profiles[p].email ? chalk.gray(` (${profiles[p].email})`) : "";
|
|
207
|
+
console.log(chalk.gray(` ${p}: ${maskKey(profiles[p].apiKey)}${email}${model}${active}`));
|
|
167
208
|
}
|
|
168
209
|
console.log();
|
|
169
210
|
}
|
|
@@ -213,6 +254,30 @@ export async function handleSetup() {
|
|
|
213
254
|
if (!profiles[provider])
|
|
214
255
|
profiles[provider] = { apiKey: "" };
|
|
215
256
|
profiles[provider].apiKey = apiKey;
|
|
257
|
+
// Step 2b: Email for this provider account (optional)
|
|
258
|
+
const existingEmail = profiles[provider].email;
|
|
259
|
+
if (existingEmail) {
|
|
260
|
+
console.log(chalk.gray(`\n Account email: ${existingEmail}`));
|
|
261
|
+
const emailIdx = await select(" Update email?", [
|
|
262
|
+
`Keep existing ${chalk.gray("(" + existingEmail + ")")}`,
|
|
263
|
+
"Enter new email",
|
|
264
|
+
"Skip",
|
|
265
|
+
]);
|
|
266
|
+
if (emailIdx === 1) {
|
|
267
|
+
const newEmail = await askText(chalk.bold(" Email: "));
|
|
268
|
+
if (newEmail) {
|
|
269
|
+
profiles[provider].email = newEmail;
|
|
270
|
+
console.log(chalk.green(` ✓ Email: ${newEmail}`));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const email = await askText(chalk.bold(` ${selected.label} account email ${chalk.gray("(optional, Enter to skip)")}: `));
|
|
276
|
+
if (email) {
|
|
277
|
+
profiles[provider].email = email;
|
|
278
|
+
console.log(chalk.green(` ✓ Email: ${email}`));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
216
281
|
// Step 3: Model selection
|
|
217
282
|
const models = PROVIDER_MODELS[provider];
|
|
218
283
|
if (models) {
|
|
@@ -232,9 +297,11 @@ export async function handleSetup() {
|
|
|
232
297
|
}
|
|
233
298
|
}
|
|
234
299
|
config.profiles = profiles;
|
|
300
|
+
// Validate with the model the user actually chose
|
|
301
|
+
const validationModel = profiles[provider].model ?? resolveModel(provider, "fast");
|
|
235
302
|
// Validate provider with spinner
|
|
236
|
-
const s = spinner(
|
|
237
|
-
let isValid = await validateProviderSilent(provider, apiKey);
|
|
303
|
+
const s = spinner(`Validating credentials with ${validationModel}`);
|
|
304
|
+
let isValid = await validateProviderSilent(provider, apiKey, validationModel);
|
|
238
305
|
s.stop(isValid ? "valid" : "invalid", isValid ? "green" : "red");
|
|
239
306
|
// Retry loop on failure
|
|
240
307
|
if (!isValid) {
|
|
@@ -248,8 +315,8 @@ export async function handleSetup() {
|
|
|
248
315
|
profiles[provider].apiKey = newKey;
|
|
249
316
|
console.log(chalk.green(` ✓ API key: ${maskKey(newKey)}`));
|
|
250
317
|
}
|
|
251
|
-
const s2 = spinner(
|
|
252
|
-
isValid = await validateProviderSilent(provider, profiles[provider].apiKey);
|
|
318
|
+
const s2 = spinner(`Validating credentials with ${validationModel}`);
|
|
319
|
+
isValid = await validateProviderSilent(provider, profiles[provider].apiKey, validationModel);
|
|
253
320
|
s2.stop(isValid ? "valid" : "invalid", isValid ? "green" : "red");
|
|
254
321
|
}
|
|
255
322
|
if (!isValid) {
|