atlarix 15.8.0 → 15.8.2

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.
@@ -31220,12 +31220,11 @@ You are in ${L2("debug")} mode. Hypothesis-first debugging for this chat turn.
31220
31220
 
31221
31221
  You CAN:
31222
31222
  - Investigate (read, glob, grep, run_command for repro/tests)
31223
- - Form a hypothesis (root cause + evidence + files) before any write/edit/delete/rename
31223
+ - Form a hypothesis (root cause + evidence + files) before any change
31224
31224
  - Minimal file changes that test that hypothesis only
31225
- - Delegate a scoped fix to a WRITER sub-agent once you have a hypothesis \u2014 task({write:true, ...}) or task({subagent_type:"build", ...}). It writes nothing; its edits return as per-file proposals. Review each diff with \`proposals\` and accept the ones that hold up (accepting writes its exact bytes through the normal gate) \u2014 a fix you haven't read is not a fix. Read-only helper: the explore sub-agent (code recon and web research)
31225
+ - Delegate a scoped fix to a writer sub-agent once you have a hypothesis (task with write:true), reading each proposed diff before you accept it \u2014 a fix you haven't read is not a fix. Read-only helper: the explore sub-agent
31226
31226
 
31227
31227
  You CANNOT:
31228
- - Change files before forming a hypothesis
31229
31228
  - Refactor unrelated code or add features
31230
31229
 
31231
31230
  Workflow: investigate \u2192 form hypothesis \u2192 minimal fix \u2192 run the project's own tests/checks (run_command) \u2192 revise if needed. Note the root cause when you report the fix.
@@ -94587,6 +94586,7 @@ __export(supabase_client_exports, {
94587
94586
  AUTH_CALLBACK_URL: () => AUTH_CALLBACK_URL,
94588
94587
  DEEP_LINK_PROTOCOL: () => DEEP_LINK_PROTOCOL,
94589
94588
  SUPABASE_REQUEST_TIMEOUT_MS: () => SUPABASE_REQUEST_TIMEOUT_MS,
94589
+ __resetUserRowForTests: () => __resetUserRowForTests,
94590
94590
  cancelPendingOAuthTimeout: () => cancelPendingOAuthTimeout,
94591
94591
  fetchPlanSnapshot: () => fetchPlanSnapshot,
94592
94592
  fetchWithTimeout: () => fetchWithTimeout,
@@ -94958,10 +94958,44 @@ async function restoreAuthSessionOnStartup(opts) {
94958
94958
  );
94959
94959
  }
94960
94960
  }
94961
+ async function readUserRow(by, fresh = false) {
94962
+ const key = by.id ? `id:${by.id}` : `email:${(by.email ?? "").toLowerCase()}`;
94963
+ const c2 = _userRow;
94964
+ if (!fresh && c2 && Date.now() - c2.at < USER_ROW_TTL_MS && c2.keys.includes(key)) return c2.row;
94965
+ const pending3 = _userRowInFlight.get(key);
94966
+ if (pending3) return pending3;
94967
+ const p2 = (async () => {
94968
+ try {
94969
+ const q3 = getSupabaseClient().from("users").select(USER_ROW_SELECT);
94970
+ const { data, error: error51 } = await (by.id ? q3.eq("id", by.id) : q3.eq("email", by.email)).maybeSingle();
94971
+ if (error51) return void 0;
94972
+ const row = data ?? null;
94973
+ const keys2 = [key];
94974
+ if (row?.id) keys2.push(`id:${row.id}`);
94975
+ if (row?.email) keys2.push(`email:${row.email.toLowerCase()}`);
94976
+ _userRow = { keys: keys2, row, at: Date.now() };
94977
+ return row;
94978
+ } catch {
94979
+ return void 0;
94980
+ } finally {
94981
+ _userRowInFlight.delete(key);
94982
+ }
94983
+ })();
94984
+ _userRowInFlight.set(key, p2);
94985
+ return p2;
94986
+ }
94987
+ function invalidateUserRow() {
94988
+ _userRow = null;
94989
+ }
94990
+ function __resetUserRowForTests() {
94991
+ _userRow = null;
94992
+ _userRowInFlight.clear();
94993
+ }
94961
94994
  async function ensureUserExists(user) {
94962
94995
  try {
94963
94996
  const supabase = getSupabaseClient();
94964
- const { data: existingUser } = await supabase.from("users").select("id").eq("id", user.id).single();
94997
+ const shared = await readUserRow({ id: user.id });
94998
+ const existingUser = shared !== void 0 ? shared : (await supabase.from("users").select("id").eq("id", user.id).single()).data;
94965
94999
  if (!existingUser) {
94966
95000
  const { error: error51 } = await supabase.from("users").insert({
94967
95001
  id: user.id,
@@ -94969,6 +95003,7 @@ async function ensureUserExists(user) {
94969
95003
  plan: "free",
94970
95004
  onboarding_completed: false
94971
95005
  });
95006
+ invalidateUserRow();
94972
95007
  if (error51) {
94973
95008
  logger13.error("[Supabase] Failed to create user:", error51);
94974
95009
  } else {
@@ -95020,6 +95055,8 @@ function computeEntitledPlan(row) {
95020
95055
  return tier;
95021
95056
  }
95022
95057
  async function fetchPlanRowForUser(supabase, userId) {
95058
+ const shared = await readUserRow({ id: userId });
95059
+ if (shared !== void 0) return { data: shared, error: null };
95023
95060
  let data = null;
95024
95061
  let error51 = null;
95025
95062
  {
@@ -95051,6 +95088,8 @@ async function getUserPlan(userId) {
95051
95088
  }
95052
95089
  async function isUserBanned(userId) {
95053
95090
  try {
95091
+ const shared = await readUserRow({ id: userId });
95092
+ if (shared !== void 0) return !!shared?.banned_at;
95054
95093
  const supabase = getSupabaseClient();
95055
95094
  const { data, error: error51 } = await supabase.from("users").select("banned_at").eq("id", userId).maybeSingle();
95056
95095
  if (error51 || !data) return false;
@@ -95080,9 +95119,10 @@ function offlinePlanOr(fallback, userId) {
95080
95119
  function requireSettings() {
95081
95120
  return init_settings(), __toCommonJS(settings_exports);
95082
95121
  }
95083
- function invalidatePlanCaches() {
95122
+ function invalidatePlanCaches(opts = {}) {
95084
95123
  _tierCache = null;
95085
95124
  _subDetailCache = null;
95125
+ if (!opts.keepRow) invalidateUserRow();
95086
95126
  }
95087
95127
  async function getSubscriptionDetails(email3) {
95088
95128
  const c2 = _subDetailCache;
@@ -95090,8 +95130,8 @@ async function getSubscriptionDetails(email3) {
95090
95130
  return { status: c2.status, endsAt: c2.endsAt };
95091
95131
  }
95092
95132
  try {
95093
- const supabase = getSupabaseClient();
95094
- const { data } = await supabase.from("users").select("subscription_status, subscription_ends_at").eq("email", email3).single();
95133
+ const shared = await readUserRow({ email: email3 });
95134
+ const data = shared !== void 0 ? shared : (await getSupabaseClient().from("users").select("subscription_status, subscription_ends_at").eq("email", email3).single()).data;
95095
95135
  const status = data?.subscription_status ?? null;
95096
95136
  const endsAt = data?.subscription_ends_at ?? null;
95097
95137
  _subDetailCache = { email: email3, status, endsAt, at: Date.now() };
@@ -95123,6 +95163,8 @@ async function getEffectiveTier(userId, ownPlan) {
95123
95163
  }
95124
95164
  async function getOnboardingCompleted(userId) {
95125
95165
  try {
95166
+ const shared = await readUserRow({ id: userId });
95167
+ if (shared !== void 0) return shared?.onboarding_completed === true;
95126
95168
  const supabase = getSupabaseClient();
95127
95169
  const { data, error: error51 } = await supabase.from("users").select("onboarding_completed").eq("id", userId).maybeSingle();
95128
95170
  if (error51) {
@@ -95139,6 +95181,7 @@ async function setOnboardingCompleted(userId, value) {
95139
95181
  try {
95140
95182
  const supabase = getSupabaseClient();
95141
95183
  const { error: error51 } = await supabase.from("users").update({ onboarding_completed: value }).eq("id", userId);
95184
+ invalidateUserRow();
95142
95185
  if (error51) {
95143
95186
  logger13.error("[Supabase] setOnboardingCompleted error:", error51.message);
95144
95187
  } else {
@@ -95162,11 +95205,10 @@ function onAuthStateChange(callback) {
95162
95205
  });
95163
95206
  return () => subscription.unsubscribe();
95164
95207
  }
95165
- async function fetchPlanSnapshot(userEmail) {
95208
+ async function fetchPlanSnapshot(userEmail, fresh = true) {
95166
95209
  try {
95167
- const { data, error: error51 } = await getSupabaseClient().from("users").select(
95168
- "plan, subscription_status, subscription_ends_at, effective_tier, banned_at"
95169
- ).eq("email", userEmail).maybeSingle();
95210
+ const shared = await readUserRow({ email: userEmail }, fresh);
95211
+ const { data, error: error51 } = shared !== void 0 ? { data: shared, error: null } : await getSupabaseClient().from("users").select("plan, subscription_status, subscription_ends_at, effective_tier, banned_at").eq("email", userEmail).maybeSingle();
95170
95212
  if (error51 || !data) return null;
95171
95213
  const row = data;
95172
95214
  return {
@@ -95180,7 +95222,7 @@ async function fetchPlanSnapshot(userEmail) {
95180
95222
  return null;
95181
95223
  }
95182
95224
  }
95183
- var import_electron_log15, logger13, DEEP_LINK_PROTOCOL, AUTH_CALLBACK_PATH, AUTH_CALLBACK_URL, supabaseClient, fileStorage, SUPABASE_REQUEST_TIMEOUT_MS, _oauthTimeoutHandle, _authFlowStartedAt, AUTH_FLOW_MAX_AGE_MS, EMAIL_SIGN_IN_URL, _pendingAuthState, sleep4, PLAN_ROW_SELECT_BASE, PLAN_ROW_SELECT_WITH_VARIANT, EFFECTIVE_TIER_TTL_MS, _tierCache, _subDetailCache;
95225
+ var import_electron_log15, logger13, DEEP_LINK_PROTOCOL, AUTH_CALLBACK_PATH, AUTH_CALLBACK_URL, supabaseClient, fileStorage, SUPABASE_REQUEST_TIMEOUT_MS, _oauthTimeoutHandle, _authFlowStartedAt, AUTH_FLOW_MAX_AGE_MS, EMAIL_SIGN_IN_URL, _pendingAuthState, sleep4, USER_ROW_SELECT, USER_ROW_TTL_MS, _userRow, _userRowInFlight, PLAN_ROW_SELECT_BASE, PLAN_ROW_SELECT_WITH_VARIANT, EFFECTIVE_TIER_TTL_MS, _tierCache, _subDetailCache;
95184
95226
  var init_supabase_client = __esm({
95185
95227
  "src/lib/auth/supabase-client.ts"() {
95186
95228
  init_dist13();
@@ -95201,6 +95243,10 @@ var init_supabase_client = __esm({
95201
95243
  EMAIL_SIGN_IN_URL = "https://atlarix.dev/auth/app";
95202
95244
  _pendingAuthState = null;
95203
95245
  sleep4 = (ms2) => new Promise((r3) => setTimeout(r3, ms2));
95246
+ USER_ROW_SELECT = "id, email, plan, effective_tier, subscription_ends_at, subscription_status, lemon_subscription_id, lemon_variant_id, banned_at, onboarding_completed";
95247
+ USER_ROW_TTL_MS = 1e4;
95248
+ _userRow = null;
95249
+ _userRowInFlight = /* @__PURE__ */ new Map();
95204
95250
  PLAN_ROW_SELECT_BASE = "plan, effective_tier, subscription_ends_at, subscription_status, lemon_subscription_id";
95205
95251
  PLAN_ROW_SELECT_WITH_VARIANT = `${PLAN_ROW_SELECT_BASE}, lemon_variant_id`;
95206
95252
  EFFECTIVE_TIER_TTL_MS = 30 * 60 * 1e3;
@@ -264469,7 +264515,7 @@ var init_SubscriptionManager = __esm({
264469
264515
  } catch {
264470
264516
  }
264471
264517
  if (user.email) {
264472
- await this.refreshPlanFromServer(0);
264518
+ await this.refreshPlanFromServer(0, false);
264473
264519
  }
264474
264520
  this.broadcastAuthResolved();
264475
264521
  }
@@ -264630,7 +264676,7 @@ var init_SubscriptionManager = __esm({
264630
264676
  */
264631
264677
  static lastPlanRefreshAt = 0;
264632
264678
  static planRefreshInFlight = null;
264633
- static async refreshPlanFromServer(minIntervalMs = 15e3) {
264679
+ static async refreshPlanFromServer(minIntervalMs = 15e3, fresh = true) {
264634
264680
  const email3 = this.session?.email;
264635
264681
  if (!email3) return;
264636
264682
  if (this.planRefreshInFlight) return this.planRefreshInFlight;
@@ -264640,7 +264686,7 @@ var init_SubscriptionManager = __esm({
264640
264686
  this.planRefreshInFlight = (async () => {
264641
264687
  try {
264642
264688
  const { fetchPlanSnapshot: fetchPlanSnapshot2 } = await Promise.resolve().then(() => (init_supabase_client(), supabase_client_exports));
264643
- const next = await fetchPlanSnapshot2(email3);
264689
+ const next = await fetchPlanSnapshot2(email3, fresh);
264644
264690
  if (!next) return;
264645
264691
  const prev = {
264646
264692
  plan: this.session?.plan ?? "free",
@@ -264650,7 +264696,7 @@ var init_SubscriptionManager = __esm({
264650
264696
  banned: this.session?.banned ?? false
264651
264697
  };
264652
264698
  const changed = next.plan !== prev.plan || next.effectiveTier !== prev.effectiveTier || Boolean(next.banned) !== Boolean(prev.banned);
264653
- invalidatePlanCaches();
264699
+ invalidatePlanCaches({ keepRow: true });
264654
264700
  if (changed) await this.applyPlanChange(next, prev);
264655
264701
  } catch (e3) {
264656
264702
  logger56.warn("[SubscriptionManager] plan refresh failed (non-fatal)", e3);
@@ -347893,7 +347939,7 @@ ${err2.stack}` : "";
347893
347939
  }
