@agi_inc/cli 0.4.0 → 0.5.2
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 +34 -19
- package/dist/index.mjs +362 -66
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @agi_inc/cli
|
|
2
2
|
|
|
3
|
-
Terminal-based agent
|
|
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
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @agi_inc/cli "open calculator and compute 2+2"
|
|
7
|
+
```
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
11
|
+
**Zero-install** (recommended):
|
|
12
|
+
|
|
7
13
|
```bash
|
|
8
|
-
|
|
14
|
+
npx @agi_inc/cli "your task here"
|
|
9
15
|
```
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
**Global install**:
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g @agi_inc/cli
|
|
21
|
+
agi "your task here"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Homebrew** (macOS/Linux):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
brew install agi-inc/tap/agi
|
|
28
|
+
agi "your task here"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Configuration
|
|
32
|
+
|
|
33
|
+
Set your API key before running:
|
|
14
34
|
|
|
15
35
|
```bash
|
|
16
36
|
export AGI_API_KEY=your_api_key
|
|
@@ -38,7 +58,7 @@ agi "Delete old files" --no-confirm
|
|
|
38
58
|
|
|
39
59
|
| Option | Alias | Description | Default |
|
|
40
60
|
|--------|-------|-------------|---------|
|
|
41
|
-
| `--model` | `-m` | Model to use | `claude-sonnet` |
|
|
61
|
+
| `--model` | `-m` | Model to use (`claude-sonnet`, `claude-opus`) | `claude-sonnet` |
|
|
42
62
|
| `--verbose` | `-v` | Show agent thinking | `false` |
|
|
43
63
|
| `--no-confirm` | | Auto-approve confirmations | `false` |
|
|
44
64
|
| `--help` | `-h` | Show help | |
|
|
@@ -54,23 +74,12 @@ While the agent is running:
|
|
|
54
74
|
| `Q` | Stop |
|
|
55
75
|
| `Ctrl+C` | Cancel |
|
|
56
76
|
|
|
57
|
-
## Features
|
|
58
|
-
|
|
59
|
-
- **Real-time event display**: See actions, thinking, and status updates as they happen
|
|
60
|
-
- **Interactive dialogs**: Respond to agent questions and confirmation requests
|
|
61
|
-
- **Pause/Resume**: Take control when needed
|
|
62
|
-
- **Verbose mode**: See the agent's reasoning process
|
|
63
|
-
- **Multiple models**: Choose between Claude Sonnet and Opus
|
|
64
|
-
|
|
65
77
|
## How It Works
|
|
66
78
|
|
|
67
|
-
The CLI uses the AGI SDK's driver module to spawn and manage the agent binary locally. The agent:
|
|
68
|
-
|
|
69
79
|
1. Captures screenshots of your desktop
|
|
70
80
|
2. Analyzes them using Claude
|
|
71
|
-
3. Decides on
|
|
72
|
-
4.
|
|
73
|
-
5. Repeats until the task is complete
|
|
81
|
+
3. Decides on and executes actions
|
|
82
|
+
4. Repeats until the task is complete
|
|
74
83
|
|
|
75
84
|
## Requirements
|
|
76
85
|
|
|
@@ -78,6 +87,12 @@ The CLI uses the AGI SDK's driver module to spawn and manage the agent binary lo
|
|
|
78
87
|
- macOS, Linux, or Windows
|
|
79
88
|
- AGI API key or Anthropic API key
|
|
80
89
|
|
|
90
|
+
## SDKs
|
|
91
|
+
|
|
92
|
+
- [agi-python](https://github.com/agi-inc/agi-python) — Python SDK
|
|
93
|
+
- [agi-node](https://github.com/agi-inc/agi-node) — Node.js SDK
|
|
94
|
+
- [agi-csharp](https://github.com/agi-inc/agi-csharp) — C# SDK
|
|
95
|
+
|
|
81
96
|
## License
|
|
82
97
|
|
|
83
98
|
MIT
|
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,262 @@
|
|
|
1
1
|
// src/index.tsx
|
|
2
2
|
import React7 from "react";
|
|
3
3
|
import { render } from "ink";
|
|
4
|
-
import { isBinaryAvailable } from "agi";
|
|
4
|
+
import { isBinaryAvailable } from "@agi_inc/agi-js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import yargs from "yargs";
|
|
8
8
|
import { hideBin } from "yargs/helpers";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
|
|
10
|
+
// src/config.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import os from "os";
|
|
14
|
+
function getCredentialsPath() {
|
|
15
|
+
return path.join(os.homedir(), ".agi", "credentials");
|
|
16
|
+
}
|
|
17
|
+
function loadApiKey() {
|
|
18
|
+
if (process.env.AGI_API_KEY) {
|
|
19
|
+
return process.env.AGI_API_KEY;
|
|
20
|
+
}
|
|
21
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
22
|
+
return process.env.ANTHROPIC_API_KEY;
|
|
23
|
+
}
|
|
24
|
+
const credPath = getCredentialsPath();
|
|
25
|
+
try {
|
|
26
|
+
const raw = fs.readFileSync(credPath, "utf-8");
|
|
27
|
+
const credentials = JSON.parse(raw);
|
|
28
|
+
if (credentials.api_key) {
|
|
29
|
+
return credentials.api_key;
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
function saveApiKey(apiKey) {
|
|
36
|
+
const credPath = getCredentialsPath();
|
|
37
|
+
const dir = path.dirname(credPath);
|
|
38
|
+
if (!fs.existsSync(dir)) {
|
|
39
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
40
|
+
}
|
|
41
|
+
const credentials = { api_key: apiKey };
|
|
42
|
+
fs.writeFileSync(credPath, JSON.stringify(credentials, null, 2) + "\n", {
|
|
43
|
+
mode: 384
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function deleteCredentials() {
|
|
47
|
+
const credPath = getCredentialsPath();
|
|
48
|
+
try {
|
|
49
|
+
fs.unlinkSync(credPath);
|
|
50
|
+
return true;
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/commands/login.ts
|
|
57
|
+
var API_BASE = "https://api.agi.tech";
|
|
58
|
+
async function openBrowser(url) {
|
|
59
|
+
const open = (await import("open")).default;
|
|
60
|
+
await open(url);
|
|
61
|
+
}
|
|
62
|
+
function sleep(ms) {
|
|
63
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
64
|
+
}
|
|
65
|
+
async function loginCommand() {
|
|
66
|
+
let deviceAuth;
|
|
67
|
+
try {
|
|
68
|
+
const res = await fetch(`${API_BASE}/v1/auth/device`, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: { "Content-Type": "application/json" }
|
|
15
71
|
});
|
|
16
|
-
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
const detail = await res.text();
|
|
74
|
+
console.error(`Failed to start login flow (${res.status}): ${detail}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
deviceAuth = await res.json();
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.error(`Failed to connect to AGI API: ${err.message}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
console.log("");
|
|
83
|
+
console.log(`Your confirmation code: ${deviceAuth.user_code}`);
|
|
84
|
+
console.log("");
|
|
85
|
+
console.log("Opening browser to authorize...");
|
|
86
|
+
console.log(` ${deviceAuth.verification_url}`);
|
|
87
|
+
console.log("");
|
|
88
|
+
try {
|
|
89
|
+
await openBrowser(deviceAuth.verification_url);
|
|
90
|
+
} catch {
|
|
91
|
+
console.log("Could not open browser automatically. Please visit the URL above.");
|
|
92
|
+
}
|
|
93
|
+
console.log("Waiting for authorization...");
|
|
94
|
+
const sigintHandler = () => {
|
|
95
|
+
console.log("\nLogin cancelled.");
|
|
96
|
+
process.exit(130);
|
|
97
|
+
};
|
|
98
|
+
process.on("SIGINT", sigintHandler);
|
|
99
|
+
const maxAttempts = Math.ceil(deviceAuth.expires_in / deviceAuth.interval);
|
|
100
|
+
const interval = deviceAuth.interval * 1e3;
|
|
101
|
+
let consecutiveErrors = 0;
|
|
102
|
+
try {
|
|
103
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
104
|
+
await sleep(interval);
|
|
105
|
+
try {
|
|
106
|
+
const res = await fetch(`${API_BASE}/v1/auth/device/token`, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: { "Content-Type": "application/json" },
|
|
109
|
+
body: JSON.stringify({ device_code: deviceAuth.device_code })
|
|
110
|
+
});
|
|
111
|
+
consecutiveErrors = 0;
|
|
112
|
+
if (res.status === 428) {
|
|
113
|
+
process.stdout.write(".");
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (res.status === 410) {
|
|
117
|
+
console.log("");
|
|
118
|
+
console.error("Login expired. Please run `agi login` again.");
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
if (res.ok) {
|
|
122
|
+
const token = await res.json();
|
|
123
|
+
console.log("");
|
|
124
|
+
saveApiKey(token.api_key);
|
|
125
|
+
const identity = token.email || "your account";
|
|
126
|
+
console.log(`Logged in as ${identity}`);
|
|
127
|
+
console.log("Your API key has been saved to ~/.agi/credentials");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const detail = await res.text();
|
|
131
|
+
console.log("");
|
|
132
|
+
console.error(`Unexpected response (${res.status}): ${detail}`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
} catch {
|
|
135
|
+
consecutiveErrors++;
|
|
136
|
+
if (consecutiveErrors >= 3) {
|
|
137
|
+
console.log("");
|
|
138
|
+
console.error("Unable to reach AGI API. Check your internet connection.");
|
|
139
|
+
console.error("Retrying...");
|
|
140
|
+
consecutiveErrors = 0;
|
|
141
|
+
} else {
|
|
142
|
+
process.stdout.write("!");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log("");
|
|
147
|
+
console.error("Login timed out. Please run `agi login` again.");
|
|
148
|
+
process.exit(1);
|
|
149
|
+
} finally {
|
|
150
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/commands/logout.ts
|
|
155
|
+
async function logoutCommand() {
|
|
156
|
+
const deleted = deleteCredentials();
|
|
157
|
+
if (deleted) {
|
|
158
|
+
console.log("Logged out. Credentials removed from ~/.agi/credentials");
|
|
159
|
+
} else {
|
|
160
|
+
console.log("No credentials file found. Already logged out.");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/commands/update.ts
|
|
165
|
+
import { execSync } from "child_process";
|
|
166
|
+
import { readFileSync, realpathSync } from "fs";
|
|
167
|
+
import { dirname, join } from "path";
|
|
168
|
+
function getCurrentVersion() {
|
|
169
|
+
const realScript = realpathSync(process.argv[1]);
|
|
170
|
+
const pkgPath = join(dirname(realScript), "..", "package.json");
|
|
171
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
172
|
+
return pkg.version;
|
|
173
|
+
}
|
|
174
|
+
async function getLatestVersion() {
|
|
175
|
+
const res = await fetch("https://registry.npmjs.org/@agi_inc/cli");
|
|
176
|
+
if (!res.ok) {
|
|
177
|
+
throw new Error(`npm registry returned ${res.status}`);
|
|
178
|
+
}
|
|
179
|
+
const data = await res.json();
|
|
180
|
+
return data["dist-tags"].latest;
|
|
181
|
+
}
|
|
182
|
+
function compareVersions(a, b) {
|
|
183
|
+
const pa = a.split(".").map(Number);
|
|
184
|
+
const pb = b.split(".").map(Number);
|
|
185
|
+
for (let i = 0; i < 3; i++) {
|
|
186
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return -1;
|
|
187
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return 1;
|
|
188
|
+
}
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
function detectInstallMethod() {
|
|
192
|
+
try {
|
|
193
|
+
const agiPath = execSync("which agi", { encoding: "utf-8" }).trim();
|
|
194
|
+
if (agiPath.includes("homebrew") || agiPath.includes("Cellar")) {
|
|
195
|
+
return "homebrew";
|
|
196
|
+
}
|
|
197
|
+
return "npm";
|
|
198
|
+
} catch {
|
|
199
|
+
return "unknown";
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async function updateCommand() {
|
|
203
|
+
const current = getCurrentVersion();
|
|
204
|
+
console.log("");
|
|
205
|
+
console.log(` \u25B8 AGI CLI v${current}`);
|
|
206
|
+
console.log("");
|
|
207
|
+
console.log(" Checking for updates...");
|
|
208
|
+
try {
|
|
209
|
+
const latest = await getLatestVersion();
|
|
210
|
+
if (compareVersions(current, latest) >= 0) {
|
|
211
|
+
console.log(` \u25CF Up to date`);
|
|
212
|
+
console.log("");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
console.log(` Update available: ${current} \u2192 ${latest}`);
|
|
216
|
+
console.log("");
|
|
217
|
+
const method = detectInstallMethod();
|
|
218
|
+
if (method === "homebrew") {
|
|
219
|
+
console.log(" Updating via Homebrew...");
|
|
220
|
+
console.log("");
|
|
221
|
+
execSync("brew upgrade agi", { stdio: "inherit" });
|
|
222
|
+
} else {
|
|
223
|
+
console.log(" Updating via npm...");
|
|
224
|
+
console.log("");
|
|
225
|
+
execSync("npm install -g @agi_inc/cli@latest", { stdio: "inherit" });
|
|
226
|
+
}
|
|
227
|
+
console.log("");
|
|
228
|
+
console.log(` \u25CF Updated to v${latest}`);
|
|
229
|
+
console.log("");
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error("");
|
|
232
|
+
console.error(` \u2715 Update failed: ${error instanceof Error ? error.message : error}`);
|
|
233
|
+
console.error("");
|
|
234
|
+
console.error(" Try manually:");
|
|
235
|
+
console.error(" npm install -g @agi_inc/cli@latest");
|
|
236
|
+
console.error("");
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/cli.ts
|
|
242
|
+
async function parseArgs() {
|
|
243
|
+
const argv = await yargs(hideBin(process.argv)).scriptName("agi").command("login", "Authenticate and save your API key", {}, async () => {
|
|
244
|
+
await loginCommand();
|
|
245
|
+
}).command("logout", "Remove saved credentials", {}, async () => {
|
|
246
|
+
await logoutCommand();
|
|
247
|
+
}).command("update", "Update AGI CLI to the latest version", {}, async () => {
|
|
248
|
+
await updateCommand();
|
|
249
|
+
}).command(
|
|
250
|
+
"$0 <goal>",
|
|
251
|
+
"Run an agent with the given goal",
|
|
252
|
+
(yargs2) => {
|
|
253
|
+
return yargs2.positional("goal", {
|
|
254
|
+
describe: "The task for the agent to accomplish",
|
|
255
|
+
type: "string",
|
|
256
|
+
demandOption: true
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
).option("model", {
|
|
17
260
|
alias: "m",
|
|
18
261
|
describe: "Model to use",
|
|
19
262
|
type: "string",
|
|
@@ -28,12 +271,19 @@ async function parseArgs() {
|
|
|
28
271
|
describe: "Auto-approve all confirmation requests",
|
|
29
272
|
type: "boolean",
|
|
30
273
|
default: false
|
|
31
|
-
}).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").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 login", "Authenticate with your API key").example("$0 update", "Update to the latest version").parse();
|
|
275
|
+
const command = argv._?.[0];
|
|
276
|
+
if (command === "login" || command === "logout" || command === "update") {
|
|
277
|
+
return { kind: "handled" };
|
|
278
|
+
}
|
|
32
279
|
return {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
280
|
+
kind: "run",
|
|
281
|
+
args: {
|
|
282
|
+
goal: argv.goal,
|
|
283
|
+
model: argv.model,
|
|
284
|
+
verbose: argv.verbose,
|
|
285
|
+
noConfirm: argv["no-confirm"]
|
|
286
|
+
}
|
|
37
287
|
};
|
|
38
288
|
}
|
|
39
289
|
|
|
@@ -43,9 +293,9 @@ import { Box as Box6, Text as Text6, useApp } from "ink";
|
|
|
43
293
|
|
|
44
294
|
// src/hooks/useAgent.ts
|
|
45
295
|
import { useState, useCallback, useRef, useEffect } from "react";
|
|
46
|
-
import { AgentDriver } from "agi";
|
|
296
|
+
import { AgentDriver } from "@agi_inc/agi-js";
|
|
47
297
|
function useAgent(options) {
|
|
48
|
-
const { model, verbose, noConfirm, onFinished } = options;
|
|
298
|
+
const { model, agentName, apiUrl, verbose, noConfirm, onFinished } = options;
|
|
49
299
|
const [state, setState] = useState("idle");
|
|
50
300
|
const [step, setStep] = useState(0);
|
|
51
301
|
const [events, setEvents] = useState([]);
|
|
@@ -57,7 +307,7 @@ function useAgent(options) {
|
|
|
57
307
|
}, []);
|
|
58
308
|
const start = useCallback(
|
|
59
309
|
async (goal) => {
|
|
60
|
-
const driver = new AgentDriver({ model, mode: "local" });
|
|
310
|
+
const driver = new AgentDriver({ model, mode: "local", agentName, apiUrl });
|
|
61
311
|
driverRef.current = driver;
|
|
62
312
|
driver.on("state_change", (newState) => {
|
|
63
313
|
setState(newState);
|
|
@@ -104,7 +354,7 @@ function useAgent(options) {
|
|
|
104
354
|
addEvent({ type: "error", message: String(error) });
|
|
105
355
|
}
|
|
106
356
|
},
|
|
107
|
-
[model, verbose, noConfirm, addEvent, onFinished, state]
|
|
357
|
+
[model, agentName, apiUrl, verbose, noConfirm, addEvent, onFinished, state]
|
|
108
358
|
);
|
|
109
359
|
const stop = useCallback(async () => {
|
|
110
360
|
if (driverRef.current) {
|
|
@@ -193,49 +443,85 @@ var stateColors = {
|
|
|
193
443
|
waiting_confirmation: "yellow",
|
|
194
444
|
waiting_answer: "yellow",
|
|
195
445
|
finished: "green",
|
|
196
|
-
stopped: "
|
|
446
|
+
stopped: "gray",
|
|
197
447
|
error: "red"
|
|
198
448
|
};
|
|
199
449
|
var stateLabels = {
|
|
200
450
|
idle: "IDLE",
|
|
201
|
-
running: "
|
|
451
|
+
running: "ACTIVE",
|
|
202
452
|
paused: "PAUSED",
|
|
203
|
-
waiting_confirmation: "
|
|
204
|
-
waiting_answer: "
|
|
205
|
-
finished: "
|
|
453
|
+
waiting_confirmation: "AWAITING",
|
|
454
|
+
waiting_answer: "AWAITING",
|
|
455
|
+
finished: "COMPLETE",
|
|
206
456
|
stopped: "STOPPED",
|
|
207
457
|
error: "ERROR"
|
|
208
458
|
};
|
|
459
|
+
var stateIndicators = {
|
|
460
|
+
idle: "\u25CB",
|
|
461
|
+
running: "\u25CF",
|
|
462
|
+
paused: "\u25C9",
|
|
463
|
+
waiting_confirmation: "\u25CE",
|
|
464
|
+
waiting_answer: "\u25CE",
|
|
465
|
+
finished: "\u25CF",
|
|
466
|
+
stopped: "\u25CB",
|
|
467
|
+
error: "\u25CF"
|
|
468
|
+
};
|
|
209
469
|
var StatusBar = ({ state, step, goal }) => {
|
|
210
470
|
const color = stateColors[state] || "white";
|
|
211
471
|
const label = stateLabels[state] || state.toUpperCase();
|
|
212
|
-
|
|
472
|
+
const indicator = stateIndicators[state] || "\u25CB";
|
|
473
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "bold", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, "\u25B8 AGI"), /* @__PURE__ */ React.createElement(Text, null, " "), /* @__PURE__ */ React.createElement(Text, { color }, indicator, " "), /* @__PURE__ */ React.createElement(Text, { color, bold: true }, label), /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "STEP "), /* @__PURE__ */ React.createElement(Text, { bold: true }, String(step).padStart(2, "0"))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, goal.length > 72 ? goal.slice(0, 72) + "\u2026" : goal)));
|
|
213
474
|
};
|
|
214
475
|
|
|
215
476
|
// src/components/EventDisplay.tsx
|
|
216
477
|
import React2 from "react";
|
|
217
478
|
import { Text as Text2, Box as Box2 } from "ink";
|
|
218
|
-
var
|
|
219
|
-
|
|
220
|
-
|
|
479
|
+
var typeConfig = {
|
|
480
|
+
thinking: { prefix: "\xB7", color: "gray" },
|
|
481
|
+
action: { prefix: "\u25B8", color: "white" },
|
|
482
|
+
confirm: { prefix: "\u25C6", color: "yellow" },
|
|
483
|
+
question: { prefix: "\u25C7", color: "cyan" },
|
|
484
|
+
error: { prefix: "\u2715", color: "red" }
|
|
221
485
|
};
|
|
222
|
-
|
|
486
|
+
function getEventText(event) {
|
|
223
487
|
switch (event.type) {
|
|
224
488
|
case "thinking":
|
|
225
|
-
return
|
|
489
|
+
return event.text;
|
|
226
490
|
case "action":
|
|
227
|
-
return
|
|
491
|
+
return event.action;
|
|
228
492
|
case "confirm":
|
|
229
|
-
return
|
|
493
|
+
return event.reason;
|
|
230
494
|
case "question":
|
|
231
|
-
return
|
|
495
|
+
return event.question;
|
|
232
496
|
case "finished":
|
|
233
|
-
return
|
|
497
|
+
return event.summary;
|
|
234
498
|
case "error":
|
|
235
|
-
return
|
|
236
|
-
default:
|
|
237
|
-
return null;
|
|
499
|
+
return event.message;
|
|
238
500
|
}
|
|
501
|
+
}
|
|
502
|
+
function getEventStyle(event) {
|
|
503
|
+
if (event.type === "finished") {
|
|
504
|
+
return event.success ? { prefix: "\u25CF", color: "green" } : { prefix: "\u2715", color: "red" };
|
|
505
|
+
}
|
|
506
|
+
return typeConfig[event.type];
|
|
507
|
+
}
|
|
508
|
+
var EventDisplay = ({ events, maxEvents = 12 }) => {
|
|
509
|
+
const displayEvents = events.slice(-maxEvents);
|
|
510
|
+
if (displayEvents.length === 0) return null;
|
|
511
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, displayEvents.map((event, index) => {
|
|
512
|
+
const style = getEventStyle(event);
|
|
513
|
+
const text = getEventText(event);
|
|
514
|
+
const isLatest = index === displayEvents.length - 1;
|
|
515
|
+
return /* @__PURE__ */ React2.createElement(Box2, { key: index }, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React2.createElement(Text2, { color: style.color }, style.prefix, " "), /* @__PURE__ */ React2.createElement(
|
|
516
|
+
Text2,
|
|
517
|
+
{
|
|
518
|
+
color: style.color === "white" ? void 0 : style.color,
|
|
519
|
+
bold: isLatest && event.type === "action",
|
|
520
|
+
dimColor: event.type === "thinking"
|
|
521
|
+
},
|
|
522
|
+
text
|
|
523
|
+
));
|
|
524
|
+
}));
|
|
239
525
|
};
|
|
240
526
|
|
|
241
527
|
// src/components/ConfirmDialog.tsx
|
|
@@ -256,21 +542,23 @@ var ConfirmDialog = ({ reason, onConfirm }) => {
|
|
|
256
542
|
onConfirm(false);
|
|
257
543
|
}
|
|
258
544
|
});
|
|
259
|
-
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", borderStyle: "
|
|
545
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", borderStyle: "bold", borderColor: "yellow", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "yellow", bold: true }, "CONFIRM")), /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, null, reason)), /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Box3, { marginRight: 2 }, /* @__PURE__ */ React3.createElement(
|
|
260
546
|
Text3,
|
|
261
547
|
{
|
|
262
548
|
backgroundColor: selected === "yes" ? "green" : void 0,
|
|
263
|
-
color: selected === "yes" ? "
|
|
549
|
+
color: selected === "yes" ? "black" : "gray",
|
|
550
|
+
bold: selected === "yes"
|
|
264
551
|
},
|
|
265
|
-
" [Y]
|
|
266
|
-
)), /* @__PURE__ */ React3.createElement(
|
|
552
|
+
" [Y] approve "
|
|
553
|
+
)), /* @__PURE__ */ React3.createElement(
|
|
267
554
|
Text3,
|
|
268
555
|
{
|
|
269
556
|
backgroundColor: selected === "no" ? "red" : void 0,
|
|
270
|
-
color: selected === "no" ? "
|
|
557
|
+
color: selected === "no" ? "black" : "gray",
|
|
558
|
+
bold: selected === "no"
|
|
271
559
|
},
|
|
272
|
-
" [N]
|
|
273
|
-
))
|
|
560
|
+
" [N] deny "
|
|
561
|
+
)), /* @__PURE__ */ React3.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Y/N or arrows + enter")));
|
|
274
562
|
};
|
|
275
563
|
|
|
276
564
|
// src/components/QuestionDialog.tsx
|
|
@@ -289,7 +577,7 @@ var QuestionDialog = ({ question, onAnswer }) => {
|
|
|
289
577
|
handleSubmit();
|
|
290
578
|
}
|
|
291
579
|
});
|
|
292
|
-
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", borderStyle: "
|
|
580
|
+
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", borderStyle: "bold", borderColor: "cyan", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React4.createElement(Box4, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "cyan", bold: true }, "INPUT REQUIRED")), /* @__PURE__ */ React4.createElement(Box4, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, question)), /* @__PURE__ */ React4.createElement(Box4, null, /* @__PURE__ */ React4.createElement(Text4, { color: "cyan" }, "\u25B8 "), /* @__PURE__ */ React4.createElement(
|
|
293
581
|
TextInput,
|
|
294
582
|
{
|
|
295
583
|
value: answer,
|
|
@@ -297,15 +585,15 @@ var QuestionDialog = ({ question, onAnswer }) => {
|
|
|
297
585
|
onSubmit: handleSubmit,
|
|
298
586
|
placeholder: "Type your answer..."
|
|
299
587
|
}
|
|
300
|
-
)), /* @__PURE__ */ React4.createElement(Box4, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, {
|
|
588
|
+
)), /* @__PURE__ */ React4.createElement(Box4, { marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "enter to submit")));
|
|
301
589
|
};
|
|
302
590
|
|
|
303
591
|
// src/components/Spinner.tsx
|
|
304
592
|
import React5 from "react";
|
|
305
593
|
import { Text as Text5, Box as Box5 } from "ink";
|
|
306
594
|
import InkSpinner from "ink-spinner";
|
|
307
|
-
var Spinner = ({ text
|
|
308
|
-
return /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, /* @__PURE__ */ React5.createElement(InkSpinner, { type })), text && /* @__PURE__ */ React5.createElement(Text5,
|
|
595
|
+
var Spinner = ({ text }) => {
|
|
596
|
+
return /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, /* @__PURE__ */ React5.createElement(InkSpinner, { type: "dots" })), text && /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " ", text));
|
|
309
597
|
};
|
|
310
598
|
|
|
311
599
|
// src/app/App.tsx
|
|
@@ -349,31 +637,39 @@ var App = ({ args }) => {
|
|
|
349
637
|
disabled: !!pendingConfirm || !!pendingQuestion
|
|
350
638
|
});
|
|
351
639
|
const isTerminal = state === "finished" || state === "stopped" || state === "error";
|
|
352
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(StatusBar, { state, step, goal: args.goal }), state === "running" && /* @__PURE__ */ React6.createElement(Box6,
|
|
640
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(StatusBar, { state, step, goal: args.goal }), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React6.createElement(EventDisplay, { events }), state === "running" && /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React6.createElement(Spinner, null)), state === "paused" && /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \u2503 "), /* @__PURE__ */ React6.createElement(Text6, { color: "yellow", bold: true }, "\u25AE\u25AE"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " paused \u2014 space to resume"))), pendingConfirm && /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(ConfirmDialog, { reason: pendingConfirm, onConfirm: respondConfirm })), pendingQuestion && /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(QuestionDialog, { question: pendingQuestion, onAnswer: respondAnswer })), !isTerminal && !pendingConfirm && !pendingQuestion && /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " space pause \xB7 q stop \xB7 ^c cancel")));
|
|
353
641
|
};
|
|
354
642
|
|
|
355
643
|
// src/index.tsx
|
|
356
644
|
async function main() {
|
|
357
|
-
if (!process.env.AGI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
|
|
358
|
-
console.error("Error: AGI_API_KEY or ANTHROPIC_API_KEY environment variable is required");
|
|
359
|
-
console.error("");
|
|
360
|
-
console.error("Set your API key:");
|
|
361
|
-
console.error(" export AGI_API_KEY=your_key");
|
|
362
|
-
console.error("");
|
|
363
|
-
process.exit(1);
|
|
364
|
-
}
|
|
365
|
-
if (!isBinaryAvailable()) {
|
|
366
|
-
console.error("Error: AGI driver binary not found");
|
|
367
|
-
console.error("");
|
|
368
|
-
console.error("The driver binary is required for local agent execution.");
|
|
369
|
-
console.error("It should be installed automatically with the agi package.");
|
|
370
|
-
console.error("");
|
|
371
|
-
console.error("Try reinstalling: npm install -g agi-cli");
|
|
372
|
-
console.error("");
|
|
373
|
-
process.exit(1);
|
|
374
|
-
}
|
|
375
645
|
try {
|
|
376
|
-
const
|
|
646
|
+
const result = await parseArgs();
|
|
647
|
+
if (result.kind === "handled") {
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
const { args } = result;
|
|
651
|
+
const apiKey = loadApiKey();
|
|
652
|
+
if (!apiKey) {
|
|
653
|
+
console.error("Error: No API key found");
|
|
654
|
+
console.error("");
|
|
655
|
+
console.error("Run `agi login` to authenticate, or set an environment variable:");
|
|
656
|
+
console.error(" export AGI_API_KEY=your_key");
|
|
657
|
+
console.error("");
|
|
658
|
+
process.exit(1);
|
|
659
|
+
}
|
|
660
|
+
if (!process.env.AGI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
|
|
661
|
+
process.env.AGI_API_KEY = apiKey;
|
|
662
|
+
}
|
|
663
|
+
if (!isBinaryAvailable()) {
|
|
664
|
+
console.error("Error: AGI driver binary not found");
|
|
665
|
+
console.error("");
|
|
666
|
+
console.error("The driver binary is required for local agent execution.");
|
|
667
|
+
console.error("It should be installed automatically with the agi package.");
|
|
668
|
+
console.error("");
|
|
669
|
+
console.error("Try reinstalling: npm install -g @agi_inc/cli");
|
|
670
|
+
console.error("");
|
|
671
|
+
process.exit(1);
|
|
672
|
+
}
|
|
377
673
|
if (!args.goal) {
|
|
378
674
|
console.error("Error: Goal is required");
|
|
379
675
|
console.error("");
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/cli.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 */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport { isBinaryAvailable } from 'agi';\nimport { parseArgs } from './cli.js';\nimport { App } from './app/App.js';\n\nasync function main(): Promise<void> {\n // Check for API key\n if (!process.env.AGI_API_KEY && !process.env.ANTHROPIC_API_KEY) {\n console.error('Error: AGI_API_KEY or ANTHROPIC_API_KEY environment variable is required');\n console.error('');\n console.error('Set your API key:');\n console.error(' export AGI_API_KEY=your_key');\n console.error('');\n process.exit(1);\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-cli');\n console.error('');\n process.exit(1);\n }\n\n try {\n const args = await parseArgs();\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';\n\nexport interface CliArgs {\n goal: string;\n model: string;\n verbose: boolean;\n noConfirm: boolean;\n}\n\nexport async function parseArgs(): Promise<CliArgs> {\n const argv = await yargs(hideBin(process.argv))\n .scriptName('agi')\n .usage('$0 <goal>', 'Run an agent with the given goal', (yargs) => {\n return yargs.positional('goal', {\n describe: 'The task for the agent to accomplish',\n type: 'string',\n demandOption: true,\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 .parse();\n\n return {\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","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 // Wait a moment for final output, then exit\n setTimeout(() => exit(), 500);\n },\n });\n\n // Start the agent on mount\n useEffect(() => {\n if (!started) {\n setStarted(true);\n start(args.goal);\n }\n }, [started, start, args.goal]);\n\n // Handle keyboard shortcuts\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 {/* Status bar */}\n <StatusBar state={state} step={step} goal={args.goal} />\n\n {/* Running indicator */}\n {state === 'running' && (\n <Box marginY={1}>\n <Spinner text=\"Agent is working...\" />\n </Box>\n )}\n\n {/* Paused indicator */}\n {state === 'paused' && (\n <Box marginY={1}>\n <Text color=\"yellow\">⏸️ Paused - Press Space to resume, Q to stop</Text>\n </Box>\n )}\n\n {/* Events display */}\n <EventDisplay events={events} />\n\n {/* Confirmation dialog */}\n {pendingConfirm && (\n <ConfirmDialog reason={pendingConfirm} onConfirm={respondConfirm} />\n )}\n\n {/* Question dialog */}\n {pendingQuestion && (\n <QuestionDialog question={pendingQuestion} onAnswer={respondAnswer} />\n )}\n\n {/* Help text */}\n {!isTerminal && !pendingConfirm && !pendingQuestion && (\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Space: Pause/Resume | Q: Stop | Ctrl+C: Cancel\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { AgentDriver } from 'agi';\nimport type { DriverState, DriverAction, DriverResult } from 'agi';\nimport type { EventItem } from '../components/EventDisplay.js';\n\ninterface UseAgentOptions {\n model: 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, 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' });\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, 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';\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: 'red',\n error: 'red',\n};\n\nconst stateLabels: Record<DriverState, string> = {\n idle: 'IDLE',\n running: 'RUNNING',\n paused: 'PAUSED',\n waiting_confirmation: 'WAITING',\n waiting_answer: 'WAITING',\n finished: 'DONE',\n stopped: 'STOPPED',\n error: '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\n return (\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n <Box>\n <Text bold>AGI Agent</Text>\n <Text> | </Text>\n <Text color={color}>{label}</Text>\n <Text> | </Text>\n <Text>Step {step}</Text>\n </Box>\n <Box>\n <Text color=\"gray\">Goal: </Text>\n <Text>{goal.length > 60 ? goal.slice(0, 60) + '...' : 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\nexport const EventDisplay: React.FC<EventDisplayProps> = ({ events, maxEvents = 10 }) => {\n const displayEvents = events.slice(-maxEvents);\n\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n {displayEvents.map((event, index) => (\n <EventLine key={index} event={event} />\n ))}\n </Box>\n );\n};\n\nconst EventLine: React.FC<{ event: EventItem }> = ({ event }) => {\n switch (event.type) {\n case 'thinking':\n return (\n <Box>\n <Text color=\"cyan\">💭 </Text>\n <Text color=\"gray\">{event.text}</Text>\n </Box>\n );\n\n case 'action':\n return (\n <Box>\n <Text color=\"blue\">⚡ </Text>\n <Text>{event.action}</Text>\n </Box>\n );\n\n case 'confirm':\n return (\n <Box>\n <Text color=\"yellow\">❓ </Text>\n <Text color=\"yellow\">{event.reason}</Text>\n </Box>\n );\n\n case 'question':\n return (\n <Box>\n <Text color=\"magenta\">📝 </Text>\n <Text color=\"magenta\">{event.question}</Text>\n </Box>\n );\n\n case 'finished':\n return (\n <Box>\n <Text color={event.success ? 'green' : 'red'}>\n {event.success ? '✅ ' : '❌ '}\n </Text>\n <Text>{event.summary}</Text>\n </Box>\n );\n\n case 'error':\n return (\n <Box>\n <Text color=\"red\">⚠️ </Text>\n <Text color=\"red\">{event.message}</Text>\n </Box>\n );\n\n default:\n return null;\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=\"round\" borderColor=\"yellow\" paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color=\"yellow\" bold>\n Confirmation Required\n </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' ? 'white' : 'gray'}\n >\n {' [Y]es '}\n </Text>\n </Box>\n <Box>\n <Text\n backgroundColor={selected === 'no' ? 'red' : undefined}\n color={selected === 'no' ? 'white' : 'gray'}\n >\n {' [N]o '}\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text color=\"gray\" dimColor>\n Press Y/N or use arrow keys and Enter\n </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=\"round\" borderColor=\"magenta\" paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color=\"magenta\" bold>\n Agent Question\n </Text>\n </Box>\n <Box marginBottom={1}>\n <Text>{question}</Text>\n </Box>\n <Box>\n <Text color=\"green\">{'> '}</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 color=\"gray\" dimColor>\n Press Enter to submit\n </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 type?: 'dots' | 'line' | 'arc' | 'circle';\n}\n\nexport const Spinner: React.FC<SpinnerProps> = ({ text = '', type = 'dots' }) => {\n return (\n <Box>\n <Text color=\"cyan\">\n <InkSpinner type={type} />\n </Text>\n {text && <Text> {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/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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi_inc/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Terminal-based agent interaction for AGI desktop automation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
"url": "https://github.com/agi-inc/agi-cli/issues"
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://docs.agi.tech",
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
37
40
|
"engines": {
|
|
38
41
|
"node": ">=20.4.0"
|
|
39
42
|
},
|
|
@@ -44,10 +47,11 @@
|
|
|
44
47
|
"LICENSE"
|
|
45
48
|
],
|
|
46
49
|
"dependencies": {
|
|
47
|
-
"agi": "^0.4.
|
|
50
|
+
"@agi_inc/agi-js": "^0.4.2",
|
|
48
51
|
"ink": "^5.0.1",
|
|
49
52
|
"ink-spinner": "^5.0.0",
|
|
50
53
|
"ink-text-input": "^6.0.0",
|
|
54
|
+
"open": "^11.0.0",
|
|
51
55
|
"react": "^18.3.1",
|
|
52
56
|
"yargs": "^17.7.2"
|
|
53
57
|
},
|