@a5c-ai/babysitter-github 5.0.1-staging.b5c14f2a → 5.0.1-staging.c66885f8

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.
@@ -0,0 +1,116 @@
1
+ # Unified Session End Hook for GitHub Copilot CLI (PowerShell)
2
+ # Routes through hooks-proxy for all hook execution.
3
+ #
4
+ # Cleanup and logging on session exit.
5
+ #
6
+ # NOTE: Unlike Claude Code's Stop hook, sessionEnd output is IGNORED by
7
+ # Copilot CLI. This hook cannot block session exit or drive an orchestration
8
+ # loop. It is purely for cleanup and logging.
9
+
10
+ $ErrorActionPreference = "Continue"
11
+
12
+ $PluginRoot = if ($env:COPILOT_PLUGIN_DIR) { $env:COPILOT_PLUGIN_DIR } else { Split-Path -Parent $PSScriptRoot }
13
+ $ProxyMarkerFile = Join-Path $PluginRoot ".hooks-proxy-install-attempted"
14
+
15
+ $GlobalRoot = if ($env:BABYSITTER_GLOBAL_STATE_DIR) { $env:BABYSITTER_GLOBAL_STATE_DIR } else { Join-Path $HOME ".a5c" }
16
+ $LogDir = if ($env:BABYSITTER_LOG_DIR) { $env:BABYSITTER_LOG_DIR } else { Join-Path $GlobalRoot "logs" }
17
+ $LogFile = Join-Path $LogDir "babysitter-session-end-hook.log"
18
+ New-Item -ItemType Directory -Path $LogDir -Force -ErrorAction SilentlyContinue | Out-Null
19
+
20
+ function Write-Blog {
21
+ param([string]$Message)
22
+ $ts = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
23
+ Add-Content -Path $LogFile -Value "[INFO] $ts $Message" -ErrorAction SilentlyContinue
24
+ }
25
+
26
+ Write-Blog "Unified hook script invoked"
27
+ Write-Blog "PLUGIN_ROOT=$PluginRoot"
28
+
29
+ # Get required version from versions.json (used for hooks-proxy)
30
+ $versionsFile = Join-Path $PluginRoot "versions.json"
31
+ try {
32
+ $SdkVersion = (Get-Content $versionsFile -Raw | ConvertFrom-Json).sdkVersion
33
+ if (-not $SdkVersion) { $SdkVersion = "latest" }
34
+ } catch {
35
+ $SdkVersion = "latest"
36
+ }
37
+
38
+ # ---------------------------------------------------------------------------
39
+ # Hooks-proxy install (same pattern as SDK install in session-start)
40
+ # ---------------------------------------------------------------------------
41
+
42
+ function Install-HooksProxy {
43
+ param([string]$TargetVersion)
44
+ try {
45
+ & npm i -g "@a5c-ai/hooks-proxy-cli@$TargetVersion" --loglevel=error 2>$null
46
+ if ($LASTEXITCODE -eq 0) {
47
+ Write-Blog "Installed hooks-proxy globally ($TargetVersion)"
48
+ return $true
49
+ }
50
+ } catch {}
51
+ try {
52
+ $prefix = Join-Path $env:USERPROFILE ".local"
53
+ & npm i -g "@a5c-ai/hooks-proxy-cli@$TargetVersion" --prefix $prefix --loglevel=error 2>$null
54
+ if ($LASTEXITCODE -eq 0) {
55
+ $env:PATH = "$prefix\bin;$env:PATH"
56
+ Write-Blog "Installed hooks-proxy to user prefix ($TargetVersion)"
57
+ return $true
58
+ }
59
+ } catch {}
60
+ return $false
61
+ }
62
+
63
+ # Resolve hooks-proxy binary
64
+ $Proxy = $null
65
+ if (Get-Command a5c-hooks-proxy -ErrorAction SilentlyContinue) {
66
+ $Proxy = "a5c-hooks-proxy"
67
+ } else {
68
+ $localProxy = Join-Path $env:USERPROFILE ".local\bin\a5c-hooks-proxy.exe"
69
+ if (Test-Path $localProxy) {
70
+ $Proxy = $localProxy
71
+ }
72
+ }
73
+
74
+ # Install if not found (only attempt once per plugin version)
75
+ if (-not $Proxy -and -not (Test-Path $ProxyMarkerFile)) {
76
+ Write-Blog "hooks-proxy not found, attempting install"
77
+ Install-HooksProxy $SdkVersion | Out-Null
78
+ Set-Content -Path $ProxyMarkerFile -Value $SdkVersion -ErrorAction SilentlyContinue
79
+ if (Get-Command a5c-hooks-proxy -ErrorAction SilentlyContinue) {
80
+ $Proxy = "a5c-hooks-proxy"
81
+ } else {
82
+ $localProxy = Join-Path $env:USERPROFILE ".local\bin\a5c-hooks-proxy.exe"
83
+ if (Test-Path $localProxy) {
84
+ $Proxy = $localProxy
85
+ }
86
+ }
87
+ }
88
+
89
+ # ---------------------------------------------------------------------------
90
+ # Capture stdin and delegate to hooks-proxy
91
+ # ---------------------------------------------------------------------------
92
+
93
+ $InputFile = [System.IO.Path]::GetTempFileName()
94
+ $input | Out-File -FilePath $InputFile -Encoding utf8
95
+
96
+ Write-Blog "Hook input received"
97
+
98
+ $stderrLog = Join-Path $LogDir "babysitter-session-end-hook-stderr.log"
99
+
100
+ try {
101
+ if ($Proxy) {
102
+ Write-Blog "Using hooks-proxy: $Proxy"
103
+ Get-Content $InputFile | & $Proxy invoke --adapter copilot --handler "babysitter hook:run --harness unified --hook-type session-end --plugin-root $PluginRoot --json" --json 2>$stderrLog | Out-Null
104
+ } else {
105
+ Write-Blog "hooks-proxy not found after install, using npx fallback"
106
+ Get-Content $InputFile | & npx -y "@a5c-ai/hooks-proxy-cli@$SdkVersion" invoke --adapter copilot --handler "babysitter hook:run --harness unified --hook-type session-end --plugin-root $PluginRoot --json" --json 2>$stderrLog | Out-Null
107
+ }
108
+ } catch {
109
+ Write-Blog "Hook error: $_"
110
+ }
111
+
112
+ Write-Blog "Session end hook complete"
113
+
114
+ Remove-Item $InputFile -Force -ErrorAction SilentlyContinue
115
+
116
+ exit 0
@@ -0,0 +1,112 @@
1
+ #!/bin/bash
2
+ # Unified Session End Hook for GitHub Copilot CLI
3
+ # Routes through hooks-proxy for all hook execution.
4
+ #
5
+ # Cleanup and logging on session exit.
6
+ #
7
+ # NOTE: Unlike Claude Code's Stop hook, sessionEnd output is IGNORED by
8
+ # Copilot CLI. This hook cannot block session exit or drive an orchestration
9
+ # loop. It is purely for cleanup and logging.
10
+ #
11
+ # Protocol:
12
+ # Input: JSON via stdin (session context)
13
+ # Output: IGNORED by Copilot CLI
14
+ # Exit 0: success (exit code also ignored)
15
+
16
+ set -uo pipefail
17
+
18
+ PLUGIN_ROOT="${COPILOT_PLUGIN_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
19
+ PROXY_MARKER_FILE="${PLUGIN_ROOT}/.hooks-proxy-install-attempted"
20
+
21
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
22
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
23
+ LOG_FILE="$LOG_DIR/babysitter-session-end-hook.log"
24
+
25
+ mkdir -p "$LOG_DIR" 2>/dev/null
26
+
27
+ # Get required version from versions.json (used for hooks-proxy)
28
+ SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}" 2>/dev/null || echo "latest")
29
+
30
+ # Structured logging helper
31
+ blog() {
32
+ local msg="$1"
33
+ local ts
34
+ ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
35
+ echo "[INFO] $ts $msg" >> "$LOG_FILE" 2>/dev/null
36
+ if command -v babysitter &>/dev/null; then
37
+ babysitter log --type hook --label "hook:session-end" --message "$msg" --source shell-hook 2>/dev/null || true
38
+ fi
39
+ }
40
+
41
+ blog "Unified hook script invoked"
42
+ blog "PLUGIN_ROOT=$PLUGIN_ROOT"
43
+
44
+ # ---------------------------------------------------------------------------
45
+ # Hooks-proxy install (same pattern as SDK install in session-start)
46
+ # ---------------------------------------------------------------------------
47
+
48
+ install_hooks_proxy() {
49
+ local target_version="$1"
50
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --loglevel=error 2>/dev/null; then
51
+ blog "Installed hooks-proxy globally (${target_version})"
52
+ return 0
53
+ else
54
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
55
+ export PATH="$HOME/.local/bin:$PATH"
56
+ blog "Installed hooks-proxy to user prefix (${target_version})"
57
+ return 0
58
+ fi
59
+ fi
60
+ return 1
61
+ }
62
+
63
+ # Resolve hooks-proxy binary
64
+ PROXY=""
65
+ if command -v a5c-hooks-proxy &>/dev/null; then
66
+ PROXY="a5c-hooks-proxy"
67
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
68
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
69
+ fi
70
+
71
+ # Install if not found (only attempt once per plugin version)
72
+ if [ -z "$PROXY" ] && [ ! -f "$PROXY_MARKER_FILE" ]; then
73
+ blog "hooks-proxy not found, attempting install"
74
+ install_hooks_proxy "$SDK_VERSION"
75
+ echo "$SDK_VERSION" > "$PROXY_MARKER_FILE" 2>/dev/null
76
+ if command -v a5c-hooks-proxy &>/dev/null; then
77
+ PROXY="a5c-hooks-proxy"
78
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
79
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
80
+ fi
81
+ fi
82
+
83
+ # npx fallback if still not found
84
+ if [ -z "$PROXY" ]; then
85
+ blog "hooks-proxy not found after install, using npx fallback"
86
+ PROXY="npx -y @a5c-ai/hooks-proxy-cli@${SDK_VERSION} "
87
+ fi
88
+
89
+ # ---------------------------------------------------------------------------
90
+ # Capture stdin and delegate to hooks-proxy
91
+ # ---------------------------------------------------------------------------
92
+
93
+ INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/hook-session-end-$$.json")
94
+ cat > "$INPUT_FILE"
95
+
96
+ blog "Hook input received ($(wc -c < "$INPUT_FILE") bytes)"
97
+
98
+ STDERR_LOG="$LOG_DIR/babysitter-session-end-hook-stderr.log"
99
+
100
+ # Run cleanup/logging via hooks-proxy; output is ignored by Copilot CLI
101
+ blog "Using hooks-proxy: $PROXY"
102
+ $PROXY invoke \
103
+ --adapter copilot \
104
+ --handler "babysitter hook:run --harness unified --hook-type session-end --plugin-root ${PLUGIN_ROOT} --json" \
105
+ --json \
106
+ < "$INPUT_FILE" 2>"$STDERR_LOG" || true
107
+
108
+ blog "Session end hook complete"
109
+
110
+ rm -f "$INPUT_FILE" 2>/dev/null
111
+
112
+ exit 0
@@ -0,0 +1,189 @@
1
+ # Unified Session Start Hook for GitHub Copilot CLI (PowerShell)
2
+ # Routes through hooks-proxy for all hook execution.
3
+ #
4
+ # Ensures the babysitter SDK CLI and hooks-proxy are installed (from versions.json
5
+ # sdkVersion), then delegates to the TypeScript handler via hooks-proxy.
6
+ #
7
+ # Protocol:
8
+ # Input: JSON via stdin (contains session_id, cwd, etc.)
9
+ # Output: JSON via stdout ({} on success)
10
+ # Stderr: debug/log output only
11
+ # Exit 0: success
12
+ # Exit 2: block (fatal error)
13
+
14
+ $ErrorActionPreference = "Stop"
15
+
16
+ $PluginRoot = if ($env:COPILOT_PLUGIN_DIR) { $env:COPILOT_PLUGIN_DIR } else { Split-Path -Parent $PSScriptRoot }
17
+ $SdkMarkerFile = Join-Path $PluginRoot ".babysitter-install-attempted"
18
+ $ProxyMarkerFile = Join-Path $PluginRoot ".hooks-proxy-install-attempted"
19
+
20
+ $GlobalRoot = if ($env:BABYSITTER_GLOBAL_STATE_DIR) { $env:BABYSITTER_GLOBAL_STATE_DIR } else { Join-Path $HOME ".a5c" }
21
+ $LogDir = if ($env:BABYSITTER_LOG_DIR) { $env:BABYSITTER_LOG_DIR } else { Join-Path $GlobalRoot "logs" }
22
+ $LogFile = Join-Path $LogDir "babysitter-session-start-hook.log"
23
+ New-Item -ItemType Directory -Path $LogDir -Force -ErrorAction SilentlyContinue | Out-Null
24
+
25
+ function Write-Blog {
26
+ param([string]$Message)
27
+ $ts = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
28
+ Add-Content -Path $LogFile -Value "[INFO] $ts $Message" -ErrorAction SilentlyContinue
29
+ if (Get-Command babysitter -ErrorAction SilentlyContinue) {
30
+ & babysitter log --type hook --label "hook:session-start" --message $Message --source shell-hook 2>$null
31
+ }
32
+ }
33
+
34
+ Write-Blog "Unified hook script invoked"
35
+ Write-Blog "PLUGIN_ROOT=$PluginRoot"
36
+
37
+ # Get required SDK version from versions.json (used for both SDK and hooks-proxy)
38
+ $versionsFile = Join-Path $PluginRoot "versions.json"
39
+ try {
40
+ $SdkVersion = (Get-Content $versionsFile -Raw | ConvertFrom-Json).sdkVersion
41
+ if (-not $SdkVersion) { $SdkVersion = "latest" }
42
+ } catch {
43
+ $SdkVersion = "latest"
44
+ }
45
+
46
+ # ---------------------------------------------------------------------------
47
+ # SDK install/upgrade
48
+ # ---------------------------------------------------------------------------
49
+
50
+ function Install-Sdk {
51
+ param([string]$TargetVersion)
52
+ try {
53
+ & npm i -g "@a5c-ai/babysitter-sdk@$TargetVersion" --loglevel=error 2>$null
54
+ if ($LASTEXITCODE -eq 0) {
55
+ Write-Blog "Installed SDK globally ($TargetVersion)"
56
+ return $true
57
+ }
58
+ } catch {}
59
+ try {
60
+ $prefix = Join-Path $env:USERPROFILE ".local"
61
+ & npm i -g "@a5c-ai/babysitter-sdk@$TargetVersion" --prefix $prefix --loglevel=error 2>$null
62
+ if ($LASTEXITCODE -eq 0) {
63
+ $env:PATH = "$prefix\bin;$env:PATH"
64
+ Write-Blog "Installed SDK to user prefix ($TargetVersion)"
65
+ return $true
66
+ }
67
+ } catch {}
68
+ return $false
69
+ }
70
+
71
+ $NeedsSdkInstall = $false
72
+ if (Get-Command babysitter -ErrorAction SilentlyContinue) {
73
+ $CurrentVersion = & babysitter --version 2>$null
74
+ if ($CurrentVersion -ne $SdkVersion) {
75
+ Write-Blog "SDK version mismatch: installed=$CurrentVersion, required=$SdkVersion"
76
+ $NeedsSdkInstall = $true
77
+ } else {
78
+ Write-Blog "SDK version OK: $CurrentVersion"
79
+ }
80
+ } else {
81
+ Write-Blog "SDK CLI not found, will install"
82
+ $NeedsSdkInstall = $true
83
+ }
84
+
85
+ if ($NeedsSdkInstall -and -not (Test-Path $SdkMarkerFile)) {
86
+ Install-Sdk $SdkVersion | Out-Null
87
+ Set-Content -Path $SdkMarkerFile -Value $SdkVersion -ErrorAction SilentlyContinue
88
+ }
89
+
90
+ if (-not (Get-Command babysitter -ErrorAction SilentlyContinue)) {
91
+ Write-Blog "CLI not found after install, using npx fallback"
92
+ }
93
+
94
+ # ---------------------------------------------------------------------------
95
+ # Hooks-proxy install/upgrade (same pattern as SDK)
96
+ # ---------------------------------------------------------------------------
97
+
98
+ function Install-HooksProxy {
99
+ param([string]$TargetVersion)
100
+ try {
101
+ & npm i -g "@a5c-ai/hooks-proxy-cli@$TargetVersion" --loglevel=error 2>$null
102
+ if ($LASTEXITCODE -eq 0) {
103
+ Write-Blog "Installed hooks-proxy globally ($TargetVersion)"
104
+ return $true
105
+ }
106
+ } catch {}
107
+ try {
108
+ $prefix = Join-Path $env:USERPROFILE ".local"
109
+ & npm i -g "@a5c-ai/hooks-proxy-cli@$TargetVersion" --prefix $prefix --loglevel=error 2>$null
110
+ if ($LASTEXITCODE -eq 0) {
111
+ $env:PATH = "$prefix\bin;$env:PATH"
112
+ Write-Blog "Installed hooks-proxy to user prefix ($TargetVersion)"
113
+ return $true
114
+ }
115
+ } catch {}
116
+ return $false
117
+ }
118
+
119
+ $NeedsProxyInstall = $false
120
+ $Proxy = $null
121
+ if (Get-Command a5c-hooks-proxy -ErrorAction SilentlyContinue) {
122
+ $ProxyVersion = & a5c-hooks-proxy --version 2>$null
123
+ if ($ProxyVersion -ne $SdkVersion) {
124
+ Write-Blog "hooks-proxy version mismatch: installed=$ProxyVersion, required=$SdkVersion"
125
+ $NeedsProxyInstall = $true
126
+ } else {
127
+ Write-Blog "hooks-proxy version OK: $ProxyVersion"
128
+ $Proxy = "a5c-hooks-proxy"
129
+ }
130
+ } else {
131
+ $localProxy = Join-Path $env:USERPROFILE ".local\bin\a5c-hooks-proxy.exe"
132
+ if (Test-Path $localProxy) {
133
+ $ProxyVersion = & $localProxy --version 2>$null
134
+ if ($ProxyVersion -ne $SdkVersion) {
135
+ Write-Blog "hooks-proxy version mismatch: installed=$ProxyVersion, required=$SdkVersion"
136
+ $NeedsProxyInstall = $true
137
+ } else {
138
+ Write-Blog "hooks-proxy version OK: $ProxyVersion"
139
+ $Proxy = $localProxy
140
+ }
141
+ } else {
142
+ Write-Blog "hooks-proxy not found, will install"
143
+ $NeedsProxyInstall = $true
144
+ }
145
+ }
146
+
147
+ if ($NeedsProxyInstall -and -not (Test-Path $ProxyMarkerFile)) {
148
+ Install-HooksProxy $SdkVersion | Out-Null
149
+ Set-Content -Path $ProxyMarkerFile -Value $SdkVersion -ErrorAction SilentlyContinue
150
+ }
151
+
152
+ # Re-resolve after potential install
153
+ if (-not $Proxy) {
154
+ if (Get-Command a5c-hooks-proxy -ErrorAction SilentlyContinue) {
155
+ $Proxy = "a5c-hooks-proxy"
156
+ } else {
157
+ $localProxy = Join-Path $env:USERPROFILE ".local\bin\a5c-hooks-proxy.exe"
158
+ if (Test-Path $localProxy) {
159
+ $Proxy = $localProxy
160
+ }
161
+ }
162
+ }
163
+
164
+ # ---------------------------------------------------------------------------
165
+ # Capture stdin and delegate to hooks-proxy
166
+ # ---------------------------------------------------------------------------
167
+
168
+ $InputFile = [System.IO.Path]::GetTempFileName()
169
+ $input | Out-File -FilePath $InputFile -Encoding utf8
170
+
171
+ Write-Blog "Hook input received"
172
+
173
+ $stderrLog = Join-Path $LogDir "babysitter-session-start-hook-stderr.log"
174
+
175
+ if ($Proxy) {
176
+ Write-Blog "Using hooks-proxy: $Proxy"
177
+ $Result = Get-Content $InputFile | & $Proxy invoke --adapter copilot --handler "babysitter hook:run --harness unified --hook-type session-start --plugin-root $PluginRoot --json" --json 2>$stderrLog
178
+ $ExitCode = $LASTEXITCODE
179
+ } else {
180
+ Write-Blog "hooks-proxy not found after install, using npx fallback"
181
+ $Result = Get-Content $InputFile | & npx -y "@a5c-ai/hooks-proxy-cli@$SdkVersion" invoke --adapter copilot --handler "babysitter hook:run --harness unified --hook-type session-start --plugin-root $PluginRoot --json" --json 2>$stderrLog
182
+ $ExitCode = $LASTEXITCODE
183
+ }
184
+
185
+ Write-Blog "CLI exit code=$ExitCode"
186
+
187
+ Remove-Item $InputFile -Force -ErrorAction SilentlyContinue
188
+ Write-Output $Result
189
+ exit $ExitCode
@@ -0,0 +1,173 @@
1
+ #!/bin/bash
2
+ # Unified Session Start Hook for GitHub Copilot CLI
3
+ # Routes through hooks-proxy for all hook execution.
4
+ #
5
+ # Ensures the babysitter SDK CLI and hooks-proxy are installed (from versions.json
6
+ # sdkVersion), then delegates to the TypeScript handler via hooks-proxy.
7
+ #
8
+ # Protocol:
9
+ # Input: JSON via stdin (contains session_id, cwd, etc.)
10
+ # Output: JSON via stdout ({} on success)
11
+ # Stderr: debug/log output only
12
+ # Exit 0: success
13
+ # Exit 2: block (fatal error)
14
+
15
+ set -euo pipefail
16
+
17
+ PLUGIN_ROOT="${COPILOT_PLUGIN_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
18
+ SDK_MARKER_FILE="${PLUGIN_ROOT}/.babysitter-install-attempted"
19
+ PROXY_MARKER_FILE="${PLUGIN_ROOT}/.hooks-proxy-install-attempted"
20
+
21
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
22
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
23
+ LOG_FILE="$LOG_DIR/babysitter-session-start-hook.log"
24
+ mkdir -p "$LOG_DIR" 2>/dev/null
25
+
26
+ # Structured logging helper -- writes to both local and global log
27
+ blog() {
28
+ local msg="$1"
29
+ local ts
30
+ ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
31
+ echo "[INFO] $ts $msg" >> "$LOG_FILE" 2>/dev/null
32
+ # Use CLI structured logging when available; fall back to direct append
33
+ if command -v babysitter &>/dev/null; then
34
+ babysitter log --type hook --label "hook:session-start" --message "$msg" --source shell-hook 2>/dev/null || true
35
+ fi
36
+ }
37
+
38
+ blog "Unified hook script invoked"
39
+ blog "PLUGIN_ROOT=$PLUGIN_ROOT"
40
+
41
+ # Get required SDK version from versions.json (used for both SDK and hooks-proxy)
42
+ SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}" 2>/dev/null || echo "latest")
43
+
44
+ # ---------------------------------------------------------------------------
45
+ # SDK install/upgrade
46
+ # ---------------------------------------------------------------------------
47
+
48
+ install_sdk() {
49
+ local target_version="$1"
50
+ # Try global install first, fall back to user-local if permissions fail
51
+ if npm i -g "@a5c-ai/babysitter-sdk@${target_version}" --loglevel=error 2>/dev/null; then
52
+ blog "Installed SDK globally (${target_version})"
53
+ return 0
54
+ else
55
+ # Global install failed (permissions) -- try user-local prefix
56
+ if npm i -g "@a5c-ai/babysitter-sdk@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
57
+ export PATH="$HOME/.local/bin:$PATH"
58
+ blog "Installed SDK to user prefix (${target_version})"
59
+ return 0
60
+ fi
61
+ fi
62
+ return 1
63
+ }
64
+
65
+ NEEDS_SDK_INSTALL=false
66
+ if command -v babysitter &>/dev/null; then
67
+ CURRENT_VERSION=$(babysitter --version 2>/dev/null || echo "unknown")
68
+ if [ "$CURRENT_VERSION" != "$SDK_VERSION" ]; then
69
+ blog "SDK version mismatch: installed=${CURRENT_VERSION}, required=${SDK_VERSION}"
70
+ NEEDS_SDK_INSTALL=true
71
+ else
72
+ blog "SDK version OK: ${CURRENT_VERSION}"
73
+ fi
74
+ else
75
+ blog "SDK CLI not found, will install"
76
+ NEEDS_SDK_INSTALL=true
77
+ fi
78
+
79
+ if [ "$NEEDS_SDK_INSTALL" = true ] && [ ! -f "$SDK_MARKER_FILE" ]; then
80
+ install_sdk "$SDK_VERSION"
81
+ echo "$SDK_VERSION" > "$SDK_MARKER_FILE" 2>/dev/null
82
+ fi
83
+
84
+ if ! command -v babysitter &>/dev/null; then
85
+ blog "CLI not found after install, using npx fallback"
86
+ babysitter() { npx -y "@a5c-ai/babysitter-sdk@${SDK_VERSION}" "$@"; }
87
+ export -f babysitter
88
+ fi
89
+
90
+ # ---------------------------------------------------------------------------
91
+ # Hooks-proxy install/upgrade (same pattern as SDK)
92
+ # ---------------------------------------------------------------------------
93
+
94
+ install_hooks_proxy() {
95
+ local target_version="$1"
96
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --loglevel=error 2>/dev/null; then
97
+ blog "Installed hooks-proxy globally (${target_version})"
98
+ return 0
99
+ else
100
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
101
+ export PATH="$HOME/.local/bin:$PATH"
102
+ blog "Installed hooks-proxy to user prefix (${target_version})"
103
+ return 0
104
+ fi
105
+ fi
106
+ return 1
107
+ }
108
+
109
+ NEEDS_PROXY_INSTALL=false
110
+ if command -v a5c-hooks-proxy &>/dev/null; then
111
+ PROXY_VERSION=$(a5c-hooks-proxy --version 2>/dev/null || echo "unknown")
112
+ if [ "$PROXY_VERSION" != "$SDK_VERSION" ]; then
113
+ blog "hooks-proxy version mismatch: installed=${PROXY_VERSION}, required=${SDK_VERSION}"
114
+ NEEDS_PROXY_INSTALL=true
115
+ else
116
+ blog "hooks-proxy version OK: ${PROXY_VERSION}"
117
+ fi
118
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
119
+ export PATH="$HOME/.local/bin:$PATH"
120
+ PROXY_VERSION=$(a5c-hooks-proxy --version 2>/dev/null || echo "unknown")
121
+ if [ "$PROXY_VERSION" != "$SDK_VERSION" ]; then
122
+ blog "hooks-proxy version mismatch: installed=${PROXY_VERSION}, required=${SDK_VERSION}"
123
+ NEEDS_PROXY_INSTALL=true
124
+ else
125
+ blog "hooks-proxy version OK: ${PROXY_VERSION}"
126
+ fi
127
+ else
128
+ blog "hooks-proxy not found, will install"
129
+ NEEDS_PROXY_INSTALL=true
130
+ fi
131
+
132
+ if [ "$NEEDS_PROXY_INSTALL" = true ] && [ ! -f "$PROXY_MARKER_FILE" ]; then
133
+ install_hooks_proxy "$SDK_VERSION"
134
+ echo "$SDK_VERSION" > "$PROXY_MARKER_FILE" 2>/dev/null
135
+ fi
136
+
137
+ # Resolve hooks-proxy binary (npx fallback if still not found)
138
+ PROXY=""
139
+ if command -v a5c-hooks-proxy &>/dev/null; then
140
+ PROXY="a5c-hooks-proxy"
141
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
142
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
143
+ fi
144
+
145
+ if [ -z "$PROXY" ]; then
146
+ blog "hooks-proxy not found after install, using npx fallback"
147
+ PROXY="npx -y @a5c-ai/hooks-proxy-cli@${SDK_VERSION} "
148
+ fi
149
+
150
+ # ---------------------------------------------------------------------------
151
+ # Capture stdin and delegate to hooks-proxy
152
+ # ---------------------------------------------------------------------------
153
+
154
+ INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/hook-session-start-$$.json")
155
+ cat > "$INPUT_FILE"
156
+
157
+ blog "Hook input received ($(wc -c < "$INPUT_FILE") bytes)"
158
+
159
+ STDERR_LOG="$LOG_DIR/babysitter-session-start-hook-stderr.log"
160
+
161
+ blog "Using hooks-proxy: $PROXY"
162
+ RESULT=$($PROXY invoke \
163
+ --adapter copilot \
164
+ --handler "babysitter hook:run --harness unified --hook-type session-start --plugin-root ${PLUGIN_ROOT} --json" \
165
+ --json \
166
+ < "$INPUT_FILE" 2>"$STDERR_LOG")
167
+ EXIT_CODE=$?
168
+
169
+ blog "CLI exit code=$EXIT_CODE"
170
+
171
+ rm -f "$INPUT_FILE" 2>/dev/null
172
+ printf '%s\n' "$RESULT"
173
+ exit $EXIT_CODE
@@ -0,0 +1,92 @@
1
+ # Unified userPromptSubmitted Hook for GitHub Copilot CLI (PowerShell)
2
+ # Routes through hooks-proxy for all hook execution.
3
+ #
4
+ # Applies density-filter compression to long user prompts.
5
+ #
6
+ # NOTE: Output from this hook is IGNORED by Copilot CLI.
7
+ # This hook is for logging and side-effects only.
8
+
9
+ $ErrorActionPreference = "Continue"
10
+
11
+ $PluginRoot = if ($env:COPILOT_PLUGIN_DIR) { $env:COPILOT_PLUGIN_DIR } else { Split-Path -Parent $PSScriptRoot }
12
+ $ProxyMarkerFile = Join-Path $PluginRoot ".hooks-proxy-install-attempted"
13
+
14
+ $GlobalRoot = if ($env:BABYSITTER_GLOBAL_STATE_DIR) { $env:BABYSITTER_GLOBAL_STATE_DIR } else { Join-Path $HOME ".a5c" }
15
+ $LogDir = if ($env:BABYSITTER_LOG_DIR) { $env:BABYSITTER_LOG_DIR } else { Join-Path $GlobalRoot "logs" }
16
+ New-Item -ItemType Directory -Path $LogDir -Force -ErrorAction SilentlyContinue | Out-Null
17
+
18
+ # Get required version from versions.json (used for hooks-proxy)
19
+ $versionsFile = Join-Path $PluginRoot "versions.json"
20
+ try {
21
+ $SdkVersion = (Get-Content $versionsFile -Raw | ConvertFrom-Json).sdkVersion
22
+ if (-not $SdkVersion) { $SdkVersion = "latest" }
23
+ } catch {
24
+ $SdkVersion = "latest"
25
+ }
26
+
27
+ # ---------------------------------------------------------------------------
28
+ # Hooks-proxy install (same pattern as SDK install in session-start)
29
+ # ---------------------------------------------------------------------------
30
+
31
+ function Install-HooksProxy {
32
+ param([string]$TargetVersion)
33
+ try {
34
+ & npm i -g "@a5c-ai/hooks-proxy-cli@$TargetVersion" --loglevel=error 2>$null
35
+ if ($LASTEXITCODE -eq 0) { return $true }
36
+ } catch {}
37
+ try {
38
+ $prefix = Join-Path $env:USERPROFILE ".local"
39
+ & npm i -g "@a5c-ai/hooks-proxy-cli@$TargetVersion" --prefix $prefix --loglevel=error 2>$null
40
+ if ($LASTEXITCODE -eq 0) {
41
+ $env:PATH = "$prefix\bin;$env:PATH"
42
+ return $true
43
+ }
44
+ } catch {}
45
+ return $false
46
+ }
47
+
48
+ # Resolve hooks-proxy binary
49
+ $Proxy = $null
50
+ if (Get-Command a5c-hooks-proxy -ErrorAction SilentlyContinue) {
51
+ $Proxy = "a5c-hooks-proxy"
52
+ } else {
53
+ $localProxy = Join-Path $env:USERPROFILE ".local\bin\a5c-hooks-proxy.exe"
54
+ if (Test-Path $localProxy) {
55
+ $Proxy = $localProxy
56
+ }
57
+ }
58
+
59
+ # Install if not found (only attempt once per plugin version)
60
+ if (-not $Proxy -and -not (Test-Path $ProxyMarkerFile)) {
61
+ Install-HooksProxy $SdkVersion | Out-Null
62
+ Set-Content -Path $ProxyMarkerFile -Value $SdkVersion -ErrorAction SilentlyContinue
63
+ if (Get-Command a5c-hooks-proxy -ErrorAction SilentlyContinue) {
64
+ $Proxy = "a5c-hooks-proxy"
65
+ } else {
66
+ $localProxy = Join-Path $env:USERPROFILE ".local\bin\a5c-hooks-proxy.exe"
67
+ if (Test-Path $localProxy) {
68
+ $Proxy = $localProxy
69
+ }
70
+ }
71
+ }
72
+
73
+ # ---------------------------------------------------------------------------
74
+ # Capture stdin and delegate to hooks-proxy
75
+ # ---------------------------------------------------------------------------
76
+
77
+ $InputFile = [System.IO.Path]::GetTempFileName()
78
+ $input | Out-File -FilePath $InputFile -Encoding utf8
79
+
80
+ $stderrLog = Join-Path $LogDir "babysitter-user-prompt-submitted-hook-stderr.log"
81
+
82
+ try {
83
+ if ($Proxy) {
84
+ Get-Content $InputFile | & $Proxy invoke --adapter copilot --handler "babysitter hook:run --harness unified --hook-type user-prompt-submitted --json" --json 2>$stderrLog | Out-Null
85
+ } else {
86
+ Get-Content $InputFile | & npx -y "@a5c-ai/hooks-proxy-cli@$SdkVersion" invoke --adapter copilot --handler "babysitter hook:run --harness unified --hook-type user-prompt-submitted --json" --json 2>$stderrLog | Out-Null
87
+ }
88
+ } catch {}
89
+
90
+ Remove-Item $InputFile -Force -ErrorAction SilentlyContinue
91
+
92
+ exit 0
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+ # Unified userPromptSubmitted Hook for GitHub Copilot CLI
3
+ # Routes through hooks-proxy for all hook execution.
4
+ #
5
+ # Applies density-filter compression to long user prompts.
6
+ # Delegates to SDK CLI: babysitter hook:run --hook-type user-prompt-submitted
7
+ #
8
+ # NOTE: Output from this hook is IGNORED by Copilot CLI.
9
+ # This hook is for logging and side-effects only.
10
+
11
+ PLUGIN_ROOT="${COPILOT_PLUGIN_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
12
+ PROXY_MARKER_FILE="${PLUGIN_ROOT}/.hooks-proxy-install-attempted"
13
+
14
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
15
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
16
+ mkdir -p "$LOG_DIR" 2>/dev/null
17
+
18
+ # Get required version from versions.json (used for hooks-proxy)
19
+ SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}" 2>/dev/null || echo "latest")
20
+
21
+ # ---------------------------------------------------------------------------
22
+ # Hooks-proxy install (same pattern as SDK install in session-start)
23
+ # ---------------------------------------------------------------------------
24
+
25
+ install_hooks_proxy() {
26
+ local target_version="$1"
27
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --loglevel=error 2>/dev/null; then
28
+ return 0
29
+ else
30
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
31
+ export PATH="$HOME/.local/bin:$PATH"
32
+ return 0
33
+ fi
34
+ fi
35
+ return 1
36
+ }
37
+
38
+ # Resolve hooks-proxy binary
39
+ PROXY=""
40
+ if command -v a5c-hooks-proxy &>/dev/null; then
41
+ PROXY="a5c-hooks-proxy"
42
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
43
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
44
+ fi
45
+
46
+ # Install if not found (only attempt once per plugin version)
47
+ if [ -z "$PROXY" ] && [ ! -f "$PROXY_MARKER_FILE" ]; then
48
+ install_hooks_proxy "$SDK_VERSION"
49
+ echo "$SDK_VERSION" > "$PROXY_MARKER_FILE" 2>/dev/null
50
+ if command -v a5c-hooks-proxy &>/dev/null; then
51
+ PROXY="a5c-hooks-proxy"
52
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
53
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
54
+ fi
55
+ fi
56
+
57
+ # npx fallback if still not found
58
+ if [ -z "$PROXY" ]; then
59
+ PROXY="npx -y @a5c-ai/hooks-proxy-cli@${SDK_VERSION} "
60
+ fi
61
+
62
+ # ---------------------------------------------------------------------------
63
+ # Capture stdin and delegate to hooks-proxy
64
+ # ---------------------------------------------------------------------------
65
+
66
+ INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/hook-user-prompt-submitted-$$.json")
67
+ cat > "$INPUT_FILE"
68
+
69
+ if command -v babysitter &>/dev/null; then
70
+ babysitter log --type hook --label "hook:user-prompt-submitted" --message "Unified hook invoked" --source shell-hook 2>/dev/null || true
71
+ fi
72
+
73
+ STDERR_LOG="$LOG_DIR/babysitter-user-prompt-submitted-hook-stderr.log"
74
+
75
+ $PROXY invoke \
76
+ --adapter copilot \
77
+ --handler "babysitter hook:run --harness unified --hook-type user-prompt-submitted --json" \
78
+ --json \
79
+ < "$INPUT_FILE" 2>"$STDERR_LOG" || true
80
+
81
+ if command -v babysitter &>/dev/null; then
82
+ babysitter log --type hook --label "hook:user-prompt-submitted" --message "Hook complete" --source shell-hook 2>/dev/null || true
83
+ fi
84
+
85
+ rm -f "$INPUT_FILE" 2>/dev/null
86
+
87
+ exit 0
@@ -0,0 +1,29 @@
1
+ {
2
+ "_comment": "NOT ACTIVE — Alternative hook registration using per-hook unified scripts with hooks-proxy support. To activate, update the harness plugin configuration to reference these scripts.",
3
+ "hooks": {
4
+ "sessionStart": [
5
+ {
6
+ "type": "command",
7
+ "bash": "bash \"./hooks/babysitter-proxied-session-start.sh\"",
8
+ "powershell": "powershell -NoProfile -ExecutionPolicy Bypass -File \"./hooks/babysitter-proxied-session-start.ps1\"",
9
+ "timeoutSec": 30
10
+ }
11
+ ],
12
+ "sessionEnd": [
13
+ {
14
+ "type": "command",
15
+ "bash": "bash \"./hooks/babysitter-proxied-session-end.sh\"",
16
+ "powershell": "powershell -NoProfile -ExecutionPolicy Bypass -File \"./hooks/babysitter-proxied-session-end.ps1\"",
17
+ "timeoutSec": 30
18
+ }
19
+ ],
20
+ "userPromptSubmitted": [
21
+ {
22
+ "type": "command",
23
+ "bash": "bash \"./hooks/babysitter-proxied-user-prompt-submitted.sh\"",
24
+ "powershell": "powershell -NoProfile -ExecutionPolicy Bypass -File \"./hooks/babysitter-proxied-user-prompt-submitted.ps1\"",
25
+ "timeoutSec": 15
26
+ }
27
+ ]
28
+ }
29
+ }
package/hooks.json CHANGED
@@ -4,25 +4,25 @@
4
4
  "sessionStart": [
5
5
  {
6
6
  "type": "command",
7
- "bash": "./hooks/session-start.sh",
8
- "powershell": "./hooks/session-start.ps1",
7
+ "bash": "bash \"./hooks/babysitter-proxied-session-start.sh\"",
8
+ "powershell": "powershell -NoProfile -ExecutionPolicy Bypass -File \"./hooks/babysitter-proxied-session-start.ps1\"",
9
9
  "timeoutSec": 30
10
10
  }
11
11
  ],
