agent-relay 2.0.10 → 2.0.12

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 (115) hide show
  1. package/bin/relay-pty-darwin-arm64 +0 -0
  2. package/bin/relay-pty-darwin-x64 +0 -0
  3. package/bin/relay-pty-linux-x64 +0 -0
  4. package/dist/dashboard/out/404.html +1 -1
  5. package/dist/dashboard/out/_next/static/chunks/320-23e5ffe6aa7eb934.js +1 -0
  6. package/{packages/dashboard/ui-dist/_next/static/css/99c2552394077586.css → dist/dashboard/out/_next/static/css/605dd4e30c91986f.css} +1 -1
  7. package/dist/dashboard/out/app/onboarding.html +1 -1
  8. package/dist/dashboard/out/app/onboarding.txt +1 -1
  9. package/dist/dashboard/out/app.html +1 -1
  10. package/dist/dashboard/out/app.txt +2 -2
  11. package/dist/dashboard/out/cloud/link.html +1 -1
  12. package/dist/dashboard/out/cloud/link.txt +1 -1
  13. package/dist/dashboard/out/connect-repos.html +1 -1
  14. package/dist/dashboard/out/connect-repos.txt +1 -1
  15. package/dist/dashboard/out/history.html +1 -1
  16. package/dist/dashboard/out/history.txt +1 -1
  17. package/dist/dashboard/out/index.html +1 -1
  18. package/dist/dashboard/out/index.txt +2 -2
  19. package/dist/dashboard/out/login.html +2 -2
  20. package/dist/dashboard/out/login.txt +1 -1
  21. package/dist/dashboard/out/metrics.html +1 -1
  22. package/dist/dashboard/out/metrics.txt +1 -1
  23. package/dist/dashboard/out/pricing.html +2 -2
  24. package/dist/dashboard/out/pricing.txt +1 -1
  25. package/dist/dashboard/out/providers/setup/claude.html +1 -1
  26. package/dist/dashboard/out/providers/setup/claude.txt +1 -1
  27. package/dist/dashboard/out/providers/setup/codex.html +1 -1
  28. package/dist/dashboard/out/providers/setup/codex.txt +1 -1
  29. package/dist/dashboard/out/providers/setup/cursor.html +1 -1
  30. package/dist/dashboard/out/providers/setup/cursor.txt +1 -1
  31. package/dist/dashboard/out/providers.html +1 -1
  32. package/dist/dashboard/out/providers.txt +1 -1
  33. package/dist/dashboard/out/signup.html +2 -2
  34. package/dist/dashboard/out/signup.txt +1 -1
  35. package/package.json +15 -15
  36. package/packages/api-types/package.json +1 -1
  37. package/packages/bridge/dist/spawner.js +3 -49
  38. package/packages/bridge/package.json +7 -7
  39. package/packages/cloud/dist/api/cli-pty-runner.js +4 -25
  40. package/packages/cloud/dist/api/provider-env.d.ts +12 -0
  41. package/packages/cloud/dist/api/provider-env.js +66 -0
  42. package/packages/cloud/dist/api/providers.js +12 -2
  43. package/packages/cloud/package.json +6 -6
  44. package/packages/config/package.json +2 -2
  45. package/packages/continuity/package.json +1 -1
  46. package/packages/daemon/dist/cli-auth.js +4 -25
  47. package/packages/daemon/package.json +12 -12
  48. package/packages/dashboard/dist/server.js +32 -0
  49. package/packages/dashboard/package.json +12 -12
  50. package/packages/dashboard/ui/react-components/settings/WorkspaceSettingsPanel.tsx +44 -3
  51. package/packages/dashboard/ui-dist/404.html +1 -1
  52. package/packages/dashboard/ui-dist/_next/static/chunks/320-23e5ffe6aa7eb934.js +1 -0
  53. package/{dist/dashboard/out/_next/static/css/99c2552394077586.css → packages/dashboard/ui-dist/_next/static/css/605dd4e30c91986f.css} +1 -1
  54. package/packages/dashboard/ui-dist/app/onboarding.html +1 -1
  55. package/packages/dashboard/ui-dist/app/onboarding.txt +1 -1
  56. package/packages/dashboard/ui-dist/app.html +1 -1
  57. package/packages/dashboard/ui-dist/app.txt +2 -2
  58. package/packages/dashboard/ui-dist/cloud/link.html +1 -1
  59. package/packages/dashboard/ui-dist/cloud/link.txt +1 -1
  60. package/packages/dashboard/ui-dist/connect-repos.html +1 -1
  61. package/packages/dashboard/ui-dist/connect-repos.txt +1 -1
  62. package/packages/dashboard/ui-dist/history.html +1 -1
  63. package/packages/dashboard/ui-dist/history.txt +1 -1
  64. package/packages/dashboard/ui-dist/index.html +1 -1
  65. package/packages/dashboard/ui-dist/index.txt +2 -2
  66. package/packages/dashboard/ui-dist/login.html +2 -2
  67. package/packages/dashboard/ui-dist/login.txt +1 -1
  68. package/packages/dashboard/ui-dist/metrics.html +1 -1
  69. package/packages/dashboard/ui-dist/metrics.txt +1 -1
  70. package/packages/dashboard/ui-dist/pricing.html +2 -2
  71. package/packages/dashboard/ui-dist/pricing.txt +1 -1
  72. package/packages/dashboard/ui-dist/providers/setup/claude.html +1 -1
  73. package/packages/dashboard/ui-dist/providers/setup/claude.txt +1 -1
  74. package/packages/dashboard/ui-dist/providers/setup/codex.html +1 -1
  75. package/packages/dashboard/ui-dist/providers/setup/codex.txt +1 -1
  76. package/packages/dashboard/ui-dist/providers/setup/cursor.html +1 -1
  77. package/packages/dashboard/ui-dist/providers/setup/cursor.txt +1 -1
  78. package/packages/dashboard/ui-dist/providers.html +1 -1
  79. package/packages/dashboard/ui-dist/providers.txt +1 -1
  80. package/packages/dashboard/ui-dist/signup.html +2 -2
  81. package/packages/dashboard/ui-dist/signup.txt +1 -1
  82. package/packages/dashboard-server/package.json +12 -12
  83. package/packages/hooks/package.json +4 -4
  84. package/packages/mcp/package.json +2 -2
  85. package/packages/memory/package.json +2 -2
  86. package/packages/policy/package.json +2 -2
  87. package/packages/protocol/package.json +1 -1
  88. package/packages/resiliency/package.json +1 -1
  89. package/packages/sdk/package.json +2 -2
  90. package/packages/spawner/package.json +1 -1
  91. package/packages/state/package.json +1 -1
  92. package/packages/storage/package.json +2 -2
  93. package/packages/telemetry/package.json +1 -1
  94. package/packages/trajectory/package.json +2 -2
  95. package/packages/user-directory/dist/user-directory.d.ts +17 -0
  96. package/packages/user-directory/dist/user-directory.js +73 -0
  97. package/packages/user-directory/package.json +2 -2
  98. package/packages/utils/dist/index.d.ts +1 -0
  99. package/packages/utils/dist/index.js +1 -0
  100. package/packages/utils/dist/relay-pty-path.d.ts +44 -0
  101. package/packages/utils/dist/relay-pty-path.js +127 -0
  102. package/packages/utils/package.json +6 -1
  103. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +1 -0
  104. package/packages/wrapper/dist/relay-pty-orchestrator.js +4 -25
  105. package/packages/wrapper/package.json +6 -6
  106. package/dist/dashboard/out/_next/static/chunks/320-22ebe7be58cf982a.js +0 -1
  107. package/packages/dashboard/ui-dist/_next/static/chunks/320-22ebe7be58cf982a.js +0 -1
  108. /package/dist/dashboard/out/_next/static/{JAvj75YIj64v2DvtpY-Up → h1U3qU5XIfQSy46M_SDsz}/_buildManifest.js +0 -0
  109. /package/dist/dashboard/out/_next/static/{JAvj75YIj64v2DvtpY-Up → h1U3qU5XIfQSy46M_SDsz}/_ssgManifest.js +0 -0
  110. /package/packages/dashboard/ui-dist/_next/static/{CGov7E2X8pfRUBsEI0LwF → 4WryIM4xHT22BbJ46YITr}/_buildManifest.js +0 -0
  111. /package/packages/dashboard/ui-dist/_next/static/{CGov7E2X8pfRUBsEI0LwF → 4WryIM4xHT22BbJ46YITr}/_ssgManifest.js +0 -0
  112. /package/packages/dashboard/ui-dist/_next/static/{JAvj75YIj64v2DvtpY-Up → dS0EgrS-iG-_pkUVhBypz}/_buildManifest.js +0 -0
  113. /package/packages/dashboard/ui-dist/_next/static/{JAvj75YIj64v2DvtpY-Up → dS0EgrS-iG-_pkUVhBypz}/_ssgManifest.js +0 -0
  114. /package/packages/dashboard/ui-dist/_next/static/{yYbcf-78mQC52r1JUhVRp → h1U3qU5XIfQSy46M_SDsz}/_buildManifest.js +0 -0
  115. /package/packages/dashboard/ui-dist/_next/static/{yYbcf-78mQC52r1JUhVRp → h1U3qU5XIfQSy46M_SDsz}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/dashboard-server",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Relay dashboard server - HTTP/WebSocket server for agent coordination",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,17 +22,17 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/protocol": "2.0.10",
