@agi_inc/cli 0.5.9 → 0.5.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.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/index.tsx
2
2
  import React10 from "react";
3
3
  import { render } from "ink";
4
- import { isBinaryAvailable } from "@agi_inc/agi-js";
4
+ import { isBinaryAvailable as isBinaryAvailable2 } from "@agi_inc/agi-js";
5
5
 
6
6
  // src/cli.ts
7
7
  import yargs from "yargs";
@@ -288,7 +288,7 @@ async function parseArgs() {
288
288
  }
289
289
 
290
290
  // src/app/App.tsx
291
- import React9, { useEffect as useEffect5, useState as useState7, useCallback as useCallback3, useMemo as useMemo2 } from "react";
291
+ import React9, { useEffect as useEffect5, useState as useState7, useCallback as useCallback3, useMemo as useMemo2, useRef as useRef3 } from "react";
292
292
  import { Box as Box8, Text as Text9, useApp } from "ink";
293
293
 
294
294
  // src/hooks/useAgent.ts
@@ -674,8 +674,447 @@ import { Text as Text6, Box as Box5, useInput as useInput4 } from "ink";
674
674
  import TextInput2 from "ink-text-input";
675
675
 
676
676
  // src/commands/slash.ts
677
- import { readFileSync as readFileSync2 } from "fs";
678
- import { basename } from "path";
677
+ import { readFileSync as readFileSync3 } from "fs";
678
+ import { basename as basename2 } from "path";
679
+ import os5 from "os";
680
+ import { isBinaryAvailable } from "@agi_inc/agi-js";
681
+
682
+ // src/history.ts
683
+ import fs2 from "fs";
684
+ import path2 from "path";
685
+ import os2 from "os";
686
+ var HISTORY_DIR = path2.join(os2.homedir(), ".agi");
687
+ var HISTORY_FILE = path2.join(HISTORY_DIR, "history.json");
688
+ var MAX_ENTRIES = 200;
689
+ function ensureDir() {
690
+ if (!fs2.existsSync(HISTORY_DIR)) {
691
+ fs2.mkdirSync(HISTORY_DIR, { recursive: true, mode: 448 });
692
+ }
693
+ }
694
+ function loadHistory() {
695
+ try {
696
+ const raw = fs2.readFileSync(HISTORY_FILE, "utf-8");
697
+ const data = JSON.parse(raw);
698
+ if (Array.isArray(data)) return data;
699
+ } catch {
700
+ }
701
+ return [];
702
+ }
703
+ function appendHistory(entry) {
704
+ ensureDir();
705
+ const history = loadHistory();
706
+ history.push(entry);
707
+ const trimmed = history.slice(-MAX_ENTRIES);
708
+ fs2.writeFileSync(HISTORY_FILE, JSON.stringify(trimmed, null, 2) + "\n", {
709
+ mode: 384
710
+ });
711
+ }
712
+ function clearHistory() {
713
+ try {
714
+ fs2.unlinkSync(HISTORY_FILE);
715
+ } catch {
716
+ }
717
+ }
718
+ function formatHistory(entries, limit = 20) {
719
+ if (entries.length === 0) return " No history yet.";
720
+ const recent = entries.slice(-limit).reverse();
721
+ const lines = ["", " Recent sessions:", ""];
722
+ for (const entry of recent) {
723
+ const date = new Date(entry.timestamp);
724
+ const timeStr = date.toLocaleDateString("en-US", {
725
+ month: "short",
726
+ day: "numeric"
727
+ }) + " " + date.toLocaleTimeString("en-US", {
728
+ hour: "2-digit",
729
+ minute: "2-digit",
730
+ hour12: false
731
+ });
732
+ const status = entry.success === true ? "\u25CF" : entry.success === false ? "\u2715" : "\u25CB";
733
+ const duration = entry.durationMs ? ` (${Math.round(entry.durationMs / 1e3)}s)` : "";
734
+ const goal = entry.goal.length > 55 ? entry.goal.slice(0, 55) + "\u2026" : entry.goal;
735
+ lines.push(` ${status} ${timeStr} ${goal}${duration}`);
736
+ }
737
+ lines.push("");
738
+ if (entries.length > limit) {
739
+ lines.push(` Showing ${limit} of ${entries.length} entries`);
740
+ lines.push("");
741
+ }
742
+ return lines.join("\n");
743
+ }
744
+
745
+ // src/project.ts
746
+ import { readFileSync as readFileSync2, existsSync, readdirSync } from "fs";
747
+ import { join as join2, basename } from "path";
748
+
749
+ // src/skills.ts
750
+ import fs3 from "fs";
751
+ import path3 from "path";
752
+ import os3 from "os";
753
+ function parseFrontmatter(content) {
754
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
755
+ if (!match) return { meta: {}, body: content.trim() };
756
+ const meta = {};
757
+ for (const line of match[1].split("\n")) {
758
+ const colonIdx = line.indexOf(":");
759
+ if (colonIdx > 0) {
760
+ const key = line.slice(0, colonIdx).trim();
761
+ const value = line.slice(colonIdx + 1).trim();
762
+ meta[key] = value;
763
+ }
764
+ }
765
+ return { meta, body: match[2].trim() };
766
+ }
767
+ var NAME_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
768
+ function isValidSkillName(name) {
769
+ if (name.length > 64) return false;
770
+ if (!NAME_RE.test(name)) return false;
771
+ if (name.includes("--")) return false;
772
+ return true;
773
+ }
774
+ function discoverSkillsInDir(skillsDir, scope) {
775
+ const skills = [];
776
+ if (!fs3.existsSync(skillsDir)) return skills;
777
+ let entries;
778
+ try {
779
+ entries = fs3.readdirSync(skillsDir);
780
+ } catch {
781
+ return skills;
782
+ }
783
+ for (const entry of entries) {
784
+ const skillDir = path3.join(skillsDir, entry);
785
+ const skillFile = path3.join(skillDir, "SKILL.md");
786
+ try {
787
+ if (!fs3.statSync(skillDir).isDirectory()) continue;
788
+ if (!fs3.existsSync(skillFile)) continue;
789
+ } catch {
790
+ continue;
791
+ }
792
+ if (!isValidSkillName(entry)) continue;
793
+ try {
794
+ const content = fs3.readFileSync(skillFile, "utf-8");
795
+ const { meta } = parseFrontmatter(content);
796
+ const name = meta["name"] || entry;
797
+ if (name !== entry) continue;
798
+ const description = meta["description"] || "";
799
+ if (!description) continue;
800
+ skills.push({
801
+ name,
802
+ description,
803
+ path: skillFile,
804
+ root: skillDir,
805
+ scope,
806
+ license: meta["license"],
807
+ compatibility: meta["compatibility"],
808
+ userInvocable: meta["user-invocable"] !== "false",
809
+ argumentHint: meta["argument-hint"],
810
+ metadata: Object.keys(meta).length > 0 ? meta : void 0
811
+ });
812
+ } catch {
813
+ }
814
+ }
815
+ return skills;
816
+ }
817
+ function discoverSkills(cwd = process.cwd()) {
818
+ const personalDir = path3.join(os3.homedir(), ".agi", "skills");
819
+ const projectDir = path3.join(cwd, ".agi", "skills");
820
+ const personal = discoverSkillsInDir(personalDir, "personal");
821
+ const project = discoverSkillsInDir(projectDir, "project");
822
+ const byName = /* @__PURE__ */ new Map();
823
+ for (const skill of personal) byName.set(skill.name, skill);
824
+ for (const skill of project) byName.set(skill.name, skill);
825
+ return Array.from(byName.values());
826
+ }
827
+ function loadSkill(skill) {
828
+ const content = fs3.readFileSync(skill.path, "utf-8");
829
+ const { body } = parseFrontmatter(content);
830
+ return { ...skill, body };
831
+ }
832
+ function generateSkillsPrompt(skills) {
833
+ if (skills.length === 0) return "";
834
+ const lines = ["<available_skills>"];
835
+ for (const skill of skills) {
836
+ lines.push(" <skill>");
837
+ lines.push(` <name>${skill.name}</name>`);
838
+ lines.push(` <description>${skill.description}</description>`);
839
+ lines.push(` <location>${skill.path}</location>`);
840
+ lines.push(" </skill>");
841
+ }
842
+ lines.push("</available_skills>");
843
+ return lines.join("\n");
844
+ }
845
+ function formatSkillsList(skills) {
846
+ if (skills.length === 0) return " No skills found.";
847
+ const lines = ["", " Available skills:", ""];
848
+ for (const skill of skills) {
849
+ const scope = skill.scope === "personal" ? "~" : ".";
850
+ const hint = skill.argumentHint ? ` ${skill.argumentHint}` : "";
851
+ lines.push(` ${scope} /${skill.name}${hint}`);
852
+ lines.push(` ${skill.description}`);
853
+ }
854
+ lines.push("");
855
+ return lines.join("\n");
856
+ }
857
+
858
+ // src/project.ts
859
+ import { mkdirSync, writeFileSync } from "fs";
860
+ var INSTRUCTION_FILES = ["AGI.md", ".agi/AGI.md", ".agi/instructions.md"];
861
+ function loadRules(cwd) {
862
+ const rulesDir = join2(cwd, ".agi", "rules");
863
+ if (!existsSync(rulesDir)) return [];
864
+ const rules = [];
865
+ try {
866
+ const files = readdirSync(rulesDir).filter((f) => f.endsWith(".md")).sort();
867
+ for (const file of files) {
868
+ const filePath = join2(rulesDir, file);
869
+ try {
870
+ const raw = readFileSync2(filePath, "utf-8");
871
+ const name = basename(file, ".md");
872
+ let content = raw.trim();
873
+ let paths;
874
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
875
+ if (fmMatch) {
876
+ const meta = fmMatch[1];
877
+ content = fmMatch[2].trim();
878
+ const pathsMatch = meta.match(/^paths:\s*(.+)$/m);
879
+ if (pathsMatch) {
880
+ paths = pathsMatch[1].split(",").map((p) => p.trim()).filter(Boolean);
881
+ }
882
+ }
883
+ if (content) {
884
+ rules.push({ name, path: filePath, content, paths });
885
+ }
886
+ } catch {
887
+ }
888
+ }
889
+ } catch {
890
+ }
891
+ return rules;
892
+ }
893
+ function loadProjectConfig(cwd = process.cwd()) {
894
+ let instructions = null;
895
+ let instructionsPath = null;
896
+ for (const relPath of INSTRUCTION_FILES) {
897
+ const fullPath = join2(cwd, relPath);
898
+ if (existsSync(fullPath)) {
899
+ try {
900
+ instructions = readFileSync2(fullPath, "utf-8").trim();
901
+ instructionsPath = fullPath;
902
+ break;
903
+ } catch {
904
+ }
905
+ }
906
+ }
907
+ const agiDir = join2(cwd, ".agi");
908
+ const agiDirExists = existsSync(agiDir);
909
+ const commandFiles = [];
910
+ const commandsDir = join2(cwd, ".agi", "commands");
911
+ if (existsSync(commandsDir)) {
912
+ try {
913
+ const files = readdirSync(commandsDir);
914
+ for (const file of files) {
915
+ if (file.endsWith(".md")) {
916
+ commandFiles.push(join2(commandsDir, file));
917
+ }
918
+ }
919
+ } catch {
920
+ }
921
+ }
922
+ const rules = loadRules(cwd);
923
+ const skills = discoverSkills(cwd);
924
+ return {
925
+ instructions,
926
+ instructionsPath,
927
+ agiDir: agiDirExists ? agiDir : null,
928
+ commandFiles,
929
+ rules,
930
+ skills
931
+ };
932
+ }
933
+ function withProjectInstructions(goal, config) {
934
+ const sections = [];
935
+ if (config.instructions) {
936
+ sections.push(
937
+ "--- Project Instructions (from " + (config.instructionsPath ?? "AGI.md") + ") ---",
938
+ config.instructions,
939
+ "--- End Project Instructions ---"
940
+ );
941
+ }
942
+ if (config.rules.length > 0) {
943
+ sections.push("--- Project Rules ---");
944
+ for (const rule of config.rules) {
945
+ sections.push(`[${rule.name}]`);
946
+ sections.push(rule.content);
947
+ sections.push("");
948
+ }
949
+ sections.push("--- End Project Rules ---");
950
+ }
951
+ if (config.skills.length > 0) {
952
+ sections.push(generateSkillsPrompt(config.skills));
953
+ }
954
+ if (sections.length === 0) return goal;
955
+ sections.push("", "Task: " + goal);
956
+ return sections.join("\n");
957
+ }
958
+ function initProject(cwd = process.cwd()) {
959
+ const created = [];
960
+ const agiMd = join2(cwd, "AGI.md");
961
+ if (!existsSync(agiMd)) {
962
+ writeFileSync(
963
+ agiMd,
964
+ [
965
+ "# Project Instructions",
966
+ "",
967
+ "<!-- Add project-specific instructions for the AGI agent here. -->",
968
+ "<!-- These instructions are loaded automatically when you run `agi`. -->",
969
+ ""
970
+ ].join("\n")
971
+ );
972
+ created.push("AGI.md");
973
+ }
974
+ const dirs = [
975
+ ".agi",
976
+ ".agi/commands",
977
+ ".agi/rules",
978
+ ".agi/skills"
979
+ ];
980
+ for (const dir of dirs) {
981
+ const fullPath = join2(cwd, dir);
982
+ if (!existsSync(fullPath)) {
983
+ mkdirSync(fullPath, { recursive: true });
984
+ created.push(dir + "/");
985
+ }
986
+ }
987
+ const gitignore = join2(cwd, ".agi", ".gitignore");
988
+ if (!existsSync(gitignore)) {
989
+ writeFileSync(
990
+ gitignore,
991
+ [
992
+ "# Local files that should not be committed",
993
+ "local.md",
994
+ ""
995
+ ].join("\n")
996
+ );
997
+ created.push(".agi/.gitignore");
998
+ }
999
+ return created;
1000
+ }
1001
+
1002
+ // src/userConfig.ts
1003
+ import fs4 from "fs";
1004
+ import path4 from "path";
1005
+ import os4 from "os";
1006
+ var CONFIG_DIR = path4.join(os4.homedir(), ".agi");
1007
+ var CONFIG_FILE = path4.join(CONFIG_DIR, "config.json");
1008
+ var VALID_KEYS = [
1009
+ "model",
1010
+ "verbose",
1011
+ "noConfirm",
1012
+ "compact",
1013
+ "theme"
1014
+ ];
1015
+ function ensureDir2() {
1016
+ if (!fs4.existsSync(CONFIG_DIR)) {
1017
+ fs4.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
1018
+ }
1019
+ }
1020
+ function loadUserConfig() {
1021
+ try {
1022
+ const raw = fs4.readFileSync(CONFIG_FILE, "utf-8");
1023
+ return JSON.parse(raw);
1024
+ } catch {
1025
+ return {};
1026
+ }
1027
+ }
1028
+ function saveUserConfig(config) {
1029
+ ensureDir2();
1030
+ fs4.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + "\n", {
1031
+ mode: 384
1032
+ });
1033
+ }
1034
+ function setConfigValue(key, value) {
1035
+ if (!VALID_KEYS.includes(key)) {
1036
+ return ` Unknown key "${key}". Valid keys: ${VALID_KEYS.join(", ")}`;
1037
+ }
1038
+ const config = loadUserConfig();
1039
+ if (key === "verbose" || key === "noConfirm" || key === "compact") {
1040
+ const bool = value.toLowerCase();
1041
+ if (bool !== "true" && bool !== "false" && bool !== "on" && bool !== "off") {
1042
+ return ` "${key}" must be true/false or on/off`;
1043
+ }
1044
+ config[key] = bool === "true" || bool === "on";
1045
+ } else {
1046
+ config[key] = value;
1047
+ }
1048
+ saveUserConfig(config);
1049
+ return ` Config: ${key} = ${value} (saved to ~/.agi/config.json)`;
1050
+ }
1051
+ function formatConfig(config) {
1052
+ const lines = ["", " User configuration (~/.agi/config.json):", ""];
1053
+ if (Object.keys(config).length === 0) {
1054
+ lines.push(" (no custom configuration \u2014 using defaults)");
1055
+ } else {
1056
+ for (const [key, value] of Object.entries(config)) {
1057
+ lines.push(` ${key.padEnd(14)} ${String(value)}`);
1058
+ }
1059
+ }
1060
+ lines.push("");
1061
+ lines.push(" Set with: /config <key> <value>");
1062
+ lines.push(` Keys: ${VALID_KEYS.join(", ")}`);
1063
+ lines.push("");
1064
+ return lines.join("\n");
1065
+ }
1066
+
1067
+ // src/hooks.ts
1068
+ import fs5 from "fs";
1069
+ import path5 from "path";
1070
+ import { execSync as execSync2 } from "child_process";
1071
+ var loadedHooks = null;
1072
+ function loadHooks(cwd = process.cwd()) {
1073
+ if (loadedHooks) return loadedHooks;
1074
+ const hooksFile = path5.join(cwd, ".agi", "hooks.json");
1075
+ try {
1076
+ const raw = fs5.readFileSync(hooksFile, "utf-8");
1077
+ loadedHooks = JSON.parse(raw);
1078
+ return loadedHooks;
1079
+ } catch {
1080
+ loadedHooks = { hooks: {} };
1081
+ return loadedHooks;
1082
+ }
1083
+ }
1084
+ function runHooks(event, env = {}) {
1085
+ const config = loadedHooks || loadHooks();
1086
+ const entries = config.hooks[event];
1087
+ if (!entries || entries.length === 0) return;
1088
+ for (const entry of entries) {
1089
+ try {
1090
+ execSync2(entry.command, {
1091
+ stdio: "ignore",
1092
+ timeout: 5e3,
1093
+ env: { ...process.env, ...env, AGI_HOOK_EVENT: event }
1094
+ });
1095
+ } catch {
1096
+ }
1097
+ }
1098
+ }
1099
+ function formatHooks() {
1100
+ const config = loadedHooks || loadHooks();
1101
+ const events = Object.keys(config.hooks);
1102
+ if (events.length === 0) {
1103
+ return " No hooks configured. Add hooks in .agi/hooks.json";
1104
+ }
1105
+ const lines = ["", " Configured hooks:", ""];
1106
+ for (const event of events) {
1107
+ const entries = config.hooks[event] || [];
1108
+ lines.push(` ${event} (${entries.length} hook${entries.length !== 1 ? "s" : ""}):`);
1109
+ for (const entry of entries) {
1110
+ lines.push(` \u25B8 ${entry.command}`);
1111
+ }
1112
+ }
1113
+ lines.push("");
1114
+ return lines.join("\n");
1115
+ }
1116
+
1117
+ // src/commands/slash.ts
679
1118
  var VALID_MODELS = ["claude-sonnet", "claude-opus"];
