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
|
@@ -18,6 +18,19 @@ export interface PromptHandler {
|
|
|
18
18
|
/** Description for logging/debugging */
|
|
19
19
|
description: string;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Error pattern configuration for detecting auth failures
|
|
23
|
+
*/
|
|
24
|
+
export interface ErrorPattern {
|
|
25
|
+
/** Pattern to detect in CLI output */
|
|
26
|
+
pattern: RegExp;
|
|
27
|
+
/** User-friendly error message */
|
|
28
|
+
message: string;
|
|
29
|
+
/** Whether this error is recoverable by retrying */
|
|
30
|
+
recoverable: boolean;
|
|
31
|
+
/** Optional hint for the user */
|
|
32
|
+
hint?: string;
|
|
33
|
+
}
|
|
21
34
|
/**
|
|
22
35
|
* CLI auth configuration for each provider
|
|
23
36
|
*/
|
|
@@ -38,6 +51,8 @@ export interface CLIAuthConfig {
|
|
|
38
51
|
prompts: PromptHandler[];
|
|
39
52
|
/** Success indicators in output */
|
|
40
53
|
successPatterns: RegExp[];
|
|
54
|
+
/** Error patterns to detect auth failures */
|
|
55
|
+
errorPatterns?: ErrorPattern[];
|
|
41
56
|
/** How long to wait for URL to appear (ms) */
|
|
42
57
|
waitTimeout: number;
|
|
43
58
|
/** Whether this provider supports device flow */
|
|
@@ -66,6 +81,10 @@ export declare function matchesSuccessPattern(text: string, patterns: RegExp[]):
|
|
|
66
81
|
* Find matching prompt handler that hasn't been responded to yet
|
|
67
82
|
*/
|
|
68
83
|
export declare function findMatchingPrompt(text: string, prompts: PromptHandler[], respondedPrompts: Set<string>): PromptHandler | null;
|
|
84
|
+
/**
|
|
85
|
+
* Check if text matches any error pattern and return the matched error
|
|
86
|
+
*/
|
|
87
|
+
export declare function findMatchingError(text: string, errorPatterns?: ErrorPattern[]): ErrorPattern | null;
|
|
69
88
|
/**
|
|
70
89
|
* Get list of supported provider IDs
|
|
71
90
|
*/
|
|
@@ -72,6 +72,8 @@ export const CLI_AUTH_CONFIG = {
|
|
|
72
72
|
{
|
|
73
73
|
// Fallback: Any "press enter" or "enter to confirm/continue" prompt
|
|
74
74
|
// Keep this LAST so more specific handlers match first
|
|
75
|
+
// NOTE: Error messages like "Press Enter to retry" are handled by checking
|
|
76
|
+
// error patterns FIRST in the PTY handler, so this won't trigger on errors
|
|
75
77
|
pattern: /press\s*enter|enter\s*to\s*(confirm|continue|proceed)|hit\s*enter/i,
|
|
76
78
|
response: '\r',
|
|
77
79
|
delay: 300,
|
|
@@ -79,6 +81,38 @@ export const CLI_AUTH_CONFIG = {
|
|
|
79
81
|
},
|
|
80
82
|
],
|
|
81
83
|
successPatterns: [/success/i, /authenticated/i, /logged\s*in/i, /you.*(?:are|now).*logged/i],
|
|
84
|
+
errorPatterns: [
|
|
85
|
+
{
|
|
86
|
+
pattern: /oauth\s*error.*(?:status\s*code\s*)?400/i,
|
|
87
|
+
message: 'Authentication failed - the authorization code was invalid or expired',
|
|
88
|
+
recoverable: true,
|
|
89
|
+
hint: 'This usually happens if the login took too long or the code was already used. Please try again and complete the browser login within a few minutes.',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
pattern: /oauth\s*error.*(?:status\s*code\s*)?401/i,
|
|
93
|
+
message: 'Authentication failed - unauthorized',
|
|
94
|
+
recoverable: true,
|
|
95
|
+
hint: 'Please try logging in again.',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
pattern: /oauth\s*error.*(?:status\s*code\s*)?403/i,
|
|
99
|
+
message: 'Authentication failed - access denied',
|
|
100
|
+
recoverable: true,
|
|
101
|
+
hint: 'Your account may not have access to Claude Code. Please check your Anthropic subscription.',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
pattern: /network\s*error|ENOTFOUND|ECONNREFUSED|timeout/i,
|
|
105
|
+
message: 'Network error during authentication',
|
|
106
|
+
recoverable: true,
|
|
107
|
+
hint: 'Please check your internet connection and try again.',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
pattern: /invalid\s*(?:code|token)|code\s*(?:expired|invalid)/i,
|
|
111
|
+
message: 'The authorization code was invalid or has expired',
|
|
112
|
+
recoverable: true,
|
|
113
|
+
hint: 'OAuth codes expire quickly. Please try again and complete the browser login promptly.',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
82
116
|
},
|
|
83
117
|
openai: {
|
|
84
118
|
command: 'codex',
|
|
@@ -160,10 +194,18 @@ export const CLI_AUTH_CONFIG = {
|
|
|
160
194
|
/**
|
|
161
195
|
* Strip ANSI escape codes from text
|
|
162
196
|
*/
|
|
197
|
+
/* eslint-disable no-control-regex */
|
|
163
198
|
export function stripAnsiCodes(text) {
|
|
164
|
-
//
|
|
165
|
-
|
|
199
|
+
// Handle various ANSI escape sequences:
|
|
200
|
+
// - CSI sequences: ESC [ params letter (params can include ?, >, =, etc.)
|
|
201
|
+
// - OSC sequences: ESC ] ... BEL/ST
|
|
202
|
+
// - Simple escapes: ESC letter
|
|
203
|
+
return text
|
|
204
|
+
.replace(/\x1b\[[0-9;?]*[a-zA-Z]/g, '') // CSI sequences including private modes (?2026h, etc.)
|
|
205
|
+
.replace(/\x1b\][^\x07]*\x07/g, '') // OSC sequences (title, etc.)
|
|
206
|
+
.replace(/\x1b[a-zA-Z]/g, ''); // Simple escape sequences
|
|
166
207
|
}
|
|
208
|
+
/* eslint-enable no-control-regex */
|
|
167
209
|
/**
|
|
168
210
|
* Check if text matches any success pattern
|
|
169
211
|
*/
|
|
@@ -185,6 +227,20 @@ export function findMatchingPrompt(text, prompts, respondedPrompts) {
|
|
|
185
227
|
}
|
|
186
228
|
return null;
|
|
187
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Check if text matches any error pattern and return the matched error
|
|
232
|
+
*/
|
|
233
|
+
export function findMatchingError(text, errorPatterns) {
|
|
234
|
+
if (!errorPatterns || errorPatterns.length === 0)
|
|
235
|
+
return null;
|
|
236
|
+
const cleanText = stripAnsiCodes(text);
|
|
237
|
+
for (const error of errorPatterns) {
|
|
238
|
+
if (error.pattern.test(cleanText)) {
|
|
239
|
+
return error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
188
244
|
/**
|
|
189
245
|
* Get list of supported provider IDs
|
|
190
246
|
*/
|
|
@@ -102,7 +102,7 @@ export function isClaudeCli(command) {
|
|
|
102
102
|
export function buildClaudeArgs(agentName, existingArgs = [], projectRoot) {
|
|
103
103
|
const config = findAgentConfig(agentName, projectRoot);
|
|
104
104
|
if (!config) {
|
|
105
|
-
return existingArgs;
|
|
105
|
+
return [...existingArgs]; // Return a copy to avoid reference issues
|
|
106
106
|
}
|
|
107
107
|
const newArgs = [...existingArgs];
|
|
108
108
|
// Add --model if specified in config and not already in args
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Revocation Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects when an AI CLI's authentication has been revoked.
|
|
5
|
+
* This can happen when:
|
|
6
|
+
* 1. User authenticates the same provider elsewhere (limited sessions)
|
|
7
|
+
* 2. Token expires or is invalidated
|
|
8
|
+
* 3. OAuth refresh fails
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Patterns that indicate authentication has been revoked or expired.
|
|
12
|
+
* These are typically output by Claude CLI, Codex, etc. when auth fails.
|
|
13
|
+
*/
|
|
14
|
+
export declare const AUTH_REVOCATION_PATTERNS: RegExp[];
|
|
15
|
+
/**
|
|
16
|
+
* Patterns that should NOT trigger auth revocation detection.
|
|
17
|
+
* These are false positives that might match auth patterns but aren't actual auth errors.
|
|
18
|
+
*/
|
|
19
|
+
export declare const AUTH_FALSE_POSITIVE_PATTERNS: RegExp[];
|
|
20
|
+
export interface AuthRevocationResult {
|
|
21
|
+
detected: boolean;
|
|
22
|
+
pattern?: string;
|
|
23
|
+
confidence: 'high' | 'medium' | 'low';
|
|
24
|
+
message?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Detect if output indicates authentication has been revoked.
|
|
28
|
+
*
|
|
29
|
+
* @param output - The CLI output to analyze
|
|
30
|
+
* @param recentOutputOnly - If true, only check the last ~500 chars (for real-time detection)
|
|
31
|
+
* @returns Detection result with confidence level
|
|
32
|
+
*/
|
|
33
|
+
export declare function detectAuthRevocation(output: string, recentOutputOnly?: boolean): AuthRevocationResult;
|
|
34
|
+
/**
|
|
35
|
+
* Check if the given text looks like an auth-related CLI prompt
|
|
36
|
+
* that's waiting for user action (not an error, but a request to auth).
|
|
37
|
+
*/
|
|
38
|
+
export declare function isAuthPrompt(text: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Provider-specific auth detection configuration.
|
|
41
|
+
* Different AI CLIs may have different error messages.
|
|
42
|
+
*/
|
|
43
|
+
export declare const PROVIDER_AUTH_PATTERNS: Record<string, RegExp[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Detect auth revocation for a specific provider.
|
|
46
|
+
* Uses provider-specific patterns in addition to general patterns.
|
|
47
|
+
*/
|
|
48
|
+
export declare function detectProviderAuthRevocation(output: string, provider: string): AuthRevocationResult;
|
|
49
|
+
//# sourceMappingURL=auth-detection.d.ts.map
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Revocation Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects when an AI CLI's authentication has been revoked.
|
|
5
|
+
* This can happen when:
|
|
6
|
+
* 1. User authenticates the same provider elsewhere (limited sessions)
|
|
7
|
+
* 2. Token expires or is invalidated
|
|
8
|
+
* 3. OAuth refresh fails
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Patterns that indicate authentication has been revoked or expired.
|
|
12
|
+
* These are typically output by Claude CLI, Codex, etc. when auth fails.
|
|
13
|
+
*/
|
|
14
|
+
export const AUTH_REVOCATION_PATTERNS = [
|
|
15
|
+
// Session/token expiration
|
|
16
|
+
/session\s+(has\s+)?expired/i,
|
|
17
|
+
/token\s+(has\s+)?expired/i,
|
|
18
|
+
/credentials?\s+(have\s+)?expired/i,
|
|
19
|
+
// Login required
|
|
20
|
+
/please\s+log\s*in\s+again/i,
|
|
21
|
+
/login\s+required/i,
|
|
22
|
+
/authentication\s+required/i,
|
|
23
|
+
/must\s+(be\s+)?log(ged)?\s*in/i,
|
|
24
|
+
/you\s+need\s+to\s+log\s*in/i,
|
|
25
|
+
// Unauthorized
|
|
26
|
+
/\bunauthorized\b/i,
|
|
27
|
+
/not\s+authorized/i,
|
|
28
|
+
/access\s+denied/i,
|
|
29
|
+
// Invalid credentials
|
|
30
|
+
/invalid\s+credentials?/i,
|
|
31
|
+
/invalid\s+token/i,
|
|
32
|
+
/invalid\s+session/i,
|
|
33
|
+
/not\s+authenticated/i,
|
|
34
|
+
// OAuth specific
|
|
35
|
+
/oauth\s+error.*401/i,
|
|
36
|
+
/oauth\s+error.*403/i,
|
|
37
|
+
/refresh\s+token\s+(is\s+)?invalid/i,
|
|
38
|
+
/failed\s+to\s+refresh/i,
|
|
39
|
+
// API errors that indicate auth issues
|
|
40
|
+
/api\s+error.*401/i,
|
|
41
|
+
/api\s+error.*403/i,
|
|
42
|
+
/http\s+401/i,
|
|
43
|
+
/http\s+403/i,
|
|
44
|
+
// Claude-specific patterns
|
|
45
|
+
/your\s+api\s+key\s+is\s+invalid/i,
|
|
46
|
+
/api\s+key\s+not\s+found/i,
|
|
47
|
+
/signed\s+out/i,
|
|
48
|
+
/session\s+revoked/i,
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Patterns that should NOT trigger auth revocation detection.
|
|
52
|
+
* These are false positives that might match auth patterns but aren't actual auth errors.
|
|
53
|
+
*/
|
|
54
|
+
export const AUTH_FALSE_POSITIVE_PATTERNS = [
|
|
55
|
+
// Documentation or help text
|
|
56
|
+
/how\s+to\s+log\s*in/i,
|
|
57
|
+
/login\s+instructions/i,
|
|
58
|
+
/authentication\s+guide/i,
|
|
59
|
+
// Code comments or strings
|
|
60
|
+
/\/\/.*unauthorized/i,
|
|
61
|
+
/\/\*.*unauthorized.*\*\//i,
|
|
62
|
+
/".*unauthorized.*"/i,
|
|
63
|
+
/'.*unauthorized.*'/i,
|
|
64
|
+
// Error handling code
|
|
65
|
+
/catch.*unauthorized/i,
|
|
66
|
+
/handle.*auth.*error/i,
|
|
67
|
+
/if.*session.*expired/i,
|
|
68
|
+
// Instructional content
|
|
69
|
+
/you\s+should\s+log\s*in/i,
|
|
70
|
+
/make\s+sure\s+you('re)?\s+logged\s*in/i,
|
|
71
|
+
];
|
|
72
|
+
/**
|
|
73
|
+
* Detect if output indicates authentication has been revoked.
|
|
74
|
+
*
|
|
75
|
+
* @param output - The CLI output to analyze
|
|
76
|
+
* @param recentOutputOnly - If true, only check the last ~500 chars (for real-time detection)
|
|
77
|
+
* @returns Detection result with confidence level
|
|
78
|
+
*/
|
|
79
|
+
export function detectAuthRevocation(output, recentOutputOnly = false) {
|
|
80
|
+
// If checking recent output only, truncate to last 500 chars
|
|
81
|
+
const textToCheck = recentOutputOnly ? output.slice(-500) : output;
|
|
82
|
+
// First check for false positives
|
|
83
|
+
for (const falsePositive of AUTH_FALSE_POSITIVE_PATTERNS) {
|
|
84
|
+
if (falsePositive.test(textToCheck)) {
|
|
85
|
+
return { detected: false, confidence: 'low' };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Check each auth revocation pattern
|
|
89
|
+
for (const pattern of AUTH_REVOCATION_PATTERNS) {
|
|
90
|
+
const match = textToCheck.match(pattern);
|
|
91
|
+
if (match) {
|
|
92
|
+
// Determine confidence based on pattern specificity
|
|
93
|
+
const confidence = getConfidenceLevel(pattern, match[0]);
|
|
94
|
+
return {
|
|
95
|
+
detected: true,
|
|
96
|
+
pattern: pattern.source,
|
|
97
|
+
confidence,
|
|
98
|
+
message: match[0],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { detected: false, confidence: 'low' };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Determine confidence level based on the matched pattern.
|
|
106
|
+
*/
|
|
107
|
+
function getConfidenceLevel(pattern, matchedText) {
|
|
108
|
+
const patternStr = pattern.source.toLowerCase();
|
|
109
|
+
// High confidence: Explicit auth failure messages
|
|
110
|
+
if (patternStr.includes('session') && patternStr.includes('expired') ||
|
|
111
|
+
patternStr.includes('please') && patternStr.includes('log') ||
|
|
112
|
+
patternStr.includes('authentication required') ||
|
|
113
|
+
patternStr.includes('token') && patternStr.includes('expired') ||
|
|
114
|
+
patternStr.includes('signed out') ||
|
|
115
|
+
patternStr.includes('session revoked')) {
|
|
116
|
+
return 'high';
|
|
117
|
+
}
|
|
118
|
+
// Medium confidence: General auth errors
|
|
119
|
+
if (patternStr.includes('unauthorized') ||
|
|
120
|
+
patternStr.includes('401') ||
|
|
121
|
+
patternStr.includes('403') ||
|
|
122
|
+
patternStr.includes('invalid') && patternStr.includes('credentials')) {
|
|
123
|
+
return 'medium';
|
|
124
|
+
}
|
|
125
|
+
// Low confidence: Could be related to other errors
|
|
126
|
+
return 'low';
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if the given text looks like an auth-related CLI prompt
|
|
130
|
+
* that's waiting for user action (not an error, but a request to auth).
|
|
131
|
+
*/
|
|
132
|
+
export function isAuthPrompt(text) {
|
|
133
|
+
const authPromptPatterns = [
|
|
134
|
+
/open\s+this\s+url/i,
|
|
135
|
+
/visit\s+.*to\s+authorize/i,
|
|
136
|
+
/enter\s+your\s+api\s+key/i,
|
|
137
|
+
/paste\s+your\s+token/i,
|
|
138
|
+
/waiting\s+for\s+authorization/i,
|
|
139
|
+
/complete\s+login\s+in\s+browser/i,
|
|
140
|
+
];
|
|
141
|
+
return authPromptPatterns.some(pattern => pattern.test(text));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Provider-specific auth detection configuration.
|
|
145
|
+
* Different AI CLIs may have different error messages.
|
|
146
|
+
*/
|
|
147
|
+
export const PROVIDER_AUTH_PATTERNS = {
|
|
148
|
+
claude: [
|
|
149
|
+
/claude.*session.*expired/i,
|
|
150
|
+
/anthropic.*unauthorized/i,
|
|
151
|
+
/claude.*not\s+authenticated/i,
|
|
152
|
+
/please\s+run\s+claude\s+login/i,
|
|
153
|
+
],
|
|
154
|
+
codex: [
|
|
155
|
+
/codex.*session.*expired/i,
|
|
156
|
+
/openai.*unauthorized/i,
|
|
157
|
+
/codex.*not\s+authenticated/i,
|
|
158
|
+
],
|
|
159
|
+
gemini: [
|
|
160
|
+
/gemini.*session.*expired/i,
|
|
161
|
+
/google.*unauthorized/i,
|
|
162
|
+
/gemini.*not\s+authenticated/i,
|
|
163
|
+
],
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Detect auth revocation for a specific provider.
|
|
167
|
+
* Uses provider-specific patterns in addition to general patterns.
|
|
168
|
+
*/
|
|
169
|
+
export function detectProviderAuthRevocation(output, provider) {
|
|
170
|
+
// First check general patterns
|
|
171
|
+
const generalResult = detectAuthRevocation(output, true);
|
|
172
|
+
if (generalResult.detected && generalResult.confidence === 'high') {
|
|
173
|
+
return generalResult;
|
|
174
|
+
}
|
|
175
|
+
// Check provider-specific patterns
|
|
176
|
+
const providerPatterns = PROVIDER_AUTH_PATTERNS[provider.toLowerCase()];
|
|
177
|
+
if (providerPatterns) {
|
|
178
|
+
for (const pattern of providerPatterns) {
|
|
179
|
+
const match = output.match(pattern);
|
|
180
|
+
if (match) {
|
|
181
|
+
return {
|
|
182
|
+
detected: true,
|
|
183
|
+
pattern: pattern.source,
|
|
184
|
+
confidence: 'high',
|
|
185
|
+
message: match[0],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return generalResult;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=auth-detection.js.map
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseWrapper - Abstract base class for agent wrappers
|
|
3
|
+
*
|
|
4
|
+
* Provides shared functionality between TmuxWrapper and PtyWrapper:
|
|
5
|
+
* - Message queue management and deduplication
|
|
6
|
+
* - Spawn/release command parsing and execution
|
|
7
|
+
* - Continuity integration (agent ID, summary saving)
|
|
8
|
+
* - Relay command handling
|
|
9
|
+
* - Line joining for multi-line commands
|
|
10
|
+
*
|
|
11
|
+
* Subclasses implement:
|
|
12
|
+
* - start() - Initialize and start the agent process
|
|
13
|
+
* - stop() - Stop the agent process
|
|
14
|
+
* - performInjection() - Inject content into the agent
|
|
15
|
+
* - getCleanOutput() - Get cleaned output for parsing
|
|
16
|
+
*/
|
|
17
|
+
import { EventEmitter } from 'node:events';
|
|
18
|
+
import { RelayClient } from './client.js';
|
|
19
|
+
import type { ParsedCommand, ParsedSummary } from './parser.js';
|
|
20
|
+
import type { SendPayload, SendMeta, SpeakOnTrigger } from '../protocol/types.js';
|
|
21
|
+
import { type QueuedMessage, type InjectionMetrics, type CliType } from './shared.js';
|
|
22
|
+
import { type ContinuityManager } from '../continuity/index.js';
|
|
23
|
+
/**
|
|
24
|
+
* Base configuration shared by all wrapper types
|
|
25
|
+
*/
|
|
26
|
+
export interface BaseWrapperConfig {
|
|
27
|
+
/** Agent name (must be unique) */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Command to execute */
|
|
30
|
+
command: string;
|
|
31
|
+
/** Command arguments */
|
|
32
|
+
args?: string[];
|
|
33
|
+
/** Relay daemon socket path */
|
|
34
|
+
socketPath?: string;
|
|
35
|
+
/** Working directory */
|
|
36
|
+
cwd?: string;
|
|
37
|
+
/** Environment variables */
|
|
38
|
+
env?: Record<string, string>;
|
|
39
|
+
/** Relay prefix pattern (default: '->relay:') */
|
|
40
|
+
relayPrefix?: string;
|
|
41
|
+
/** CLI type (auto-detected if not set) */
|
|
42
|
+
cliType?: CliType;
|
|
43
|
+
/** Dashboard port for spawn/release API */
|
|
44
|
+
dashboardPort?: number;
|
|
45
|
+
/** Callback when spawn command is parsed */
|
|
46
|
+
onSpawn?: (name: string, cli: string, task: string) => Promise<void>;
|
|
47
|
+
/** Callback when release command is parsed */
|
|
48
|
+
onRelease?: (name: string) => Promise<void>;
|
|
49
|
+
/** Agent ID to resume from (for continuity) */
|
|
50
|
+
resumeAgentId?: string;
|
|
51
|
+
/** Stream logs to daemon */
|
|
52
|
+
streamLogs?: boolean;
|
|
53
|
+
/** Task/role description */
|
|
54
|
+
task?: string;
|
|
55
|
+
/** Shadow configuration */
|
|
56
|
+
shadowOf?: string;
|
|
57
|
+
shadowSpeakOn?: SpeakOnTrigger[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Abstract base class for agent wrappers
|
|
61
|
+
*/
|
|
62
|
+
export declare abstract class BaseWrapper extends EventEmitter {
|
|
63
|
+
protected config: BaseWrapperConfig;
|
|
64
|
+
protected client: RelayClient;
|
|
65
|
+
protected relayPrefix: string;
|
|
66
|
+
protected cliType: CliType;
|
|
67
|
+
protected running: boolean;
|
|
68
|
+
protected messageQueue: QueuedMessage[];
|
|
69
|
+
protected sentMessageHashes: Set<string>;
|
|
70
|
+
protected isInjecting: boolean;
|
|
71
|
+
protected receivedMessageIds: Set<string>;
|
|
72
|
+
protected injectionMetrics: InjectionMetrics;
|
|
73
|
+
protected processedSpawnCommands: Set<string>;
|
|
74
|
+
protected processedReleaseCommands: Set<string>;
|
|
75
|
+
protected pendingFencedSpawn: {
|
|
76
|
+
name: string;
|
|
77
|
+
cli: string;
|
|
78
|
+
taskLines: string[];
|
|
79
|
+
} | null;
|
|
80
|
+
protected continuity?: ContinuityManager;
|
|
81
|
+
protected agentId?: string;
|
|
82
|
+
protected processedContinuityCommands: Set<string>;
|
|
83
|
+
protected sessionEndProcessed: boolean;
|
|
84
|
+
protected sessionEndData?: {
|
|
85
|
+
summary?: string;
|
|
86
|
+
completedTasks?: string[];
|
|
87
|
+
};
|
|
88
|
+
protected lastSummaryRawContent: string;
|
|
89
|
+
constructor(config: BaseWrapperConfig);
|
|
90
|
+
/** Start the agent process */
|
|
91
|
+
abstract start(): Promise<void>;
|
|
92
|
+
/** Stop the agent process */
|
|
93
|
+
abstract stop(): Promise<void> | void;
|
|
94
|
+
/** Inject content into the agent */
|
|
95
|
+
protected abstract performInjection(content: string): Promise<void>;
|
|
96
|
+
/** Get cleaned output for parsing */
|
|
97
|
+
protected abstract getCleanOutput(): string;
|
|
98
|
+
get isRunning(): boolean;
|
|
99
|
+
get name(): string;
|
|
100
|
+
getAgentId(): string | undefined;
|
|
101
|
+
getInjectionMetrics(): InjectionMetrics & {
|
|
102
|
+
successRate: number;
|
|
103
|
+
};
|
|
104
|
+
get pendingMessageCount(): number;
|
|
105
|
+
/**
|
|
106
|
+
* Handle incoming message from relay
|
|
107
|
+
*/
|
|
108
|
+
protected handleIncomingMessage(from: string, payload: SendPayload, messageId: string, meta?: SendMeta, originalTo?: string): void;
|
|
109
|
+
/**
|
|
110
|
+
* Send a relay command via the client
|
|
111
|
+
*/
|
|
112
|
+
protected sendRelayCommand(cmd: ParsedCommand): void;
|
|
113
|
+
/**
|
|
114
|
+
* Parse spawn and release commands from output
|
|
115
|
+
*/
|
|
116
|
+
protected parseSpawnReleaseCommands(content: string): void;
|
|
117
|
+
/**
|
|
118
|
+
* Execute a spawn command
|
|
119
|
+
*/
|
|
120
|
+
protected executeSpawn(name: string, cli: string, task: string): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Execute a release command
|
|
123
|
+
*/
|
|
124
|
+
protected executeRelease(name: string): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Initialize agent ID for continuity/resume
|
|
127
|
+
*/
|
|
128
|
+
protected initializeAgentId(): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Parse continuity commands from output
|
|
131
|
+
*/
|
|
132
|
+
protected parseContinuityCommands(content: string): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Save a parsed summary to the continuity ledger
|
|
135
|
+
*/
|
|
136
|
+
protected saveSummaryToLedger(summary: ParsedSummary): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Reset session-specific state for wrapper reuse
|
|
139
|
+
*/
|
|
140
|
+
resetSessionState(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Join continuation lines for multi-line relay/continuity commands.
|
|
143
|
+
* TUIs like Claude Code insert real newlines in output, causing
|
|
144
|
+
* messages to span multiple lines. This joins indented
|
|
145
|
+
* continuation lines back to the command line.
|
|
146
|
+
*/
|
|
147
|
+
protected joinContinuationLines(content: string): string;
|
|
148
|
+
/**
|
|
149
|
+
* Clean up resources
|
|
150
|
+
*/
|
|
151
|
+
protected destroyClient(): void;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=base-wrapper.d.ts.map
|