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.
Files changed (189) hide show
  1. package/.trajectories/agent-relay-322-324.md +17 -0
  2. package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.json +49 -0
  3. package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.md +31 -0
  4. package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.json +125 -0
  5. package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.md +62 -0
  6. package/.trajectories/completed/2026-01/traj_33iuy72sezbk.json +49 -0
  7. package/.trajectories/completed/2026-01/traj_33iuy72sezbk.md +31 -0
  8. package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.json +77 -0
  9. package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.md +42 -0
  10. package/.trajectories/completed/2026-01/traj_6mieijqyvaag.json +77 -0
  11. package/.trajectories/completed/2026-01/traj_6mieijqyvaag.md +42 -0
  12. package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.json +77 -0
  13. package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.md +42 -0
  14. package/.trajectories/completed/2026-01/traj_94gnp3k30goq.json +66 -0
  15. package/.trajectories/completed/2026-01/traj_94gnp3k30goq.md +36 -0
  16. package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.json +40 -0
  17. package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.md +22 -0
  18. package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.json +121 -0
  19. package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.md +29 -0
  20. package/.trajectories/completed/2026-01/traj_fhx9irlckht6.json +53 -0
  21. package/.trajectories/completed/2026-01/traj_fhx9irlckht6.md +32 -0
  22. package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.json +101 -0
  23. package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.md +52 -0
  24. package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.json +49 -0
  25. package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.md +31 -0
  26. package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.json +65 -0
  27. package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.md +37 -0
  28. package/.trajectories/completed/2026-01/traj_lq450ly148uw.json +49 -0
  29. package/.trajectories/completed/2026-01/traj_lq450ly148uw.md +31 -0
  30. package/.trajectories/completed/2026-01/traj_multi_server_arch.md +101 -0
  31. package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.json +27 -0
  32. package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.md +14 -0
  33. package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.json +53 -0
  34. package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.md +32 -0
  35. package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.json +186 -0
  36. package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.md +86 -0
  37. package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.json +77 -0
  38. package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.md +42 -0
  39. package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.json +89 -0
  40. package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.md +47 -0
  41. package/.trajectories/completed/2026-01/traj_xy9vifpqet80.json +65 -0
  42. package/.trajectories/completed/2026-01/traj_xy9vifpqet80.md +37 -0
  43. package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.json +49 -0
  44. package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.md +31 -0
  45. package/.trajectories/consolidate-settings-panel.md +24 -0
  46. package/.trajectories/gh-cli-user-token.md +26 -0
  47. package/.trajectories/index.json +155 -1
  48. package/deploy/workspace/codex.config.toml +15 -0
  49. package/deploy/workspace/entrypoint.sh +167 -7
  50. package/deploy/workspace/git-credential-relay +17 -2
  51. package/dist/bridge/spawner.d.ts +7 -0
  52. package/dist/bridge/spawner.js +40 -9
  53. package/dist/bridge/types.d.ts +2 -0
  54. package/dist/cli/index.js +210 -168
  55. package/dist/cloud/api/admin.d.ts +8 -0
  56. package/dist/cloud/api/admin.js +212 -0
  57. package/dist/cloud/api/auth.js +8 -0
  58. package/dist/cloud/api/billing.d.ts +0 -10
  59. package/dist/cloud/api/billing.js +248 -58
  60. package/dist/cloud/api/codex-auth-helper.d.ts +10 -4
  61. package/dist/cloud/api/codex-auth-helper.js +215 -8
  62. package/dist/cloud/api/coordinators.js +402 -0
  63. package/dist/cloud/api/daemons.js +15 -11
  64. package/dist/cloud/api/git.js +104 -17
  65. package/dist/cloud/api/github-app.js +42 -8
  66. package/dist/cloud/api/nango-auth.js +297 -16
  67. package/dist/cloud/api/onboarding.js +97 -33
  68. package/dist/cloud/api/providers.js +12 -16
  69. package/dist/cloud/api/repos.js +200 -124
  70. package/dist/cloud/api/test-helpers.js +40 -0
  71. package/dist/cloud/api/usage.js +13 -0
  72. package/dist/cloud/api/webhooks.js +1 -1
  73. package/dist/cloud/api/workspaces.d.ts +18 -0
  74. package/dist/cloud/api/workspaces.js +945 -15
  75. package/dist/cloud/config.d.ts +8 -0
  76. package/dist/cloud/config.js +15 -0
  77. package/dist/cloud/db/drizzle.d.ts +5 -2
  78. package/dist/cloud/db/drizzle.js +27 -20
  79. package/dist/cloud/db/schema.d.ts +19 -51
  80. package/dist/cloud/db/schema.js +5 -4
  81. package/dist/cloud/index.d.ts +0 -1
  82. package/dist/cloud/index.js +0 -1
  83. package/dist/cloud/provisioner/index.d.ts +93 -1
  84. package/dist/cloud/provisioner/index.js +608 -63
  85. package/dist/cloud/server.js +156 -16
  86. package/dist/cloud/services/compute-enforcement.d.ts +57 -0
  87. package/dist/cloud/services/compute-enforcement.js +175 -0
  88. package/dist/cloud/services/index.d.ts +2 -0
  89. package/dist/cloud/services/index.js +4 -0
  90. package/dist/cloud/services/intro-expiration.d.ts +55 -0
  91. package/dist/cloud/services/intro-expiration.js +211 -0
  92. package/dist/cloud/services/nango.d.ts +14 -0
  93. package/dist/cloud/services/nango.js +74 -14
  94. package/dist/cloud/services/ssh-security.d.ts +31 -0
  95. package/dist/cloud/services/ssh-security.js +63 -0
  96. package/dist/continuity/manager.d.ts +5 -0
  97. package/dist/continuity/manager.js +56 -2
  98. package/dist/daemon/api.d.ts +2 -0
  99. package/dist/daemon/api.js +214 -5
  100. package/dist/daemon/cli-auth.d.ts +13 -1
  101. package/dist/daemon/cli-auth.js +166 -47
  102. package/dist/daemon/connection.d.ts +7 -1
  103. package/dist/daemon/connection.js +15 -0
  104. package/dist/daemon/orchestrator.d.ts +2 -0
  105. package/dist/daemon/orchestrator.js +26 -0
  106. package/dist/daemon/repo-manager.d.ts +116 -0
  107. package/dist/daemon/repo-manager.js +384 -0
  108. package/dist/daemon/router.d.ts +60 -1
  109. package/dist/daemon/router.js +281 -20
  110. package/dist/daemon/user-directory.d.ts +111 -0
  111. package/dist/daemon/user-directory.js +233 -0
  112. package/dist/dashboard/out/404.html +1 -1
  113. package/dist/dashboard/out/_next/static/chunks/532-bace199897eeab37.js +9 -0
  114. package/dist/dashboard/out/_next/static/chunks/766-b54f0853794b78c3.js +1 -0
  115. package/dist/dashboard/out/_next/static/chunks/83-b51836037078006c.js +1 -0
  116. package/dist/dashboard/out/_next/static/chunks/891-6cd50de1224f70bb.js +1 -0
  117. package/dist/dashboard/out/_next/static/chunks/899-fc02ed79e3de4302.js +1 -0
  118. package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/{page-3fdfa60e53f2810d.js → page-8553743baca53a00.js} +1 -1
  119. package/dist/dashboard/out/_next/static/chunks/app/app/page-c617745b81344f4f.js +1 -0
  120. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-f829604fb75a831a.js +1 -0
  121. package/dist/dashboard/out/_next/static/chunks/app/{page-77e9c65420a06cfb.js → page-dc786c183425c2ac.js} +1 -1
  122. package/dist/dashboard/out/_next/static/chunks/app/providers/page-84322991d7244499.js +1 -0
  123. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-05606941a8e2be83.js +1 -0
  124. package/dist/dashboard/out/_next/static/chunks/{main-ed4e1fb6f29c34cf.js → main-2ee6beb2ae96d210.js} +1 -1
  125. package/dist/dashboard/out/_next/static/css/48a8fbe3e659080e.css +1 -0
  126. package/dist/dashboard/out/_next/static/css/fe4b28883eeff359.css +1 -0
  127. package/dist/dashboard/out/_next/static/sDcbGRTYLcpPvyTs_rsNb/_ssgManifest.js +1 -0
  128. package/dist/dashboard/out/app/onboarding.html +1 -1
  129. package/dist/dashboard/out/app/onboarding.txt +3 -3
  130. package/dist/dashboard/out/app.html +1 -1
  131. package/dist/dashboard/out/app.txt +3 -3
  132. package/dist/dashboard/out/apple-icon.png +0 -0
  133. package/dist/dashboard/out/connect-repos.html +1 -1
  134. package/dist/dashboard/out/connect-repos.txt +2 -2
  135. package/dist/dashboard/out/history.html +1 -1
  136. package/dist/dashboard/out/history.txt +2 -2
  137. package/dist/dashboard/out/index.html +1 -1
  138. package/dist/dashboard/out/index.txt +3 -3
  139. package/dist/dashboard/out/login.html +2 -2
  140. package/dist/dashboard/out/login.txt +2 -2
  141. package/dist/dashboard/out/metrics.html +1 -1
  142. package/dist/dashboard/out/metrics.txt +3 -3
  143. package/dist/dashboard/out/pricing.html +2 -2
  144. package/dist/dashboard/out/pricing.txt +3 -3
  145. package/dist/dashboard/out/providers/setup/claude.html +1 -0
  146. package/dist/dashboard/out/providers/setup/claude.txt +8 -0
  147. package/dist/dashboard/out/providers/setup/codex.html +1 -0
  148. package/dist/dashboard/out/providers/setup/codex.txt +8 -0
  149. package/dist/dashboard/out/providers.html +1 -1
  150. package/dist/dashboard/out/providers.txt +3 -3
  151. package/dist/dashboard/out/signup.html +2 -2
  152. package/dist/dashboard/out/signup.txt +2 -2
  153. package/dist/dashboard-server/server.js +316 -12
  154. package/dist/dashboard-server/user-bridge.d.ts +103 -0
  155. package/dist/dashboard-server/user-bridge.js +189 -0
  156. package/dist/protocol/channels.d.ts +205 -0
  157. package/dist/protocol/channels.js +154 -0
  158. package/dist/protocol/types.d.ts +13 -1
  159. package/dist/resiliency/provider-context.js +2 -0
  160. package/dist/shared/cli-auth-config.d.ts +19 -0
  161. package/dist/shared/cli-auth-config.js +58 -2
  162. package/dist/utils/agent-config.js +1 -1
  163. package/dist/wrapper/auth-detection.d.ts +49 -0
  164. package/dist/wrapper/auth-detection.js +192 -0
  165. package/dist/wrapper/base-wrapper.d.ts +153 -0
  166. package/dist/wrapper/base-wrapper.js +393 -0
  167. package/dist/wrapper/client.d.ts +7 -1
  168. package/dist/wrapper/client.js +3 -0
  169. package/dist/wrapper/index.d.ts +1 -0
  170. package/dist/wrapper/index.js +4 -3
  171. package/dist/wrapper/pty-wrapper.d.ts +62 -84
  172. package/dist/wrapper/pty-wrapper.js +154 -180
  173. package/dist/wrapper/tmux-wrapper.d.ts +41 -66
  174. package/dist/wrapper/tmux-wrapper.js +90 -134
  175. package/package.json +4 -2
  176. package/scripts/postinstall.js +11 -155
  177. package/scripts/test-interactive-terminal.sh +248 -0
  178. package/dist/cloud/vault/index.d.ts +0 -76
  179. package/dist/cloud/vault/index.js +0 -219
  180. package/dist/dashboard/out/_next/static/chunks/699-3b1cd6618a45d259.js +0 -1
  181. package/dist/dashboard/out/_next/static/chunks/724-2dae7627550ab88f.js +0 -9
  182. package/dist/dashboard/out/_next/static/chunks/766-1f2dd8cb7f766b0b.js +0 -1
  183. package/dist/dashboard/out/_next/static/chunks/app/app/page-e6381e5a6e1fbcfd.js +0 -1
  184. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-67a3e98d9a43a6ed.js +0 -1
  185. package/dist/dashboard/out/_next/static/chunks/app/providers/page-e88bc117ef7671c3.js +0 -1
  186. package/dist/dashboard/out/_next/static/css/29852f26181969a0.css +0 -1
  187. package/dist/dashboard/out/_next/static/css/7c3ae9e8617d42a5.css +0 -1
  188. package/dist/dashboard/out/_next/static/wPgKJtcOmTFLpUncDg16A/_ssgManifest.js +0 -1
  189. /package/dist/dashboard/out/_next/static/{wPgKJtcOmTFLpUncDg16A → sDcbGRTYLcpPvyTs_rsNb}/_buildManifest.js +0 -0
