archondev 2.19.48 → 2.19.50

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.
@@ -5071,11 +5071,17 @@ ${conflictReport.blockerCount} blocking conflict(s) found.`));
5071
5071
  const config = await loadConfig();
5072
5072
  let billingContext;
5073
5073
  if (config.userId && config.accessToken) {
5074
+ const profileId = await resolveProfileId(config.userId, config.accessToken);
5075
+ if (!profileId) {
5076
+ console.log(chalk2.dim("Billing context unavailable: could not resolve profile ID. Usage tracking skipped for this execution."));
5077
+ }
5074
5078
  const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, config.accessToken);
5075
- billingContext = {
5076
- userId: config.userId,
5077
- supabase
5078
- };
5079
+ if (profileId) {
5080
+ billingContext = {
5081
+ userId: profileId,
5082
+ supabase
5083
+ };
5084
+ }
5079
5085
  }
5080
5086
  const roleOverrides = await loadRoleOverrides(cwd);
5081
5087
  const executorConfig = roleOverrides?.executor?.model ? { model: roleOverrides.executor.model } : void 0;
@@ -5284,6 +5290,19 @@ Running quality gates for ${targetEnvName}...`));
5284
5290
  prompt.close();
5285
5291
  }
5286
5292
  }
5293
+ async function resolveProfileId(authId, accessToken) {
5294
+ try {
5295
+ const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, accessToken);
5296
+ const { data: rawData, error } = await supabase.from("user_profiles").select("id").eq("auth_id", authId).single();
5297
+ const data = rawData;
5298
+ if (error || !data?.id) {
5299
+ return null;
5300
+ }
5301
+ return data.id;
5302
+ } catch {
5303
+ return null;
5304
+ }
5305
+ }
5287
5306
  function printExecuteNextActions(atomExternalId, success, context = "generic") {
5288
5307
  console.log();
5289
5308
  console.log(chalk2.bold("Next best action:"));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  execute
3
- } from "./chunk-O22UMAM5.js";
3
+ } from "./chunk-TXUHANIN.js";
4
4
  import "./chunk-EBHHIUCB.js";
5
5
  import "./chunk-RH64CSQU.js";