26
- "@agent-relay/config": "2.0.10",
27
- "@agent-relay/storage": "2.0.10",
28
- "@agent-relay/bridge": "2.0.10",
29
- "@agent-relay/utils": "2.0.10",
30
- "@agent-relay/resiliency": "2.0.10",
31
- "@agent-relay/trajectory": "2.0.10",
32
- "@agent-relay/cloud": "2.0.10",
33
- "@agent-relay/daemon": "2.0.10",
34
- "@agent-relay/user-directory": "2.0.10",
35
- "@agent-relay/sdk": "2.0.10",
25
+ "@agent-relay/protocol": "2.0.12",
26
+ "@agent-relay/config": "2.0.12",
27
+ "@agent-relay/storage": "2.0.12",
28
+ "@agent-relay/bridge": "2.0.12",
29
+ "@agent-relay/utils": "2.0.12",
30
+ "@agent-relay/resiliency": "2.0.12",
31
+ "@agent-relay/trajectory": "2.0.12",
32
+ "@agent-relay/cloud": "2.0.12",
33
+ "@agent-relay/daemon": "2.0.12",
34
+ "@agent-relay/user-directory": "2.0.12",
35
+ "@agent-relay/sdk": "2.0.12",
36
36
  "array-flatten": "^1.1.1",