@@ -0,0 +1,233 @@
1
+ /**
2
+ * User Directory Service
3
+ *
4
+ * Manages per-user directories on workspace volumes for CLI credential storage.
5
+ * Each user gets their own home directory at /data/users/{userId}/ with
6
+ * provider-specific subdirectories for credentials.
7
+ *
8
+ * Structure:
9
+ * /data/
10
+ * └── users/
11
+ * ├── {userId1}/
12
+ * │ ├── .claude/
13
+ * │ │ └── .credentials.json
14
+ * │ ├── .codex/
15
+ * │ │ └── credentials.json
16
+ * │ └── .config/
17
+ * │ └── gcloud/
18
+ * │ └── application_default_credentials.json
19
+ * └── {userId2}/
20
+ * └── ...
21
+ */
22
+ import * as fs from 'fs';
23
+ import * as path from 'path';
24
+ import { createLogger } from '../resiliency/logger.js';
25
+ const logger = createLogger('user-directory');
26
+ const PROVIDER_CONFIGS = {
27
+ claude: {
28
+ dir: '.claude',
29
+ credentialsFile: '.credentials.json',
30
+ },
31
+ codex: {
32
+ dir: '.codex',
33
+ credentialsFile: 'credentials.json',
34
+ },
35
+ gemini: {
36
+ dir: '.config/gcloud',
37
+ credentialsFile: 'application_default_credentials.json',
38
+ },
39
+ opencode: {
40
+ dir: '.opencode',
41
+ credentialsFile: 'credentials.json',
42
+ },
43
+ droid: {
44
+ dir: '.factory',
45
+ credentialsFile: 'credentials.json',
46
+ },
47
+ };
48
+ /**
49
+ * All supported providers for initialization
50
+ */
51
+ const ALL_PROVIDERS = Object.keys(PROVIDER_CONFIGS);
52
+ /**
53
+ * Service for managing per-user directories on workspace volumes.
54
+ * Enables multi-user credential storage without conflicts.
55
+ */
56
+ export class UserDirectoryService {
57
+ baseDir;
58
+ usersDir;
59
+ /**
60
+ * Create a new UserDirectoryService.
61
+ * @param baseDir - Base data directory (e.g., /data)
62
+ */
63
+ constructor(baseDir) {
64
+ this.baseDir = baseDir;
65
+ this.usersDir = path.join(baseDir, 'users');
66
+ // Ensure users directory exists
67
+ this.ensureDirectory(this.usersDir);
68
+ logger.info(`UserDirectoryService initialized at ${this.usersDir}`);
69
+ }
70
+ /**
71
+ * Get the home directory path for a user.
72
+ * Creates the directory if it doesn't exist.
73
+ *
74
+ * @param userId - User ID (UUID or similar)
75
+ * @returns Absolute path to user's home directory
76
+ * @throws Error if userId is invalid
77
+ */
78
+ getUserHome(userId) {
79
+ this.validateUserId(userId);
80
+ const userHome = path.join(this.usersDir, userId);
81
+ this.ensureDirectory(userHome);
82
+ return userHome;
83
+ }
84
+ /**
85
+ * Ensure a provider's credential directory exists for a user.
86
+ *
87
+ * @param userId - User ID
88
+ * @param provider - Provider name (claude, codex, gemini, etc.)
89
+ * @returns Absolute path to provider directory
90
+ */
91
+ ensureProviderDir(userId, provider) {
92
+ this.validateUserId(userId);
93
+ const config = PROVIDER_CONFIGS[provider];
94
+ if (!config) {
95
+ // For unknown providers, use .{provider} directory
96
+ const userHome = this.getUserHome(userId);
97
+ const providerDir = path.join(userHome, `.${provider}`);
98
+ this.ensureDirectory(providerDir);
99
+ return providerDir;
100
+ }
101
+ const userHome = this.getUserHome(userId);
102
+ const providerDir = path.join(userHome, config.dir);
103
+ this.ensureDirectory(providerDir);
104
+ return providerDir;
105
+ }
106
+ /**
107
+ * Initialize a complete user environment with all provider directories.
108
+ *
109
+ * @param userId - User ID
110
+ * @returns User's home directory path
111
+ */
112
+ initializeUserEnvironment(userId) {
113
+ this.validateUserId(userId);
114
+ const userHome = this.getUserHome(userId);
115
+ // Create all provider directories
116
+ for (const provider of ALL_PROVIDERS) {
117
+ this.ensureProviderDir(userId, provider);
118
+ }
119
+ logger.info(`Initialized user environment for ${userId} at ${userHome}`);
120
+ return userHome;
121
+ }
122
+ /**
123
+ * Get environment variables for spawning an agent with user-specific HOME.
124
+ *
125
+ * @param userId - User ID
126
+ * @returns Environment variables to merge with process.env
127
+ */
128
+ getUserEnvironment(userId) {
129
+ const userHome = this.getUserHome(userId);
130
+ return {
131
+ HOME: userHome,
132
+ XDG_CONFIG_HOME: path.join(userHome, '.config'),
133
+ AGENT_RELAY_USER_ID: userId,
134
+ };
135
+ }
136
+ /**
137
+ * List all user IDs that have directories.
138
+ *
139
+ * @returns Array of user IDs
140
+ */
141
+ listUsers() {
142
+ try {
143
+ const entries = fs.readdirSync(this.usersDir, { withFileTypes: true });
144
+ return entries
145
+ .filter((entry) => entry.isDirectory())
146
+ .map((entry) => entry.name);
147
+ }
148
+ catch {
149
+ return [];
150
+ }
151
+ }
152
+ /**
153
+ * Check if a user has an existing directory.
154
+ *
155
+ * @param userId - User ID
156
+ * @returns True if directory exists
157
+ */
158
+ hasUserDirectory(userId) {
159
+ const userHome = path.join(this.usersDir, userId);
160
+ return fs.existsSync(userHome);
161
+ }
162
+ /**
163
+ * Get the path to a provider's credentials file for a user.
164
+ *
165
+ * @param userId - User ID
166
+ * @param provider - Provider name
167
+ * @returns Absolute path to credentials file
168
+ */
169
+ getProviderCredentialPath(userId, provider) {
170
+ const config = PROVIDER_CONFIGS[provider];
171
+ if (!config) {
172
+ const userHome = this.getUserHome(userId);
173
+ return path.join(userHome, `.${provider}`, 'credentials.json');
174
+ }
175
+ const providerDir = this.ensureProviderDir(userId, provider);
176
+ return path.join(providerDir, config.credentialsFile);
177
+ }
178
+ /**
179
+ * Validate a user ID to prevent path traversal and other issues.
180
+ *
181
+ * @param userId - User ID to validate
182
+ * @throws Error if userId is invalid
183
+ */
184
+ validateUserId(userId) {
185
+ if (!userId || userId.trim() === '') {
186
+ throw new Error('User ID cannot be empty');
187
+ }
188
+ // Prevent path traversal
189
+ if (userId.includes('..') || userId.includes('/') || userId.includes('\\')) {
190
+ throw new Error('User ID contains invalid characters');
191
+ }
192
+ // Ensure resolved path is within users directory
193
+ const resolved = path.resolve(this.usersDir, userId);
194
+ if (!resolved.startsWith(this.usersDir)) {
195
+ throw new Error('User ID would escape users directory');
196
+ }
197
+ }
198
+ /**
199
+ * Ensure a directory exists, creating it recursively if needed.
200
+ */
201
+ ensureDirectory(dirPath) {
202
+ if (!fs.existsSync(dirPath)) {
203
+ fs.mkdirSync(dirPath, { recursive: true });
204
+ }
205
+ }
206
+ }
207
+ /**
208
+ * Get the default data directory for user directories.
209
+ * Uses AGENT_RELAY_DATA_DIR if set, otherwise /data (for Fly.io volumes).
210
+ */
211
+ export function getDefaultDataDir() {
212
+ return process.env.AGENT_RELAY_DATA_DIR || '/data';
213
+ }
214
+ /**
215
+ * Singleton instance for the workspace.
216
+ */
217
+ let _instance = null;
218
+ /**
219
+ * Get the singleton UserDirectoryService instance.
220
+ */
221
+ export function getUserDirectoryService() {
222
+ if (!_instance) {
223
+ _instance = new UserDirectoryService(getDefaultDataDir());
224
+ }
225
+ return _instance;
226
+ }
227
+ /**
228
+ * Create a new UserDirectoryService for testing or custom paths.
229
+ */
230
+ export function createUserDirectoryService(baseDir) {
231
+ return new UserDirectoryService(baseDir);
232
+ }
233
+ //# sourceMappingURL=user-directory.js.map
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/7c3ae9e8617d42a5.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js"/><script src="/_next/static/chunks/fd9d1056-609918ca7b6280bb.js" async=""></script><script src="/_next/static/chunks/117-f7b8ab0809342e77.js" async=""></script><script src="/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Agent Relay Dashboard</title><meta name="description" content="Fleet control dashboard for Agent Relay"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/css/7c3ae9e8617d42a5.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"2:I[2846,[],\"\"]\n4:I[4707,[],\"\"]\n5:I[6423,[],\"\"]\nb:I[1060,[],\"\"]\n6:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n7:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n8:{\"display\":\"inline-block\"}\n9:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nc:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L2\",null,{\"buildId\":\"wPgKJtcOmTFLpUncDg16A\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L3\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/7c3ae9e8617d42a5.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$6\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$7\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$8\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$9\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Agent Relay Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Fleet control dashboard for Agent Relay\"}]]\n3:null\n"])</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/48a8fbe3e659080e.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js"/><script src="/_next/static/chunks/fd9d1056-609918ca7b6280bb.js" async=""></script><script src="/_next/static/chunks/117-f7b8ab0809342e77.js" async=""></script><script src="/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Agent Relay Dashboard</title><meta name="description" content="Fleet control dashboard for Agent Relay"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/css/48a8fbe3e659080e.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"2:I[2846,[],\"\"]\n4:I[4707,[],\"\"]\n5:I[6423,[],\"\"]\nb:I[1060,[],\"\"]\n6:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n7:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n8:{\"display\":\"inline-block\"}\n9:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nc:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L2\",null,{\"buildId\":\"sDcbGRTYLcpPvyTs_rsNb\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L3\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/48a8fbe3e659080e.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$6\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$7\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$8\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$9\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Agent Relay Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Fleet control dashboard for Agent Relay\"}]]\n3:null\n"])</script></body></html>