680
1119
  var builtinCommands = [
681
1120
  {
@@ -689,8 +1128,9 @@ var builtinCommands = [
689
1128
  " Available commands:",
690
1129
  ""
691
1130
  ];
692
- const builtins = all.filter((c) => !c.isUserDefined);
1131
+ const builtins = all.filter((c) => !c.isUserDefined && !c.isSkill);
693
1132
  const userDefined = all.filter((c) => c.isUserDefined);
1133
+ const skills = all.filter((c) => c.isSkill);
694
1134
  for (const cmd of builtins) {
695
1135
  const aliases = cmd.aliases?.length ? ` (${cmd.aliases.map((a) => "/" + a).join(", ")})` : "";
696
1136
  const usage = cmd.usage ? ` ${cmd.usage}` : "";
@@ -707,6 +1147,65 @@ var builtinCommands = [
707
1147
  lines.push(` ${cmd.description}`);
708
1148
  }
709
1149
  }
1150
+ if (skills.length > 0) {
1151
+ lines.push("");
1152
+ lines.push(" Skills (.agi/skills/):");
1153
+ lines.push("");
1154
+ for (const cmd of skills) {
1155
+ const usage = cmd.usage ? ` ${cmd.usage}` : "";
1156
+ lines.push(` /${cmd.name}${usage}`);
1157
+ lines.push(` ${cmd.description}`);
1158
+ }
1159
+ }
1160
+ lines.push("");
1161
+ return lines.join("\n");
1162
+ }
1163
+ },
1164
+ {
1165
+ name: "history",
1166
+ aliases: ["hist"],
1167
+ description: "Show session history",
1168
+ usage: "[clear]",
1169
+ execute: (args) => {
1170
+ if (args.trim().toLowerCase() === "clear") {
1171
+ clearHistory();
1172
+ return " History cleared.";
1173
+ }
1174
+ const entries = loadHistory();
1175
+ return formatHistory(entries);
1176
+ }
1177
+ },
1178
+ {
1179
+ name: "status",
1180
+ aliases: ["info"],
1181
+ description: "Show environment and session info",
1182
+ execute: (_args, ctx) => {
1183
+ const lines = ["", " Environment:", ""];
1184
+ lines.push(` Version ${ctx.version || "unknown"}`);
1185
+ lines.push(` Model ${ctx.model}`);
1186
+ lines.push(` Working dir ${process.cwd().replace(os5.homedir(), "~")}`);
1187
+ lines.push(` Node.js ${process.version}`);
1188
+ lines.push(` Platform ${process.platform} ${process.arch}`);
1189
+ lines.push(` Driver ${isBinaryAvailable() ? "\u2714 available" : "\u2718 not found"}`);
1190
+ lines.push(` API key ${process.env.AGI_API_KEY ? "\u2714 set" : process.env.ANTHROPIC_API_KEY ? "\u2714 set (ANTHROPIC_API_KEY)" : "\u2718 not set"}`);
1191
+ lines.push("");
1192
+ lines.push(" Session:");
1193
+ lines.push("");
1194
+ lines.push(` Verbose ${ctx.verbose ? "on" : "off"}`);
1195
+ lines.push(` Auto-confirm ${ctx.noConfirm ? "on" : "off"}`);
1196
+ lines.push(` Compact mode ${ctx.compact ? "on" : "off"}`);
1197
+ if (ctx.projectConfig) {
1198
+ lines.push("");
1199
+ lines.push(" Project:");
1200
+ lines.push("");
1201
+ lines.push(` Instructions ${ctx.projectConfig.instructionsPath?.replace(process.cwd(), ".") || "none"}`);
1202
+ lines.push(` Rules ${ctx.projectConfig.rules.length} loaded`);
1203
+ lines.push(` Commands ${ctx.projectConfig.commandFiles.length} custom`);
1204
+ lines.push(` Skills ${ctx.projectConfig.skills.length} discovered`);
1205
+ }
1206
+ const history = loadHistory();
1207
+ lines.push("");
1208
+ lines.push(` History ${history.length} past sessions`);
710
1209
  lines.push("");
711
1210
  return lines.join("\n");
712
1211
  }
@@ -737,6 +1236,14 @@ var builtinCommands = [
737
1236
  return ` Verbose output ${!ctx.verbose ? "on" : "off"}`;
738
1237
  }
739
1238
  },
