@agent-coder/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -0
- package/dist/auth.d.ts +12 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +169 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +167 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +71 -0
- package/dist/config.js.map +1 -0
- package/dist/firebase.d.ts +25 -0
- package/dist/firebase.d.ts.map +1 -0
- package/dist/firebase.js +70 -0
- package/dist/firebase.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/tmux.d.ts +14 -0
- package/dist/tmux.d.ts.map +1 -0
- package/dist/tmux.js +105 -0
- package/dist/tmux.js.map +1 -0
- package/dist/watcher.d.ts +21 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +278 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @agent-coder/cli
|
|
2
|
+
|
|
3
|
+
Run AI coding agents (Claude, Gemini, Codex, Grok) on your machine, controlled from anywhere via [agentcoder.space](https://agentcoder.space).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @agent-coder/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### 1. Login with your account
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
agentcoder login
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This opens your browser for authentication. Once logged in, your credentials are stored locally.
|
|
20
|
+
|
|
21
|
+
### 2. Start the agent
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
agentcoder start <workspace-id>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The agent connects to your workspace and processes commands from the web UI.
|
|
28
|
+
|
|
29
|
+
### 3. Check status
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
agentcoder status
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Shows current login status and active tmux sessions.
|
|
36
|
+
|
|
37
|
+
## Commands
|
|
38
|
+
|
|
39
|
+
| Command | Description |
|
|
40
|
+
|---------|-------------|
|
|
41
|
+
| `agentcoder login` | Authenticate with your account |
|
|
42
|
+
| `agentcoder logout` | Clear stored credentials |
|
|
43
|
+
| `agentcoder start <workspace-id>` | Start the agent |
|
|
44
|
+
| `agentcoder status` | Show agent status |
|
|
45
|
+
| `agentcoder help` | Show help |
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
- Node.js 18+
|
|
50
|
+
- tmux (for terminal session management)
|
|
51
|
+
- One or more AI CLI tools installed:
|
|
52
|
+
- [Claude Code](https://claude.ai/code) - `claude`
|
|
53
|
+
- Gemini CLI - `gemini`
|
|
54
|
+
- Codex CLI - `codex`
|
|
55
|
+
- Grok CLI - `grok`
|
|
56
|
+
|
|
57
|
+
## How it works
|
|
58
|
+
|
|
59
|
+
1. The agent authenticates with your AgentCoder account
|
|
60
|
+
2. It connects to Firebase using your credentials
|
|
61
|
+
3. It watches for messages in your workspace
|
|
62
|
+
4. When you send a command from the web UI, the agent:
|
|
63
|
+
- Creates/attaches to a tmux session
|
|
64
|
+
- Sends the command to the AI CLI
|
|
65
|
+
- Captures the output
|
|
66
|
+
- Sends it back to the web UI
|
|
67
|
+
|
|
68
|
+
All communication happens through Firebase - your credentials never leave your machine.
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication module - handles browser OAuth flow.
|
|
3
|
+
*/
|
|
4
|
+
import { Credentials } from "./config.js";
|
|
5
|
+
/**
|
|
6
|
+
* Start OAuth login flow.
|
|
7
|
+
* Opens browser to web app, which handles OAuth and redirects back with tokens.
|
|
8
|
+
*/
|
|
9
|
+
export declare function login(): Promise<Credentials>;
|
|
10
|
+
export declare function logout(): Promise<void>;
|
|
11
|
+
export declare function getCredentials(): Credentials | null;
|
|
12
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,WAAW,EAAkE,MAAM,aAAa,CAAC;AAK1G;;;GAGG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,CA+ElD;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAG5C;AAED,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAEnD"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication module - handles browser OAuth flow.
|
|
3
|
+
*/
|
|
4
|
+
import { createServer } from "node:http";
|
|
5
|
+
import open from "open";
|
|
6
|
+
import { saveCredentials, loadCredentials, clearCredentials, loadConfig } from "./config.js";
|
|
7
|
+
const CALLBACK_PORT = 9876;
|
|
8
|
+
const CALLBACK_PATH = "/auth/callback";
|
|
9
|
+
/**
|
|
10
|
+
* Start OAuth login flow.
|
|
11
|
+
* Opens browser to web app, which handles OAuth and redirects back with tokens.
|
|
12
|
+
*/
|
|
13
|
+
export async function login() {
|
|
14
|
+
const config = loadConfig();
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const server = createServer((req, res) => {
|
|
17
|
+
const url = new URL(req.url || "/", `http://localhost:${CALLBACK_PORT}`);
|
|
18
|
+
if (url.pathname === CALLBACK_PATH) {
|
|
19
|
+
const accessToken = url.searchParams.get("accessToken");
|
|
20
|
+
const refreshToken = url.searchParams.get("refreshToken");
|
|
21
|
+
const uid = url.searchParams.get("uid");
|
|
22
|
+
const email = url.searchParams.get("email");
|
|
23
|
+
const displayName = url.searchParams.get("displayName");
|
|
24
|
+
const expiresIn = url.searchParams.get("expiresIn");
|
|
25
|
+
const error = url.searchParams.get("error");
|
|
26
|
+
if (error) {
|
|
27
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
28
|
+
res.end(errorPage(error));
|
|
29
|
+
server.close();
|
|
30
|
+
reject(new Error(error));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!accessToken || !uid) {
|
|
34
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
35
|
+
res.end(errorPage("Missing required authentication data"));
|
|
36
|
+
server.close();
|
|
37
|
+
reject(new Error("Missing required parameters from callback"));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const credentials = {
|
|
41
|
+
uid,
|
|
42
|
+
email: email || null,
|
|
43
|
+
displayName: displayName || null,
|
|
44
|
+
accessToken,
|
|
45
|
+
refreshToken: refreshToken || "",
|
|
46
|
+
expiresAt: Date.now() + parseInt(expiresIn || "3600", 10) * 1000,
|
|
47
|
+
};
|
|
48
|
+
saveCredentials(credentials);
|
|
49
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
50
|
+
res.end(successPage(displayName || email || "User"));
|
|
51
|
+
server.close();
|
|
52
|
+
resolve(credentials);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
res.writeHead(404);
|
|
56
|
+
res.end("Not found");
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
server.listen(CALLBACK_PORT, () => {
|
|
60
|
+
const loginUrl = `${config.webUrl}/#/auth/agent?callbackPort=${CALLBACK_PORT}&callbackPath=${encodeURIComponent(CALLBACK_PATH)}`;
|
|
61
|
+
console.log("");
|
|
62
|
+
console.log("Opening browser for login...");
|
|
63
|
+
console.log("");
|
|
64
|
+
console.log(`If browser doesn't open, visit:`);
|
|
65
|
+
console.log(` ${loginUrl}`);
|
|
66
|
+
console.log("");
|
|
67
|
+
open(loginUrl).catch(() => {
|
|
68
|
+
console.log("Could not open browser automatically.");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
server.on("error", (err) => {
|
|
72
|
+
reject(err);
|
|
73
|
+
});
|
|
74
|
+
// Timeout after 5 minutes
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
server.close();
|
|
77
|
+
reject(new Error("Login timed out after 5 minutes"));
|
|
78
|
+
}, 5 * 60 * 1000);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export async function logout() {
|
|
82
|
+
clearCredentials();
|
|
83
|
+
console.log("Logged out successfully.");
|
|
84
|
+
}
|
|
85
|
+
export function getCredentials() {
|
|
86
|
+
return loadCredentials();
|
|
87
|
+
}
|
|
88
|
+
function successPage(name) {
|
|
89
|
+
return `<!DOCTYPE html>
|
|
90
|
+
<html>
|
|
91
|
+
<head>
|
|
92
|
+
<title>AgentCoder - Login Successful</title>
|
|
93
|
+
<style>
|
|
94
|
+
body {
|
|
95
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
align-items: center;
|
|
99
|
+
height: 100vh;
|
|
100
|
+
margin: 0;
|
|
101
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
102
|
+
}
|
|
103
|
+
.container {
|
|
104
|
+
text-align: center;
|
|
105
|
+
color: white;
|
|
106
|
+
padding: 2rem;
|
|
107
|
+
}
|
|
108
|
+
.logo {
|
|
109
|
+
width: 64px;
|
|
110
|
+
height: 64px;
|
|
111
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
|
112
|
+
border-radius: 16px;
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
justify-content: center;
|
|
116
|
+
margin: 0 auto 1.5rem;
|
|
117
|
+
font-weight: bold;
|
|
118
|
+
font-size: 24px;
|
|
119
|
+
}
|
|
120
|
+
h1 { color: #4ade80; margin-bottom: 0.5rem; }
|
|
121
|
+
p { color: #94a3b8; }
|
|
122
|
+
.name { color: #60a5fa; }
|
|
123
|
+
</style>
|
|
124
|
+
</head>
|
|
125
|
+
<body>
|
|
126
|
+
<div class="container">
|
|
127
|
+
<div class="logo">AC</div>
|
|
128
|
+
<h1>Login Successful!</h1>
|
|
129
|
+
<p>Welcome, <span class="name">${name}</span>!</p>
|
|
130
|
+
<p>You can close this window and return to the terminal.</p>
|
|
131
|
+
</div>
|
|
132
|
+
</body>
|
|
133
|
+
</html>`;
|
|
134
|
+
}
|
|
135
|
+
function errorPage(error) {
|
|
136
|
+
return `<!DOCTYPE html>
|
|
137
|
+
<html>
|
|
138
|
+
<head>
|
|
139
|
+
<title>AgentCoder - Login Failed</title>
|
|
140
|
+
<style>
|
|
141
|
+
body {
|
|
142
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
143
|
+
display: flex;
|
|
144
|
+
justify-content: center;
|
|
145
|
+
align-items: center;
|
|
146
|
+
height: 100vh;
|
|
147
|
+
margin: 0;
|
|
148
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
149
|
+
}
|
|
150
|
+
.container {
|
|
151
|
+
text-align: center;
|
|
152
|
+
color: white;
|
|
153
|
+
padding: 2rem;
|
|
154
|
+
}
|
|
155
|
+
h1 { color: #f87171; margin-bottom: 0.5rem; }
|
|
156
|
+
p { color: #94a3b8; }
|
|
157
|
+
.error { color: #fbbf24; font-family: monospace; }
|
|
158
|
+
</style>
|
|
159
|
+
</head>
|
|
160
|
+
<body>
|
|
161
|
+
<div class="container">
|
|
162
|
+
<h1>Login Failed</h1>
|
|
163
|
+
<p class="error">${error}</p>
|
|
164
|
+
<p>Please try again.</p>
|
|
165
|
+
</div>
|
|
166
|
+
</body>
|
|
167
|
+
</html>`;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentCoder CLI - Run AI coding agents on your machine.
|
|
4
|
+
*/
|
|
5
|
+
import { login, logout, getCredentials } from "./auth.js";
|
|
6
|
+
import { loadConfig, isLoggedIn } from "./config.js";
|
|
7
|
+
import { initializeFirebase } from "./firebase.js";
|
|
8
|
+
import { FirestoreWatcher } from "./watcher.js";
|
|
9
|
+
import { listSessions } from "./tmux.js";
|
|
10
|
+
const VERSION = "0.1.0";
|
|
11
|
+
function showHelp() {
|
|
12
|
+
console.log(`
|
|
13
|
+
AgentCoder v${VERSION} - Run AI coding agents on your machine
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
agentcoder <command>
|
|
17
|
+
|
|
18
|
+
Commands:
|
|
19
|
+
start Start the agent and connect to relay
|
|
20
|
+
login Authenticate with your AgentCoder account
|
|
21
|
+
logout Clear stored credentials
|
|
22
|
+
status Show agent status and active sessions
|
|
23
|
+
help Show this help message
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
agentcoder login # Authenticate (opens browser)
|
|
27
|
+
agentcoder start # Start the agent
|
|
28
|
+
agentcoder status # Check status
|
|
29
|
+
|
|
30
|
+
Environment variables:
|
|
31
|
+
AGENTCODER_RELAY_URL Override the relay server URL
|
|
32
|
+
AGENTCODER_WEB_URL Override the web app URL
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
async function showStatus() {
|
|
36
|
+
const creds = getCredentials();
|
|
37
|
+
const config = loadConfig();
|
|
38
|
+
const sessions = listSessions();
|
|
39
|
+
console.log("");
|
|
40
|
+
console.log("AgentCoder Status");
|
|
41
|
+
console.log("=".repeat(40));
|
|
42
|
+
console.log("");
|
|
43
|
+
if (creds) {
|
|
44
|
+
console.log("Authentication:");
|
|
45
|
+
console.log(` Logged in as: ${creds.email || creds.uid}`);
|
|
46
|
+
console.log(` Name: ${creds.displayName || "(not set)"}`);
|
|
47
|
+
console.log(` Token expires: ${new Date(creds.expiresAt).toLocaleString()}`);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.log("Authentication:");
|
|
51
|
+
console.log(" Not logged in");
|
|
52
|
+
console.log(" Run 'agentcoder login' to authenticate");
|
|
53
|
+
}
|
|
54
|
+
console.log("");
|
|
55
|
+
console.log("Configuration:");
|
|
56
|
+
console.log(` Server ID: ${config.serverId}`);
|
|
57
|
+
console.log(` Server Name: ${config.serverName}`);
|
|
58
|
+
console.log(` Web URL: ${config.webUrl}`);
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log("Active Sessions:");
|
|
61
|
+
if (sessions.length === 0) {
|
|
62
|
+
console.log(" No active tmux sessions");
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
sessions.forEach((s) => console.log(` - ${s}`));
|
|
66
|
+
}
|
|
67
|
+
console.log("");
|
|
68
|
+
}
|
|
69
|
+
async function startAgent(workspaceId) {
|
|
70
|
+
if (!isLoggedIn()) {
|
|
71
|
+
console.error("Not logged in. Run 'agentcoder login' first.");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
const creds = getCredentials();
|
|
75
|
+
const config = loadConfig();
|
|
76
|
+
console.log("");
|
|
77
|
+
console.log("=".repeat(50));
|
|
78
|
+
console.log("AgentCoder Agent v" + VERSION);
|
|
79
|
+
console.log("=".repeat(50));
|
|
80
|
+
console.log("");
|
|
81
|
+
console.log(`User: ${creds.email || creds.uid}`);
|
|
82
|
+
console.log(`Server: ${config.serverName} (${config.serverId})`);
|
|
83
|
+
console.log("");
|
|
84
|
+
// Initialize Firebase with user credentials
|
|
85
|
+
console.log("Connecting to Firebase...");
|
|
86
|
+
try {
|
|
87
|
+
await initializeFirebase();
|
|
88
|
+
console.log("Connected!");
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
console.error("Failed to connect:", err instanceof Error ? err.message : err);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
// Get workspace ID (from args or prompt)
|
|
95
|
+
if (!workspaceId) {
|
|
96
|
+
// TODO: Fetch user's workspaces and let them choose
|
|
97
|
+
console.error("Please specify a workspace ID: agentcoder start <workspace-id>");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
const watcher = new FirestoreWatcher();
|
|
101
|
+
// Handle graceful shutdown
|
|
102
|
+
process.on("SIGINT", () => {
|
|
103
|
+
console.log("\nShutting down...");
|
|
104
|
+
watcher.stop();
|
|
105
|
+
process.exit(0);
|
|
106
|
+
});
|
|
107
|
+
process.on("SIGTERM", () => {
|
|
108
|
+
console.log("\nShutting down...");
|
|
109
|
+
watcher.stop();
|
|
110
|
+
process.exit(0);
|
|
111
|
+
});
|
|
112
|
+
try {
|
|
113
|
+
await watcher.start(workspaceId);
|
|
114
|
+
console.log("");
|
|
115
|
+
console.log("Agent is running. Press Ctrl+C to stop.");
|
|
116
|
+
console.log("");
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
console.error("Failed to start watcher:", err instanceof Error ? err.message : err);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function main() {
|
|
124
|
+
const command = process.argv[2];
|
|
125
|
+
switch (command) {
|
|
126
|
+
case "start":
|
|
127
|
+
await startAgent(process.argv[3]); // workspace ID as second arg
|
|
128
|
+
break;
|
|
129
|
+
case "login":
|
|
130
|
+
try {
|
|
131
|
+
const creds = await login();
|
|
132
|
+
console.log("");
|
|
133
|
+
console.log("Successfully logged in!");
|
|
134
|
+
console.log(` User: ${creds.displayName || creds.email || creds.uid}`);
|
|
135
|
+
console.log("");
|
|
136
|
+
console.log("You can now run 'agentcoder start' to connect.");
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
console.error("Login failed:", err instanceof Error ? err.message : err);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
case "logout":
|
|
144
|
+
await logout();
|
|
145
|
+
break;
|
|
146
|
+
case "status":
|
|
147
|
+
await showStatus();
|
|
148
|
+
break;
|
|
149
|
+
case "help":
|
|
150
|
+
case "--help":
|
|
151
|
+
case "-h":
|
|
152
|
+
showHelp();
|
|
153
|
+
break;
|
|
154
|
+
case undefined:
|
|
155
|
+
showHelp();
|
|
156
|
+
break;
|
|
157
|
+
default:
|
|
158
|
+
console.error(`Unknown command: ${command}`);
|
|
159
|
+
console.error("Run 'agentcoder help' for usage information.");
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
main().catch((err) => {
|
|
164
|
+
console.error("Error:", err);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
});
|
|
167
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration storage for the agent.
|
|
3
|
+
*/
|
|
4
|
+
export declare const DATA_DIR: string;
|
|
5
|
+
export declare const CONFIG_FILE: string;
|
|
6
|
+
export declare const CREDENTIALS_FILE: string;
|
|
7
|
+
export declare const DEFAULT_WEB_URL: string;
|
|
8
|
+
export interface Credentials {
|
|
9
|
+
uid: string;
|
|
10
|
+
email: string | null;
|
|
11
|
+
displayName: string | null;
|
|
12
|
+
accessToken: string;
|
|
13
|
+
refreshToken: string;
|
|
14
|
+
expiresAt: number;
|
|
15
|
+
}
|
|
16
|
+
export interface Config {
|
|
17
|
+
webUrl: string;
|
|
18
|
+
serverId: string;
|
|
19
|
+
serverName: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function loadConfig(): Config;
|
|
22
|
+
export declare function saveConfig(config: Config): void;
|
|
23
|
+
export declare function loadCredentials(): Credentials | null;
|
|
24
|
+
export declare function saveCredentials(creds: Credentials): void;
|
|
25
|
+
export declare function clearCredentials(): void;
|
|
26
|
+
export declare function isLoggedIn(): boolean;
|
|
27
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,eAAO,MAAM,QAAQ,QAAyC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAAqC,CAAC;AAC9D,eAAO,MAAM,gBAAgB,QAA0C,CAAC;AAGxE,eAAO,MAAM,eAAe,QAA+D,CAAC;AAE5F,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAQD,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/C;AAED,wBAAgB,eAAe,IAAI,WAAW,GAAG,IAAI,CAiBpD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAGxD;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAGpC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration storage for the agent.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
// Paths
|
|
8
|
+
export const DATA_DIR = path.join(os.homedir(), ".agentcoder");
|
|
9
|
+
export const CONFIG_FILE = path.join(DATA_DIR, "config.json");
|
|
10
|
+
export const CREDENTIALS_FILE = path.join(DATA_DIR, "credentials.json");
|
|
11
|
+
// Default URLs (your hosted service)
|
|
12
|
+
export const DEFAULT_WEB_URL = process.env.AGENTCODER_WEB_URL || "https://agentcoder.space";
|
|
13
|
+
function ensureDataDir() {
|
|
14
|
+
if (!existsSync(DATA_DIR)) {
|
|
15
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function loadConfig() {
|
|
19
|
+
ensureDataDir();
|
|
20
|
+
if (existsSync(CONFIG_FILE)) {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Fall through to defaults
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Generate default config
|
|
29
|
+
const config = {
|
|
30
|
+
webUrl: DEFAULT_WEB_URL,
|
|
31
|
+
serverId: `${os.hostname()}-${Math.random().toString(36).slice(2, 10)}`,
|
|
32
|
+
serverName: os.hostname(),
|
|
33
|
+
};
|
|
34
|
+
saveConfig(config);
|
|
35
|
+
return config;
|
|
36
|
+
}
|
|
37
|
+
export function saveConfig(config) {
|
|
38
|
+
ensureDataDir();
|
|
39
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
40
|
+
}
|
|
41
|
+
export function loadCredentials() {
|
|
42
|
+
try {
|
|
43
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const data = readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
47
|
+
const creds = JSON.parse(data);
|
|
48
|
+
// Check if expired
|
|
49
|
+
if (creds.expiresAt && creds.expiresAt <= Date.now()) {
|
|
50
|
+
return null; // Token expired
|
|
51
|
+
}
|
|
52
|
+
return creds;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function saveCredentials(creds) {
|
|
59
|
+
ensureDataDir();
|
|
60
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2));
|
|
61
|
+
}
|
|
62
|
+
export function clearCredentials() {
|
|
63
|
+
if (existsSync(CREDENTIALS_FILE)) {
|
|
64
|
+
writeFileSync(CREDENTIALS_FILE, "");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function isLoggedIn() {
|
|
68
|
+
const creds = loadCredentials();
|
|
69
|
+
return creds !== null;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase client SDK setup for the agent.
|
|
3
|
+
* Uses user credentials to access Firestore directly.
|
|
4
|
+
*/
|
|
5
|
+
import { User } from "firebase/auth";
|
|
6
|
+
import { Firestore, collection, doc, onSnapshot, updateDoc, addDoc, query, where, serverTimestamp, Unsubscribe } from "firebase/firestore";
|
|
7
|
+
export declare function initializeFirebase(): Promise<{
|
|
8
|
+
db: Firestore;
|
|
9
|
+
user: User;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function getDb(): Firestore;
|
|
12
|
+
export declare function getCurrentUser(): User | null;
|
|
13
|
+
export declare const paths: {
|
|
14
|
+
workspace: (workspaceId: string) => string;
|
|
15
|
+
agents: (workspaceId: string) => string;
|
|
16
|
+
agent: (workspaceId: string, agentId: string) => string;
|
|
17
|
+
sessions: (workspaceId: string, agentId: string) => string;
|
|
18
|
+
session: (workspaceId: string, agentId: string, sessionId: string) => string;
|
|
19
|
+
messages: (workspaceId: string, agentId: string, sessionId: string) => string;
|
|
20
|
+
servers: (workspaceId: string) => string;
|
|
21
|
+
server: (workspaceId: string, serverId: string) => string;
|
|
22
|
+
};
|
|
23
|
+
export { collection, doc, onSnapshot, updateDoc, addDoc, query, where, serverTimestamp };
|
|
24
|
+
export type { Unsubscribe };
|
|
25
|
+
//# sourceMappingURL=firebase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase.d.ts","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAIL,IAAI,EAEL,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,SAAS,EACT,UAAU,EACV,GAAG,EACH,UAAU,EACV,SAAS,EACT,MAAM,EACN,KAAK,EACL,KAAK,EACL,eAAe,EACf,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAgB5B,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAiCjF;AAED,wBAAgB,KAAK,IAAI,SAAS,CAGjC;AAED,wBAAgB,cAAc,IAAI,IAAI,GAAG,IAAI,CAE5C;AAGD,eAAO,MAAM,KAAK;6BACS,MAAM;0BACT,MAAM;yBACP,MAAM,WAAW,MAAM;4BAEpB,MAAM,WAAW,MAAM;2BAExB,MAAM,WAAW,MAAM,aAAa,MAAM;4BAEzC,MAAM,WAAW,MAAM,aAAa,MAAM;2BAE3C,MAAM;0BACP,MAAM,YAAY,MAAM;CAE/C,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;AACzF,YAAY,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/firebase.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase client SDK setup for the agent.
|
|
3
|
+
* Uses user credentials to access Firestore directly.
|
|
4
|
+
*/
|
|
5
|
+
import { initializeApp } from "firebase/app";
|
|
6
|
+
import { getAuth, signInWithCustomToken, onAuthStateChanged, } from "firebase/auth";
|
|
7
|
+
import { getFirestore, collection, doc, onSnapshot, updateDoc, addDoc, query, where, serverTimestamp, } from "firebase/firestore";
|
|
8
|
+
import { loadCredentials } from "./config.js";
|
|
9
|
+
// Firebase config - bundled with the agent
|
|
10
|
+
// These are client-side keys, safe to include
|
|
11
|
+
const firebaseConfig = {
|
|
12
|
+
apiKey: process.env.FIREBASE_API_KEY || "AIzaSyExample", // Will be replaced at build time
|
|
13
|
+
authDomain: process.env.FIREBASE_AUTH_DOMAIN || "your-project.firebaseapp.com",
|
|
14
|
+
projectId: process.env.FIREBASE_PROJECT_ID || "your-project-id",
|
|
15
|
+
};
|
|
16
|
+
let app = null;
|
|
17
|
+
let auth = null;
|
|
18
|
+
let db = null;
|
|
19
|
+
let currentUser = null;
|
|
20
|
+
export async function initializeFirebase() {
|
|
21
|
+
const credentials = loadCredentials();
|
|
22
|
+
if (!credentials) {
|
|
23
|
+
throw new Error("Not logged in. Run 'agentcoder login' first.");
|
|
24
|
+
}
|
|
25
|
+
// Initialize Firebase app
|
|
26
|
+
app = initializeApp(firebaseConfig);
|
|
27
|
+
auth = getAuth(app);
|
|
28
|
+
db = getFirestore(app);
|
|
29
|
+
// Sign in with the stored credentials
|
|
30
|
+
// Note: We need to handle token refresh properly
|
|
31
|
+
// For now, we'll use the access token to authenticate via a custom approach
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
// Listen for auth state changes
|
|
34
|
+
const unsubscribe = onAuthStateChanged(auth, (user) => {
|
|
35
|
+
if (user) {
|
|
36
|
+
currentUser = user;
|
|
37
|
+
unsubscribe();
|
|
38
|
+
resolve({ db: db, user });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
// Try to sign in with the stored token
|
|
42
|
+
// This requires the token to be a valid Firebase ID token or custom token
|
|
43
|
+
signInWithCustomToken(auth, credentials.accessToken)
|
|
44
|
+
.catch((error) => {
|
|
45
|
+
unsubscribe();
|
|
46
|
+
reject(new Error(`Authentication failed: ${error.message}`));
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function getDb() {
|
|
51
|
+
if (!db)
|
|
52
|
+
throw new Error("Firebase not initialized");
|
|
53
|
+
return db;
|
|
54
|
+
}
|
|
55
|
+
export function getCurrentUser() {
|
|
56
|
+
return currentUser;
|
|
57
|
+
}
|
|
58
|
+
// Firestore paths (same as bridge)
|
|
59
|
+
export const paths = {
|
|
60
|
+
workspace: (workspaceId) => `workspaces/${workspaceId}`,
|
|
61
|
+
agents: (workspaceId) => `workspaces/${workspaceId}/agents`,
|
|
62
|
+
agent: (workspaceId, agentId) => `workspaces/${workspaceId}/agents/${agentId}`,
|
|
63
|
+
sessions: (workspaceId, agentId) => `workspaces/${workspaceId}/agents/${agentId}/sessions`,
|
|
64
|
+
session: (workspaceId, agentId, sessionId) => `workspaces/${workspaceId}/agents/${agentId}/sessions/${sessionId}`,
|
|
65
|
+
messages: (workspaceId, agentId, sessionId) => `workspaces/${workspaceId}/agents/${agentId}/sessions/${sessionId}/messages`,
|
|
66
|
+
servers: (workspaceId) => `workspaces/${workspaceId}/servers`,
|
|
67
|
+
server: (workspaceId, serverId) => `workspaces/${workspaceId}/servers/${serverId}`,
|
|
68
|
+
};
|
|
69
|
+
export { collection, doc, onSnapshot, updateDoc, addDoc, query, where, serverTimestamp };
|
|
70
|
+
//# sourceMappingURL=firebase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase.js","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentCoder Agent - Run AI coding agents on your machine.
|
|
3
|
+
*
|
|
4
|
+
* This package provides a lightweight agent that uses Firebase Client SDK
|
|
5
|
+
* to connect directly to Firestore and process agent commands locally via tmux.
|
|
6
|
+
* No service account required - just login with your account.
|
|
7
|
+
*/
|
|
8
|
+
export { login, logout, getCredentials } from "./auth.js";
|
|
9
|
+
export { loadConfig, saveConfig, isLoggedIn, type Config, type Credentials } from "./config.js";
|
|
10
|
+
export { initializeFirebase, getDb, getCurrentUser, paths } from "./firebase.js";
|
|
11
|
+
export { FirestoreWatcher } from "./watcher.js";
|
|
12
|
+
export * as tmux from "./tmux.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentCoder Agent - Run AI coding agents on your machine.
|
|
3
|
+
*
|
|
4
|
+
* This package provides a lightweight agent that uses Firebase Client SDK
|
|
5
|
+
* to connect directly to Firestore and process agent commands locally via tmux.
|
|
6
|
+
* No service account required - just login with your account.
|
|
7
|
+
*/
|
|
8
|
+
export { login, logout, getCredentials } from "./auth.js";
|
|
9
|
+
export { loadConfig, saveConfig, isLoggedIn } from "./config.js";
|
|
10
|
+
export { initializeFirebase, getDb, getCurrentUser, paths } from "./firebase.js";
|
|
11
|
+
export { FirestoreWatcher } from "./watcher.js";
|
|
12
|
+
export * as tmux from "./tmux.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAiC,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC"}
|
package/dist/tmux.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tmux operations - handles local terminal sessions.
|
|
3
|
+
*/
|
|
4
|
+
export declare function sanitizeSessionName(name: string): string;
|
|
5
|
+
export declare function sessionExists(sessionName: string): boolean;
|
|
6
|
+
export declare function createSession(sessionName: string, workdir: string): boolean;
|
|
7
|
+
export declare function killSession(sessionName: string): boolean;
|
|
8
|
+
export declare function sendKeys(target: string, keys: string): void;
|
|
9
|
+
export declare function sendText(target: string, text: string): void;
|
|
10
|
+
export declare function capturePane(target: string, lines?: number): string;
|
|
11
|
+
export declare function startCli(target: string, cli: string, workdir: string): void;
|
|
12
|
+
export declare function listSessions(): string[];
|
|
13
|
+
export declare const CLI_COMMANDS: Record<string, string>;
|
|
14
|
+
//# sourceMappingURL=tmux.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../src/tmux.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAS1D;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAU3E;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAOxD;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM3D;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAe3D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,MAAM,CAWvE;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAQ3E;AAED,wBAAgB,YAAY,IAAI,MAAM,EAAE,CASvC;AAGD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK/C,CAAC"}
|
package/dist/tmux.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tmux operations - handles local terminal sessions.
|
|
3
|
+
*/
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
export function sanitizeSessionName(name) {
|
|
6
|
+
return name
|
|
7
|
+
.replace(/[^a-zA-Z0-9_-]/g, "_")
|
|
8
|
+
.replace(/^[^a-zA-Z]/, "s")
|
|
9
|
+
.slice(0, 50);
|
|
10
|
+
}
|
|
11
|
+
export function sessionExists(sessionName) {
|
|
12
|
+
try {
|
|
13
|
+
execSync(`tmux has-session -t "${sessionName}" 2>/dev/null`, {
|
|
14
|
+
stdio: "ignore",
|
|
15
|
+
});
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function createSession(sessionName, workdir) {
|
|
23
|
+
try {
|
|
24
|
+
execSync(`tmux new-session -d -s "${sessionName}" -c "${workdir}"`, {
|
|
25
|
+
stdio: "ignore",
|
|
26
|
+
});
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
console.error("Failed to create tmux session:", err);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function killSession(sessionName) {
|
|
35
|
+
try {
|
|
36
|
+
execSync(`tmux kill-session -t "${sessionName}"`, { stdio: "ignore" });
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function sendKeys(target, keys) {
|
|
44
|
+
try {
|
|
45
|
+
execSync(`tmux send-keys -t "${target}" ${keys}`, { stdio: "ignore" });
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error("Failed to send keys:", err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function sendText(target, text) {
|
|
52
|
+
try {
|
|
53
|
+
// Escape special characters for tmux
|
|
54
|
+
const escaped = text
|
|
55
|
+
.replace(/\\/g, "\\\\")
|
|
56
|
+
.replace(/"/g, '\\"')
|
|
57
|
+
.replace(/\$/g, "\\$")
|
|
58
|
+
.replace(/`/g, "\\`");
|
|
59
|
+
execSync(`tmux send-keys -t "${target}" "${escaped}" Enter`, {
|
|
60
|
+
stdio: "ignore",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.error("Failed to send text:", err);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function capturePane(target, lines = 100) {
|
|
68
|
+
try {
|
|
69
|
+
const output = execSync(`tmux capture-pane -t "${target}" -p -S -${lines}`, { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
|
|
70
|
+
return output;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
console.error("Failed to capture pane:", err);
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function startCli(target, cli, workdir) {
|
|
78
|
+
try {
|
|
79
|
+
execSync(`tmux send-keys -t "${target}" "cd '${workdir}' && ${cli}" Enter`, {
|
|
80
|
+
stdio: "ignore",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
console.error("Failed to start CLI:", err);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export function listSessions() {
|
|
88
|
+
try {
|
|
89
|
+
const output = execSync("tmux list-sessions -F '#{session_name}'", {
|
|
90
|
+
encoding: "utf-8",
|
|
91
|
+
});
|
|
92
|
+
return output.trim().split("\n").filter(Boolean);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// CLI commands for different AI agents
|
|
99
|
+
export const CLI_COMMANDS = {
|
|
100
|
+
claude: "claude --dangerously-skip-permissions",
|
|
101
|
+
gemini: "gemini",
|
|
102
|
+
grok: "grok",
|
|
103
|
+
codex: "codex",
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=tmux.js.map
|
package/dist/tmux.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../src/tmux.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firestore watcher - watches for messages and processes them locally.
|
|
3
|
+
* This replaces the bridge's watchers.ts for the user-run agent.
|
|
4
|
+
*/
|
|
5
|
+
export declare class FirestoreWatcher {
|
|
6
|
+
private config;
|
|
7
|
+
private unsubscribes;
|
|
8
|
+
private sessionWatchers;
|
|
9
|
+
start(workspaceId: string): Promise<void>;
|
|
10
|
+
private registerServer;
|
|
11
|
+
private startHeartbeat;
|
|
12
|
+
private watchSessionMessages;
|
|
13
|
+
private handleStartRequest;
|
|
14
|
+
private processMessage;
|
|
15
|
+
private captureOutput;
|
|
16
|
+
private handleSpecialCommand;
|
|
17
|
+
private updateAgent;
|
|
18
|
+
private unwatchAgent;
|
|
19
|
+
stop(): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoCH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,eAAe,CAAkC;IAEnD,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA2CjC,cAAc;IAc5B,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,oBAAoB;YAoCd,kBAAkB;YAkElB,cAAc;YA6Ed,aAAa;YAoCb,oBAAoB;YAqBpB,WAAW;IAUzB,OAAO,CAAC,YAAY;IAoBpB,IAAI,IAAI,IAAI;CAQb"}
|
package/dist/watcher.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firestore watcher - watches for messages and processes them locally.
|
|
3
|
+
* This replaces the bridge's watchers.ts for the user-run agent.
|
|
4
|
+
*/
|
|
5
|
+
import { getDb, paths, collection, doc, onSnapshot, updateDoc, addDoc, query, where, serverTimestamp, } from "./firebase.js";
|
|
6
|
+
import { loadConfig } from "./config.js";
|
|
7
|
+
import * as tmux from "./tmux.js";
|
|
8
|
+
export class FirestoreWatcher {
|
|
9
|
+
config = loadConfig();
|
|
10
|
+
unsubscribes = [];
|
|
11
|
+
sessionWatchers = new Map();
|
|
12
|
+
async start(workspaceId) {
|
|
13
|
+
const db = getDb();
|
|
14
|
+
console.log(`Watching workspace: ${workspaceId}`);
|
|
15
|
+
// Register this server
|
|
16
|
+
await this.registerServer(workspaceId);
|
|
17
|
+
// Watch agents for this workspace
|
|
18
|
+
const agentsRef = collection(db, paths.agents(workspaceId));
|
|
19
|
+
const unsubAgents = onSnapshot(agentsRef, (snapshot) => {
|
|
20
|
+
snapshot.docChanges().forEach((change) => {
|
|
21
|
+
const agentData = change.doc.data();
|
|
22
|
+
const agentId = change.doc.id;
|
|
23
|
+
// Only process agents assigned to this server (or unassigned)
|
|
24
|
+
if (agentData.serverId && agentData.serverId !== this.config.serverId) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (change.type === "removed") {
|
|
28
|
+
this.unwatchAgent(workspaceId, agentId, agentData.name);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// Watch messages for current session
|
|
32
|
+
if (agentData.currentSessionId) {
|
|
33
|
+
this.watchSessionMessages(workspaceId, agentId, agentData.currentSessionId);
|
|
34
|
+
}
|
|
35
|
+
// Handle start request
|
|
36
|
+
if (change.type === "modified" && agentData.startRequested) {
|
|
37
|
+
this.handleStartRequest(workspaceId, agentId, agentData);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
this.unsubscribes.push(unsubAgents);
|
|
42
|
+
// Start heartbeat
|
|
43
|
+
this.startHeartbeat(workspaceId);
|
|
44
|
+
}
|
|
45
|
+
async registerServer(workspaceId) {
|
|
46
|
+
const db = getDb();
|
|
47
|
+
const serverRef = doc(db, paths.server(workspaceId, this.config.serverId));
|
|
48
|
+
await updateDoc(serverRef, {
|
|
49
|
+
name: this.config.serverName,
|
|
50
|
+
status: "online",
|
|
51
|
+
lastHeartbeat: serverTimestamp(),
|
|
52
|
+
}).catch(() => {
|
|
53
|
+
// Document might not exist, create it
|
|
54
|
+
// Note: setDoc would be better here but we're using updateDoc for simplicity
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
startHeartbeat(workspaceId) {
|
|
58
|
+
setInterval(async () => {
|
|
59
|
+
try {
|
|
60
|
+
const db = getDb();
|
|
61
|
+
const serverRef = doc(db, paths.server(workspaceId, this.config.serverId));
|
|
62
|
+
await updateDoc(serverRef, {
|
|
63
|
+
lastHeartbeat: serverTimestamp(),
|
|
64
|
+
status: "online",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
console.error("Heartbeat failed:", err);
|
|
69
|
+
}
|
|
70
|
+
}, 30000);
|
|
71
|
+
}
|
|
72
|
+
watchSessionMessages(workspaceId, agentId, sessionId) {
|
|
73
|
+
const key = `${agentId}:${sessionId}`;
|
|
74
|
+
// Already watching this session
|
|
75
|
+
if (this.sessionWatchers.has(key))
|
|
76
|
+
return;
|
|
77
|
+
const db = getDb();
|
|
78
|
+
const messagesRef = collection(db, paths.messages(workspaceId, agentId, sessionId));
|
|
79
|
+
const q = query(messagesRef, where("role", "==", "user"), where("status", "==", "pending"));
|
|
80
|
+
const unsubscribe = onSnapshot(q, (snapshot) => {
|
|
81
|
+
snapshot.docChanges().forEach((change) => {
|
|
82
|
+
if (change.type === "added") {
|
|
83
|
+
const data = change.doc.data();
|
|
84
|
+
this.processMessage(workspaceId, agentId, sessionId, change.doc.id, data.content);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
this.sessionWatchers.set(key, unsubscribe);
|
|
89
|
+
}
|
|
90
|
+
async handleStartRequest(workspaceId, agentId, agentData) {
|
|
91
|
+
const clientType = agentData.requestedClientType || "claude";
|
|
92
|
+
const workdir = agentData.workdir || "";
|
|
93
|
+
console.log(`Starting session for ${agentData.name} (${clientType})`);
|
|
94
|
+
if (!workdir) {
|
|
95
|
+
console.error("Cannot start: workdir is empty");
|
|
96
|
+
await this.updateAgent(workspaceId, agentId, {
|
|
97
|
+
startRequested: false,
|
|
98
|
+
requestedClientType: null,
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Claim this agent for this server
|
|
103
|
+
await this.updateAgent(workspaceId, agentId, {
|
|
104
|
+
serverId: this.config.serverId,
|
|
105
|
+
});
|
|
106
|
+
const sessionName = tmux.sanitizeSessionName(agentData.name || agentId);
|
|
107
|
+
const target = `${sessionName}:0.0`;
|
|
108
|
+
let success = false;
|
|
109
|
+
if (tmux.sessionExists(target)) {
|
|
110
|
+
success = true;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
success = tmux.createSession(sessionName, workdir);
|
|
114
|
+
if (success) {
|
|
115
|
+
const cli = tmux.CLI_COMMANDS[clientType] || tmux.CLI_COMMANDS.claude;
|
|
116
|
+
tmux.startCli(target, cli, workdir);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Create a new session document
|
|
120
|
+
if (success) {
|
|
121
|
+
const db = getDb();
|
|
122
|
+
const sessionsRef = collection(db, paths.sessions(workspaceId, agentId));
|
|
123
|
+
const sessionDoc = await addDoc(sessionsRef, {
|
|
124
|
+
clientType,
|
|
125
|
+
status: "active",
|
|
126
|
+
startedAt: serverTimestamp(),
|
|
127
|
+
});
|
|
128
|
+
await this.updateAgent(workspaceId, agentId, {
|
|
129
|
+
active: true,
|
|
130
|
+
startRequested: false,
|
|
131
|
+
requestedClientType: null,
|
|
132
|
+
currentSessionId: sessionDoc.id,
|
|
133
|
+
});
|
|
134
|
+
console.log(`Session started: ${sessionDoc.id}`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
await this.updateAgent(workspaceId, agentId, {
|
|
138
|
+
active: false,
|
|
139
|
+
startRequested: false,
|
|
140
|
+
requestedClientType: null,
|
|
141
|
+
});
|
|
142
|
+
console.error("Failed to start session");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async processMessage(workspaceId, agentId, sessionId, messageId, content) {
|
|
146
|
+
console.log(`Processing message: "${content.slice(0, 50)}..."`);
|
|
147
|
+
const db = getDb();
|
|
148
|
+
const messageRef = doc(db, paths.messages(workspaceId, agentId, sessionId), messageId);
|
|
149
|
+
// Mark as processing
|
|
150
|
+
await updateDoc(messageRef, { status: "processing" });
|
|
151
|
+
// Mark agent as busy
|
|
152
|
+
await this.updateAgent(workspaceId, agentId, { busy: true });
|
|
153
|
+
try {
|
|
154
|
+
// Get agent data for session name
|
|
155
|
+
const agentRef = doc(db, paths.agent(workspaceId, agentId));
|
|
156
|
+
// We'd need to get the agent data here - simplified for now
|
|
157
|
+
const sessionName = tmux.sanitizeSessionName(agentId);
|
|
158
|
+
const target = `${sessionName}:0.0`;
|
|
159
|
+
if (!tmux.sessionExists(target)) {
|
|
160
|
+
await updateDoc(messageRef, {
|
|
161
|
+
status: "error",
|
|
162
|
+
error: "Session not found",
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Create assistant message
|
|
167
|
+
const messagesRef = collection(db, paths.messages(workspaceId, agentId, sessionId));
|
|
168
|
+
const assistantRef = await addDoc(messagesRef, {
|
|
169
|
+
role: "assistant",
|
|
170
|
+
content: "",
|
|
171
|
+
timestamp: serverTimestamp(),
|
|
172
|
+
status: "processing",
|
|
173
|
+
});
|
|
174
|
+
// Handle special commands
|
|
175
|
+
if (content.startsWith("!")) {
|
|
176
|
+
const response = await this.handleSpecialCommand(target, content);
|
|
177
|
+
await updateDoc(assistantRef, {
|
|
178
|
+
content: response,
|
|
179
|
+
status: "complete",
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Send command and capture output
|
|
184
|
+
tmux.sendText(target, content);
|
|
185
|
+
const response = await this.captureOutput(target, assistantRef);
|
|
186
|
+
await updateDoc(assistantRef, {
|
|
187
|
+
content: response,
|
|
188
|
+
status: "complete",
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
await updateDoc(messageRef, { status: "complete" });
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
await updateDoc(messageRef, {
|
|
195
|
+
status: "error",
|
|
196
|
+
error: err instanceof Error ? err.message : String(err),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
await this.updateAgent(workspaceId, agentId, { busy: false });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async captureOutput(target, assistantRef) {
|
|
204
|
+
let lastOutput = "";
|
|
205
|
+
let stableCount = 0;
|
|
206
|
+
const maxWait = 300000; // 5 minutes
|
|
207
|
+
const startTime = Date.now();
|
|
208
|
+
while (Date.now() - startTime < maxWait) {
|
|
209
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
210
|
+
const output = tmux.capturePane(target, 100);
|
|
211
|
+
if (output !== lastOutput) {
|
|
212
|
+
lastOutput = output;
|
|
213
|
+
stableCount = 0;
|
|
214
|
+
// Send partial update
|
|
215
|
+
await updateDoc(assistantRef, {
|
|
216
|
+
content: output,
|
|
217
|
+
status: "processing",
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
stableCount++;
|
|
222
|
+
// If output is stable for 3 seconds, consider it complete
|
|
223
|
+
if (stableCount >= 6) {
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return lastOutput || "(no output)";
|
|
229
|
+
}
|
|
230
|
+
async handleSpecialCommand(target, content) {
|
|
231
|
+
if (content === "!screen") {
|
|
232
|
+
return tmux.capturePane(target, 50);
|
|
233
|
+
}
|
|
234
|
+
else if (content === "!fullscreen") {
|
|
235
|
+
return tmux.capturePane(target, 200);
|
|
236
|
+
}
|
|
237
|
+
else if (content === "!ctrl+c" || content === "!c") {
|
|
238
|
+
tmux.sendKeys(target, "C-c");
|
|
239
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
240
|
+
return tmux.capturePane(target, 30);
|
|
241
|
+
}
|
|
242
|
+
else if (content === "!enter") {
|
|
243
|
+
tmux.sendKeys(target, "Enter");
|
|
244
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
245
|
+
return tmux.capturePane(target, 30);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
return tmux.capturePane(target, 30);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async updateAgent(workspaceId, agentId, data) {
|
|
252
|
+
const db = getDb();
|
|
253
|
+
const agentRef = doc(db, paths.agent(workspaceId, agentId));
|
|
254
|
+
await updateDoc(agentRef, data);
|
|
255
|
+
}
|
|
256
|
+
unwatchAgent(workspaceId, agentId, agentName) {
|
|
257
|
+
// Remove session watchers for this agent
|
|
258
|
+
for (const [key, unsub] of this.sessionWatchers) {
|
|
259
|
+
if (key.startsWith(`${agentId}:`)) {
|
|
260
|
+
unsub();
|
|
261
|
+
this.sessionWatchers.delete(key);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Kill tmux session
|
|
265
|
+
if (agentName) {
|
|
266
|
+
const sessionName = tmux.sanitizeSessionName(agentName);
|
|
267
|
+
tmux.killSession(sessionName);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
stop() {
|
|
271
|
+
// Unsubscribe all watchers
|
|
272
|
+
this.unsubscribes.forEach((unsub) => unsub());
|
|
273
|
+
this.unsubscribes = [];
|
|
274
|
+
this.sessionWatchers.forEach((unsub) => unsub());
|
|
275
|
+
this.sessionWatchers.clear();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-coder/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AgentCoder - Run AI coding agents on your machine",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentcoder": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/cli.js start",
|
|
14
|
+
"login": "node dist/cli.js login",
|
|
15
|
+
"logout": "node dist/cli.js logout",
|
|
16
|
+
"status": "node dist/cli.js status"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"ai",
|
|
24
|
+
"coding",
|
|
25
|
+
"agent",
|
|
26
|
+
"claude",
|
|
27
|
+
"gemini",
|
|
28
|
+
"codex"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"firebase": "^11.0.0",
|
|
33
|
+
"open": "^10.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.10.0",
|
|
37
|
+
"typescript": "^5.3.0"
|
|
38
|
+
}
|
|
39
|
+
}
|