- AssetCategory::Hooks + InstallFilter::Hooks (NAMES/parse/clap), reserving
the 'hooks' bundle name via the existing AssetCategory::parse check
- HookAssets embed + install_builtin_hooks(force): installs the bundled
example scripts 0755 into paths::hooks_dir() via write_file_atomic, wired
into install_builtins() and install_assets(); warns once when
COYOTE_HOOKS_DIR diverges from the config-dir default
- assets/hooks/notify.sh: notify-send -> osascript -> terminal fallback,
with AppleScript-literal sanitization of model-influenced values
- assets/hooks/log-events.sh: appends a COYOTE_* env snapshot (secrets
excluded, 0600 log, symlink-refusing) to ${COYOTE_HOOK_LOG:-/tmp/coyote-hooks.log}
- sbx-mixin discovery now scans roles/*.sbx-mixin.yaml and
roles/hooks/*.sbx-mixin.yaml (mirroring the role-hook cwd)
- tests: install+0755+force, install_assets(Hooks) end-to-end, discover()
roles scanning, reserved bundle name, no-ARGC-BUILD embed content, script
content order + real execution (secret exclusion, tty-less fallback),
CLI parser round-trips; hooks_dir env test made #[serial]
43 lines
1.8 KiB
Bash
Executable File
43 lines
1.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Desktop-notification hook: posts a notification describing the event that
|
|
# fired, falling back to a message on the controlling terminal when no
|
|
# notifier is present.
|
|
#
|
|
# Env vars read (set by coyote when the hook fires):
|
|
# COYOTE_EVENT dotted event name, e.g. turn.completed
|
|
# COYOTE_AGENT_NAME agent name, when the event carries one
|
|
# COYOTE_TOOL_NAME tool name, when the event carries one
|
|
#
|
|
# Wire it up under `hooks:` in your config.yaml:
|
|
# hooks:
|
|
# turn.completed:
|
|
# - name: notify
|
|
# command: ./hooks/notify.sh
|
|
#
|
|
# A relative command path like ./hooks/notify.sh resolves against the coyote
|
|
# config directory for global hooks, so this works with the default hooks dir.
|
|
#
|
|
# See https://github.com/Dark-Alex-17/coyote/wiki/Hooks for the full list of
|
|
# events and env vars. Hooks are fire-and-forget: this script never fails
|
|
# loudly, and coyote ignores its exit code either way.
|
|
|
|
set -u
|
|
|
|
title="coyote"
|
|
body="${COYOTE_EVENT:-event}"
|
|
[ -n "${COYOTE_AGENT_NAME:-}" ] && body="$body agent=$COYOTE_AGENT_NAME"
|
|
[ -n "${COYOTE_TOOL_NAME:-}" ] && body="$body tool=$COYOTE_TOOL_NAME"
|
|
|
|
if command -v notify-send > /dev/null 2>&1; then
|
|
notify-send "$title" "$body" 2> /dev/null || true
|
|
elif command -v osascript > /dev/null 2>&1; then
|
|
# $body carries model-influenced values (e.g. tool names); strip quotes and
|
|
# backslashes so it cannot escape the AppleScript string literal.
|
|
safe_body=${body//[\"\\]/}
|
|
osascript -e "display notification \"$safe_body\" with title \"$title\"" 2> /dev/null || true
|
|
else
|
|
# coyote discards hook stdout, so aim the fallback at the controlling
|
|
# terminal when one exists; plain stdout keeps direct/manual runs working.
|
|
{ echo "[$title] $body" > /dev/tty; } 2> /dev/null || echo "[$title] $body"
|
|
fi
|