archondev 2.19.9 → 2.19.11
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 +188 -40
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2844,6 +2844,55 @@ async function start(options = {}) {
|
|
|
2844
2844
|
} catch {
|
|
2845
2845
|
}
|
|
2846
2846
|
}
|
|
2847
|
+
if (currentTier === "BYOK" && config.accessToken) {
|
|
2848
|
+
try {
|
|
2849
|
+
let usageStats = await fetchByokUsageStats(config.accessToken);
|
|
2850
|
+
const usageStatsUnavailable = !usageStats;
|
|
2851
|
+
if (!usageStats) {
|
|
2852
|
+
usageStats = {
|
|
2853
|
+
totalInputTokens: 0,
|
|
2854
|
+
totalOutputTokens: 0,
|
|
2855
|
+
totalBaseCost: 0,
|
|
2856
|
+
byModel: []
|
|
2857
|
+
};
|
|
2858
|
+
}
|
|
2859
|
+
console.log();
|
|
2860
|
+
console.log(chalk6.bold("\u{1F4CA} BYOK Usage"));
|
|
2861
|
+
console.log(chalk6.dim("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
2862
|
+
if (usageStats.periodStart) {
|
|
2863
|
+
const periodStart = new Date(usageStats.periodStart);
|
|
2864
|
+
const periodEnd = usageStats.periodEnd ? new Date(usageStats.periodEnd) : null;
|
|
2865
|
+
const formattedStart = isNaN(periodStart.getTime()) ? usageStats.periodStart : periodStart.toLocaleDateString();
|
|
2866
|
+
const formattedEnd = periodEnd && !isNaN(periodEnd.getTime()) ? periodEnd.toLocaleDateString() : void 0;
|
|
2867
|
+
if (formattedEnd) {
|
|
2868
|
+
console.log(chalk6.dim(` Period: ${formattedStart} \u2192 ${formattedEnd}`));
|
|
2869
|
+
} else {
|
|
2870
|
+
console.log(chalk6.dim(` Period start: ${formattedStart}`));
|
|
2871
|
+
}
|
|
2872
|
+
} else {
|
|
2873
|
+
console.log(chalk6.dim(" Period: Current month to date"));
|
|
2874
|
+
}
|
|
2875
|
+
const totalTokens = usageStats.totalInputTokens + usageStats.totalOutputTokens;
|
|
2876
|
+
console.log(` Tokens: ${chalk6.dim(totalTokens.toLocaleString())}`);
|
|
2877
|
+
console.log(` Estimated provider spend: ${chalk6.dim(`$${usageStats.totalBaseCost.toFixed(4)}`)}`);
|
|
2878
|
+
console.log();
|
|
2879
|
+
console.log(chalk6.dim(" Model Usage:"));
|
|
2880
|
+
if (usageStats.byModel.length > 0) {
|
|
2881
|
+
for (const model of usageStats.byModel) {
|
|
2882
|
+
const modelName = model.model.length > 32 ? model.model.slice(0, 29) + "..." : model.model;
|
|
2883
|
+
console.log(chalk6.dim(` ${modelName.padEnd(34)} $${model.cost.toFixed(4)}`));
|
|
2884
|
+
}
|
|
2885
|
+
} else {
|
|
2886
|
+
console.log(chalk6.dim(` ${"No usage yet".padEnd(34)} $0.0000`));
|
|
2887
|
+
}
|
|
2888
|
+
console.log(chalk6.dim("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
2889
|
+
if (usageStatsUnavailable) {
|
|
2890
|
+
console.log(chalk6.dim("Usage details may be delayed. Run `archon usage` to refresh."));
|
|
2891
|
+
}
|
|
2892
|
+
console.log(chalk6.dim("View details: archon usage | Models: archon preferences | Switch tier: archon upgrade"));
|
|
2893
|
+
} catch {
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2847
2896
|
if (currentTier === "BYOK") {
|
|
2848
2897
|
const { keyManager } = await import("./keys-THCHXIFD.js");
|
|
2849
2898
|
const hasKeys = await keyManager.hasAnyKey();
|
|
@@ -2988,6 +3037,38 @@ async function fetchCreditsUsageStats(accessToken, authId) {
|
|
|
2988
3037
|
}
|
|
2989
3038
|
return fetchCreditsUsageStatsFromSupabase(accessToken, authId);
|
|
2990
3039
|
}
|
|
3040
|
+
async function fetchByokUsageStats(accessToken) {
|
|
3041
|
+
try {
|
|
3042
|
+
const { API_URL: API_URL3 } = await import("./constants-XDIWFFPN.js");
|
|
3043
|
+
const response = await fetch(`${API_URL3}/api/usage`, {
|
|
3044
|
+
headers: {
|
|
3045
|
+
"Authorization": `Bearer ${accessToken}`
|
|
3046
|
+
}
|
|
3047
|
+
});
|
|
3048
|
+
if (!response.ok) {
|
|
3049
|
+
return null;
|
|
3050
|
+
}
|
|
3051
|
+
const data = await response.json();
|
|
3052
|
+
if (data.tier && data.tier !== "BYOK") {
|
|
3053
|
+
return null;
|
|
3054
|
+
}
|
|
3055
|
+
const byModel = [...data.byModel ?? []].map((row) => ({
|
|
3056
|
+
model: row.model,
|
|
3057
|
+
cost: typeof row.cost === "number" ? row.cost : 0
|
|
3058
|
+
})).sort((a, b) => b.cost - a.cost);
|
|
3059
|
+
return {
|
|
3060
|
+
totalInputTokens: data.totalInputTokens ?? 0,
|
|
3061
|
+
totalOutputTokens: data.totalOutputTokens ?? 0,
|
|
3062
|
+
totalBaseCost: data.totalBaseCost ?? 0,
|
|
3063
|
+
byModel,
|
|
3064
|
+
periodStart: data.periodStart,
|
|
3065
|
+
periodEnd: data.periodEnd,
|
|
3066
|
+
periodSource: data.periodSource
|
|
3067
|
+
};
|
|
3068
|
+
} catch {
|
|
3069
|
+
return null;
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
2991
3072
|
async function fetchCreditsUsageStatsFromSupabase(accessToken, authId) {
|
|
2992
3073
|
try {
|
|
2993
3074
|
const { SUPABASE_URL: SUPABASE_URL2, SUPABASE_ANON_KEY: SUPABASE_ANON_KEY2 } = await import("./constants-XDIWFFPN.js");
|
|
@@ -3496,7 +3577,7 @@ async function runAIInterview(cwd, initialMessage, agent) {
|
|
|
3496
3577
|
console.log(chalk6.dim(`
|
|
3497
3578
|
(Interview used ${usage.totalTokens} tokens, $${usage.baseCost.toFixed(4)})`));
|
|
3498
3579
|
}
|
|
3499
|
-
await finishInterview(cwd, state);
|
|
3580
|
+
await finishInterview(cwd, state, initialMessage);
|
|
3500
3581
|
} catch (error) {
|
|
3501
3582
|
console.log(chalk6.yellow("\n[!] AI interview unavailable, using simple setup.\n"));
|
|
3502
3583
|
await runSimpleInterview(cwd, initialMessage);
|
|
@@ -3524,46 +3605,17 @@ async function runSimpleInterview(cwd, initialMessage) {
|
|
|
3524
3605
|
}
|
|
3525
3606
|
}
|
|
3526
3607
|
if (!state.audience) {
|
|
3527
|
-
|
|
3528
|
-
const audience = await prompt("Who is this for? (me / team / public)");
|
|
3529
|
-
if (!wantsToSkip(audience)) {
|
|
3530
|
-
const lower = audience.toLowerCase().trim();
|
|
3531
|
-
if (lower.includes("me") || lower.includes("personal") || lower.includes("myself")) {
|
|
3532
|
-
state.audience = "personal";
|
|
3533
|
-
state.posture = "prototype";
|
|
3534
|
-
} else if (lower.includes("team") || lower.includes("internal")) {
|
|
3535
|
-
state.audience = "team";
|
|
3536
|
-
state.posture = "production";
|
|
3537
|
-
} else if (lower.includes("public") || lower.includes("user") || lower.includes("customer")) {
|
|
3538
|
-
state.audience = "endusers";
|
|
3539
|
-
state.posture = "production";
|
|
3540
|
-
}
|
|
3541
|
-
}
|
|
3608
|
+
state.audience = inferAudienceFromMessage(initialMessage);
|
|
3542
3609
|
}
|
|
3543
3610
|
if (!state.language) {
|
|
3544
|
-
|
|
3545
|
-
const lang = await prompt("What language? (typescript / python / go / rust / other)");
|
|
3546
|
-
if (!wantsToSkip(lang)) {
|
|
3547
|
-
const lower = lang.toLowerCase().trim();
|
|
3548
|
-
if (lower.includes("typescript") || lower.includes("ts") || lower.includes("javascript") || lower.includes("js")) {
|
|
3549
|
-
state.language = "typescript";
|
|
3550
|
-
} else if (lower.includes("python") || lower.includes("py")) {
|
|
3551
|
-
state.language = "python";
|
|
3552
|
-
} else if (lower.includes("go") || lower.includes("golang")) {
|
|
3553
|
-
state.language = "go";
|
|
3554
|
-
} else if (lower.includes("rust") || lower.includes("rs")) {
|
|
3555
|
-
state.language = "rust";
|
|
3556
|
-
} else if (lang.trim()) {
|
|
3557
|
-
state.language = lang.trim();
|
|
3558
|
-
}
|
|
3559
|
-
}
|
|
3611
|
+
state.language = inferLanguageFromProjectFiles(cwd) ?? "typescript";
|
|
3560
3612
|
}
|
|
3561
3613
|
if (!state.posture) {
|
|
3562
3614
|
state.posture = inferPosture(state) ?? "production";
|
|
3563
3615
|
}
|
|
3564
|
-
await finishInterview(cwd, state);
|
|
3616
|
+
await finishInterview(cwd, state, initialMessage);
|
|
3565
3617
|
}
|
|
3566
|
-
async function finishInterview(cwd, state) {
|
|
3618
|
+
async function finishInterview(cwd, state, initialTaskHint) {
|
|
3567
3619
|
console.log(chalk6.blue("\n-- Recording Project Details --\n"));
|
|
3568
3620
|
const posture = state.posture === "enterprise" ? "enterprise" : state.posture === "prototype" ? "prototype" : "production";
|
|
3569
3621
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -3609,14 +3661,110 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
|
|
|
3609
3661
|
console.log(` 1. ${chalk6.cyan("Review")} ARCHITECTURE.md and customize if needed`);
|
|
3610
3662
|
console.log(` 2. ${chalk6.cyan("Run")} ${chalk6.dim('archon plan "your first task"')} to create an atom`);
|
|
3611
3663
|
console.log();
|
|
3612
|
-
const
|
|
3613
|
-
if (
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3664
|
+
const hintedTask = initialTaskHint?.trim() ?? "";
|
|
3665
|
+
if (hintedTask) {
|
|
3666
|
+
console.log(chalk6.dim("Using your request above as the first task.\n"));
|
|
3667
|
+
const { plan: plan2 } = await import("./plan-AR6Y4QUD.js");
|
|
3668
|
+
await plan2(hintedTask, {});
|
|
3669
|
+
return;
|
|
3670
|
+
}
|
|
3671
|
+
const continueAnswer = await prompt("Would you like to plan your first task now? (Y/n)");
|
|
3672
|
+
const normalized = continueAnswer.trim().toLowerCase();
|
|
3673
|
+
const useDefault = normalized === "";
|
|
3674
|
+
const isYes = normalized === "y" || normalized === "yes";
|
|
3675
|
+
const isNo = normalized === "n" || normalized === "no";
|
|
3676
|
+
if (isNo) {
|
|
3677
|
+
return;
|
|
3678
|
+
}
|
|
3679
|
+
let description = "";
|
|
3680
|
+
if (useDefault || isYes) {
|
|
3681
|
+
const hinted = initialTaskHint?.trim() ?? "";
|
|
3682
|
+
if (hinted) {
|
|
3683
|
+
description = hinted;
|
|
3684
|
+
console.log(chalk6.dim("\nUsing your request above as the first task.\n"));
|
|
3685
|
+
} else {
|
|
3686
|
+
description = await promptWithCommands("Describe what you want to build first", { allowMultiline: true });
|
|
3687
|
+
}
|
|
3688
|
+
} else {
|
|
3689
|
+
description = continueAnswer.trim();
|
|
3690
|
+
}
|
|
3691
|
+
if (description.trim()) {
|
|
3692
|
+
const { plan: plan2 } = await import("./plan-AR6Y4QUD.js");
|
|
3693
|
+
await plan2(description, {});
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
function inferAudienceFromMessage(message) {
|
|
3697
|
+
const lower = message.toLowerCase();
|
|
3698
|
+
if (/\b(i|me|my|myself)\b/.test(lower) && !/\b(users?|customers?|public|team|internal)\b/.test(lower)) {
|
|
3699
|
+
return "personal";
|
|
3700
|
+
}
|
|
3701
|
+
if (/\bteam|internal|coworkers?|org\b/.test(lower)) {
|
|
3702
|
+
return "team";
|
|
3703
|
+
}
|
|
3704
|
+
return "endusers";
|
|
3705
|
+
}
|
|
3706
|
+
function inferLanguageFromProjectFiles(cwd) {
|
|
3707
|
+
const extToLanguage = /* @__PURE__ */ new Map([
|
|
3708
|
+
[".ts", "typescript"],
|
|
3709
|
+
[".tsx", "typescript"],
|
|
3710
|
+
[".js", "javascript"],
|
|
3711
|
+
[".jsx", "javascript"],
|
|
3712
|
+
[".py", "python"],
|
|
3713
|
+
[".go", "go"],
|
|
3714
|
+
[".rs", "rust"],
|
|
3715
|
+
[".java", "java"],
|
|
3716
|
+
[".kt", "kotlin"],
|
|
3717
|
+
[".swift", "swift"],
|
|
3718
|
+
[".rb", "ruby"],
|
|
3719
|
+
[".php", "php"],
|
|
3720
|
+
[".cs", "csharp"]
|
|
3721
|
+
]);
|
|
3722
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3723
|
+
const rootDirs = ["src", "app", "lib", "server", "backend", "frontend", "services"];
|
|
3724
|
+
for (const root of rootDirs) {
|
|
3725
|
+
const rootPath = join6(cwd, root);
|
|
3726
|
+
if (!existsSync6(rootPath)) {
|
|
3727
|
+
continue;
|
|
3728
|
+
}
|
|
3729
|
+
try {
|
|
3730
|
+
const stack = [rootPath];
|
|
3731
|
+
while (stack.length > 0) {
|
|
3732
|
+
const current = stack.pop();
|
|
3733
|
+
if (!current) {
|
|
3734
|
+
continue;
|
|
3735
|
+
}
|
|
3736
|
+
const entries = readdirSync3(current, { withFileTypes: true });
|
|
3737
|
+
for (const entry of entries) {
|
|
3738
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build") {
|
|
3739
|
+
continue;
|
|
3740
|
+
}
|
|
3741
|
+
const fullPath = join6(current, entry.name);
|
|
3742
|
+
if (entry.isDirectory()) {
|
|
3743
|
+
stack.push(fullPath);
|
|
3744
|
+
continue;
|
|
3745
|
+
}
|
|
3746
|
+
const dotIndex = entry.name.lastIndexOf(".");
|
|
3747
|
+
if (dotIndex === -1) {
|
|
3748
|
+
continue;
|
|
3749
|
+
}
|
|
3750
|
+
const ext = entry.name.slice(dotIndex);
|
|
3751
|
+
const language = extToLanguage.get(ext);
|
|
3752
|
+
if (!language) {
|
|
3753
|
+
continue;
|
|
3754
|
+
}
|
|
3755
|
+
counts.set(language, (counts.get(language) ?? 0) + 1);
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
} catch {
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
let best;
|
|
3762
|
+
for (const [language, count] of counts.entries()) {
|
|
3763
|
+
if (!best || count > best.count) {
|
|
3764
|
+
best = { language, count };
|
|
3618
3765
|
}
|
|
3619
3766
|
}
|
|
3767
|
+
return best?.language;
|
|
3620
3768
|
}
|
|
3621
3769
|
async function quickStart(cwd) {
|
|
3622
3770
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|