37
37
  "express": "^4.21.2",
38
38
  "ws": "^8.18.3"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/hooks",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Hook emitter, registry, and trajectory hooks for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,9 +37,9 @@
37
37
  "test:watch": "vitest"
38
38
  },
39
39
  "dependencies": {
40
- "@agent-relay/protocol": "2.0.10",
41
- "@agent-relay/config": "2.0.10",
42
- "@agent-relay/trajectory": "2.0.10"
40
+ "@agent-relay/protocol": "2.0.12",
41
+ "@agent-relay/config": "2.0.12",
42
+ "@agent-relay/trajectory": "2.0.12"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/mcp",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "MCP server for Agent Relay - native messaging tools for AI agents in Claude, Cursor, and VS Code",
5
5
  "author": "Agent Workforce Inc.",
6
6
  "license": "Apache-2.0",
@@ -47,7 +47,7 @@
47
47
  "prepublishOnly": "npm run clean && npm run build && npm test"
48
48
  },
49
49
  "dependencies": {
50
- "@agent-relay/config": "2.0.10",
50
+ "@agent-relay/config": "2.0.12",
51
51
  "@modelcontextprotocol/sdk": "^1.0.0",
52
52
  "zod": "^3.23.8"
53
53
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/memory",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Semantic memory storage and retrieval system for agent-relay with multiple backend support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/hooks": "2.0.10"
25
+ "@agent-relay/hooks": "2.0.12"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/policy",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Agent policy management with multi-level fallback (repo, local PRPM, cloud workspace)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/config": "2.0.10"
25
+ "@agent-relay/config": "2.0.12"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/protocol",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Wire protocol types and framing for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/resiliency",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Health monitoring, logging, metrics, and crash resilience utilities for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/sdk",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Lightweight SDK for agent-to-agent communication via Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -55,7 +55,7 @@
55
55
  "access": "public"
56
56
  },
