* claude-companion: v1.3.0 — headless aggregator, user settings, sessions panel Catalog-side update for lowcache/claude-companion, from 1.0.1 to 1.3.0. Architecture: the pulse aggregator moved out of the bar widget into a headless [[service]] (pulse-svc.luau). Capture no longer depends on the bar dot being placed — the service starts with the shell and listens regardless of surfaces, retiring the plugin's old "pulse must sit on a bar" deployment invariant. The bar widget and desktop orb are now independent subscribers of the claude.pulse rollup, rendering only. Noctalia 5 beta also fixed the older limitation where bar widgets did not receive state.watch callbacks, so the bar dot is event-driven like the orb; both docs are updated accordingly. New: a `sessions` panel on right-click of the pulse (left-click still opens the answer panel) — one row per live session with state, model and token burn, plus a Retire control for a session whose SessionEnd hook never fired and which would otherwise sit at idle indefinitely. It introduces no new IPC verb: only the trailing `session` payload field is read for routing, so `session_end` with `,,,,,<sid>` is already a well-formed single-session retire. PROTOCOL.md now documents that property so any adapter can use it. Session ids are allowlisted before reaching a shell command. New: three animation settings (breath_speed, pulse_glow_floor, orb_swell), each declaring an explicit `step` — an omitted step defaults to 1.0 in the manifest parser, which collapses a fractional range to a couple of preset stops instead of a slider. plugin_api stays at 3. Everything used here is ungated at that level, and the contributing guidance is to raise it only when adopting a capability from a newer level. Verified against the installed build rather than assumed. Also ships tests/manifest_spec.py, which pins the settings contract: every numeric setting must declare an explicit step finer than its range, defaults must land on a step boundary, label/description must use the *_key form, and every key must resolve in translations/en.json. Neither the linter nor a widget spec can catch a bad step, which is how the slider bug shipped in the first place. Validated: catalog validator 54/54 exit 0, its own 54 self-tests pass, and the plugin's suite (5 luau + shim + manifest) is green. Live-tested on niri against Noctalia 5 beta; the compositor shim is unchanged in this update. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * claude-companion: tint the sessions retire control, fix singular header Follow-up on the v1.3.0 submission from live review: the retire button carried no variant and rendered at the background colour; a single session read "1 sessions". The panel root stays unfilled by design — noctalia panels are translucent under the glass style, so the backdrop is the shell's, not the plugin's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: lowcache <drawpdeadredd@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
44 lines
1.8 KiB
Bash
Executable File
44 lines
1.8 KiB
Bash
Executable File
#!/bin/sh
|
|
# pulse-emit — generic, agent-agnostic emitter for the pulse protocol.
|
|
# The whole contract lives in PROTOCOL.md; this is the reference adapter for
|
|
# any agent that can run a shell command on its lifecycle hooks (gemini-cli,
|
|
# codex, opencode, a CI job). Claude Code uses pulse.py instead (it enriches
|
|
# events with transcript-derived token telemetry; this one just relays args).
|
|
#
|
|
# pulse-emit <event> [session] [model] [in] [out] [cacheCreate] [cacheRead]
|
|
#
|
|
# With a session id the event carries the space-free CSV payload
|
|
# "model,in,out,cacheCreate,cacheRead,session" (omitted fields -> ?/0).
|
|
# Without one it sends a bare event, which lands in the widget's shared
|
|
# "default" test slot — fine for a poke, wrong for a real integration.
|
|
#
|
|
# Env: PULSE_TARGET plugin dispatch id (default lowcache/claude-companion:pulse-svc)
|
|
# PULSE_DRYRUN non-empty -> print the command instead of dispatching
|
|
#
|
|
# Fail-open by contract: exits 0 no matter what, output swallowed, dispatch
|
|
# capped at 3 s. A hook must never block or error the agent driving it.
|
|
|
|
TARGET="${PULSE_TARGET:-lowcache/claude-companion:pulse-svc}"
|
|
event="${1:-idle}"
|
|
session="$2"
|
|
|
|
# CSV fields must stay space- and comma-free (payload is one positional token).
|
|
clean() { printf '%s' "$1" | tr -cd 'A-Za-z0-9._?-'; }
|
|
|
|
payload=""
|
|
if [ -n "$session" ]; then
|
|
payload="$(clean "${3:-?}"),$(clean "${4:-0}"),$(clean "${5:-0}"),$(clean "${6:-0}"),$(clean "${7:-0}"),$(clean "$session")"
|
|
fi
|
|
|
|
if [ -n "$PULSE_DRYRUN" ]; then
|
|
echo "noctalia msg plugin $TARGET all $event${payload:+ $payload}"
|
|
exit 0
|
|
fi
|
|
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
timeout 3 noctalia msg plugin "$TARGET" all "$event" ${payload:+"$payload"} >/dev/null 2>&1
|
|
else
|
|
noctalia msg plugin "$TARGET" all "$event" ${payload:+"$payload"} >/dev/null 2>&1
|
|
fi
|
|
exit 0
|