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
|
@@ -87,6 +87,8 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
87
87
|
sessionStartTime = 0;
|
|
88
88
|
// Track if agent is being gracefully stopped (vs crashed)
|
|
89
89
|
isGracefulStop = false;
|
|
90
|
+
// Track early process exit for better error messages
|
|
91
|
+
earlyExitInfo;
|
|
90
92
|
// Memory/CPU monitoring
|
|
91
93
|
memoryMonitor;
|
|
92
94
|
memoryAlertHandler = null;
|
|
@@ -383,7 +385,13 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
383
385
|
throw new Error('relay-pty binary not found. Build with: cd relay-pty && cargo build --release');
|
|
384
386
|
}
|
|
385
387
|
this.log(` Using binary: ${binaryPath}`);
|
|
386
|
-
//
|
|
388
|
+
// Spawn relay-pty process FIRST (before connecting to daemon)
|
|
389
|
+
// This ensures the CLI is actually running before we register with the daemon
|
|
390
|
+
await this.spawnRelayPty(binaryPath);
|
|
391
|
+
// Wait for socket to become available and connect
|
|
392
|
+
await this.connectToSocket();
|
|
393
|
+
// Connect to relay daemon AFTER CLI is spawned
|
|
394
|
+
// This prevents the spawner from seeing us as "registered" before the CLI runs
|
|
387
395
|
try {
|
|
388
396
|
await this.client.connect();
|
|
389
397
|
this.log(` Relay daemon connected`);
|
|
@@ -391,10 +399,6 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
391
399
|
catch (err) {
|
|
392
400
|
this.logError(` Relay connect failed: ${err.message}`);
|
|
393
401
|
}
|
|
394
|
-
// Spawn relay-pty process
|
|
395
|
-
await this.spawnRelayPty(binaryPath);
|
|
396
|
-
// Wait for socket to become available and connect
|
|
397
|
-
await this.connectToSocket();
|
|
398
402
|
this.running = true;
|
|
399
403
|
// DON'T set readyForMessages yet - wait for CLI to be ready first
|
|
400
404
|
// This prevents messages from being injected during CLI startup
|
|
@@ -540,6 +544,8 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
540
544
|
...(this.config.args ?? []),
|
|
541
545
|
];
|
|
542
546
|
this.log(` Spawning: ${binaryPath} ${args.join(' ')}`);
|
|
547
|
+
// Reset early exit info from any previous spawn attempt
|
|
548
|
+
this.earlyExitInfo = undefined;
|
|
543
549
|
// For interactive mode, let Rust directly inherit stdin/stdout from the terminal
|
|
544
550
|
// This is more robust than manual forwarding through pipes
|
|
545
551
|
// We still pipe stderr to capture JSON parsed commands
|
|
@@ -566,10 +572,14 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
566
572
|
this.handleOutput(text);
|
|
567
573
|
});
|
|
568
574
|
}
|
|
575
|
+
// Capture stderr for early exit diagnosis
|
|
576
|
+
let stderrBuffer = '';
|
|
569
577
|
// Handle stderr (relay-pty logs and JSON output) - always needed
|
|
578
|
+
// Also captures to buffer for error diagnostics if process dies early
|
|
570
579
|
if (proc.stderr) {
|
|
571
580
|
proc.stderr.on('data', (data) => {
|
|
572
581
|
const text = data.toString();
|
|
582
|
+
stderrBuffer += text;
|
|
573
583
|
this.handleStderr(text);
|
|
574
584
|
});
|
|
575
585
|
}
|
|
@@ -577,6 +587,10 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
577
587
|
proc.on('exit', (code, signal) => {
|
|
578
588
|
const exitCode = code ?? (signal === 'SIGKILL' ? 137 : 1);
|
|
579
589
|
this.log(` Process exited: code=${exitCode} signal=${signal}`);
|
|
590
|
+
// Capture early exit info for better error messages if socket not yet connected
|
|
591
|
+
if (!this.socketConnected) {
|
|
592
|
+
this.earlyExitInfo = { code, signal, stderr: stderrBuffer };
|
|
593
|
+
}
|
|
580
594
|
this.running = false;
|
|
581
595
|
// Get crash context before unregistering from memory monitor
|
|
582
596
|
const crashContext = this.memoryMonitor.getCrashContext(this.config.name);
|
|
@@ -942,6 +956,22 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
942
956
|
// =========================================================================
|
|
943
957
|
// Socket communication
|
|
944
958
|
// =========================================================================
|
|
959
|
+
/**
|
|
960
|
+
* Check if the relay-pty process is still alive
|
|
961
|
+
*/
|
|
962
|
+
isProcessAlive() {
|
|
963
|
+
if (!this.relayPtyProcess || this.relayPtyProcess.exitCode !== null) {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
try {
|
|
967
|
+
// Signal 0 checks if process exists without killing it
|
|
968
|
+
process.kill(this.relayPtyProcess.pid, 0);
|
|
969
|
+
return true;
|
|
970
|
+
}
|
|
971
|
+
catch {
|
|
972
|
+
return false;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
945
975
|
/**
|
|
946
976
|
* Connect to the relay-pty socket
|
|
947
977
|
*/
|
|
@@ -949,6 +979,20 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
949
979
|
const timeout = this.config.socketConnectTimeoutMs ?? 5000;
|
|
950
980
|
const maxAttempts = this.config.socketReconnectAttempts ?? 3;
|
|
951
981
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
982
|
+
// Check if relay-pty process died before attempting connection
|
|
983
|
+
if (!this.isProcessAlive()) {
|
|
984
|
+
const exitInfo = this.earlyExitInfo;
|
|
985
|
+
if (exitInfo) {
|
|
986
|
+
const exitReason = exitInfo.signal
|
|
987
|
+
? `signal ${exitInfo.signal}`
|
|
988
|
+
: `code ${exitInfo.code ?? 'unknown'}`;
|
|
989
|
+
const stderrHint = exitInfo.stderr
|
|
990
|
+
? `\n stderr: ${exitInfo.stderr.trim().slice(0, 500)}`
|
|
991
|
+
: '';
|
|
992
|
+
throw new Error(`relay-pty process died early (${exitReason}).${stderrHint}`);
|
|
993
|
+
}
|
|
994
|
+
throw new Error('relay-pty process died before socket could be created');
|
|
995
|
+
}
|
|
952
996
|
try {
|
|
953
997
|
await this.attemptSocketConnection(timeout);
|
|
954
998
|
this.log(` Socket connected`);
|
|
@@ -961,6 +1005,17 @@ export class RelayPtyOrchestrator extends BaseWrapper {
|
|
|
961
1005
|
}
|
|
962
1006
|
}
|
|
963
1007
|
}
|
|
1008
|
+
// Final check for process death after all attempts
|
|
1009
|
+
if (!this.isProcessAlive() && this.earlyExitInfo) {
|
|
1010
|
+
const exitInfo = this.earlyExitInfo;
|
|
1011
|
+
const exitReason = exitInfo.signal
|
|
1012
|
+
? `signal ${exitInfo.signal}`
|
|
1013
|
+
: `code ${exitInfo.code ?? 'unknown'}`;
|
|
1014
|
+
const stderrHint = exitInfo.stderr
|
|
1015
|
+
? `\n stderr: ${exitInfo.stderr.trim().slice(0, 500)}`
|
|
1016
|
+
: '';
|
|
1017
|
+
throw new Error(`relay-pty process died during socket connection (${exitReason}).${stderrHint}`);
|
|
1018
|
+
}
|
|
964
1019
|
throw new Error(`Failed to connect to socket after ${maxAttempts} attempts`);
|
|
965
1020
|
}
|
|
966
1021
|
/**
|
|
@@ -805,6 +805,22 @@ export class TmuxWrapper extends BaseWrapper {
|
|
|
805
805
|
requires_ack: cmd.meta.ackRequired,
|
|
806
806
|
};
|
|
807
807
|
}
|
|
808
|
+
// Check if target is a channel (starts with #)
|
|
809
|
+
if (cmd.to.startsWith('#')) {
|
|
810
|
+
// Use CHANNEL_MESSAGE protocol for channel targets
|
|
811
|
+
this.logStderr(`→ [channel] ${cmd.to}: ${cmd.body.substring(0, Math.min(RELAY_LOG_TRUNCATE_LENGTH, cmd.body.length))}...`);
|
|
812
|
+
const success = this.client.sendChannelMessage(cmd.to, cmd.body, {
|
|
813
|
+
thread: cmd.thread,
|
|
814
|
+
data: cmd.data,
|
|
815
|
+
});
|
|
816
|
+
if (success) {
|
|
817
|
+
this.sentMessageHashes.add(msgHash);
|
|
818
|
+
this.queuedMessageHashes.delete(msgHash);
|
|
819
|
+
this.trajectory?.message('sent', this.config.name, cmd.to, cmd.body);
|
|
820
|
+
}
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
// Use SEND protocol for direct messages and broadcasts
|
|
808
824
|
if (cmd.sync?.blocking) {
|
|
809
825
|
this.client.sendAndWait(cmd.to, cmd.body, {
|
|
810
826
|
timeoutMs: cmd.sync.timeoutMs,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-relay/wrapper",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
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.
|
|
34
|
-
"@agent-relay/protocol": "2.0.
|
|
35
|
-
"@agent-relay/config": "2.0.
|
|
36
|
-
"@agent-relay/continuity": "2.0.
|
|
37
|
-
"@agent-relay/resiliency": "2.0.
|
|
33
|
+
"@agent-relay/api-types": "2.0.20",
|
|
34
|
+
"@agent-relay/protocol": "2.0.20",
|
|
35
|
+
"@agent-relay/config": "2.0.20",
|
|
36
|
+
"@agent-relay/continuity": "2.0.20",
|
|
37
|
+
"@agent-relay/resiliency": "2.0.20"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"typescript": "^5.9.3",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"url": "git+https://github.com/AgentWorkforce/relay.git",
|
|
60
60
|
"directory": "packages/wrapper"
|
|
61
61
|
},
|
|
62
|
-
"license": "
|
|
62
|
+
"license": "Apache-2.0"
|
|
63
63
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Install git hooks for agent-relay
|
|
3
|
+
# Usage: ./scripts/hooks/install.sh
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
7
|
+
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
|
8
|
+
|
|
9
|
+
echo "Installing git hooks..."
|
|
10
|
+
|
|
11
|
+
# Install pre-commit hook
|
|
12
|
+
cp "$SCRIPT_DIR/pre-commit" "$HOOKS_DIR/pre-commit"
|
|
13
|
+
chmod +x "$HOOKS_DIR/pre-commit"
|
|
14
|
+
echo " Installed pre-commit hook"
|
|
15
|
+
|
|
16
|
+
echo "Done! Git hooks installed."
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Pre-commit hook for agent-relay
|
|
3
|
+
# Handles Rust formatting and bd (beads) sync
|
|
4
|
+
#
|
|
5
|
+
# Install: cp scripts/hooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
|
|
6
|
+
# Or run: npm run hooks:install
|
|
7
|
+
|
|
8
|
+
# ============================================================
|
|
9
|
+
# Rust formatting (auto-format staged .rs files)
|
|
10
|
+
# ============================================================
|
|
11
|
+
RUST_STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.rs$' || true)
|
|
12
|
+
if [ -n "$RUST_STAGED" ]; then
|
|
13
|
+
if command -v rustfmt >/dev/null 2>&1; then
|
|
14
|
+
echo "Formatting Rust files..."
|
|
15
|
+
for file in $RUST_STAGED; do
|
|
16
|
+
if [ -f "$file" ]; then
|
|
17
|
+
rustfmt "$file" 2>/dev/null || true
|
|
18
|
+
git add "$file"
|
|
19
|
+
fi
|
|
20
|
+
done
|
|
21
|
+
else
|
|
22
|
+
echo "Warning: rustfmt not found, skipping Rust formatting" >&2
|
|
23
|
+
echo "Install with: rustup component add rustfmt" >&2
|
|
24
|
+
fi
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# ============================================================
|
|
28
|
+
# bd (beads) sync - flush pending changes before commit
|
|
29
|
+
# ============================================================
|
|
30
|
+
# Check if bd is available
|
|
31
|
+
if ! command -v bd >/dev/null 2>&1; then
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Check if we're in a bd workspace
|
|
36
|
+
if [ ! -d .beads ]; then
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Check if sync-branch is configured (if so, .beads goes to separate branch)
|
|
41
|
+
SYNC_BRANCH="${BEADS_SYNC_BRANCH:-}"
|
|
42
|
+
if [ -z "$SYNC_BRANCH" ] && [ -f .beads/config.yaml ]; then
|
|
43
|
+
SYNC_BRANCH=$(grep -E '^sync-branch:' .beads/config.yaml 2>/dev/null | head -1 | sed 's/^sync-branch:[[:space:]]*//' | sed 's/^["'"'"']//' | sed 's/["'"'"']$//')
|
|
44
|
+
fi
|
|
45
|
+
if [ -n "$SYNC_BRANCH" ]; then
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Flush pending changes
|
|
50
|
+
if ! bd sync --flush-only >/dev/null 2>&1; then
|
|
51
|
+
echo "Error: Failed to flush bd changes" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Stage JSONL files
|
|
56
|
+
for f in .beads/beads.jsonl .beads/issues.jsonl .beads/deletions.jsonl; do
|
|
57
|
+
[ -f "$f" ] && git add "$f" 2>/dev/null || true
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
exit 0
|
package/scripts/postinstall.js
CHANGED
|
@@ -73,6 +73,36 @@ function getRelayPtyBinaryName() {
|
|
|
73
73
|
return `relay-pty-${targetPlatform}-${targetArch}`;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Re-sign a binary with ad-hoc signature on macOS.
|
|
78
|
+
* This is required because macOS code signature validation can fail
|
|
79
|
+
* when binaries are copied/downloaded, causing SIGKILL on execution.
|
|
80
|
+
*
|
|
81
|
+
* The codesign tool is always available on macOS (part of the system).
|
|
82
|
+
* This is a common solution for npm packages distributing native binaries.
|
|
83
|
+
* Similar approach is used by esbuild, swc, and other Rust/Go tools.
|
|
84
|
+
*
|
|
85
|
+
* @param {string} binaryPath - Path to the binary to sign
|
|
86
|
+
* @returns {boolean} - Whether signing succeeded
|
|
87
|
+
*/
|
|
88
|
+
function resignBinaryForMacOS(binaryPath) {
|
|
89
|
+
if (os.platform() !== 'darwin') {
|
|
90
|
+
return true; // Only needed on macOS
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
// codesign is always available on macOS as a system utility
|
|
95
|
+
execSync(`codesign --force --sign - "${binaryPath}"`, { stdio: 'pipe' });
|
|
96
|
+
return true;
|
|
97
|
+
} catch (err) {
|
|
98
|
+
// This shouldn't happen on a normal macOS system, but handle gracefully
|
|
99
|
+
warn(`Failed to re-sign binary: ${err.message}`);
|
|
100
|
+
warn('The binary may fail to execute due to code signature issues.');
|
|
101
|
+
warn('You can manually fix this by running: codesign --force --sign - ' + binaryPath);
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
76
106
|
/**
|
|
77
107
|
* Install the relay-pty binary for the current platform
|
|
78
108
|
*/
|
|
@@ -103,6 +133,9 @@ function installRelayPtyBinary() {
|
|
|
103
133
|
const sourceStats = fs.statSync(sourcePath);
|
|
104
134
|
const targetStats = fs.statSync(targetPath);
|
|
105
135
|
if (sourceStats.size === targetStats.size) {
|
|
136
|
+
// Re-sign even if already installed to ensure signature is valid
|
|
137
|
+
// This fixes issues where previous installs have invalid signatures
|
|
138
|
+
resignBinaryForMacOS(targetPath);
|
|
106
139
|
info('relay-pty binary already installed');
|
|
107
140
|
return true;
|
|
108
141
|
}
|
|
@@ -115,7 +148,14 @@ function installRelayPtyBinary() {
|
|
|
115
148
|
try {
|
|
116
149
|
fs.copyFileSync(sourcePath, targetPath);
|
|
117
150
|
fs.chmodSync(targetPath, 0o755);
|
|
118
|
-
|
|
151
|
+
|
|
152
|
+
// Re-sign the binary on macOS to prevent code signature validation failures
|
|
153
|
+
// Without this, macOS may SIGKILL the process immediately on execution
|
|
154
|
+
if (resignBinaryForMacOS(targetPath)) {
|
|
155
|
+
success(`Installed relay-pty binary for ${os.platform()}-${os.arch()}`);
|
|
156
|
+
} else {
|
|
157
|
+
warn(`Installed relay-pty binary but signing failed - may not work on macOS`);
|
|
158
|
+
}
|
|
119
159
|
return true;
|
|
120
160
|
} catch (err) {
|
|
121
161
|
warn(`Failed to install relay-pty binary: ${err.message}`);
|