@agi_inc/cli 0.5.2 → 0.5.3
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/README.md +59 -2
- package/dist/index.mjs +83 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Terminal-based AI agent for desktop automation. Give it a task in plain English and watch it take control of your computer to get it done.
|
|
4
4
|
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="https://github.com/agi-inc/agi-cli/releases/latest/download/hero.png" alt="AGI CLI running a task" width="680">
|
|
7
|
+
</p>
|
|
8
|
+
|
|
5
9
|
```bash
|
|
6
10
|
npx @agi_inc/cli "open calculator and compute 2+2"
|
|
7
11
|
```
|
|
@@ -28,9 +32,21 @@ brew install agi-inc/tap/agi
|
|
|
28
32
|
agi "your task here"
|
|
29
33
|
```
|
|
30
34
|
|
|
31
|
-
##
|
|
35
|
+
## Authentication
|
|
36
|
+
|
|
37
|
+
Log in with your AGI account to automatically configure your API key:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
agi login
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This opens a browser-based device authorization flow. Once approved, your API key is saved to `~/.agi/credentials` and used automatically.
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
```bash
|
|
46
|
+
agi logout # remove stored credentials
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Alternatively, set your API key via environment variable:
|
|
34
50
|
|
|
35
51
|
```bash
|
|
36
52
|
export AGI_API_KEY=your_api_key
|
|
@@ -54,6 +70,27 @@ agi "Install Node.js" --verbose
|
|
|
54
70
|
agi "Delete old files" --no-confirm
|
|
55
71
|
```
|
|
56
72
|
|
|
73
|
+
When the agent needs approval before a destructive action, it shows a confirmation dialog:
|
|
74
|
+
|
|
75
|
+
<p align="center">
|
|
76
|
+
<img src="https://github.com/agi-inc/agi-cli/releases/latest/download/confirm.png" alt="AGI CLI confirmation dialog" width="680">
|
|
77
|
+
</p>
|
|
78
|
+
|
|
79
|
+
When the agent needs more information, it prompts with a question:
|
|
80
|
+
|
|
81
|
+
<p align="center">
|
|
82
|
+
<img src="https://github.com/agi-inc/agi-cli/releases/latest/download/question.png" alt="AGI CLI question dialog" width="680">
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
## Commands
|
|
86
|
+
|
|
87
|
+
| Command | Description |
|
|
88
|
+
|---------|-------------|
|
|
89
|
+
| `agi "task"` | Run the agent with a task |
|
|
90
|
+
| `agi login` | Authenticate via browser-based device flow |
|
|
91
|
+
| `agi logout` | Remove stored credentials |
|
|
92
|
+
| `agi update` | Check for updates and self-update |
|
|
93
|
+
|
|
57
94
|
## Options
|
|
58
95
|
|
|
59
96
|
| Option | Alias | Description | Default |
|
|
@@ -74,6 +111,22 @@ While the agent is running:
|
|
|
74
111
|
| `Q` | Stop |
|
|
75
112
|
| `Ctrl+C` | Cancel |
|
|
76
113
|
|
|
114
|
+
<p align="center">
|
|
115
|
+
<img src="https://github.com/agi-inc/agi-cli/releases/latest/download/paused.png" alt="AGI CLI paused state" width="680">
|
|
116
|
+
</p>
|
|
117
|
+
|
|
118
|
+
## Updating
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
agi update
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
<p align="center">
|
|
125
|
+
<img src="https://github.com/agi-inc/agi-cli/releases/latest/download/update.png" alt="agi update output" width="520">
|
|
126
|
+
</p>
|
|
127
|
+
|
|
128
|
+
Detects your install method (npm or Homebrew) and runs the appropriate upgrade command.
|
|
129
|
+
|
|
77
130
|
## How It Works
|
|
78
131
|
|
|
79
132
|
1. Captures screenshots of your desktop
|
|
@@ -81,6 +134,10 @@ While the agent is running:
|
|
|
81
134
|
3. Decides on and executes actions
|
|
82
135
|
4. Repeats until the task is complete
|
|
83
136
|
|
|
137
|
+
<p align="center">
|
|
138
|
+
<img src="https://github.com/agi-inc/agi-cli/releases/latest/download/complete.png" alt="AGI CLI task completed" width="680">
|
|
139
|
+
</p>
|
|
140
|
+
|
|
84
141
|
## Requirements
|
|
85
142
|
|
|
86
143
|
- Node.js 20.4.0 or later
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.tsx
|
|
2
|
-
import
|
|
2
|
+
import React8 from "react";
|
|
3
3
|
import { render } from "ink";
|
|
4
4
|
import { isBinaryAvailable } from "@agi_inc/agi-js";
|
|
5
5
|
|
|
@@ -247,13 +247,13 @@ async function parseArgs() {
|
|
|
247
247
|
}).command("update", "Update AGI CLI to the latest version", {}, async () => {
|
|
248
248
|
await updateCommand();
|
|
249
249
|
}).command(
|
|
250
|
-
"$0
|
|
250
|
+
"$0 [goal]",
|
|
251
251
|
"Run an agent with the given goal",
|
|
252
252
|
(yargs2) => {
|
|
253
253
|
return yargs2.positional("goal", {
|
|
254
254
|
describe: "The task for the agent to accomplish",
|
|
255
255
|
type: "string",
|
|
256
|
-
demandOption:
|
|
256
|
+
demandOption: false
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
259
|
).option("model", {
|
|
@@ -271,7 +271,7 @@ async function parseArgs() {
|
|
|
271
271
|
describe: "Auto-approve all confirmation requests",
|
|
272
272
|
type: "boolean",
|
|
273
273
|
default: false
|
|
274
|
-
}).help().alias("help", "h").version().alias("version", "V").example('$0 "Open calculator and compute 2+2"', "Basic task").example('$0 "Find flights from SFO to JFK" --model claude-opus', "Use a specific model").example('$0 "Install Node.js" --verbose', "Verbose output").example("$0 login", "Authenticate with your API key").example("$0 update", "Update to the latest version").parse();
|
|
274
|
+
}).help().alias("help", "h").version().alias("version", "V").example('$0 "Open calculator and compute 2+2"', "Basic task").example('$0 "Find flights from SFO to JFK" --model claude-opus', "Use a specific model").example('$0 "Install Node.js" --verbose', "Verbose output").example("$0", "Start interactive mode").example("$0 login", "Authenticate with your API key").example("$0 update", "Update to the latest version").parse();
|
|
275
275
|
const command = argv._?.[0];
|
|
276
276
|
if (command === "login" || command === "logout" || command === "update") {
|
|
277
277
|
return { kind: "handled" };
|
|
@@ -288,8 +288,8 @@ async function parseArgs() {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
// src/app/App.tsx
|
|
291
|
-
import
|
|
292
|
-
import { Box as
|
|
291
|
+
import React7, { useEffect as useEffect2, useState as useState5, useCallback as useCallback3 } from "react";
|
|
292
|
+
import { Box as Box7, Text as Text7, useApp } from "ink";
|
|
293
293
|
|
|
294
294
|
// src/hooks/useAgent.ts
|
|
295
295
|
import { useState, useCallback, useRef, useEffect } from "react";
|
|
@@ -302,11 +302,32 @@ function useAgent(options) {
|
|
|
302
302
|
const [pendingConfirm, setPendingConfirm] = useState(null);
|
|
303
303
|
const [pendingQuestion, setPendingQuestion] = useState(null);
|
|
304
304
|
const driverRef = useRef(null);
|
|
305
|
+
const onFinishedRef = useRef(onFinished);
|
|
306
|
+
useEffect(() => {
|
|
307
|
+
onFinishedRef.current = onFinished;
|
|
308
|
+
}, [onFinished]);
|
|
305
309
|
const addEvent = useCallback((event) => {
|
|
306
310
|
setEvents((prev) => [...prev, event]);
|
|
307
311
|
}, []);
|
|
308
312
|
const start = useCallback(
|
|
309
313
|
async (goal) => {
|
|
314
|
+
if (driverRef.current) {
|
|
315
|
+
try {
|
|
316
|
+
await driverRef.current.stop("New task started");
|
|
317
|
+
} catch {
|
|
318
|
+
}
|
|
319
|
+
driverRef.current = null;
|
|
320
|
+
}
|
|
321
|
+
setState("idle");
|
|
322
|
+
setStep(0);
|
|
323
|
+
setPendingConfirm(null);
|
|
324
|
+
setPendingQuestion(null);
|
|
325
|
+
setEvents((prev) => {
|
|
326
|
+
if (prev.length > 0) {
|
|
327
|
+
return [...prev, { type: "separator", goal }];
|
|
328
|
+
}
|
|
329
|
+
return prev;
|
|
330
|
+
});
|
|
310
331
|
const driver = new AgentDriver({ model, mode: "local", agentName, apiUrl });
|
|
311
332
|
driverRef.current = driver;
|
|
312
333
|
driver.on("state_change", (newState) => {
|
|
@@ -319,7 +340,10 @@ function useAgent(options) {
|
|
|
319
340
|
});
|
|
320
341
|
driver.on("action", async (action) => {
|
|
321
342
|
const actionStr = action.type + (action.x !== void 0 ? ` (${action.x}, ${action.y})` : "");
|
|
322
|
-
|
|
343
|
+
const parts = [];
|
|
344
|
+
if (action.text) parts.push(`"${action.text}"`);
|
|
345
|
+
if (action.key) parts.push(`[${action.key}]`);
|
|
346
|
+
addEvent({ type: "action", action: actionStr, params: parts.length ? parts.join(" ") : void 0 });
|
|
323
347
|
});
|
|
324
348
|
driver.on("confirm", async (reason) => {
|
|
325
349
|
if (noConfirm) {
|
|
@@ -347,14 +371,14 @@ function useAgent(options) {
|
|
|
347
371
|
});
|
|
348
372
|
try {
|
|
349
373
|
const result = await driver.start(goal);
|
|
350
|
-
if (
|
|
351
|
-
|
|
374
|
+
if (onFinishedRef.current) {
|
|
375
|
+
onFinishedRef.current(result);
|
|
352
376
|
}
|
|
353
377
|
} catch (error) {
|
|
354
378
|
addEvent({ type: "error", message: String(error) });
|
|
355
379
|
}
|
|
356
380
|
},
|
|
357
|
-
[model, agentName, apiUrl, verbose, noConfirm, addEvent
|
|
381
|
+
[model, agentName, apiUrl, verbose, noConfirm, addEvent]
|
|
358
382
|
);
|
|
359
383
|
const stop = useCallback(async () => {
|
|
360
384
|
if (driverRef.current) {
|
|
@@ -497,6 +521,8 @@ function getEventText(event) {
|
|
|
497
521
|
return event.summary;
|
|
498
522
|
case "error":
|
|
499
523
|
return event.message;
|
|
524
|
+
case "separator":
|
|
525
|
+
return event.goal;
|
|
500
526
|
}
|
|
501
527
|
}
|
|
502
528
|
function getEventStyle(event) {
|
|
@@ -509,6 +535,9 @@ var EventDisplay = ({ events, maxEvents = 12 }) => {
|
|
|
509
535
|
const displayEvents = events.slice(-maxEvents);
|
|
510
536
|
if (displayEvents.length === 0) return null;
|
|
511
537
|
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, displayEvents.map((event, index) => {
|
|
538
|
+
if (event.type === "separator") {
|
|
539
|
+
return /* @__PURE__ */ React2.createElement(Box2, { key: index, marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " \u2500\u2500 "), /* @__PURE__ */ React2.createElement(Text2, { bold: true }, event.goal), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " \u2500\u2500"));
|
|
540
|
+
}
|
|
512
541
|
const style = getEventStyle(event);
|
|
513
542
|
const text = getEventText(event);
|
|
514
543
|
const isLatest = index === displayEvents.length - 1;
|
|
@@ -520,7 +549,7 @@ var EventDisplay = ({ events, maxEvents = 12 }) => {
|
|
|
520
549
|
dimColor: event.type === "thinking"
|
|
521
550
|
},
|
|
522
551
|
text
|
|
523
|
-
));
|
|
552
|
+
), event.type === "action" && event.params && /* @__PURE__ */ React2.createElement(Text2, { color: "gray" }, " ", event.params));
|
|
524
553
|
}));
|
|
525
554
|
};
|
|
526
555
|
|
|
@@ -588,18 +617,43 @@ var QuestionDialog = ({ question, onAnswer }) => {
|
|
|
588
617
|
)), /* @__PURE__ */ React4.createElement(Box4, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "enter to submit")));
|
|
589
618
|
};
|
|
590
619
|
|
|
591
|
-
// src/components/
|
|
592
|
-
import React5 from "react";
|
|
620
|
+
// src/components/PromptInput.tsx
|
|
621
|
+
import React5, { useState as useState4 } from "react";
|
|
593
622
|
import { Text as Text5, Box as Box5 } from "ink";
|
|
623
|
+
import TextInput2 from "ink-text-input";
|
|
624
|
+
var PromptInput = ({ onSubmit }) => {
|
|
625
|
+
const [value, setValue] = useState4("");
|
|
626
|
+
const handleSubmit = () => {
|
|
627
|
+
const trimmed = value.trim();
|
|
628
|
+
if (trimmed) {
|
|
629
|
+
onSubmit(trimmed);
|
|
630
|
+
setValue("");
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
return /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan", bold: true }, "\u25B8 "), /* @__PURE__ */ React5.createElement(
|
|
634
|
+
TextInput2,
|
|
635
|
+
{
|
|
636
|
+
value,
|
|
637
|
+
onChange: setValue,
|
|
638
|
+
onSubmit: handleSubmit,
|
|
639
|
+
placeholder: "Enter a task..."
|
|
640
|
+
}
|
|
641
|
+
));
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
// src/components/Spinner.tsx
|
|
645
|
+
import React6 from "react";
|
|
646
|
+
import { Text as Text6, Box as Box6 } from "ink";
|
|
594
647
|
import InkSpinner from "ink-spinner";
|
|
595
648
|
var Spinner = ({ text }) => {
|
|
596
|
-
return /* @__PURE__ */
|
|
649
|
+
return /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, /* @__PURE__ */ React6.createElement(InkSpinner, { type: "dots" })), text && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " ", text));
|
|
597
650
|
};
|
|
598
651
|
|
|
599
652
|
// src/app/App.tsx
|
|
600
653
|
var App = ({ args }) => {
|
|
601
654
|
const { exit } = useApp();
|
|
602
|
-
const [
|
|
655
|
+
const [phase, setPhase] = useState5(args.goal ? "executing" : "input");
|
|
656
|
+
const [currentGoal, setCurrentGoal] = useState5(args.goal ?? "");
|
|
603
657
|
const {
|
|
604
658
|
state,
|
|
605
659
|
step,
|
|
@@ -617,27 +671,32 @@ var App = ({ args }) => {
|
|
|
617
671
|
verbose: args.verbose,
|
|
618
672
|
noConfirm: args.noConfirm,
|
|
619
673
|
onFinished: () => {
|
|
620
|
-
|
|
674
|
+
setPhase("input");
|
|
621
675
|
}
|
|
622
676
|
});
|
|
623
677
|
useEffect2(() => {
|
|
624
|
-
if (
|
|
625
|
-
|
|
626
|
-
start(args.goal);
|
|
678
|
+
if (phase === "executing" && currentGoal) {
|
|
679
|
+
start(currentGoal);
|
|
627
680
|
}
|
|
628
|
-
}, [
|
|
681
|
+
}, [phase, currentGoal, start]);
|
|
682
|
+
const handleSubmitGoal = useCallback3((goal) => {
|
|
683
|
+
setCurrentGoal(goal);
|
|
684
|
+
setPhase("executing");
|
|
685
|
+
}, []);
|
|
629
686
|
useKeybindings({
|
|
630
687
|
onPause: pause,
|
|
631
688
|
onResume: resume,
|
|
632
689
|
onStop: async () => {
|
|
633
|
-
|
|
690
|
+
if (phase === "executing") {
|
|
691
|
+
await stop();
|
|
692
|
+
}
|
|
634
693
|
exit();
|
|
635
694
|
},
|
|
636
695
|
isPaused: state === "paused",
|
|
637
|
-
disabled: !!pendingConfirm || !!pendingQuestion
|
|
696
|
+
disabled: phase === "input" || !!pendingConfirm || !!pendingQuestion
|
|
638
697
|
});
|
|
639
698
|
const isTerminal = state === "finished" || state === "stopped" || state === "error";
|
|
640
|
-
return /* @__PURE__ */
|
|
699
|
+
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, phase === "input" && events.length === 0 && /* @__PURE__ */ React7.createElement(Box7, { borderStyle: "bold", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan", bold: true }, "\u25B8 AGI"), /* @__PURE__ */ React7.createElement(Text7, null, " interactive mode")), phase === "executing" && /* @__PURE__ */ React7.createElement(StatusBar, { state, step, goal: currentGoal }), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React7.createElement(EventDisplay, { events }), phase === "executing" && state === "running" && /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React7.createElement(Spinner, null)), phase === "executing" && state === "paused" && /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React7.createElement(Text7, { color: "yellow", bold: true }, "\u25AE\u25AE"), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " paused \u2014 space to resume"))), pendingConfirm && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(ConfirmDialog, { reason: pendingConfirm, onConfirm: respondConfirm })), pendingQuestion && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(QuestionDialog, { question: pendingQuestion, onAnswer: respondAnswer })), phase === "input" && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(PromptInput, { onSubmit: handleSubmitGoal })), phase === "executing" && !isTerminal && !pendingConfirm && !pendingQuestion && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " space pause \xB7 q stop \xB7 ^c quit")));
|
|
641
700
|
};
|
|
642
701
|
|
|
643
702
|
// src/index.tsx
|
|
@@ -670,15 +729,7 @@ async function main() {
|
|
|
670
729
|
console.error("");
|
|
671
730
|
process.exit(1);
|
|
672
731
|
}
|
|
673
|
-
|
|
674
|
-
console.error("Error: Goal is required");
|
|
675
|
-
console.error("");
|
|
676
|
-
console.error("Usage: agi <goal>");
|
|
677
|
-
console.error("");
|
|
678
|
-
console.error('Example: agi "Open calculator and compute 2+2"');
|
|
679
|
-
process.exit(1);
|
|
680
|
-
}
|
|
681
|
-
const { waitUntilExit } = render(/* @__PURE__ */ React7.createElement(App, { args }));
|
|
732
|
+
const { waitUntilExit } = render(/* @__PURE__ */ React8.createElement(App, { args }));
|
|
682
733
|
await waitUntilExit();
|
|
683
734
|
} catch (error) {
|
|
684
735
|
console.error("Error:", error);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/cli.ts","../src/config.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/update.ts","../src/app/App.tsx","../src/hooks/useAgent.ts","../src/hooks/useKeybindings.ts","../src/components/StatusBar.tsx","../src/components/EventDisplay.tsx","../src/components/ConfirmDialog.tsx","../src/components/QuestionDialog.tsx","../src/components/Spinner.tsx"],"sourcesContent":["/**\n * AGI CLI - Terminal-based agent interaction for AGI desktop automation.\n *\n * Usage:\n * agi \"Open calculator and compute 2+2\"\n * agi \"Find flights from SFO to JFK\" --model claude-opus\n * agi \"Install Node.js\" --verbose\n * agi login\n * agi logout\n */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport { isBinaryAvailable } from '@agi_inc/agi-js';\nimport { parseArgs } from './cli.js';\nimport { App } from './app/App.js';\nimport { loadApiKey } from './config.js';\n\nasync function main(): Promise<void> {\n try {\n const result = await parseArgs();\n\n // login/logout subcommands are self-contained\n if (result.kind === 'handled') {\n return;\n }\n\n const { args } = result;\n\n // Check for API key\n const apiKey = loadApiKey();\n if (!apiKey) {\n console.error('Error: No API key found');\n console.error('');\n console.error('Run `agi login` to authenticate, or set an environment variable:');\n console.error(' export AGI_API_KEY=your_key');\n console.error('');\n process.exit(1);\n }\n\n // Make the key available to downstream code via env\n if (!process.env.AGI_API_KEY && !process.env.ANTHROPIC_API_KEY) {\n process.env.AGI_API_KEY = apiKey;\n }\n\n // Check for driver binary\n if (!isBinaryAvailable()) {\n console.error('Error: AGI driver binary not found');\n console.error('');\n console.error('The driver binary is required for local agent execution.');\n console.error('It should be installed automatically with the agi package.');\n console.error('');\n console.error('Try reinstalling: npm install -g @agi_inc/cli');\n console.error('');\n process.exit(1);\n }\n\n // Check if goal is provided\n if (!args.goal) {\n console.error('Error: Goal is required');\n console.error('');\n console.error('Usage: agi <goal>');\n console.error('');\n console.error('Example: agi \"Open calculator and compute 2+2\"');\n process.exit(1);\n }\n\n // Render the app\n const { waitUntilExit } = render(<App args={args} />);\n await waitUntilExit();\n } catch (error) {\n console.error('Error:', error);\n process.exit(1);\n }\n}\n\nmain();\n","/**\n * CLI argument parsing and configuration.\n */\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { loginCommand } from './commands/login.js';\nimport { logoutCommand } from './commands/logout.js';\nimport { updateCommand } from './commands/update.js';\n\nexport interface CliArgs {\n goal: string;\n model: string;\n verbose: boolean;\n noConfirm: boolean;\n}\n\nexport type ParseResult =\n | { kind: 'run'; args: CliArgs }\n | { kind: 'handled' };\n\nexport async function parseArgs(): Promise<ParseResult> {\n const argv = await yargs(hideBin(process.argv))\n .scriptName('agi')\n .command('login', 'Authenticate and save your API key', {}, async () => {\n await loginCommand();\n })\n .command('logout', 'Remove saved credentials', {}, async () => {\n await logoutCommand();\n })\n .command('update', 'Update AGI CLI to the latest version', {}, async () => {\n await updateCommand();\n })\n .command(\n '$0 <goal>',\n 'Run an agent with the given goal',\n (yargs) => {\n return yargs.positional('goal', {\n describe: 'The task for the agent to accomplish',\n type: 'string',\n demandOption: true,\n });\n },\n )\n .option('model', {\n alias: 'm',\n describe: 'Model to use',\n type: 'string',\n default: 'claude-sonnet',\n choices: ['claude-sonnet', 'claude-opus'],\n })\n .option('verbose', {\n alias: 'v',\n describe: 'Show verbose output including agent thinking',\n type: 'boolean',\n default: false,\n })\n .option('no-confirm', {\n describe: 'Auto-approve all confirmation requests',\n type: 'boolean',\n default: false,\n })\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'V')\n .example('$0 \"Open calculator and compute 2+2\"', 'Basic task')\n .example('$0 \"Find flights from SFO to JFK\" --model claude-opus', 'Use a specific model')\n .example('$0 \"Install Node.js\" --verbose', 'Verbose output')\n .example('$0 login', 'Authenticate with your API key')\n .example('$0 update', 'Update to the latest version')\n .parse();\n\n // If a subcommand (login/logout) was handled, yargs already ran its handler\n const command = argv._?.[0];\n if (command === 'login' || command === 'logout' || command === 'update') {\n return { kind: 'handled' };\n }\n\n return {\n kind: 'run',\n args: {\n goal: argv.goal as string,\n model: argv.model as string,\n verbose: argv.verbose as boolean,\n noConfirm: argv['no-confirm'] as boolean,\n },\n };\n}\n","/**\n * Credentials file management for AGI CLI.\n *\n * Checks AGI_API_KEY env -> ANTHROPIC_API_KEY env -> ~/.agi/credentials file.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\ninterface Credentials {\n api_key: string;\n}\n\nexport function getCredentialsPath(): string {\n return path.join(os.homedir(), '.agi', 'credentials');\n}\n\n/**\n * Load API key from environment variables or credentials file.\n * Priority: AGI_API_KEY env -> ANTHROPIC_API_KEY env -> ~/.agi/credentials\n */\nexport function loadApiKey(): string | undefined {\n if (process.env.AGI_API_KEY) {\n return process.env.AGI_API_KEY;\n }\n\n if (process.env.ANTHROPIC_API_KEY) {\n return process.env.ANTHROPIC_API_KEY;\n }\n\n const credPath = getCredentialsPath();\n try {\n const raw = fs.readFileSync(credPath, 'utf-8');\n const credentials: Credentials = JSON.parse(raw);\n if (credentials.api_key) {\n return credentials.api_key;\n }\n } catch {\n // File doesn't exist or is invalid\n }\n\n return undefined;\n}\n\n/**\n * Save API key to ~/.agi/credentials.\n * Creates the ~/.agi/ directory if it doesn't exist.\n */\nexport function saveApiKey(apiKey: string): void {\n const credPath = getCredentialsPath();\n const dir = path.dirname(credPath);\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n const credentials: Credentials = { api_key: apiKey };\n fs.writeFileSync(credPath, JSON.stringify(credentials, null, 2) + '\\n', {\n mode: 0o600,\n });\n}\n\n/**\n * Delete the credentials file.\n */\nexport function deleteCredentials(): boolean {\n const credPath = getCredentialsPath();\n try {\n fs.unlinkSync(credPath);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * `agi login` command — device code auth flow.\n *\n * 1. POST /v1/auth/device -> get device_code + user_code\n * 2. Open browser to verification_url\n * 3. Poll POST /v1/auth/device/token every 5s\n * 4. On approval -> save API key to ~/.agi/credentials\n */\n\nimport { saveApiKey } from '../config.js';\n\nconst API_BASE = 'https://api.agi.tech';\n\ninterface DeviceAuthResponse {\n device_code: string;\n user_code: string;\n verification_url: string;\n expires_in: number;\n interval: number;\n}\n\ninterface DeviceAuthTokenResponse {\n api_key: string;\n email: string | null;\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const open = (await import('open')).default;\n await open(url);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function loginCommand(): Promise<void> {\n // Step 1: Initiate device auth\n let deviceAuth: DeviceAuthResponse;\n try {\n const res = await fetch(`${API_BASE}/v1/auth/device`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n });\n\n if (!res.ok) {\n const detail = await res.text();\n console.error(`Failed to start login flow (${res.status}): ${detail}`);\n process.exit(1);\n }\n\n deviceAuth = (await res.json()) as DeviceAuthResponse;\n } catch (err) {\n console.error(`Failed to connect to AGI API: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // Step 2: Show code and open browser\n console.log('');\n console.log(`Your confirmation code: ${deviceAuth.user_code}`);\n console.log('');\n console.log('Opening browser to authorize...');\n console.log(` ${deviceAuth.verification_url}`);\n console.log('');\n\n try {\n await openBrowser(deviceAuth.verification_url);\n } catch {\n console.log('Could not open browser automatically. Please visit the URL above.');\n }\n\n console.log('Waiting for authorization...');\n\n // Handle Ctrl+C gracefully during polling\n const sigintHandler = () => {\n console.log('\\nLogin cancelled.');\n process.exit(130);\n };\n process.on('SIGINT', sigintHandler);\n\n // Step 3: Poll for token\n const maxAttempts = Math.ceil(deviceAuth.expires_in / deviceAuth.interval);\n const interval = deviceAuth.interval * 1000;\n let consecutiveErrors = 0;\n\n try {\n for (let i = 0; i < maxAttempts; i++) {\n await sleep(interval);\n\n try {\n const res = await fetch(`${API_BASE}/v1/auth/device/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ device_code: deviceAuth.device_code }),\n });\n\n consecutiveErrors = 0;\n\n if (res.status === 428) {\n // Still pending\n process.stdout.write('.');\n continue;\n }\n\n if (res.status === 410) {\n console.log('');\n console.error('Login expired. Please run `agi login` again.');\n process.exit(1);\n }\n\n if (res.ok) {\n const token = (await res.json()) as DeviceAuthTokenResponse;\n console.log('');\n\n saveApiKey(token.api_key);\n\n const identity = token.email || 'your account';\n console.log(`Logged in as ${identity}`);\n console.log('Your API key has been saved to ~/.agi/credentials');\n return;\n }\n\n // Unexpected status\n const detail = await res.text();\n console.log('');\n console.error(`Unexpected response (${res.status}): ${detail}`);\n process.exit(1);\n } catch {\n consecutiveErrors++;\n if (consecutiveErrors >= 3) {\n console.log('');\n console.error('Unable to reach AGI API. Check your internet connection.');\n console.error('Retrying...');\n consecutiveErrors = 0;\n } else {\n process.stdout.write('!');\n }\n }\n }\n\n console.log('');\n console.error('Login timed out. Please run `agi login` again.');\n process.exit(1);\n } finally {\n process.removeListener('SIGINT', sigintHandler);\n }\n}\n","/**\n * `agi logout` command — remove stored credentials.\n */\n\nimport { deleteCredentials } from '../config.js';\n\nexport async function logoutCommand(): Promise<void> {\n const deleted = deleteCredentials();\n\n if (deleted) {\n console.log('Logged out. Credentials removed from ~/.agi/credentials');\n } else {\n console.log('No credentials file found. Already logged out.');\n }\n}\n","/**\n * Self-update command for AGI CLI.\n *\n * Checks the npm registry for the latest version, detects install method\n * (npm or Homebrew), and runs the appropriate update command.\n */\n\nimport { execSync } from 'node:child_process';\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nfunction getCurrentVersion(): string {\n // Resolve symlinks (npm global bin is a symlink to the package)\n const realScript = realpathSync(process.argv[1]);\n const pkgPath = join(dirname(realScript), '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version;\n}\n\nasync function getLatestVersion(): Promise<string> {\n const res = await fetch('https://registry.npmjs.org/@agi_inc/cli');\n if (!res.ok) {\n throw new Error(`npm registry returned ${res.status}`);\n }\n const data = (await res.json()) as { 'dist-tags': { latest: string } };\n return data['dist-tags'].latest;\n}\n\nfunction compareVersions(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n if ((pa[i] || 0) < (pb[i] || 0)) return -1;\n if ((pa[i] || 0) > (pb[i] || 0)) return 1;\n }\n return 0;\n}\n\nfunction detectInstallMethod(): 'npm' | 'homebrew' | 'unknown' {\n try {\n const agiPath = execSync('which agi', { encoding: 'utf-8' }).trim();\n if (agiPath.includes('homebrew') || agiPath.includes('Cellar')) {\n return 'homebrew';\n }\n return 'npm';\n } catch {\n return 'unknown';\n }\n}\n\nexport async function updateCommand(): Promise<void> {\n const current = getCurrentVersion();\n\n console.log('');\n console.log(` \\u25B8 AGI CLI v${current}`);\n console.log('');\n console.log(' Checking for updates...');\n\n try {\n const latest = await getLatestVersion();\n\n if (compareVersions(current, latest) >= 0) {\n console.log(` \\u25CF Up to date`);\n console.log('');\n return;\n }\n\n console.log(` Update available: ${current} \\u2192 ${latest}`);\n console.log('');\n\n const method = detectInstallMethod();\n\n if (method === 'homebrew') {\n console.log(' Updating via Homebrew...');\n console.log('');\n execSync('brew upgrade agi', { stdio: 'inherit' });\n } else {\n console.log(' Updating via npm...');\n console.log('');\n execSync('npm install -g @agi_inc/cli@latest', { stdio: 'inherit' });\n }\n\n console.log('');\n console.log(` \\u25CF Updated to v${latest}`);\n console.log('');\n } catch (error) {\n console.error('');\n console.error(` \\u2715 Update failed: ${error instanceof Error ? error.message : error}`);\n console.error('');\n console.error(' Try manually:');\n console.error(' npm install -g @agi_inc/cli@latest');\n console.error('');\n process.exit(1);\n }\n}\n","import React, { useEffect, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport type { CliArgs } from '../cli.js';\nimport { useAgent } from '../hooks/useAgent.js';\nimport { useKeybindings } from '../hooks/useKeybindings.js';\nimport { StatusBar } from '../components/StatusBar.js';\nimport { EventDisplay } from '../components/EventDisplay.js';\nimport { ConfirmDialog } from '../components/ConfirmDialog.js';\nimport { QuestionDialog } from '../components/QuestionDialog.js';\nimport { Spinner } from '../components/Spinner.js';\n\ninterface AppProps {\n args: CliArgs;\n}\n\nexport const App: React.FC<AppProps> = ({ args }) => {\n const { exit } = useApp();\n const [started, setStarted] = useState(false);\n\n const {\n state,\n step,\n events,\n pendingConfirm,\n pendingQuestion,\n start,\n stop,\n pause,\n resume,\n respondConfirm,\n respondAnswer,\n } = useAgent({\n model: args.model,\n verbose: args.verbose,\n noConfirm: args.noConfirm,\n onFinished: () => {\n setTimeout(() => exit(), 500);\n },\n });\n\n useEffect(() => {\n if (!started) {\n setStarted(true);\n start(args.goal);\n }\n }, [started, start, args.goal]);\n\n useKeybindings({\n onPause: pause,\n onResume: resume,\n onStop: async () => {\n await stop();\n exit();\n },\n isPaused: state === 'paused',\n disabled: !!pendingConfirm || !!pendingQuestion,\n });\n\n const isTerminal = state === 'finished' || state === 'stopped' || state === 'error';\n\n return (\n <Box flexDirection=\"column\">\n <StatusBar state={state} step={step} goal={args.goal} />\n\n {/* Activity log */}\n <Box flexDirection=\"column\" marginTop={1}>\n <EventDisplay events={events} />\n\n {state === 'running' && (\n <Box>\n <Text dimColor>{' \\u2503 '}</Text>\n <Spinner />\n </Box>\n )}\n\n {state === 'paused' && (\n <Box>\n <Text dimColor>{' \\u2503 '}</Text>\n <Text color=\"yellow\" bold>{'\\u25AE\\u25AE'}</Text>\n <Text dimColor>{' paused \\u2014 space to resume'}</Text>\n </Box>\n )}\n </Box>\n\n {pendingConfirm && (\n <Box marginTop={1}>\n <ConfirmDialog reason={pendingConfirm} onConfirm={respondConfirm} />\n </Box>\n )}\n\n {pendingQuestion && (\n <Box marginTop={1}>\n <QuestionDialog question={pendingQuestion} onAnswer={respondAnswer} />\n </Box>\n )}\n\n {!isTerminal && !pendingConfirm && !pendingQuestion && (\n <Box marginTop={1}>\n <Text dimColor>{' space pause \\u00B7 q stop \\u00B7 ^c cancel'}</Text>\n </Box>\n )}\n </Box>\n );\n};\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { AgentDriver } from '@agi_inc/agi-js';\nimport type { DriverState, DriverAction, DriverResult } from '@agi_inc/agi-js';\nimport type { EventItem } from '../components/EventDisplay.js';\n\ninterface UseAgentOptions {\n model: string;\n agentName?: string;\n apiUrl?: string;\n verbose: boolean;\n noConfirm: boolean;\n onFinished?: (result: DriverResult) => void;\n}\n\ninterface UseAgentReturn {\n state: DriverState;\n step: number;\n events: EventItem[];\n pendingConfirm: string | null;\n pendingQuestion: string | null;\n start: (goal: string) => Promise<void>;\n stop: () => Promise<void>;\n pause: () => void;\n resume: () => void;\n respondConfirm: (approved: boolean) => void;\n respondAnswer: (answer: string) => void;\n}\n\nexport function useAgent(options: UseAgentOptions): UseAgentReturn {\n const { model, agentName, apiUrl, verbose, noConfirm, onFinished } = options;\n\n const [state, setState] = useState<DriverState>('idle');\n const [step, setStep] = useState(0);\n const [events, setEvents] = useState<EventItem[]>([]);\n const [pendingConfirm, setPendingConfirm] = useState<string | null>(null);\n const [pendingQuestion, setPendingQuestion] = useState<string | null>(null);\n\n const driverRef = useRef<AgentDriver | null>(null);\n\n const addEvent = useCallback((event: EventItem) => {\n setEvents((prev) => [...prev, event]);\n }, []);\n\n const start = useCallback(\n async (goal: string) => {\n const driver = new AgentDriver({ model, mode: 'local', agentName, apiUrl });\n driverRef.current = driver;\n\n // Set up event handlers\n driver.on('state_change', (newState: DriverState) => {\n setState(newState);\n });\n\n driver.on('thinking', (text: string) => {\n if (verbose) {\n addEvent({ type: 'thinking', text });\n }\n });\n\n driver.on('action', async (action: DriverAction) => {\n const actionStr = action.type + (action.x !== undefined ? ` (${action.x}, ${action.y})` : '');\n addEvent({ type: 'action', action: actionStr });\n // In local mode, the driver binary executes actions and captures screenshots\n });\n\n driver.on('confirm', async (reason: string) => {\n if (noConfirm) {\n driver.respondConfirm(true);\n return true;\n }\n addEvent({ type: 'confirm', reason });\n setPendingConfirm(reason);\n return true;\n });\n\n driver.on('ask_question', async (question: string) => {\n addEvent({ type: 'question', question });\n setPendingQuestion(question);\n return '';\n });\n\n driver.on('finished', (evt) => {\n addEvent({\n type: 'finished',\n summary: evt.summary,\n success: evt.success,\n });\n });\n\n driver.on('error', (evt) => {\n addEvent({ type: 'error', message: evt.message });\n });\n\n // Start the agent in local mode — no screenshot needed, driver handles it\n try {\n const result = await driver.start(goal);\n\n if (onFinished) {\n onFinished(result);\n }\n } catch (error) {\n addEvent({ type: 'error', message: String(error) });\n }\n },\n [model, agentName, apiUrl, verbose, noConfirm, addEvent, onFinished, state]\n );\n\n const stop = useCallback(async () => {\n if (driverRef.current) {\n await driverRef.current.stop('User cancelled');\n }\n }, []);\n\n const pause = useCallback(() => {\n if (driverRef.current) {\n driverRef.current.pause();\n }\n }, []);\n\n const resume = useCallback(() => {\n if (driverRef.current) {\n driverRef.current.resume();\n }\n }, []);\n\n const respondConfirm = useCallback((approved: boolean) => {\n if (driverRef.current && pendingConfirm) {\n driverRef.current.respondConfirm(approved);\n setPendingConfirm(null);\n }\n }, [pendingConfirm]);\n\n const respondAnswer = useCallback((answer: string) => {\n if (driverRef.current && pendingQuestion) {\n driverRef.current.respondAnswer(answer);\n setPendingQuestion(null);\n }\n }, [pendingQuestion]);\n\n // Update step from driver\n useEffect(() => {\n const interval = setInterval(() => {\n if (driverRef.current) {\n setStep(driverRef.current.currentStep);\n }\n }, 100);\n return () => clearInterval(interval);\n }, []);\n\n return {\n state,\n step,\n events,\n pendingConfirm,\n pendingQuestion,\n start,\n stop,\n pause,\n resume,\n respondConfirm,\n respondAnswer,\n };\n}\n","import { useInput } from 'ink';\nimport { useCallback } from 'react';\n\ninterface UseKeybindingsOptions {\n onPause?: () => void;\n onResume?: () => void;\n onStop?: () => void;\n isPaused?: boolean;\n disabled?: boolean;\n}\n\n/**\n * Hook for handling keyboard shortcuts.\n *\n * - Space: Pause/Resume\n * - Q/Ctrl+C: Stop\n * - Escape: Stop\n */\nexport function useKeybindings(options: UseKeybindingsOptions): void {\n const { onPause, onResume, onStop, isPaused = false, disabled = false } = options;\n\n const handleInput = useCallback(\n (input: string, key: { ctrl: boolean; escape: boolean }) => {\n if (disabled) return;\n\n // Space: Toggle pause/resume\n if (input === ' ') {\n if (isPaused) {\n onResume?.();\n } else {\n onPause?.();\n }\n }\n\n // Q or Ctrl+C: Stop\n if (input === 'q' || input === 'Q' || (key.ctrl && input === 'c')) {\n onStop?.();\n }\n\n // Escape: Stop\n if (key.escape) {\n onStop?.();\n }\n },\n [disabled, isPaused, onPause, onResume, onStop]\n );\n\n useInput(handleInput);\n}\n","import React from 'react';\nimport { Text, Box } from 'ink';\nimport type { DriverState } from '@agi_inc/agi-js';\n\ninterface StatusBarProps {\n state: DriverState;\n step: number;\n goal: string;\n}\n\nconst stateColors: Record<DriverState, string> = {\n idle: 'gray',\n running: 'green',\n paused: 'yellow',\n waiting_confirmation: 'yellow',\n waiting_answer: 'yellow',\n finished: 'green',\n stopped: 'gray',\n error: 'red',\n};\n\nconst stateLabels: Record<DriverState, string> = {\n idle: 'IDLE',\n running: 'ACTIVE',\n paused: 'PAUSED',\n waiting_confirmation: 'AWAITING',\n waiting_answer: 'AWAITING',\n finished: 'COMPLETE',\n stopped: 'STOPPED',\n error: 'ERROR',\n};\n\nconst stateIndicators: Record<DriverState, string> = {\n idle: '○',\n running: '●',\n paused: '◉',\n waiting_confirmation: '◎',\n waiting_answer: '◎',\n finished: '●',\n stopped: '○',\n error: '●',\n};\n\nexport const StatusBar: React.FC<StatusBarProps> = ({ state, step, goal }) => {\n const color = stateColors[state] || 'white';\n const label = stateLabels[state] || state.toUpperCase();\n const indicator = stateIndicators[state] || '○';\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"bold\" borderColor=\"gray\" paddingX={1}>\n <Box>\n <Text color=\"cyan\" bold>{'▸ AGI'}</Text>\n <Text>{' '}</Text>\n <Text color={color}>{indicator} </Text>\n <Text color={color} bold>{label}</Text>\n <Box flexGrow={1} />\n <Text dimColor>STEP </Text>\n <Text bold>{String(step).padStart(2, '0')}</Text>\n </Box>\n <Box>\n <Text dimColor>{goal.length > 72 ? goal.slice(0, 72) + '\\u2026' : goal}</Text>\n </Box>\n </Box>\n );\n};\n","import React from 'react';\nimport { Text, Box } from 'ink';\n\nexport type EventItem =\n | { type: 'thinking'; text: string }\n | { type: 'action'; action: string }\n | { type: 'confirm'; reason: string }\n | { type: 'question'; question: string }\n | { type: 'finished'; summary: string; success: boolean }\n | { type: 'error'; message: string };\n\ninterface EventDisplayProps {\n events: EventItem[];\n maxEvents?: number;\n}\n\nconst typeConfig: Record<string, { prefix: string; color: string }> = {\n thinking: { prefix: '\\u00B7', color: 'gray' },\n action: { prefix: '\\u25B8', color: 'white' },\n confirm: { prefix: '\\u25C6', color: 'yellow' },\n question: { prefix: '\\u25C7', color: 'cyan' },\n error: { prefix: '\\u2715', color: 'red' },\n};\n\nfunction getEventText(event: EventItem): string {\n switch (event.type) {\n case 'thinking':\n return event.text;\n case 'action':\n return event.action;\n case 'confirm':\n return event.reason;\n case 'question':\n return event.question;\n case 'finished':\n return event.summary;\n case 'error':\n return event.message;\n }\n}\n\nfunction getEventStyle(event: EventItem): { prefix: string; color: string } {\n if (event.type === 'finished') {\n return event.success\n ? { prefix: '\\u25CF', color: 'green' }\n : { prefix: '\\u2715', color: 'red' };\n }\n return typeConfig[event.type];\n}\n\nexport const EventDisplay: React.FC<EventDisplayProps> = ({ events, maxEvents = 12 }) => {\n const displayEvents = events.slice(-maxEvents);\n\n if (displayEvents.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\">\n {displayEvents.map((event, index) => {\n const style = getEventStyle(event);\n const text = getEventText(event);\n const isLatest = index === displayEvents.length - 1;\n\n return (\n <Box key={index}>\n <Text dimColor>{' \\u2503 '}</Text>\n <Text color={style.color}>{style.prefix} </Text>\n <Text\n color={style.color === 'white' ? undefined : style.color}\n bold={isLatest && event.type === 'action'}\n dimColor={event.type === 'thinking'}\n >\n {text}\n </Text>\n </Box>\n );\n })}\n </Box>\n );\n};\n","import React, { useState } from 'react';\nimport { Text, Box, useInput } from 'ink';\n\ninterface ConfirmDialogProps {\n reason: string;\n onConfirm: (approved: boolean) => void;\n}\n\nexport const ConfirmDialog: React.FC<ConfirmDialogProps> = ({ reason, onConfirm }) => {\n const [selected, setSelected] = useState<'yes' | 'no'>('yes');\n\n useInput((input, key) => {\n if (key.leftArrow || input === 'h') {\n setSelected('yes');\n } else if (key.rightArrow || input === 'l') {\n setSelected('no');\n } else if (key.return) {\n onConfirm(selected === 'yes');\n } else if (input === 'y' || input === 'Y') {\n onConfirm(true);\n } else if (input === 'n' || input === 'N') {\n onConfirm(false);\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"bold\" borderColor=\"yellow\" paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color=\"yellow\" bold>CONFIRM</Text>\n </Box>\n <Box marginBottom={1}>\n <Text>{reason}</Text>\n </Box>\n <Box>\n <Box marginRight={2}>\n <Text\n backgroundColor={selected === 'yes' ? 'green' : undefined}\n color={selected === 'yes' ? 'black' : 'gray'}\n bold={selected === 'yes'}\n >\n {' [Y] approve '}\n </Text>\n </Box>\n <Text\n backgroundColor={selected === 'no' ? 'red' : undefined}\n color={selected === 'no' ? 'black' : 'gray'}\n bold={selected === 'no'}\n >\n {' [N] deny '}\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Y/N or arrows + enter</Text>\n </Box>\n </Box>\n );\n};\n","import React, { useState } from 'react';\nimport { Text, Box, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface QuestionDialogProps {\n question: string;\n onAnswer: (answer: string) => void;\n}\n\nexport const QuestionDialog: React.FC<QuestionDialogProps> = ({ question, onAnswer }) => {\n const [answer, setAnswer] = useState('');\n\n const handleSubmit = () => {\n if (answer.trim()) {\n onAnswer(answer.trim());\n }\n };\n\n useInput((_, key) => {\n if (key.return && answer.trim()) {\n handleSubmit();\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"bold\" borderColor=\"cyan\" paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color=\"cyan\" bold>INPUT REQUIRED</Text>\n </Box>\n <Box marginBottom={1}>\n <Text>{question}</Text>\n </Box>\n <Box>\n <Text color=\"cyan\">{'\\u25B8 '}</Text>\n <TextInput\n value={answer}\n onChange={setAnswer}\n onSubmit={handleSubmit}\n placeholder=\"Type your answer...\"\n />\n </Box>\n <Box marginTop={1}>\n <Text dimColor>enter to submit</Text>\n </Box>\n </Box>\n );\n};\n","import React from 'react';\nimport { Text, Box } from 'ink';\nimport InkSpinner from 'ink-spinner';\n\ninterface SpinnerProps {\n text?: string;\n}\n\nexport const Spinner: React.FC<SpinnerProps> = ({ text }) => {\n return (\n <Box>\n <Text color=\"cyan\">\n <InkSpinner type=\"dots\" />\n </Text>\n {text && <Text dimColor> {text}</Text>}\n </Box>\n );\n};\n"],"mappings":"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","names":["React","yargs","React","useEffect","useState","Box","Text","useCallback","React","Text","Box","React","useState","Text","Box","useInput","React","useState","Text","Box","useInput","React","Text","Box","useState","useEffect","React","Box","Text","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/cli.ts","../src/config.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/update.ts","../src/app/App.tsx","../src/hooks/useAgent.ts","../src/hooks/useKeybindings.ts","../src/components/StatusBar.tsx","../src/components/EventDisplay.tsx","../src/components/ConfirmDialog.tsx","../src/components/QuestionDialog.tsx","../src/components/PromptInput.tsx","../src/components/Spinner.tsx"],"sourcesContent":["/**\n * AGI CLI - Terminal-based agent interaction for AGI desktop automation.\n *\n * Usage:\n * agi \"Open calculator and compute 2+2\"\n * agi \"Find flights from SFO to JFK\" --model claude-opus\n * agi \"Install Node.js\" --verbose\n * agi login\n * agi logout\n */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport { isBinaryAvailable } from '@agi_inc/agi-js';\nimport { parseArgs } from './cli.js';\nimport { App } from './app/App.js';\nimport { loadApiKey } from './config.js';\n\nasync function main(): Promise<void> {\n try {\n const result = await parseArgs();\n\n // login/logout subcommands are self-contained\n if (result.kind === 'handled') {\n return;\n }\n\n const { args } = result;\n\n // Check for API key\n const apiKey = loadApiKey();\n if (!apiKey) {\n console.error('Error: No API key found');\n console.error('');\n console.error('Run `agi login` to authenticate, or set an environment variable:');\n console.error(' export AGI_API_KEY=your_key');\n console.error('');\n process.exit(1);\n }\n\n // Make the key available to downstream code via env\n if (!process.env.AGI_API_KEY && !process.env.ANTHROPIC_API_KEY) {\n process.env.AGI_API_KEY = apiKey;\n }\n\n // Check for driver binary\n if (!isBinaryAvailable()) {\n console.error('Error: AGI driver binary not found');\n console.error('');\n console.error('The driver binary is required for local agent execution.');\n console.error('It should be installed automatically with the agi package.');\n console.error('');\n console.error('Try reinstalling: npm install -g @agi_inc/cli');\n console.error('');\n process.exit(1);\n }\n\n // Render the app\n const { waitUntilExit } = render(<App args={args} />);\n await waitUntilExit();\n } catch (error) {\n console.error('Error:', error);\n process.exit(1);\n }\n}\n\nmain();\n","/**\n * CLI argument parsing and configuration.\n */\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { loginCommand } from './commands/login.js';\nimport { logoutCommand } from './commands/logout.js';\nimport { updateCommand } from './commands/update.js';\n\nexport interface CliArgs {\n goal: string | undefined;\n model: string;\n verbose: boolean;\n noConfirm: boolean;\n}\n\nexport type ParseResult =\n | { kind: 'run'; args: CliArgs }\n | { kind: 'handled' };\n\nexport async function parseArgs(): Promise<ParseResult> {\n const argv = await yargs(hideBin(process.argv))\n .scriptName('agi')\n .command('login', 'Authenticate and save your API key', {}, async () => {\n await loginCommand();\n })\n .command('logout', 'Remove saved credentials', {}, async () => {\n await logoutCommand();\n })\n .command('update', 'Update AGI CLI to the latest version', {}, async () => {\n await updateCommand();\n })\n .command(\n '$0 [goal]',\n 'Run an agent with the given goal',\n (yargs) => {\n return yargs.positional('goal', {\n describe: 'The task for the agent to accomplish',\n type: 'string',\n demandOption: false,\n });\n },\n )\n .option('model', {\n alias: 'm',\n describe: 'Model to use',\n type: 'string',\n default: 'claude-sonnet',\n choices: ['claude-sonnet', 'claude-opus'],\n })\n .option('verbose', {\n alias: 'v',\n describe: 'Show verbose output including agent thinking',\n type: 'boolean',\n default: false,\n })\n .option('no-confirm', {\n describe: 'Auto-approve all confirmation requests',\n type: 'boolean',\n default: false,\n })\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'V')\n .example('$0 \"Open calculator and compute 2+2\"', 'Basic task')\n .example('$0 \"Find flights from SFO to JFK\" --model claude-opus', 'Use a specific model')\n .example('$0 \"Install Node.js\" --verbose', 'Verbose output')\n .example('$0', 'Start interactive mode')\n .example('$0 login', 'Authenticate with your API key')\n .example('$0 update', 'Update to the latest version')\n .parse();\n\n // If a subcommand (login/logout) was handled, yargs already ran its handler\n const command = argv._?.[0];\n if (command === 'login' || command === 'logout' || command === 'update') {\n return { kind: 'handled' };\n }\n\n return {\n kind: 'run',\n args: {\n goal: argv.goal as string | undefined,\n model: argv.model as string,\n verbose: argv.verbose as boolean,\n noConfirm: argv['no-confirm'] as boolean,\n },\n };\n}\n","/**\n * Credentials file management for AGI CLI.\n *\n * Checks AGI_API_KEY env -> ANTHROPIC_API_KEY env -> ~/.agi/credentials file.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\ninterface Credentials {\n api_key: string;\n}\n\nexport function getCredentialsPath(): string {\n return path.join(os.homedir(), '.agi', 'credentials');\n}\n\n/**\n * Load API key from environment variables or credentials file.\n * Priority: AGI_API_KEY env -> ANTHROPIC_API_KEY env -> ~/.agi/credentials\n */\nexport function loadApiKey(): string | undefined {\n if (process.env.AGI_API_KEY) {\n return process.env.AGI_API_KEY;\n }\n\n if (process.env.ANTHROPIC_API_KEY) {\n return process.env.ANTHROPIC_API_KEY;\n }\n\n const credPath = getCredentialsPath();\n try {\n const raw = fs.readFileSync(credPath, 'utf-8');\n const credentials: Credentials = JSON.parse(raw);\n if (credentials.api_key) {\n return credentials.api_key;\n }\n } catch {\n // File doesn't exist or is invalid\n }\n\n return undefined;\n}\n\n/**\n * Save API key to ~/.agi/credentials.\n * Creates the ~/.agi/ directory if it doesn't exist.\n */\nexport function saveApiKey(apiKey: string): void {\n const credPath = getCredentialsPath();\n const dir = path.dirname(credPath);\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n const credentials: Credentials = { api_key: apiKey };\n fs.writeFileSync(credPath, JSON.stringify(credentials, null, 2) + '\\n', {\n mode: 0o600,\n });\n}\n\n/**\n * Delete the credentials file.\n */\nexport function deleteCredentials(): boolean {\n const credPath = getCredentialsPath();\n try {\n fs.unlinkSync(credPath);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * `agi login` command — device code auth flow.\n *\n * 1. POST /v1/auth/device -> get device_code + user_code\n * 2. Open browser to verification_url\n * 3. Poll POST /v1/auth/device/token every 5s\n * 4. On approval -> save API key to ~/.agi/credentials\n */\n\nimport { saveApiKey } from '../config.js';\n\nconst API_BASE = 'https://api.agi.tech';\n\ninterface DeviceAuthResponse {\n device_code: string;\n user_code: string;\n verification_url: string;\n expires_in: number;\n interval: number;\n}\n\ninterface DeviceAuthTokenResponse {\n api_key: string;\n email: string | null;\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const open = (await import('open')).default;\n await open(url);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function loginCommand(): Promise<void> {\n // Step 1: Initiate device auth\n let deviceAuth: DeviceAuthResponse;\n try {\n const res = await fetch(`${API_BASE}/v1/auth/device`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n });\n\n if (!res.ok) {\n const detail = await res.text();\n console.error(`Failed to start login flow (${res.status}): ${detail}`);\n process.exit(1);\n }\n\n deviceAuth = (await res.json()) as DeviceAuthResponse;\n } catch (err) {\n console.error(`Failed to connect to AGI API: ${(err as Error).message}`);\n process.exit(1);\n }\n\n // Step 2: Show code and open browser\n console.log('');\n console.log(`Your confirmation code: ${deviceAuth.user_code}`);\n console.log('');\n console.log('Opening browser to authorize...');\n console.log(` ${deviceAuth.verification_url}`);\n console.log('');\n\n try {\n await openBrowser(deviceAuth.verification_url);\n } catch {\n console.log('Could not open browser automatically. Please visit the URL above.');\n }\n\n console.log('Waiting for authorization...');\n\n // Handle Ctrl+C gracefully during polling\n const sigintHandler = () => {\n console.log('\\nLogin cancelled.');\n process.exit(130);\n };\n process.on('SIGINT', sigintHandler);\n\n // Step 3: Poll for token\n const maxAttempts = Math.ceil(deviceAuth.expires_in / deviceAuth.interval);\n const interval = deviceAuth.interval * 1000;\n let consecutiveErrors = 0;\n\n try {\n for (let i = 0; i < maxAttempts; i++) {\n await sleep(interval);\n\n try {\n const res = await fetch(`${API_BASE}/v1/auth/device/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ device_code: deviceAuth.device_code }),\n });\n\n consecutiveErrors = 0;\n\n if (res.status === 428) {\n // Still pending\n process.stdout.write('.');\n continue;\n }\n\n if (res.status === 410) {\n console.log('');\n console.error('Login expired. Please run `agi login` again.');\n process.exit(1);\n }\n\n if (res.ok) {\n const token = (await res.json()) as DeviceAuthTokenResponse;\n console.log('');\n\n saveApiKey(token.api_key);\n\n const identity = token.email || 'your account';\n console.log(`Logged in as ${identity}`);\n console.log('Your API key has been saved to ~/.agi/credentials');\n return;\n }\n\n // Unexpected status\n const detail = await res.text();\n console.log('');\n console.error(`Unexpected response (${res.status}): ${detail}`);\n process.exit(1);\n } catch {\n consecutiveErrors++;\n if (consecutiveErrors >= 3) {\n console.log('');\n console.error('Unable to reach AGI API. Check your internet connection.');\n console.error('Retrying...');\n consecutiveErrors = 0;\n } else {\n process.stdout.write('!');\n }\n }\n }\n\n console.log('');\n console.error('Login timed out. Please run `agi login` again.');\n process.exit(1);\n } finally {\n process.removeListener('SIGINT', sigintHandler);\n }\n}\n","/**\n * `agi logout` command — remove stored credentials.\n */\n\nimport { deleteCredentials } from '../config.js';\n\nexport async function logoutCommand(): Promise<void> {\n const deleted = deleteCredentials();\n\n if (deleted) {\n console.log('Logged out. Credentials removed from ~/.agi/credentials');\n } else {\n console.log('No credentials file found. Already logged out.');\n }\n}\n","/**\n * Self-update command for AGI CLI.\n *\n * Checks the npm registry for the latest version, detects install method\n * (npm or Homebrew), and runs the appropriate update command.\n */\n\nimport { execSync } from 'node:child_process';\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nfunction getCurrentVersion(): string {\n // Resolve symlinks (npm global bin is a symlink to the package)\n const realScript = realpathSync(process.argv[1]);\n const pkgPath = join(dirname(realScript), '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version;\n}\n\nasync function getLatestVersion(): Promise<string> {\n const res = await fetch('https://registry.npmjs.org/@agi_inc/cli');\n if (!res.ok) {\n throw new Error(`npm registry returned ${res.status}`);\n }\n const data = (await res.json()) as { 'dist-tags': { latest: string } };\n return data['dist-tags'].latest;\n}\n\nfunction compareVersions(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n if ((pa[i] || 0) < (pb[i] || 0)) return -1;\n if ((pa[i] || 0) > (pb[i] || 0)) return 1;\n }\n return 0;\n}\n\nfunction detectInstallMethod(): 'npm' | 'homebrew' | 'unknown' {\n try {\n const agiPath = execSync('which agi', { encoding: 'utf-8' }).trim();\n if (agiPath.includes('homebrew') || agiPath.includes('Cellar')) {\n return 'homebrew';\n }\n return 'npm';\n } catch {\n return 'unknown';\n }\n}\n\nexport async function updateCommand(): Promise<void> {\n const current = getCurrentVersion();\n\n console.log('');\n console.log(` \\u25B8 AGI CLI v${current}`);\n console.log('');\n console.log(' Checking for updates...');\n\n try {\n const latest = await getLatestVersion();\n\n if (compareVersions(current, latest) >= 0) {\n console.log(` \\u25CF Up to date`);\n console.log('');\n return;\n }\n\n console.log(` Update available: ${current} \\u2192 ${latest}`);\n console.log('');\n\n const method = detectInstallMethod();\n\n if (method === 'homebrew') {\n console.log(' Updating via Homebrew...');\n console.log('');\n execSync('brew upgrade agi', { stdio: 'inherit' });\n } else {\n console.log(' Updating via npm...');\n console.log('');\n execSync('npm install -g @agi_inc/cli@latest', { stdio: 'inherit' });\n }\n\n console.log('');\n console.log(` \\u25CF Updated to v${latest}`);\n console.log('');\n } catch (error) {\n console.error('');\n console.error(` \\u2715 Update failed: ${error instanceof Error ? error.message : error}`);\n console.error('');\n console.error(' Try manually:');\n console.error(' npm install -g @agi_inc/cli@latest');\n console.error('');\n process.exit(1);\n }\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport type { CliArgs } from '../cli.js';\nimport { useAgent } from '../hooks/useAgent.js';\nimport { useKeybindings } from '../hooks/useKeybindings.js';\nimport { StatusBar } from '../components/StatusBar.js';\nimport { EventDisplay } from '../components/EventDisplay.js';\nimport { ConfirmDialog } from '../components/ConfirmDialog.js';\nimport { QuestionDialog } from '../components/QuestionDialog.js';\nimport { PromptInput } from '../components/PromptInput.js';\nimport { Spinner } from '../components/Spinner.js';\n\ninterface AppProps {\n args: CliArgs;\n}\n\ntype Phase = 'input' | 'executing';\n\nexport const App: React.FC<AppProps> = ({ args }) => {\n const { exit } = useApp();\n const [phase, setPhase] = useState<Phase>(args.goal ? 'executing' : 'input');\n const [currentGoal, setCurrentGoal] = useState(args.goal ?? '');\n\n const {\n state,\n step,\n events,\n pendingConfirm,\n pendingQuestion,\n start,\n stop,\n pause,\n resume,\n respondConfirm,\n respondAnswer,\n } = useAgent({\n model: args.model,\n verbose: args.verbose,\n noConfirm: args.noConfirm,\n onFinished: () => {\n setPhase('input');\n },\n });\n\n // Start executing when phase transitions to 'executing' with a goal\n useEffect(() => {\n if (phase === 'executing' && currentGoal) {\n start(currentGoal);\n }\n }, [phase, currentGoal, start]);\n\n const handleSubmitGoal = useCallback((goal: string) => {\n setCurrentGoal(goal);\n setPhase('executing');\n }, []);\n\n useKeybindings({\n onPause: pause,\n onResume: resume,\n onStop: async () => {\n if (phase === 'executing') {\n await stop();\n }\n exit();\n },\n isPaused: state === 'paused',\n disabled: phase === 'input' || !!pendingConfirm || !!pendingQuestion,\n });\n\n const isTerminal = state === 'finished' || state === 'stopped' || state === 'error';\n\n return (\n <Box flexDirection=\"column\">\n {/* Header: show interactive mode box when in input phase with no events */}\n {phase === 'input' && events.length === 0 && (\n <Box borderStyle=\"bold\" borderColor=\"gray\" paddingX={1}>\n <Text color=\"cyan\" bold>{'\\u25B8 AGI'}</Text>\n <Text>{' interactive mode'}</Text>\n </Box>\n )}\n\n {/* Status bar during execution */}\n {phase === 'executing' && (\n <StatusBar state={state} step={step} goal={currentGoal} />\n )}\n\n {/* Activity log */}\n <Box flexDirection=\"column\" marginTop={1}>\n <EventDisplay events={events} />\n\n {phase === 'executing' && state === 'running' && (\n <Box>\n <Text dimColor>{' \\u2503 '}</Text>\n <Spinner />\n </Box>\n )}\n\n {phase === 'executing' && state === 'paused' && (\n <Box>\n <Text dimColor>{' \\u2503 '}</Text>\n <Text color=\"yellow\" bold>{'\\u25AE\\u25AE'}</Text>\n <Text dimColor>{' paused \\u2014 space to resume'}</Text>\n </Box>\n )}\n </Box>\n\n {pendingConfirm && (\n <Box marginTop={1}>\n <ConfirmDialog reason={pendingConfirm} onConfirm={respondConfirm} />\n </Box>\n )}\n\n {pendingQuestion && (\n <Box marginTop={1}>\n <QuestionDialog question={pendingQuestion} onAnswer={respondAnswer} />\n </Box>\n )}\n\n {/* Prompt input when in input phase */}\n {phase === 'input' && (\n <Box marginTop={1}>\n <PromptInput onSubmit={handleSubmitGoal} />\n </Box>\n )}\n\n {/* Help bar: only during execution, not in terminal states or dialogs */}\n {phase === 'executing' && !isTerminal && !pendingConfirm && !pendingQuestion && (\n <Box marginTop={1}>\n <Text dimColor>{' space pause \\u00B7 q stop \\u00B7 ^c quit'}</Text>\n </Box>\n )}\n </Box>\n );\n};\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { AgentDriver } from '@agi_inc/agi-js';\nimport type { DriverState, DriverAction, DriverResult } from '@agi_inc/agi-js';\nimport type { EventItem } from '../components/EventDisplay.js';\n\ninterface UseAgentOptions {\n model: string;\n agentName?: string;\n apiUrl?: string;\n verbose: boolean;\n noConfirm: boolean;\n onFinished?: (result: DriverResult) => void;\n}\n\ninterface UseAgentReturn {\n state: DriverState;\n step: number;\n events: EventItem[];\n pendingConfirm: string | null;\n pendingQuestion: string | null;\n start: (goal: string) => Promise<void>;\n stop: () => Promise<void>;\n pause: () => void;\n resume: () => void;\n respondConfirm: (approved: boolean) => void;\n respondAnswer: (answer: string) => void;\n}\n\nexport function useAgent(options: UseAgentOptions): UseAgentReturn {\n const { model, agentName, apiUrl, verbose, noConfirm, onFinished } = options;\n\n const [state, setState] = useState<DriverState>('idle');\n const [step, setStep] = useState(0);\n const [events, setEvents] = useState<EventItem[]>([]);\n const [pendingConfirm, setPendingConfirm] = useState<string | null>(null);\n const [pendingQuestion, setPendingQuestion] = useState<string | null>(null);\n\n const driverRef = useRef<AgentDriver | null>(null);\n const onFinishedRef = useRef(onFinished);\n\n // Keep the ref up to date so start() never captures a stale callback\n useEffect(() => {\n onFinishedRef.current = onFinished;\n }, [onFinished]);\n\n const addEvent = useCallback((event: EventItem) => {\n setEvents((prev) => [...prev, event]);\n }, []);\n\n const start = useCallback(\n async (goal: string) => {\n // Stop previous driver if one exists\n if (driverRef.current) {\n try {\n await driverRef.current.stop('New task started');\n } catch {\n // Ignore errors from stopping previous driver\n }\n driverRef.current = null;\n }\n\n // Reset per-task state but keep events\n setState('idle');\n setStep(0);\n setPendingConfirm(null);\n setPendingQuestion(null);\n\n // Insert separator if there are already events from a previous task\n setEvents((prev) => {\n if (prev.length > 0) {\n return [...prev, { type: 'separator', goal }];\n }\n return prev;\n });\n\n const driver = new AgentDriver({ model, mode: 'local', agentName, apiUrl });\n driverRef.current = driver;\n\n // Set up event handlers\n driver.on('state_change', (newState: DriverState) => {\n setState(newState);\n });\n\n driver.on('thinking', (text: string) => {\n if (verbose) {\n addEvent({ type: 'thinking', text });\n }\n });\n\n driver.on('action', async (action: DriverAction) => {\n const actionStr = action.type + (action.x !== undefined ? ` (${action.x}, ${action.y})` : '');\n const parts: string[] = [];\n if (action.text) parts.push(`\"${action.text}\"`);\n if (action.key) parts.push(`[${action.key}]`);\n addEvent({ type: 'action', action: actionStr, params: parts.length ? parts.join(' ') : undefined });\n // In local mode, the driver binary executes actions and captures screenshots\n });\n\n driver.on('confirm', async (reason: string) => {\n if (noConfirm) {\n driver.respondConfirm(true);\n return true;\n }\n addEvent({ type: 'confirm', reason });\n setPendingConfirm(reason);\n return true;\n });\n\n driver.on('ask_question', async (question: string) => {\n addEvent({ type: 'question', question });\n setPendingQuestion(question);\n return '';\n });\n\n driver.on('finished', (evt) => {\n addEvent({\n type: 'finished',\n summary: evt.summary,\n success: evt.success,\n });\n });\n\n driver.on('error', (evt) => {\n addEvent({ type: 'error', message: evt.message });\n });\n\n // Start the agent in local mode — no screenshot needed, driver handles it\n try {\n const result = await driver.start(goal);\n\n if (onFinishedRef.current) {\n onFinishedRef.current(result);\n }\n } catch (error) {\n addEvent({ type: 'error', message: String(error) });\n }\n },\n [model, agentName, apiUrl, verbose, noConfirm, addEvent]\n );\n\n const stop = useCallback(async () => {\n if (driverRef.current) {\n await driverRef.current.stop('User cancelled');\n }\n }, []);\n\n const pause = useCallback(() => {\n if (driverRef.current) {\n driverRef.current.pause();\n }\n }, []);\n\n const resume = useCallback(() => {\n if (driverRef.current) {\n driverRef.current.resume();\n }\n }, []);\n\n const respondConfirm = useCallback((approved: boolean) => {\n if (driverRef.current && pendingConfirm) {\n driverRef.current.respondConfirm(approved);\n setPendingConfirm(null);\n }\n }, [pendingConfirm]);\n\n const respondAnswer = useCallback((answer: string) => {\n if (driverRef.current && pendingQuestion) {\n driverRef.current.respondAnswer(answer);\n setPendingQuestion(null);\n }\n }, [pendingQuestion]);\n\n // Update step from driver\n useEffect(() => {\n const interval = setInterval(() => {\n if (driverRef.current) {\n setStep(driverRef.current.currentStep);\n }\n }, 100);\n return () => clearInterval(interval);\n }, []);\n\n return {\n state,\n step,\n events,\n pendingConfirm,\n pendingQuestion,\n start,\n stop,\n pause,\n resume,\n respondConfirm,\n respondAnswer,\n };\n}\n","import { useInput } from 'ink';\nimport { useCallback } from 'react';\n\ninterface UseKeybindingsOptions {\n onPause?: () => void;\n onResume?: () => void;\n onStop?: () => void;\n isPaused?: boolean;\n disabled?: boolean;\n}\n\n/**\n * Hook for handling keyboard shortcuts.\n *\n * - Space: Pause/Resume\n * - Q/Ctrl+C: Stop\n * - Escape: Stop\n */\nexport function useKeybindings(options: UseKeybindingsOptions): void {\n const { onPause, onResume, onStop, isPaused = false, disabled = false } = options;\n\n const handleInput = useCallback(\n (input: string, key: { ctrl: boolean; escape: boolean }) => {\n if (disabled) return;\n\n // Space: Toggle pause/resume\n if (input === ' ') {\n if (isPaused) {\n onResume?.();\n } else {\n onPause?.();\n }\n }\n\n // Q or Ctrl+C: Stop\n if (input === 'q' || input === 'Q' || (key.ctrl && input === 'c')) {\n onStop?.();\n }\n\n // Escape: Stop\n if (key.escape) {\n onStop?.();\n }\n },\n [disabled, isPaused, onPause, onResume, onStop]\n );\n\n useInput(handleInput);\n}\n","import React from 'react';\nimport { Text, Box } from 'ink';\nimport type { DriverState } from '@agi_inc/agi-js';\n\ninterface StatusBarProps {\n state: DriverState;\n step: number;\n goal: string;\n}\n\nconst stateColors: Record<DriverState, string> = {\n idle: 'gray',\n running: 'green',\n paused: 'yellow',\n waiting_confirmation: 'yellow',\n waiting_answer: 'yellow',\n finished: 'green',\n stopped: 'gray',\n error: 'red',\n};\n\nconst stateLabels: Record<DriverState, string> = {\n idle: 'IDLE',\n running: 'ACTIVE',\n paused: 'PAUSED',\n waiting_confirmation: 'AWAITING',\n waiting_answer: 'AWAITING',\n finished: 'COMPLETE',\n stopped: 'STOPPED',\n error: 'ERROR',\n};\n\nconst stateIndicators: Record<DriverState, string> = {\n idle: '○',\n running: '●',\n paused: '◉',\n waiting_confirmation: '◎',\n waiting_answer: '◎',\n finished: '●',\n stopped: '○',\n error: '●',\n};\n\nexport const StatusBar: React.FC<StatusBarProps> = ({ state, step, goal }) => {\n const color = stateColors[state] || 'white';\n const label = stateLabels[state] || state.toUpperCase();\n const indicator = stateIndicators[state] || '○';\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"bold\" borderColor=\"gray\" paddingX={1}>\n <Box>\n <Text color=\"cyan\" bold>{'▸ AGI'}</Text>\n <Text>{' '}</Text>\n <Text color={color}>{indicator} </Text>\n <Text color={color} bold>{label}</Text>\n <Box flexGrow={1} />\n <Text dimColor>STEP </Text>\n <Text bold>{String(step).padStart(2, '0')}</Text>\n </Box>\n <Box>\n <Text dimColor>{goal.length > 72 ? goal.slice(0, 72) + '\\u2026' : goal}</Text>\n </Box>\n </Box>\n );\n};\n","import React from 'react';\nimport { Text, Box } from 'ink';\n\nexport type EventItem =\n | { type: 'thinking'; text: string }\n | { type: 'action'; action: string; params?: string }\n | { type: 'confirm'; reason: string }\n | { type: 'question'; question: string }\n | { type: 'finished'; summary: string; success: boolean }\n | { type: 'error'; message: string }\n | { type: 'separator'; goal: string };\n\ninterface EventDisplayProps {\n events: EventItem[];\n maxEvents?: number;\n}\n\nconst typeConfig: Record<string, { prefix: string; color: string }> = {\n thinking: { prefix: '\\u00B7', color: 'gray' },\n action: { prefix: '\\u25B8', color: 'white' },\n confirm: { prefix: '\\u25C6', color: 'yellow' },\n question: { prefix: '\\u25C7', color: 'cyan' },\n error: { prefix: '\\u2715', color: 'red' },\n};\n\nfunction getEventText(event: EventItem): string {\n switch (event.type) {\n case 'thinking':\n return event.text;\n case 'action':\n return event.action;\n case 'confirm':\n return event.reason;\n case 'question':\n return event.question;\n case 'finished':\n return event.summary;\n case 'error':\n return event.message;\n case 'separator':\n return event.goal;\n }\n}\n\nfunction getEventStyle(event: EventItem): { prefix: string; color: string } {\n if (event.type === 'finished') {\n return event.success\n ? { prefix: '\\u25CF', color: 'green' }\n : { prefix: '\\u2715', color: 'red' };\n }\n return typeConfig[event.type];\n}\n\nexport const EventDisplay: React.FC<EventDisplayProps> = ({ events, maxEvents = 12 }) => {\n const displayEvents = events.slice(-maxEvents);\n\n if (displayEvents.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\">\n {displayEvents.map((event, index) => {\n if (event.type === 'separator') {\n return (\n <Box key={index} marginTop={1}>\n <Text dimColor>{' \\u2500\\u2500 '}</Text>\n <Text bold>{event.goal}</Text>\n <Text dimColor>{' \\u2500\\u2500'}</Text>\n </Box>\n );\n }\n\n const style = getEventStyle(event);\n const text = getEventText(event);\n const isLatest = index === displayEvents.length - 1;\n\n return (\n <Box key={index}>\n <Text dimColor>{' \\u2503 '}</Text>\n <Text color={style.color}>{style.prefix} </Text>\n <Text\n color={style.color === 'white' ? undefined : style.color}\n bold={isLatest && event.type === 'action'}\n dimColor={event.type === 'thinking'}\n >\n {text}\n </Text>\n {event.type === 'action' && event.params && (\n <Text color=\"gray\">{' '}{event.params}</Text>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n","import React, { useState } from 'react';\nimport { Text, Box, useInput } from 'ink';\n\ninterface ConfirmDialogProps {\n reason: string;\n onConfirm: (approved: boolean) => void;\n}\n\nexport const ConfirmDialog: React.FC<ConfirmDialogProps> = ({ reason, onConfirm }) => {\n const [selected, setSelected] = useState<'yes' | 'no'>('yes');\n\n useInput((input, key) => {\n if (key.leftArrow || input === 'h') {\n setSelected('yes');\n } else if (key.rightArrow || input === 'l') {\n setSelected('no');\n } else if (key.return) {\n onConfirm(selected === 'yes');\n } else if (input === 'y' || input === 'Y') {\n onConfirm(true);\n } else if (input === 'n' || input === 'N') {\n onConfirm(false);\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"bold\" borderColor=\"yellow\" paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color=\"yellow\" bold>CONFIRM</Text>\n </Box>\n <Box marginBottom={1}>\n <Text>{reason}</Text>\n </Box>\n <Box>\n <Box marginRight={2}>\n <Text\n backgroundColor={selected === 'yes' ? 'green' : undefined}\n color={selected === 'yes' ? 'black' : 'gray'}\n bold={selected === 'yes'}\n >\n {' [Y] approve '}\n </Text>\n </Box>\n <Text\n backgroundColor={selected === 'no' ? 'red' : undefined}\n color={selected === 'no' ? 'black' : 'gray'}\n bold={selected === 'no'}\n >\n {' [N] deny '}\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Y/N or arrows + enter</Text>\n </Box>\n </Box>\n );\n};\n","import React, { useState } from 'react';\nimport { Text, Box, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface QuestionDialogProps {\n question: string;\n onAnswer: (answer: string) => void;\n}\n\nexport const QuestionDialog: React.FC<QuestionDialogProps> = ({ question, onAnswer }) => {\n const [answer, setAnswer] = useState('');\n\n const handleSubmit = () => {\n if (answer.trim()) {\n onAnswer(answer.trim());\n }\n };\n\n useInput((_, key) => {\n if (key.return && answer.trim()) {\n handleSubmit();\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"bold\" borderColor=\"cyan\" paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color=\"cyan\" bold>INPUT REQUIRED</Text>\n </Box>\n <Box marginBottom={1}>\n <Text>{question}</Text>\n </Box>\n <Box>\n <Text color=\"cyan\">{'\\u25B8 '}</Text>\n <TextInput\n value={answer}\n onChange={setAnswer}\n onSubmit={handleSubmit}\n placeholder=\"Type your answer...\"\n />\n </Box>\n <Box marginTop={1}>\n <Text dimColor>enter to submit</Text>\n </Box>\n </Box>\n );\n};\n","import React, { useState } from 'react';\nimport { Text, Box } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface PromptInputProps {\n onSubmit: (goal: string) => void;\n}\n\nexport const PromptInput: React.FC<PromptInputProps> = ({ onSubmit }) => {\n const [value, setValue] = useState('');\n\n const handleSubmit = () => {\n const trimmed = value.trim();\n if (trimmed) {\n onSubmit(trimmed);\n setValue('');\n }\n };\n\n return (\n <Box>\n <Text color=\"cyan\" bold>{'\\u25B8 '}</Text>\n <TextInput\n value={value}\n onChange={setValue}\n onSubmit={handleSubmit}\n placeholder=\"Enter a task...\"\n />\n </Box>\n );\n};\n","import React from 'react';\nimport { Text, Box } from 'ink';\nimport InkSpinner from 'ink-spinner';\n\ninterface SpinnerProps {\n text?: string;\n}\n\nexport const Spinner: React.FC<SpinnerProps> = ({ text }) => {\n return (\n <Box>\n <Text color=\"cyan\">\n <InkSpinner type=\"dots\" />\n </Text>\n {text && <Text dimColor> {text}</Text>}\n </Box>\n );\n};\n"],"mappings":";AAWA,OAAOA,YAAW;AAClB,SAAS,cAAc;AACvB,SAAS,yBAAyB;;;ACTlC,OAAO,WAAW;AAClB,SAAS,eAAe;;;ACCxB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAMR,SAAS,qBAA6B;AAC3C,SAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ,aAAa;AACtD;AAMO,SAAS,aAAiC;AAC/C,MAAI,QAAQ,IAAI,aAAa;AAC3B,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,QAAM,WAAW,mBAAmB;AACpC,MAAI;AACF,UAAM,MAAM,GAAG,aAAa,UAAU,OAAO;AAC7C,UAAM,cAA2B,KAAK,MAAM,GAAG;AAC/C,QAAI,YAAY,SAAS;AACvB,aAAO,YAAY;AAAA,IACrB;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAMO,SAAS,WAAW,QAAsB;AAC/C,QAAM,WAAW,mBAAmB;AACpC,QAAM,MAAM,KAAK,QAAQ,QAAQ;AAEjC,MAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,OAAG,UAAU,KAAK,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAAA,EACpD;AAEA,QAAM,cAA2B,EAAE,SAAS,OAAO;AACnD,KAAG,cAAc,UAAU,KAAK,UAAU,aAAa,MAAM,CAAC,IAAI,MAAM;AAAA,IACtE,MAAM;AAAA,EACR,CAAC;AACH;AAKO,SAAS,oBAA6B;AAC3C,QAAM,WAAW,mBAAmB;AACpC,MAAI;AACF,OAAG,WAAW,QAAQ;AACtB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC/DA,IAAM,WAAW;AAejB,eAAe,YAAY,KAA4B;AACrD,QAAM,QAAQ,MAAM,OAAO,MAAM,GAAG;AACpC,QAAM,KAAK,GAAG;AAChB;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,eAAsB,eAA8B;AAElD,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,mBAAmB;AAAA,MACpD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAChD,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,cAAQ,MAAM,+BAA+B,IAAI,MAAM,MAAM,MAAM,EAAE;AACrE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,iBAAc,MAAM,IAAI,KAAK;AAAA,EAC/B,SAAS,KAAK;AACZ,YAAQ,MAAM,iCAAkC,IAAc,OAAO,EAAE;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,2BAA2B,WAAW,SAAS,EAAE;AAC7D,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,iCAAiC;AAC7C,UAAQ,IAAI,KAAK,WAAW,gBAAgB,EAAE;AAC9C,UAAQ,IAAI,EAAE;AAEd,MAAI;AACF,UAAM,YAAY,WAAW,gBAAgB;AAAA,EAC/C,QAAQ;AACN,YAAQ,IAAI,mEAAmE;AAAA,EACjF;AAEA,UAAQ,IAAI,8BAA8B;AAG1C,QAAM,gBAAgB,MAAM;AAC1B,YAAQ,IAAI,oBAAoB;AAChC,YAAQ,KAAK,GAAG;AAAA,EAClB;AACA,UAAQ,GAAG,UAAU,aAAa;AAGlC,QAAM,cAAc,KAAK,KAAK,WAAW,aAAa,WAAW,QAAQ;AACzE,QAAM,WAAW,WAAW,WAAW;AACvC,MAAI,oBAAoB;AAExB,MAAI;AACF,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,YAAM,MAAM,QAAQ;AAEpB,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,yBAAyB;AAAA,UAC1D,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,EAAE,aAAa,WAAW,YAAY,CAAC;AAAA,QAC9D,CAAC;AAED,4BAAoB;AAEpB,YAAI,IAAI,WAAW,KAAK;AAEtB,kBAAQ,OAAO,MAAM,GAAG;AACxB;AAAA,QACF;AAEA,YAAI,IAAI,WAAW,KAAK;AACtB,kBAAQ,IAAI,EAAE;AACd,kBAAQ,MAAM,8CAA8C;AAC5D,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAEA,YAAI,IAAI,IAAI;AACV,gBAAM,QAAS,MAAM,IAAI,KAAK;AAC9B,kBAAQ,IAAI,EAAE;AAEd,qBAAW,MAAM,OAAO;AAExB,gBAAM,WAAW,MAAM,SAAS;AAChC,kBAAQ,IAAI,gBAAgB,QAAQ,EAAE;AACtC,kBAAQ,IAAI,mDAAmD;AAC/D;AAAA,QACF;AAGA,cAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,gBAAQ,IAAI,EAAE;AACd,gBAAQ,MAAM,wBAAwB,IAAI,MAAM,MAAM,MAAM,EAAE;AAC9D,gBAAQ,KAAK,CAAC;AAAA,MAChB,QAAQ;AACN;AACA,YAAI,qBAAqB,GAAG;AAC1B,kBAAQ,IAAI,EAAE;AACd,kBAAQ,MAAM,0DAA0D;AACxE,kBAAQ,MAAM,aAAa;AAC3B,8BAAoB;AAAA,QACtB,OAAO;AACL,kBAAQ,OAAO,MAAM,GAAG;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,MAAM,gDAAgD;AAC9D,YAAQ,KAAK,CAAC;AAAA,EAChB,UAAE;AACA,YAAQ,eAAe,UAAU,aAAa;AAAA,EAChD;AACF;;;AC3IA,eAAsB,gBAA+B;AACnD,QAAM,UAAU,kBAAkB;AAElC,MAAI,SAAS;AACX,YAAQ,IAAI,yDAAyD;AAAA,EACvE,OAAO;AACL,YAAQ,IAAI,gDAAgD;AAAA,EAC9D;AACF;;;ACPA,SAAS,gBAAgB;AACzB,SAAS,cAAc,oBAAoB;AAC3C,SAAS,SAAS,YAAY;AAE9B,SAAS,oBAA4B;AAEnC,QAAM,aAAa,aAAa,QAAQ,KAAK,CAAC,CAAC;AAC/C,QAAM,UAAU,KAAK,QAAQ,UAAU,GAAG,MAAM,cAAc;AAC9D,QAAM,MAAM,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC;AACrD,SAAO,IAAI;AACb;AAEA,eAAe,mBAAoC;AACjD,QAAM,MAAM,MAAM,MAAM,yCAAyC;AACjE,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,yBAAyB,IAAI,MAAM,EAAE;AAAA,EACvD;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,SAAO,KAAK,WAAW,EAAE;AAC3B;AAEA,SAAS,gBAAgB,GAAW,GAAmB;AACrD,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAClC,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAClC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,SAAK,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,KAAK,GAAI,QAAO;AACxC,SAAK,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,KAAK,GAAI,QAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAEA,SAAS,sBAAsD;AAC7D,MAAI;AACF,UAAM,UAAU,SAAS,aAAa,EAAE,UAAU,QAAQ,CAAC,EAAE,KAAK;AAClE,QAAI,QAAQ,SAAS,UAAU,KAAK,QAAQ,SAAS,QAAQ,GAAG;AAC9D,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBAA+B;AACnD,QAAM,UAAU,kBAAkB;AAElC,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,qBAAqB,OAAO,EAAE;AAC1C,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,2BAA2B;AAEvC,MAAI;AACF,UAAM,SAAS,MAAM,iBAAiB;AAEtC,QAAI,gBAAgB,SAAS,MAAM,KAAK,GAAG;AACzC,cAAQ,IAAI,qBAAqB;AACjC,cAAQ,IAAI,EAAE;AACd;AAAA,IACF;AAEA,YAAQ,IAAI,uBAAuB,OAAO,WAAW,MAAM,EAAE;AAC7D,YAAQ,IAAI,EAAE;AAEd,UAAM,SAAS,oBAAoB;AAEnC,QAAI,WAAW,YAAY;AACzB,cAAQ,IAAI,4BAA4B;AACxC,cAAQ,IAAI,EAAE;AACd,eAAS,oBAAoB,EAAE,OAAO,UAAU,CAAC;AAAA,IACnD,OAAO;AACL,cAAQ,IAAI,uBAAuB;AACnC,cAAQ,IAAI,EAAE;AACd,eAAS,sCAAsC,EAAE,OAAO,UAAU,CAAC;AAAA,IACrE;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,wBAAwB,MAAM,EAAE;AAC5C,YAAQ,IAAI,EAAE;AAAA,EAChB,SAAS,OAAO;AACd,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,KAAK,EAAE;AACzF,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,iBAAiB;AAC/B,YAAQ,MAAM,wCAAwC;AACtD,YAAQ,MAAM,EAAE;AAChB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AJzEA,eAAsB,YAAkC;AACtD,QAAM,OAAO,MAAM,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAC3C,WAAW,KAAK,EAChB,QAAQ,SAAS,sCAAsC,CAAC,GAAG,YAAY;AACtE,UAAM,aAAa;AAAA,EACrB,CAAC,EACA,QAAQ,UAAU,4BAA4B,CAAC,GAAG,YAAY;AAC7D,UAAM,cAAc;AAAA,EACtB,CAAC,EACA,QAAQ,UAAU,wCAAwC,CAAC,GAAG,YAAY;AACzE,UAAM,cAAc;AAAA,EACtB,CAAC,EACA;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAACC,WAAU;AACT,aAAOA,OAAM,WAAW,QAAQ;AAAA,QAC9B,UAAU;AAAA,QACV,MAAM;AAAA,QACN,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF,EACC,OAAO,SAAS;AAAA,IACf,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,CAAC,iBAAiB,aAAa;AAAA,EAC1C,CAAC,EACA,OAAO,WAAW;AAAA,IACjB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC,EACA,OAAO,cAAc;AAAA,IACpB,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC,EACA,KAAK,EACL,MAAM,QAAQ,GAAG,EACjB,QAAQ,EACR,MAAM,WAAW,GAAG,EACpB,QAAQ,wCAAwC,YAAY,EAC5D,QAAQ,yDAAyD,sBAAsB,EACvF,QAAQ,kCAAkC,gBAAgB,EAC1D,QAAQ,MAAM,wBAAwB,EACtC,QAAQ,YAAY,gCAAgC,EACpD,QAAQ,aAAa,8BAA8B,EACnD,MAAM;AAGT,QAAM,UAAU,KAAK,IAAI,CAAC;AAC1B,MAAI,YAAY,WAAW,YAAY,YAAY,YAAY,UAAU;AACvE,WAAO,EAAE,MAAM,UAAU;AAAA,EAC3B;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,WAAW,KAAK,YAAY;AAAA,IAC9B;AAAA,EACF;AACF;;;AKzFA,OAAOC,UAAS,aAAAC,YAAW,YAAAC,WAAU,eAAAC,oBAAmB;AACxD,SAAS,OAAAC,MAAK,QAAAC,OAAM,cAAc;;;ACDlC,SAAS,UAAU,aAAa,QAAQ,iBAAiB;AACzD,SAAS,mBAAmB;AA2BrB,SAAS,SAAS,SAA0C;AACjE,QAAM,EAAE,OAAO,WAAW,QAAQ,SAAS,WAAW,WAAW,IAAI;AAErE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAsB,MAAM;AACtD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,CAAC;AAClC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAsB,CAAC,CAAC;AACpD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB,IAAI;AACxE,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAwB,IAAI;AAE1E,QAAM,YAAY,OAA2B,IAAI;AACjD,QAAM,gBAAgB,OAAO,UAAU;AAGvC,YAAU,MAAM;AACd,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,WAAW,YAAY,CAAC,UAAqB;AACjD,cAAU,CAAC,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,EACtC,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ;AAAA,IACZ,OAAO,SAAiB;AAEtB,UAAI,UAAU,SAAS;AACrB,YAAI;AACF,gBAAM,UAAU,QAAQ,KAAK,kBAAkB;AAAA,QACjD,QAAQ;AAAA,QAER;AACA,kBAAU,UAAU;AAAA,MACtB;AAGA,eAAS,MAAM;AACf,cAAQ,CAAC;AACT,wBAAkB,IAAI;AACtB,yBAAmB,IAAI;AAGvB,gBAAU,CAAC,SAAS;AAClB,YAAI,KAAK,SAAS,GAAG;AACnB,iBAAO,CAAC,GAAG,MAAM,EAAE,MAAM,aAAa,KAAK,CAAC;AAAA,QAC9C;AACA,eAAO;AAAA,MACT,CAAC;AAED,YAAM,SAAS,IAAI,YAAY,EAAE,OAAO,MAAM,SAAS,WAAW,OAAO,CAAC;AAC1E,gBAAU,UAAU;AAGpB,aAAO,GAAG,gBAAgB,CAAC,aAA0B;AACnD,iBAAS,QAAQ;AAAA,MACnB,CAAC;AAED,aAAO,GAAG,YAAY,CAAC,SAAiB;AACtC,YAAI,SAAS;AACX,mBAAS,EAAE,MAAM,YAAY,KAAK,CAAC;AAAA,QACrC;AAAA,MACF,CAAC;AAED,aAAO,GAAG,UAAU,OAAO,WAAyB;AAClD,cAAM,YAAY,OAAO,QAAQ,OAAO,MAAM,SAAY,KAAK,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM;AAC1F,cAAM,QAAkB,CAAC;AACzB,YAAI,OAAO,KAAM,OAAM,KAAK,IAAI,OAAO,IAAI,GAAG;AAC9C,YAAI,OAAO,IAAK,OAAM,KAAK,IAAI,OAAO,GAAG,GAAG;AAC5C,iBAAS,EAAE,MAAM,UAAU,QAAQ,WAAW,QAAQ,MAAM,SAAS,MAAM,KAAK,GAAG,IAAI,OAAU,CAAC;AAAA,MAEpG,CAAC;AAED,aAAO,GAAG,WAAW,OAAO,WAAmB;AAC7C,YAAI,WAAW;AACb,iBAAO,eAAe,IAAI;AAC1B,iBAAO;AAAA,QACT;AACA,iBAAS,EAAE,MAAM,WAAW,OAAO,CAAC;AACpC,0BAAkB,MAAM;AACxB,eAAO;AAAA,MACT,CAAC;AAED,aAAO,GAAG,gBAAgB,OAAO,aAAqB;AACpD,iBAAS,EAAE,MAAM,YAAY,SAAS,CAAC;AACvC,2BAAmB,QAAQ;AAC3B,eAAO;AAAA,MACT,CAAC;AAED,aAAO,GAAG,YAAY,CAAC,QAAQ;AAC7B,iBAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS,IAAI;AAAA,UACb,SAAS,IAAI;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAED,aAAO,GAAG,SAAS,CAAC,QAAQ;AAC1B,iBAAS,EAAE,MAAM,SAAS,SAAS,IAAI,QAAQ,CAAC;AAAA,MAClD,CAAC;AAGD,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM,IAAI;AAEtC,YAAI,cAAc,SAAS;AACzB,wBAAc,QAAQ,MAAM;AAAA,QAC9B;AAAA,MACF,SAAS,OAAO;AACd,iBAAS,EAAE,MAAM,SAAS,SAAS,OAAO,KAAK,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,IACA,CAAC,OAAO,WAAW,QAAQ,SAAS,WAAW,QAAQ;AAAA,EACzD;AAEA,QAAM,OAAO,YAAY,YAAY;AACnC,QAAI,UAAU,SAAS;AACrB,YAAM,UAAU,QAAQ,KAAK,gBAAgB;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ,YAAY,MAAM;AAC9B,QAAI,UAAU,SAAS;AACrB,gBAAU,QAAQ,MAAM;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,YAAY,MAAM;AAC/B,QAAI,UAAU,SAAS;AACrB,gBAAU,QAAQ,OAAO;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiB,YAAY,CAAC,aAAsB;AACxD,QAAI,UAAU,WAAW,gBAAgB;AACvC,gBAAU,QAAQ,eAAe,QAAQ;AACzC,wBAAkB,IAAI;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,gBAAgB,YAAY,CAAC,WAAmB;AACpD,QAAI,UAAU,WAAW,iBAAiB;AACxC,gBAAU,QAAQ,cAAc,MAAM;AACtC,yBAAmB,IAAI;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,eAAe,CAAC;AAGpB,YAAU,MAAM;AACd,UAAM,WAAW,YAAY,MAAM;AACjC,UAAI,UAAU,SAAS;AACrB,gBAAQ,UAAU,QAAQ,WAAW;AAAA,MACvC;AAAA,IACF,GAAG,GAAG;AACN,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACnMA,SAAS,gBAAgB;AACzB,SAAS,eAAAC,oBAAmB;AAiBrB,SAAS,eAAe,SAAsC;AACnE,QAAM,EAAE,SAAS,UAAU,QAAQ,WAAW,OAAO,WAAW,MAAM,IAAI;AAE1E,QAAM,cAAcA;AAAA,IAClB,CAAC,OAAe,QAA4C;AAC1D,UAAI,SAAU;AAGd,UAAI,UAAU,KAAK;AACjB,YAAI,UAAU;AACZ,qBAAW;AAAA,QACb,OAAO;AACL,oBAAU;AAAA,QACZ;AAAA,MACF;AAGA,UAAI,UAAU,OAAO,UAAU,OAAQ,IAAI,QAAQ,UAAU,KAAM;AACjE,iBAAS;AAAA,MACX;AAGA,UAAI,IAAI,QAAQ;AACd,iBAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,CAAC,UAAU,UAAU,SAAS,UAAU,MAAM;AAAA,EAChD;AAEA,WAAS,WAAW;AACtB;;;AChDA,OAAO,WAAW;AAClB,SAAS,MAAM,WAAW;AAS1B,IAAM,cAA2C;AAAA,EAC/C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AACT;AAEA,IAAM,cAA2C;AAAA,EAC/C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AACT;AAEA,IAAM,kBAA+C;AAAA,EACnD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AACT;AAEO,IAAM,YAAsC,CAAC,EAAE,OAAO,MAAM,KAAK,MAAM;AAC5E,QAAM,QAAQ,YAAY,KAAK,KAAK;AACpC,QAAM,QAAQ,YAAY,KAAK,KAAK,MAAM,YAAY;AACtD,QAAM,YAAY,gBAAgB,KAAK,KAAK;AAE5C,SACE,oCAAC,OAAI,eAAc,UAAS,aAAY,QAAO,aAAY,QAAO,UAAU,KAC1E,oCAAC,WACC,oCAAC,QAAK,OAAM,QAAO,MAAI,QAAE,YAAQ,GACjC,oCAAC,YAAM,KAAM,GACb,oCAAC,QAAK,SAAe,WAAU,GAAC,GAChC,oCAAC,QAAK,OAAc,MAAI,QAAE,KAAM,GAChC,oCAAC,OAAI,UAAU,GAAG,GAClB,oCAAC,QAAK,UAAQ,QAAC,OAAK,GACpB,oCAAC,QAAK,MAAI,QAAE,OAAO,IAAI,EAAE,SAAS,GAAG,GAAG,CAAE,CAC5C,GACA,oCAAC,WACC,oCAAC,QAAK,UAAQ,QAAE,KAAK,SAAS,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,WAAW,IAAK,CACzE,CACF;AAEJ;;;AChEA,OAAOC,YAAW;AAClB,SAAS,QAAAC,OAAM,OAAAC,YAAW;AAgB1B,IAAM,aAAgE;AAAA,EACpE,UAAU,EAAE,QAAQ,QAAU,OAAO,OAAO;AAAA,EAC5C,QAAQ,EAAE,QAAQ,UAAU,OAAO,QAAQ;AAAA,EAC3C,SAAS,EAAE,QAAQ,UAAU,OAAO,SAAS;AAAA,EAC7C,UAAU,EAAE,QAAQ,UAAU,OAAO,OAAO;AAAA,EAC5C,OAAO,EAAE,QAAQ,UAAU,OAAO,MAAM;AAC1C;AAEA,SAAS,aAAa,OAA0B;AAC9C,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,EACjB;AACF;AAEA,SAAS,cAAc,OAAqD;AAC1E,MAAI,MAAM,SAAS,YAAY;AAC7B,WAAO,MAAM,UACT,EAAE,QAAQ,UAAU,OAAO,QAAQ,IACnC,EAAE,QAAQ,UAAU,OAAO,MAAM;AAAA,EACvC;AACA,SAAO,WAAW,MAAM,IAAI;AAC9B;AAEO,IAAM,eAA4C,CAAC,EAAE,QAAQ,YAAY,GAAG,MAAM;AACvF,QAAM,gBAAgB,OAAO,MAAM,CAAC,SAAS;AAE7C,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,SACE,gBAAAF,OAAA,cAACE,MAAA,EAAI,eAAc,YAChB,cAAc,IAAI,CAAC,OAAO,UAAU;AACnC,QAAI,MAAM,SAAS,aAAa;AAC9B,aACE,gBAAAF,OAAA,cAACE,MAAA,EAAI,KAAK,OAAO,WAAW,KAC1B,gBAAAF,OAAA,cAACC,OAAA,EAAK,UAAQ,QAAE,iBAAkB,GAClC,gBAAAD,OAAA,cAACC,OAAA,EAAK,MAAI,QAAE,MAAM,IAAK,GACvB,gBAAAD,OAAA,cAACC,OAAA,EAAK,UAAQ,QAAE,eAAgB,CAClC;AAAA,IAEJ;AAEA,UAAM,QAAQ,cAAc,KAAK;AACjC,UAAM,OAAO,aAAa,KAAK;AAC/B,UAAM,WAAW,UAAU,cAAc,SAAS;AAElD,WACE,gBAAAD,OAAA,cAACE,MAAA,EAAI,KAAK,SACR,gBAAAF,OAAA,cAACC,OAAA,EAAK,UAAQ,QAAE,YAAa,GAC7B,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAO,MAAM,SAAQ,MAAM,QAAO,GAAC,GACzC,gBAAAD,OAAA;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,OAAO,MAAM,UAAU,UAAU,SAAY,MAAM;AAAA,QACnD,MAAM,YAAY,MAAM,SAAS;AAAA,QACjC,UAAU,MAAM,SAAS;AAAA;AAAA,MAExB;AAAA,IACH,GACC,MAAM,SAAS,YAAY,MAAM,UAChC,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAM,UAAQ,KAAK,MAAM,MAAO,CAE1C;AAAA,EAEJ,CAAC,CACH;AAEJ;;;AC9FA,OAAOE,UAAS,YAAAC,iBAAgB;AAChC,SAAS,QAAAC,OAAM,OAAAC,MAAK,YAAAC,iBAAgB;AAO7B,IAAM,gBAA8C,CAAC,EAAE,QAAQ,UAAU,MAAM;AACpF,QAAM,CAAC,UAAU,WAAW,IAAIH,UAAuB,KAAK;AAE5D,EAAAG,UAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,aAAa,UAAU,KAAK;AAClC,kBAAY,KAAK;AAAA,IACnB,WAAW,IAAI,cAAc,UAAU,KAAK;AAC1C,kBAAY,IAAI;AAAA,IAClB,WAAW,IAAI,QAAQ;AACrB,gBAAU,aAAa,KAAK;AAAA,IAC9B,WAAW,UAAU,OAAO,UAAU,KAAK;AACzC,gBAAU,IAAI;AAAA,IAChB,WAAW,UAAU,OAAO,UAAU,KAAK;AACzC,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF,CAAC;AAED,SACE,gBAAAJ,OAAA,cAACG,MAAA,EAAI,eAAc,UAAS,aAAY,QAAO,aAAY,UAAS,UAAU,GAAG,UAAU,KACzF,gBAAAH,OAAA,cAACG,MAAA,EAAI,cAAc,KACjB,gBAAAH,OAAA,cAACE,OAAA,EAAK,OAAM,UAAS,MAAI,QAAC,SAAO,CACnC,GACA,gBAAAF,OAAA,cAACG,MAAA,EAAI,cAAc,KACjB,gBAAAH,OAAA,cAACE,OAAA,MAAM,MAAO,CAChB,GACA,gBAAAF,OAAA,cAACG,MAAA,MACC,gBAAAH,OAAA,cAACG,MAAA,EAAI,aAAa,KAChB,gBAAAH,OAAA;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,iBAAiB,aAAa,QAAQ,UAAU;AAAA,MAChD,OAAO,aAAa,QAAQ,UAAU;AAAA,MACtC,MAAM,aAAa;AAAA;AAAA,IAElB;AAAA,EACH,CACF,GACA,gBAAAF,OAAA;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,iBAAiB,aAAa,OAAO,QAAQ;AAAA,MAC7C,OAAO,aAAa,OAAO,UAAU;AAAA,MACrC,MAAM,aAAa;AAAA;AAAA,IAElB;AAAA,EACH,CACF,GACA,gBAAAF,OAAA,cAACG,MAAA,EAAI,WAAW,KACd,gBAAAH,OAAA,cAACE,OAAA,EAAK,UAAQ,QAAC,uBAAqB,CACtC,CACF;AAEJ;;;ACxDA,OAAOG,UAAS,YAAAC,iBAAgB;AAChC,SAAS,QAAAC,OAAM,OAAAC,MAAK,YAAAC,iBAAgB;AACpC,OAAO,eAAe;AAOf,IAAM,iBAAgD,CAAC,EAAE,UAAU,SAAS,MAAM;AACvF,QAAM,CAAC,QAAQ,SAAS,IAAIH,UAAS,EAAE;AAEvC,QAAM,eAAe,MAAM;AACzB,QAAI,OAAO,KAAK,GAAG;AACjB,eAAS,OAAO,KAAK,CAAC;AAAA,IACxB;AAAA,EACF;AAEA,EAAAG,UAAS,CAAC,GAAG,QAAQ;AACnB,QAAI,IAAI,UAAU,OAAO,KAAK,GAAG;AAC/B,mBAAa;AAAA,IACf;AAAA,EACF,CAAC;AAED,SACE,gBAAAJ,OAAA,cAACG,MAAA,EAAI,eAAc,UAAS,aAAY,QAAO,aAAY,QAAO,UAAU,GAAG,UAAU,KACvF,gBAAAH,OAAA,cAACG,MAAA,EAAI,cAAc,KACjB,gBAAAH,OAAA,cAACE,OAAA,EAAK,OAAM,QAAO,MAAI,QAAC,gBAAc,CACxC,GACA,gBAAAF,OAAA,cAACG,MAAA,EAAI,cAAc,KACjB,gBAAAH,OAAA,cAACE,OAAA,MAAM,QAAS,CAClB,GACA,gBAAAF,OAAA,cAACG,MAAA,MACC,gBAAAH,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,SAAU,GAC9B,gBAAAF,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV,aAAY;AAAA;AAAA,EACd,CACF,GACA,gBAAAA,OAAA,cAACG,MAAA,EAAI,WAAW,KACd,gBAAAH,OAAA,cAACE,OAAA,EAAK,UAAQ,QAAC,iBAAe,CAChC,CACF;AAEJ;;;AC9CA,OAAOG,UAAS,YAAAC,iBAAgB;AAChC,SAAS,QAAAC,OAAM,OAAAC,YAAW;AAC1B,OAAOC,gBAAe;AAMf,IAAM,cAA0C,CAAC,EAAE,SAAS,MAAM;AACvE,QAAM,CAAC,OAAO,QAAQ,IAAIH,UAAS,EAAE;AAErC,QAAM,eAAe,MAAM;AACzB,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,SAAS;AACX,eAAS,OAAO;AAChB,eAAS,EAAE;AAAA,IACb;AAAA,EACF;AAEA,SACE,gBAAAD,OAAA,cAACG,MAAA,MACC,gBAAAH,OAAA,cAACE,OAAA,EAAK,OAAM,QAAO,MAAI,QAAE,SAAU,GACnC,gBAAAF,OAAA;AAAA,IAACI;AAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,aAAY;AAAA;AAAA,EACd,CACF;AAEJ;;;AC9BA,OAAOC,YAAW;AAClB,SAAS,QAAAC,OAAM,OAAAC,YAAW;AAC1B,OAAO,gBAAgB;AAMhB,IAAM,UAAkC,CAAC,EAAE,KAAK,MAAM;AAC3D,SACE,gBAAAF,OAAA,cAACE,MAAA,MACC,gBAAAF,OAAA,cAACC,OAAA,EAAK,OAAM,UACV,gBAAAD,OAAA,cAAC,cAAW,MAAK,QAAO,CAC1B,GACC,QAAQ,gBAAAA,OAAA,cAACC,OAAA,EAAK,UAAQ,QAAC,KAAE,IAAK,CACjC;AAEJ;;;ARCO,IAAM,MAA0B,CAAC,EAAE,KAAK,MAAM;AACnD,QAAM,EAAE,KAAK,IAAI,OAAO;AACxB,QAAM,CAAC,OAAO,QAAQ,IAAIE,UAAgB,KAAK,OAAO,cAAc,OAAO;AAC3E,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK,QAAQ,EAAE;AAE9D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,SAAS;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK;AAAA,IACd,WAAW,KAAK;AAAA,IAChB,YAAY,MAAM;AAChB,eAAS,OAAO;AAAA,IAClB;AAAA,EACF,CAAC;AAGD,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU,eAAe,aAAa;AACxC,YAAM,WAAW;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,OAAO,aAAa,KAAK,CAAC;AAE9B,QAAM,mBAAmBC,aAAY,CAAC,SAAiB;AACrD,mBAAe,IAAI;AACnB,aAAS,WAAW;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,iBAAe;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ,YAAY;AAClB,UAAI,UAAU,aAAa;AACzB,cAAM,KAAK;AAAA,MACb;AACA,WAAK;AAAA,IACP;AAAA,IACA,UAAU,UAAU;AAAA,IACpB,UAAU,UAAU,WAAW,CAAC,CAAC,kBAAkB,CAAC,CAAC;AAAA,EACvD,CAAC;AAED,QAAM,aAAa,UAAU,cAAc,UAAU,aAAa,UAAU;AAE5E,SACE,gBAAAC,OAAA,cAACC,MAAA,EAAI,eAAc,YAEhB,UAAU,WAAW,OAAO,WAAW,KACtC,gBAAAD,OAAA,cAACC,MAAA,EAAI,aAAY,QAAO,aAAY,QAAO,UAAU,KACnD,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,QAAO,MAAI,QAAE,YAAa,GACtC,gBAAAF,OAAA,cAACE,OAAA,MAAM,oBAAqB,CAC9B,GAID,UAAU,eACT,gBAAAF,OAAA,cAAC,aAAU,OAAc,MAAY,MAAM,aAAa,GAI1D,gBAAAA,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,WAAW,KACrC,gBAAAD,OAAA,cAAC,gBAAa,QAAgB,GAE7B,UAAU,eAAe,UAAU,aAClC,gBAAAA,OAAA,cAACC,MAAA,MACC,gBAAAD,OAAA,cAACE,OAAA,EAAK,UAAQ,QAAE,YAAa,GAC7B,gBAAAF,OAAA,cAAC,aAAQ,CACX,GAGD,UAAU,eAAe,UAAU,YAClC,gBAAAA,OAAA,cAACC,MAAA,MACC,gBAAAD,OAAA,cAACE,OAAA,EAAK,UAAQ,QAAE,YAAa,GAC7B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAS,MAAI,QAAE,cAAe,GAC1C,gBAAAF,OAAA,cAACE,OAAA,EAAK,UAAQ,QAAE,gCAAiC,CACnD,CAEJ,GAEC,kBACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,WAAW,KACd,gBAAAD,OAAA,cAAC,iBAAc,QAAQ,gBAAgB,WAAW,gBAAgB,CACpE,GAGD,mBACC,gBAAAA,OAAA,cAACC,MAAA,EAAI,WAAW,KACd,gBAAAD,OAAA,cAAC,kBAAe,UAAU,iBAAiB,UAAU,eAAe,CACtE,GAID,UAAU,WACT,gBAAAA,OAAA,cAACC,MAAA,EAAI,WAAW,KACd,gBAAAD,OAAA,cAAC,eAAY,UAAU,kBAAkB,CAC3C,GAID,UAAU,eAAe,CAAC,cAAc,CAAC,kBAAkB,CAAC,mBAC3D,gBAAAA,OAAA,cAACC,MAAA,EAAI,WAAW,KACd,gBAAAD,OAAA,cAACE,OAAA,EAAK,UAAQ,QAAE,4CAAiD,CACnE,CAEJ;AAEJ;;;ANnHA,eAAe,OAAsB;AACnC,MAAI;AACF,UAAM,SAAS,MAAM,UAAU;AAG/B,QAAI,OAAO,SAAS,WAAW;AAC7B;AAAA,IACF;AAEA,UAAM,EAAE,KAAK,IAAI;AAGjB,UAAM,SAAS,WAAW;AAC1B,QAAI,CAAC,QAAQ;AACX,cAAQ,MAAM,yBAAyB;AACvC,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,kEAAkE;AAChF,cAAQ,MAAM,+BAA+B;AAC7C,cAAQ,MAAM,EAAE;AAChB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,QAAQ,IAAI,mBAAmB;AAC9D,cAAQ,IAAI,cAAc;AAAA,IAC5B;AAGA,QAAI,CAAC,kBAAkB,GAAG;AACxB,cAAQ,MAAM,oCAAoC;AAClD,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,0DAA0D;AACxE,cAAQ,MAAM,4DAA4D;AAC1E,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,+CAA+C;AAC7D,cAAQ,MAAM,EAAE;AAChB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,EAAE,cAAc,IAAI,OAAO,gBAAAC,OAAA,cAAC,OAAI,MAAY,CAAE;AACpD,UAAM,cAAc;AAAA,EACtB,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,KAAK;AAC7B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;","names":["React","yargs","React","useEffect","useState","useCallback","Box","Text","useCallback","React","Text","Box","React","useState","Text","Box","useInput","React","useState","Text","Box","useInput","React","useState","Text","Box","TextInput","React","Text","Box","useState","useEffect","useCallback","React","Box","Text","React"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi_inc/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Terminal-based agent interaction for AGI desktop automation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"lint": "eslint src --ext .ts,.tsx",
|
|
14
14
|
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
15
15
|
"typecheck": "tsc --noEmit",
|
|
16
|
-
"prepublishOnly": "npm run build"
|
|
16
|
+
"prepublishOnly": "npm run build",
|
|
17
|
+
"screenshots": "node scripts/generate-screenshots.mjs"
|
|
17
18
|
},
|
|
18
19
|
"keywords": [
|
|
19
20
|
"agi",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"eslint": "^8.55.0",
|
|
65
66
|
"eslint-config-prettier": "^9.1.0",
|
|
66
67
|
"prettier": "^3.1.0",
|
|
68
|
+
"puppeteer": "^24.37.2",
|
|
67
69
|
"tsup": "^8.0.1",
|
|
68
70
|
"typescript": "^5.3.3"
|
|
69
71
|
}
|