@verboo/code 0.14.2 → 0.14.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.
Files changed (2) hide show
  1. package/dist/cli.mjs +228 -93
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -140974,7 +140974,9 @@ async function prefetchFastModeStatus() {
140974
140974
  if (isAuthError) {
140975
140975
  const failedAccessToken = getClaudeAIOAuthTokens()?.accessToken;
140976
140976
  if (failedAccessToken) {
140977
- await handleOAuth401Error(failedAccessToken);
140977
+ const outcome = await handleOAuth401ErrorWithOutcome(failedAccessToken);
140978
+ if (!didOAuthRefreshRecover(outcome))
140979
+ throw err;
140978
140980
  status = await fetchWithCurrentAuth();
140979
140981
  } else {
140980
140982
  throw err;
@@ -144182,6 +144184,7 @@ __export(exports_auth, {
144182
144184
  hasProfileScope: () => hasProfileScope,
144183
144185
  hasOpusAccess: () => hasOpusAccess,
144184
144186
  hasAnthropicApiKeyAuth: () => hasAnthropicApiKeyAuth,
144187
+ handleOAuth401ErrorWithOutcome: () => handleOAuth401ErrorWithOutcome,
144185
144188
  handleOAuth401Error: () => handleOAuth401Error,
144186
144189
  getSubscriptionType: () => getSubscriptionType,
144187
144190
  getSubscriptionName: () => getSubscriptionName,
@@ -144199,6 +144202,7 @@ __export(exports_auth, {
144199
144202
  getAnthropicApiKeyWithSource: () => getAnthropicApiKeyWithSource,
144200
144203
  getAnthropicApiKey: () => getAnthropicApiKey,
144201
144204
  getAccountInformation: () => getAccountInformation,
144205
+ didOAuthRefreshRecover: () => didOAuthRefreshRecover,
144202
144206
  clearOAuthTokenCache: () => clearOAuthTokenCache,
144203
144207
  clearGcpCredentialsCache: () => clearGcpCredentialsCache,
144204
144208
  clearAwsCredentialsCache: () => clearAwsCredentialsCache,
@@ -144837,15 +144841,18 @@ function saveOAuthTokensIfNeeded(tokens) {
144837
144841
  const secureStorage = getSecureStorage();
144838
144842
  const storageBackend = secureStorage.name;
144839
144843
  try {
144840
- const storageData = secureStorage.read() || {};
144841
- const existingOauth = storageData.verbooOauth;
144842
- storageData.verbooOauth = {
144843
- accessToken: tokens.accessToken,
144844
- refreshToken: tokens.refreshToken,
144845
- expiresAt: tokens.expiresAt,
144846
- scopes: tokens.scopes,
144847
- subscriptionType: tokens.subscriptionType ?? existingOauth?.subscriptionType ?? null,
144848
- rateLimitTier: tokens.rateLimitTier ?? existingOauth?.rateLimitTier ?? null
144844
+ const currentStorageData = secureStorage.read() || {};
144845
+ const existingOauth = currentStorageData.verbooOauth;
144846
+ const storageData = {
144847
+ ...currentStorageData,
144848
+ verbooOauth: {
144849
+ accessToken: tokens.accessToken,
144850
+ refreshToken: tokens.refreshToken,
144851
+ expiresAt: tokens.expiresAt,
144852
+ scopes: tokens.scopes,
144853
+ subscriptionType: tokens.subscriptionType ?? existingOauth?.subscriptionType ?? null,
144854
+ rateLimitTier: tokens.rateLimitTier ?? existingOauth?.rateLimitTier ?? null
144855
+ }
144849
144856
  };
144850
144857
  const updateStatus = secureStorage.update(storageData);
144851
144858
  if (updateStatus.success) {
@@ -144899,7 +144906,10 @@ async function invalidateOAuthCacheIfDiskChanged() {
144899
144906
  getClaudeAIOAuthTokens.cache?.clear?.();
144900
144907
  }
144901
144908
  }
144902
- function handleOAuth401Error(failedAccessToken) {
144909
+ function didOAuthRefreshRecover(outcome) {
144910
+ return outcome === "token_changed" || outcome === "refreshed";
144911
+ }
144912
+ function handleOAuth401ErrorWithOutcome(failedAccessToken) {
144903
144913
  const pending = pending401Handlers.get(failedAccessToken);
144904
144914
  if (pending)
144905
144915
  return pending;
@@ -144909,17 +144919,20 @@ function handleOAuth401Error(failedAccessToken) {
144909
144919
  pending401Handlers.set(failedAccessToken, promise2);
144910
144920
  return promise2;
144911
144921
  }
144922
+ async function handleOAuth401Error(failedAccessToken) {
144923
+ return didOAuthRefreshRecover(await handleOAuth401ErrorWithOutcome(failedAccessToken));
144924
+ }
144912
144925
  async function handleOAuth401ErrorImpl(failedAccessToken) {
144913
144926
  clearOAuthTokenCache();
144914
144927
  const currentTokens = await getClaudeAIOAuthTokensAsync();
144915
144928
  if (!currentTokens?.refreshToken) {
144916
- return false;
144929
+ return "reauth_required";
144917
144930
  }
144918
144931
  if (currentTokens.accessToken !== failedAccessToken) {
144919
144932
  logEvent("tengu_oauth_401_recovered_from_keychain", {});
144920
- return true;
144933
+ return "token_changed";
144921
144934
  }
144922
- return checkAndRefreshOAuthTokenIfNeeded(0, true);
144935
+ return checkAndRefreshOAuthTokenIfNeededImpl(0, true, failedAccessToken);
144923
144936
  }
144924
144937
  async function getClaudeAIOAuthTokensAsync() {
144925
144938
  if (isBareMode())
@@ -144934,39 +144947,83 @@ async function getClaudeAIOAuthTokensAsync() {
144934
144947
  }
144935
144948
  return getStoredVerbooOAuthTokensAsync();
144936
144949
  }
144950
+ function isOAuthInvalidGrant(error41) {
144951
+ const response = error41?.response;
144952
+ const data = response?.data;
144953
+ return typeof data === "object" && data !== null && "error" in data && data.error === "invalid_grant";
144954
+ }
144955
+ async function persistRefreshedOAuthTokens(refreshedTokens) {
144956
+ const delays = [0, 100, 250];
144957
+ for (const delay of delays) {
144958
+ if (delay > 0)
144959
+ await sleep2(delay);
144960
+ const status = saveOAuthTokensIfNeeded(refreshedTokens);
144961
+ if (!status.success)
144962
+ continue;
144963
+ clearOAuthTokenCache();
144964
+ const stored = await getClaudeAIOAuthTokensAsync();
144965
+ if (stored?.accessToken === refreshedTokens.accessToken && stored.refreshToken === refreshedTokens.refreshToken) {
144966
+ return true;
144967
+ }
144968
+ }
144969
+ logEvent("tengu_oauth_tokens_save_retry_exhausted", {});
144970
+ return false;
144971
+ }
144972
+ function clearStoredVerbooOAuthIfRefreshTokenMatches(refreshToken) {
144973
+ if (!isVerbooMode())
144974
+ return;
144975
+ try {
144976
+ const secureStorage = getSecureStorage();
144977
+ const data = secureStorage.read();
144978
+ if (data?.verbooOauth?.refreshToken !== refreshToken)
144979
+ return;
144980
+ const { verbooOauth: _, ...dataWithoutVerbooOAuth } = data;
144981
+ secureStorage.update(dataWithoutVerbooOAuth);
144982
+ clearOAuthTokenCache();
144983
+ } catch (error41) {
144984
+ logError2(error41);
144985
+ }
144986
+ }
144937
144987
  function checkAndRefreshOAuthTokenIfNeeded(retryCount = 0, force = false) {
144938
144988
  if (retryCount === 0 && !force) {
144939
144989
  if (pendingRefreshCheck) {
144940
- return pendingRefreshCheck;
144990
+ return pendingRefreshCheck.then(didOAuthRefreshRecover);
144941
144991
  }
144942
144992
  const promise2 = checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force);
144943
144993
  pendingRefreshCheck = promise2.finally(() => {
144944
144994
  pendingRefreshCheck = null;
144945
144995
  });
144946
- return pendingRefreshCheck;
144996
+ return pendingRefreshCheck.then(didOAuthRefreshRecover);
144947
144997
  }
144948
- return checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force);
144998
+ return checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force).then(didOAuthRefreshRecover);
144949
144999
  }
144950
- async function checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force) {
145000
+ async function checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force, failedAccessToken) {
144951
145001
  const MAX_RETRIES = 5;
144952
145002
  await invalidateOAuthCacheIfDiskChanged();
144953
145003
  const tokens = getClaudeAIOAuthTokens();
144954
145004
  if (!force) {
144955
145005
  if (!tokens?.refreshToken || !isOAuthTokenExpired(tokens.expiresAt)) {
144956
- return false;
145006
+ return "unchanged";
144957
145007
  }
144958
145008
  }
144959
145009
  if (!tokens?.refreshToken) {
144960
- return false;
145010
+ return force ? "reauth_required" : "unchanged";
144961
145011
  }
144962
145012
  if (!shouldUseClaudeAIAuth(tokens.scopes)) {
144963
- return false;
145013
+ return "unchanged";
144964
145014
  }
144965
145015
  getClaudeAIOAuthTokens.cache?.clear?.();
144966
145016
  clearKeychainCache();
144967
145017
  const freshTokens = await getClaudeAIOAuthTokensAsync();
144968
- if (!freshTokens?.refreshToken || !isOAuthTokenExpired(freshTokens.expiresAt)) {
144969
- return false;
145018
+ if (!freshTokens?.refreshToken) {
145019
+ return force ? "reauth_required" : "unchanged";
145020
+ }
145021
+ if (force && failedAccessToken && freshTokens.accessToken !== failedAccessToken) {
145022
+ logEvent("tengu_oauth_token_refresh_race_resolved", {});
145023
+ return "token_changed";
145024
+ }
145025
+ if (!force && !isOAuthTokenExpired(freshTokens.expiresAt)) {
145026
+ return "unchanged";
144970
145027
  }
144971
145028
  const claudeDir = getClaudeConfigHomeDir();
144972
145029
  await mkdir3(claudeDir, { recursive: true });
@@ -144982,45 +145039,65 @@ async function checkAndRefreshOAuthTokenIfNeededImpl(retryCount, force) {
144982
145039
  retryCount: retryCount + 1
144983
145040
  });
144984
145041
  await sleep2(1000 + Math.random() * 1000);
144985
- return checkAndRefreshOAuthTokenIfNeededImpl(retryCount + 1, force);
145042
+ return checkAndRefreshOAuthTokenIfNeededImpl(retryCount + 1, force, failedAccessToken);
144986
145043
  }
144987
145044
  logEvent("tengu_oauth_token_refresh_lock_retry_limit_reached", {
144988
145045
  maxRetries: MAX_RETRIES
144989
145046
  });
144990
- return false;
145047
+ clearOAuthTokenCache();
145048
+ const latestTokens = await getClaudeAIOAuthTokensAsync();
145049
+ return failedAccessToken && latestTokens?.accessToken && latestTokens.accessToken !== failedAccessToken ? "token_changed" : "transient_error";
144991
145050
  }
144992
145051
  logError2(err);
144993
145052
  logEvent("tengu_oauth_token_refresh_lock_error", {
144994
145053
  error: errorMessage(err)
144995
145054
  });
144996
- return false;
145055
+ return "transient_error";
144997
145056
  }
145057
+ let attemptedRefreshToken;
144998
145058
  try {
144999
145059
  getClaudeAIOAuthTokens.cache?.clear?.();
145000
145060
  clearKeychainCache();
145001
145061
  const lockedTokens = await getClaudeAIOAuthTokensAsync();
145002
- if (!lockedTokens?.refreshToken || !isOAuthTokenExpired(lockedTokens.expiresAt)) {
145062
+ if (!lockedTokens?.refreshToken) {
145063
+ return force ? "reauth_required" : "unchanged";
145064
+ }
145065
+ if (force && failedAccessToken && lockedTokens.accessToken !== failedAccessToken) {
145003
145066
  logEvent("tengu_oauth_token_refresh_race_resolved", {});
145004
- return false;
145067
+ return "token_changed";
145068
+ }
145069
+ if (!force && !isOAuthTokenExpired(lockedTokens.expiresAt)) {
145070
+ logEvent("tengu_oauth_token_refresh_race_resolved", {});
145071
+ return "unchanged";
145005
145072
  }
145006
145073
  logEvent("tengu_oauth_token_refresh_starting", {});
145007
- const refreshedTokens = await refreshOAuthToken(lockedTokens.refreshToken, {
145074
+ attemptedRefreshToken = lockedTokens.refreshToken;
145075
+ const refreshedTokens = await refreshOAuthToken(attemptedRefreshToken, {
145008
145076
  scopes: shouldUseClaudeAIAuth(lockedTokens.scopes) ? undefined : lockedTokens.scopes
145009
145077
  });
145010
- saveOAuthTokensIfNeeded(refreshedTokens);
145011
- getClaudeAIOAuthTokens.cache?.clear?.();
145012
- clearKeychainCache();
145013
- return true;
145078
+ const persisted = await persistRefreshedOAuthTokens(refreshedTokens);
145079
+ if (!persisted) {
145080
+ clearStoredVerbooOAuthIfRefreshTokenMatches(attemptedRefreshToken);
145081
+ return "storage_error";
145082
+ }
145083
+ clearOAuthTokenCache();
145084
+ return "refreshed";
145014
145085
  } catch (error41) {
145015
145086
  logError2(error41);
145016
- getClaudeAIOAuthTokens.cache?.clear?.();
145017
- clearKeychainCache();
145087
+ clearOAuthTokenCache();
145018
145088
  const currentTokens = await getClaudeAIOAuthTokensAsync();
145019
- if (currentTokens && !isOAuthTokenExpired(currentTokens.expiresAt)) {
145089
+ if (currentTokens?.accessToken && (failedAccessToken && currentTokens.accessToken !== failedAccessToken || !failedAccessToken && tokens?.accessToken && currentTokens.accessToken !== tokens.accessToken)) {
145020
145090
  logEvent("tengu_oauth_token_refresh_race_recovered", {});
145021
- return true;
145091
+ return "token_changed";
145022
145092
  }
145023
- return false;
145093
+ if (isOAuthInvalidGrant(error41)) {
145094
+ if (attemptedRefreshToken) {
145095
+ clearStoredVerbooOAuthIfRefreshTokenMatches(attemptedRefreshToken);
145096
+ }
145097
+ logEvent("tengu_oauth_token_refresh_reauth_required", {});
145098
+ return "reauth_required";
145099
+ }
145100
+ return "transient_error";
145024
145101
  } finally {
145025
145102
  logEvent("tengu_oauth_token_refresh_lock_releasing", {});
145026
145103
  await release();
@@ -169532,7 +169609,10 @@ async function* withRetry(getClient, operation, options2) {
169532
169609
  if (lastError instanceof APIError && lastError.status === 401 || isOAuthTokenRevokedError(lastError)) {
169533
169610
  const failedAccessToken = getClaudeAIOAuthTokens()?.accessToken;
169534
169611
  if (failedAccessToken) {
169535
- await handleOAuth401Error(failedAccessToken);
169612
+ const outcome = await handleOAuth401ErrorWithOutcome(failedAccessToken);
169613
+ if (!didOAuthRefreshRecover(outcome)) {
169614
+ throw new CannotRetryError(lastError, retryContext);
169615
+ }
169536
169616
  }
169537
169617
  }
169538
169618
  client = await getClient();
@@ -173830,7 +173910,7 @@ function getClaudeCodeUserAgent() {
173830
173910
  return `claude-code/${"99.0.0"}`;
173831
173911
  }
173832
173912
  function getVerbooCodeUserAgent() {
173833
- const version2 = typeof MACRO !== "undefined" ? "0.14.2" : "unknown";
173913
+ const version2 = "0.14.4";
173834
173914
  return `verboo-code/${version2}`;
173835
173915
  }
173836
173916
 
@@ -173902,7 +173982,9 @@ async function withOAuth401Retry(request, opts) {
173902
173982
  const failedAccessToken = getClaudeAIOAuthTokens()?.accessToken;
173903
173983
  if (!failedAccessToken)
173904
173984
  throw err2;
173905
- await handleOAuth401Error(failedAccessToken);
173985
+ const outcome = await handleOAuth401ErrorWithOutcome(failedAccessToken);
173986
+ if (!didOAuthRefreshRecover(outcome))
173987
+ throw err2;
173906
173988
  return await request();
173907
173989
  }
173908
173990
  }
@@ -192410,8 +192492,8 @@ async function getAnthropicClient({
192410
192492
  apiKey: accessToken ?? "",
192411
192493
  getApiKey: () => getClaudeAIOAuthTokens()?.accessToken ?? "",
192412
192494
  refreshApiKey: async (failedAccessToken) => {
192413
- const recovered = await handleOAuth401Error(failedAccessToken);
192414
- return recovered ? getClaudeAIOAuthTokens()?.accessToken ?? null : null;
192495
+ const outcome = await handleOAuth401ErrorWithOutcome(failedAccessToken);
192496
+ return didOAuthRefreshRecover(outcome) ? getClaudeAIOAuthTokens()?.accessToken ?? null : null;
192415
192497
  }
192416
192498
  }
192417
192499
  });
@@ -229430,7 +229512,8 @@ function createClaudeAiProxyFetch(innerFetch) {
229430
229512
  if (response.status !== 401) {
229431
229513
  return response;
229432
229514
  }
229433
- const tokenChanged = await handleOAuth401Error(sentToken).catch(() => false);
229515
+ const refreshOutcome = await handleOAuth401ErrorWithOutcome(sentToken).catch(() => "transient_error");
229516
+ const tokenChanged = didOAuthRefreshRecover(refreshOutcome);
229434
229517
  logEvent("tengu_mcp_claudeai_proxy_401", {
229435
229518
  tokenChanged
229436
229519
  });
@@ -295016,7 +295099,7 @@ function movePlanFocus(index, direction, count3, columns) {
295016
295099
  return safeIndex + columns < count3 ? safeIndex + columns : safeIndex;
295017
295100
  }
295018
295101
  function isCurrentLocalTrial(subscription) {
295019
- return subscription?.source === "trial" && subscription.status === "trialing";
295102
+ return subscription?.status === "trialing" && ["trial", "stripe_trial"].includes(subscription.source ?? "");
295020
295103
  }
295021
295104
  function filterCliPurchasablePlans(groups, subscriptions) {
295022
295105
  const subscriptionsByGroup = new Map(subscriptions.filter((subscription) => ["active", "trialing", "past_due"].includes(subscription.status)).map((subscription) => [subscription.groupId, subscription]));
@@ -300333,6 +300416,38 @@ var init_auth6 = __esm(() => {
300333
300416
  init_crypto2();
300334
300417
  });
300335
300418
 
300419
+ // src/services/oauth/subscriptionAccess.ts
300420
+ function hasCurrentSubscriptionAccess(subscription, now2 = Date.now()) {
300421
+ if (subscription.status !== "active" && subscription.status !== "trialing") {
300422
+ return false;
300423
+ }
300424
+ if (!subscription.currentPeriodEnd)
300425
+ return true;
300426
+ const periodEnd = new Date(subscription.currentPeriodEnd).getTime();
300427
+ return Number.isFinite(periodEnd) && periodEnd > now2;
300428
+ }
300429
+ function hasCurrentSubscriptionEntitlement(subscriptions, now2 = Date.now()) {
300430
+ return subscriptions.some((subscription) => hasCurrentSubscriptionAccess(subscription, now2));
300431
+ }
300432
+ function getPastDueAccessDecision(subscriptions, now2 = Date.now()) {
300433
+ const pastDueSubscriptions = subscriptions.filter((subscription) => subscription.status === "past_due");
300434
+ if (pastDueSubscriptions.length === 0) {
300435
+ return { kind: "continue", pastDueSubscriptions };
300436
+ }
300437
+ if (hasCurrentSubscriptionEntitlement(subscriptions, now2)) {
300438
+ return { kind: "warn", pastDueSubscriptions };
300439
+ }
300440
+ return { kind: "block", pastDueSubscriptions };
300441
+ }
300442
+ function formatPastDuePlanNames(subscriptions) {
300443
+ const names = subscriptions.map((subscription) => subscription.group?.name ?? subscription.groupId);
300444
+ if (names.length <= 1)
300445
+ return names[0] ?? "";
300446
+ if (names.length === 2)
300447
+ return `${names[0]} e ${names[1]}`;
300448
+ return `${names.slice(0, -1).join(", ")} e ${names.at(-1)}`;
300449
+ }
300450
+
300336
300451
  // src/services/oauth/pastDueFlow.tsx
300337
300452
  function formatPrice3(cents, currency) {
300338
300453
  return new Intl.NumberFormat("pt-BR", {
@@ -300340,6 +300455,12 @@ function formatPrice3(cents, currency) {
300340
300455
  currency: currency.toUpperCase()
300341
300456
  }).format(cents / 100);
300342
300457
  }
300458
+ function getPastDueWarningMessage(subscriptions) {
300459
+ return [
300460
+ `⚠ Pagamento pendente em ${formatPastDuePlanNames(subscriptions)}.`,
300461
+ "Seu acesso pelos outros planos ativos continua liberado; regularize no painel de assinaturas."
300462
+ ].join(" ");
300463
+ }
300343
300464
  function PastDueView({
300344
300465
  accessToken,
300345
300466
  onDone
@@ -300362,12 +300483,12 @@ function PastDueView({
300362
300483
  });
300363
300484
  if (controller.signal.aborted)
300364
300485
  return;
300365
- const pastDue = subscriptions.filter((subscription) => subscription.status === "past_due");
300366
- setPastDueGroups(pastDue);
300367
- if (pastDue.length === 0)
300486
+ const decision = getPastDueAccessDecision(subscriptions);
300487
+ setPastDueGroups(decision.pastDueSubscriptions);
300488
+ if (decision.kind === "continue")
300368
300489
  onDone(true);
300369
300490
  else
300370
- setStep("notice");
300491
+ setStep(decision.kind === "warn" ? "warning" : "notice");
300371
300492
  } catch (error42) {
300372
300493
  if (controller.signal.aborted)
300373
300494
  return;
@@ -300376,6 +300497,12 @@ function PastDueView({
300376
300497
  setStep("error");
300377
300498
  }
300378
300499
  }, [accessToken, onDone]);
300500
+ import_react63.useEffect(() => {
300501
+ if (step !== "warning")
300502
+ return;
300503
+ const timer = setTimeout(() => onDone(true), 0);
300504
+ return () => clearTimeout(timer);
300505
+ }, [onDone, step]);
300379
300506
  import_react63.useEffect(() => {
300380
300507
  loadSubscriptions();
300381
300508
  return () => {
@@ -300398,7 +300525,7 @@ function PastDueView({
300398
300525
  const subscriptions = await fetchSubscriptions(accessToken, {
300399
300526
  signal: controller.signal
300400
300527
  });
300401
- if (!subscriptions.some((subscription) => subscription.status === "past_due")) {
300528
+ if (getPastDueAccessDecision(subscriptions).kind !== "block") {
300402
300529
  setStep("success");
300403
300530
  completionTimerRef.current = setTimeout(() => onDone(true), 1500);
300404
300531
  return;
@@ -300441,6 +300568,12 @@ function PastDueView({
300441
300568
  }, [accessToken, startPolling]);
300442
300569
  if (step === "loading")
300443
300570
  return null;
300571
+ if (step === "warning") {
300572
+ return /* @__PURE__ */ jsx_runtime73.jsx(ThemedText, {
300573
+ color: "yellow",
300574
+ children: getPastDueWarningMessage(pastDueGroups)
300575
+ });
300576
+ }
300444
300577
  if (step === "notice") {
300445
300578
  return /* @__PURE__ */ jsx_runtime73.jsxs(ThemedBox_default, {
300446
300579
  flexDirection: "column",
@@ -300548,7 +300681,7 @@ function PastDueView({
300548
300681
  async function showPastDueNotice(accessToken) {
300549
300682
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
300550
300683
  const subscriptions = await fetchSubscriptions(accessToken);
300551
- return !subscriptions.some((subscription) => subscription.status === "past_due");
300684
+ return getPastDueAccessDecision(subscriptions).kind !== "block";
300552
300685
  }
300553
300686
  return new Promise((resolve21) => {
300554
300687
  let instance = null;
@@ -300904,11 +301037,13 @@ async function validateVerbooSession() {
300904
301037
  if (result.status === "unauthorized" && tokens.refreshToken) {
300905
301038
  logForDebugging("[VerbooStartup] /api/me returned 401, tentando refresh");
300906
301039
  try {
300907
- const refreshed = await refreshOAuthToken(tokens.refreshToken, {
300908
- scopes: [...getActiveScopes()]
300909
- });
300910
- saveOAuthTokensIfNeeded(refreshed);
300911
- clearOAuthTokenCache();
301040
+ const outcome = await handleOAuth401ErrorWithOutcome(tokens.accessToken);
301041
+ if (!didOAuthRefreshRecover(outcome)) {
301042
+ return outcome === "transient_error" ? { kind: "degraded", reason: "temporary OAuth refresh failure" } : { kind: "unauthenticated" };
301043
+ }
301044
+ const refreshed = await getClaudeAIOAuthTokensAsync();
301045
+ if (!refreshed?.accessToken)
301046
+ return { kind: "unauthenticated" };
300912
301047
  result = await callApiMe(refreshed.accessToken);
300913
301048
  if (result.status === "ok" && result.data) {
300914
301049
  persistAccount(result.data);
@@ -300960,7 +301095,7 @@ async function loadAndCheckModels(accessToken) {
300960
301095
  throw new Error(getVerbooModelsUnavailableMessage(result.reason));
300961
301096
  }
300962
301097
  const subscriptions = await fetchSubscriptions(accessToken);
300963
- const hasCurrentEntitlement = subscriptions.some((subscription) => subscription.status === "active" || subscription.status === "trialing");
301098
+ const hasCurrentEntitlement = hasCurrentSubscriptionEntitlement(subscriptions);
300964
301099
  if (hasCurrentEntitlement) {
300965
301100
  for (let attempt = 0;attempt < 4; attempt += 1) {
300966
301101
  await new Promise((resolve21) => setTimeout(resolve21, 3000));
@@ -395756,7 +395891,7 @@ function getAnthropicEnvMetadata() {
395756
395891
  function getBuildAgeMinutes() {
395757
395892
  if (false)
395758
395893
  ;
395759
- const buildTime = new Date("2026-07-19T23:00:41.253Z").getTime();
395894
+ const buildTime = new Date("2026-07-22T14:10:51.823Z").getTime();
395760
395895
  if (isNaN(buildTime))
395761
395896
  return;
395762
395897
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -424016,7 +424151,7 @@ function buildPrimarySection() {
424016
424151
  });
424017
424152
  return [{
424018
424153
  label: "Version",
424019
- value: "0.14.2"
424154
+ value: "0.14.4"
424020
424155
  }, {
424021
424156
  label: "Session name",
424022
424157
  value: nameValue
@@ -436945,7 +437080,7 @@ function getReleaseTagUrl(version2 = publicBuildVersion) {
436945
437080
  return `${VERBOO_RELEASES_URL}/tag/v${normalizePublicVersion(version2)}`;
436946
437081
  }
436947
437082
  function getPublicBuildVersion() {
436948
- return "0.14.2";
437083
+ return "0.14.4";
436949
437084
  }
436950
437085
  var import_semver10, VERBOO_RELEASES_URL = "https://github.com/verbeux-ai/code/releases", fallbackBuildVersion, publicBuildVersion;
436951
437086
  var init_version = __esm(() => {
@@ -488338,7 +488473,7 @@ var init_bridge_kick = __esm(() => {
488338
488473
  var call64 = async () => {
488339
488474
  return {
488340
488475
  type: "text",
488341
- value: `${"99.0.0"} (built ${"2026-07-19T23:00:41.253Z"})`
488476
+ value: `${"99.0.0"} (built ${"2026-07-22T14:10:51.823Z"})`
488342
488477
  };
488343
488478
  }, version2, version_default;
488344
488479
  var init_version2 = __esm(() => {
@@ -521413,7 +521548,7 @@ function printStartupScreen(modelOverride) {
521413
521548
  const home = process.env.HOME || process.env.USERPROFILE || "";
521414
521549
  const cwd2 = process.cwd();
521415
521550
  const displayCwd = home && cwd2.startsWith(home) ? `~${cwd2.slice(home.length)}` : cwd2;
521416
- const version3 = "0.14.2";
521551
+ const version3 = "0.14.4";
521417
521552
  const bold2 = `${ESC4}1m`;
521418
521553
  const PURPLE = rgb3(...ACCENT);
521419
521554
  const SOFT = rgb3(...CREAM);
@@ -539705,7 +539840,7 @@ var init_routerRateLimitHook = __esm(() => {
539705
539840
  function getSemverPart(version3) {
539706
539841
  return `${import_semver13.major(version3, { loose: true })}.${import_semver13.minor(version3, { loose: true })}.${import_semver13.patch(version3, { loose: true })}`;
539707
539842
  }
539708
- function useUpdateNotification(updatedVersion, initialVersion = "0.14.2") {
539843
+ function useUpdateNotification(updatedVersion, initialVersion = "0.14.4") {
539709
539844
  const [lastNotifiedSemver, setLastNotifiedSemver] = import_react225.useState(() => getSemverPart(initialVersion));
539710
539845
  const [pendingNotification2, setPendingNotification] = import_react225.useState(null);
539711
539846
  if (updatedVersion) {
@@ -539745,7 +539880,7 @@ function AutoUpdater({
539745
539880
  return;
539746
539881
  }
539747
539882
  if (false) {}
539748
- const currentVersion = "0.14.2";
539883
+ const currentVersion = "0.14.4";
539749
539884
  const channel2 = getInitialSettings()?.autoUpdatesChannel ?? "latest";
539750
539885
  let latestVersion = await getLatestVersion(channel2);
539751
539886
  const isDisabled = isAutoUpdaterDisabled();
@@ -540098,17 +540233,17 @@ function PackageManagerAutoUpdater(t0) {
540098
540233
  const maxVersion = await getMaxVersion();
540099
540234
  if (maxVersion && latest && gt(latest, maxVersion)) {
540100
540235
  logForDebugging(`PackageManagerAutoUpdater: maxVersion ${maxVersion} is set, capping update from ${latest} to ${maxVersion}`);
540101
- if (gte("0.14.2", maxVersion)) {
540102
- logForDebugging(`PackageManagerAutoUpdater: current version ${"0.14.2"} is already at or above maxVersion ${maxVersion}, skipping update`);
540236
+ if (gte("0.14.4", maxVersion)) {
540237
+ logForDebugging(`PackageManagerAutoUpdater: current version ${"0.14.4"} is already at or above maxVersion ${maxVersion}, skipping update`);
540103
540238
  setUpdateAvailable(false);
540104
540239
  return;
540105
540240
  }
540106
540241
  latest = maxVersion;
540107
540242
  }
540108
- const hasUpdate = latest && !gte("0.14.2", latest) && !shouldSkipVersion(latest);
540243
+ const hasUpdate = latest && !gte("0.14.4", latest) && !shouldSkipVersion(latest);
540109
540244
  setUpdateAvailable(!!hasUpdate);
540110
540245
  if (hasUpdate) {
540111
- logForDebugging(`PackageManagerAutoUpdater: Update available ${"0.14.2"} -> ${latest}`);
540246
+ logForDebugging(`PackageManagerAutoUpdater: Update available ${"0.14.4"} -> ${latest}`);
540112
540247
  }
540113
540248
  };
540114
540249
  $2[0] = t1;
@@ -540142,7 +540277,7 @@ function PackageManagerAutoUpdater(t0) {
540142
540277
  wrap: "truncate",
540143
540278
  children: [
540144
540279
  "currentVersion: ",
540145
- "0.14.2"
540280
+ "0.14.4"
540146
540281
  ]
540147
540282
  });
540148
540283
  $2[3] = verbose;
@@ -556093,10 +556228,10 @@ async function autoUpdateCliInBackground() {
556093
556228
  return;
556094
556229
  const channel2 = getInitialSettings()?.autoUpdatesChannel ?? "latest";
556095
556230
  const latest = await getLatestVersion(channel2);
556096
- if (!latest || gte("0.14.2", latest))
556231
+ if (!latest || gte("0.14.4", latest))
556097
556232
  return;
556098
556233
  writeToStdout(`
556099
- Nova versão disponível: ${latest} (atual: ${"0.14.2"})
556234
+ Nova versão disponível: ${latest} (atual: ${"0.14.4"})
556100
556235
  `);
556101
556236
  writeToStdout(`Atualizando automaticamente...
556102
556237
  `);
@@ -573790,7 +573925,7 @@ function WelcomeV2() {
573790
573925
  dimColor: true,
573791
573926
  children: [
573792
573927
  "v",
573793
- "0.14.2",
573928
+ "0.14.4",
573794
573929
  " "
573795
573930
  ]
573796
573931
  })
@@ -573977,7 +574112,7 @@ function WelcomeV2() {
573977
574112
  dimColor: true,
573978
574113
  children: [
573979
574114
  "v",
573980
- "0.14.2",
574115
+ "0.14.4",
573981
574116
  " "
573982
574117
  ]
573983
574118
  })
@@ -574193,7 +574328,7 @@ function AppleTerminalWelcomeV2(t0) {
574193
574328
  dimColor: true,
574194
574329
  children: [
574195
574330
  "v",
574196
- "0.14.2",
574331
+ "0.14.4",
574197
574332
  " "
574198
574333
  ]
574199
574334
  });
@@ -574402,7 +574537,7 @@ function AppleTerminalWelcomeV2(t0) {
574402
574537
  dimColor: true,
574403
574538
  children: [
574404
574539
  "v",
574405
- "0.14.2",
574540
+ "0.14.4",
574406
574541
  " "
574407
574542
  ]
574408
574543
  });
@@ -591804,7 +591939,7 @@ __export(exports_update, {
591804
591939
  });
591805
591940
  async function update() {
591806
591941
  logEvent("tengu_update_check", {});
591807
- writeToStdout(`Current version: ${"0.14.2"}
591942
+ writeToStdout(`Current version: ${"0.14.4"}
591808
591943
  `);
591809
591944
  const channel2 = getInitialSettings()?.autoUpdatesChannel ?? "latest";
591810
591945
  writeToStdout(`Checking for updates to ${channel2} version...
@@ -591889,8 +592024,8 @@ async function update() {
591889
592024
  writeToStdout(`Verboo Code is managed by Homebrew.
591890
592025
  `);
591891
592026
  const latest = await getLatestVersion(channel2);
591892
- if (latest && !gte("0.14.2", latest)) {
591893
- writeToStdout(`Update available: ${"0.14.2"} → ${latest}
592027
+ if (latest && !gte("0.14.4", latest)) {
592028
+ writeToStdout(`Update available: ${"0.14.4"} → ${latest}
591894
592029
  `);
591895
592030
  writeToStdout(`
591896
592031
  `);
@@ -591906,8 +592041,8 @@ async function update() {
591906
592041
  writeToStdout(`Verboo Code is managed by winget.
591907
592042
  `);
591908
592043
  const latest = await getLatestVersion(channel2);
591909
- if (latest && !gte("0.14.2", latest)) {
591910
- writeToStdout(`Update available: ${"0.14.2"} → ${latest}
592044
+ if (latest && !gte("0.14.4", latest)) {
592045
+ writeToStdout(`Update available: ${"0.14.4"} → ${latest}
591911
592046
  `);
591912
592047
  writeToStdout(`
591913
592048
  `);
@@ -591923,8 +592058,8 @@ async function update() {
591923
592058
  writeToStdout(`Verboo Code is managed by apk.
591924
592059
  `);
591925
592060
  const latest = await getLatestVersion(channel2);
591926
- if (latest && !gte("0.14.2", latest)) {
591927
- writeToStdout(`Update available: ${"0.14.2"} → ${latest}
592061
+ if (latest && !gte("0.14.4", latest)) {
592062
+ writeToStdout(`Update available: ${"0.14.4"} → ${latest}
591928
592063
  `);
591929
592064
  writeToStdout(`
591930
592065
  `);
@@ -591977,11 +592112,11 @@ async function update() {
591977
592112
  `);
591978
592113
  await gracefulShutdown(1);
591979
592114
  }
591980
- if (result.latestVersion === "0.14.2") {
591981
- writeToStdout(source_default.green(`Verboo Code is up to date (${"0.14.2"})`) + `
592115
+ if (result.latestVersion === "0.14.4") {
592116
+ writeToStdout(source_default.green(`Verboo Code is up to date (${"0.14.4"})`) + `
591982
592117
  `);
591983
592118
  } else {
591984
- writeToStdout(source_default.green(`Successfully updated from ${"0.14.2"} to version ${result.latestVersion}`) + `
592119
+ writeToStdout(source_default.green(`Successfully updated from ${"0.14.4"} to version ${result.latestVersion}`) + `
591985
592120
  `);
591986
592121
  await regenerateCompletionCache();
591987
592122
  }
@@ -592041,12 +592176,12 @@ async function update() {
592041
592176
  `);
592042
592177
  await gracefulShutdown(1);
592043
592178
  }
592044
- if (latestVersion === "0.14.2") {
592045
- writeToStdout(source_default.green(`Verboo Code is up to date (${"0.14.2"})`) + `
592179
+ if (latestVersion === "0.14.4") {
592180
+ writeToStdout(source_default.green(`Verboo Code is up to date (${"0.14.4"})`) + `
592046
592181
  `);
592047
592182
  await gracefulShutdown(0);
592048
592183
  }
592049
- writeToStdout(`New version available: ${latestVersion} (current: ${"0.14.2"})
592184
+ writeToStdout(`New version available: ${latestVersion} (current: ${"0.14.4"})
592050
592185
  `);
592051
592186
  writeToStdout(`Installing update...
592052
592187
  `);
@@ -592091,7 +592226,7 @@ async function update() {
592091
592226
  logForDebugging(`update: Installation status: ${status2}`);
592092
592227
  switch (status2) {
592093
592228
  case "success":
592094
- writeToStdout(source_default.green(`Successfully updated from ${"0.14.2"} to version ${latestVersion}`) + `
592229
+ writeToStdout(source_default.green(`Successfully updated from ${"0.14.4"} to version ${latestVersion}`) + `
592095
592230
  `);
592096
592231
  await regenerateCompletionCache();
592097
592232
  break;
@@ -593375,7 +593510,7 @@ ${customInstructions}` : customInstructions;
593375
593510
  is_native_binary: isInBundledMode()
593376
593511
  });
593377
593512
  logMemoryDiagnostics("start", {
593378
- version: "0.14.2",
593513
+ version: "0.14.4",
593379
593514
  debug: debug2,
593380
593515
  debugToStderr,
593381
593516
  print: print ?? false,
@@ -594186,7 +594321,7 @@ Usage: verboo --remote "your task description"`, () => gracefulShutdown(1));
594186
594321
  pendingHookMessages
594187
594322
  }, renderAndRun);
594188
594323
  }
594189
- }).version(`0.14.2 (${cliDesc})`, "-v, --version", "Output the version number");
594324
+ }).version(`0.14.4 (${cliDesc})`, "-v, --version", "Output the version number");
594190
594325
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
594191
594326
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
594192
594327
  if (canUserConfigureAdvisor()) {
@@ -594762,7 +594897,7 @@ if (false) {}
594762
594897
  async function main2() {
594763
594898
  const args = process.argv.slice(2);
594764
594899
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
594765
- console.log(`${"0.14.2"} (Verboo Code)`);
594900
+ console.log(`${"0.14.4"} (Verboo Code)`);
594766
594901
  return;
594767
594902
  }
594768
594903
  if (!IS_VERBOO_CLI && args.includes("--provider")) {
@@ -594936,4 +595071,4 @@ async function main2() {
594936
595071
  }
594937
595072
  main2();
594938
595073
 
594939
- //# debugId=41123190D4DA309164756E2164756E21
595074
+ //# debugId=C12D97D25723522B64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verboo/code",
3
- "version": "0.14.2",
3
+ "version": "0.14.4",
4
4
  "description": "Verboo Code — coding agent for the Verboo platform",
5
5
  "type": "module",
6
6
  "bin": {