archondev 2.19.5 → 2.19.6
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.
|
@@ -792,7 +792,7 @@ async function interactiveSettings() {
|
|
|
792
792
|
await interactiveSettings();
|
|
793
793
|
break;
|
|
794
794
|
case "4":
|
|
795
|
-
await showUsageDetails();
|
|
795
|
+
await showUsageDetails({ pauseForInput: true });
|
|
796
796
|
await interactiveSettings();
|
|
797
797
|
break;
|
|
798
798
|
case "5":
|
|
@@ -1188,7 +1188,91 @@ var __preferencesChoiceHelpers = {
|
|
|
1188
1188
|
resolveProviderIndexChoice,
|
|
1189
1189
|
resolveModelChoice
|
|
1190
1190
|
};
|
|
1191
|
-
|
|
1191
|
+
function formatLocalDateTime(value) {
|
|
1192
|
+
const date = new Date(value);
|
|
1193
|
+
if (isNaN(date.getTime())) {
|
|
1194
|
+
return value;
|
|
1195
|
+
}
|
|
1196
|
+
return date.toLocaleString();
|
|
1197
|
+
}
|
|
1198
|
+
function formatUsagePeriodLabel(periodSource) {
|
|
1199
|
+
if (periodSource === "credit_purchase") return "Since last top-up";
|
|
1200
|
+
if (periodSource === "month") return "Current month to date";
|
|
1201
|
+
return "Current billing period";
|
|
1202
|
+
}
|
|
1203
|
+
function sumModelCost(byModel) {
|
|
1204
|
+
return (byModel ?? []).reduce((sum, row) => sum + row.cost, 0);
|
|
1205
|
+
}
|
|
1206
|
+
function renderModelBreakdown(rows, options = {}) {
|
|
1207
|
+
const indent = options.indent ?? " ";
|
|
1208
|
+
if (rows.length === 0) {
|
|
1209
|
+
console.log(chalk.dim(`${indent}No usage recorded.`));
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
const total = rows.reduce((sum, row) => sum + row.cost, 0);
|
|
1213
|
+
const sorted = [...rows].sort((a, b) => b.cost - a.cost);
|
|
1214
|
+
for (const row of sorted) {
|
|
1215
|
+
const modelInfo = findModel(row.model);
|
|
1216
|
+
const name = modelInfo?.name ?? row.model;
|
|
1217
|
+
const tokenTotal = row.inputTokens + row.outputTokens;
|
|
1218
|
+
const share = total > 0 ? (row.cost / total * 100).toFixed(1) : "0.0";
|
|
1219
|
+
const note = options.costNote ? ` ${chalk.dim(options.costNote)}` : "";
|
|
1220
|
+
console.log(`${indent}${name}: ${formatTokens(tokenTotal)} tokens | ${formatCost(row.cost)} (${share}%)${note}`);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
async function resolveAuthAndProfileIds(authToken, fallbackAuthId) {
|
|
1224
|
+
const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, authToken);
|
|
1225
|
+
let authId = fallbackAuthId ?? null;
|
|
1226
|
+
if (!authId) {
|
|
1227
|
+
const { data, error } = await supabase.auth.getUser();
|
|
1228
|
+
if (error || !data.user?.id) {
|
|
1229
|
+
return { authId: null, profileId: null };
|
|
1230
|
+
}
|
|
1231
|
+
authId = data.user.id;
|
|
1232
|
+
}
|
|
1233
|
+
const { data: profileRow, error: profileError } = await supabase.from("user_profiles").select("id").eq("auth_id", authId).single();
|
|
1234
|
+
if (profileError || !profileRow?.id) {
|
|
1235
|
+
return { authId, profileId: null };
|
|
1236
|
+
}
|
|
1237
|
+
return { authId, profileId: profileRow.id };
|
|
1238
|
+
}
|
|
1239
|
+
async function fetchUsageRows(authToken, profileId, startIso, endIso) {
|
|
1240
|
+
const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, authToken);
|
|
1241
|
+
const { data, error } = await supabase.from("token_usage").select("model, input_tokens, output_tokens, base_cost, created_at").eq("user_id", profileId).gte("created_at", startIso).lte("created_at", endIso);
|
|
1242
|
+
if (error || !data) {
|
|
1243
|
+
return null;
|
|
1244
|
+
}
|
|
1245
|
+
return data;
|
|
1246
|
+
}
|
|
1247
|
+
function aggregateUsageRows(rows, start, end) {
|
|
1248
|
+
let totalInputTokens = 0;
|
|
1249
|
+
let totalOutputTokens = 0;
|
|
1250
|
+
let totalCost = 0;
|
|
1251
|
+
const byModelMap = /* @__PURE__ */ new Map();
|
|
1252
|
+
for (const row of rows) {
|
|
1253
|
+
const ts = new Date(row.created_at);
|
|
1254
|
+
if (ts < start || ts > end) continue;
|
|
1255
|
+
totalInputTokens += row.input_tokens;
|
|
1256
|
+
totalOutputTokens += row.output_tokens;
|
|
1257
|
+
totalCost += row.base_cost;
|
|
1258
|
+
const existing = byModelMap.get(row.model);
|
|
1259
|
+
if (existing) {
|
|
1260
|
+
existing.inputTokens += row.input_tokens;
|
|
1261
|
+
existing.outputTokens += row.output_tokens;
|
|
1262
|
+
existing.cost += row.base_cost;
|
|
1263
|
+
} else {
|
|
1264
|
+
byModelMap.set(row.model, {
|
|
1265
|
+
inputTokens: row.input_tokens,
|
|
1266
|
+
outputTokens: row.output_tokens,
|
|
1267
|
+
cost: row.base_cost
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
const byModel = Array.from(byModelMap.entries()).map(([model, stats]) => ({ model, ...stats })).sort((a, b) => b.cost - a.cost);
|
|
1272
|
+
return { totalInputTokens, totalOutputTokens, totalCost, byModel };
|
|
1273
|
+
}
|
|
1274
|
+
async function showUsageDetails(options = {}) {
|
|
1275
|
+
const { pauseForInput = false } = options;
|
|
1192
1276
|
console.log(chalk.bold("\n-- Usage Details --\n"));
|
|
1193
1277
|
const spinner = ora("Loading usage data...").start();
|
|
1194
1278
|
const config = await loadConfig();
|
|
@@ -1210,84 +1294,49 @@ async function showUsageDetails() {
|
|
|
1210
1294
|
}
|
|
1211
1295
|
const data = await response.json();
|
|
1212
1296
|
if (data.tier === "BYOK") {
|
|
1213
|
-
|
|
1297
|
+
const ids = await resolveAuthAndProfileIds(authToken, authId);
|
|
1298
|
+
if (!ids.authId || !ids.profileId) {
|
|
1214
1299
|
console.log(chalk.yellow("Unable to resolve user ID for usage details."));
|
|
1215
1300
|
return;
|
|
1216
1301
|
}
|
|
1217
|
-
const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, authToken);
|
|
1218
|
-
const { data: profileRow, error: profileError } = await supabase.from("user_profiles").select("id").eq("auth_id", authId).single();
|
|
1219
|
-
if (profileError || !profileRow?.id) {
|
|
1220
|
-
console.log(chalk.yellow("Unable to resolve profile for usage details."));
|
|
1221
|
-
return;
|
|
1222
|
-
}
|
|
1223
|
-
const profileId = profileRow.id;
|
|
1224
1302
|
const now = /* @__PURE__ */ new Date();
|
|
1225
1303
|
const yearStart = new Date(now.getFullYear(), 0, 1);
|
|
1226
|
-
const
|
|
1227
|
-
if (
|
|
1304
|
+
const usageRows = await fetchUsageRows(authToken, ids.profileId, yearStart.toISOString(), now.toISOString());
|
|
1305
|
+
if (!usageRows) {
|
|
1228
1306
|
console.log(chalk.yellow("Unable to fetch BYOK usage data."));
|
|
1229
1307
|
return;
|
|
1230
1308
|
}
|
|
1231
|
-
const rows = usageRows;
|
|
1232
1309
|
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
1233
|
-
const
|
|
1234
|
-
const
|
|
1310
|
+
const startOf24h = new Date(now.getTime() - 24 * 60 * 60 * 1e3);
|
|
1311
|
+
const startOf7d = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1e3);
|
|
1312
|
+
const startOf30d = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1e3);
|
|
1235
1313
|
const periods = [
|
|
1236
1314
|
{ label: "Today", start: startOfToday, end: now },
|
|
1237
|
-
{ label: "
|
|
1238
|
-
{ label: "
|
|
1315
|
+
{ label: "Last 24 Hours", start: startOf24h, end: now },
|
|
1316
|
+
{ label: "Last 7 Days", start: startOf7d, end: now },
|
|
1317
|
+
{ label: "Last 30 Days", start: startOf30d, end: now },
|
|
1239
1318
|
{ label: "Year to Date", start: yearStart, end: now }
|
|
1240
1319
|
];
|
|
1241
|
-
const aggregate = (start, end) => {
|
|
1242
|
-
let totalInputTokens = 0;
|
|
1243
|
-
let totalOutputTokens = 0;
|
|
1244
|
-
let totalCost = 0;
|
|
1245
|
-
const byModelMap = /* @__PURE__ */ new Map();
|
|
1246
|
-
for (const row of rows) {
|
|
1247
|
-
const ts = new Date(row.created_at);
|
|
1248
|
-
if (ts < start || ts > end) continue;
|
|
1249
|
-
totalInputTokens += row.input_tokens;
|
|
1250
|
-
totalOutputTokens += row.output_tokens;
|
|
1251
|
-
totalCost += row.base_cost;
|
|
1252
|
-
const existing = byModelMap.get(row.model);
|
|
1253
|
-
if (existing) {
|
|
1254
|
-
existing.inputTokens += row.input_tokens;
|
|
1255
|
-
existing.outputTokens += row.output_tokens;
|
|
1256
|
-
existing.cost += row.base_cost;
|
|
1257
|
-
} else {
|
|
1258
|
-
byModelMap.set(row.model, {
|
|
1259
|
-
inputTokens: row.input_tokens,
|
|
1260
|
-
outputTokens: row.output_tokens,
|
|
1261
|
-
cost: row.base_cost
|
|
1262
|
-
});
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
const byModel = Array.from(byModelMap.entries()).map(([model, stats]) => ({ model, ...stats })).sort((a, b) => b.cost - a.cost);
|
|
1266
|
-
return { totalInputTokens, totalOutputTokens, totalCost, byModel };
|
|
1267
|
-
};
|
|
1268
1320
|
console.log(chalk.blue("BYOK Usage (local time):"));
|
|
1321
|
+
console.log(chalk.dim("Estimated provider spend by model (you are billed directly by provider)."));
|
|
1269
1322
|
for (const period of periods) {
|
|
1270
|
-
const summary =
|
|
1323
|
+
const summary = aggregateUsageRows(usageRows, period.start, period.end);
|
|
1271
1324
|
console.log();
|
|
1272
1325
|
console.log(chalk.bold(`${period.label}:`));
|
|
1273
1326
|
console.log(` ${period.start.toLocaleDateString()} \u2192 ${period.end.toLocaleDateString()}`);
|
|
1274
1327
|
console.log(` Tokens: ${formatTokens(summary.totalInputTokens + summary.totalOutputTokens)} (in ${formatTokens(summary.totalInputTokens)} / out ${formatTokens(summary.totalOutputTokens)})`);
|
|
1275
|
-
console.log(`
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
for (const model of summary.byModel) {
|
|
1279
|
-
const modelInfo = findModel(model.model);
|
|
1280
|
-
const name = modelInfo?.name ?? model.model;
|
|
1281
|
-
const tokenTotal = model.inputTokens + model.outputTokens;
|
|
1282
|
-
console.log(` ${name}: ${formatTokens(tokenTotal)} tokens (${formatCost(model.cost)})`);
|
|
1283
|
-
}
|
|
1284
|
-
} else {
|
|
1285
|
-
console.log(chalk.dim(" No usage recorded."));
|
|
1286
|
-
}
|
|
1328
|
+
console.log(` Estimated Spend: ${formatCost(summary.totalCost)} ${chalk.dim("(paid directly to provider)")}`);
|
|
1329
|
+
console.log(chalk.dim(" By Model:"));
|
|
1330
|
+
renderModelBreakdown(summary.byModel, { indent: " " });
|
|
1287
1331
|
}
|
|
1288
1332
|
} else {
|
|
1289
|
-
|
|
1290
|
-
|
|
1333
|
+
const periodLabel = formatUsagePeriodLabel(data.periodSource);
|
|
1334
|
+
const byModel = [...data.byModel ?? []].sort((a, b) => b.cost - a.cost);
|
|
1335
|
+
const modelBilledTotal = sumModelCost(byModel);
|
|
1336
|
+
const modelBaseTotal = data.totalBaseCost;
|
|
1337
|
+
const modelFeeTotal = Math.max(0, modelBilledTotal - modelBaseTotal);
|
|
1338
|
+
console.log(chalk.blue(`${periodLabel}:`));
|
|
1339
|
+
console.log(` ${formatLocalDateTime(data.periodStart)} \u2192 ${formatLocalDateTime(data.periodEnd)}`);
|
|
1291
1340
|
console.log();
|
|
1292
1341
|
console.log(chalk.blue("Token Usage:"));
|
|
1293
1342
|
console.log(` Input: ${formatTokens(data.totalInputTokens)} tokens`);
|
|
@@ -1295,24 +1344,29 @@ async function showUsageDetails() {
|
|
|
1295
1344
|
console.log(` Total: ${formatTokens(data.totalInputTokens + data.totalOutputTokens)} tokens`);
|
|
1296
1345
|
console.log();
|
|
1297
1346
|
console.log(chalk.blue("Cost:"));
|
|
1298
|
-
console.log(` Base Cost: ${formatCost(data.totalBaseCost)}`);
|
|
1299
1347
|
if (data.tier === "CREDITS") {
|
|
1300
|
-
|
|
1301
|
-
console.log(`
|
|
1348
|
+
console.log(` Base Model Cost: ${formatCost(modelBaseTotal)}`);
|
|
1349
|
+
console.log(` Platform Fee: ${formatCost(modelFeeTotal)}`);
|
|
1350
|
+
console.log(` Credits Deducted:${formatCost(modelBilledTotal)}`);
|
|
1351
|
+
} else {
|
|
1352
|
+
console.log(` Estimated Cost: ${formatCost(modelBaseTotal)}`);
|
|
1302
1353
|
}
|
|
1303
|
-
if (
|
|
1354
|
+
if (byModel.length > 0) {
|
|
1304
1355
|
console.log();
|
|
1305
1356
|
console.log(chalk.blue("By Model:"));
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1357
|
+
renderModelBreakdown(
|
|
1358
|
+
byModel.map((row) => ({
|
|
1359
|
+
model: row.model,
|
|
1360
|
+
inputTokens: row.inputTokens,
|
|
1361
|
+
outputTokens: row.outputTokens,
|
|
1362
|
+
cost: row.cost
|
|
1363
|
+
}))
|
|
1364
|
+
);
|
|
1311
1365
|
}
|
|
1312
1366
|
if (data.byOperation && data.byOperation.length > 0) {
|
|
1313
1367
|
console.log();
|
|
1314
1368
|
console.log(chalk.blue("By Operation:"));
|
|
1315
|
-
for (const stats of data.byOperation) {
|
|
1369
|
+
for (const stats of [...data.byOperation].sort((a, b) => b.cost - a.cost)) {
|
|
1316
1370
|
console.log(` ${stats.operation}: ${formatTokens(stats.tokenCount)} tokens (${formatCost(stats.cost)})`);
|
|
1317
1371
|
}
|
|
1318
1372
|
}
|
|
@@ -1321,8 +1375,12 @@ async function showUsageDetails() {
|
|
|
1321
1375
|
spinner.stop();
|
|
1322
1376
|
console.log(chalk.yellow("Error fetching usage data."));
|
|
1323
1377
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1378
|
+
if (pauseForInput) {
|
|
1379
|
+
console.log();
|
|
1380
|
+
await prompt("Press Enter to continue");
|
|
1381
|
+
} else {
|
|
1382
|
+
console.log();
|
|
1383
|
+
}
|
|
1326
1384
|
}
|
|
1327
1385
|
|
|
1328
1386
|
export {
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
showExecutionPreferences,
|
|
29
29
|
showPreferences,
|
|
30
30
|
showUsageDetails
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-MIT5Z5V7.js";
|
|
32
32
|
import {
|
|
33
33
|
a11yBadge,
|
|
34
34
|
a11yCheck,
|
|
@@ -3187,7 +3187,7 @@ async function handleNewProject(cwd, _state) {
|
|
|
3187
3187
|
}
|
|
3188
3188
|
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3189
3189
|
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
3190
|
-
await runExploreFlow(cwd);
|
|
3190
|
+
await runExploreFlow(cwd, initialResponse);
|
|
3191
3191
|
return;
|
|
3192
3192
|
}
|
|
3193
3193
|
if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
|
|
@@ -3274,7 +3274,7 @@ async function showNewProjectMenu(cwd) {
|
|
|
3274
3274
|
await showNewProjectMenu(cwd);
|
|
3275
3275
|
}
|
|
3276
3276
|
}
|
|
3277
|
-
async function runExploreFlow(cwd) {
|
|
3277
|
+
async function runExploreFlow(cwd, followUpInput) {
|
|
3278
3278
|
console.log(chalk6.blue("-- Analyzing Project --\n"));
|
|
3279
3279
|
const projectInfo = await gatherProjectInfo(cwd);
|
|
3280
3280
|
console.log(chalk6.bold("\u{1F4C1} Project Overview\n"));
|
|
@@ -3315,6 +3315,13 @@ async function runExploreFlow(cwd) {
|
|
|
3315
3315
|
}
|
|
3316
3316
|
console.log();
|
|
3317
3317
|
console.log(chalk6.green("\u2713 Analysis complete! I'm ready to work on this project.\n"));
|
|
3318
|
+
const actionableFollowUp = extractActionableFollowUpFromExplore(followUpInput ?? "");
|
|
3319
|
+
if (actionableFollowUp) {
|
|
3320
|
+
console.log(chalk6.dim("I finished the project scan. Continuing with your requested task...\n"));
|
|
3321
|
+
await handlePostExploreAction(cwd, actionableFollowUp);
|
|
3322
|
+
await showMainMenu();
|
|
3323
|
+
return;
|
|
3324
|
+
}
|
|
3318
3325
|
console.log(chalk6.bold("What would you like to do next?\n"));
|
|
3319
3326
|
console.log(chalk6.dim("You can describe it naturally, or use shortcuts:\n"));
|
|
3320
3327
|
console.log(` ${chalk6.cyan("1")}) ${chalk6.bold("Plan a task")} \u2014 Tell me what to implement, fix, or change`);
|
|
@@ -3332,22 +3339,26 @@ async function runExploreFlow(cwd) {
|
|
|
3332
3339
|
const { plan: plan2 } = await import("./plan-7SCZH7EA.js");
|
|
3333
3340
|
await plan2(description, {});
|
|
3334
3341
|
}
|
|
3335
|
-
|
|
3342
|
+
await showMainMenu();
|
|
3343
|
+
return;
|
|
3336
3344
|
}
|
|
3337
3345
|
case "2":
|
|
3338
3346
|
await codeReviewFirst(cwd);
|
|
3339
|
-
|
|
3347
|
+
await showMainMenu();
|
|
3348
|
+
return;
|
|
3340
3349
|
case "3":
|
|
3341
3350
|
if (!projectInfo.hasArchitecture) {
|
|
3342
3351
|
await analyzeAndAdapt(cwd);
|
|
3343
3352
|
}
|
|
3344
|
-
|
|
3353
|
+
await showMainMenu();
|
|
3354
|
+
return;
|
|
3345
3355
|
case "q":
|
|
3346
3356
|
process.exit(0);
|
|
3347
3357
|
default:
|
|
3348
3358
|
if (choice.trim()) {
|
|
3349
3359
|
const handled = await handleFreeformJourneyInput(cwd, choice);
|
|
3350
3360
|
if (handled) {
|
|
3361
|
+
await showMainMenu();
|
|
3351
3362
|
return;
|
|
3352
3363
|
}
|
|
3353
3364
|
}
|
|
@@ -3649,7 +3660,7 @@ async function handleAdaptExisting(cwd, state) {
|
|
|
3649
3660
|
const intent = detectUserIntent(response);
|
|
3650
3661
|
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3651
3662
|
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
3652
|
-
await runExploreFlow(cwd);
|
|
3663
|
+
await runExploreFlow(cwd, response);
|
|
3653
3664
|
return;
|
|
3654
3665
|
}
|
|
3655
3666
|
if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
|
|
@@ -3874,7 +3885,7 @@ async function handleFreeformJourneyInput(cwd, input) {
|
|
|
3874
3885
|
const intent = detectUserIntent(freeform);
|
|
3875
3886
|
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3876
3887
|
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
3877
|
-
await runExploreFlow(cwd);
|
|
3888
|
+
await runExploreFlow(cwd, freeform);
|
|
3878
3889
|
return true;
|
|
3879
3890
|
}
|
|
3880
3891
|
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
@@ -3887,6 +3898,42 @@ async function handleFreeformJourneyInput(cwd, input) {
|
|
|
3887
3898
|
await plan2(freeform, {});
|
|
3888
3899
|
return true;
|
|
3889
3900
|
}
|
|
3901
|
+
function extractActionableFollowUpFromExplore(input) {
|
|
3902
|
+
const trimmed = input.trim();
|
|
3903
|
+
if (!trimmed) return null;
|
|
3904
|
+
const normalized = trimmed.toLowerCase();
|
|
3905
|
+
const hasExploreSignal = /(analyz|review|explore|scan|inspect|understand|get familiar)/.test(normalized);
|
|
3906
|
+
const hasActionSignal = /(how (can|could|do i)|create|build|generate|make|produce|plan|implement|write)/.test(normalized);
|
|
3907
|
+
if (!hasExploreSignal || !hasActionSignal) {
|
|
3908
|
+
return null;
|
|
3909
|
+
}
|
|
3910
|
+
const transitions = [" and then ", " then ", " and "];
|
|
3911
|
+
for (const token of transitions) {
|
|
3912
|
+
const idx = normalized.indexOf(token);
|
|
3913
|
+
if (idx !== -1) {
|
|
3914
|
+
const candidate = trimmed.slice(idx + token.length).trim();
|
|
3915
|
+
if (candidate.length > 10) {
|
|
3916
|
+
return candidate;
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3920
|
+
return trimmed;
|
|
3921
|
+
}
|
|
3922
|
+
async function handlePostExploreAction(cwd, request) {
|
|
3923
|
+
const intent = detectUserIntent(request);
|
|
3924
|
+
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
3925
|
+
console.log(chalk6.dim("> Let me understand your project better...\n"));
|
|
3926
|
+
await runConversationalInterview(cwd, request);
|
|
3927
|
+
return;
|
|
3928
|
+
}
|
|
3929
|
+
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3930
|
+
console.log(chalk6.dim("> I can go deeper. Creating a concrete task from your request...\n"));
|
|
3931
|
+
} else {
|
|
3932
|
+
console.log(chalk6.dim("> Got it! Creating a task for this...\n"));
|
|
3933
|
+
}
|
|
3934
|
+
const { plan: plan2 } = await import("./plan-7SCZH7EA.js");
|
|
3935
|
+
await plan2(request, {});
|
|
3936
|
+
}
|
|
3890
3937
|
async function showReviewProgress(cwd) {
|
|
3891
3938
|
try {
|
|
3892
3939
|
const { ReviewDatabase } = await import("./code-review-GJVBZPZA.js");
|
|
@@ -3919,7 +3966,7 @@ async function listAtoms() {
|
|
|
3919
3966
|
async function executeNext() {
|
|
3920
3967
|
const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-7SCZH7EA.js");
|
|
3921
3968
|
const { analyzeProject, getComplexityDescription, getModeDescription } = await import("./orchestration-HIF3KP25.js");
|
|
3922
|
-
const { loadExecutionPreferences } = await import("./preferences-
|
|
3969
|
+
const { loadExecutionPreferences } = await import("./preferences-4V4C7MVD.js");
|
|
3923
3970
|
const cwd = process.cwd();
|
|
3924
3971
|
const atoms = await listLocalAtoms2();
|
|
3925
3972
|
const pendingAtoms = atoms.filter((a) => a.status === "READY" || a.status === "IN_PROGRESS");
|
|
@@ -4018,7 +4065,7 @@ async function viewStatus() {
|
|
|
4018
4065
|
await status2();
|
|
4019
4066
|
}
|
|
4020
4067
|
async function settingsMenu() {
|
|
4021
|
-
const { interactiveSettings } = await import("./preferences-
|
|
4068
|
+
const { interactiveSettings } = await import("./preferences-4V4C7MVD.js");
|
|
4022
4069
|
await interactiveSettings();
|
|
4023
4070
|
await showMainMenu();
|
|
4024
4071
|
}
|
|
@@ -4376,16 +4423,38 @@ import readline2 from "readline";
|
|
|
4376
4423
|
function getSupabaseClient(accessToken) {
|
|
4377
4424
|
return createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, accessToken);
|
|
4378
4425
|
}
|
|
4426
|
+
async function resolveAuthAndProfileIds(accessToken, fallbackAuthId) {
|
|
4427
|
+
const supabase = getSupabaseClient(accessToken);
|
|
4428
|
+
let authId = fallbackAuthId ?? null;
|
|
4429
|
+
if (!authId) {
|
|
4430
|
+
const { data, error } = await supabase.auth.getUser();
|
|
4431
|
+
if (error || !data.user?.id) {
|
|
4432
|
+
return { authId: null, profileId: null };
|
|
4433
|
+
}
|
|
4434
|
+
authId = data.user.id;
|
|
4435
|
+
}
|
|
4436
|
+
const { data: profile } = await supabase.from("user_profiles").select("id").eq("auth_id", authId).single();
|
|
4437
|
+
return {
|
|
4438
|
+
authId,
|
|
4439
|
+
profileId: profile?.id ?? null
|
|
4440
|
+
};
|
|
4441
|
+
}
|
|
4379
4442
|
async function showCredits() {
|
|
4380
4443
|
const spinner = ora("Fetching credit balance...").start();
|
|
4381
4444
|
try {
|
|
4382
4445
|
const config = await loadConfig();
|
|
4383
|
-
|
|
4446
|
+
const authToken = getAuthToken(config);
|
|
4447
|
+
if (!authToken) {
|
|
4384
4448
|
spinner.fail("Not logged in. Run: archon login");
|
|
4385
4449
|
return;
|
|
4386
4450
|
}
|
|
4387
|
-
const supabase = getSupabaseClient(
|
|
4388
|
-
const
|
|
4451
|
+
const supabase = getSupabaseClient(authToken);
|
|
4452
|
+
const ids = await resolveAuthAndProfileIds(authToken, config.userId);
|
|
4453
|
+
if (!ids.authId) {
|
|
4454
|
+
spinner.fail("Could not resolve account. Run: archon login");
|
|
4455
|
+
return;
|
|
4456
|
+
}
|
|
4457
|
+
const { data, error } = await supabase.from("user_profiles").select("tier, credit_balance_cents, atoms_used_this_month").eq("auth_id", ids.authId).single();
|
|
4389
4458
|
if (error || !data) {
|
|
4390
4459
|
spinner.fail("Could not fetch profile");
|
|
4391
4460
|
return;
|
|
@@ -4406,6 +4475,7 @@ async function showCredits() {
|
|
|
4406
4475
|
} else if (profile.tier === "CREDITS") {
|
|
4407
4476
|
console.log();
|
|
4408
4477
|
console.log(chalk7.dim(" Add more credits: archon credits add"));
|
|
4478
|
+
console.log(chalk7.dim(" Detailed usage by model: archon usage"));
|
|
4409
4479
|
printCreditsNextAction("CREDITS");
|
|
4410
4480
|
if (balance < 5) {
|
|
4411
4481
|
const addNow = await promptYesNo2("Balance is low. Add credits now?", false);
|
|
@@ -4416,6 +4486,7 @@ async function showCredits() {
|
|
|
4416
4486
|
} else if (profile.tier === "BYOK") {
|
|
4417
4487
|
console.log();
|
|
4418
4488
|
console.log(chalk7.dim(" Using your own API keys - no credit charges"));
|
|
4489
|
+
console.log(chalk7.dim(" Estimated spend by model: archon usage"));
|
|
4419
4490
|
printCreditsNextAction("BYOK");
|
|
4420
4491
|
}
|
|
4421
4492
|
console.log();
|
|
@@ -4514,13 +4585,19 @@ async function showHistory(options = {}) {
|
|
|
4514
4585
|
const spinner = ora("Fetching usage history...").start();
|
|
4515
4586
|
try {
|
|
4516
4587
|
const config = await loadConfig();
|
|
4517
|
-
|
|
4588
|
+
const authToken = getAuthToken(config);
|
|
4589
|
+
if (!authToken) {
|
|
4518
4590
|
spinner.fail("Not logged in. Run: archon login");
|
|
4519
4591
|
return;
|
|
4520
4592
|
}
|
|
4521
|
-
const supabase = getSupabaseClient(
|
|
4593
|
+
const supabase = getSupabaseClient(authToken);
|
|
4594
|
+
const ids = await resolveAuthAndProfileIds(authToken, config.userId);
|
|
4595
|
+
if (!ids.profileId) {
|
|
4596
|
+
spinner.fail("Could not resolve profile for usage history");
|
|
4597
|
+
return;
|
|
4598
|
+
}
|
|
4522
4599
|
const limit = options.limit ? parseInt(options.limit, 10) : 20;
|
|
4523
|
-
const { data, error } = await supabase.from("token_usage").select("model, input_tokens, output_tokens, base_cost, created_at").eq("user_id",
|
|
4600
|
+
const { data, error } = await supabase.from("token_usage").select("model, input_tokens, output_tokens, base_cost, created_at").eq("user_id", ids.profileId).order("created_at", { ascending: false }).limit(limit);
|
|
4524
4601
|
if (error) {
|
|
4525
4602
|
spinner.fail("Could not fetch usage");
|
|
4526
4603
|
return;
|