12
12
  "sessionEnd": [
13
13
  {
14
14
  "type": "command",
15
- "bash": "./hooks/session-end.sh",
16
- "powershell": "./hooks/session-end.ps1",
15
+ "bash": "bash \"./hooks/babysitter-proxied-session-end.sh\"",
16
+ "powershell": "powershell -NoProfile -ExecutionPolicy Bypass -File \"./hooks/babysitter-proxied-session-end.ps1\"",
17
17
  "timeoutSec": 30
18
18
  }
19
19
  ],
20
20
  "userPromptSubmitted": [
21
21
  {
22
22
  "type": "command",
23
- "bash": "./hooks/user-prompt-submitted.sh",
24
- "powershell": "./hooks/user-prompt-submitted.ps1",
25
- "timeoutSec": 30
23
+ "bash": "bash \"./hooks/babysitter-proxied-user-prompt-submitted.sh\"",
24
+ "powershell": "powershell -NoProfile -ExecutionPolicy Bypass -File \"./hooks/babysitter-proxied-user-prompt-submitted.ps1\"",
25
+ "timeoutSec": 15
26
26
  }
27
27
  ]
28
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a5c-ai/babysitter-github",
3
- "version": "5.0.1-staging.b5c14f2a",
3
+ "version": "5.0.1-staging.c66885f8",
4
4
  "description": "Babysitter orchestration plugin for GitHub Copilot CLI with lifecycle hooks and SDK-managed process-library bootstrapping",
5
5
  "scripts": {
6
6
  "test": "node scripts/sync-command-surfaces.js --check && node test/cloud-agent-install.test.js",
@@ -45,6 +45,6 @@
45
45
  },
46
46
  "homepage": "https://github.com/a5c-ai/babysitter/tree/main/plugins/babysitter-github#readme",
47
47
  "dependencies": {
48
- "@a5c-ai/babysitter-sdk": "5.0.1-staging.b5c14f2a"
48
+ "@a5c-ai/babysitter-sdk": "5.0.1-staging.c66885f8"
49
49
  }
50
50
  }
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babysitter",
3
- "version": "5.0.1-staging.b5c14f2a",
3
+ "version": "5.0.1-staging.c66885f8",
4
4
  "description": "Orchestrate complex, multi-step workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop approval -- powered by the Babysitter SDK",
5
5
  "author": {
6
6
  "name": "a5c.ai",
package/versions.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "sdkVersion": "5.0.1-staging.b5c14f2a"
2
+ "sdkVersion": "5.0.1-staging.c66885f8"
3
3
  }