feat(plugin): add /api/plugin/context push-channel endpoint + dogfood hook
Phase 1 of plan #755 (Scribe-as-plugin). Gives Scribe its own session-start push channel so always-on rules + active-project context surface without being asked — the gap behind 'I have to prompt for everything'. - services/plugin_context.build_session_context: renders always-on rule titles grouped by topic (under the 10k additionalContext cap; full text stays one list_always_on_rules/get_rule call away) + optional project goal/open-task count + a recall/update-over-create reflex line. Capped at 9000 chars. - routes/plugin GET /api/plugin/context (login_required already accepts Bearer fmcp_ keys; read scope suffices). - tests: titles-not-statements, project scoping, length cap (pure mocks). - scripts/scribe_session_context.sh: dogfood SessionStart hook, fail-open, reads url+token from .mcp.json. Superseded in Phase 2 by the plugin-bundled hook using userConfig. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Scribe SessionStart hook (dogfood / pre-plugin).
|
||||
#
|
||||
# Curls the running Scribe dev instance for the operator's always-on rules +
|
||||
# active-project context and emits it as SessionStart `additionalContext` — the
|
||||
# push channel that lets Scribe surface reflexively (plan #755, Phase 1).
|
||||
#
|
||||
# FAIL-OPEN by design: any missing tool, missing config, network error, or
|
||||
# unreachable instance results in injecting nothing and exiting 0. A session
|
||||
# must NEVER be blocked because Scribe is down. Reads URL+token from the
|
||||
# project's .mcp.json so no secret lives in this tracked script.
|
||||
#
|
||||
# Superseded in Phase 2 by the same hook bundled in the Scribe plugin, where
|
||||
# URL+token come from plugin userConfig instead of .mcp.json.
|
||||
set -uo pipefail
|
||||
|
||||
MCP_JSON="${CLAUDE_PROJECT_DIR:-.}/.mcp.json"
|
||||
command -v jq >/dev/null 2>&1 || exit 0
|
||||
command -v curl >/dev/null 2>&1 || exit 0
|
||||
[ -f "$MCP_JSON" ] || exit 0
|
||||
|
||||
# scribe-dev is the locally-wired instance (prod id 2 / dev id 3 per binding).
|
||||
url=$(jq -r '.mcpServers["scribe-dev"].url // empty' "$MCP_JSON" 2>/dev/null) || exit 0
|
||||
auth=$(jq -r '.mcpServers["scribe-dev"].headers.Authorization // empty' "$MCP_JSON" 2>/dev/null) || exit 0
|
||||
token=${auth#Bearer }
|
||||
[ -n "$url" ] && [ -n "$token" ] || exit 0
|
||||
|
||||
base=${url%/mcp}
|
||||
body=$(curl -fsS --max-time 8 \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
"${base}/api/plugin/context?project_id=3" 2>/dev/null) || exit 0
|
||||
|
||||
text=$(printf '%s' "$body" | jq -r '.context // empty' 2>/dev/null) || exit 0
|
||||
[ -n "$text" ] || exit 0
|
||||
|
||||
jq -n --arg c "$text" \
|
||||
'{hookSpecificOutput: {hookEventName: "SessionStart", additionalContext: $c}}'
|
||||
exit 0
|
||||
Reference in New Issue
Block a user