347894
347940
 
347895
347941
  // src/headless/atlarix-headless.mts
347896
- var VERSION15 = false ? "dev" : "15.8.0";
347942
+ var VERSION15 = false ? "dev" : "15.8.2";
347897
347943
  if (process.argv[2] === "run") process.argv.splice(2, 1);
347898
347944
  var RUN_HELP = `atlarix run: one turn without the UI, for scripts and CI
347899
347945
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atlarix",
3
- "version": "15.8.0",
3
+ "version": "15.8.2",
4
4
  "description": "Atlarix CLI: an AI coding agent in your terminal. Works with any model (Atlarix Auto, your own API key, or a local model) and runs unattended with `atlarix run` for CI.",
5
5
  "license": "PROPRIETARY",
6
6
  "author": {
@@ -65,12 +65,12 @@
65
65
  "provenance": false
66
66
  },
67
67
  "optionalDependencies": {
68
- "atlarix-darwin-arm64": "15.8.0",
69
- "atlarix-darwin-x64": "15.8.0",
70
- "atlarix-linux-x64": "15.8.0",
71
- "atlarix-linux-arm64": "15.8.0",
72
- "atlarix-linux-x64-musl": "15.8.0",
73
- "atlarix-linux-arm64-musl": "15.8.0",
74
- "atlarix-windows-x64": "15.8.0"
68
+ "atlarix-darwin-arm64": "15.8.2",
69
+ "atlarix-darwin-x64": "15.8.2",
70
+ "atlarix-linux-x64": "15.8.2",
71
+ "atlarix-linux-arm64": "15.8.2",
72
+ "atlarix-linux-x64-musl": "15.8.2",
73
+ "atlarix-linux-arm64-musl": "15.8.2",
74
+ "atlarix-windows-x64": "15.8.2"
75
75
  }
76
76
  }