mirror of
https://github.com/cursor/plugins.git
synced 2026-09-14 20:00:00 +08:00
659a6363c0
Adds an Advisor plugin: the main model consults a stronger model before major decisions, when stuck on an error, and before declaring a task done. The advisor gets a full briefing plus the conversation transcript path, returns a verdict with guidance, and the main model keeps doing the work. The default advisor is the latest Grok (Grok 4.6) at its highest reasoning effort; /advisor <model> accepts any model available to subagents. - skill `advisor`: /advisor [model|off|status|ask ...|nudge on|off], checkpoint protocol, briefing template, usable as a Custom Mode - agent `advisor-subagent`: read-only, pinned to grok-4.6[effort=xhigh] - hooks: track edits since the last consult, log consults to .cursor/advisor/log.md, nudge a pre-completion consult once per batch of edits; state is bound to the conversation that enabled it - registered in marketplace.json and the root README
62 lines
2.2 KiB
Bash
Executable File
62 lines
2.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Shared helpers for the Advisor hooks. Source this file; do not run it.
|
|
#
|
|
# State lives in $CURSOR_PROJECT_DIR/.cursor/advisor/:
|
|
# state.json written by the advisor skill, kept current here
|
|
# pending marker: files were edited since the last consult
|
|
# last-response.txt tail of the latest assistant message
|
|
# log.md one entry per completed consult
|
|
|
|
ADVISOR_DIR="${CURSOR_PROJECT_DIR:-.}/.cursor/advisor"
|
|
STATE_FILE="$ADVISOR_DIR/state.json"
|
|
PENDING_FILE="$ADVISOR_DIR/pending"
|
|
LAST_RESPONSE_FILE="$ADVISOR_DIR/last-response.txt"
|
|
LOG_FILE="$ADVISOR_DIR/log.md"
|
|
|
|
# Exit quietly unless advisor mode is on and jq is available.
|
|
advisor_require_enabled() {
|
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
[[ -f "$STATE_FILE" ]] || exit 0
|
|
[[ "$(jq -r '.enabled // false' "$STATE_FILE" 2>/dev/null)" == "true" ]] || exit 0
|
|
}
|
|
|
|
# Atomically apply a jq filter to state.json.
|
|
# Usage: advisor_state_update '<filter>' [jq args...]
|
|
advisor_state_update() {
|
|
local filter="$1"
|
|
shift
|
|
local tmp="${STATE_FILE}.tmp.$$"
|
|
if jq "$@" "$filter" "$STATE_FILE" > "$tmp" 2>/dev/null; then
|
|
mv "$tmp" "$STATE_FILE"
|
|
else
|
|
rm -f "$tmp"
|
|
fi
|
|
}
|
|
|
|
# Bind the state to the first conversation that touches it and keep transcript_path
|
|
# current. Returns 1 when the hook input belongs to a different conversation, so
|
|
# callers can stay out of conversations that did not enable the advisor.
|
|
# A fresh bind also drops per-conversation markers so a re-bind cannot inherit
|
|
# the previous conversation's pending edits.
|
|
advisor_bind_conversation() {
|
|
local input="$1"
|
|
local conv bound transcript current
|
|
conv=$(jq -r '.conversation_id // empty' <<< "$input")
|
|
bound=$(jq -r '.conversation_id // empty' "$STATE_FILE")
|
|
if [[ -n "$conv" ]]; then
|
|
if [[ -z "$bound" ]]; then
|
|
advisor_state_update '.conversation_id = $conv' --arg conv "$conv"
|
|
rm -f "$PENDING_FILE" "$LAST_RESPONSE_FILE"
|
|
elif [[ "$bound" != "$conv" ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
transcript=$(jq -r '.transcript_path // empty' <<< "$input")
|
|
current=$(jq -r '.transcript_path // empty' "$STATE_FILE")
|
|
if [[ -n "$transcript" && "$transcript" != "$current" ]]; then
|
|
advisor_state_update '.transcript_path = $path' --arg path "$transcript"
|
|
fi
|
|
return 0
|
|
}
|