archondev 1.1.0 → 1.2.0
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/bug-DXLBBW3U.js +1 -1
- package/dist/{chunk-4NZPAEKS.js → chunk-EDP55FCI.js} +23 -416
- package/dist/{chunk-QPYDPMUV.js → chunk-I4ZVNLNO.js} +1 -1
- package/dist/chunk-IMZN36GC.js +159 -0
- package/dist/{chunk-BL5TX2UW.js → chunk-PK3OQVBG.js} +1 -1
- package/dist/chunk-SMR7JQK6.js +399 -0
- package/dist/chunk-UG2ZZ7CM.js +737 -0
- package/dist/{execute-55VINPV5.js → execute-LYID2ODD.js} +4 -3
- package/dist/index.js +91 -584
- package/dist/keys-EL3FUM5O.js +15 -0
- package/dist/{list-LKYYAGSN.js → list-VXMVEIL5.js} +4 -3
- package/dist/{plan-MWUUJV3W.js → plan-7VSFESVD.js} +3 -2
- package/dist/preferences-PL2ON5VY.js +17 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
listModels,
|
|
4
|
+
resetPreferences,
|
|
5
|
+
setPreference,
|
|
6
|
+
showPreferences
|
|
7
|
+
} from "./chunk-UG2ZZ7CM.js";
|
|
2
8
|
import {
|
|
3
9
|
reviewAnalyze,
|
|
4
10
|
reviewExport,
|
|
@@ -11,6 +17,7 @@ import {
|
|
|
11
17
|
reviewStatus,
|
|
12
18
|
reviewUpdate
|
|
13
19
|
} from "./chunk-UDBFDXJI.js";
|
|
20
|
+
import "./chunk-VKM3HAHW.js";
|
|
14
21
|
import {
|
|
15
22
|
API_URL,
|
|
16
23
|
SUPABASE_ANON_KEY,
|
|
@@ -23,35 +30,36 @@ import {
|
|
|
23
30
|
EnvironmentConfigLoader,
|
|
24
31
|
EnvironmentValidator,
|
|
25
32
|
execute
|
|
26
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-I4ZVNLNO.js";
|
|
27
34
|
import {
|
|
28
35
|
list
|
|
29
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-PK3OQVBG.js";
|
|
30
37
|
import {
|
|
31
|
-
KeyValidator,
|
|
32
|
-
keyManager,
|
|
33
38
|
listLocalAtoms,
|
|
34
39
|
loadAtom,
|
|
35
40
|
plan
|
|
36
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-EDP55FCI.js";
|
|
37
42
|
import "./chunk-2CFO5GVH.js";
|
|
38
43
|
import {
|
|
39
44
|
bugReport
|
|
40
45
|
} from "./chunk-JBKFAD4M.js";
|
|
41
46
|
import "./chunk-MOZHC2GX.js";
|
|
47
|
+
import "./chunk-A7QU6JC6.js";
|
|
42
48
|
import {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
addKey,
|
|
50
|
+
listKeys,
|
|
51
|
+
removeKey,
|
|
52
|
+
setPrimaryKey
|
|
53
|
+
} from "./chunk-IMZN36GC.js";
|
|
54
|
+
import "./chunk-SMR7JQK6.js";
|
|
55
|
+
import {
|
|
56
|
+
loadConfig
|
|
47
57
|
} from "./chunk-WCCBJSNI.js";
|
|
48
|
-
import "./chunk-VKM3HAHW.js";
|
|
49
|
-
import "./chunk-A7QU6JC6.js";
|
|
50
58
|
import "./chunk-QGM4M3NI.js";
|
|
51
59
|
|
|
52
60
|
// src/cli/index.ts
|
|
53
61
|
import { Command } from "commander";
|
|
54
|
-
import
|
|
62
|
+
import chalk6 from "chalk";
|
|
55
63
|
import "dotenv/config";
|
|
56
64
|
|
|
57
65
|
// src/cli/init.ts
|
|
@@ -607,160 +615,16 @@ function formatDateTime(date) {
|
|
|
607
615
|
return d.toLocaleString();
|
|
608
616
|
}
|
|
609
617
|
|
|
610
|
-
// src/cli/keys.ts
|
|
611
|
-
import chalk4 from "chalk";
|
|
612
|
-
import ora2 from "ora";
|
|
613
|
-
import { createInterface } from "readline";
|
|
614
|
-
var VALID_PROVIDERS = ["anthropic", "openai", "google"];
|
|
615
|
-
function isValidProvider(provider) {
|
|
616
|
-
return VALID_PROVIDERS.includes(provider);
|
|
617
|
-
}
|
|
618
|
-
async function promptForKey(provider) {
|
|
619
|
-
const rl = createInterface({
|
|
620
|
-
input: process.stdin,
|
|
621
|
-
output: process.stdout
|
|
622
|
-
});
|
|
623
|
-
return new Promise((resolve) => {
|
|
624
|
-
const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
625
|
-
rl.question(`Enter your ${providerName} API key: `, (answer) => {
|
|
626
|
-
rl.close();
|
|
627
|
-
resolve(answer.trim());
|
|
628
|
-
});
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
async function addKey(provider, options = {}) {
|
|
632
|
-
if (!isValidProvider(provider)) {
|
|
633
|
-
console.error(chalk4.red(`Invalid provider: ${provider}`));
|
|
634
|
-
console.log(chalk4.dim(`Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
635
|
-
process.exit(1);
|
|
636
|
-
}
|
|
637
|
-
const label = options.label ?? "default";
|
|
638
|
-
const apiKey = await promptForKey(provider);
|
|
639
|
-
if (!apiKey) {
|
|
640
|
-
console.error(chalk4.red("API key cannot be empty"));
|
|
641
|
-
process.exit(1);
|
|
642
|
-
}
|
|
643
|
-
const spinner = ora2("Validating API key...").start();
|
|
644
|
-
const validator = new KeyValidator();
|
|
645
|
-
const validationResult = await validator.validateKey(provider, apiKey);
|
|
646
|
-
if (!validationResult.valid) {
|
|
647
|
-
spinner.fail(chalk4.red(`API key validation failed: ${validationResult.error}`));
|
|
648
|
-
process.exit(1);
|
|
649
|
-
}
|
|
650
|
-
spinner.text = "Encrypting and storing API key...";
|
|
651
|
-
const result = await keyManager.addKey(provider, apiKey, label);
|
|
652
|
-
if (!result.success) {
|
|
653
|
-
spinner.fail(chalk4.red(`Failed to store key: ${result.error}`));
|
|
654
|
-
process.exit(1);
|
|
655
|
-
}
|
|
656
|
-
const config = await loadConfig();
|
|
657
|
-
if (config.tier === "FREE") {
|
|
658
|
-
await saveConfig({ ...config, tier: "BYOK" });
|
|
659
|
-
spinner.succeed(chalk4.green(`API key for ${provider} (${label}) added successfully!`));
|
|
660
|
-
console.log(chalk4.blue("Your tier has been upgraded to BYOK (Bring Your Own Key)"));
|
|
661
|
-
console.log(chalk4.dim("You now have access to all models and unlimited atoms."));
|
|
662
|
-
} else {
|
|
663
|
-
spinner.succeed(chalk4.green(`API key for ${provider} (${label}) added successfully!`));
|
|
664
|
-
}
|
|
665
|
-
const adversarialStatus = await keyManager.getAdversarialStatus();
|
|
666
|
-
if (adversarialStatus.enabled) {
|
|
667
|
-
console.log(chalk4.green(`\u2713 ${adversarialStatus.message}`));
|
|
668
|
-
} else {
|
|
669
|
-
console.log(chalk4.yellow(`\u25CB ${adversarialStatus.message}`));
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
async function listKeys() {
|
|
673
|
-
const spinner = ora2("Loading configured keys...").start();
|
|
674
|
-
const keys = await keyManager.listKeys();
|
|
675
|
-
spinner.stop();
|
|
676
|
-
if (keys.length === 0) {
|
|
677
|
-
console.log(chalk4.yellow("No API keys configured"));
|
|
678
|
-
console.log(chalk4.dim("Run `archon keys add <provider>` to add a key"));
|
|
679
|
-
console.log(chalk4.dim(`Available providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
console.log(chalk4.green("Configured API keys:"));
|
|
683
|
-
console.log();
|
|
684
|
-
const byProvider = {};
|
|
685
|
-
for (const key of keys) {
|
|
686
|
-
if (!byProvider[key.provider]) {
|
|
687
|
-
byProvider[key.provider] = [];
|
|
688
|
-
}
|
|
689
|
-
byProvider[key.provider]?.push(key);
|
|
690
|
-
}
|
|
691
|
-
for (const [provider, providerKeys] of Object.entries(byProvider)) {
|
|
692
|
-
console.log(chalk4.blue(` ${provider.toUpperCase()}`));
|
|
693
|
-
for (const key of providerKeys ?? []) {
|
|
694
|
-
const addedDate = new Date(key.createdAt).toLocaleDateString();
|
|
695
|
-
const primaryBadge = key.isPrimary ? chalk4.green(" [primary]") : "";
|
|
696
|
-
console.log(` \u2022 ${key.label}${primaryBadge} ${chalk4.dim(`(added ${addedDate})`)}`);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
console.log();
|
|
700
|
-
const adversarialStatus = await keyManager.getAdversarialStatus();
|
|
701
|
-
if (adversarialStatus.enabled) {
|
|
702
|
-
console.log(chalk4.green(`\u2713 ${adversarialStatus.message}`));
|
|
703
|
-
} else {
|
|
704
|
-
console.log(chalk4.yellow(`\u25CB ${adversarialStatus.message}`));
|
|
705
|
-
}
|
|
706
|
-
console.log();
|
|
707
|
-
console.log(chalk4.dim("Note: API keys are stored locally with encryption"));
|
|
708
|
-
}
|
|
709
|
-
async function removeKey(provider, options = {}) {
|
|
710
|
-
if (!isValidProvider(provider)) {
|
|
711
|
-
console.error(chalk4.red(`Invalid provider: ${provider}`));
|
|
712
|
-
console.log(chalk4.dim(`Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
713
|
-
process.exit(1);
|
|
714
|
-
}
|
|
715
|
-
const label = options.label;
|
|
716
|
-
const labelMsg = label ? ` (${label})` : "";
|
|
717
|
-
const spinner = ora2(`Removing API key for ${provider}${labelMsg}...`).start();
|
|
718
|
-
const result = await keyManager.removeKey(provider, label);
|
|
719
|
-
if (!result.success) {
|
|
720
|
-
spinner.fail(chalk4.red(result.error ?? "Failed to remove key"));
|
|
721
|
-
process.exit(1);
|
|
722
|
-
}
|
|
723
|
-
const hasRemainingKeys = await keyManager.hasAnyKey();
|
|
724
|
-
if (!hasRemainingKeys) {
|
|
725
|
-
const config = await loadConfig();
|
|
726
|
-
if (config.tier === "BYOK") {
|
|
727
|
-
await saveConfig({ ...config, tier: "FREE" });
|
|
728
|
-
spinner.succeed(chalk4.green(`API key for ${provider}${labelMsg} removed`));
|
|
729
|
-
console.log(chalk4.yellow("No API keys remaining. Tier reverted to FREE."));
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
spinner.succeed(chalk4.green(`API key for ${provider}${labelMsg} removed`));
|
|
734
|
-
const adversarialStatus = await keyManager.getAdversarialStatus();
|
|
735
|
-
if (!adversarialStatus.enabled && adversarialStatus.providerCount > 0) {
|
|
736
|
-
console.log(chalk4.yellow(`\u25CB ${adversarialStatus.message}`));
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
async function setPrimaryKey(provider, label) {
|
|
740
|
-
if (!isValidProvider(provider)) {
|
|
741
|
-
console.error(chalk4.red(`Invalid provider: ${provider}`));
|
|
742
|
-
console.log(chalk4.dim(`Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
743
|
-
process.exit(1);
|
|
744
|
-
}
|
|
745
|
-
const spinner = ora2(`Setting primary key for ${provider} to "${label}"...`).start();
|
|
746
|
-
const result = await keyManager.setPrimary(provider, label);
|
|
747
|
-
if (!result.success) {
|
|
748
|
-
spinner.fail(chalk4.red(result.error ?? "Failed to set primary key"));
|
|
749
|
-
process.exit(1);
|
|
750
|
-
}
|
|
751
|
-
spinner.succeed(chalk4.green(`Primary key for ${provider} set to "${label}"`));
|
|
752
|
-
}
|
|
753
|
-
|
|
754
618
|
// src/cli/start.ts
|
|
755
|
-
import
|
|
619
|
+
import chalk4 from "chalk";
|
|
756
620
|
import readline2 from "readline";
|
|
757
621
|
import { existsSync as existsSync3, readdirSync } from "fs";
|
|
758
622
|
import { join as join3 } from "path";
|
|
759
623
|
async function start() {
|
|
760
624
|
const cwd = process.cwd();
|
|
761
|
-
console.log(
|
|
762
|
-
console.log(
|
|
763
|
-
console.log(
|
|
625
|
+
console.log(chalk4.blue("\n\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
626
|
+
console.log(chalk4.bold.white(" ArchonDev - AI-Powered Development Governance"));
|
|
627
|
+
console.log(chalk4.blue("\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
764
628
|
const projectState = detectProjectState(cwd);
|
|
765
629
|
await showProjectStatus(cwd, projectState);
|
|
766
630
|
const choices = [
|
|
@@ -770,11 +634,12 @@ async function start() {
|
|
|
770
634
|
{ key: "4", label: "Report a bug", action: () => reportBug() },
|
|
771
635
|
{ key: "5", label: "View status", action: () => viewStatus() },
|
|
772
636
|
{ key: "6", label: "Code Review", action: () => reviewCode() },
|
|
637
|
+
{ key: "7", label: "Settings & Preferences", action: () => settingsMenu() },
|
|
773
638
|
{ key: "q", label: "Quit", action: async () => process.exit(0) }
|
|
774
639
|
];
|
|
775
|
-
console.log(
|
|
640
|
+
console.log(chalk4.bold("What would you like to do?\n"));
|
|
776
641
|
for (const choice2 of choices) {
|
|
777
|
-
console.log(` ${
|
|
642
|
+
console.log(` ${chalk4.cyan(choice2.key)}) ${choice2.label}`);
|
|
778
643
|
}
|
|
779
644
|
console.log();
|
|
780
645
|
const selected = await prompt("Enter choice");
|
|
@@ -782,7 +647,7 @@ async function start() {
|
|
|
782
647
|
if (choice) {
|
|
783
648
|
await choice.action();
|
|
784
649
|
} else {
|
|
785
|
-
console.log(
|
|
650
|
+
console.log(chalk4.yellow("Invalid choice. Please try again."));
|
|
786
651
|
await start();
|
|
787
652
|
}
|
|
788
653
|
}
|
|
@@ -813,19 +678,19 @@ function detectProjectState(cwd) {
|
|
|
813
678
|
}
|
|
814
679
|
async function showProjectStatus(cwd, state) {
|
|
815
680
|
if (state.hasSourceFiles && !state.hasArchitecture) {
|
|
816
|
-
console.log(
|
|
817
|
-
console.log(
|
|
681
|
+
console.log(chalk4.yellow("\u{1F4C1} Existing project detected") + chalk4.dim(" (source files found, no ARCHITECTURE.md)"));
|
|
682
|
+
console.log(chalk4.dim(" Consider running ") + chalk4.cyan("Code Review") + chalk4.dim(" first, then set up governance."));
|
|
818
683
|
console.log();
|
|
819
684
|
}
|
|
820
685
|
if (state.hasArchitecture) {
|
|
821
|
-
console.log(
|
|
686
|
+
console.log(chalk4.green("\u2713") + " ARCHITECTURE.md found");
|
|
822
687
|
}
|
|
823
688
|
if (state.hasReviewDb) {
|
|
824
689
|
await showReviewProgress(cwd);
|
|
825
690
|
}
|
|
826
691
|
const atomsDir = join3(cwd, ".archon", "atoms");
|
|
827
692
|
if (existsSync3(atomsDir)) {
|
|
828
|
-
console.log(
|
|
693
|
+
console.log(chalk4.dim(" Checking for pending work..."));
|
|
829
694
|
}
|
|
830
695
|
console.log();
|
|
831
696
|
}
|
|
@@ -841,29 +706,29 @@ async function showReviewProgress(cwd) {
|
|
|
841
706
|
const pending = stats.pending + stats.inReview;
|
|
842
707
|
const needsFix = stats.needsFix;
|
|
843
708
|
console.log(
|
|
844
|
-
|
|
709
|
+
chalk4.blue("\u{1F4CA} Review Progress:") + chalk4.dim(` ${completed}/${total} completed`) + (needsFix > 0 ? chalk4.red(` (${needsFix} need fixes)`) : "") + (pending > 0 ? chalk4.yellow(` (${pending} pending)`) : "")
|
|
845
710
|
);
|
|
846
711
|
} catch {
|
|
847
712
|
}
|
|
848
713
|
}
|
|
849
714
|
async function planTask() {
|
|
850
|
-
const { plan: plan2 } = await import("./plan-
|
|
715
|
+
const { plan: plan2 } = await import("./plan-7VSFESVD.js");
|
|
851
716
|
const description = await prompt("Describe what you want to build");
|
|
852
717
|
if (description.trim()) {
|
|
853
718
|
await plan2(description, {});
|
|
854
719
|
}
|
|
855
720
|
}
|
|
856
721
|
async function listAtoms() {
|
|
857
|
-
const { list: list2 } = await import("./list-
|
|
722
|
+
const { list: list2 } = await import("./list-VXMVEIL5.js");
|
|
858
723
|
await list2({});
|
|
859
724
|
}
|
|
860
725
|
async function executeNext() {
|
|
861
726
|
const atomId = await prompt("Enter atom ID to execute (or press Enter for next planned)");
|
|
862
727
|
if (atomId.trim()) {
|
|
863
|
-
const { execute: execute2 } = await import("./execute-
|
|
728
|
+
const { execute: execute2 } = await import("./execute-LYID2ODD.js");
|
|
864
729
|
await execute2(atomId.trim(), {});
|
|
865
730
|
} else {
|
|
866
|
-
console.log(
|
|
731
|
+
console.log(chalk4.yellow('No atom ID provided. Use "archon list" to see available atoms.'));
|
|
867
732
|
}
|
|
868
733
|
}
|
|
869
734
|
async function reportBug() {
|
|
@@ -877,21 +742,26 @@ async function viewStatus() {
|
|
|
877
742
|
const { status: status2 } = await import("./auth-2QIFQZTL.js");
|
|
878
743
|
await status2();
|
|
879
744
|
}
|
|
745
|
+
async function settingsMenu() {
|
|
746
|
+
const { interactiveSettings } = await import("./preferences-PL2ON5VY.js");
|
|
747
|
+
await interactiveSettings();
|
|
748
|
+
await start();
|
|
749
|
+
}
|
|
880
750
|
async function reviewCode() {
|
|
881
751
|
const cwd = process.cwd();
|
|
882
752
|
const reviewDbPath = join3(cwd, "docs", "code-review", "review-tasks.db");
|
|
883
753
|
if (!existsSync3(reviewDbPath)) {
|
|
884
|
-
console.log(
|
|
754
|
+
console.log(chalk4.dim("Code review not initialized. Starting setup...\n"));
|
|
885
755
|
const { reviewInit: reviewInit2 } = await import("./review-3R6QXAXQ.js");
|
|
886
756
|
await reviewInit2();
|
|
887
757
|
console.log();
|
|
888
758
|
}
|
|
889
|
-
console.log(
|
|
890
|
-
console.log(` ${
|
|
891
|
-
console.log(` ${
|
|
892
|
-
console.log(` ${
|
|
893
|
-
console.log(` ${
|
|
894
|
-
console.log(` ${
|
|
759
|
+
console.log(chalk4.bold("\nCode Review Options:\n"));
|
|
760
|
+
console.log(` ${chalk4.cyan("1")}) Analyze project`);
|
|
761
|
+
console.log(` ${chalk4.cyan("2")}) Show review status`);
|
|
762
|
+
console.log(` ${chalk4.cyan("3")}) Review next file`);
|
|
763
|
+
console.log(` ${chalk4.cyan("4")}) List all tasks`);
|
|
764
|
+
console.log(` ${chalk4.cyan("b")}) Back to main menu`);
|
|
895
765
|
console.log();
|
|
896
766
|
const choice = await prompt("Enter choice");
|
|
897
767
|
switch (choice.toLowerCase()) {
|
|
@@ -919,7 +789,7 @@ async function reviewCode() {
|
|
|
919
789
|
await start();
|
|
920
790
|
return;
|
|
921
791
|
default:
|
|
922
|
-
console.log(
|
|
792
|
+
console.log(chalk4.yellow("Invalid choice."));
|
|
923
793
|
}
|
|
924
794
|
await reviewCode();
|
|
925
795
|
}
|
|
@@ -929,7 +799,7 @@ function prompt(question) {
|
|
|
929
799
|
input: process.stdin,
|
|
930
800
|
output: process.stdout
|
|
931
801
|
});
|
|
932
|
-
rl.question(`${
|
|
802
|
+
rl.question(`${chalk4.cyan("?")} ${question}: `, (answer) => {
|
|
933
803
|
rl.close();
|
|
934
804
|
resolve(answer);
|
|
935
805
|
});
|
|
@@ -937,8 +807,8 @@ function prompt(question) {
|
|
|
937
807
|
}
|
|
938
808
|
|
|
939
809
|
// src/cli/credits.ts
|
|
940
|
-
import
|
|
941
|
-
import
|
|
810
|
+
import chalk5 from "chalk";
|
|
811
|
+
import ora2 from "ora";
|
|
942
812
|
import open from "open";
|
|
943
813
|
import { createClient } from "@supabase/supabase-js";
|
|
944
814
|
function getSupabaseClient(accessToken) {
|
|
@@ -947,7 +817,7 @@ function getSupabaseClient(accessToken) {
|
|
|
947
817
|
});
|
|
948
818
|
}
|
|
949
819
|
async function showCredits() {
|
|
950
|
-
const spinner =
|
|
820
|
+
const spinner = ora2("Fetching credit balance...").start();
|
|
951
821
|
try {
|
|
952
822
|
const config = await loadConfig();
|
|
953
823
|
if (!config.accessToken || !config.userId) {
|
|
@@ -963,21 +833,21 @@ async function showCredits() {
|
|
|
963
833
|
const profile = data;
|
|
964
834
|
spinner.stop();
|
|
965
835
|
console.log();
|
|
966
|
-
console.log(
|
|
836
|
+
console.log(chalk5.bold("\u{1F4B0} Credit Balance"));
|
|
967
837
|
console.log();
|
|
968
838
|
const balance = (profile.credit_balance_cents || 0) / 100;
|
|
969
839
|
console.log(` Tier: ${formatTier(profile.tier)}`);
|
|
970
|
-
console.log(` Balance: ${
|
|
840
|
+
console.log(` Balance: ${chalk5.green(`$${balance.toFixed(2)}`)}`);
|
|
971
841
|
if (profile.tier === "FREE") {
|
|
972
842
|
console.log(` Atoms: ${profile.atoms_used_this_month}/10,000 this month`);
|
|
973
843
|
console.log();
|
|
974
|
-
console.log(
|
|
844
|
+
console.log(chalk5.dim(" Upgrade to Credits tier: archon credits add"));
|
|
975
845
|
} else if (profile.tier === "CREDITS") {
|
|
976
846
|
console.log();
|
|
977
|
-
console.log(
|
|
847
|
+
console.log(chalk5.dim(" Add more credits: archon credits add"));
|
|
978
848
|
} else if (profile.tier === "BYOK") {
|
|
979
849
|
console.log();
|
|
980
|
-
console.log(
|
|
850
|
+
console.log(chalk5.dim(" Using your own API keys - no credit charges"));
|
|
981
851
|
}
|
|
982
852
|
console.log();
|
|
983
853
|
} catch (err) {
|
|
@@ -986,7 +856,7 @@ async function showCredits() {
|
|
|
986
856
|
}
|
|
987
857
|
}
|
|
988
858
|
async function addCredits(options = {}) {
|
|
989
|
-
const spinner =
|
|
859
|
+
const spinner = ora2("Preparing checkout...").start();
|
|
990
860
|
try {
|
|
991
861
|
const config = await loadConfig();
|
|
992
862
|
if (!config.accessToken || !config.userId) {
|
|
@@ -1023,18 +893,18 @@ async function addCredits(options = {}) {
|
|
|
1023
893
|
}
|
|
1024
894
|
spinner.succeed("Checkout ready");
|
|
1025
895
|
console.log();
|
|
1026
|
-
console.log(
|
|
896
|
+
console.log(chalk5.bold("\u{1F6D2} Add Credits"));
|
|
1027
897
|
console.log();
|
|
1028
|
-
console.log(` Amount: ${
|
|
898
|
+
console.log(` Amount: ${chalk5.green(`$${amountDollars.toFixed(2)}`)}`);
|
|
1029
899
|
console.log();
|
|
1030
900
|
console.log(" Opening checkout in browser...");
|
|
1031
901
|
console.log();
|
|
1032
|
-
console.log(
|
|
902
|
+
console.log(chalk5.dim(` Or visit: ${checkoutUrl}`));
|
|
1033
903
|
console.log();
|
|
1034
904
|
try {
|
|
1035
905
|
await open(checkoutUrl);
|
|
1036
906
|
} catch {
|
|
1037
|
-
console.log(
|
|
907
|
+
console.log(chalk5.yellow(" Could not open browser. Please visit the URL above."));
|
|
1038
908
|
}
|
|
1039
909
|
} catch (err) {
|
|
1040
910
|
spinner.fail("Error preparing checkout");
|
|
@@ -1042,7 +912,7 @@ async function addCredits(options = {}) {
|
|
|
1042
912
|
}
|
|
1043
913
|
}
|
|
1044
914
|
async function showHistory(options = {}) {
|
|
1045
|
-
const spinner =
|
|
915
|
+
const spinner = ora2("Fetching usage history...").start();
|
|
1046
916
|
try {
|
|
1047
917
|
const config = await loadConfig();
|
|
1048
918
|
if (!config.accessToken || !config.userId) {
|
|
@@ -1059,15 +929,15 @@ async function showHistory(options = {}) {
|
|
|
1059
929
|
const usage = data;
|
|
1060
930
|
spinner.stop();
|
|
1061
931
|
console.log();
|
|
1062
|
-
console.log(
|
|
932
|
+
console.log(chalk5.bold("\u{1F4CA} Usage History"));
|
|
1063
933
|
console.log();
|
|
1064
934
|
if (!usage || usage.length === 0) {
|
|
1065
|
-
console.log(
|
|
935
|
+
console.log(chalk5.dim(" No usage recorded yet."));
|
|
1066
936
|
console.log();
|
|
1067
937
|
return;
|
|
1068
938
|
}
|
|
1069
|
-
console.log(
|
|
1070
|
-
console.log(
|
|
939
|
+
console.log(chalk5.dim(" Model Tokens Cost Date"));
|
|
940
|
+
console.log(chalk5.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1071
941
|
for (const row of usage) {
|
|
1072
942
|
const model = row.model.padEnd(30).slice(0, 30);
|
|
1073
943
|
const tokens = (row.input_tokens + row.output_tokens).toString().padStart(8);
|
|
@@ -1077,9 +947,9 @@ async function showHistory(options = {}) {
|
|
|
1077
947
|
}
|
|
1078
948
|
const totalCost = usage.reduce((sum, r) => sum + r.base_cost, 0);
|
|
1079
949
|
const totalTokens = usage.reduce((sum, r) => sum + r.input_tokens + r.output_tokens, 0);
|
|
1080
|
-
console.log(
|
|
950
|
+
console.log(chalk5.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1081
951
|
console.log(
|
|
1082
|
-
` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${
|
|
952
|
+
` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${chalk5.green(`$${totalCost.toFixed(4)}`.padStart(10))}`
|
|
1083
953
|
);
|
|
1084
954
|
console.log();
|
|
1085
955
|
} catch (err) {
|
|
@@ -1088,7 +958,7 @@ async function showHistory(options = {}) {
|
|
|
1088
958
|
}
|
|
1089
959
|
}
|
|
1090
960
|
async function manageBudget(options = {}) {
|
|
1091
|
-
const spinner =
|
|
961
|
+
const spinner = ora2("Fetching budget settings...").start();
|
|
1092
962
|
try {
|
|
1093
963
|
const config = await loadConfig();
|
|
1094
964
|
if (!config.accessToken || !config.userId) {
|
|
@@ -1145,24 +1015,24 @@ async function manageBudget(options = {}) {
|
|
|
1145
1015
|
}
|
|
1146
1016
|
spinner.stop();
|
|
1147
1017
|
console.log();
|
|
1148
|
-
console.log(
|
|
1018
|
+
console.log(chalk5.bold("\u{1F4CA} Monthly Budget"));
|
|
1149
1019
|
console.log();
|
|
1150
1020
|
if (profile.monthly_budget_cents === null) {
|
|
1151
|
-
console.log(` Budget: ${
|
|
1021
|
+
console.log(` Budget: ${chalk5.dim("No limit set")}`);
|
|
1152
1022
|
} else {
|
|
1153
1023
|
const budget = profile.monthly_budget_cents / 100;
|
|
1154
1024
|
const spend = (profile.monthly_spend_cents || 0) / 100;
|
|
1155
1025
|
const remaining = budget - spend;
|
|
1156
1026
|
const percent = budget > 0 ? Math.round(spend / budget * 100) : 0;
|
|
1157
|
-
console.log(` Budget: ${
|
|
1027
|
+
console.log(` Budget: ${chalk5.green(`$${budget.toFixed(2)}`)} / month`);
|
|
1158
1028
|
console.log(` Spent: $${spend.toFixed(2)} (${percent}%)`);
|
|
1159
|
-
console.log(` Remaining: ${remaining >= 0 ?
|
|
1029
|
+
console.log(` Remaining: ${remaining >= 0 ? chalk5.green(`$${remaining.toFixed(2)}`) : chalk5.red(`-$${Math.abs(remaining).toFixed(2)}`)}`);
|
|
1160
1030
|
}
|
|
1161
1031
|
console.log(` Alert at: ${profile.budget_alert_threshold_percent}% of budget`);
|
|
1162
1032
|
console.log();
|
|
1163
|
-
console.log(
|
|
1164
|
-
console.log(
|
|
1165
|
-
console.log(
|
|
1033
|
+
console.log(chalk5.dim(" Set budget: archon credits budget --set 50"));
|
|
1034
|
+
console.log(chalk5.dim(" Clear budget: archon credits budget --clear"));
|
|
1035
|
+
console.log(chalk5.dim(" Set alert: archon credits budget --alert 80"));
|
|
1166
1036
|
console.log();
|
|
1167
1037
|
} catch (err) {
|
|
1168
1038
|
spinner.fail("Error managing budget");
|
|
@@ -1170,7 +1040,7 @@ async function manageBudget(options = {}) {
|
|
|
1170
1040
|
}
|
|
1171
1041
|
}
|
|
1172
1042
|
async function manageAutoRecharge(options = {}) {
|
|
1173
|
-
const spinner =
|
|
1043
|
+
const spinner = ora2("Fetching auto-recharge settings...").start();
|
|
1174
1044
|
try {
|
|
1175
1045
|
const config = await loadConfig();
|
|
1176
1046
|
if (!config.accessToken || !config.userId) {
|
|
@@ -1224,12 +1094,12 @@ async function manageAutoRecharge(options = {}) {
|
|
|
1224
1094
|
}
|
|
1225
1095
|
spinner.stop();
|
|
1226
1096
|
console.log();
|
|
1227
|
-
console.log(
|
|
1097
|
+
console.log(chalk5.bold("\u{1F504} Auto-Recharge"));
|
|
1228
1098
|
console.log();
|
|
1229
1099
|
if (!profile.auto_recharge_enabled) {
|
|
1230
|
-
console.log(` Status: ${
|
|
1100
|
+
console.log(` Status: ${chalk5.dim("Disabled")}`);
|
|
1231
1101
|
} else {
|
|
1232
|
-
console.log(` Status: ${
|
|
1102
|
+
console.log(` Status: ${chalk5.green("Enabled")}`);
|
|
1233
1103
|
if (profile.auto_recharge_threshold_cents !== null) {
|
|
1234
1104
|
console.log(` When: Balance drops below $${(profile.auto_recharge_threshold_cents / 100).toFixed(2)}`);
|
|
1235
1105
|
}
|
|
@@ -1237,10 +1107,10 @@ async function manageAutoRecharge(options = {}) {
|
|
|
1237
1107
|
console.log(` Amount: $${(profile.auto_recharge_amount_cents / 100).toFixed(2)}`);
|
|
1238
1108
|
}
|
|
1239
1109
|
}
|
|
1240
|
-
console.log(` Payment: ${profile.stripe_payment_method_id ?
|
|
1110
|
+
console.log(` Payment: ${profile.stripe_payment_method_id ? chalk5.green("Card saved") : chalk5.dim("No card saved")}`);
|
|
1241
1111
|
console.log();
|
|
1242
|
-
console.log(
|
|
1243
|
-
console.log(
|
|
1112
|
+
console.log(chalk5.dim(" Enable: archon credits auto-recharge --enable --threshold 5 --amount 20"));
|
|
1113
|
+
console.log(chalk5.dim(" Disable: archon credits auto-recharge --disable"));
|
|
1244
1114
|
console.log();
|
|
1245
1115
|
} catch (err) {
|
|
1246
1116
|
spinner.fail("Error managing auto-recharge");
|
|
@@ -1250,11 +1120,11 @@ async function manageAutoRecharge(options = {}) {
|
|
|
1250
1120
|
function formatTier(tier) {
|
|
1251
1121
|
switch (tier) {
|
|
1252
1122
|
case "FREE":
|
|
1253
|
-
return
|
|
1123
|
+
return chalk5.blue("Free (10k atoms/month)");
|
|
1254
1124
|
case "CREDITS":
|
|
1255
|
-
return
|
|
1125
|
+
return chalk5.green("Credits (Pay-as-you-go)");
|
|
1256
1126
|
case "BYOK":
|
|
1257
|
-
return
|
|
1127
|
+
return chalk5.magenta("BYOK (Bring Your Own Key)");
|
|
1258
1128
|
default:
|
|
1259
1129
|
return tier;
|
|
1260
1130
|
}
|
|
@@ -1529,375 +1399,12 @@ async function watch() {
|
|
|
1529
1399
|
await waitUntilExit();
|
|
1530
1400
|
}
|
|
1531
1401
|
|
|
1532
|
-
// src/cli/preferences.ts
|
|
1533
|
-
import chalk7 from "chalk";
|
|
1534
|
-
import ora4 from "ora";
|
|
1535
|
-
|
|
1536
|
-
// src/core/models/registry.json
|
|
1537
|
-
var registry_default = {
|
|
1538
|
-
lastUpdated: "2026-01-21T00:00:00Z",
|
|
1539
|
-
version: "1.0.0",
|
|
1540
|
-
providers: {
|
|
1541
|
-
anthropic: {
|
|
1542
|
-
displayName: "Anthropic",
|
|
1543
|
-
fast: [
|
|
1544
|
-
{
|
|
1545
|
-
id: "claude-3-haiku-20240307",
|
|
1546
|
-
name: "Claude 3 Haiku",
|
|
1547
|
-
active: true,
|
|
1548
|
-
costPer1kInput: 25e-5,
|
|
1549
|
-
costPer1kOutput: 125e-5
|
|
1550
|
-
}
|
|
1551
|
-
],
|
|
1552
|
-
thinking: [
|
|
1553
|
-
{
|
|
1554
|
-
id: "claude-3-5-sonnet-20241022",
|
|
1555
|
-
name: "Claude 3.5 Sonnet",
|
|
1556
|
-
active: true,
|
|
1557
|
-
default: true,
|
|
1558
|
-
costPer1kInput: 3e-3,
|
|
1559
|
-
costPer1kOutput: 0.015
|
|
1560
|
-
},
|
|
1561
|
-
{
|
|
1562
|
-
id: "claude-3-opus-20240229",
|
|
1563
|
-
name: "Claude 3 Opus",
|
|
1564
|
-
active: true,
|
|
1565
|
-
costPer1kInput: 0.015,
|
|
1566
|
-
costPer1kOutput: 0.075
|
|
1567
|
-
}
|
|
1568
|
-
]
|
|
1569
|
-
},
|
|
1570
|
-
openai: {
|
|
1571
|
-
displayName: "OpenAI",
|
|
1572
|
-
fast: [
|
|
1573
|
-
{
|
|
1574
|
-
id: "gpt-4o-mini",
|
|
1575
|
-
name: "GPT-4o Mini",
|
|
1576
|
-
active: true,
|
|
1577
|
-
costPer1kInput: 15e-5,
|
|
1578
|
-
costPer1kOutput: 6e-4
|
|
1579
|
-
}
|
|
1580
|
-
],
|
|
1581
|
-
thinking: [
|
|
1582
|
-
{
|
|
1583
|
-
id: "gpt-4o",
|
|
1584
|
-
name: "GPT-4o",
|
|
1585
|
-
active: true,
|
|
1586
|
-
default: true,
|
|
1587
|
-
costPer1kInput: 5e-3,
|
|
1588
|
-
costPer1kOutput: 0.015
|
|
1589
|
-
},
|
|
1590
|
-
{
|
|
1591
|
-
id: "o1-preview",
|
|
1592
|
-
name: "o1 Preview",
|
|
1593
|
-
active: true,
|
|
1594
|
-
costPer1kInput: 0.015,
|
|
1595
|
-
costPer1kOutput: 0.06
|
|
1596
|
-
},
|
|
1597
|
-
{
|
|
1598
|
-
id: "o1-mini",
|
|
1599
|
-
name: "o1 Mini",
|
|
1600
|
-
active: true,
|
|
1601
|
-
costPer1kInput: 3e-3,
|
|
1602
|
-
costPer1kOutput: 0.012
|
|
1603
|
-
}
|
|
1604
|
-
]
|
|
1605
|
-
},
|
|
1606
|
-
google: {
|
|
1607
|
-
displayName: "Google",
|
|
1608
|
-
fast: [
|
|
1609
|
-
{
|
|
1610
|
-
id: "gemini-1.5-flash",
|
|
1611
|
-
name: "Gemini 1.5 Flash",
|
|
1612
|
-
active: true,
|
|
1613
|
-
costPer1kInput: 75e-6,
|
|
1614
|
-
costPer1kOutput: 3e-4
|
|
1615
|
-
}
|
|
1616
|
-
],
|
|
1617
|
-
thinking: [
|
|
1618
|
-
{
|
|
1619
|
-
id: "gemini-1.5-pro",
|
|
1620
|
-
name: "Gemini 1.5 Pro",
|
|
1621
|
-
active: true,
|
|
1622
|
-
default: true,
|
|
1623
|
-
costPer1kInput: 125e-5,
|
|
1624
|
-
costPer1kOutput: 5e-3
|
|
1625
|
-
},
|
|
1626
|
-
{
|
|
1627
|
-
id: "gemini-2.0-flash-thinking-exp",
|
|
1628
|
-
name: "Gemini 2.0 Flash Thinking",
|
|
1629
|
-
active: true,
|
|
1630
|
-
costPer1kInput: 0,
|
|
1631
|
-
costPer1kOutput: 0
|
|
1632
|
-
}
|
|
1633
|
-
]
|
|
1634
|
-
}
|
|
1635
|
-
},
|
|
1636
|
-
defaults: {
|
|
1637
|
-
fast: "claude-3-haiku-20240307",
|
|
1638
|
-
thinking: "claude-3-5-sonnet-20241022",
|
|
1639
|
-
primaryAdversarial: "claude-3-5-sonnet-20241022",
|
|
1640
|
-
secondaryAdversarial: "gpt-4o"
|
|
1641
|
-
},
|
|
1642
|
-
freeModels: [
|
|
1643
|
-
"claude-3-haiku-20240307",
|
|
1644
|
-
"gpt-4o-mini",
|
|
1645
|
-
"gemini-1.5-flash"
|
|
1646
|
-
]
|
|
1647
|
-
};
|
|
1648
|
-
|
|
1649
|
-
// src/core/models/index.ts
|
|
1650
|
-
var registry = registry_default;
|
|
1651
|
-
function getAllActiveModels() {
|
|
1652
|
-
const models = [];
|
|
1653
|
-
for (const [provider, data] of Object.entries(registry.providers)) {
|
|
1654
|
-
for (const model of data.fast.filter((m) => m.active)) {
|
|
1655
|
-
models.push({
|
|
1656
|
-
provider,
|
|
1657
|
-
modelId: model.id,
|
|
1658
|
-
modelName: model.name,
|
|
1659
|
-
category: "fast"
|
|
1660
|
-
});
|
|
1661
|
-
}
|
|
1662
|
-
for (const model of data.thinking.filter((m) => m.active)) {
|
|
1663
|
-
models.push({
|
|
1664
|
-
provider,
|
|
1665
|
-
modelId: model.id,
|
|
1666
|
-
modelName: model.name,
|
|
1667
|
-
category: "thinking"
|
|
1668
|
-
});
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
return models;
|
|
1672
|
-
}
|
|
1673
|
-
function getDefaultModel(category) {
|
|
1674
|
-
return registry.defaults[category];
|
|
1675
|
-
}
|
|
1676
|
-
function getDefaultAdversarialModels() {
|
|
1677
|
-
return {
|
|
1678
|
-
primary: registry.defaults.primaryAdversarial,
|
|
1679
|
-
secondary: registry.defaults.secondaryAdversarial
|
|
1680
|
-
};
|
|
1681
|
-
}
|
|
1682
|
-
function findModel(modelId) {
|
|
1683
|
-
for (const [provider, data] of Object.entries(registry.providers)) {
|
|
1684
|
-
for (const model of data.fast) {
|
|
1685
|
-
if (model.id === modelId) {
|
|
1686
|
-
return { ...model, provider, category: "fast" };
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
for (const model of data.thinking) {
|
|
1690
|
-
if (model.id === modelId) {
|
|
1691
|
-
return { ...model, provider, category: "thinking" };
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
return null;
|
|
1696
|
-
}
|
|
1697
|
-
function getModelProvider(modelId) {
|
|
1698
|
-
const model = findModel(modelId);
|
|
1699
|
-
return model?.provider ?? null;
|
|
1700
|
-
}
|
|
1701
|
-
function isValidModel(modelId) {
|
|
1702
|
-
const model = findModel(modelId);
|
|
1703
|
-
return model !== null && model.active;
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
// src/cli/preferences.ts
|
|
1707
|
-
var PREF_KEYS = ["fast-model", "thinking-model", "primary-adversarial", "secondary-adversarial"];
|
|
1708
|
-
function prefKeyToDbColumn(key) {
|
|
1709
|
-
const map = {
|
|
1710
|
-
"fast-model": "pref_fast_model",
|
|
1711
|
-
"thinking-model": "pref_thinking_model",
|
|
1712
|
-
"primary-adversarial": "pref_primary_adversarial",
|
|
1713
|
-
"secondary-adversarial": "pref_secondary_adversarial"
|
|
1714
|
-
};
|
|
1715
|
-
return map[key];
|
|
1716
|
-
}
|
|
1717
|
-
function isPrefKey(key) {
|
|
1718
|
-
return PREF_KEYS.includes(key);
|
|
1719
|
-
}
|
|
1720
|
-
async function fetchPreferences() {
|
|
1721
|
-
const config = await loadConfig();
|
|
1722
|
-
const authToken = getAuthToken(config);
|
|
1723
|
-
if (!authToken) {
|
|
1724
|
-
return null;
|
|
1725
|
-
}
|
|
1726
|
-
const apiUrl = getApiUrl(config);
|
|
1727
|
-
try {
|
|
1728
|
-
const response = await fetch(`${apiUrl}/api/preferences`, {
|
|
1729
|
-
headers: {
|
|
1730
|
-
"Authorization": `Bearer ${authToken}`
|
|
1731
|
-
}
|
|
1732
|
-
});
|
|
1733
|
-
if (!response.ok) {
|
|
1734
|
-
return null;
|
|
1735
|
-
}
|
|
1736
|
-
const data = await response.json();
|
|
1737
|
-
return {
|
|
1738
|
-
fastModel: data.pref_fast_model,
|
|
1739
|
-
thinkingModel: data.pref_thinking_model,
|
|
1740
|
-
primaryAdversarial: data.pref_primary_adversarial,
|
|
1741
|
-
secondaryAdversarial: data.pref_secondary_adversarial
|
|
1742
|
-
};
|
|
1743
|
-
} catch {
|
|
1744
|
-
return null;
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
async function updatePreference(key, value) {
|
|
1748
|
-
const config = await loadConfig();
|
|
1749
|
-
const authToken = getAuthToken(config);
|
|
1750
|
-
if (!authToken) {
|
|
1751
|
-
return { success: false, error: "Not logged in. Run: archon login" };
|
|
1752
|
-
}
|
|
1753
|
-
const apiUrl = getApiUrl(config);
|
|
1754
|
-
const column = prefKeyToDbColumn(key);
|
|
1755
|
-
try {
|
|
1756
|
-
const response = await fetch(`${apiUrl}/api/preferences`, {
|
|
1757
|
-
method: "PATCH",
|
|
1758
|
-
headers: {
|
|
1759
|
-
"Authorization": `Bearer ${authToken}`,
|
|
1760
|
-
"Content-Type": "application/json"
|
|
1761
|
-
},
|
|
1762
|
-
body: JSON.stringify({ [column]: value })
|
|
1763
|
-
});
|
|
1764
|
-
if (!response.ok) {
|
|
1765
|
-
const text = await response.text();
|
|
1766
|
-
return { success: false, error: text };
|
|
1767
|
-
}
|
|
1768
|
-
return { success: true };
|
|
1769
|
-
} catch (err) {
|
|
1770
|
-
const message = err instanceof Error ? err.message : "Unknown error";
|
|
1771
|
-
return { success: false, error: message };
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
async function getUserProviders() {
|
|
1775
|
-
return keyManager.listProviders();
|
|
1776
|
-
}
|
|
1777
|
-
function formatModelDisplay(modelId, defaultId) {
|
|
1778
|
-
if (!modelId) {
|
|
1779
|
-
const model2 = findModel(defaultId);
|
|
1780
|
-
return chalk7.dim(`${model2?.name ?? defaultId} (default)`);
|
|
1781
|
-
}
|
|
1782
|
-
const model = findModel(modelId);
|
|
1783
|
-
return model?.name ?? modelId;
|
|
1784
|
-
}
|
|
1785
|
-
async function showPreferences() {
|
|
1786
|
-
const spinner = ora4("Loading preferences...").start();
|
|
1787
|
-
const prefs = await fetchPreferences();
|
|
1788
|
-
const defaults = getDefaultAdversarialModels();
|
|
1789
|
-
spinner.stop();
|
|
1790
|
-
if (!prefs) {
|
|
1791
|
-
console.log(chalk7.yellow("Not logged in or unable to fetch preferences."));
|
|
1792
|
-
console.log(chalk7.dim("Using system defaults:"));
|
|
1793
|
-
console.log();
|
|
1794
|
-
console.log(` ${chalk7.blue("Fast Model:")} ${formatModelDisplay(null, getDefaultModel("fast"))}`);
|
|
1795
|
-
console.log(` ${chalk7.blue("Thinking Model:")} ${formatModelDisplay(null, getDefaultModel("thinking"))}`);
|
|
1796
|
-
console.log(` ${chalk7.blue("Primary Adversarial:")} ${formatModelDisplay(null, defaults.primary)}`);
|
|
1797
|
-
console.log(` ${chalk7.blue("Secondary Adversarial:")} ${formatModelDisplay(null, defaults.secondary)}`);
|
|
1798
|
-
return;
|
|
1799
|
-
}
|
|
1800
|
-
console.log(chalk7.green("Model Preferences:"));
|
|
1801
|
-
console.log();
|
|
1802
|
-
console.log(` ${chalk7.blue("Fast Model:")} ${formatModelDisplay(prefs.fastModel, getDefaultModel("fast"))}`);
|
|
1803
|
-
console.log(` ${chalk7.blue("Thinking Model:")} ${formatModelDisplay(prefs.thinkingModel, getDefaultModel("thinking"))}`);
|
|
1804
|
-
console.log(` ${chalk7.blue("Primary Adversarial:")} ${formatModelDisplay(prefs.primaryAdversarial, defaults.primary)}`);
|
|
1805
|
-
console.log(` ${chalk7.blue("Secondary Adversarial:")} ${formatModelDisplay(prefs.secondaryAdversarial, defaults.secondary)}`);
|
|
1806
|
-
console.log();
|
|
1807
|
-
const providers = await getUserProviders();
|
|
1808
|
-
if (providers.length > 0) {
|
|
1809
|
-
console.log(chalk7.dim(`Available providers: ${providers.join(", ")}`));
|
|
1810
|
-
} else {
|
|
1811
|
-
console.log(chalk7.dim("No API keys configured. Run: archon keys add <provider>"));
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
async function setPreference(key, modelId) {
|
|
1815
|
-
if (!isPrefKey(key)) {
|
|
1816
|
-
console.error(chalk7.red(`Invalid preference key: ${key}`));
|
|
1817
|
-
console.log(chalk7.dim(`Valid keys: ${PREF_KEYS.join(", ")}`));
|
|
1818
|
-
process.exit(1);
|
|
1819
|
-
}
|
|
1820
|
-
if (!isValidModel(modelId)) {
|
|
1821
|
-
console.error(chalk7.red(`Invalid or inactive model: ${modelId}`));
|
|
1822
|
-
console.log(chalk7.dim("Run: archon models to see available models"));
|
|
1823
|
-
process.exit(1);
|
|
1824
|
-
}
|
|
1825
|
-
const model = findModel(modelId);
|
|
1826
|
-
if (!model) {
|
|
1827
|
-
console.error(chalk7.red(`Model not found: ${modelId}`));
|
|
1828
|
-
process.exit(1);
|
|
1829
|
-
}
|
|
1830
|
-
const providers = await getUserProviders();
|
|
1831
|
-
const modelProvider = getModelProvider(modelId);
|
|
1832
|
-
if (modelProvider && !providers.includes(modelProvider)) {
|
|
1833
|
-
console.error(chalk7.red(`You don't have an API key for ${modelProvider}`));
|
|
1834
|
-
console.log(chalk7.dim(`Add one with: archon keys add ${modelProvider}`));
|
|
1835
|
-
process.exit(1);
|
|
1836
|
-
}
|
|
1837
|
-
if (key === "fast-model" && model.category !== "fast") {
|
|
1838
|
-
console.log(chalk7.yellow(`Note: ${model.name} is a ${model.category} model, typically used for complex tasks.`));
|
|
1839
|
-
}
|
|
1840
|
-
if (key === "thinking-model" && model.category !== "thinking") {
|
|
1841
|
-
console.log(chalk7.yellow(`Note: ${model.name} is a ${model.category} model, typically used for quick tasks.`));
|
|
1842
|
-
}
|
|
1843
|
-
const spinner = ora4(`Setting ${key} to ${model.name}...`).start();
|
|
1844
|
-
const result = await updatePreference(key, modelId);
|
|
1845
|
-
if (!result.success) {
|
|
1846
|
-
spinner.fail(chalk7.red(result.error ?? "Failed to update preference"));
|
|
1847
|
-
process.exit(1);
|
|
1848
|
-
}
|
|
1849
|
-
spinner.succeed(chalk7.green(`${key} set to ${model.name}`));
|
|
1850
|
-
}
|
|
1851
|
-
async function resetPreferences() {
|
|
1852
|
-
const spinner = ora4("Resetting preferences to defaults...").start();
|
|
1853
|
-
const results = await Promise.all([
|
|
1854
|
-
updatePreference("fast-model", null),
|
|
1855
|
-
updatePreference("thinking-model", null),
|
|
1856
|
-
updatePreference("primary-adversarial", null),
|
|
1857
|
-
updatePreference("secondary-adversarial", null)
|
|
1858
|
-
]);
|
|
1859
|
-
const failed = results.filter((r) => !r.success);
|
|
1860
|
-
if (failed.length > 0) {
|
|
1861
|
-
spinner.fail(chalk7.red("Failed to reset some preferences"));
|
|
1862
|
-
process.exit(1);
|
|
1863
|
-
}
|
|
1864
|
-
spinner.succeed(chalk7.green("Preferences reset to system defaults"));
|
|
1865
|
-
}
|
|
1866
|
-
async function listModels() {
|
|
1867
|
-
const models = getAllActiveModels();
|
|
1868
|
-
const providers = await getUserProviders();
|
|
1869
|
-
console.log(chalk7.green("Available Models:"));
|
|
1870
|
-
console.log();
|
|
1871
|
-
const byProvider = {};
|
|
1872
|
-
for (const model of models) {
|
|
1873
|
-
const key = model.provider;
|
|
1874
|
-
if (!byProvider[key]) {
|
|
1875
|
-
byProvider[key] = [];
|
|
1876
|
-
}
|
|
1877
|
-
byProvider[key].push(model);
|
|
1878
|
-
}
|
|
1879
|
-
for (const [provider, providerModels] of Object.entries(byProvider)) {
|
|
1880
|
-
const hasKey = providers.includes(provider);
|
|
1881
|
-
const status2 = hasKey ? chalk7.green("\u2713") : chalk7.dim("\u25CB");
|
|
1882
|
-
console.log(`${status2} ${chalk7.blue(provider.toUpperCase())}`);
|
|
1883
|
-
for (const model of providerModels ?? []) {
|
|
1884
|
-
const categoryLabel = model.category === "fast" ? chalk7.cyan("[fast]") : chalk7.magenta("[thinking]");
|
|
1885
|
-
console.log(` ${model.modelId} ${categoryLabel}`);
|
|
1886
|
-
console.log(chalk7.dim(` ${model.modelName}`));
|
|
1887
|
-
}
|
|
1888
|
-
console.log();
|
|
1889
|
-
}
|
|
1890
|
-
if (providers.length === 0) {
|
|
1891
|
-
console.log(chalk7.dim("Add API keys to use models: archon keys add <provider>"));
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1895
1402
|
// src/cli/index.ts
|
|
1896
1403
|
var program = new Command();
|
|
1897
1404
|
program.name("archon").description("Local-first AI-powered development governance").version("1.1.0").action(async () => {
|
|
1898
1405
|
const cwd = process.cwd();
|
|
1899
1406
|
if (!isInitialized(cwd)) {
|
|
1900
|
-
console.log(
|
|
1407
|
+
console.log(chalk6.blue("\nArchonDev is not initialized in this folder.\n"));
|
|
1901
1408
|
await init({ analyze: true, git: true });
|
|
1902
1409
|
}
|
|
1903
1410
|
await start();
|
|
@@ -1905,7 +1412,7 @@ program.name("archon").description("Local-first AI-powered development governanc
|
|
|
1905
1412
|
program.command("login").description("Authenticate with ArchonDev").option("-p, --provider <provider>", "OAuth provider (github or google)", "github").action(async (options) => {
|
|
1906
1413
|
const provider = options.provider;
|
|
1907
1414
|
if (provider !== "github" && provider !== "google") {
|
|
1908
|
-
console.error(
|
|
1415
|
+
console.error(chalk6.red('Invalid provider. Use "github" or "google"'));
|
|
1909
1416
|
process.exit(1);
|
|
1910
1417
|
}
|
|
1911
1418
|
await login(provider);
|