57
57
  "dependencies": {
58
- "@agent-relay/protocol": "2.0.10"
58
+ "@agent-relay/protocol": "2.0.12"
59
59
  },
60
60
  "engines": {
61
61
  "node": ">=18.0.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/spawner",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Agent spawning types and utilities for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/state",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Agent state persistence for non-hook CLIs (Codex, Gemini, etc.)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/storage",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Storage adapters and interfaces for Relay message/session persistence",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -56,7 +56,7 @@
56
56
  }
57
57
  },
58
58
  "dependencies": {
59
- "@agent-relay/protocol": "2.0.10"
59
+ "@agent-relay/protocol": "2.0.12"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/node": "^22.19.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/telemetry",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Anonymous telemetry for Agent Relay usage analytics",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/trajectory",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Trajectory integration utilities (trail/PDERO) for Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/config": "2.0.10"
25
+ "@agent-relay/config": "2.0.12"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -93,6 +93,16 @@ export declare class UserDirectoryService {
93
93
  * @returns Path to the written credential file
94
94
  */
95
95
  writeApiKeyCredential(userId: string, provider: string, apiKey: string): string;
96
+ /**
97
+ * Delete the credential file for a provider.
98
+ * Removes all known credential paths for the provider.
99
+ *
100
+ * @param userId - User ID
101
+ * @param provider - Provider name (claude, codex, gemini, etc.)
102
+ * @returns Array of deleted file paths
103
+ * @throws Error if provider is invalid
104
+ */
105
+ deleteProviderCredentials(userId: string, provider: string): string[];
96
106
  /**
97
107
  * Validate a user ID to prevent path traversal and other issues.
98
108
  *
@@ -100,6 +110,13 @@ export declare class UserDirectoryService {
100
110
  * @throws Error if userId is invalid
101
111
  */
102
112
  private validateUserId;
113
+ /**
114
+ * Validate a provider name to prevent injection attacks.
115
+ *
116
+ * @param provider - Provider name to validate
117
+ * @throws Error if provider is invalid
118
+ */
119
+ private validateProvider;
103
120
  /**
104
121
  * Ensure a directory exists, creating it recursively if needed.
105
122
  */
@@ -53,6 +53,15 @@ const PROVIDER_CONFIGS = {
53
53
  * All supported providers for initialization
54
54
  */
55
55
  const ALL_PROVIDERS = Object.keys(PROVIDER_CONFIGS);
56
+ /**
57
+ * Valid provider names for credential operations.
58
+ * Includes aliases like 'anthropic' for 'claude' and 'google' for 'gemini'.
59
+ */
60
+ const VALID_PROVIDERS = new Set([
61
+ ...ALL_PROVIDERS,
62
+ 'anthropic', // alias for claude
63
+ 'google', // alias for gemini
64
+ ]);
56
65
  /**
57
66
  * Service for managing per-user directories on workspace volumes.
58
67
  * Enables multi-user credential storage without conflicts.
@@ -209,6 +218,55 @@ export class UserDirectoryService {
209
218
  logger.info(`Wrote ${provider} API key for user ${userId} to ${credPath}`);
210
219
  return credPath;
211
220
  }
221
+ /**
222
+ * Delete the credential file for a provider.
223
+ * Removes all known credential paths for the provider.
224
+ *
225
+ * @param userId - User ID
226
+ * @param provider - Provider name (claude, codex, gemini, etc.)
227
+ * @returns Array of deleted file paths
228
+ * @throws Error if provider is invalid
229
+ */
230
+ deleteProviderCredentials(userId, provider) {
231
+ this.validateUserId(userId);
232
+ this.validateProvider(provider);
233
+ // Normalize provider to lowercase after validation
234
+ const normalizedProvider = provider.toLowerCase().trim();
235
+ const userHome = this.getUserHome(userId);
236
+ const deleted = [];
237
+ // Get all potential credential paths for this provider
238
+ const pathsToDelete = [];
239
+ // Add standard credential path
240
+ const config = PROVIDER_CONFIGS[normalizedProvider];
241
+ if (config) {
242
+ const providerDir = path.join(userHome, config.dir);
243
+ pathsToDelete.push(path.join(providerDir, config.credentialsFile));
244
+ }
245
+ // Handle Gemini/Google special case (.gemini/.env)
246
+ if (normalizedProvider === 'gemini' || normalizedProvider === 'google') {
247
+ pathsToDelete.push(path.join(userHome, '.gemini', '.env'));
248
+ }
249
+ // Handle anthropic special case (both .credentials.json and credentials.json)
250
+ if (normalizedProvider === 'anthropic' || normalizedProvider === 'claude') {
251
+ const claudeDir = path.join(userHome, '.claude');
252
+ pathsToDelete.push(path.join(claudeDir, '.credentials.json'));
253
+ pathsToDelete.push(path.join(claudeDir, 'credentials.json'));
254
+ }
255
+ // Delete each file if it exists
256
+ for (const credPath of pathsToDelete) {
257
+ try {
258
+ if (fs.existsSync(credPath)) {
259
+ fs.unlinkSync(credPath);
260
+ deleted.push(credPath);
261
+ logger.info(`Deleted ${normalizedProvider} credential file for user ${userId}: ${credPath}`);
262
+ }
263
+ }
264
+ catch (err) {
265
+ logger.warn('Failed to delete credential file', { path: credPath, error: String(err) });
266
+ }
267
+ }
268
+ return deleted;
269
+ }
212
270
  /**
213
271
  * Validate a user ID to prevent path traversal and other issues.
214
272
  *
@@ -229,6 +287,21 @@ export class UserDirectoryService {
229
287
  throw new Error('User ID would escape users directory');
230
288
  }
231
289
  }
290
+ /**
291
+ * Validate a provider name to prevent injection attacks.
292
+ *
293
+ * @param provider - Provider name to validate
294
+ * @throws Error if provider is invalid
295
+ */
296
+ validateProvider(provider) {
297
+ if (!provider || typeof provider !== 'string') {
298
+ throw new Error('Provider name is required');
299
+ }
300
+ const normalizedProvider = provider.toLowerCase().trim();
301
+ if (!VALID_PROVIDERS.has(normalizedProvider)) {
302
+ throw new Error(`Invalid provider: ${normalizedProvider.substring(0, 20)}`);
303
+ }
304
+ }
232
305
  /**
233
306
  * Ensure a directory exists, creating it recursively if needed.
234
307
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/user-directory",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "User directory service for agent-relay (per-user credential storage)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test:watch": "vitest"
23
23
  },
24
24
  "dependencies": {
25
- "@agent-relay/resiliency": "2.0.10"
25
+ "@agent-relay/resiliency": "2.0.12"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.19.3",
@@ -6,4 +6,5 @@ export * from './git-remote.js';
6
6
  export * from './update-checker.js';
7
7
  export * from './error-tracking.js';
8
8
  export * from './model-mapping.js';
9
+ export * from './relay-pty-path.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -6,4 +6,5 @@ export * from './git-remote.js';
6
6
  export * from './update-checker.js';
7
7
  export * from './error-tracking.js';
8
8
  export * from './model-mapping.js';
9
+ export * from './relay-pty-path.js';
9
10
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Shared utility for finding the relay-pty binary path.
3
+ *
4
+ * This is used by both:
5
+ * - packages/bridge/src/spawner.ts (AgentSpawner)
6
+ * - packages/wrapper/src/relay-pty-orchestrator.ts (RelayPtyOrchestrator)
7
+ *
8
+ * The search order handles multiple installation scenarios:
9
+ * 1. Development (local Rust build)
10
+ * 2. Local npm install (node_modules/agent-relay)
11
+ * 3. Global npm install via nvm
12
+ * 4. System-wide installs (/usr/local/bin)
13
+ */
14
+ /**
15
+ * Find the relay-pty binary.
16
+ *
17
+ * Search order:
18
+ * 1. bin/relay-pty in package root (installed by postinstall)
19
+ * 2. relay-pty/target/release/relay-pty (local Rust build)
20
+ * 3. /usr/local/bin/relay-pty (global install)
21
+ * 4. In node_modules when installed as dependency
22
+ * 5. Global npm installs (nvm) - both scoped and root packages
23
+ *
24
+ * @param callerDirname - The __dirname of the calling module (needed to resolve relative paths)
25
+ * @returns Path to relay-pty binary, or null if not found
26
+ */
27
+ export declare function findRelayPtyBinary(callerDirname: string): string | null;
28
+ /**
29
+ * Check if relay-pty binary is available (cached).
30
+ * Returns true if the binary exists, false otherwise.
31
+ *
32
+ * @param callerDirname - The __dirname of the calling module
33
+ */
34
+ export declare function hasRelayPtyBinary(callerDirname: string): boolean;
35
+ /**
36
+ * Get the cached relay-pty binary path.
37
+ * Must call hasRelayPtyBinary() or findRelayPtyBinary() first.
38
+ */
39
+ export declare function getCachedRelayPtyPath(): string | null | undefined;
40
+ /**
41
+ * Clear the cached binary path (for testing).
42
+ */
43
+ export declare function clearBinaryCache(): void;
44
+ //# sourceMappingURL=relay-pty-path.d.ts.map
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Shared utility for finding the relay-pty binary path.
3
+ *
4
+ * This is used by both:
5
+ * - packages/bridge/src/spawner.ts (AgentSpawner)
6
+ * - packages/wrapper/src/relay-pty-orchestrator.ts (RelayPtyOrchestrator)
7
+ *
8
+ * The search order handles multiple installation scenarios:
9
+ * 1. Development (local Rust build)
10
+ * 2. Local npm install (node_modules/agent-relay)
11
+ * 3. Global npm install via nvm
12
+ * 4. System-wide installs (/usr/local/bin)
13
+ */
14
+ import fs from 'node:fs';
15
+ import path from 'node:path';
16
+ /** Cached result of relay-pty binary check */
17
+ let cachedBinaryPath;
18
+ let cacheChecked = false;
19
+ /**
20
+ * Find the relay-pty binary.
21
+ *
22
+ * Search order:
23
+ * 1. bin/relay-pty in package root (installed by postinstall)
24
+ * 2. relay-pty/target/release/relay-pty (local Rust build)
25
+ * 3. /usr/local/bin/relay-pty (global install)
26
+ * 4. In node_modules when installed as dependency
27
+ * 5. Global npm installs (nvm) - both scoped and root packages
28
+ *
29
+ * @param callerDirname - The __dirname of the calling module (needed to resolve relative paths)
30
+ * @returns Path to relay-pty binary, or null if not found
31
+ */
32
+ export function findRelayPtyBinary(callerDirname) {
33
+ // Determine the agent-relay package root
34
+ // This code runs from either:
35
+ // - packages/{package}/dist/ (development/workspace)
36
+ // - node_modules/@agent-relay/{package}/dist/ (npm install)
37
+ //
38
+ // We need to find the agent-relay package root where bin/relay-pty lives
39
+ let packageRoot;
40
+ // Check if we're inside node_modules/@agent-relay/*/
41
+ if (callerDirname.includes('node_modules/@agent-relay/')) {
42
+ // Go from node_modules/@agent-relay/{package}/dist/ to agent-relay/
43
+ // dist/ -> {package}/ -> @agent-relay/ -> node_modules/ -> agent-relay/
44
+ packageRoot = path.join(callerDirname, '..', '..', '..', '..');
45
+ }
46
+ else if (callerDirname.includes('node_modules/agent-relay')) {
47
+ // Direct dependency: node_modules/agent-relay/packages/{package}/dist/
48
+ // dist/ -> {package}/ -> packages/ -> agent-relay/
49
+ packageRoot = path.join(callerDirname, '..', '..', '..');
50
+ }
51
+ else {
52
+ // Development: packages/{package}/dist/ -> packages/ -> project root
53
+ packageRoot = path.join(callerDirname, '..', '..', '..');
54
+ }
55
+ // Find the node_modules root for global installs
56
+ // When running from node_modules/@agent-relay/dashboard/node_modules/@agent-relay/wrapper/dist/
57
+ // we need to look for agent-relay at node_modules/agent-relay
58
+ // Use non-greedy match (.+?) to get the FIRST node_modules, not the last
59
+ let nodeModulesRoot = null;
60
+ const nodeModulesMatch = callerDirname.match(/^(.+?\/node_modules)\/@agent-relay\//);
61
+ if (nodeModulesMatch) {
62
+ nodeModulesRoot = nodeModulesMatch[1];
63
+ }
64
+ const candidates = [
65
+ // Primary: installed by postinstall from platform-specific binary
66
+ path.join(packageRoot, 'bin', 'relay-pty'),
67
+ // Development: local Rust build
68
+ path.join(packageRoot, 'relay-pty', 'target', 'release', 'relay-pty'),
69
+ path.join(packageRoot, 'relay-pty', 'target', 'debug', 'relay-pty'),
70
+ // Local build in cwd (for development)
71
+ path.join(process.cwd(), 'relay-pty', 'target', 'release', 'relay-pty'),
72
+ // Docker container (CI tests)
73
+ '/app/bin/relay-pty',
74
+ // Installed globally
75
+ '/usr/local/bin/relay-pty',
76
+ // In node_modules (when installed as local dependency)
77
+ path.join(process.cwd(), 'node_modules', 'agent-relay', 'bin', 'relay-pty'),
78
+ // Global npm install (nvm) - root package
79
+ path.join(process.env.HOME || '', '.nvm', 'versions', 'node', process.version, 'lib', 'node_modules', 'agent-relay', 'bin', 'relay-pty'),
80
+ ];
81
+ // Add candidate for root agent-relay package when running from scoped @agent-relay/* packages
82
+ if (nodeModulesRoot) {
83
+ candidates.push(path.join(nodeModulesRoot, 'agent-relay', 'bin', 'relay-pty'));
84
+ }
85
+ // Try common global npm paths
86
+ if (process.env.HOME) {
87
+ // Homebrew npm (macOS)
88
+ candidates.push(path.join('/usr/local/lib/node_modules', 'agent-relay', 'bin', 'relay-pty'));
89
+ candidates.push(path.join('/opt/homebrew/lib/node_modules', 'agent-relay', 'bin', 'relay-pty'));
90
+ // pnpm global
91
+ candidates.push(path.join(process.env.HOME, '.local', 'share', 'pnpm', 'global', 'node_modules', 'agent-relay', 'bin', 'relay-pty'));
92
+ }
93
+ for (const candidate of candidates) {
94
+ if (fs.existsSync(candidate)) {
95
+ return candidate;
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ /**
101
+ * Check if relay-pty binary is available (cached).
102
+ * Returns true if the binary exists, false otherwise.
103
+ *
104
+ * @param callerDirname - The __dirname of the calling module
105
+ */
106
+ export function hasRelayPtyBinary(callerDirname) {
107
+ if (!cacheChecked) {
108
+ cachedBinaryPath = findRelayPtyBinary(callerDirname);
109
+ cacheChecked = true;
110
+ }
111
+ return cachedBinaryPath !== null;
112
+ }
113
+ /**
114
+ * Get the cached relay-pty binary path.
115
+ * Must call hasRelayPtyBinary() or findRelayPtyBinary() first.
116
+ */
117
+ export function getCachedRelayPtyPath() {
118
+ return cachedBinaryPath;
119
+ }
120
+ /**
121
+ * Clear the cached binary path (for testing).
122
+ */
123
+ export function clearBinaryCache() {
124
+ cachedBinaryPath = undefined;
125
+ cacheChecked = false;
126
+ }
127
+ //# sourceMappingURL=relay-pty-path.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/utils",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "Shared utilities for agent-relay: logging, name generation, command resolution, update checking",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -49,6 +49,11 @@
49
49
  "types": "./dist/model-mapping.d.ts",
50
50
  "import": "./dist/model-mapping.js",
51
51
  "default": "./dist/model-mapping.js"
52
+ },
53
+ "./relay-pty-path": {
54
+ "types": "./dist/relay-pty-path.d.ts",
55
+ "import": "./dist/relay-pty-path.js",
56
+ "default": "./dist/relay-pty-path.js"
52
57
  }
53
58
  },
54
59
  "files": [
@@ -144,6 +144,7 @@ export declare class RelayPtyOrchestrator extends BaseWrapper {
144
144
  protected getCleanOutput(): string;
145
145
  /**
146
146
  * Find the relay-pty binary
147
+ * Uses shared utility from @agent-relay/utils
147
148
  */
148
149
  private findRelayPtyBinary;
149
150
  /**
@@ -27,6 +27,7 @@ const __filename = fileURLToPath(import.meta.url);
27
27
  const __dirname = dirname(__filename);
28
28
  import { BaseWrapper } from './base-wrapper.js';
29
29
  import { parseSummaryWithDetails, parseSessionEndFromOutput } from './parser.js';
30
+ import { findRelayPtyBinary as findRelayPtyBinaryUtil } from '@agent-relay/utils/relay-pty-path';
30
31
  import { stripAnsi, sleep, buildInjectionString, verifyInjection, INJECTION_CONSTANTS, AdaptiveThrottle, } from './shared.js';
31
32
  import { getMemoryMonitor, formatBytes, getCgroupManager, } from '@agent-relay/resiliency';
32
33
  // ============================================================================
@@ -388,37 +389,15 @@ export class RelayPtyOrchestrator extends BaseWrapper {
388
389
  // =========================================================================
389
390
  /**
390
391
  * Find the relay-pty binary
392
+ * Uses shared utility from @agent-relay/utils
391
393
  */
392
394
  findRelayPtyBinary() {
393
395
  // Check config path first
394
396
  if (this.config.relayPtyPath && existsSync(this.config.relayPtyPath)) {
395
397
  return this.config.relayPtyPath;
396
398
  }
397
- // Get the project root (three levels up from packages/wrapper/dist/)
398
- // packages/wrapper/dist/ -> packages/wrapper -> packages -> project root
399
- const projectRoot = join(__dirname, '..', '..', '..');
400
- // Check common locations (ordered by priority)
401
- const candidates = [
402
- // Primary: installed by postinstall from platform-specific binary
403
- join(projectRoot, 'bin', 'relay-pty'),
404
- // Development: local Rust build
405
- join(projectRoot, 'relay-pty', 'target', 'release', 'relay-pty'),
406
- join(projectRoot, 'relay-pty', 'target', 'debug', 'relay-pty'),
407
- // Local build in cwd (for development)
408
- join(process.cwd(), 'relay-pty', 'target', 'release', 'relay-pty'),
409
- join(process.cwd(), 'relay-pty', 'target', 'debug', 'relay-pty'),
410
- // Installed globally
411
- '/usr/local/bin/relay-pty',
412
- // In node_modules (when installed as dependency)
413
- join(process.cwd(), 'node_modules', 'agent-relay', 'bin', 'relay-pty'),
414
- join(process.cwd(), 'node_modules', '.bin', 'relay-pty'),
415
- ];
416
- for (const candidate of candidates) {
417
- if (existsSync(candidate)) {
418
- return candidate;
419
- }
420
- }
421
- return null;
399
+ // Use shared utility with current module's __dirname
400
+ return findRelayPtyBinaryUtil(__dirname);
422
401
  }
423
402
  /**
424
403
  * Spawn the relay-pty process
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/wrapper",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "CLI agent wrappers for Agent Relay - tmux, pty integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,11 +30,11 @@
30
30
  "clean": "rm -rf dist"
31
31
  },
32
32
  "dependencies": {
33
- "@agent-relay/api-types": "2.0.10",
34
- "@agent-relay/protocol": "2.0.10",
35
- "@agent-relay/config": "2.0.10",
36
- "@agent-relay/continuity": "2.0.10",
37
- "@agent-relay/resiliency": "2.0.10"
33
+ "@agent-relay/api-types": "2.0.12",
34
+ "@agent-relay/protocol": "2.0.12",
35
+ "@agent-relay/config": "2.0.12",
36
+ "@agent-relay/continuity": "2.0.12",
37
+ "@agent-relay/resiliency": "2.0.12"
38
38
  },
39
39
  "devDependencies": {
40
40
  "typescript": "^5.9.3",