1239
+ {
1240
+ name: "compact",
1241
+ description: "Toggle compact output mode",
1242
+ execute: (_args, ctx) => {
1243
+ ctx.setCompact(!ctx.compact);
1244
+ return ` Compact mode ${!ctx.compact ? "on" : "off"}`;
1245
+ }
1246
+ },
740
1247
  {
741
1248
  name: "confirm",
742
1249
  description: "Toggle auto-confirm mode",
@@ -745,6 +1252,133 @@ var builtinCommands = [
745
1252
  return ` Auto-confirm ${!ctx.noConfirm ? "on" : "off"}`;
746
1253
  }
747
1254
  },
1255
+ {
1256
+ name: "init",
1257
+ description: "Initialize AGI.md and .agi/ project structure",
1258
+ execute: () => {
1259
+ const created = initProject();
1260
+ if (created.length === 0) {
1261
+ return " Project already initialized \u2014 AGI.md and .agi/ exist.";
1262
+ }
1263
+ const lines = ["", " Initialized project:", ""];
1264
+ for (const item of created) {
1265
+ lines.push(` \u2714 Created ${item}`);
1266
+ }
1267
+ lines.push("");
1268
+ lines.push(" Edit AGI.md to add project instructions for the agent.");
1269
+ lines.push(" Add custom commands in .agi/commands/*.md");
1270
+ lines.push(" Add rules in .agi/rules/*.md");
1271
+ lines.push(" Add skills in .agi/skills/<name>/SKILL.md");
1272
+ lines.push("");
1273
+ return lines.join("\n");
1274
+ }
1275
+ },
1276
+ {
1277
+ name: "doctor",
1278
+ aliases: ["check"],
1279
+ description: "Check system health and configuration",
1280
+ execute: (_args, ctx) => {
1281
+ const checks = [];
1282
+ const hasKey = !!(process.env.AGI_API_KEY || process.env.ANTHROPIC_API_KEY);
1283
+ checks.push({
1284
+ label: "API key",
1285
+ ok: hasKey,
1286
+ detail: hasKey ? "configured" : "missing \u2014 run `agi login` or set AGI_API_KEY"
1287
+ });
1288
+ const hasDriver = isBinaryAvailable();
1289
+ checks.push({
1290
+ label: "Driver binary",
1291
+ ok: hasDriver,
1292
+ detail: hasDriver ? "found" : "not found \u2014 reinstall @agi_inc/cli"
1293
+ });
1294
+ const nodeVer = process.versions.node;
1295
+ const [major] = nodeVer.split(".").map(Number);
1296
+ checks.push({
1297
+ label: "Node.js",
1298
+ ok: major >= 18,
1299
+ detail: `v${nodeVer}${major < 18 ? " \u2014 v18+ required" : ""}`
1300
+ });
1301
+ if (ctx.projectConfig) {
1302
+ checks.push({
1303
+ label: "Project instructions",
1304
+ ok: !!ctx.projectConfig.instructions,
1305
+ detail: ctx.projectConfig.instructionsPath?.replace(process.cwd(), ".") || "none \u2014 run /init"
1306
+ });
1307
+ }
1308
+ const lines = ["", " System health:", ""];
1309
+ for (const check of checks) {
1310
+ const icon = check.ok ? "\u2714" : "\u2718";
1311
+ const color = check.ok ? "" : "";
1312
+ lines.push(` ${icon} ${check.label.padEnd(22)} ${check.detail}`);
1313
+ }
1314
+ const allOk = checks.every((c) => c.ok);
1315
+ lines.push("");
1316
+ lines.push(allOk ? " All checks passed." : " Some checks failed \u2014 see above.");
1317
+ lines.push("");
1318
+ return lines.join("\n");
1319
+ }
1320
+ },
1321
+ {
1322
+ name: "skills",
1323
+ description: "List discovered skills",
1324
+ execute: (_args, ctx) => {
1325
+ if (!ctx.projectConfig) return " No project config loaded.";
1326
+ return formatSkillsList(ctx.projectConfig.skills);
1327
+ }
1328
+ },
1329
+ {
1330
+ name: "config",
1331
+ aliases: ["cfg"],
1332
+ description: "Show or set persistent config",
1333
+ usage: "[key] [value]",
1334
+ execute: (args) => {
1335
+ const parts = args.trim().split(/\s+/);
1336
+ if (!args.trim()) {
1337
+ const config = loadUserConfig();
1338
+ return formatConfig(config);
1339
+ }
1340
+ if (parts.length === 1) {
1341
+ const config = loadUserConfig();
1342
+ const val = config[parts[0]];
1343
+ if (val === void 0) return ` ${parts[0]} is not set`;
1344
+ return ` ${parts[0]} = ${String(val)}`;
1345
+ }
1346
+ return setConfigValue(parts[0], parts.slice(1).join(" "));
1347
+ }
1348
+ },
1349
+ {
1350
+ name: "redo",
1351
+ aliases: ["r"],
1352
+ description: "Re-run the last goal",
1353
+ execute: (_args, ctx) => {
1354
+ if (!ctx.lastGoal) return " No previous goal to re-run.";
1355
+ if (!ctx.runGoal) return " Error: cannot run goals in this context";
1356
+ ctx.runGoal(ctx.lastGoal);
1357
+ return null;
1358
+ }
1359
+ },
1360
+ {
1361
+ name: "hooks",
1362
+ description: "Show configured hooks",
1363
+ execute: () => {
1364
+ return formatHooks();
1365
+ }
1366
+ },
1367
+ {
1368
+ name: "bug",
1369
+ description: "Report a bug or issue",
1370
+ execute: () => {
1371
+ return [
1372
+ "",
1373
+ " Report issues at:",
1374
+ " https://github.com/agi-inc/cli/issues",
1375
+ "",
1376
+ " Include: agi version, OS, Node.js version, and steps to reproduce.",
1377
+ " Run /doctor to check your environment.",
1378
+ ""
1379
+ ].join("\n");
1380
+ }
1381
+ },
748
1382
  {
749
1383
  name: "clear",
750
1384
  aliases: ["c"],
@@ -764,7 +1398,7 @@ var builtinCommands = [
764
1398
  }
765
1399
  }