6
6
  import "./chunk-WGLVDEZC.js";
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ import {
56
56
  EnvironmentConfigLoader,
57
57
  EnvironmentValidator,
58
58
  execute
59
- } from "./chunk-O22UMAM5.js";
59
+ } from "./chunk-TXUHANIN.js";
60
60
  import {
61
61
  cloudCancel,
62
62
  cloudLogs,
@@ -2843,7 +2843,15 @@ async function start(options = {}) {
2843
2843
  }
2844
2844
  if (currentTier === "BYOK" && config.accessToken) {
2845
2845
  try {
2846
+ const resolvedAuthId = await resolveAuthIdFromToken(config.accessToken, config.userId);
2846
2847
  let usageStats = await fetchByokUsageStats(config.accessToken);
2848
+ const apiLooksEmpty = !!usageStats && usageStats.totalInputTokens === 0 && usageStats.totalOutputTokens === 0 && usageStats.totalBaseCost === 0 && usageStats.byModel.length === 0;
2849
+ if (!usageStats || apiLooksEmpty && resolvedAuthId) {
2850
+ const supabaseStats = resolvedAuthId ? await fetchByokUsageStatsFromSupabase(config.accessToken, resolvedAuthId) : null;
2851
+ if (supabaseStats) {
2852
+ usageStats = supabaseStats;
2853
+ }
2854
+ }
2847
2855
  const usageStatsUnavailable = !usageStats;
2848
2856
  if (!usageStats) {
2849
2857
  usageStats = {
@@ -3094,6 +3102,48 @@ async function fetchByokUsageStats(accessToken) {
3094
3102
  return null;
3095
3103
  }
3096
3104
  }
3105
+ async function fetchByokUsageStatsFromSupabase(accessToken, authId) {
3106
+ try {
3107
+ const { SUPABASE_URL: SUPABASE_URL2, SUPABASE_ANON_KEY: SUPABASE_ANON_KEY2 } = await import("./constants-XDIWFFPN.js");
3108
+ const { createAuthedSupabaseClient: createAuthedSupabaseClient2 } = await import("./client-PHW2C2HB.js");
3109
+ const supabase = createAuthedSupabaseClient2(SUPABASE_URL2, SUPABASE_ANON_KEY2, accessToken);
3110
+ const { data: rawProfile, error: profileError } = await supabase.from("user_profiles").select("id, current_period_start, current_period_end").eq("auth_id", authId).single();
3111
+ const profile = rawProfile;
3112
+ if (profileError || !profile?.id) {
3113
+ return null;
3114
+ }
3115
+ const now = /* @__PURE__ */ new Date();
3116
+ const defaultStart = new Date(now.getFullYear(), now.getMonth(), 1);
3117
+ const defaultEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
3118
+ const periodStart = profile.current_period_start ? new Date(profile.current_period_start) : defaultStart;
3119
+ const periodEnd = profile.current_period_end ? new Date(profile.current_period_end) : defaultEnd;
3120
+ const { data: rawUsageRows } = await supabase.from("token_usage").select("model, input_tokens, output_tokens, base_cost, total_cents, marked_up_cost").eq("user_id", profile.id).gte("created_at", periodStart.toISOString()).lte("created_at", periodEnd.toISOString());
3121
+ const usageRows = rawUsageRows;
3122
+ let totalInputTokens = 0;
3123
+ let totalOutputTokens = 0;
3124
+ let totalBaseCost = 0;
3125
+ const byModelMap = /* @__PURE__ */ new Map();
3126
+ for (const row of usageRows ?? []) {
3127
+ totalInputTokens += row.input_tokens ?? 0;
3128
+ totalOutputTokens += row.output_tokens ?? 0;
3129
+ const baseCost = typeof row.base_cost === "number" ? row.base_cost : typeof row.total_cents === "number" ? row.total_cents / 100 : typeof row.marked_up_cost === "number" ? row.marked_up_cost : 0;
3130
+ totalBaseCost += baseCost;
3131
+ byModelMap.set(row.model, (byModelMap.get(row.model) ?? 0) + baseCost);
3132
+ }
3133
+ const byModel = Array.from(byModelMap.entries()).map(([model, cost]) => ({ model, cost })).sort((a, b) => b.cost - a.cost);
3134
+ return {
3135
+ totalInputTokens,
3136
+ totalOutputTokens,
3137
+ totalBaseCost,
3138
+ byModel,
3139
+ periodStart: periodStart.toISOString(),
3140
+ periodEnd: periodEnd.toISOString(),
3141
+ periodSource: profile.current_period_start ? "profile_period" : "month"
3142
+ };
3143
+ } catch {
3144
+ return null;
3145
+ }
3146
+ }
3097
3147
  async function fetchCreditsUsageStatsFromSupabase(accessToken, authId) {
3098
3148
  try {
3099
3149
  const { SUPABASE_URL: SUPABASE_URL2, SUPABASE_ANON_KEY: SUPABASE_ANON_KEY2 } = await import("./constants-XDIWFFPN.js");
@@ -3774,6 +3824,10 @@ async function handleAgentConversationInput(cwd, input) {
3774
3824
  await answerLatestOutputLocation(cwd);
3775
3825
  return true;
3776
3826
  }
3827
+ if (isRunBacklogDirective(normalized)) {
3828
+ await continueWithCurrentTask(cwd, { runAllReady: true });
3829
+ return true;
3830
+ }
3777
3831
  if (pendingAnalysisToAtomRequest && isCreateAtomDirective(normalized)) {
3778
3832
  const request = pendingAnalysisToAtomRequest;
3779
3833
  pendingAnalysisToAtomRequest = null;
@@ -3961,6 +4015,20 @@ function isExecutionDirective(input) {
3961
4015
  }
3962
4016
  return /\b(start execution|implement now)\b/.test(normalized);
3963
4017
  }
4018
+ function isRunBacklogDirective(input) {
4019
+ const normalized = normalizeDirectiveInput(input);
4020
+ if (!normalized) return false;
4021
+ const direct = /* @__PURE__ */ new Set([
4022
+ "run backlog",
4023
+ "execute backlog",
4024
+ "resume backlog",
4025
+ "run queue",
4026
+ "run pending atoms",
4027
+ "execute pending atoms"
4028
+ ]);
4029
+ if (direct.has(normalized)) return true;
4030
+ return /\b(run|execute|resume)\b/.test(normalized) && /\b(backlog|queue|pending atoms)\b/.test(normalized);
4031
+ }
3964
4032
  function isCreateAtomDirective(input) {
3965
4033
  const normalized = normalizeDirectiveInput(input);
3966
4034
  if (!normalized) return false;
@@ -4206,7 +4274,7 @@ async function continueWithCurrentTask(cwd, options = {}) {
4206
4274
  const bTime = new Date(String(b.updatedAt ?? b.createdAt ?? "")).getTime() || 0;
4207
4275
  return bTime - aTime;
4208
4276
  };
4209
- const { execute: execute2 } = await import("./execute-AQWHZKDH.js");
4277
+ const { execute: execute2 } = await import("./execute-QQ3OPP6H.js");
4210
4278
  const runAllReady = options.runAllReady === true;
4211
4279
  const scopeIds = options.onlyAtomIds ? new Set(options.onlyAtomIds) : null;
4212
4280
  const attempted = /* @__PURE__ */ new Set();
@@ -4374,6 +4442,10 @@ async function handleFreeformJourneyInput(cwd, input) {
4374
4442
  await answerLatestOutputLocation(cwd);
4375
4443
  return true;
4376
4444
  }
4445
+ if (isRunBacklogDirective(freeform)) {
4446
+ await continueWithCurrentTask(cwd, { runAllReady: true });
4447
+ return true;
4448
+ }
4377
4449
  if (isExecutionDirective(freeform) || isContinuationDirective(freeform)) {
4378
4450
  await continueWithCurrentTask(cwd);
4379
4451
  return true;
@@ -4464,15 +4536,13 @@ async function answerLatestOutputLocation(cwd) {
4464
4536
  const files = latestDone.plan?.files_to_modify ?? [];
4465
4537
  if (files.length === 0) {
4466
4538
  console.log(chalk6.yellow(`Latest completed atom is ${latestDone.externalId}, but it has no recorded output paths.`));
4539
+ console.log(chalk6.dim(`Inspect details with: archon show ${latestDone.externalId}`));
4467
4540
  return;
4468
4541
  }
4469
4542
  console.log(chalk6.green(`Latest output file(s) from ${latestDone.externalId}:`));
4470
4543
  for (const file of files) {
4471
4544
  console.log(chalk6.dim(` - ${file}`));
4472
- }
4473
- const firstPath = files[0];
4474
- if (firstPath) {
4475
- console.log(chalk6.dim(`Absolute path: ${join6(cwd, firstPath)}`));
4545
+ console.log(chalk6.dim(` ${join6(cwd, file)}`));
4476
4546
  }
4477
4547
  }
4478
4548
  function containsActionIntent(input) {
@@ -4619,7 +4689,7 @@ async function executeNext() {
4619
4689
  const atomId = await prompt("Enter atom ID to execute (or press Enter for first pending)");
4620
4690
  const targetId = atomId.trim() || pendingAtoms[0]?.id;
4621
4691
  if (targetId) {
4622
- const { execute: execute2 } = await import("./execute-AQWHZKDH.js");
4692
+ const { execute: execute2 } = await import("./execute-QQ3OPP6H.js");
4623
4693
  await execute2(targetId, {});
4624
4694
  } else {
4625
4695
  console.log(chalk6.yellow("No atom to execute."));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archondev",
3
- "version": "2.19.48",
3
+ "version": "2.19.50",
4
4
  "description": "Local-first AI-powered development governance system",
5
5
  "main": "dist/index.js",
6
6
  "bin": {