clawmoney 0.15.55 → 0.15.56
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/commands/relay-setup.js +83 -91
- package/package.json +1 -1
|
@@ -11,7 +11,6 @@ import { setupCommand } from "./setup.js";
|
|
|
11
11
|
import { API_PRICES, PLATFORM_FEE } from "../relay/pricing.js";
|
|
12
12
|
import { hasClaudeFingerprint, bootstrapClaudeFingerprint, } from "../relay/upstream/claude-bootstrap.js";
|
|
13
13
|
import { hasGeminiFingerprint, bootstrapGeminiFingerprint, } from "../relay/upstream/gemini-bootstrap.js";
|
|
14
|
-
import { hasCodexFingerprint, bootstrapCodexFingerprint, } from "../relay/upstream/codex-bootstrap.js";
|
|
15
14
|
// ── Per-cli_type model catalogs ──
|
|
16
15
|
//
|
|
17
16
|
// `RECOMMENDED_MODELS` is what gets registered when the user picks "all
|
|
@@ -207,94 +206,42 @@ export async function relaySetupCommand() {
|
|
|
207
206
|
process.exit(0);
|
|
208
207
|
}
|
|
209
208
|
const selectedClis = familyChoice;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
// antigravity is handled separately via `clawmoney antigravity
|
|
226
|
-
// login` and doesn't need a fingerprint file.
|
|
227
|
-
const runCliBootstrap = async (cli) => {
|
|
228
|
-
let startLabel;
|
|
229
|
-
let run;
|
|
230
|
-
let check;
|
|
231
|
-
if (cli === "claude") {
|
|
232
|
-
if (hasClaudeFingerprint())
|
|
233
|
-
return;
|
|
234
|
-
startLabel = "Capturing Claude fingerprint (runs `claude -p hi` once, ~5-15s)";
|
|
235
|
-
check = hasClaudeFingerprint;
|
|
236
|
-
run = async () => {
|
|
237
|
-
const fp = await bootstrapClaudeFingerprint({ timeoutMs: 45_000 });
|
|
238
|
-
return `device=${fp.device_id.slice(0, 8)}… cc_version=${fp.cc_version || "?"}`;
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
else if (cli === "gemini") {
|
|
242
|
-
if (hasGeminiFingerprint())
|
|
243
|
-
return;
|
|
244
|
-
startLabel = "Capturing Gemini fingerprint (runs `gemini -p hi` once, ~10-20s)";
|
|
245
|
-
check = hasGeminiFingerprint;
|
|
246
|
-
run = async () => {
|
|
247
|
-
const fp = await bootstrapGeminiFingerprint({ timeoutMs: 60_000 });
|
|
248
|
-
return `project=${fp.project_id} cli_version=${fp.cli_version}`;
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
else if (cli === "codex") {
|
|
252
|
-
if (hasCodexFingerprint())
|
|
253
|
-
return;
|
|
254
|
-
startLabel = "Capturing Codex fingerprint (runs `codex -p hi` once, ~15-30s)";
|
|
255
|
-
check = hasCodexFingerprint;
|
|
256
|
-
run = async () => {
|
|
257
|
-
await bootstrapCodexFingerprint({ timeoutMs: 60_000 });
|
|
258
|
-
return "from chatgpt.com WS handshake";
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
// antigravity or unknown — skip, no fingerprint needed.
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
// In-place line replacement: print start line without a newline,
|
|
266
|
-
// then clear it on completion and print the result over the top.
|
|
267
|
-
// Uses readline.cursorTo/clearLine for terminal portability.
|
|
268
|
-
const startLine = `${chalk.gray("◇")} ${chalk.bold(startLabel)}`;
|
|
269
|
-
process.stdout.write(startLine);
|
|
270
|
-
const clearStartLine = () => {
|
|
271
|
-
try {
|
|
272
|
-
readline.cursorTo(process.stdout, 0);
|
|
273
|
-
readline.clearLine(process.stdout, 0);
|
|
274
|
-
}
|
|
275
|
-
catch {
|
|
276
|
-
process.stdout.write("\n");
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
try {
|
|
280
|
-
const summary = await run();
|
|
281
|
-
clearStartLine();
|
|
282
|
-
process.stdout.write(`${chalk.green("◆")} ${chalk.bold(cli)} fingerprint captured ` +
|
|
283
|
-
chalk.dim(`(${summary})`) +
|
|
284
|
-
"\n");
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
clearStartLine();
|
|
288
|
-
process.stdout.write(`${chalk.yellow("⚠")} ${chalk.bold(cli)} fingerprint capture failed: ${err.message}\n`);
|
|
289
|
-
log.message(chalk.dim(`${cli} providers will be registered but the daemon won't be able ` +
|
|
290
|
-
"to serve them until the fingerprint is bootstrapped. " +
|
|
291
|
-
`Make sure \`${cli}\` is installed and logged in, then re-run setup.`));
|
|
209
|
+
const runAllBootstraps = async () => {
|
|
210
|
+
const tasks = [];
|
|
211
|
+
if (selectedClis.includes("claude") && !hasClaudeFingerprint()) {
|
|
212
|
+
tasks.push(bootstrapClaudeFingerprint({ timeoutMs: 45_000 })
|
|
213
|
+
.then((fp) => ({
|
|
214
|
+
cli: "claude",
|
|
215
|
+
ok: true,
|
|
216
|
+
summary: `device=${fp.device_id.slice(0, 8)}… cc_version=${fp.cc_version || "?"}`,
|
|
217
|
+
}))
|
|
218
|
+
.catch((err) => ({
|
|
219
|
+
cli: "claude",
|
|
220
|
+
ok: false,
|
|
221
|
+
error: err.message,
|
|
222
|
+
})));
|
|
292
223
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
224
|
+
if (selectedClis.includes("gemini") && !hasGeminiFingerprint()) {
|
|
225
|
+
// Shorter timeout on gemini — recent CLI versions are flaky
|
|
226
|
+
// under our subprocess-intercept approach. 25s is enough for
|
|
227
|
+
// a working capture; beyond that we fall through to the
|
|
228
|
+
// manual instruction path cleanly.
|
|
229
|
+
tasks.push(bootstrapGeminiFingerprint({ timeoutMs: 25_000 })
|
|
230
|
+
.then((fp) => ({
|
|
231
|
+
cli: "gemini",
|
|
232
|
+
ok: true,
|
|
233
|
+
summary: `project=${fp.project_id} cli_version=${fp.cli_version}`,
|
|
234
|
+
}))
|
|
235
|
+
.catch((err) => ({
|
|
236
|
+
cli: "gemini",
|
|
237
|
+
ok: false,
|
|
238
|
+
error: err.message,
|
|
239
|
+
})));
|
|
297
240
|
}
|
|
241
|
+
// Codex intentionally omitted — codex-api.ts has safe defaults.
|
|
242
|
+
if (tasks.length === 0)
|
|
243
|
+
return [];
|
|
244
|
+
return Promise.all(tasks);
|
|
298
245
|
};
|
|
299
246
|
const registrations = [];
|
|
300
247
|
for (const cli of selectedClis) {
|
|
@@ -305,10 +252,6 @@ export async function relaySetupCommand() {
|
|
|
305
252
|
continue;
|
|
306
253
|
}
|
|
307
254
|
log.success(`${chalk.bold(cli)}: ${recommended.length} models ${chalk.dim("— " + recommended.join(", "))}`);
|
|
308
|
-
// Bootstrap the fingerprint for this cli right after its model
|
|
309
|
-
// line so the ◆ "fingerprint captured" message sits visually
|
|
310
|
-
// under its owning family (claude / codex / gemini / antigravity).
|
|
311
|
-
await runCliBootstrap(cli);
|
|
312
255
|
for (const model of recommended) {
|
|
313
256
|
const p = API_PRICES[model];
|
|
314
257
|
registrations.push({
|
|
@@ -323,6 +266,55 @@ export async function relaySetupCommand() {
|
|
|
323
266
|
cancel("No models selected — nothing to register");
|
|
324
267
|
process.exit(0);
|
|
325
268
|
}
|
|
269
|
+
// ── Step 3b: parallel fingerprint bootstrap for selected clis ──
|
|
270
|
+
//
|
|
271
|
+
// One "Configuring providers..." line that gets overwritten with
|
|
272
|
+
// the consolidated result. Claude and gemini run concurrently;
|
|
273
|
+
// codex is skipped (defaults OK); antigravity doesn't use a
|
|
274
|
+
// fingerprint file.
|
|
275
|
+
const startLine = `${chalk.gray("◇")} Configuring providers`;
|
|
276
|
+
process.stdout.write(startLine);
|
|
277
|
+
const tickEvery = 500;
|
|
278
|
+
const ticker = setInterval(() => {
|
|
279
|
+
process.stdout.write(chalk.dim("."));
|
|
280
|
+
}, tickEvery);
|
|
281
|
+
const results = await runAllBootstraps();
|
|
282
|
+
clearInterval(ticker);
|
|
283
|
+
try {
|
|
284
|
+
readline.cursorTo(process.stdout, 0);
|
|
285
|
+
readline.clearLine(process.stdout, 0);
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
process.stdout.write("\n");
|
|
289
|
+
}
|
|
290
|
+
if (results.length === 0) {
|
|
291
|
+
// No bootstraps needed — everything was already in place.
|
|
292
|
+
process.stdout.write(`${chalk.green("◆")} Providers configured ${chalk.dim("(fingerprints already in place)")}\n`);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
const okCount = results.filter((r) => r.ok).length;
|
|
296
|
+
const failCount = results.length - okCount;
|
|
297
|
+
if (failCount === 0) {
|
|
298
|
+
process.stdout.write(`${chalk.green("◆")} Providers configured ` +
|
|
299
|
+
chalk.dim(`(${okCount} fingerprint${okCount === 1 ? "" : "s"} captured: ${results
|
|
300
|
+
.map((r) => r.cli)
|
|
301
|
+
.join(", ")})`) +
|
|
302
|
+
"\n");
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
process.stdout.write(`${chalk.yellow("⚠")} Providers configured with warnings ` +
|
|
306
|
+
chalk.dim(`(${okCount} ok / ${failCount} failed)`) +
|
|
307
|
+
"\n");
|
|
308
|
+
for (const r of results) {
|
|
309
|
+
if (r.ok)
|
|
310
|
+
continue;
|
|
311
|
+
log.warn(`${chalk.bold(r.cli)} fingerprint capture failed: ${r.error ?? "unknown"}`);
|
|
312
|
+
log.message(chalk.dim(`${r.cli} providers will be registered but the daemon won't serve them until you ` +
|
|
313
|
+
`run \`node $(npm root -g)/clawmoney/scripts/capture-${r.cli}-request.mjs\` in one terminal ` +
|
|
314
|
+
`and \`<CLI env vars> ${r.cli} -p hi\` in another.`));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
326
318
|
// ── Step 4: per-provider daily quota share ──
|
|
327
319
|
//
|
|
328
320
|
// We deliberately don't show USD earnings projections in this prompt
|