766
1400
  ];
767
- function parseFrontmatter(content) {
1401
+ function parseFrontmatter2(content) {
768
1402
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
769
1403
  if (!match) return { meta: {}, body: content.trim() };
770
1404
  const meta = {};
@@ -782,9 +1416,9 @@ function loadUserCommands(commandFiles) {
782
1416
  const userCommands = [];
783
1417
  for (const filePath of commandFiles) {
784
1418
  try {
785
- const content = readFileSync2(filePath, "utf-8");
786
- const { meta, body } = parseFrontmatter(content);
787
- const name = basename(filePath, ".md");
1419
+ const content = readFileSync3(filePath, "utf-8");
1420
+ const { meta, body } = parseFrontmatter2(content);
1421
+ const name = basename2(filePath, ".md");
788
1422
  const description = meta["description"] || body.split("\n")[0].slice(0, 60);
789
1423
  const usage = meta["argument-hint"];
790
1424
  userCommands.push({
@@ -810,6 +1444,26 @@ function loadUserCommands(commandFiles) {
810
1444
  }
811
1445
  return userCommands;
812
1446
  }
1447
+ function loadSkillCommands(skills) {
1448
+ return skills.filter((s) => s.userInvocable).map((skill) => ({
1449
+ name: skill.name,
1450
+ description: skill.description,
1451
+ usage: skill.argumentHint,
1452
+ isSkill: true,
1453
+ execute: (args, ctx) => {
1454
+ if (!ctx.runGoal) return ` Error: cannot run skill commands in this context`;
1455
+ const loaded = loadSkill(skill);
1456
+ let prompt = loaded.body;
1457
+ prompt = prompt.replace(/\$ARGUMENTS/g, args);
1458
+ const argParts = args.split(/\s+/).filter(Boolean);
1459
+ for (let i = 0; i < argParts.length; i++) {
1460
+ prompt = prompt.replace(new RegExp(`\\$${i + 1}`, "g"), argParts[i]);
1461
+ }
1462
+ ctx.runGoal(prompt);
1463
+ return null;
1464
+ }
1465
+ }));
1466
+ }
813
1467
  var allCommands = [...builtinCommands];
814
1468
  var commandMap = /* @__PURE__ */ new Map();
815
1469
  function rebuildMap() {
@@ -843,10 +1497,12 @@ function getAllCommands() {
843
1497
  }
844
1498
 
845
1499
  // src/components/PromptInput.tsx
846
- var PromptInput = ({ onSubmit }) => {
1500
+ var PromptInput = ({ onSubmit, goalHistory = [] }) => {
847
1501
  const [value, setValue] = useState5("");
848
1502
  const [selectedIndex, setSelectedIndex] = useState5(-1);
849
1503
  const [inputKey, setInputKey] = useState5(0);
1504
+ const [historyIndex, setHistoryIndex] = useState5(-1);
1505
+ const savedInput = useRef2("");
850
1506
  const showSuggestions = value.startsWith("/") && value.length > 0 && !value.includes(" ");
851
1507
  const suggestions = showSuggestions ? getAllCommands().filter((cmd) => {
852
1508
  const typed = value.slice(1).toLowerCase();
@@ -872,19 +1528,41 @@ var PromptInput = ({ onSubmit }) => {
872
1528
  }
873
1529
  };
874
1530
  useInput4((input, key) => {
875
- if (!showSuggestions || suggestions.length === 0) return;
876
- if (key.downArrow) {
877
- setSelectedIndex(
878
- (prev) => prev < suggestions.length - 1 ? prev + 1 : 0
879
- );
1531
+ if (showSuggestions && suggestions.length > 0) {
1532
+ if (key.downArrow) {
1533
+ setSelectedIndex(
1534
+ (prev) => prev < suggestions.length - 1 ? prev + 1 : 0
1535
+ );
1536
+ return;
1537
+ }
1538
+ if (key.upArrow) {
1539
+ setSelectedIndex(
1540
+ (prev) => prev > 0 ? prev - 1 : suggestions.length - 1
1541
+ );
1542
+ return;
1543
+ }
1544
+ if (key.tab) {
1545
+ completeSelected();
1546
+ return;
1547
+ }
1548
+ return;
880
1549
  }
881
- if (key.upArrow) {
882
- setSelectedIndex(
883
- (prev) => prev > 0 ? prev - 1 : suggestions.length - 1
884
- );
1550
+ if (key.upArrow && goalHistory.length > 0) {
1551
+ if (historyIndex === -1) {
1552
+ savedInput.current = value;
1553
+ }
1554
+ const next = Math.min(historyIndex + 1, goalHistory.length - 1);
1555
+ setHistoryIndex(next);
1556
+ pendingValue.current = goalHistory[next];
1557
+ setInputKey((k) => k + 1);
1558
+ return;
885
1559
  }
886
- if (key.tab) {
887
- completeSelected();
1560
+ if (key.downArrow && historyIndex >= 0) {
1561
+ const next = historyIndex - 1;
1562
+ setHistoryIndex(next);
1563
+ pendingValue.current = next === -1 ? savedInput.current : goalHistory[next];
1564
+ setInputKey((k) => k + 1);
1565
+ return;
888
1566
  }
889
1567
  });
890
1568
  const handleSubmit = () => {
@@ -902,6 +1580,8 @@ var PromptInput = ({ onSubmit }) => {
902
1580
  pendingValue.current = "";
903
1581
  setInputKey((k) => k + 1);
904
1582
  setSelectedIndex(-1);
1583
+ setHistoryIndex(-1);
1584
+ savedInput.current = "";
905
1585
  }
906
1586
  };
907
1587
  const visibleSuggestions = suggestions.slice(0, 6);
@@ -1034,57 +1714,6 @@ var Logo = ({
1034
1714
  )), info[r] != null && /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text8, null, " "), info[r]))));
1035
1715
  };
1036
1716
 
1037
- // src/project.ts
1038
- import { readFileSync as readFileSync3, existsSync, readdirSync } from "fs";
1039
- import { join as join2 } from "path";
1040
- var INSTRUCTION_FILES = ["AGI.md", ".agi/AGI.md", ".agi/instructions.md"];
1041
- function loadProjectConfig(cwd = process.cwd()) {
1042
- let instructions = null;
1043
- let instructionsPath = null;
1044
- for (const relPath of INSTRUCTION_FILES) {
1045
- const fullPath = join2(cwd, relPath);
1046
- if (existsSync(fullPath)) {
1047
- try {
1048
- instructions = readFileSync3(fullPath, "utf-8").trim();
1049
- instructionsPath = fullPath;
1050
- break;
1051
- } catch {
1052
- }
1053
- }
1054
- }
1055
- const agiDir = join2(cwd, ".agi");
1056
- const agiDirExists = existsSync(agiDir);
1057
- const commandFiles = [];
1058
- const commandsDir = join2(cwd, ".agi", "commands");
1059
- if (existsSync(commandsDir)) {
1060
- try {
1061
- const files = readdirSync(commandsDir);
1062
- for (const file of files) {
1063
- if (file.endsWith(".md")) {
1064
- commandFiles.push(join2(commandsDir, file));
1065
- }
1066
- }
1067
- } catch {
1068
- }
1069
- }
1070
- return {
1071
- instructions,
1072
- instructionsPath,
1073
- agiDir: agiDirExists ? agiDir : null,
1074
- commandFiles
1075
- };
1076
- }
1077
- function withProjectInstructions(goal, config) {
1078
- if (!config.instructions) return goal;
1079
- return [
1080
- "--- Project Instructions (from " + (config.instructionsPath ?? "AGI.md") + ") ---",
1081
- config.instructions,
1082
- "--- End Project Instructions ---",
1083
- "",
1084
- "Task: " + goal
1085
- ].join("\n");
1086
- }
1087
-
1088
1717
  // src/app/App.tsx
1089
1718
  import { createRequire } from "module";
1090
1719
  var require2 = createRequire(import.meta.url);
@@ -1093,18 +1722,32 @@ var App = ({ args }) => {
1093
1722
  const { exit } = useApp();
1094
1723
  const [phase, setPhase] = useState7(args.goal ? "executing" : "input");
1095
1724
  const [currentGoal, setCurrentGoal] = useState7(args.goal ?? "");
1725
+ const [goalHistory, setGoalHistory] = useState7([]);
1726
+ const userConfig = useMemo2(() => loadUserConfig(), []);
1727
+ useMemo2(() => loadHooks(), []);
1728
+ useEffect5(() => {
1729
+ runHooks("SessionStart");
1730
+ }, []);
1096
1731
  const projectConfig = useMemo2(() => {
1097
1732
  const config = loadProjectConfig();
1733
+ const cmds = [];
1098
1734
  if (config.commandFiles.length > 0) {
1099
- const userCmds = loadUserCommands(config.commandFiles);
1100
- registerCommands(userCmds);
1735
+ cmds.push(...loadUserCommands(config.commandFiles));
1736
+ }
1737
+ if (config.skills.length > 0) {
1738
+ cmds.push(...loadSkillCommands(config.skills));
1739
+ }
1740
+ if (cmds.length > 0) {
1741
+ registerCommands(cmds);
1101
1742
  }
1102
1743
  return config;
1103
1744
  }, []);
1104
- const [model, setModel] = useState7(args.model);
1105
- const [verbose, setVerbose] = useState7(args.verbose);
1106
- const [noConfirm, setNoConfirm] = useState7(args.noConfirm);
1745
+ const [model, setModel] = useState7(args.model !== "claude-sonnet" ? args.model : userConfig.model ?? args.model);
1746
+ const [verbose, setVerbose] = useState7(args.verbose || (userConfig.verbose ?? false));
1747
+ const [noConfirm, setNoConfirm] = useState7(args.noConfirm || (userConfig.noConfirm ?? false));
1748
+ const [compact, setCompact] = useState7(userConfig.compact ?? false);
1107
1749
  const [commandMessage, setCommandMessage] = useState7(null);
1750
+ const taskStartTime = useRef3(null);
1108
1751
  const {
1109
1752
  state,
1110
1753
  step,
@@ -1122,17 +1765,34 @@ var App = ({ args }) => {
1122
1765
  model,
1123
1766
  verbose,
1124
1767
  noConfirm,
1125
- onFinished: () => {
1768
+ onFinished: (result) => {
1769
+ if (currentGoal) {
1770
+ const entry = {
1771
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1772
+ goal: currentGoal,
1773
+ model,
1774
+ durationMs: taskStartTime.current ? Date.now() - taskStartTime.current : void 0,
1775
+ success: result?.success
1776
+ };
1777
+ appendHistory(entry);
1778
+ taskStartTime.current = null;
1779
+ runHooks("TaskComplete", {
1780
+ AGI_GOAL: currentGoal,
1781
+ AGI_SUCCESS: String(result?.success ?? "")
1782
+ });
1783
+ }
1126
1784
  setPhase("input");
1127
1785
  }
1128
1786
  });
1129
1787
  useEffect5(() => {
1130
1788
  if (phase === "executing" && currentGoal) {
1789
+ taskStartTime.current = Date.now();
1131
1790
  start(withProjectInstructions(currentGoal, projectConfig));
1132
1791
  }
1133
1792
  }, [phase, currentGoal, start, projectConfig]);
1134
1793
  const runGoal = useCallback3((goal) => {
1135
1794
  setCommandMessage(null);
1795
+ setGoalHistory((prev) => [goal, ...prev.filter((g) => g !== goal)]);
1136
1796
  setCurrentGoal(goal);
1137
1797
  setPhase("executing");
1138
1798
  }, []);
@@ -1140,12 +1800,17 @@ var App = ({ args }) => {
1140
1800
  model,
1141
1801
  verbose,
1142
1802
  noConfirm,
1803
+ compact,
1143
1804
  setModel,
1144
1805
  setVerbose,
1145
1806
  setNoConfirm,
1807
+ setCompact,
1146
1808
  clearEvents,
1147
1809
  quit: () => exit(),
1148
- runGoal
1810
+ runGoal,
1811
+ projectConfig,
1812
+ version: CLI_VERSION,
1813
+ lastGoal: goalHistory[0]
1149
1814
  };
1150
1815
  const handleSubmitGoal = useCallback3(
1151
1816
  (input) => {
@@ -1159,6 +1824,7 @@ var App = ({ args }) => {
1159
1824
  return;
1160
1825
  }
1161
1826
  setCommandMessage(null);
1827
+ setGoalHistory((prev) => [input, ...prev.filter((g) => g !== input)]);
1162
1828
  setCurrentGoal(input);
1163
1829
  setPhase("executing");
1164
1830
  },
@@ -1184,7 +1850,7 @@ var App = ({ args }) => {
1184
1850
  if (state === "paused") return "thinking";
1185
1851
  return "active";
1186
1852
  })();
1187
- return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, phase === "input" && events.length === 0 && /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Logo, { version: CLI_VERSION, model, cwd: process.cwd(), mood: logoMood }), projectConfig.instructions && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1, marginLeft: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "\u25B8 loaded "), /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, projectConfig.instructionsPath)), projectConfig.commandFiles.length > 0 && /* @__PURE__ */ React9.createElement(Box8, { marginLeft: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "\u25B8 "), /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, projectConfig.commandFiles.length), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " custom command(s) from .agi/commands/"))), phase === "executing" && /* @__PURE__ */ React9.createElement(StatusBar, { state, step, goal: currentGoal }), /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React9.createElement(EventDisplay, { events }), phase === "executing" && state === "running" && /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React9.createElement(Spinner, null)), phase === "executing" && state === "paused" && /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", bold: true }, "\u25AE\u25AE"), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " paused \u2014 space to resume"))), pendingConfirm && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(ConfirmDialog, { reason: pendingConfirm, onConfirm: respondConfirm })), pendingQuestion && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(QuestionDialog, { question: pendingQuestion, onAnswer: respondAnswer })), commandMessage && phase === "input" && /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text9, { color: "gray" }, commandMessage)), phase === "input" && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(PromptInput, { onSubmit: handleSubmitGoal })), phase === "executing" && !isTerminal && !pendingConfirm && !pendingQuestion && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " space pause \xB7 q stop \xB7 ^c quit")));
1853
+ return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, phase === "input" && events.length === 0 && /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Logo, { version: CLI_VERSION, model, cwd: process.cwd(), mood: logoMood }), projectConfig.instructions && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1, marginLeft: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "\u25B8 loaded "), /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, projectConfig.instructionsPath)), projectConfig.rules.length > 0 && /* @__PURE__ */ React9.createElement(Box8, { marginLeft: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "\u25B8 "), /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, projectConfig.rules.length), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " rule(s) from .agi/rules/")), projectConfig.commandFiles.length > 0 && /* @__PURE__ */ React9.createElement(Box8, { marginLeft: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "\u25B8 "), /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, projectConfig.commandFiles.length), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " custom command(s) from .agi/commands/")), projectConfig.skills.length > 0 && /* @__PURE__ */ React9.createElement(Box8, { marginLeft: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "\u25B8 "), /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, projectConfig.skills.length), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " skill(s) from .agi/skills/"))), phase === "executing" && /* @__PURE__ */ React9.createElement(StatusBar, { state, step, goal: currentGoal }), /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React9.createElement(EventDisplay, { events, maxEvents: compact ? 6 : 12 }), phase === "executing" && state === "running" && /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React9.createElement(Spinner, null)), phase === "executing" && state === "paused" && /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", bold: true }, "\u25AE\u25AE"), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " paused \u2014 space to resume"))), pendingConfirm && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(ConfirmDialog, { reason: pendingConfirm, onConfirm: respondConfirm })), pendingQuestion && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(QuestionDialog, { question: pendingQuestion, onAnswer: respondAnswer })), commandMessage && phase === "input" && /* @__PURE__ */ React9.createElement(Box8, null, /* @__PURE__ */ React9.createElement(Text9, { color: "gray" }, commandMessage)), phase === "input" && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(PromptInput, { onSubmit: handleSubmitGoal, goalHistory })), phase === "executing" && !isTerminal && !pendingConfirm && !pendingQuestion && /* @__PURE__ */ React9.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, " space pause \xB7 q stop \xB7 ^c quit")));
1188
1854
  };
1189
1855
 
1190
1856
  // src/index.tsx
@@ -1207,7 +1873,7 @@ async function main() {
1207
1873
  if (!process.env.AGI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
1208
1874
  process.env.AGI_API_KEY = apiKey;
1209
1875
  }
1210
- if (!isBinaryAvailable()) {
1876
+ if (!isBinaryAvailable2()) {
1211
1877
  console.error("Error: AGI driver binary not found");
1212
1878
  console.error("");
1213
1879
  console.error("The driver binary is required for local agent execution.");