agent-relay 2.0.18 → 2.0.20
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/bin/relay-pty-darwin-arm64 +0 -0
- package/bin/relay-pty-darwin-x64 +0 -0
- package/bin/relay-pty-linux-x64 +0 -0
- package/dist/dashboard/out/404.html +1 -1
- package/dist/dashboard/out/_next/static/chunks/320-a6304232cd0ee2ce.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/631-16b905e5920f9b59.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-ecb16ffd3b36262b.js +1 -0
- package/dist/dashboard/out/_next/static/css/{45361ce86b2847c4.css → 6892f8422896ef7a.css} +1 -1
- package/dist/dashboard/out/app/onboarding.html +1 -1
- package/dist/dashboard/out/app/onboarding.txt +1 -1
- package/dist/dashboard/out/app.html +1 -1
- package/dist/dashboard/out/app.txt +2 -2
- package/dist/dashboard/out/cloud/link.html +1 -1
- package/dist/dashboard/out/cloud/link.txt +1 -1
- package/dist/dashboard/out/complete-profile.html +2 -2
- package/dist/dashboard/out/complete-profile.txt +1 -1
- package/dist/dashboard/out/connect-repos.html +1 -1
- package/dist/dashboard/out/connect-repos.txt +1 -1
- package/dist/dashboard/out/history.html +1 -1
- package/dist/dashboard/out/history.txt +1 -1
- package/dist/dashboard/out/index.html +1 -1
- package/dist/dashboard/out/index.txt +2 -2
- package/dist/dashboard/out/login.html +2 -2
- package/dist/dashboard/out/login.txt +1 -1
- package/dist/dashboard/out/metrics.html +1 -1
- package/dist/dashboard/out/metrics.txt +1 -1
- package/dist/dashboard/out/pricing.html +2 -2
- package/dist/dashboard/out/pricing.txt +1 -1
- package/dist/dashboard/out/providers/setup/claude.html +1 -1
- package/dist/dashboard/out/providers/setup/claude.txt +1 -1
- package/dist/dashboard/out/providers/setup/codex.html +1 -1
- package/dist/dashboard/out/providers/setup/codex.txt +1 -1
- package/dist/dashboard/out/providers/setup/cursor.html +1 -1
- package/dist/dashboard/out/providers/setup/cursor.txt +1 -1
- package/dist/dashboard/out/providers.html +1 -1
- package/dist/dashboard/out/providers.txt +2 -2
- package/dist/dashboard/out/signup.html +2 -2
- package/dist/dashboard/out/signup.txt +1 -1
- package/package.json +23 -17
- package/packages/api-types/package.json +2 -2
- package/packages/bridge/dist/spawner.d.ts +2 -0
- package/packages/bridge/dist/spawner.js +75 -23
- package/packages/bridge/package.json +8 -8
- package/packages/cli-tester/README.md +277 -0
- package/packages/cli-tester/dist/index.d.ts +21 -0
- package/packages/cli-tester/dist/index.js +21 -0
- package/packages/cli-tester/dist/utils/credential-check.d.ts +56 -0
- package/packages/cli-tester/dist/utils/credential-check.js +230 -0
- package/packages/cli-tester/dist/utils/socket-client.d.ts +76 -0
- package/packages/cli-tester/dist/utils/socket-client.js +153 -0
- package/packages/cli-tester/docker/entrypoint.sh +58 -0
- package/packages/cli-tester/package.json +32 -0
- package/packages/cli-tester/scripts/clear-auth.sh +101 -0
- package/packages/cli-tester/scripts/inject-message.sh +42 -0
- package/packages/cli-tester/scripts/start.sh +71 -0
- package/packages/cli-tester/scripts/test-cli.sh +56 -0
- package/packages/cli-tester/scripts/test-full-spawn.sh +238 -0
- package/packages/cli-tester/scripts/test-registration.sh +182 -0
- package/packages/cli-tester/scripts/test-setup-flow.sh +202 -0
- package/packages/cli-tester/scripts/test-spawn.sh +140 -0
- package/packages/cli-tester/scripts/test-with-daemon.sh +247 -0
- package/packages/cli-tester/scripts/verify-auth.sh +112 -0
- package/packages/cloud/dist/api/cli-pty-runner.js +9 -6
- package/packages/cloud/package.json +6 -6
- package/packages/config/dist/cli-auth-config.js +75 -0
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +1 -1
- package/packages/daemon/dist/cli-auth.js +5 -1
- package/packages/daemon/dist/router.js +4 -4
- package/packages/daemon/dist/server.js +38 -19
- package/packages/daemon/dist/spawn-manager.d.ts +4 -0
- package/packages/daemon/dist/spawn-manager.js +2 -0
- package/packages/daemon/package.json +12 -12
- package/packages/dashboard/dist/server.js +4 -0
- package/packages/dashboard/package.json +14 -14
- package/packages/dashboard/ui/app/providers/page.tsx +2 -2
- package/packages/dashboard/ui/react-components/ProviderConnectionList.tsx +23 -8
- package/packages/dashboard/ui/react-components/SpawnModal.tsx +16 -6
- package/packages/dashboard/ui/react-components/settings/WorkspaceSettingsPanel.tsx +22 -6
- package/packages/dashboard/ui-dist/404.html +1 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/320-a6304232cd0ee2ce.js +1 -0
- package/packages/dashboard/ui-dist/_next/static/chunks/631-16b905e5920f9b59.js +1 -0
- package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-ecb16ffd3b36262b.js +1 -0
- package/packages/dashboard/ui-dist/_next/static/css/{45361ce86b2847c4.css → 6892f8422896ef7a.css} +1 -1
- package/packages/dashboard/ui-dist/app/onboarding.html +1 -1
- package/packages/dashboard/ui-dist/app/onboarding.txt +1 -1
- package/packages/dashboard/ui-dist/app.html +1 -1
- package/packages/dashboard/ui-dist/app.txt +2 -2
- package/packages/dashboard/ui-dist/cloud/link.html +1 -1
- package/packages/dashboard/ui-dist/cloud/link.txt +1 -1
- package/packages/dashboard/ui-dist/complete-profile.html +2 -2
- package/packages/dashboard/ui-dist/complete-profile.txt +1 -1
- package/packages/dashboard/ui-dist/connect-repos.html +1 -1
- package/packages/dashboard/ui-dist/connect-repos.txt +1 -1
- package/packages/dashboard/ui-dist/history.html +1 -1
- package/packages/dashboard/ui-dist/history.txt +1 -1
- package/packages/dashboard/ui-dist/index.html +1 -1
- package/packages/dashboard/ui-dist/index.txt +2 -2
- package/packages/dashboard/ui-dist/login.html +2 -2
- package/packages/dashboard/ui-dist/login.txt +1 -1
- package/packages/dashboard/ui-dist/metrics.html +1 -1
- package/packages/dashboard/ui-dist/metrics.txt +1 -1
- package/packages/dashboard/ui-dist/pricing.html +2 -2
- package/packages/dashboard/ui-dist/pricing.txt +1 -1
- package/packages/dashboard/ui-dist/providers/setup/claude.html +1 -1
- package/packages/dashboard/ui-dist/providers/setup/claude.txt +1 -1
- package/packages/dashboard/ui-dist/providers/setup/codex.html +1 -1
- package/packages/dashboard/ui-dist/providers/setup/codex.txt +1 -1
- package/packages/dashboard/ui-dist/providers/setup/cursor.html +1 -1
- package/packages/dashboard/ui-dist/providers/setup/cursor.txt +1 -1
- package/packages/dashboard/ui-dist/providers.html +1 -1
- package/packages/dashboard/ui-dist/providers.txt +2 -2
- package/packages/dashboard/ui-dist/signup.html +2 -2
- package/packages/dashboard/ui-dist/signup.txt +1 -1
- package/packages/dashboard-server/dist/server.js +4 -0
- package/packages/dashboard-server/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/README.md +512 -58
- package/packages/sdk/dist/client.d.ts +135 -1
- package/packages/sdk/dist/client.js +338 -0
- package/packages/sdk/dist/index.d.ts +2 -1
- package/packages/sdk/dist/index.js +2 -0
- package/packages/sdk/dist/logs.d.ts +61 -0
- package/packages/sdk/dist/logs.js +95 -0
- package/packages/sdk/dist/protocol/index.d.ts +1 -1
- package/packages/sdk/dist/protocol/types.d.ts +186 -1
- package/packages/sdk/package.json +3 -3
- package/packages/spawner/package.json +2 -2
- package/packages/state/package.json +1 -1
- package/packages/storage/dist/sqlite-adapter.js +2 -0
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +1 -1
- package/packages/wrapper/dist/base-wrapper.js +27 -10
- package/packages/wrapper/dist/idle-detector.d.ts +4 -0
- package/packages/wrapper/dist/idle-detector.js +21 -8
- package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +5 -0
- package/packages/wrapper/dist/relay-pty-orchestrator.js +60 -5
- package/packages/wrapper/dist/tmux-wrapper.js +16 -0
- package/packages/wrapper/package.json +7 -7
- package/scripts/hooks/install.sh +16 -0
- package/scripts/hooks/pre-commit +60 -0
- package/scripts/postinstall.js +41 -1
- package/specs/PRIMITIVES_ROADMAP.md +2154 -0
- package/dist/dashboard/out/_next/static/chunks/320-402ffc8646b31da1.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/631-af51bad94027527a.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-bcf46064ac4474ce.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/320-402ffc8646b31da1.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/631-af51bad94027527a.js +0 -1
- package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-bcf46064ac4474ce.js +0 -1
- /package/dist/dashboard/out/_next/static/{JIjqkuDKNeoSg7KaMMuhx → PwtT8u1tFMW_S1HUv0i5S}/_buildManifest.js +0 -0
- /package/dist/dashboard/out/_next/static/{JIjqkuDKNeoSg7KaMMuhx → PwtT8u1tFMW_S1HUv0i5S}/_ssgManifest.js +0 -0
- /package/packages/dashboard/ui-dist/_next/static/{JIjqkuDKNeoSg7KaMMuhx → 52xh7eSCZzG97BVf5zzLY}/_buildManifest.js +0 -0
- /package/packages/dashboard/ui-dist/_next/static/{JIjqkuDKNeoSg7KaMMuhx → 52xh7eSCZzG97BVf5zzLY}/_ssgManifest.js +0 -0
- /package/packages/dashboard/ui-dist/_next/static/{nmkOi7bqeDmLMoWBih8lz → NN1eZ4W4r5XU6mkmJWV2-}/_buildManifest.js +0 -0
- /package/packages/dashboard/ui-dist/_next/static/{nmkOi7bqeDmLMoWBih8lz → NN1eZ4W4r5XU6mkmJWV2-}/_ssgManifest.js +0 -0
- /package/packages/dashboard/ui-dist/_next/static/{wk_gKRNSPpWE-ZhGL6UMl → PwtT8u1tFMW_S1HUv0i5S}/_buildManifest.js +0 -0
- /package/packages/dashboard/ui-dist/_next/static/{wk_gKRNSPpWE-ZhGL6UMl → PwtT8u1tFMW_S1HUv0i5S}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Test CLI spawn flow - simulates real spawner behavior
|
|
3
|
+
# This is a more realistic test that mimics what AgentSpawner does
|
|
4
|
+
#
|
|
5
|
+
# Usage: ./test-spawn.sh <cli> [--interactive]
|
|
6
|
+
# Example: ./test-spawn.sh cursor
|
|
7
|
+
# ./test-spawn.sh cursor --interactive
|
|
8
|
+
# DEBUG_SPAWN=1 ./test-spawn.sh cursor
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
CLI=${1:-cursor}
|
|
13
|
+
INTERACTIVE=""
|
|
14
|
+
if [ "$2" = "--interactive" ]; then
|
|
15
|
+
INTERACTIVE="1"
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Map CLI name to actual command (cursor installs as 'agent')
|
|
19
|
+
CLI_CMD="$CLI"
|
|
20
|
+
if [ "$CLI" = "cursor" ]; then
|
|
21
|
+
CLI_CMD="agent"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
NAME="spawn-test-${CLI}"
|
|
25
|
+
SOCKET="/tmp/relay-pty-${NAME}.sock"
|
|
26
|
+
RELAY_DATA_DIR="/tmp/relay-test-data"
|
|
27
|
+
|
|
28
|
+
# Create test data directories
|
|
29
|
+
mkdir -p "$RELAY_DATA_DIR"
|
|
30
|
+
|
|
31
|
+
# Cleanup function
|
|
32
|
+
cleanup() {
|
|
33
|
+
echo ""
|
|
34
|
+
echo "Cleaning up..."
|
|
35
|
+
rm -f "$SOCKET"
|
|
36
|
+
pkill -f "relay-pty.*${NAME}" 2>/dev/null || true
|
|
37
|
+
}
|
|
38
|
+
trap cleanup EXIT
|
|
39
|
+
|
|
40
|
+
# Remove stale socket if exists
|
|
41
|
+
rm -f "$SOCKET"
|
|
42
|
+
|
|
43
|
+
echo "========================================"
|
|
44
|
+
echo " Spawn Flow Test: $CLI"
|
|
45
|
+
echo "========================================"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "This test simulates what AgentSpawner.spawn() does:"
|
|
48
|
+
echo " 1. Builds command with appropriate flags"
|
|
49
|
+
echo " 2. Starts relay-pty with the CLI"
|
|
50
|
+
echo " 3. Monitors for daemon registration"
|
|
51
|
+
echo ""
|
|
52
|
+
echo "Session name: $NAME"
|
|
53
|
+
echo "Socket path: $SOCKET"
|
|
54
|
+
echo "Data dir: $RELAY_DATA_DIR"
|
|
55
|
+
echo ""
|
|
56
|
+
|
|
57
|
+
# Build CLI arguments exactly like spawner does
|
|
58
|
+
CLI_ARGS=()
|
|
59
|
+
|
|
60
|
+
# Add args based on CLI type
|
|
61
|
+
case $CLI in
|
|
62
|
+
claude)
|
|
63
|
+
# Claude: add --dangerously-skip-permissions in non-interactive mode
|
|
64
|
+
if [ -z "$INTERACTIVE" ]; then
|
|
65
|
+
CLI_ARGS+=(--dangerously-skip-permissions)
|
|
66
|
+
echo "[spawn] Adding --dangerously-skip-permissions (non-interactive mode)"
|
|
67
|
+
fi
|
|
68
|
+
;;
|
|
69
|
+
cursor)
|
|
70
|
+
# Cursor: add --force in non-interactive mode
|
|
71
|
+
if [ -z "$INTERACTIVE" ]; then
|
|
72
|
+
CLI_ARGS+=(--force)
|
|
73
|
+
echo "[spawn] Adding --force (non-interactive mode)"
|
|
74
|
+
fi
|
|
75
|
+
;;
|
|
76
|
+
codex)
|
|
77
|
+
# Codex: supports device flow for headless
|
|
78
|
+
if [ -z "$INTERACTIVE" ]; then
|
|
79
|
+
CLI_ARGS+=(login --device-auth)
|
|
80
|
+
echo "[spawn] Adding login --device-auth (non-interactive mode)"
|
|
81
|
+
fi
|
|
82
|
+
;;
|
|
83
|
+
copilot)
|
|
84
|
+
# Copilot: needs auth login command, device flow for headless
|
|
85
|
+
if [ -z "$INTERACTIVE" ]; then
|
|
86
|
+
CLI_ARGS+=(auth login --device)
|
|
87
|
+
echo "[spawn] Adding auth login --device (non-interactive mode)"
|
|
88
|
+
else
|
|
89
|
+
CLI_ARGS+=(auth login)
|
|
90
|
+
echo "[spawn] Adding auth login (interactive mode)"
|
|
91
|
+
fi
|
|
92
|
+
;;
|
|
93
|
+
opencode)
|
|
94
|
+
# OpenCode: needs auth login command
|
|
95
|
+
CLI_ARGS+=(auth login)
|
|
96
|
+
echo "[spawn] Adding auth login"
|
|
97
|
+
;;
|
|
98
|
+
droid)
|
|
99
|
+
# Droid: needs --login flag
|
|
100
|
+
CLI_ARGS+=(--login)
|
|
101
|
+
echo "[spawn] Adding --login"
|
|
102
|
+
;;
|
|
103
|
+
esac
|
|
104
|
+
|
|
105
|
+
echo ""
|
|
106
|
+
echo "Command: $CLI_CMD ${CLI_ARGS[*]}"
|
|
107
|
+
echo ""
|
|
108
|
+
|
|
109
|
+
# Build relay-pty args
|
|
110
|
+
RELAY_ARGS=(
|
|
111
|
+
--name "$NAME"
|
|
112
|
+
--socket "$SOCKET"
|
|
113
|
+
--idle-timeout 300
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Enable JSON output for debugging
|
|
117
|
+
if [ -n "$DEBUG_SPAWN" ] || [ -n "$DEBUG" ]; then
|
|
118
|
+
RELAY_ARGS+=(--json-output)
|
|
119
|
+
echo "[debug] JSON output enabled"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
echo "========================================"
|
|
123
|
+
echo " Starting CLI with relay-pty"
|
|
124
|
+
echo "========================================"
|
|
125
|
+
echo ""
|
|
126
|
+
echo "Press Ctrl+C to stop."
|
|
127
|
+
echo ""
|
|
128
|
+
echo "In another terminal, you can:"
|
|
129
|
+
echo " - Check socket status: echo '{\"type\":\"status\"}' | nc -U $SOCKET"
|
|
130
|
+
echo " - Inject message: echo '{\"type\":\"inject\",\"body\":\"test\"}' | nc -U $SOCKET"
|
|
131
|
+
echo " - Monitor registration: watch -n1 'cat $RELAY_DATA_DIR/*.json 2>/dev/null || echo no files'"
|
|
132
|
+
echo ""
|
|
133
|
+
|
|
134
|
+
# Start the CLI with relay-pty
|
|
135
|
+
# In a real spawn, this would be done via AgentSpawner which handles registration waiting
|
|
136
|
+
if [ ${#CLI_ARGS[@]} -gt 0 ]; then
|
|
137
|
+
exec relay-pty "${RELAY_ARGS[@]}" -- "$CLI_CMD" "${CLI_ARGS[@]}"
|
|
138
|
+
else
|
|
139
|
+
exec relay-pty "${RELAY_ARGS[@]}" -- "$CLI_CMD"
|
|
140
|
+
fi
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Full integration test with daemon
|
|
3
|
+
# This starts a local daemon and tests the complete spawn flow
|
|
4
|
+
#
|
|
5
|
+
# Usage: ./test-with-daemon.sh <cli>
|
|
6
|
+
# Example: ./test-with-daemon.sh cursor
|
|
7
|
+
# DEBUG=1 ./test-with-daemon.sh cursor
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
CLI=${1:-cursor}
|
|
12
|
+
|
|
13
|
+
# Map CLI name to actual command
|
|
14
|
+
CLI_CMD="$CLI"
|
|
15
|
+
if [ "$CLI" = "cursor" ]; then
|
|
16
|
+
CLI_CMD="agent"
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
NAME="daemon-test-${CLI}"
|
|
20
|
+
SOCKET="/tmp/relay-pty-${NAME}.sock"
|
|
21
|
+
|
|
22
|
+
# Daemon configuration
|
|
23
|
+
DAEMON_PORT=${DAEMON_PORT:-3377}
|
|
24
|
+
DAEMON_HOST="127.0.0.1"
|
|
25
|
+
DAEMON_URL="http://${DAEMON_HOST}:${DAEMON_PORT}"
|
|
26
|
+
DATA_DIR="/tmp/relay-daemon-test"
|
|
27
|
+
|
|
28
|
+
# Cleanup function
|
|
29
|
+
cleanup() {
|
|
30
|
+
echo ""
|
|
31
|
+
echo "========================================"
|
|
32
|
+
echo " Cleaning up"
|
|
33
|
+
echo "========================================"
|
|
34
|
+
rm -f "$SOCKET"
|
|
35
|
+
if [ -n "$DAEMON_PID" ]; then
|
|
36
|
+
echo "Stopping daemon (PID: $DAEMON_PID)..."
|
|
37
|
+
kill $DAEMON_PID 2>/dev/null || true
|
|
38
|
+
fi
|
|
39
|
+
if [ -n "$PTY_PID" ]; then
|
|
40
|
+
echo "Stopping relay-pty (PID: $PTY_PID)..."
|
|
41
|
+
kill $PTY_PID 2>/dev/null || true
|
|
42
|
+
fi
|
|
43
|
+
echo "Done."
|
|
44
|
+
}
|
|
45
|
+
trap cleanup EXIT
|
|
46
|
+
|
|
47
|
+
# Create data directory
|
|
48
|
+
mkdir -p "$DATA_DIR"
|
|
49
|
+
|
|
50
|
+
echo "========================================"
|
|
51
|
+
echo " Full Daemon Integration Test: $CLI"
|
|
52
|
+
echo "========================================"
|
|
53
|
+
echo ""
|
|
54
|
+
echo "This test starts a real daemon and tests the complete flow:"
|
|
55
|
+
echo " 1. Start relay-daemon"
|
|
56
|
+
echo " 2. Start relay-pty with CLI"
|
|
57
|
+
echo " 3. Wait for agent registration"
|
|
58
|
+
echo " 4. Monitor the full flow"
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Configuration:"
|
|
61
|
+
echo " CLI: $CLI_CMD"
|
|
62
|
+
echo " Agent name: $NAME"
|
|
63
|
+
echo " Daemon URL: $DAEMON_URL"
|
|
64
|
+
echo " Data dir: $DATA_DIR"
|
|
65
|
+
echo ""
|
|
66
|
+
|
|
67
|
+
# Check if daemon binary is available
|
|
68
|
+
if ! command -v relay-daemon &> /dev/null; then
|
|
69
|
+
echo "WARNING: relay-daemon not found in PATH"
|
|
70
|
+
echo ""
|
|
71
|
+
echo "To build the daemon:"
|
|
72
|
+
echo " cd packages/daemon && npm run build"
|
|
73
|
+
echo ""
|
|
74
|
+
echo "Or run a daemon manually:"
|
|
75
|
+
echo " npm run daemon"
|
|
76
|
+
echo ""
|
|
77
|
+
echo "Then re-run this test."
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
echo "========================================"
|
|
82
|
+
echo " Phase 1: Starting Daemon"
|
|
83
|
+
echo "========================================"
|
|
84
|
+
echo ""
|
|
85
|
+
|
|
86
|
+
# Check if a daemon is already running
|
|
87
|
+
if curl -s "${DAEMON_URL}/health" > /dev/null 2>&1; then
|
|
88
|
+
echo "Daemon already running at $DAEMON_URL"
|
|
89
|
+
DAEMON_PID=""
|
|
90
|
+
else
|
|
91
|
+
echo "Starting daemon on port $DAEMON_PORT..."
|
|
92
|
+
|
|
93
|
+
# Start daemon in background with test configuration
|
|
94
|
+
RELAY_DATA_DIR="$DATA_DIR" \
|
|
95
|
+
RELAY_PORT="$DAEMON_PORT" \
|
|
96
|
+
DEBUG="${DEBUG:-}" \
|
|
97
|
+
relay-daemon > "$DATA_DIR/daemon.log" 2>&1 &
|
|
98
|
+
|
|
99
|
+
DAEMON_PID=$!
|
|
100
|
+
echo "Daemon started (PID: $DAEMON_PID)"
|
|
101
|
+
|
|
102
|
+
# Wait for daemon to be ready
|
|
103
|
+
echo "Waiting for daemon to be ready..."
|
|
104
|
+
for i in $(seq 1 30); do
|
|
105
|
+
if curl -s "${DAEMON_URL}/health" > /dev/null 2>&1; then
|
|
106
|
+
echo "Daemon is ready!"
|
|
107
|
+
break
|
|
108
|
+
fi
|
|
109
|
+
if [ $i -eq 30 ]; then
|
|
110
|
+
echo "ERROR: Daemon failed to start within 30 seconds"
|
|
111
|
+
echo ""
|
|
112
|
+
echo "Daemon log:"
|
|
113
|
+
cat "$DATA_DIR/daemon.log" | tail -50
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
sleep 1
|
|
117
|
+
done
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
echo ""
|
|
121
|
+
|
|
122
|
+
echo "========================================"
|
|
123
|
+
echo " Phase 2: Starting CLI with relay-pty"
|
|
124
|
+
echo "========================================"
|
|
125
|
+
echo ""
|
|
126
|
+
|
|
127
|
+
# Build CLI arguments
|
|
128
|
+
CLI_ARGS=()
|
|
129
|
+
case $CLI in
|
|
130
|
+
claude)
|
|
131
|
+
CLI_ARGS+=(--dangerously-skip-permissions)
|
|
132
|
+
;;
|
|
133
|
+
cursor)
|
|
134
|
+
CLI_ARGS+=(--force)
|
|
135
|
+
;;
|
|
136
|
+
esac
|
|
137
|
+
|
|
138
|
+
echo "Command: $CLI_CMD ${CLI_ARGS[*]}"
|
|
139
|
+
|
|
140
|
+
# Build relay-pty args
|
|
141
|
+
RELAY_ARGS=(
|
|
142
|
+
--name "$NAME"
|
|
143
|
+
--socket "$SOCKET"
|
|
144
|
+
--idle-timeout 300
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Enable verbose output
|
|
148
|
+
if [ -n "$DEBUG" ]; then
|
|
149
|
+
RELAY_ARGS+=(--json-output)
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# Set daemon URL environment variable so relay-pty connects to our test daemon
|
|
153
|
+
export RELAY_DAEMON_URL="$DAEMON_URL"
|
|
154
|
+
|
|
155
|
+
echo "Starting relay-pty..."
|
|
156
|
+
if [ ${#CLI_ARGS[@]} -gt 0 ]; then
|
|
157
|
+
relay-pty "${RELAY_ARGS[@]}" -- "$CLI_CMD" "${CLI_ARGS[@]}" 2>&1 &
|
|
158
|
+
else
|
|
159
|
+
relay-pty "${RELAY_ARGS[@]}" -- "$CLI_CMD" 2>&1 &
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
PTY_PID=$!
|
|
163
|
+
echo "relay-pty started (PID: $PTY_PID)"
|
|
164
|
+
echo ""
|
|
165
|
+
|
|
166
|
+
echo "========================================"
|
|
167
|
+
echo " Phase 3: Monitoring Registration"
|
|
168
|
+
echo "========================================"
|
|
169
|
+
echo ""
|
|
170
|
+
|
|
171
|
+
# Poll for registration via daemon API
|
|
172
|
+
START_TIME=$(date +%s)
|
|
173
|
+
TIMEOUT_SEC=60
|
|
174
|
+
|
|
175
|
+
echo "Polling daemon for agent registration (timeout: ${TIMEOUT_SEC}s)..."
|
|
176
|
+
echo ""
|
|
177
|
+
|
|
178
|
+
while true; do
|
|
179
|
+
CURRENT_TIME=$(date +%s)
|
|
180
|
+
ELAPSED=$((CURRENT_TIME - START_TIME))
|
|
181
|
+
|
|
182
|
+
# Check if PTY process is still running
|
|
183
|
+
if ! kill -0 $PTY_PID 2>/dev/null; then
|
|
184
|
+
echo ""
|
|
185
|
+
echo "[$(date +%T)] ERROR: relay-pty exited after ${ELAPSED}s"
|
|
186
|
+
echo ""
|
|
187
|
+
echo "The CLI crashed or exited before completing registration."
|
|
188
|
+
echo ""
|
|
189
|
+
if [ -f "$DATA_DIR/daemon.log" ]; then
|
|
190
|
+
echo "Daemon log (last 20 lines):"
|
|
191
|
+
tail -20 "$DATA_DIR/daemon.log"
|
|
192
|
+
fi
|
|
193
|
+
exit 1
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
# Query daemon for connected agents
|
|
197
|
+
AGENTS=$(curl -s "${DAEMON_URL}/api/agents" 2>/dev/null || echo "[]")
|
|
198
|
+
|
|
199
|
+
# Check if our agent is registered
|
|
200
|
+
if echo "$AGENTS" | grep -q "\"$NAME\""; then
|
|
201
|
+
echo ""
|
|
202
|
+
echo "========================================"
|
|
203
|
+
echo " SUCCESS: Agent Registered!"
|
|
204
|
+
echo "========================================"
|
|
205
|
+
echo ""
|
|
206
|
+
echo "Agent '$NAME' successfully registered with daemon after ${ELAPSED}s"
|
|
207
|
+
echo ""
|
|
208
|
+
echo "Connected agents:"
|
|
209
|
+
echo "$AGENTS" | jq . 2>/dev/null || echo "$AGENTS"
|
|
210
|
+
echo ""
|
|
211
|
+
echo "Press Ctrl+C to stop the test, or leave running to interact with the CLI."
|
|
212
|
+
|
|
213
|
+
# Keep running so user can interact
|
|
214
|
+
wait $PTY_PID
|
|
215
|
+
exit 0
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
echo "[$(date +%T)] +${ELAPSED}s: Waiting for registration... (agents: $(echo "$AGENTS" | grep -o '"' | wc -l | xargs))"
|
|
219
|
+
|
|
220
|
+
# Check timeout
|
|
221
|
+
if [ $ELAPSED -ge $TIMEOUT_SEC ]; then
|
|
222
|
+
echo ""
|
|
223
|
+
echo "========================================"
|
|
224
|
+
echo " TIMEOUT: Registration Failed"
|
|
225
|
+
echo "========================================"
|
|
226
|
+
echo ""
|
|
227
|
+
echo "Agent '$NAME' did not register within ${TIMEOUT_SEC}s"
|
|
228
|
+
echo ""
|
|
229
|
+
echo "This is the same timeout the real spawner would hit."
|
|
230
|
+
echo ""
|
|
231
|
+
echo "Debugging info:"
|
|
232
|
+
echo ""
|
|
233
|
+
echo "1. Connected agents from daemon:"
|
|
234
|
+
echo "$AGENTS" | jq . 2>/dev/null || echo "$AGENTS"
|
|
235
|
+
echo ""
|
|
236
|
+
if [ -f "$DATA_DIR/daemon.log" ]; then
|
|
237
|
+
echo "2. Daemon log (last 30 lines):"
|
|
238
|
+
tail -30 "$DATA_DIR/daemon.log"
|
|
239
|
+
fi
|
|
240
|
+
echo ""
|
|
241
|
+
echo "3. Check if CLI is stuck on a prompt (auth, trust, etc.)"
|
|
242
|
+
echo ""
|
|
243
|
+
exit 1
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
sleep 2
|
|
247
|
+
done
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Verify CLI credentials exist and show (redacted) contents
|
|
3
|
+
# Usage: ./verify-auth.sh <cli>
|
|
4
|
+
# Example: ./verify-auth.sh claude
|
|
5
|
+
|
|
6
|
+
CLI=${1:-claude}
|
|
7
|
+
|
|
8
|
+
# Map CLI to credential file path
|
|
9
|
+
case $CLI in
|
|
10
|
+
claude)
|
|
11
|
+
CRED_FILE="$HOME/.claude/.credentials.json"
|
|
12
|
+
;;
|
|
13
|
+
codex)
|
|
14
|
+
CRED_FILE="$HOME/.codex/auth.json"
|
|
15
|
+
;;
|
|
16
|
+
gemini)
|
|
17
|
+
# Gemini stores in application_default_credentials.json
|
|
18
|
+
CRED_FILE="$HOME/.config/gcloud/application_default_credentials.json"
|
|
19
|
+
ALT_FILE="$HOME/.gemini/credentials.json"
|
|
20
|
+
;;
|
|
21
|
+
cursor|agent)
|
|
22
|
+
# Cursor CLI installs as 'agent', credentials in ~/.cursor/
|
|
23
|
+
CRED_FILE="$HOME/.cursor/auth.json"
|
|
24
|
+
CLI="cursor" # Normalize name
|
|
25
|
+
;;
|
|
26
|
+
opencode)
|
|
27
|
+
CRED_FILE="$HOME/.local/share/opencode/auth.json"
|
|
28
|
+
;;
|
|
29
|
+
droid)
|
|
30
|
+
CRED_FILE="$HOME/.droid/auth.json"
|
|
31
|
+
;;
|
|
32
|
+
copilot)
|
|
33
|
+
# GitHub Copilot uses gh CLI auth - stored in YAML format
|
|
34
|
+
CRED_FILE="$HOME/.config/gh/hosts.yml"
|
|
35
|
+
;;
|
|
36
|
+
*)
|
|
37
|
+
echo "Unknown CLI: $CLI"
|
|
38
|
+
echo "Supported: claude, codex, gemini, cursor, opencode, droid, copilot"
|
|
39
|
+
exit 1
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
echo "========================================"
|
|
44
|
+
echo " Checking credentials for: $CLI"
|
|
45
|
+
echo "========================================"
|
|
46
|
+
echo ""
|
|
47
|
+
|
|
48
|
+
# Check primary credential file
|
|
49
|
+
if [ -f "$CRED_FILE" ]; then
|
|
50
|
+
echo "✓ Credentials found: $CRED_FILE"
|
|
51
|
+
echo ""
|
|
52
|
+
echo "Contents (tokens redacted):"
|
|
53
|
+
echo "----------------------------------------"
|
|
54
|
+
# Redact any values that look like tokens (long strings, JWTs, etc.)
|
|
55
|
+
cat "$CRED_FILE" | jq '.' 2>/dev/null | \
|
|
56
|
+
sed -E 's/"([^"]*[Tt]oken[^"]*|[Aa]ccess[^"]*|[Rr]efresh[^"]*|[Ss]ecret[^"]*)": "[^"]{20,}"/"***\1***": "[REDACTED]"/g' || \
|
|
57
|
+
cat "$CRED_FILE" | sed -E 's/"[^"]{40,}"/"[REDACTED]"/g'
|
|
58
|
+
echo "----------------------------------------"
|
|
59
|
+
echo ""
|
|
60
|
+
|
|
61
|
+
# Check for specific fields
|
|
62
|
+
if command -v jq &> /dev/null && [ -f "$CRED_FILE" ]; then
|
|
63
|
+
echo "Token check:"
|
|
64
|
+
if jq -e '.claudeAiOauth.accessToken' "$CRED_FILE" &>/dev/null; then
|
|
65
|
+
echo " ✓ Access token present (Claude format)"
|
|
66
|
+
elif jq -e '.tokens.access_token' "$CRED_FILE" &>/dev/null; then
|
|
67
|
+
echo " ✓ Access token present (Codex format)"
|
|
68
|
+
elif jq -e '.accessToken' "$CRED_FILE" &>/dev/null; then
|
|
69
|
+
echo " ✓ Access token present (generic format)"
|
|
70
|
+
elif jq -e '.access_token' "$CRED_FILE" &>/dev/null; then
|
|
71
|
+
echo " ✓ Access token present (OAuth format)"
|
|
72
|
+
else
|
|
73
|
+
echo " ? Access token format unknown"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
if jq -e '.claudeAiOauth.refreshToken' "$CRED_FILE" &>/dev/null || \
|
|
77
|
+
jq -e '.tokens.refresh_token' "$CRED_FILE" &>/dev/null || \
|
|
78
|
+
jq -e '.refreshToken' "$CRED_FILE" &>/dev/null || \
|
|
79
|
+
jq -e '.refresh_token' "$CRED_FILE" &>/dev/null; then
|
|
80
|
+
echo " ✓ Refresh token present"
|
|
81
|
+
else
|
|
82
|
+
echo " ✗ No refresh token found"
|
|
83
|
+
fi
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
exit 0
|
|
87
|
+
else
|
|
88
|
+
echo "✗ No credentials found at: $CRED_FILE"
|
|
89
|
+
|
|
90
|
+
# Check alternate location for Gemini
|
|
91
|
+
if [ -n "$ALT_FILE" ] && [ -f "$ALT_FILE" ]; then
|
|
92
|
+
echo ""
|
|
93
|
+
echo "✓ Found alternate credentials: $ALT_FILE"
|
|
94
|
+
cat "$ALT_FILE" | jq '.' 2>/dev/null | \
|
|
95
|
+
sed -E 's/"[^"]{40,}"/"[REDACTED]"/g' || \
|
|
96
|
+
cat "$ALT_FILE"
|
|
97
|
+
exit 0
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Show what files exist in the CLI's config directory
|
|
101
|
+
CLI_DIR=$(dirname "$CRED_FILE")
|
|
102
|
+
if [ -d "$CLI_DIR" ]; then
|
|
103
|
+
echo ""
|
|
104
|
+
echo "Files in $CLI_DIR:"
|
|
105
|
+
ls -la "$CLI_DIR" 2>/dev/null || echo " (directory exists but is empty or unreadable)"
|
|
106
|
+
else
|
|
107
|
+
echo ""
|
|
108
|
+
echo "Config directory does not exist: $CLI_DIR"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
@@ -114,9 +114,11 @@ export async function runCLIAuthViaPTY(config, options = {}) {
|
|
|
114
114
|
}
|
|
115
115
|
}, delay);
|
|
116
116
|
}
|
|
117
|
-
// Look for auth URL
|
|
118
|
-
|
|
119
|
-
const
|
|
117
|
+
// Look for auth URL in accumulated output
|
|
118
|
+
// Join lines that look like URL continuations (handles wrapped URLs)
|
|
119
|
+
const cleanAccumulated = stripAnsiCodes(result.output)
|
|
120
|
+
.replace(/\n(?=[a-zA-Z0-9\-_.~:/?#\[\]@!$&'()*+,;=%])/g, '');
|
|
121
|
+
const match = cleanAccumulated.match(config.urlPattern);
|
|
120
122
|
if (match && match[1] && !result.authUrl) {
|
|
121
123
|
result.authUrl = match[1];
|
|
122
124
|
if (result.authUrl) {
|
|
@@ -134,9 +136,10 @@ export async function runCLIAuthViaPTY(config, options = {}) {
|
|
|
134
136
|
// Also check stderr for output (some CLIs write to stderr)
|
|
135
137
|
result.output += text;
|
|
136
138
|
options.onOutput?.(text);
|
|
137
|
-
// Check stderr for auth URLs too
|
|
138
|
-
const
|
|
139
|
-
|
|
139
|
+
// Check stderr for auth URLs too (using accumulated output)
|
|
140
|
+
const cleanAccumulated = stripAnsiCodes(result.output)
|
|
141
|
+
.replace(/\n(?=[a-zA-Z0-9\-_.~:/?#\[\]@!$&'()*+,;=%])/g, '');
|
|
142
|
+
const match = cleanAccumulated.match(config.urlPattern);
|
|
140
143
|
if (match && match[1] && !result.authUrl) {
|
|
141
144
|
result.authUrl = match[1];
|
|
142
145
|
if (result.authUrl) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/cloud",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
4
4
|
"description": "Cloud API server and services for Agent Relay",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"test:watch": "vitest"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@agent-relay/wrapper": "2.0.
|
|
42
|
-
"@agent-relay/config": "2.0.
|
|
43
|
-
"@agent-relay/resiliency": "2.0.
|
|
44
|
-
"@agent-relay/storage": "2.0.
|
|
45
|
-
"@agent-relay/protocol": "2.0.
|
|
41
|
+
"@agent-relay/wrapper": "2.0.20",
|
|
42
|
+
"@agent-relay/config": "2.0.20",
|
|
43
|
+
"@agent-relay/resiliency": "2.0.20",
|
|
44
|
+
"@agent-relay/storage": "2.0.20",
|
|
45
|
+
"@agent-relay/protocol": "2.0.20"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.19.3",
|
|
@@ -69,6 +69,16 @@ export const CLI_AUTH_CONFIG = {
|
|
|
69
69
|
delay: 300,
|
|
70
70
|
description: 'Ready to code permission prompt',
|
|
71
71
|
},
|
|
72
|
+
{
|
|
73
|
+
// Bypass Permissions mode prompt - for cloud workspaces running in sandboxed containers
|
|
74
|
+
// Shows "1. No, exit" (default selected) and "2. Yes, I accept"
|
|
75
|
+
// We need to select option 2 (down arrow) then confirm (enter)
|
|
76
|
+
// This is safe because cloud workspaces are sandboxed containers
|
|
77
|
+
pattern: /bypass\s*permissions\s*mode|will\s*not\s*ask\s*for\s*your\s*approval|sandboxed\s*container/i,
|
|
78
|
+
response: '\x1b[B\r', // Down arrow to select "Yes, I accept", then Enter
|
|
79
|
+
delay: 500, // Longer delay to ensure menu is fully rendered
|
|
80
|
+
description: 'Bypass permissions mode prompt',
|
|
81
|
+
},
|
|
72
82
|
{
|
|
73
83
|
// Fallback: Any "press enter" or "enter to confirm/continue" prompt
|
|
74
84
|
// Keep this LAST so more specific handlers match first
|
|
@@ -213,6 +223,15 @@ export const CLI_AUTH_CONFIG = {
|
|
|
213
223
|
displayName: 'Cursor',
|
|
214
224
|
waitTimeout: 30000,
|
|
215
225
|
prompts: [
|
|
226
|
+
{
|
|
227
|
+
// Initial login prompt - "Press any key to log in..."
|
|
228
|
+
// This is the FIRST prompt shown by Cursor Agent and blocks all progress
|
|
229
|
+
// Must send a keystroke to proceed to the auth URL
|
|
230
|
+
pattern: /press any key to log in/i,
|
|
231
|
+
response: '\r', // Send Enter to proceed
|
|
232
|
+
delay: 500,
|
|
233
|
+
description: 'Initial login prompt',
|
|
234
|
+
},
|
|
216
235
|
{
|
|
217
236
|
// Workspace Trust screen - must press 'a' to trust
|
|
218
237
|
// "Do you want to mark this workspace as trusted?"
|
|
@@ -261,6 +280,62 @@ export const CLI_AUTH_CONFIG = {
|
|
|
261
280
|
},
|
|
262
281
|
],
|
|
263
282
|
},
|
|
283
|
+
copilot: {
|
|
284
|
+
command: 'copilot',
|
|
285
|
+
args: ['auth', 'login'], // copilot auth login - triggers GitHub OAuth flow
|
|
286
|
+
deviceFlowArgs: ['auth', 'login', '--device'], // Device flow for headless environments
|
|
287
|
+
supportsDeviceFlow: true,
|
|
288
|
+
urlPattern: /(https:\/\/[^\s]+)/,
|
|
289
|
+
// Copilot uses gh CLI's auth - credentials stored via GitHub CLI config
|
|
290
|
+
credentialPath: '~/.config/gh/hosts.yml',
|
|
291
|
+
displayName: 'GitHub Copilot',
|
|
292
|
+
waitTimeout: 30000,
|
|
293
|
+
prompts: [
|
|
294
|
+
{
|
|
295
|
+
// Browser or device code selection
|
|
296
|
+
pattern: /login\s*with\s*a\s*code|one-time\s*code|device\s*code|browser|authenticate/i,
|
|
297
|
+
response: '\r', // Select first option (browser-based auth)
|
|
298
|
+
delay: 200,
|
|
299
|
+
description: 'Auth method selection',
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
// Press Enter to open browser
|
|
303
|
+
pattern: /press\s*enter\s*to\s*open|open.*browser|opening\s*browser/i,
|
|
304
|
+
response: '\r',
|
|
305
|
+
delay: 200,
|
|
306
|
+
description: 'Open browser prompt',
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
// Login success - press enter to continue
|
|
310
|
+
pattern: /login\s*successful|logged\s*in.*press\s*enter|press\s*enter\s*to\s*continue|authentication\s*complete/i,
|
|
311
|
+
response: '\r',
|
|
312
|
+
delay: 200,
|
|
313
|
+
description: 'Login success prompt',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
// Generic enter prompt (fallback)
|
|
317
|
+
pattern: /press\s*enter|enter\s*to\s*(confirm|continue|proceed)/i,
|
|
318
|
+
response: '\r',
|
|
319
|
+
delay: 300,
|
|
320
|
+
description: 'Generic enter prompt',
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
successPatterns: [/success/i, /authenticated/i, /logged\s*in/i, /you.*(?:are|now).*logged/i, /authentication\s*complete/i],
|
|
324
|
+
errorPatterns: [
|
|
325
|
+
{
|
|
326
|
+
pattern: /oauth\s*error|auth.*failed|authentication\s*error/i,
|
|
327
|
+
message: 'GitHub authentication failed',
|
|
328
|
+
recoverable: true,
|
|
329
|
+
hint: 'Please try logging in again. Make sure you have GitHub Copilot access.',
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
pattern: /network\s*error|ENOTFOUND|ECONNREFUSED|timeout/i,
|
|
333
|
+
message: 'Network error during authentication',
|
|
334
|
+
recoverable: true,
|
|
335
|
+
hint: 'Please check your internet connection and try again.',
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
},
|
|
264
339
|
};
|
|
265
340
|
/**
|
|
266
341
|
* Strip ANSI escape codes from text
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/config",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
4
4
|
"description": "Shared configuration schemas and loaders for Agent Relay",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"test:watch": "vitest"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@agent-relay/protocol": "2.0.
|
|
86
|
+
"@agent-relay/protocol": "2.0.20",
|
|
87
87
|
"zod": "^3.23.8",
|
|
88
88
|
"zod-to-json-schema": "^3.23.1"
|
|
89
89
|
},
|