agent-relay 1.2.3 → 1.3.1
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/.trajectories/agent-relay-322-324.md +17 -0
- package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.json +49 -0
- package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.md +31 -0
- package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.json +125 -0
- package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.md +62 -0
- package/.trajectories/completed/2026-01/traj_33iuy72sezbk.json +49 -0
- package/.trajectories/completed/2026-01/traj_33iuy72sezbk.md +31 -0
- package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.json +77 -0
- package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.md +42 -0
- package/.trajectories/completed/2026-01/traj_6mieijqyvaag.json +77 -0
- package/.trajectories/completed/2026-01/traj_6mieijqyvaag.md +42 -0
- package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.json +77 -0
- package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.md +42 -0
- package/.trajectories/completed/2026-01/traj_94gnp3k30goq.json +66 -0
- package/.trajectories/completed/2026-01/traj_94gnp3k30goq.md +36 -0
- package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.json +40 -0
- package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.md +22 -0
- package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.json +121 -0
- package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.md +29 -0
- package/.trajectories/completed/2026-01/traj_fhx9irlckht6.json +53 -0
- package/.trajectories/completed/2026-01/traj_fhx9irlckht6.md +32 -0
- package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.json +101 -0
- package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.md +52 -0
- package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.json +49 -0
- package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.md +31 -0
- package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.json +65 -0
- package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.md +37 -0
- package/.trajectories/completed/2026-01/traj_lq450ly148uw.json +49 -0
- package/.trajectories/completed/2026-01/traj_lq450ly148uw.md +31 -0
- package/.trajectories/completed/2026-01/traj_multi_server_arch.md +101 -0
- package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.json +27 -0
- package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.md +14 -0
- package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.json +53 -0
- package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.md +32 -0
- package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.json +186 -0
- package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.md +86 -0
- package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.json +77 -0
- package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.md +42 -0
- package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.json +89 -0
- package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.md +47 -0
- package/.trajectories/completed/2026-01/traj_xy9vifpqet80.json +65 -0
- package/.trajectories/completed/2026-01/traj_xy9vifpqet80.md +37 -0
- package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.json +49 -0
- package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.md +31 -0
- package/.trajectories/consolidate-settings-panel.md +24 -0
- package/.trajectories/gh-cli-user-token.md +26 -0
- package/.trajectories/index.json +155 -1
- package/deploy/workspace/codex.config.toml +15 -0
- package/deploy/workspace/entrypoint.sh +167 -7
- package/deploy/workspace/git-credential-relay +17 -2
- package/dist/bridge/spawner.d.ts +7 -0
- package/dist/bridge/spawner.js +40 -9
- package/dist/bridge/types.d.ts +2 -0
- package/dist/cli/index.js +210 -168
- package/dist/cloud/api/admin.d.ts +8 -0
- package/dist/cloud/api/admin.js +212 -0
- package/dist/cloud/api/auth.js +8 -0
- package/dist/cloud/api/billing.d.ts +0 -10
- package/dist/cloud/api/billing.js +248 -58
- package/dist/cloud/api/codex-auth-helper.d.ts +10 -4
- package/dist/cloud/api/codex-auth-helper.js +215 -8
- package/dist/cloud/api/coordinators.js +402 -0
- package/dist/cloud/api/daemons.js +15 -11
- package/dist/cloud/api/git.js +104 -17
- package/dist/cloud/api/github-app.js +42 -8
- package/dist/cloud/api/nango-auth.js +297 -16
- package/dist/cloud/api/onboarding.js +97 -33
- package/dist/cloud/api/providers.js +12 -16
- package/dist/cloud/api/repos.js +200 -124
- package/dist/cloud/api/test-helpers.js +40 -0
- package/dist/cloud/api/usage.js +13 -0
- package/dist/cloud/api/webhooks.js +1 -1
- package/dist/cloud/api/workspaces.d.ts +18 -0
- package/dist/cloud/api/workspaces.js +945 -15
- package/dist/cloud/config.d.ts +8 -0
- package/dist/cloud/config.js +15 -0
- package/dist/cloud/db/drizzle.d.ts +5 -2
- package/dist/cloud/db/drizzle.js +27 -20
- package/dist/cloud/db/schema.d.ts +19 -51
- package/dist/cloud/db/schema.js +5 -4
- package/dist/cloud/index.d.ts +0 -1
- package/dist/cloud/index.js +0 -1
- package/dist/cloud/provisioner/index.d.ts +93 -1
- package/dist/cloud/provisioner/index.js +608 -63
- package/dist/cloud/server.js +156 -16
- package/dist/cloud/services/compute-enforcement.d.ts +57 -0
- package/dist/cloud/services/compute-enforcement.js +175 -0
- package/dist/cloud/services/index.d.ts +2 -0
- package/dist/cloud/services/index.js +4 -0
- package/dist/cloud/services/intro-expiration.d.ts +55 -0
- package/dist/cloud/services/intro-expiration.js +211 -0
- package/dist/cloud/services/nango.d.ts +14 -0
- package/dist/cloud/services/nango.js +74 -14
- package/dist/cloud/services/ssh-security.d.ts +31 -0
- package/dist/cloud/services/ssh-security.js +63 -0
- package/dist/continuity/manager.d.ts +5 -0
- package/dist/continuity/manager.js +56 -2
- package/dist/daemon/api.d.ts +2 -0
- package/dist/daemon/api.js +214 -5
- package/dist/daemon/cli-auth.d.ts +13 -1
- package/dist/daemon/cli-auth.js +166 -47
- package/dist/daemon/connection.d.ts +7 -1
- package/dist/daemon/connection.js +15 -0
- package/dist/daemon/orchestrator.d.ts +2 -0
- package/dist/daemon/orchestrator.js +26 -0
- package/dist/daemon/repo-manager.d.ts +116 -0
- package/dist/daemon/repo-manager.js +384 -0
- package/dist/daemon/router.d.ts +60 -1
- package/dist/daemon/router.js +281 -20
- package/dist/daemon/user-directory.d.ts +111 -0
- package/dist/daemon/user-directory.js +233 -0
- package/dist/dashboard/out/404.html +1 -1
- package/dist/dashboard/out/_next/static/chunks/532-bace199897eeab37.js +9 -0
- package/dist/dashboard/out/_next/static/chunks/766-b54f0853794b78c3.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/83-b51836037078006c.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/891-6cd50de1224f70bb.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/899-fc02ed79e3de4302.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/{page-3fdfa60e53f2810d.js → page-8553743baca53a00.js} +1 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/page-c617745b81344f4f.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-f829604fb75a831a.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/{page-77e9c65420a06cfb.js → page-dc786c183425c2ac.js} +1 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-84322991d7244499.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-05606941a8e2be83.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/{main-ed4e1fb6f29c34cf.js → main-2ee6beb2ae96d210.js} +1 -1
- package/dist/dashboard/out/_next/static/css/48a8fbe3e659080e.css +1 -0
- package/dist/dashboard/out/_next/static/css/fe4b28883eeff359.css +1 -0
- package/dist/dashboard/out/_next/static/sDcbGRTYLcpPvyTs_rsNb/_ssgManifest.js +1 -0
- package/dist/dashboard/out/app/onboarding.html +1 -1
- package/dist/dashboard/out/app/onboarding.txt +3 -3
- package/dist/dashboard/out/app.html +1 -1
- package/dist/dashboard/out/app.txt +3 -3
- package/dist/dashboard/out/apple-icon.png +0 -0
- package/dist/dashboard/out/connect-repos.html +1 -1
- package/dist/dashboard/out/connect-repos.txt +2 -2
- package/dist/dashboard/out/history.html +1 -1
- package/dist/dashboard/out/history.txt +2 -2
- package/dist/dashboard/out/index.html +1 -1
- package/dist/dashboard/out/index.txt +3 -3
- package/dist/dashboard/out/login.html +2 -2
- package/dist/dashboard/out/login.txt +2 -2
- package/dist/dashboard/out/metrics.html +1 -1
- package/dist/dashboard/out/metrics.txt +3 -3
- package/dist/dashboard/out/pricing.html +2 -2
- package/dist/dashboard/out/pricing.txt +3 -3
- package/dist/dashboard/out/providers/setup/claude.html +1 -0
- package/dist/dashboard/out/providers/setup/claude.txt +8 -0
- package/dist/dashboard/out/providers/setup/codex.html +1 -0
- package/dist/dashboard/out/providers/setup/codex.txt +8 -0
- package/dist/dashboard/out/providers.html +1 -1
- package/dist/dashboard/out/providers.txt +3 -3
- package/dist/dashboard/out/signup.html +2 -2
- package/dist/dashboard/out/signup.txt +2 -2
- package/dist/dashboard-server/server.js +316 -12
- package/dist/dashboard-server/user-bridge.d.ts +103 -0
- package/dist/dashboard-server/user-bridge.js +189 -0
- package/dist/protocol/channels.d.ts +205 -0
- package/dist/protocol/channels.js +154 -0
- package/dist/protocol/types.d.ts +13 -1
- package/dist/resiliency/provider-context.js +2 -0
- package/dist/shared/cli-auth-config.d.ts +19 -0
- package/dist/shared/cli-auth-config.js +58 -2
- package/dist/utils/agent-config.js +1 -1
- package/dist/wrapper/auth-detection.d.ts +49 -0
- package/dist/wrapper/auth-detection.js +192 -0
- package/dist/wrapper/base-wrapper.d.ts +153 -0
- package/dist/wrapper/base-wrapper.js +393 -0
- package/dist/wrapper/client.d.ts +7 -1
- package/dist/wrapper/client.js +3 -0
- package/dist/wrapper/index.d.ts +1 -0
- package/dist/wrapper/index.js +4 -3
- package/dist/wrapper/pty-wrapper.d.ts +62 -84
- package/dist/wrapper/pty-wrapper.js +154 -180
- package/dist/wrapper/tmux-wrapper.d.ts +41 -66
- package/dist/wrapper/tmux-wrapper.js +90 -134
- package/package.json +4 -2
- package/scripts/postinstall.js +11 -155
- package/scripts/test-interactive-terminal.sh +248 -0
- package/dist/cloud/vault/index.d.ts +0 -76
- package/dist/cloud/vault/index.js +0 -219
- package/dist/dashboard/out/_next/static/chunks/699-3b1cd6618a45d259.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/724-2dae7627550ab88f.js +0 -9
- package/dist/dashboard/out/_next/static/chunks/766-1f2dd8cb7f766b0b.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/page-e6381e5a6e1fbcfd.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-67a3e98d9a43a6ed.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-e88bc117ef7671c3.js +0 -1
- package/dist/dashboard/out/_next/static/css/29852f26181969a0.css +0 -1
- package/dist/dashboard/out/_next/static/css/7c3ae9e8617d42a5.css +0 -1
- package/dist/dashboard/out/_next/static/wPgKJtcOmTFLpUncDg16A/_ssgManifest.js +0 -1
- /package/dist/dashboard/out/_next/static/{wPgKJtcOmTFLpUncDg16A → sDcbGRTYLcpPvyTs_rsNb}/_buildManifest.js +0 -0
package/scripts/postinstall.js
CHANGED
|
@@ -3,18 +3,14 @@
|
|
|
3
3
|
* Postinstall Script for agent-relay
|
|
4
4
|
*
|
|
5
5
|
* This script runs after npm install to:
|
|
6
|
-
* 1.
|
|
7
|
-
* 2.
|
|
8
|
-
*
|
|
9
|
-
* The tmux binary is installed within the package itself (bin/tmux),
|
|
10
|
-
* making it portable and not requiring global installation.
|
|
6
|
+
* 1. Install dashboard dependencies
|
|
7
|
+
* 2. Patch agent-trajectories CLI
|
|
8
|
+
* 3. Check for tmux availability
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
11
|
import { execSync } from 'node:child_process';
|
|
14
|
-
import os from 'node:os';
|
|
15
12
|
import path from 'node:path';
|
|
16
13
|
import fs from 'node:fs';
|
|
17
|
-
import https from 'node:https';
|
|
18
14
|
import { fileURLToPath } from 'node:url';
|
|
19
15
|
|
|
20
16
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -25,18 +21,12 @@ function getPackageRoot() {
|
|
|
25
21
|
return path.resolve(__dirname, '..');
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
/** Installation directory (within the package) */
|
|
29
|
-
function getInstallDir() {
|
|
30
|
-
return path.join(getPackageRoot(), 'bin');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
24
|
// Colors for console output
|
|
34
25
|
const colors = {
|
|
35
26
|
reset: '\x1b[0m',
|
|
36
27
|
green: '\x1b[32m',
|
|
37
28
|
yellow: '\x1b[33m',
|
|
38
29
|
blue: '\x1b[34m',
|
|
39
|
-
red: '\x1b[31m',
|
|
40
30
|
};
|
|
41
31
|
|
|
42
32
|
function info(msg) {
|
|
@@ -51,10 +41,6 @@ function warn(msg) {
|
|
|
51
41
|
console.log(`${colors.yellow}[warn]${colors.reset} ${msg}`);
|
|
52
42
|
}
|
|
53
43
|
|
|
54
|
-
function error(msg) {
|
|
55
|
-
console.log(`${colors.red}[error]${colors.reset} ${msg}`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
44
|
/**
|
|
59
45
|
* Check if tmux is available on the system
|
|
60
46
|
*/
|
|
@@ -67,137 +53,6 @@ function hasSystemTmux() {
|
|
|
67
53
|
}
|
|
68
54
|
}
|
|
69
55
|
|
|
70
|
-
/**
|
|
71
|
-
* Get platform identifier for tmux-builds
|
|
72
|
-
*/
|
|
73
|
-
function getPlatformId() {
|
|
74
|
-
const platform = os.platform();
|
|
75
|
-
const arch = os.arch();
|
|
76
|
-
|
|
77
|
-
if (platform === 'darwin') {
|
|
78
|
-
return arch === 'arm64' ? 'macos-arm64' : 'macos-x86_64';
|
|
79
|
-
} else if (platform === 'linux') {
|
|
80
|
-
return arch === 'arm64' ? 'linux-arm64' : 'linux-x86_64';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Download file with redirect support
|
|
88
|
-
*/
|
|
89
|
-
function downloadFile(url, destPath) {
|
|
90
|
-
return new Promise((resolve, reject) => {
|
|
91
|
-
const file = fs.createWriteStream(destPath);
|
|
92
|
-
|
|
93
|
-
const request = (currentUrl, redirectCount = 0) => {
|
|
94
|
-
if (redirectCount > 5) {
|
|
95
|
-
reject(new Error('Too many redirects'));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const urlObj = new URL(currentUrl);
|
|
100
|
-
const options = {
|
|
101
|
-
hostname: urlObj.hostname,
|
|
102
|
-
path: urlObj.pathname + urlObj.search,
|
|
103
|
-
headers: {
|
|
104
|
-
'User-Agent': 'agent-relay-installer',
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
https
|
|
109
|
-
.get(options, (response) => {
|
|
110
|
-
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
111
|
-
const location = response.headers.location;
|
|
112
|
-
if (location) {
|
|
113
|
-
request(location, redirectCount + 1);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (response.statusCode !== 200) {
|
|
119
|
-
reject(new Error(`HTTP ${response.statusCode}`));
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
response.pipe(file);
|
|
124
|
-
file.on('finish', () => {
|
|
125
|
-
file.close();
|
|
126
|
-
resolve();
|
|
127
|
-
});
|
|
128
|
-
})
|
|
129
|
-
.on('error', reject);
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
request(url);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Install tmux binary
|
|
138
|
-
*/
|
|
139
|
-
async function installTmux() {
|
|
140
|
-
const TMUX_VERSION = '3.6a';
|
|
141
|
-
const INSTALL_DIR = getInstallDir();
|
|
142
|
-
const tmuxPath = path.join(INSTALL_DIR, 'tmux');
|
|
143
|
-
|
|
144
|
-
// Check if already installed
|
|
145
|
-
if (fs.existsSync(tmuxPath)) {
|
|
146
|
-
info('Bundled tmux already installed');
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const platformId = getPlatformId();
|
|
151
|
-
if (!platformId) {
|
|
152
|
-
const platform = os.platform();
|
|
153
|
-
warn(`Unsupported platform: ${platform} ${os.arch()}`);
|
|
154
|
-
if (platform === 'win32') {
|
|
155
|
-
warn('tmux requires WSL (Windows Subsystem for Linux)');
|
|
156
|
-
warn('Install WSL first, then run: sudo apt install tmux');
|
|
157
|
-
} else {
|
|
158
|
-
warn('Please install tmux manually: https://github.com/tmux/tmux/wiki/Installing');
|
|
159
|
-
}
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
info(`Installing tmux ${TMUX_VERSION} for ${platformId}...`);
|
|
164
|
-
|
|
165
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-relay-tmux-'));
|
|
166
|
-
const archiveName = `tmux-${TMUX_VERSION}-${platformId}.tar.gz`;
|
|
167
|
-
const archivePath = path.join(tmpDir, archiveName);
|
|
168
|
-
const downloadUrl = `https://github.com/tmux/tmux-builds/releases/download/v${TMUX_VERSION}/${archiveName}`;
|
|
169
|
-
|
|
170
|
-
try {
|
|
171
|
-
info('Downloading tmux binary...');
|
|
172
|
-
await downloadFile(downloadUrl, archivePath);
|
|
173
|
-
|
|
174
|
-
info('Extracting...');
|
|
175
|
-
execSync(`tar -xzf "${archivePath}" -C "${tmpDir}"`, { stdio: 'pipe' });
|
|
176
|
-
|
|
177
|
-
const extractedTmux = path.join(tmpDir, 'tmux');
|
|
178
|
-
if (!fs.existsSync(extractedTmux)) {
|
|
179
|
-
throw new Error('tmux binary not found in archive');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
183
|
-
fs.copyFileSync(extractedTmux, tmuxPath);
|
|
184
|
-
fs.chmodSync(tmuxPath, 0o755);
|
|
185
|
-
|
|
186
|
-
success(`Installed tmux to ${tmuxPath}`);
|
|
187
|
-
return true;
|
|
188
|
-
} catch (err) {
|
|
189
|
-
error(`Failed to install tmux: ${err.message}`);
|
|
190
|
-
warn('Please install tmux manually, then reinstall: npm install agent-relay');
|
|
191
|
-
return false;
|
|
192
|
-
} finally {
|
|
193
|
-
try {
|
|
194
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
195
|
-
} catch {
|
|
196
|
-
// Ignore
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
56
|
/**
|
|
202
57
|
* Install dashboard dependencies
|
|
203
58
|
*/
|
|
@@ -220,7 +75,7 @@ function installDashboardDeps() {
|
|
|
220
75
|
execSync('npm install', { cwd: dashboardDir, stdio: 'inherit' });
|
|
221
76
|
success('Dashboard dependencies installed');
|
|
222
77
|
} catch (err) {
|
|
223
|
-
|
|
78
|
+
warn(`Failed to install dashboard dependencies: ${err.message}`);
|
|
224
79
|
}
|
|
225
80
|
}
|
|
226
81
|
|
|
@@ -291,9 +146,8 @@ async function main() {
|
|
|
291
146
|
// Always install dashboard dependencies (needed for build)
|
|
292
147
|
installDashboardDeps();
|
|
293
148
|
|
|
294
|
-
// Skip tmux
|
|
149
|
+
// Skip tmux check in CI environments
|
|
295
150
|
if (process.env.CI === 'true') {
|
|
296
|
-
info('Skipping tmux install in CI environment');
|
|
297
151
|
return;
|
|
298
152
|
}
|
|
299
153
|
|
|
@@ -303,12 +157,14 @@ async function main() {
|
|
|
303
157
|
return;
|
|
304
158
|
}
|
|
305
159
|
|
|
306
|
-
//
|
|
307
|
-
|
|
160
|
+
// Recommend user installs tmux manually
|
|
161
|
+
warn('tmux not found on system');
|
|
162
|
+
info('To use tmux mode, install tmux:');
|
|
163
|
+
info(' macOS: brew install tmux');
|
|
164
|
+
info(' Ubuntu: sudo apt install tmux');
|
|
165
|
+
info(' Or use PTY mode via the dashboard (no tmux required)');
|
|
308
166
|
}
|
|
309
167
|
|
|
310
168
|
main().catch((err) => {
|
|
311
|
-
// Don't fail the install if tmux installation fails
|
|
312
|
-
// User can still install tmux manually
|
|
313
169
|
warn(`Postinstall warning: ${err.message}`);
|
|
314
170
|
});
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Test Interactive Terminal Flow
|
|
4
|
+
#
|
|
5
|
+
# This script sets up a Docker environment to test the interactive terminal
|
|
6
|
+
# WITHOUT requiring GitHub OAuth.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./scripts/test-interactive-terminal.sh [command]
|
|
10
|
+
#
|
|
11
|
+
# Commands:
|
|
12
|
+
# start - Build, start, and auto-setup test user/workspace
|
|
13
|
+
# stop - Stop all containers
|
|
14
|
+
# logs - Show logs
|
|
15
|
+
# rebuild - Rebuild images with code changes
|
|
16
|
+
# clean - Stop and remove all data
|
|
17
|
+
# setup - Just run the test setup (if containers already running)
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
COMPOSE_FILE="docker-compose.dev.yml"
|
|
23
|
+
PROJECT_NAME="agent-relay-dev"
|
|
24
|
+
CLOUD_URL="http://localhost:4567"
|
|
25
|
+
|
|
26
|
+
log() {
|
|
27
|
+
echo -e "\033[1;36m[test-terminal]\033[0m $*"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
err() {
|
|
31
|
+
echo -e "\033[1;31m[test-terminal]\033[0m $*" >&2
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
success() {
|
|
35
|
+
echo -e "\033[1;32m[test-terminal]\033[0m $*"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
check_docker() {
|
|
39
|
+
if ! docker info >/dev/null 2>&1; then
|
|
40
|
+
err "Docker is not running. Please start Docker and try again."
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
wait_for_cloud() {
|
|
46
|
+
log "Waiting for cloud service..."
|
|
47
|
+
for i in {1..30}; do
|
|
48
|
+
if curl -sf "$CLOUD_URL/health" >/dev/null 2>&1; then
|
|
49
|
+
return 0
|
|
50
|
+
fi
|
|
51
|
+
sleep 2
|
|
52
|
+
done
|
|
53
|
+
return 1
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
wait_for_workspace() {
|
|
57
|
+
log "Waiting for workspace service..."
|
|
58
|
+
for i in {1..20}; do
|
|
59
|
+
if curl -sf "http://localhost:3888/health" >/dev/null 2>&1; then
|
|
60
|
+
return 0
|
|
61
|
+
fi
|
|
62
|
+
sleep 2
|
|
63
|
+
done
|
|
64
|
+
return 1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Setup test user and workspace (no OAuth needed!)
|
|
68
|
+
setup_test_environment() {
|
|
69
|
+
log "Setting up test environment (no OAuth required)..."
|
|
70
|
+
|
|
71
|
+
# Create a cookie jar for session
|
|
72
|
+
COOKIE_JAR=$(mktemp)
|
|
73
|
+
trap "rm -f $COOKIE_JAR" EXIT
|
|
74
|
+
|
|
75
|
+
# Step 1: Login as test user
|
|
76
|
+
log "Creating test user and logging in..."
|
|
77
|
+
LOGIN_RESULT=$(curl -sf -X POST "$CLOUD_URL/api/test/login-as" \
|
|
78
|
+
-H "Content-Type: application/json" \
|
|
79
|
+
-d '{"username": "terminal-tester"}' \
|
|
80
|
+
-c "$COOKIE_JAR" 2>&1) || {
|
|
81
|
+
err "Failed to login. Is the cloud service running?"
|
|
82
|
+
err "Response: $LOGIN_RESULT"
|
|
83
|
+
return 1
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
USER_ID=$(echo "$LOGIN_RESULT" | jq -r '.userId // empty')
|
|
87
|
+
if [[ -z "$USER_ID" ]]; then
|
|
88
|
+
err "Failed to get user ID from login response"
|
|
89
|
+
err "Response: $LOGIN_RESULT"
|
|
90
|
+
return 1
|
|
91
|
+
fi
|
|
92
|
+
log "Logged in as user: $USER_ID"
|
|
93
|
+
|
|
94
|
+
# Step 2: Create mock workspace pointing to the Docker workspace
|
|
95
|
+
log "Creating test workspace..."
|
|
96
|
+
WORKSPACE_RESULT=$(curl -sf -X POST "$CLOUD_URL/api/test/create-mock-workspace" \
|
|
97
|
+
-H "Content-Type: application/json" \
|
|
98
|
+
-d '{"name": "Terminal Test Workspace", "publicUrl": "http://workspace:3888"}' \
|
|
99
|
+
-b "$COOKIE_JAR" 2>&1) || {
|
|
100
|
+
err "Failed to create workspace"
|
|
101
|
+
err "Response: $WORKSPACE_RESULT"
|
|
102
|
+
return 1
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
WORKSPACE_ID=$(echo "$WORKSPACE_RESULT" | jq -r '.workspaceId // empty')
|
|
106
|
+
if [[ -z "$WORKSPACE_ID" ]]; then
|
|
107
|
+
err "Failed to get workspace ID"
|
|
108
|
+
err "Response: $WORKSPACE_RESULT"
|
|
109
|
+
return 1
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
success "Test environment ready!"
|
|
113
|
+
echo ""
|
|
114
|
+
log "=============================================="
|
|
115
|
+
log " Interactive Terminal Test Environment"
|
|
116
|
+
log "=============================================="
|
|
117
|
+
echo ""
|
|
118
|
+
log "Workspace ID: $WORKSPACE_ID"
|
|
119
|
+
echo ""
|
|
120
|
+
log "Test the interactive terminal (auto-login included):"
|
|
121
|
+
echo ""
|
|
122
|
+
echo " Claude: $CLOUD_URL/api/test/auto-login?redirect=/providers/setup/claude?workspace=$WORKSPACE_ID"
|
|
123
|
+
echo ""
|
|
124
|
+
echo " Codex: $CLOUD_URL/api/test/auto-login?redirect=/providers/setup/codex?workspace=$WORKSPACE_ID"
|
|
125
|
+
echo ""
|
|
126
|
+
log "Or access the dashboard:"
|
|
127
|
+
echo ""
|
|
128
|
+
echo " $CLOUD_URL/api/test/auto-login?redirect=/app"
|
|
129
|
+
echo ""
|
|
130
|
+
log "The terminal will show the CLI starting up."
|
|
131
|
+
log "Type directly to interact with prompts."
|
|
132
|
+
log "Auth URLs will trigger a popup modal."
|
|
133
|
+
echo ""
|
|
134
|
+
log "Commands:"
|
|
135
|
+
log " $0 logs - View service logs"
|
|
136
|
+
log " $0 rebuild - Rebuild after code changes"
|
|
137
|
+
log " $0 stop - Stop services"
|
|
138
|
+
log " $0 clean - Remove all data"
|
|
139
|
+
echo ""
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
start_services() {
|
|
143
|
+
check_docker
|
|
144
|
+
|
|
145
|
+
log "Building images with latest code..."
|
|
146
|
+
docker compose -f "$COMPOSE_FILE" build cloud workspace
|
|
147
|
+
|
|
148
|
+
log "Starting services (including workspace)..."
|
|
149
|
+
docker compose -f "$COMPOSE_FILE" --profile workspace up -d
|
|
150
|
+
|
|
151
|
+
if ! wait_for_cloud; then
|
|
152
|
+
err "Cloud service failed to start. Check logs with: $0 logs"
|
|
153
|
+
exit 1
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
if ! wait_for_workspace; then
|
|
157
|
+
err "Workspace service failed to start. Check logs with: $0 logs"
|
|
158
|
+
exit 1
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Auto-setup test environment
|
|
162
|
+
sleep 2
|
|
163
|
+
setup_test_environment
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
rebuild_services() {
|
|
167
|
+
check_docker
|
|
168
|
+
log "Rebuilding images..."
|
|
169
|
+
docker compose -f "$COMPOSE_FILE" build cloud workspace --no-cache
|
|
170
|
+
log "Restarting services..."
|
|
171
|
+
docker compose -f "$COMPOSE_FILE" --profile workspace up -d
|
|
172
|
+
|
|
173
|
+
if ! wait_for_cloud; then
|
|
174
|
+
err "Cloud service failed to start after rebuild"
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
if ! wait_for_workspace; then
|
|
179
|
+
err "Workspace service failed to start after rebuild"
|
|
180
|
+
exit 1
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
sleep 2
|
|
184
|
+
setup_test_environment
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
stop_services() {
|
|
188
|
+
check_docker
|
|
189
|
+
log "Stopping services..."
|
|
190
|
+
docker compose -f "$COMPOSE_FILE" --profile workspace down
|
|
191
|
+
log "Services stopped."
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
show_logs() {
|
|
195
|
+
check_docker
|
|
196
|
+
docker compose -f "$COMPOSE_FILE" --profile workspace logs -f
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
clean_all() {
|
|
200
|
+
check_docker
|
|
201
|
+
log "Stopping services and removing volumes..."
|
|
202
|
+
docker compose -f "$COMPOSE_FILE" --profile workspace down -v
|
|
203
|
+
log "Cleaned up."
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
# Main
|
|
207
|
+
cd "$(dirname "$0")/.."
|
|
208
|
+
|
|
209
|
+
case "${1:-start}" in
|
|
210
|
+
start)
|
|
211
|
+
start_services
|
|
212
|
+
;;
|
|
213
|
+
stop)
|
|
214
|
+
stop_services
|
|
215
|
+
;;
|
|
216
|
+
logs)
|
|
217
|
+
show_logs
|
|
218
|
+
;;
|
|
219
|
+
rebuild)
|
|
220
|
+
rebuild_services
|
|
221
|
+
;;
|
|
222
|
+
clean)
|
|
223
|
+
clean_all
|
|
224
|
+
;;
|
|
225
|
+
setup)
|
|
226
|
+
# Just run setup (containers must be running)
|
|
227
|
+
if ! curl -sf "$CLOUD_URL/health" >/dev/null 2>&1; then
|
|
228
|
+
err "Cloud service not running. Use '$0 start' first."
|
|
229
|
+
exit 1
|
|
230
|
+
fi
|
|
231
|
+
setup_test_environment
|
|
232
|
+
;;
|
|
233
|
+
help|--help|-h)
|
|
234
|
+
echo "Usage: $0 {start|stop|logs|rebuild|clean|setup|help}"
|
|
235
|
+
echo ""
|
|
236
|
+
echo "Commands:"
|
|
237
|
+
echo " start - Build, start, and auto-setup test environment"
|
|
238
|
+
echo " stop - Stop all containers"
|
|
239
|
+
echo " logs - Show service logs"
|
|
240
|
+
echo " rebuild - Rebuild images and restart"
|
|
241
|
+
echo " clean - Stop and remove all data"
|
|
242
|
+
echo " setup - Re-run test setup (if already running)"
|
|
243
|
+
;;
|
|
244
|
+
*)
|
|
245
|
+
echo "Usage: $0 {start|stop|logs|rebuild|clean|setup|help}"
|
|
246
|
+
exit 1
|
|
247
|
+
;;
|
|
248
|
+
esac
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Relay Cloud - Credential Vault
|
|
3
|
-
*
|
|
4
|
-
* Secure storage for OAuth tokens with AES-256-GCM encryption.
|
|
5
|
-
*/
|
|
6
|
-
export interface StoredCredential {
|
|
7
|
-
userId: string;
|
|
8
|
-
provider: string;
|
|
9
|
-
accessToken: string;
|
|
10
|
-
refreshToken?: string;
|
|
11
|
-
tokenExpiresAt?: Date;
|
|
12
|
-
scopes?: string[];
|
|
13
|
-
providerAccountId?: string;
|
|
14
|
-
providerAccountEmail?: string;
|
|
15
|
-
}
|
|
16
|
-
export interface DecryptedCredential {
|
|
17
|
-
accessToken: string;
|
|
18
|
-
refreshToken?: string;
|
|
19
|
-
tokenExpiresAt?: Date;
|
|
20
|
-
scopes?: string[];
|
|
21
|
-
providerAccountId?: string;
|
|
22
|
-
providerAccountEmail?: string;
|
|
23
|
-
}
|
|
24
|
-
export declare class CredentialVault {
|
|
25
|
-
private masterKey;
|
|
26
|
-
constructor();
|
|
27
|
-
/**
|
|
28
|
-
* Encrypt a string value
|
|
29
|
-
*/
|
|
30
|
-
private encrypt;
|
|
31
|
-
/**
|
|
32
|
-
* Decrypt a string value
|
|
33
|
-
*/
|
|
34
|
-
private decrypt;
|
|
35
|
-
/**
|
|
36
|
-
* Store encrypted credential
|
|
37
|
-
*/
|
|
38
|
-
storeCredential(credential: StoredCredential): Promise<void>;
|
|
39
|
-
/**
|
|
40
|
-
* Retrieve and decrypt credential
|
|
41
|
-
*/
|
|
42
|
-
getCredential(userId: string, provider: string): Promise<DecryptedCredential | null>;
|
|
43
|
-
/**
|
|
44
|
-
* Get all credentials for a user (decrypted)
|
|
45
|
-
*/
|
|
46
|
-
getUserCredentials(userId: string): Promise<Map<string, DecryptedCredential>>;
|
|
47
|
-
/**
|
|
48
|
-
* Update tokens (e.g., after refresh)
|
|
49
|
-
*/
|
|
50
|
-
updateTokens(userId: string, provider: string, accessToken: string, refreshToken?: string, expiresAt?: Date): Promise<void>;
|
|
51
|
-
/**
|
|
52
|
-
* Delete credential
|
|
53
|
-
*/
|
|
54
|
-
deleteCredential(userId: string, provider: string): Promise<void>;
|
|
55
|
-
/**
|
|
56
|
-
* Check if credential needs refresh (within 5 minutes of expiry)
|
|
57
|
-
*/
|
|
58
|
-
needsRefresh(userId: string, provider: string): Promise<boolean>;
|
|
59
|
-
/**
|
|
60
|
-
* Refresh OAuth token for a provider
|
|
61
|
-
*/
|
|
62
|
-
refreshToken(userId: string, provider: string): Promise<boolean>;
|
|
63
|
-
}
|
|
64
|
-
export declare function getVault(): CredentialVault;
|
|
65
|
-
export declare const vault: {
|
|
66
|
-
readonly instance: CredentialVault;
|
|
67
|
-
storeCredential: (cred: StoredCredential) => Promise<void>;
|
|
68
|
-
getCredential: (userId: string, provider: string) => Promise<DecryptedCredential | null>;
|
|
69
|
-
getUserCredentials: (userId: string) => Promise<Map<string, DecryptedCredential>>;
|
|
70
|
-
updateTokens: (userId: string, provider: string, accessToken: string, refreshToken?: string, expiresAt?: Date) => Promise<void>;
|
|
71
|
-
deleteCredential: (userId: string, provider: string) => Promise<void>;
|
|
72
|
-
needsRefresh: (userId: string, provider: string) => Promise<boolean>;
|
|
73
|
-
refreshToken: (userId: string, provider: string) => Promise<boolean>;
|
|
74
|
-
};
|
|
75
|
-
export declare function generateMasterKey(): string;
|
|
76
|
-
//# sourceMappingURL=index.d.ts.map
|