feat: v0.5.0 header, switcher, phone key bar, shared polling, Matrix "needs you"
- Header: no SSO chip ("Sign in again" only on expiry), state dot on the
session chip, LIVE as a dot, ⋯ menu for text size/notifications/fullscreen,
Panels badge for waiting sessions and alerts.
- Session switcher on the chip; bare URL reattaches the last session; + New
opens the panel form with project folders.
- Notifications when other sessions start waiting; alerts polled with the
panels closed; one tab polls for all tabs over BroadcastChannel.
- Sidebar: context bar per session instead of the Context panel; compact
Repo/CI with "Ask Claude to fix CI"; legible labels.
- Phone: key bar, drawer with backdrop, visualViewport-aware layout, DOM
renderer on touch, compact connection dot.
- devdesk-notify-matrix: one Matrix message per wait that lasts
DEVDESK_MATRIX_DELAY seconds with nobody attached.
Closes #8
Closes #13
Closes #14
Closes #15
Closes #16
Closes #17
Closes #28
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ setup() {
|
||||
export DEVDESK_LIBEXEC="$REPO/libexec"
|
||||
export DEVDESK_SHARE="$REPO/share"
|
||||
export DEVDESK_NO_SYSTEMD=1
|
||||
export DEVDESK_MATRIX_WEBHOOK_FILE="$TMP/no-webhook" # never the real room
|
||||
export FAKE_LOG="$TMP/claude-args"
|
||||
export CLAUDE_BIN="$TMP/fake-claude"
|
||||
export PATH="$REPO/bin:$PATH"
|
||||
@@ -269,6 +270,63 @@ claude_args() {
|
||||
[ ! -e "$DEVDESK_STATE_DIR/state/beta.json" ]
|
||||
}
|
||||
|
||||
# Local stand-in for the hookshot webhook: appends each POST body to $TMP/posts.
|
||||
start_receiver() {
|
||||
python3 - "$TMP" <<'PY' &
|
||||
import http.server, sys
|
||||
tmp = sys.argv[1]
|
||||
class H(http.server.BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
body = self.rfile.read(int(self.headers['Content-Length']))
|
||||
with open(f'{tmp}/posts', 'ab') as f:
|
||||
f.write(body + b'\n')
|
||||
self.send_response(200); self.end_headers(); self.wfile.write(b'{"ok":true}')
|
||||
def log_message(self, *a):
|
||||
pass
|
||||
srv = http.server.HTTPServer(('127.0.0.1', 0), H)
|
||||
open(f'{tmp}/port', 'w').write(str(srv.server_port))
|
||||
srv.serve_forever()
|
||||
PY
|
||||
RECEIVER=$!
|
||||
for _ in $(seq 1 50); do [ -s "$TMP/port" ] && break; sleep 0.1; done
|
||||
printf 'http://127.0.0.1:%s/webhook/test\n' "$(cat "$TMP/port")" >"$TMP/webhook"
|
||||
chmod 600 "$TMP/webhook"
|
||||
export DEVDESK_MATRIX_WEBHOOK_FILE="$TMP/webhook"
|
||||
}
|
||||
|
||||
posts() { [ -f "$TMP/posts" ] && wc -l <"$TMP/posts" || echo 0; }
|
||||
|
||||
@test "a wait nobody is attached to is posted to Matrix once (#28)" {
|
||||
start_server
|
||||
start_receiver
|
||||
export DEVDESK_MATRIX_DELAY=1 DEVDESK_PUBLIC_URL=https://dev.example.org
|
||||
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"; }
|
||||
|
||||
echo '{"hook_event_name":"Notification","message":"Claude needs your permission to use Bash"}' | hook
|
||||
# a second notification in the same wait: no second message
|
||||
echo '{"hook_event_name":"Notification","message":"Claude is waiting for your input"}' | hook
|
||||
sleep 2.5
|
||||
[ "$(posts)" -eq 1 ]
|
||||
run jq -r '[.session, .url, (.text | test("Claude needs you in alpha"))] | @tsv' "$TMP/posts"
|
||||
[ "$output" = "$(printf 'alpha\thttps://dev.example.org/?arg=alpha\ttrue')" ]
|
||||
|
||||
# answered within the delay: nothing is posted
|
||||
echo '{"hook_event_name":"PostToolUse"}' | hook
|
||||
echo '{"hook_event_name":"Notification","message":"Claude needs your permission to use Edit"}' | hook
|
||||
echo '{"hook_event_name":"PostToolUse"}' | hook
|
||||
sleep 2
|
||||
[ "$(posts)" -eq 1 ]
|
||||
|
||||
# no webhook file: feature off
|
||||
rm "$TMP/webhook"
|
||||
echo '{"hook_event_name":"Notification","message":"again"}' | hook
|
||||
sleep 2
|
||||
[ "$(posts)" -eq 1 ]
|
||||
kill "$RECEIVER"
|
||||
}
|
||||
|
||||
@test "alerts reports unconfigured and unreachable Grafana cleanly" {
|
||||
run env DEVDESK_GRAFANA_URL= devdesk alerts
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
Reference in New Issue
Block a user