@@ -7,6 +7,7 @@ import { createDemoAgent } from "./demo";
77import systemPrompt from "./prompt.md" ;
88import { App } from "./tui/App.tsx" ;
99import { initColorScheme } from "./tui/color-scheme.ts" ;
10+ import { ApiKeyPrompt } from "./tui/components/ApiKeyPrompt.tsx" ;
1011
1112await initColorScheme ( ) ;
1213
@@ -21,7 +22,9 @@ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
2122}
2223
2324const agent =
24- process . env . DEMO === "1" ? await createDemoAgent ( ) : await createAgent ( resolveLlmClientOrExit ( ) ) ;
25+ process . env . DEMO === "1"
26+ ? await createDemoAgent ( )
27+ : await createAgent ( await resolveLlmClientInteractive ( ) ) ;
2528
2629const { waitUntilExit } = render ( createElement ( App , { agent } ) , { exitOnCtrlC : true } ) ;
2730try {
@@ -30,24 +33,60 @@ try {
3033 leaveAltScreen ( ) ;
3134}
3235
33- function resolveLlmClientOrExit ( ) {
34- try {
35- return resolveLlmClient ( systemPrompt ) ;
36- } catch ( error ) {
37- leaveAltScreen ( ) ;
38- console . error ( `Error: ${ error instanceof Error ? error . message : error } ` ) ;
39- process . exit ( 1 ) ;
40- }
36+ async function resolveLlmClientInteractive ( ) {
37+ const configured = resolveLlmClient ( systemPrompt ) ;
38+ if ( configured ) return configured ;
39+
40+ const key = await promptForApiKey ( "ANTHROPIC_API_KEY" ) ;
41+ process . env . ANTHROPIC_API_KEY = key ;
42+
43+ clearScreen ( ) ;
44+
45+ const client = resolveLlmClient ( systemPrompt ) ;
46+ if ( client ) return client ;
47+
48+ leaveAltScreen ( ) ;
49+ console . error ( "Error: could not initialise an LLM client from the provided key." ) ;
50+ process . exit ( 1 ) ;
51+ }
52+
53+ function promptForApiKey ( envVarName : string ) : Promise < string > {
54+ return new Promise ( ( resolve ) => {
55+ let submitted = false ;
56+ const { unmount, waitUntilExit } = render (
57+ createElement ( ApiKeyPrompt , {
58+ envVarName,
59+ onSubmit : ( key : string ) => {
60+ submitted = true ;
61+ unmount ( ) ;
62+ resolve ( key ) ;
63+ } ,
64+ } ) ,
65+ { exitOnCtrlC : true } ,
66+ ) ;
67+ void waitUntilExit ( ) . then ( ( ) => {
68+ if ( ! submitted ) {
69+ leaveAltScreen ( ) ;
70+ process . exit ( 0 ) ;
71+ }
72+ } ) ;
73+ } ) ;
4174}
4275
4376function enterAltScreen ( ) {
4477 if ( ! process . stdout . isTTY ) return ;
45- writeSync ( process . stdout . fd , "\x1b[?1049h\x1b[2J\x1b[H " ) ;
78+ writeSync ( process . stdout . fd , "\x1b[?1049h" ) ;
4679 altScreenActive = true ;
80+ clearScreen ( ) ;
4781}
4882
4983function leaveAltScreen ( ) {
5084 if ( ! altScreenActive ) return ;
5185 writeSync ( process . stdout . fd , "\x1b[?1049l\x1b[?25h" ) ;
5286 altScreenActive = false ;
5387}
88+
89+ function clearScreen ( ) {
90+ if ( ! process . stdout . isTTY ) return ;
91+ writeSync ( process . stdout . fd , "\x1b[2J\x1b[H" ) ;
92+ }
0 commit comments