clawmoney 0.13.2 → 0.13.4

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/index.js CHANGED
@@ -395,8 +395,8 @@ relay
395
395
  .option('--mode <mode>', 'Safety mode: chat, search, code, full', 'chat')
396
396
  .option('--concurrency <n>', 'Max concurrent requests', '5')
397
397
  .option('--daily-limit <usd>', 'Max daily spend in USD', '20')
398
- .option('--price-input <usd>', 'Price per 1M input tokens', '5')
399
- .option('--price-output <usd>', 'Price per 1M output tokens', '25')
398
+ .option('--price-input <usd>', 'Override input price per 1M (auto-populated from pricing.ts)')
399
+ .option('--price-output <usd>', 'Override output price per 1M (auto-populated from pricing.ts)')
400
400
  .action(async (options) => {
401
401
  try {
402
402
  await relayRegisterCommand(options);
@@ -72,14 +72,6 @@ export declare function configureAntigravityDispatcher(): void;
72
72
  export declare function ensureClawmoneyDir(): void;
73
73
  export declare function loadAccounts(): AntigravityAccountsFile;
74
74
  export declare function saveAccounts(file: AntigravityAccountsFile): void;
75
- /**
76
- * Discover the Google Cloud project ID associated with this Antigravity
77
- * account via `loadCodeAssist`. Required for every v1internal request.
78
- *
79
- * Some workspace / business accounts return an empty string here — we fall
80
- * back to `ANTIGRAVITY_DEFAULT_PROJECT_ID` in that case, matching the
81
- * sub2api and opencode-antigravity-auth behavior.
82
- */
83
75
  export declare function resolveAntigravityProjectId(accessToken: string): Promise<string>;
84
76
  export declare function configureAntigravityRateGuard(config?: RelayRateGuardConfig): void;
85
77
  export declare function getAntigravityRateGuardSnapshot(): ReturnType<RateGuard["currentLoad"]> | null;
@@ -69,6 +69,16 @@ const ANTIGRAVITY_ENDPOINTS = [
69
69
  ANTIGRAVITY_ENDPOINT_AUTOPUSH,
70
70
  ANTIGRAVITY_ENDPOINT_PROD,
71
71
  ];
72
+ // For project discovery (loadCodeAssist / onboardUser) we hit PROD first.
73
+ // sub2api and opencode-antigravity-auth both found that the sandbox daily/
74
+ // autopush endpoints often 404 on these setup calls even though they handle
75
+ // the generate path fine. Mirroring their order avoids the "no project →
76
+ // fallback to hardcoded rising-fact-p41fc → 403 API not enabled" trap.
77
+ const ANTIGRAVITY_LOAD_ENDPOINTS = [
78
+ ANTIGRAVITY_ENDPOINT_PROD,
79
+ ANTIGRAVITY_ENDPOINT_DAILY,
80
+ ANTIGRAVITY_ENDPOINT_AUTOPUSH,
81
+ ];
72
82
  const GENERATE_PATH = "/v1internal:generateContent";
73
83
  // Hardcoded fallback project ID used for workspace/business accounts that
74
84
  // don't return their own `cloudaicompanionProject` from `loadCodeAssist`. Same
@@ -271,8 +281,27 @@ async function getFreshAccount() {
271
281
  * back to `ANTIGRAVITY_DEFAULT_PROJECT_ID` in that case, matching the
272
282
  * sub2api and opencode-antigravity-auth behavior.
273
283
  */
274
- export async function resolveAntigravityProjectId(accessToken) {
275
- configureDispatcher();
284
+ function extractProjectId(raw) {
285
+ if (!raw)
286
+ return undefined;
287
+ const project = raw.cloudaicompanionProject;
288
+ if (typeof project === "string" && project)
289
+ return project;
290
+ if (project && typeof project === "object" && project.id)
291
+ return project.id;
292
+ return undefined;
293
+ }
294
+ function extractTierId(data) {
295
+ const pick = (t) => {
296
+ if (!t)
297
+ return undefined;
298
+ if (typeof t === "string")
299
+ return t || undefined;
300
+ return t.id || undefined;
301
+ };
302
+ return pick(data.paidTier) ?? pick(data.currentTier);
303
+ }
304
+ async function callLoadCodeAssist(accessToken) {
276
305
  const body = JSON.stringify({
277
306
  metadata: {
278
307
  ideType: "ANTIGRAVITY",
@@ -281,24 +310,82 @@ export async function resolveAntigravityProjectId(accessToken) {
281
310
  },
282
311
  });
283
312
  const headers = antigravityHeaders(accessToken);
284
- for (const baseEndpoint of ANTIGRAVITY_ENDPOINTS) {
313
+ for (const baseEndpoint of ANTIGRAVITY_LOAD_ENDPOINTS) {
285
314
  try {
286
315
  const resp = await fetchWithProxy(`${baseEndpoint}/v1internal:loadCodeAssist`, { method: "POST", headers, body });
287
- if (!resp.ok)
316
+ if (!resp.ok) {
317
+ logger.warn(`[antigravity-api] loadCodeAssist ${resp.status} at ${baseEndpoint}`);
288
318
  continue;
319
+ }
289
320
  const data = (await resp.json());
290
- const project = data.cloudaicompanionProject;
291
- if (typeof project === "string" && project)
292
- return project;
293
- if (project && typeof project === "object" && project.id) {
294
- return project.id;
321
+ return {
322
+ project: extractProjectId(data),
323
+ tier: extractTierId(data),
324
+ };
325
+ }
326
+ catch (err) {
327
+ logger.warn(`[antigravity-api] loadCodeAssist error at ${baseEndpoint}: ${err.message}`);
328
+ }
329
+ }
330
+ return null;
331
+ }
332
+ /**
333
+ * Trigger Google's onboarding flow so a fresh account gets a real project
334
+ * ID back. Some accounts (especially first-time Antigravity users) return
335
+ * an empty `cloudaicompanionProject` from loadCodeAssist; they have to be
336
+ * onboarded first. Mirrors sub2api's Client.OnboardUser retry/poll logic.
337
+ */
338
+ async function callOnboardUser(accessToken, tierId) {
339
+ const body = JSON.stringify({
340
+ tierId,
341
+ metadata: {
342
+ ideType: "ANTIGRAVITY",
343
+ platform: "PLATFORM_UNSPECIFIED",
344
+ pluginType: "GEMINI",
345
+ },
346
+ });
347
+ const headers = antigravityHeaders(accessToken);
348
+ for (const baseEndpoint of ANTIGRAVITY_LOAD_ENDPOINTS) {
349
+ for (let attempt = 1; attempt <= 5; attempt++) {
350
+ try {
351
+ const resp = await fetchWithProxy(`${baseEndpoint}/v1internal:onboardUser`, { method: "POST", headers, body });
352
+ if (!resp.ok) {
353
+ if (resp.status >= 500 || resp.status === 404)
354
+ break; // try next endpoint
355
+ logger.warn(`[antigravity-api] onboardUser ${resp.status} at ${baseEndpoint}`);
356
+ return undefined;
357
+ }
358
+ const data = (await resp.json());
359
+ const project = extractProjectId(data.response);
360
+ if (data.done && project)
361
+ return project;
362
+ // done=false → wait a couple seconds and poll again
363
+ await new Promise((r) => setTimeout(r, 2000));
364
+ }
365
+ catch (err) {
366
+ logger.warn(`[antigravity-api] onboardUser error at ${baseEndpoint}: ${err.message}`);
367
+ break;
295
368
  }
296
369
  }
297
- catch {
298
- // try next endpoint
370
+ }
371
+ return undefined;
372
+ }
373
+ export async function resolveAntigravityProjectId(accessToken) {
374
+ configureDispatcher();
375
+ const loaded = await callLoadCodeAssist(accessToken);
376
+ if (loaded?.project)
377
+ return loaded.project;
378
+ if (loaded?.tier) {
379
+ logger.info(`[antigravity-api] loadCodeAssist returned no project (tier=${loaded.tier}) — running onboardUser...`);
380
+ const onboarded = await callOnboardUser(accessToken, loaded.tier);
381
+ if (onboarded) {
382
+ logger.info(`[antigravity-api] onboardUser succeeded, project=${onboarded}`);
383
+ return onboarded;
299
384
  }
300
385
  }
301
- logger.warn(`[antigravity-api] loadCodeAssist did not return a project — using default ${ANTIGRAVITY_DEFAULT_PROJECT_ID}`);
386
+ logger.warn(`[antigravity-api] could not resolve a real project — falling back to ${ANTIGRAVITY_DEFAULT_PROJECT_ID}. ` +
387
+ `This shared project needs staging-cloudaicompanion API enabled in Google Cloud Console; ` +
388
+ `expect 403 errors until a real project is resolved.`);
302
389
  return ANTIGRAVITY_DEFAULT_PROJECT_ID;
303
390
  }
304
391
  function antigravityHeaders(accessToken) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {