bluera-knowledge 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +16 -0
- package/README.md +7 -19
- package/dist/index.js +69 -2
- package/dist/index.js.map +1 -1
- package/hooks/hooks.json +17 -1
- package/hooks/stop-bk-check.py +86 -0
- package/hooks/userpromptsubmit-bk-nudge.py +136 -0
- package/package.json +1 -1
- package/scripts/auto-setup.sh +11 -3
- package/skills/knowledge-search/SKILL.md +1 -1
- package/skills/suggest/SKILL.md +13 -6
package/hooks/hooks.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "bluera-knowledge plugin hooks - auto-setup, readiness checks, job monitoring, and BK suggestions",
|
|
2
|
+
"description": "bluera-knowledge plugin hooks - auto-setup, readiness checks, job monitoring, activation nudges, and BK suggestions",
|
|
3
3
|
"hooks": {
|
|
4
4
|
"SessionStart": [
|
|
5
5
|
{
|
|
@@ -72,6 +72,22 @@
|
|
|
72
72
|
"command": "${CLAUDE_PLUGIN_ROOT:-.}/hooks/job-status-hook.sh",
|
|
73
73
|
"timeout": 2,
|
|
74
74
|
"async": true
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"type": "command",
|
|
78
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT:-.}/hooks/userpromptsubmit-bk-nudge.py",
|
|
79
|
+
"timeout": 2
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"Stop": [
|
|
85
|
+
{
|
|
86
|
+
"hooks": [
|
|
87
|
+
{
|
|
88
|
+
"type": "command",
|
|
89
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT:-.}/hooks/stop-bk-check.py",
|
|
90
|
+
"timeout": 2
|
|
75
91
|
}
|
|
76
92
|
]
|
|
77
93
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Stop hook for bluera-knowledge plugin.
|
|
4
|
+
|
|
5
|
+
Fires when Claude is about to stop responding. If the conversation
|
|
6
|
+
involved dependency-related work but BK was never consulted, blocks
|
|
7
|
+
once to suggest checking BK.
|
|
8
|
+
|
|
9
|
+
Uses stop_hook_active for loop protection — only blocks the first time.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main() -> None:
|
|
17
|
+
try:
|
|
18
|
+
stdin_data = sys.stdin.read()
|
|
19
|
+
if not stdin_data.strip():
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
data = json.loads(stdin_data)
|
|
23
|
+
|
|
24
|
+
# Loop protection: if stop hook already fired, allow stop
|
|
25
|
+
stop_hook_active = data.get("stop_hook_active", False)
|
|
26
|
+
if stop_hook_active:
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
# Check if BK tools were used in this conversation
|
|
30
|
+
# The tool_uses field contains tools used so far in the session
|
|
31
|
+
tool_uses = data.get("tool_uses", [])
|
|
32
|
+
|
|
33
|
+
bk_was_used = False
|
|
34
|
+
has_dependency_context = False
|
|
35
|
+
|
|
36
|
+
for tool_use in tool_uses:
|
|
37
|
+
tool_name = ""
|
|
38
|
+
if isinstance(tool_use, dict):
|
|
39
|
+
tool_name = tool_use.get("tool_name", tool_use.get("name", ""))
|
|
40
|
+
elif isinstance(tool_use, str):
|
|
41
|
+
tool_name = tool_use
|
|
42
|
+
|
|
43
|
+
# Check if BK search was used
|
|
44
|
+
if "bluera-knowledge" in tool_name and (
|
|
45
|
+
"search" in tool_name or "get_full_context" in tool_name
|
|
46
|
+
):
|
|
47
|
+
bk_was_used = True
|
|
48
|
+
break
|
|
49
|
+
|
|
50
|
+
# Check if dependency dirs were accessed (Read/Grep in node_modules etc.)
|
|
51
|
+
tool_input = (
|
|
52
|
+
tool_use.get("tool_input", {}) if isinstance(tool_use, dict) else {}
|
|
53
|
+
)
|
|
54
|
+
path = tool_input.get("path", tool_input.get("file_path", ""))
|
|
55
|
+
if isinstance(path, str):
|
|
56
|
+
dep_markers = (
|
|
57
|
+
"/node_modules/",
|
|
58
|
+
"/vendor/",
|
|
59
|
+
"/site-packages/",
|
|
60
|
+
"/.venv/",
|
|
61
|
+
)
|
|
62
|
+
if any(marker in path for marker in dep_markers):
|
|
63
|
+
has_dependency_context = True
|
|
64
|
+
|
|
65
|
+
# If BK was used or no dependency context detected, allow stop
|
|
66
|
+
if bk_was_used or not has_dependency_context:
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
# Block stop once — suggest checking BK
|
|
70
|
+
output = {
|
|
71
|
+
"decision": "block",
|
|
72
|
+
"reason": (
|
|
73
|
+
"You accessed dependency directories but haven't consulted Bluera Knowledge. "
|
|
74
|
+
"Consider using mcp__bluera-knowledge__search to verify your answer "
|
|
75
|
+
"against authoritative source code before completing."
|
|
76
|
+
),
|
|
77
|
+
}
|
|
78
|
+
print(json.dumps(output))
|
|
79
|
+
|
|
80
|
+
except Exception:
|
|
81
|
+
# Hooks must never crash — silent failure allows stop
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
main()
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
UserPromptSubmit hook for bluera-knowledge plugin.
|
|
4
|
+
|
|
5
|
+
Detects dependency-related prompts and injects a gentle BK reminder
|
|
6
|
+
into context, reinforcing the directive skill description.
|
|
7
|
+
|
|
8
|
+
Fires when:
|
|
9
|
+
- Prompt mentions dependency errors (Cannot find module, ModuleNotFoundError, etc.)
|
|
10
|
+
- Prompt involves planning/implementing with external packages
|
|
11
|
+
- Prompt mentions debugging + library/package keywords
|
|
12
|
+
- Prompt contains import/require statements with package names
|
|
13
|
+
|
|
14
|
+
Does NOT fire when:
|
|
15
|
+
- Prompt already mentions bluera-knowledge, /search, or mcp__bluera-knowledge
|
|
16
|
+
- No dependency-related content detected
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import re
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Patterns that indicate dependency-related work
|
|
25
|
+
DEPENDENCY_ERROR_PATTERNS = [
|
|
26
|
+
r"cannot find module",
|
|
27
|
+
r"module not found",
|
|
28
|
+
r"modulenotfounderror",
|
|
29
|
+
r"importerror",
|
|
30
|
+
r"no module named",
|
|
31
|
+
r"package .+ not found",
|
|
32
|
+
r"could not resolve",
|
|
33
|
+
r"cannot resolve",
|
|
34
|
+
r"peer dep",
|
|
35
|
+
r"unresolved import",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
LIBRARY_KEYWORDS = [
|
|
39
|
+
r"\b(?:dependency|dependencies|package|library|framework|sdk|api)\b",
|
|
40
|
+
r"\b(?:npm|pip|cargo|gem|maven|gradle|composer|nuget)\b",
|
|
41
|
+
r"\b(?:node_modules|vendor|site-packages|\.venv)\b",
|
|
42
|
+
r"\b(?:import|require|from .+ import)\b.*\b(?:express|react|vue|angular|fastapi|django|flask|hono|zod|pydantic|axios|lodash|prisma|drizzle|next|svelte|tailwind)\b",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
PLANNING_PATTERNS = [
|
|
46
|
+
r"\b(?:implement|integrate|set up|configure|use|add)\b.{1,40}\b(?:with|using)\b",
|
|
47
|
+
r"\bhow (?:does|do|to)\b.{1,30}\b(?:work|handle|process)\b",
|
|
48
|
+
r"\bwhat (?:is|are|does)\b.{1,30}\b(?:api|method|function|class|option|parameter)\b",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
DEBUG_PATTERNS = [
|
|
52
|
+
r"\b(?:error|bug|issue|crash|fail|broken|stuck|debug)\b.{1,60}\b(?:package|library|dependency|module|import)\b",
|
|
53
|
+
r"\b(?:package|library|dependency|module|import)\b.{1,60}\b(?:error|bug|issue|crash|fail|broken|stuck|debug)\b",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
# Patterns indicating the user is already using BK
|
|
57
|
+
ALREADY_USING_BK = [
|
|
58
|
+
r"bluera.knowledge",
|
|
59
|
+
r"/search",
|
|
60
|
+
r"/bluera-knowledge",
|
|
61
|
+
r"mcp__bluera.knowledge",
|
|
62
|
+
r"mcp__.*bluera.*knowledge",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def prompt_involves_dependencies(prompt: str) -> bool:
|
|
67
|
+
"""Check if the prompt involves dependency/library work."""
|
|
68
|
+
lower = prompt.lower()
|
|
69
|
+
|
|
70
|
+
for pattern in DEPENDENCY_ERROR_PATTERNS:
|
|
71
|
+
if re.search(pattern, lower):
|
|
72
|
+
return True
|
|
73
|
+
|
|
74
|
+
for pattern in LIBRARY_KEYWORDS:
|
|
75
|
+
if re.search(pattern, lower, re.IGNORECASE):
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
for pattern in PLANNING_PATTERNS:
|
|
79
|
+
if re.search(pattern, lower, re.IGNORECASE):
|
|
80
|
+
return True
|
|
81
|
+
|
|
82
|
+
for pattern in DEBUG_PATTERNS:
|
|
83
|
+
if re.search(pattern, lower, re.IGNORECASE):
|
|
84
|
+
return True
|
|
85
|
+
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def already_using_bk(prompt: str) -> bool:
|
|
90
|
+
"""Check if the prompt already references BK."""
|
|
91
|
+
lower = prompt.lower()
|
|
92
|
+
for pattern in ALREADY_USING_BK:
|
|
93
|
+
if re.search(pattern, lower):
|
|
94
|
+
return True
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def main() -> None:
|
|
99
|
+
try:
|
|
100
|
+
stdin_data = sys.stdin.read()
|
|
101
|
+
if not stdin_data.strip():
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
data = json.loads(stdin_data)
|
|
105
|
+
prompt = data.get("prompt", "")
|
|
106
|
+
|
|
107
|
+
if not prompt:
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
# Don't fire if user is already using BK
|
|
111
|
+
if already_using_bk(prompt):
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
# Don't fire if prompt doesn't involve dependencies
|
|
115
|
+
if not prompt_involves_dependencies(prompt):
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
output = {
|
|
119
|
+
"hookSpecificOutput": {
|
|
120
|
+
"hookEventName": "UserPromptSubmit",
|
|
121
|
+
"additionalContext": (
|
|
122
|
+
"You have indexed library sources available via Bluera Knowledge. "
|
|
123
|
+
"Use mcp__bluera-knowledge__search to look up library APIs, "
|
|
124
|
+
"implementation details, and usage patterns before relying on training data."
|
|
125
|
+
),
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
print(json.dumps(output))
|
|
129
|
+
|
|
130
|
+
except Exception:
|
|
131
|
+
# Hooks must never crash — silent failure is safer than blocking
|
|
132
|
+
pass
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if __name__ == "__main__":
|
|
136
|
+
main()
|
package/package.json
CHANGED
package/scripts/auto-setup.sh
CHANGED
|
@@ -30,11 +30,18 @@ log_debug() {
|
|
|
30
30
|
|
|
31
31
|
log_debug "Auto-setup starting, PLUGIN_ROOT=$PLUGIN_ROOT"
|
|
32
32
|
|
|
33
|
-
# Fast exit if already set up
|
|
33
|
+
# Fast exit if already set up AND version hasn't changed
|
|
34
34
|
WRAPPER_PATH="$HOME/.local/bin/bluera-knowledge-mcp"
|
|
35
|
+
VERSION_FILE="$PLUGIN_ROOT/.installed-version"
|
|
36
|
+
CURRENT_VERSION=$(cat "$PLUGIN_ROOT/package.json" 2>/dev/null | grep '"version"' | head -1 | sed 's/.*"\([0-9][0-9.]*\)".*/\1/')
|
|
37
|
+
INSTALLED_VERSION=$(cat "$VERSION_FILE" 2>/dev/null || echo "none")
|
|
38
|
+
|
|
35
39
|
if [ -d "$PLUGIN_ROOT/node_modules" ] && [ -f "$WRAPPER_PATH" ]; then
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
if [ "$CURRENT_VERSION" = "$INSTALLED_VERSION" ]; then
|
|
41
|
+
log_debug "Already set up (v$INSTALLED_VERSION), exiting"
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
log_debug "Version changed ($INSTALLED_VERSION -> $CURRENT_VERSION), re-running setup"
|
|
38
45
|
fi
|
|
39
46
|
|
|
40
47
|
log_debug "Setup needed - node_modules: $([ -d "$PLUGIN_ROOT/node_modules" ] && echo 'exists' || echo 'missing'), wrapper: $([ -f "$WRAPPER_PATH" ] && echo 'exists' || echo 'missing')"
|
|
@@ -60,6 +67,7 @@ echo -e "${YELLOW}[bluera-knowledge] Running first-time setup (this may take a m
|
|
|
60
67
|
export NONINTERACTIVE=1
|
|
61
68
|
if "$PLUGIN_ROOT/scripts/setup.sh"; then
|
|
62
69
|
log_debug "Setup completed successfully"
|
|
70
|
+
echo "$CURRENT_VERSION" > "$VERSION_FILE" 2>/dev/null || true
|
|
63
71
|
echo -e "${GREEN}[bluera-knowledge] Setup complete ✓${NC}"
|
|
64
72
|
echo -e "${GREEN}[bluera-knowledge] Restart Claude Code to enable MCP server.${NC}"
|
|
65
73
|
else
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: knowledge-search
|
|
3
|
-
description:
|
|
3
|
+
description: Library and dependency expert. ALWAYS invoke this skill when working with third-party libraries, frameworks, or dependencies — including debugging dependency errors, planning code that uses external packages, checking API signatures, or understanding library internals. Do not grep node_modules, vendor directories, or rely on training data for library questions directly — use this skill first.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Using Bluera Knowledge (BK)
|
package/skills/suggest/SKILL.md
CHANGED
|
@@ -28,16 +28,23 @@ Analyze project dependencies and suggest important libraries to add to knowledge
|
|
|
28
28
|
- Count imports/requires for each dependency
|
|
29
29
|
- Rank dependencies by frequency of use
|
|
30
30
|
|
|
31
|
-
4. **
|
|
31
|
+
4. **Select the IMPORTANT dependencies** — not all of them. Apply these criteria:
|
|
32
|
+
- Prioritize core frameworks and libraries the project builds ON (e.g., React, Express, FastAPI)
|
|
33
|
+
- Include libraries with complex APIs where understanding internals helps (e.g., Prisma, Drizzle, Zod)
|
|
34
|
+
- Include deps likely to cause debugging issues or have non-obvious behavior
|
|
35
|
+
- **Skip**: test runners (jest, vitest, pytest), linters (eslint, ruff), formatters (prettier, black), build tools (webpack, vite, esbuild), @types packages, trivial utilities
|
|
36
|
+
- Aim for 5-10 most impactful dependencies, not every dependency
|
|
37
|
+
|
|
38
|
+
5. **Get existing stores** using mcp__bluera-knowledge__execute with command "stores":
|
|
32
39
|
- Filter out dependencies already in stores
|
|
33
40
|
- Focus on new suggestions
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
- For
|
|
42
|
+
6. **Find repository URLs** using WebSearch:
|
|
43
|
+
- For the selected important dependencies
|
|
37
44
|
- Search for official GitHub/GitLab repositories
|
|
38
45
|
- Prefer official repos over forks
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
7. **Present selectable list** using AskUserQuestion:
|
|
41
48
|
|
|
42
49
|
First, show a summary of what was found:
|
|
43
50
|
```
|
|
@@ -79,7 +86,7 @@ Then use AskUserQuestion with multiSelect to let the user choose which to add:
|
|
|
79
86
|
|
|
80
87
|
**Note:** Maximum 4 options per question (AskUserQuestion limit). If more than 4 dependencies, show top 4 and mention others in summary.
|
|
81
88
|
|
|
82
|
-
|
|
89
|
+
8. **Execute selected add-repo commands**:
|
|
83
90
|
|
|
84
91
|
For each selected dependency, invoke the Skill tool:
|
|
85
92
|
```
|
|
@@ -91,7 +98,7 @@ Example for react selection:
|
|
|
91
98
|
Skill(skill="bluera-knowledge:add-repo", args="https://github.com/facebook/react --name=react")
|
|
92
99
|
```
|
|
93
100
|
|
|
94
|
-
|
|
101
|
+
9. **Show completion summary**:
|
|
95
102
|
```
|
|
96
103
|
## Added to Knowledge Stores
|
|
97
104
|
|