feat: session status at a glance, file & image drop, live Ops Alerts (0.4.0)
- devdesk-state-hook (Claude UserPromptSubmit/PostToolUse/Notification/Stop/ SessionStart/SessionEnd) records whether each session is working, waiting on you or idle; --list carries it. The sidebar shows it, the header shows the current session's state, and a pulsing "needs you" chip jumps to sessions waiting for input. Session refresh no longer depends on the sidebar being open. - `devdesk attach --upload SESSION FILE BYTES` receives a file as base64 terminal input (raw mode, exact length, size-checked, sanitised name) into /var/lib/devdesk/uploads/<session>/. The UI uploads dropped or pasted files and pastes the path into Claude, which attaches images itself. - `devdesk alerts` / `--alerts`: firing and pending Grafana alert rules with severity, instances, summary and a link. The panel's "Ask Claude" types an investigation prompt into the current session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -246,6 +246,55 @@ claude_args() {
|
||||
[ "$output" = "$DEVDESK_PROJECTS_ROOT/alpha/ops" ]
|
||||
}
|
||||
|
||||
@test "state hook tracks working, waiting and idle per session" {
|
||||
start_server
|
||||
devdesk new alpha
|
||||
pane=$(tmux -S "$DEVDESK_SOCKET" display -p -t =alpha:shell '#{pane_id}')
|
||||
hook() { TMUX="$DEVDESK_SOCKET,1,0" TMUX_PANE="$pane" "$REPO/libexec/devdesk-state-hook"; }
|
||||
state() { jq -r '.sessions[] | select(.name=="alpha") | .status.state // "none"' <<<"$(devdesk attach --list)"; }
|
||||
echo '{"hook_event_name":"UserPromptSubmit","prompt":"hi"}' | hook
|
||||
[ "$(state)" = working ]
|
||||
echo '{"hook_event_name":"Notification","message":"Claude needs your permission to use Bash"}' | hook
|
||||
[ "$(state)" = waiting ]
|
||||
[ "$(jq -r '.message' "$DEVDESK_STATE_DIR/state/alpha.json")" = "Claude needs your permission to use Bash" ]
|
||||
echo '{"hook_event_name":"PostToolUse","tool_name":"Bash"}' | hook
|
||||
[ "$(state)" = working ]
|
||||
echo '{"hook_event_name":"Stop"}' | hook
|
||||
[ "$(state)" = idle ]
|
||||
echo '{"hook_event_name":"PreCompact"}' | hook
|
||||
[ "$(state)" = idle ]
|
||||
devdesk rename alpha beta
|
||||
[ -f "$DEVDESK_STATE_DIR/state/beta.json" ] && [ ! -e "$DEVDESK_STATE_DIR/state/alpha.json" ]
|
||||
devdesk end beta
|
||||
[ ! -e "$DEVDESK_STATE_DIR/state/beta.json" ]
|
||||
}
|
||||
|
||||
@test "alerts reports unconfigured and unreachable Grafana cleanly" {
|
||||
run env DEVDESK_GRAFANA_URL= devdesk alerts
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(jq -r '.configured' <<<"$output")" = false ]
|
||||
run env DEVDESK_GRAFANA_URL=http://127.0.0.1:9 devdesk attach --alerts
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(jq -r '.configured' <<<"$output")" = true ]
|
||||
[ "$(jq -r '.error | length > 0' <<<"$output")" = true ]
|
||||
}
|
||||
|
||||
@test "upload stores the exact bytes under a sanitised name" {
|
||||
head -c 50001 /dev/urandom >"$TMP/in.bin"
|
||||
run bash -c "base64 -w0 '$TMP/in.bin' | devdesk attach --upload alpha '../../etc/My Shot (1).png' 50001"
|
||||
[ "$status" -eq 0 ]
|
||||
path=$(tail -n1 <<<"$output" | jq -r .path)
|
||||
[[ $path == "$DEVDESK_STATE_DIR/uploads/alpha/"*-My_Shot__1_.png ]]
|
||||
cmp "$TMP/in.bin" "$path"
|
||||
run bash -c "printf short | devdesk attach --upload alpha x.bin 100"
|
||||
[ "$status" -ne 0 ]
|
||||
[[ $output == *"upload incomplete"* ]]
|
||||
run devdesk attach --upload alpha x.bin 999999999999
|
||||
[ "$status" -ne 0 ]
|
||||
run devdesk attach --upload ../x x.bin 10
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "web actions run through attach and answer with JSON" {
|
||||
start_server
|
||||
run devdesk attach --new web1 alpha
|
||||
|
||||
Reference in New Issue
Block a user