aboutsummaryrefslogtreecommitdiff
path: root/src/integration/assets/copilot/herdr-agent-state.ps1
blob: 61cec0c9fac15d2deb3fee6a08c992910407eecf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# installed by herdr
# managed by herdr; reinstalling or updating the integration overwrites this file.
# add custom hooks beside this file instead of editing it.
# HERDR_INTEGRATION_ID=copilot
# HERDR_INTEGRATION_VERSION=1

if ($env:HERDR_ENV -ne "1") { exit 0 }
if ([string]::IsNullOrWhiteSpace($env:HERDR_PANE_ID)) { exit 0 }

$inputText = [Console]::In.ReadToEnd()
try {
    $payload = if ([string]::IsNullOrWhiteSpace($inputText)) { @{} } else { $inputText | ConvertFrom-Json }
} catch {
    $payload = @{}
}

function First-Text {
    param([object[]]$Names)
    foreach ($name in $Names) {
        $value = $payload.$name
        if ($value -is [string] -and -not [string]::IsNullOrWhiteSpace($value)) {
            return $value
        }
    }
    return $null
}

function Normalize-Event {
    param([string]$Event)
    if ([string]::IsNullOrWhiteSpace($Event)) { return "" }
    return $Event.Replace("_", "").Replace("-", "").ToLowerInvariant()
}

function Infer-Event {
    $explicit = First-Text @("hook_event_name", "hookEventName")
    if ($explicit) { return $explicit }
    if (First-Text @("notification_type", "notificationType")) { return "notification" }
    if ($payload.PSObject.Properties.Name -contains "toolResult" -or $payload.PSObject.Properties.Name -contains "tool_result") { return "postToolUse" }
    if (($payload.PSObject.Properties.Name -contains "error") -and (First-Text @("tool_name", "toolName"))) { return "postToolUseFailure" }
    if (First-Text @("tool_name", "toolName")) { return "preToolUse" }
    if (First-Text @("stop_reason", "stopReason")) { return "agentStop" }
    if (First-Text @("reason")) { return "sessionEnd" }
    if ($payload.PSObject.Properties.Name -contains "prompt") { return "userPromptSubmitted" }
    if (
        $payload.PSObject.Properties.Name -contains "initial_prompt" -or
        $payload.PSObject.Properties.Name -contains "initialPrompt" -or
        $payload.PSObject.Properties.Name -contains "source" -or
        (First-Text @("session_id", "sessionId"))
    ) { return "sessionStart" }
    return ""
}

function Has-Initial-Prompt {
    $value = $payload.initial_prompt
    if ($null -eq $value) { $value = $payload.initialPrompt }
    return ($value -is [string] -and -not [string]::IsNullOrWhiteSpace($value))
}

function Report-State {
    param([string]$State, [string]$SessionId)
    $seq = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
    $args = @("pane", "report-agent", $env:HERDR_PANE_ID, "--source", "herdr:copilot", "--agent", "copilot", "--state", $State, "--seq", "$seq")
    if (-not [string]::IsNullOrWhiteSpace($SessionId)) {
        $args += @("--agent-session-id", $SessionId)
    }
    & herdr @args 2>$null | Out-Null
}

function Release-Agent {
    $seq = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
    & herdr pane release-agent $env:HERDR_PANE_ID --source herdr:copilot --agent copilot --seq $seq 2>$null | Out-Null
}

try {
    $eventKey = Normalize-Event (Infer-Event)
    $sessionId = First-Text @("session_id", "sessionId")
    $toolName = First-Text @("tool_name", "toolName")
    $notificationType = First-Text @("notification_type", "notificationType")
    $stopReason = First-Text @("stop_reason", "stopReason")
    $reason = First-Text @("reason")

    if ($eventKey -eq "sessionstart") {
        Report-State ($(if (Has-Initial-Prompt) { "working" } else { "idle" })) $sessionId
    } elseif ($eventKey -in @("userpromptsubmit", "userpromptsubmitted")) {
        Report-State "working" $sessionId
    } elseif ($eventKey -eq "pretooluse") {
        Report-State ($(if ($toolName -in @("ask_user", "exit_plan_mode")) { "blocked" } else { "working" })) $sessionId
    } elseif ($eventKey -in @("posttooluse", "posttoolusefailure")) {
        if ($toolName -ne "report_intent") { Report-State "working" $sessionId }
    } elseif ($eventKey -eq "notification") {
        if ($notificationType -in @("permission_prompt", "elicitation_dialog")) {
            Report-State "blocked" $sessionId
        } elseif ($notificationType -eq "agent_idle") {
            Report-State "idle" $sessionId
        }
    } elseif ($eventKey -in @("stop", "agentstop", "sessionstop")) {
        if ([string]::IsNullOrWhiteSpace($stopReason) -or $stopReason -eq "end_turn") {
            Report-State "idle" $sessionId
        }
    } elseif ($eventKey -eq "sessionend") {
        if ($reason -in @("user_exit", "abort")) { Release-Agent }
    }
} catch {
}