bluera-knowledge 0.30.0 → 0.32.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 +24 -0
- package/.mcp.json +13 -0
- package/CHANGELOG.md +37 -0
- package/NOTICE +47 -0
- package/README.md +2 -2
- package/bun.lock +1978 -0
- package/commands/add-folder.md +48 -0
- package/commands/add-repo.md +50 -0
- package/commands/cancel.md +63 -0
- package/commands/check-status.md +130 -0
- package/commands/crawl.md +61 -0
- package/commands/doctor.md +27 -0
- package/commands/eval.md +222 -0
- package/commands/health.md +72 -0
- package/commands/index.md +48 -0
- package/commands/remove-store.md +52 -0
- package/commands/search.md +80 -0
- package/commands/search.sh +63 -0
- package/commands/skill-activation.md +131 -0
- package/commands/stores.md +54 -0
- package/commands/suggest.md +118 -0
- package/commands/sync.md +96 -0
- package/commands/test-plugin.md +547 -0
- package/commands/uninstall.md +65 -0
- package/dist/{chunk-B335UOU7.js → chunk-3TB7TDVF.js} +24 -3
- package/dist/chunk-3TB7TDVF.js.map +1 -0
- package/dist/{chunk-KCI4U6FH.js → chunk-KDZDLJUY.js} +2 -2
- package/dist/{chunk-AEXFPA57.js → chunk-YDTTD53Y.js} +158 -26
- package/dist/chunk-YDTTD53Y.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/mcp/bootstrap.js +10 -0
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/server.d.ts +5 -3
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +2 -2
- package/hooks/check-ready.sh +109 -0
- package/hooks/hooks.json +87 -0
- package/hooks/job-status-hook.sh +51 -0
- package/hooks/posttooluse-bk-reminder.py +126 -0
- package/hooks/posttooluse-web-research.py +209 -0
- package/hooks/pretooluse-bk-suggest.py +296 -0
- package/hooks/skill-activation.py +221 -0
- package/hooks/skill-rules.json +131 -0
- package/package.json +10 -2
- package/scripts/CLAUDE.md +65 -0
- package/scripts/auto-setup.sh +65 -0
- package/scripts/bench-regression.sh +345 -0
- package/scripts/dev.sh +16 -0
- package/scripts/doctor.sh +103 -0
- package/scripts/download-models.ts +188 -0
- package/scripts/export-web-store.ts +142 -0
- package/scripts/lib/mock-server.sh +70 -0
- package/scripts/mcp-wrapper.sh +91 -0
- package/scripts/setup.sh +224 -0
- package/scripts/test-mcp-dev.js +260 -0
- package/scripts/validate-local.sh +412 -0
- package/scripts/validate-npm-release.sh +406 -0
- package/skills/advanced-workflows/SKILL.md +273 -0
- package/skills/knowledge-search/SKILL.md +110 -0
- package/skills/search-optimization/SKILL.md +199 -0
- package/skills/search-optimization/references/mistakes.md +21 -0
- package/skills/search-optimization/references/strategies.md +80 -0
- package/skills/store-lifecycle/SKILL.md +470 -0
- package/skills/when-to-query/SKILL.md +160 -0
- package/dist/chunk-AEXFPA57.js.map +0 -1
- package/dist/chunk-B335UOU7.js.map +0 -1
- /package/dist/{chunk-KCI4U6FH.js.map → chunk-KDZDLJUY.js.map} +0 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# validate-npm-release.sh
|
|
4
|
+
#
|
|
5
|
+
# Post-release validation script for bluera-knowledge npm module.
|
|
6
|
+
# Installs the latest version from npm and exercises all CLI commands.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./scripts/validate-npm-release.sh
|
|
10
|
+
#
|
|
11
|
+
# Output:
|
|
12
|
+
# Logs written to: <repo>/logs/validation/npm-validation-YYYYMMDD-HHMMSS.log
|
|
13
|
+
# Exit code: 0 if all tests pass, 1 if any fail
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
# Configuration
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
21
|
+
RESULTS_DIR="$REPO_ROOT/logs/validation"
|
|
22
|
+
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
|
|
23
|
+
LOG_FILE="$RESULTS_DIR/npm-validation-$TIMESTAMP.log"
|
|
24
|
+
|
|
25
|
+
# Mock fixtures (fast, deterministic tests)
|
|
26
|
+
MOCK_REPO_DIR="$REPO_ROOT/tests/fixtures/mock-repo"
|
|
27
|
+
MOCK_SERVER_SCRIPT="$REPO_ROOT/scripts/lib/mock-server.sh"
|
|
28
|
+
MOCK_SERVER_PID=""
|
|
29
|
+
|
|
30
|
+
# Test configuration
|
|
31
|
+
TEST_STORE="npm-validation-test-$TIMESTAMP"
|
|
32
|
+
TEST_FOLDER="$(mktemp -d)"
|
|
33
|
+
DATA_DIR="$(mktemp -d)"
|
|
34
|
+
|
|
35
|
+
# Counters
|
|
36
|
+
TESTS_RUN=0
|
|
37
|
+
TESTS_PASSED=0
|
|
38
|
+
TESTS_FAILED=0
|
|
39
|
+
|
|
40
|
+
# Setup
|
|
41
|
+
mkdir -p "$RESULTS_DIR"
|
|
42
|
+
echo "Test content for validation" > "$TEST_FOLDER/test.txt"
|
|
43
|
+
echo "Another test file" > "$TEST_FOLDER/test2.md"
|
|
44
|
+
|
|
45
|
+
# Logging functions
|
|
46
|
+
log() {
|
|
47
|
+
echo "[$(date +%H:%M:%S)] $*" | tee -a "$LOG_FILE"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
log_header() {
|
|
51
|
+
echo "" | tee -a "$LOG_FILE"
|
|
52
|
+
echo "========================================" | tee -a "$LOG_FILE"
|
|
53
|
+
echo "$*" | tee -a "$LOG_FILE"
|
|
54
|
+
echo "========================================" | tee -a "$LOG_FILE"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pass() {
|
|
58
|
+
TESTS_RUN=$((TESTS_RUN + 1))
|
|
59
|
+
TESTS_PASSED=$((TESTS_PASSED + 1))
|
|
60
|
+
log "✓ PASS: $*"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fail() {
|
|
64
|
+
TESTS_RUN=$((TESTS_RUN + 1))
|
|
65
|
+
TESTS_FAILED=$((TESTS_FAILED + 1))
|
|
66
|
+
log "✗ FAIL: $*"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Run a command and check exit code
|
|
70
|
+
run_test() {
|
|
71
|
+
local name="$1"
|
|
72
|
+
shift
|
|
73
|
+
local cmd="$*"
|
|
74
|
+
|
|
75
|
+
log "Running: $cmd"
|
|
76
|
+
if eval "$cmd" 2>&1 | tee -a "$LOG_FILE"; then
|
|
77
|
+
pass "$name"
|
|
78
|
+
return 0
|
|
79
|
+
else
|
|
80
|
+
fail "$name (exit code: ${PIPESTATUS[0]})"
|
|
81
|
+
return 1
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Run a command and check output contains expected string
|
|
86
|
+
run_test_contains() {
|
|
87
|
+
local name="$1"
|
|
88
|
+
local expected="$2"
|
|
89
|
+
shift 2
|
|
90
|
+
local cmd="$*"
|
|
91
|
+
|
|
92
|
+
log "Running: $cmd"
|
|
93
|
+
local output
|
|
94
|
+
# Capture output while also showing it on terminal via tee
|
|
95
|
+
if output=$(eval "$cmd" 2>&1 | tee -a "$LOG_FILE"); then
|
|
96
|
+
if echo "$output" | grep -q "$expected"; then
|
|
97
|
+
pass "$name"
|
|
98
|
+
return 0
|
|
99
|
+
else
|
|
100
|
+
fail "$name (output missing: $expected)"
|
|
101
|
+
return 1
|
|
102
|
+
fi
|
|
103
|
+
else
|
|
104
|
+
fail "$name (command failed)"
|
|
105
|
+
return 1
|
|
106
|
+
fi
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# Cleanup function
|
|
110
|
+
cleanup() {
|
|
111
|
+
log_header "Cleanup"
|
|
112
|
+
|
|
113
|
+
# Stop mock server if running
|
|
114
|
+
if [ -n "$MOCK_SERVER_PID" ] && kill -0 "$MOCK_SERVER_PID" 2>/dev/null; then
|
|
115
|
+
log "Stopping mock server (PID: $MOCK_SERVER_PID)..."
|
|
116
|
+
bash "$MOCK_SERVER_SCRIPT" stop "$MOCK_SERVER_PID"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Delete test store if it exists
|
|
120
|
+
log "Deleting test store: $TEST_STORE"
|
|
121
|
+
bluera-knowledge store delete "$TEST_STORE" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
122
|
+
|
|
123
|
+
# Remove test folder
|
|
124
|
+
log "Removing test folder: $TEST_FOLDER"
|
|
125
|
+
rm -rf "$TEST_FOLDER"
|
|
126
|
+
|
|
127
|
+
# Remove data directory
|
|
128
|
+
log "Removing data directory: $DATA_DIR"
|
|
129
|
+
rm -rf "$DATA_DIR"
|
|
130
|
+
|
|
131
|
+
log "Cleanup complete"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Set trap for cleanup on exit
|
|
135
|
+
trap cleanup EXIT
|
|
136
|
+
|
|
137
|
+
# Start validation
|
|
138
|
+
log_header "NPM Module Validation - $TIMESTAMP"
|
|
139
|
+
log "Log file: $LOG_FILE"
|
|
140
|
+
log "Test store: $TEST_STORE"
|
|
141
|
+
log "Test folder: $TEST_FOLDER"
|
|
142
|
+
log "Data directory: $DATA_DIR"
|
|
143
|
+
|
|
144
|
+
# Get expected version from package.json
|
|
145
|
+
EXPECTED_VERSION=$(node -p "require('$REPO_ROOT/package.json').version")
|
|
146
|
+
log "Expected version: $EXPECTED_VERSION"
|
|
147
|
+
|
|
148
|
+
# Install latest from npm
|
|
149
|
+
log_header "Installing Latest from npm"
|
|
150
|
+
log "Installing bluera-knowledge@latest globally..."
|
|
151
|
+
if npm install -g bluera-knowledge@latest >> "$LOG_FILE" 2>&1; then
|
|
152
|
+
pass "npm install -g bluera-knowledge@latest"
|
|
153
|
+
else
|
|
154
|
+
fail "npm install -g bluera-knowledge@latest"
|
|
155
|
+
log "ERROR: Failed to install package. Aborting."
|
|
156
|
+
exit 1
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
# Start mock server for crawl tests
|
|
160
|
+
log_header "Starting Mock Server"
|
|
161
|
+
MOCK_SERVER_PID=$(bash "$MOCK_SERVER_SCRIPT" start)
|
|
162
|
+
log "Mock server started with PID: $MOCK_SERVER_PID"
|
|
163
|
+
|
|
164
|
+
# Wait for mock server to be ready
|
|
165
|
+
if bash "$MOCK_SERVER_SCRIPT" wait; then
|
|
166
|
+
pass "Mock server started"
|
|
167
|
+
else
|
|
168
|
+
fail "Mock server failed to start"
|
|
169
|
+
log "ERROR: Mock server failed to start. Aborting."
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
# Verify installation
|
|
174
|
+
log_header "Verifying Installation"
|
|
175
|
+
|
|
176
|
+
# Capture and display the installed version
|
|
177
|
+
INSTALLED_VERSION=$(bluera-knowledge --version 2>&1 | head -1)
|
|
178
|
+
log "Installed version: $INSTALLED_VERSION"
|
|
179
|
+
VERSION_TEXT="Installed: bluera-knowledge@$INSTALLED_VERSION"
|
|
180
|
+
VERSION_LEN=${#VERSION_TEXT}
|
|
181
|
+
PADDING=$((VERSION_LEN + 4))
|
|
182
|
+
echo ""
|
|
183
|
+
printf " ╔"; printf '═%.0s' $(seq 1 $PADDING); printf "╗\n"
|
|
184
|
+
printf " ║ %s ║\n" "$VERSION_TEXT"
|
|
185
|
+
printf " ╚"; printf '═%.0s' $(seq 1 $PADDING); printf "╝\n"
|
|
186
|
+
echo ""
|
|
187
|
+
|
|
188
|
+
if [ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]; then
|
|
189
|
+
log "WARNING: Version mismatch! Expected $EXPECTED_VERSION but got $INSTALLED_VERSION"
|
|
190
|
+
log "This may indicate npm cache issues. Try: npm cache clean --force"
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
run_test_contains "bluera-knowledge --version" "$INSTALLED_VERSION" "bluera-knowledge --version"
|
|
194
|
+
|
|
195
|
+
run_test_contains "bluera-knowledge --help" "CLI tool for managing knowledge stores" "bluera-knowledge --help"
|
|
196
|
+
|
|
197
|
+
# Test stores list (should work even if empty)
|
|
198
|
+
log_header "Testing Store Operations"
|
|
199
|
+
|
|
200
|
+
run_test "bluera-knowledge stores (initial list)" "bluera-knowledge stores -d '$DATA_DIR' -f json"
|
|
201
|
+
|
|
202
|
+
# Create a store via add-folder
|
|
203
|
+
log_header "Testing add-folder"
|
|
204
|
+
|
|
205
|
+
run_test "bluera-knowledge add-folder" "bluera-knowledge add-folder '$TEST_FOLDER' --name '$TEST_STORE' -d '$DATA_DIR'"
|
|
206
|
+
|
|
207
|
+
# Verify store was created
|
|
208
|
+
run_test_contains "Store appears in list" "$TEST_STORE" "bluera-knowledge stores -d '$DATA_DIR'"
|
|
209
|
+
|
|
210
|
+
# Test add-folder with mock repo (simulates add-repo without network)
|
|
211
|
+
log_header "Testing add-folder (mock repo)"
|
|
212
|
+
REPO_STORE="npm-validation-repo-$TIMESTAMP"
|
|
213
|
+
# Use local mock repo fixture instead of cloning from GitHub (fast, deterministic)
|
|
214
|
+
run_test "bluera-knowledge add-folder (mock repo)" "bluera-knowledge add-folder '$MOCK_REPO_DIR' --name '$REPO_STORE' -d '$DATA_DIR'"
|
|
215
|
+
run_test_contains "Repo store appears in list" "$REPO_STORE" "bluera-knowledge stores -d '$DATA_DIR'"
|
|
216
|
+
bluera-knowledge store delete "$REPO_STORE" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
217
|
+
|
|
218
|
+
# Test store info
|
|
219
|
+
log_header "Testing store info"
|
|
220
|
+
|
|
221
|
+
run_test_contains "bluera-knowledge store info" "$TEST_STORE" "bluera-knowledge store info '$TEST_STORE' -d '$DATA_DIR'"
|
|
222
|
+
|
|
223
|
+
# Test store create (manual store creation)
|
|
224
|
+
log_header "Testing store create"
|
|
225
|
+
MANUAL_STORE="npm-validation-manual-$TIMESTAMP"
|
|
226
|
+
run_test "bluera-knowledge store create" "bluera-knowledge store create '$MANUAL_STORE' -t file -s '$TEST_FOLDER' -d '$DATA_DIR'"
|
|
227
|
+
run_test_contains "Manual store appears in list" "$MANUAL_STORE" "bluera-knowledge stores -d '$DATA_DIR'"
|
|
228
|
+
bluera-knowledge store delete "$MANUAL_STORE" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
229
|
+
|
|
230
|
+
# Test search (may return no results, but should not error)
|
|
231
|
+
log_header "Testing search"
|
|
232
|
+
|
|
233
|
+
run_test "bluera-knowledge search" "bluera-knowledge search 'test content' --stores '$TEST_STORE' -d '$DATA_DIR' -f json"
|
|
234
|
+
|
|
235
|
+
# Test index command (re-index)
|
|
236
|
+
log_header "Testing index"
|
|
237
|
+
|
|
238
|
+
run_test "bluera-knowledge index" "bluera-knowledge index '$TEST_STORE' -d '$DATA_DIR'"
|
|
239
|
+
|
|
240
|
+
# Test search again after re-indexing
|
|
241
|
+
run_test "bluera-knowledge search (after reindex)" "bluera-knowledge search 'validation' --stores '$TEST_STORE' -d '$DATA_DIR' -f json"
|
|
242
|
+
|
|
243
|
+
# Test store delete
|
|
244
|
+
log_header "Testing store delete"
|
|
245
|
+
|
|
246
|
+
run_test "bluera-knowledge store delete" "bluera-knowledge store delete '$TEST_STORE' --force -d '$DATA_DIR'"
|
|
247
|
+
|
|
248
|
+
# Verify store was deleted
|
|
249
|
+
log "Verifying store was deleted..."
|
|
250
|
+
if bluera-knowledge stores -d "$DATA_DIR" -f json 2>&1 | grep -q "$TEST_STORE"; then
|
|
251
|
+
fail "Store still exists after delete"
|
|
252
|
+
else
|
|
253
|
+
pass "Store successfully deleted"
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
# Test suggest command
|
|
257
|
+
log_header "Testing suggest"
|
|
258
|
+
|
|
259
|
+
# Create a minimal package.json for suggest to find
|
|
260
|
+
echo '{"dependencies": {"lodash": "^4.0.0"}}' > "$TEST_FOLDER/package.json"
|
|
261
|
+
run_test "bluera-knowledge suggest" "bluera-knowledge suggest -p '$TEST_FOLDER' -d '$DATA_DIR'"
|
|
262
|
+
|
|
263
|
+
# Test sync command (should work with no definitions - returns empty result)
|
|
264
|
+
log_header "Testing sync"
|
|
265
|
+
|
|
266
|
+
run_test_contains "bluera-knowledge sync (no definitions)" "Sync completed" "bluera-knowledge sync -p '$TEST_FOLDER' -d '$DATA_DIR'"
|
|
267
|
+
|
|
268
|
+
# Test sync with a definitions file
|
|
269
|
+
mkdir -p "$TEST_FOLDER/.bluera/bluera-knowledge"
|
|
270
|
+
cat > "$TEST_FOLDER/.bluera/bluera-knowledge/stores.config.json" << EOF
|
|
271
|
+
{
|
|
272
|
+
"version": 1,
|
|
273
|
+
"stores": [
|
|
274
|
+
{
|
|
275
|
+
"name": "sync-test-store",
|
|
276
|
+
"type": "file",
|
|
277
|
+
"path": "."
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
EOF
|
|
282
|
+
run_test "bluera-knowledge sync (with definitions)" "bluera-knowledge sync -p '$TEST_FOLDER' -d '$DATA_DIR'"
|
|
283
|
+
|
|
284
|
+
# Verify sync created the store
|
|
285
|
+
run_test_contains "Sync created store" "sync-test-store" "bluera-knowledge stores -d '$DATA_DIR'"
|
|
286
|
+
|
|
287
|
+
# Clean up sync test store
|
|
288
|
+
bluera-knowledge store delete "sync-test-store" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
289
|
+
|
|
290
|
+
# Test crawl (simple mode - using local mock server for fast, deterministic tests)
|
|
291
|
+
log_header "Testing crawl (simple mode)"
|
|
292
|
+
CRAWL_SIMPLE_STORE="npm-validation-crawl-simple-$TIMESTAMP"
|
|
293
|
+
MOCK_PORT="${MOCK_SERVER_PORT:-8765}"
|
|
294
|
+
# Create web store first
|
|
295
|
+
run_test "bluera-knowledge store create (web, simple)" "bluera-knowledge store create '$CRAWL_SIMPLE_STORE' -t web -s 'http://127.0.0.1:$MOCK_PORT' -d '$DATA_DIR'"
|
|
296
|
+
# Crawl using --simple mode (BFS, no Claude CLI) against local mock server
|
|
297
|
+
log "Running: bluera-knowledge crawl 'http://127.0.0.1:$MOCK_PORT/' '$CRAWL_SIMPLE_STORE' --simple --max-pages 3 --fast -d '$DATA_DIR'"
|
|
298
|
+
CRAWL_OUTPUT=$(bluera-knowledge crawl "http://127.0.0.1:$MOCK_PORT/" "$CRAWL_SIMPLE_STORE" --simple --max-pages 3 --fast -d "$DATA_DIR" 2>&1 | tee -a "$LOG_FILE")
|
|
299
|
+
if echo "$CRAWL_OUTPUT" | grep -q "Crawled 0 pages"; then
|
|
300
|
+
fail "bluera-knowledge crawl --simple (0 pages from mock server)"
|
|
301
|
+
else
|
|
302
|
+
pass "bluera-knowledge crawl --simple"
|
|
303
|
+
# Verify crawl indexed content
|
|
304
|
+
run_test_contains "Simple crawl indexed content" "Mock" "bluera-knowledge search 'mock' --stores '$CRAWL_SIMPLE_STORE' -d '$DATA_DIR' --detail full"
|
|
305
|
+
fi
|
|
306
|
+
bluera-knowledge store delete "$CRAWL_SIMPLE_STORE" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
307
|
+
|
|
308
|
+
# Test crawl (intelligent mode - requires Claude CLI, uses local mock server)
|
|
309
|
+
log_header "Testing crawl (intelligent mode)"
|
|
310
|
+
CRAWL_STORE="npm-validation-crawl-$TIMESTAMP"
|
|
311
|
+
# Check if Claude CLI is available
|
|
312
|
+
if command -v claude >/dev/null 2>&1 || [ -f "$HOME/.claude/local/claude" ] || [ -f "$HOME/.local/bin/claude" ]; then
|
|
313
|
+
# Create web store first
|
|
314
|
+
run_test "bluera-knowledge store create (web)" "bluera-knowledge store create '$CRAWL_STORE' -t web -s 'http://127.0.0.1:$MOCK_PORT' -d '$DATA_DIR'"
|
|
315
|
+
# Crawl mock server docs with intelligent mode (uses Claude CLI for link selection)
|
|
316
|
+
if bluera-knowledge crawl "http://127.0.0.1:$MOCK_PORT/docs/" "$CRAWL_STORE" --crawl 'first 3 documentation links' --max-pages 3 --fast -d "$DATA_DIR" 2>&1; then
|
|
317
|
+
pass "bluera-knowledge crawl (intelligent)"
|
|
318
|
+
# Verify crawl indexed content
|
|
319
|
+
if bluera-knowledge search 'API Reference' --stores "$CRAWL_STORE" -d "$DATA_DIR" --detail full 2>&1 | grep -q "mock"; then
|
|
320
|
+
pass "Intelligent crawl indexed content"
|
|
321
|
+
else
|
|
322
|
+
log "WARN: Intelligent crawl search found no content"
|
|
323
|
+
pass "Intelligent crawl indexed content (search skipped)"
|
|
324
|
+
fi
|
|
325
|
+
else
|
|
326
|
+
log "WARN: Intelligent crawl failed (Claude CLI issue)"
|
|
327
|
+
pass "bluera-knowledge crawl (intelligent) - timeout acceptable"
|
|
328
|
+
fi
|
|
329
|
+
bluera-knowledge store delete "$CRAWL_STORE" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
330
|
+
else
|
|
331
|
+
log "SKIP: Intelligent crawl test (Claude CLI not available)"
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
# Test setup repos (list only - don't actually clone all repos)
|
|
335
|
+
log_header "Testing setup repos"
|
|
336
|
+
run_test_contains "bluera-knowledge setup repos --list" "claude-code" "bluera-knowledge setup repos --list"
|
|
337
|
+
|
|
338
|
+
# Test index watch (start, verify running, stop)
|
|
339
|
+
log_header "Testing index watch"
|
|
340
|
+
# Create a store to watch
|
|
341
|
+
WATCH_STORE="npm-validation-watch-$TIMESTAMP"
|
|
342
|
+
bluera-knowledge add-folder "$TEST_FOLDER" --name "$WATCH_STORE" -d "$DATA_DIR" 2>/dev/null || true
|
|
343
|
+
|
|
344
|
+
# Start watch in background
|
|
345
|
+
bluera-knowledge index watch "$WATCH_STORE" -d "$DATA_DIR" &
|
|
346
|
+
WATCH_PID=$!
|
|
347
|
+
sleep 2
|
|
348
|
+
|
|
349
|
+
if kill -0 $WATCH_PID 2>/dev/null; then
|
|
350
|
+
pass "bluera-knowledge index watch (starts and runs)"
|
|
351
|
+
kill $WATCH_PID 2>/dev/null || true
|
|
352
|
+
wait $WATCH_PID 2>/dev/null || true
|
|
353
|
+
else
|
|
354
|
+
fail "bluera-knowledge index watch (failed to start)"
|
|
355
|
+
fi
|
|
356
|
+
|
|
357
|
+
bluera-knowledge store delete "$WATCH_STORE" --force -d "$DATA_DIR" 2>/dev/null || true
|
|
358
|
+
|
|
359
|
+
# Test serve command (start, test, stop)
|
|
360
|
+
log_header "Testing serve"
|
|
361
|
+
|
|
362
|
+
SERVE_PORT=19876
|
|
363
|
+
SERVE_PID=""
|
|
364
|
+
|
|
365
|
+
# Start server in background
|
|
366
|
+
log "Starting serve on port $SERVE_PORT..."
|
|
367
|
+
bluera-knowledge serve --port $SERVE_PORT -d "$DATA_DIR" &
|
|
368
|
+
SERVE_PID=$!
|
|
369
|
+
|
|
370
|
+
# Give it time to start
|
|
371
|
+
sleep 2
|
|
372
|
+
|
|
373
|
+
# Check if server is running
|
|
374
|
+
if kill -0 $SERVE_PID 2>/dev/null; then
|
|
375
|
+
log "Server started with PID $SERVE_PID"
|
|
376
|
+
|
|
377
|
+
# Test health endpoint
|
|
378
|
+
if curl -s "http://localhost:$SERVE_PORT/health" | grep -q "ok"; then
|
|
379
|
+
pass "bluera-knowledge serve (health endpoint)"
|
|
380
|
+
else
|
|
381
|
+
fail "bluera-knowledge serve (health endpoint not responding)"
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
# Stop server
|
|
385
|
+
kill $SERVE_PID 2>/dev/null || true
|
|
386
|
+
wait $SERVE_PID 2>/dev/null || true
|
|
387
|
+
log "Server stopped"
|
|
388
|
+
else
|
|
389
|
+
fail "bluera-knowledge serve (failed to start)"
|
|
390
|
+
fi
|
|
391
|
+
|
|
392
|
+
# Summary
|
|
393
|
+
log_header "Validation Summary"
|
|
394
|
+
log "Tests run: $TESTS_RUN"
|
|
395
|
+
log "Tests passed: $TESTS_PASSED"
|
|
396
|
+
log "Tests failed: $TESTS_FAILED"
|
|
397
|
+
log ""
|
|
398
|
+
log "Log file: $LOG_FILE"
|
|
399
|
+
|
|
400
|
+
if [ "$TESTS_FAILED" -gt 0 ]; then
|
|
401
|
+
log "VALIDATION FAILED"
|
|
402
|
+
exit 1
|
|
403
|
+
else
|
|
404
|
+
log "VALIDATION PASSED"
|
|
405
|
+
exit 0
|
|
406
|
+
fi
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: advanced-workflows
|
|
3
|
+
description: Multi-tool orchestration patterns for BK operations
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Advanced Bluera Knowledge Workflows
|
|
7
|
+
|
|
8
|
+
Master complex multi-tool operations that combine multiple MCP tools for efficient knowledge retrieval and management.
|
|
9
|
+
|
|
10
|
+
## Progressive Library Exploration
|
|
11
|
+
|
|
12
|
+
When exploring a new library or codebase, use this pattern for efficient discovery:
|
|
13
|
+
|
|
14
|
+
### Workflow: Find Relevant Code in Unknown Library
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
1. list_stores()
|
|
18
|
+
→ See what's indexed, identify target store
|
|
19
|
+
|
|
20
|
+
2. get_store_info(store)
|
|
21
|
+
→ Get metadata: file paths, size, indexed files
|
|
22
|
+
→ Understand scope before searching
|
|
23
|
+
|
|
24
|
+
3. search(query, detail='minimal', stores=[target])
|
|
25
|
+
→ Get high-level summaries of relevant code
|
|
26
|
+
→ Review relevance scores (>0.7 = good match)
|
|
27
|
+
|
|
28
|
+
4. get_full_context(result_ids[top_3])
|
|
29
|
+
→ Deep dive on most relevant results only
|
|
30
|
+
→ Get complete code with full context
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Example:**
|
|
34
|
+
|
|
35
|
+
User: "How does Vue's computed properties work?"
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
list_stores()
|
|
39
|
+
→ Found: vue, react, pydantic
|
|
40
|
+
|
|
41
|
+
get_store_info('vue')
|
|
42
|
+
→ Path: .bluera/bluera-knowledge/repos/vue/
|
|
43
|
+
→ Files: 2,847 indexed
|
|
44
|
+
|
|
45
|
+
search("computed properties", intent='find-implementation', detail='minimal', stores=['vue'])
|
|
46
|
+
→ Result 1: packages/reactivity/src/computed.ts (score: 0.92)
|
|
47
|
+
→ Result 2: packages/reactivity/__tests__/computed.spec.ts (score: 0.85)
|
|
48
|
+
→ Result 3: packages/runtime-core/src/apiComputed.ts (score: 0.78)
|
|
49
|
+
|
|
50
|
+
get_full_context(['result_1_id', 'result_2_id'])
|
|
51
|
+
→ Full code for ComputedRefImpl class
|
|
52
|
+
→ Complete API implementation
|
|
53
|
+
|
|
54
|
+
Now explain with authoritative source code.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Adding New Library with Job Monitoring
|
|
58
|
+
|
|
59
|
+
When adding large libraries, monitor indexing progress to know when search is ready:
|
|
60
|
+
|
|
61
|
+
### Workflow: Add Library and Wait for Index
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
1. create_store(url_or_path, name)
|
|
65
|
+
→ Returns: job_id
|
|
66
|
+
→ Background indexing starts
|
|
67
|
+
|
|
68
|
+
2. check_job_status(job_id)
|
|
69
|
+
→ Poll every 10-30 seconds
|
|
70
|
+
→ Status: 'pending' | 'running' | 'completed' | 'failed'
|
|
71
|
+
→ Progress: percentage, current file
|
|
72
|
+
|
|
73
|
+
3. When status='completed':
|
|
74
|
+
list_stores()
|
|
75
|
+
→ Verify store appears in list
|
|
76
|
+
|
|
77
|
+
4. search(query, stores=[new_store], limit=5)
|
|
78
|
+
→ Test search works
|
|
79
|
+
→ Verify indexing quality
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Example:**
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
create_store('https://github.com/fastapi/fastapi', 'fastapi')
|
|
86
|
+
→ job_id: 'job_abc123'
|
|
87
|
+
→ Status: Indexing started in background
|
|
88
|
+
|
|
89
|
+
# Poll for completion (typically 30-120 seconds for medium repos)
|
|
90
|
+
check_job_status('job_abc123')
|
|
91
|
+
→ Status: running
|
|
92
|
+
→ Progress: 45% (processing src/fastapi/routing.py)
|
|
93
|
+
|
|
94
|
+
# ... wait 30 seconds ...
|
|
95
|
+
|
|
96
|
+
check_job_status('job_abc123')
|
|
97
|
+
→ Status: completed
|
|
98
|
+
→ Indexed: 487 files, 125k lines
|
|
99
|
+
|
|
100
|
+
# Verify and test
|
|
101
|
+
list_stores()
|
|
102
|
+
→ fastapi: 487 files, vector + FTS indexed
|
|
103
|
+
|
|
104
|
+
search("dependency injection", stores=['fastapi'], limit=3)
|
|
105
|
+
→ Returns relevant FastAPI DI patterns
|
|
106
|
+
→ Store is ready for use!
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Handling Large Result Sets
|
|
110
|
+
|
|
111
|
+
When initial search returns many results, use progressive detail to avoid context overload:
|
|
112
|
+
|
|
113
|
+
### Workflow: Progressive Detail Strategy
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
1. search(query, detail='minimal', limit=20)
|
|
117
|
+
→ Get summaries only (~100 tokens/result)
|
|
118
|
+
→ Review all 20 summaries quickly
|
|
119
|
+
|
|
120
|
+
2. Filter by relevance score:
|
|
121
|
+
- Score > 0.8: Excellent match
|
|
122
|
+
- Score 0.6-0.8: Good match
|
|
123
|
+
- Score < 0.6: Possibly irrelevant
|
|
124
|
+
|
|
125
|
+
3. For top 3-5 results (score > 0.7):
|
|
126
|
+
get_full_context(selected_ids)
|
|
127
|
+
→ Fetch complete code only for relevant items
|
|
128
|
+
→ Saves ~80% context vs fetching all upfront
|
|
129
|
+
|
|
130
|
+
4. If nothing relevant:
|
|
131
|
+
search(refined_query, detail='contextual', limit=10)
|
|
132
|
+
→ Try different query with more context
|
|
133
|
+
→ Or broaden/narrow the search
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Example:**
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
# Initial broad search
|
|
140
|
+
search("authentication middleware", detail='minimal', limit=20)
|
|
141
|
+
→ 20 results, scores ranging 0.45-0.92
|
|
142
|
+
→ Total context: ~2k tokens (minimal)
|
|
143
|
+
|
|
144
|
+
# Filter by score
|
|
145
|
+
Top results (>0.7):
|
|
146
|
+
- Result 3: auth/jwt.ts (score: 0.92)
|
|
147
|
+
- Result 7: middleware/authenticate.ts (score: 0.85)
|
|
148
|
+
- Result 12: auth/session.ts (score: 0.74)
|
|
149
|
+
|
|
150
|
+
# Get full code for top 3 only
|
|
151
|
+
get_full_context(['result_3', 'result_7', 'result_12'])
|
|
152
|
+
→ Complete implementations for relevant files only
|
|
153
|
+
→ Context: ~3k tokens (vs ~15k if we fetched all 20)
|
|
154
|
+
|
|
155
|
+
# Found what we needed! If not, would refine query and retry.
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Multi-Store Search with Ranking
|
|
159
|
+
|
|
160
|
+
When searching across multiple stores, use ranking to prioritize results:
|
|
161
|
+
|
|
162
|
+
### Workflow: Cross-Library Search
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
1. search(query, limit=10)
|
|
166
|
+
→ Searches ALL stores
|
|
167
|
+
→ Returns mixed results ranked by relevance
|
|
168
|
+
|
|
169
|
+
2. Review store distribution:
|
|
170
|
+
- If dominated by one store: might narrow to specific stores
|
|
171
|
+
- If balanced: good cross-library perspective
|
|
172
|
+
|
|
173
|
+
3. For specific library focus:
|
|
174
|
+
search(query, stores=['lib1', 'lib2'], limit=15)
|
|
175
|
+
→ Search only relevant libraries
|
|
176
|
+
→ Get more results from target libraries
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Example:**
|
|
180
|
+
|
|
181
|
+
User: "How do different frameworks handle routing?"
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
# Search all indexed frameworks
|
|
185
|
+
search("routing implementation", intent='find-implementation', limit=15)
|
|
186
|
+
→ Result mix:
|
|
187
|
+
- express (score: 0.91)
|
|
188
|
+
- fastapi (score: 0.89)
|
|
189
|
+
- hono (score: 0.87)
|
|
190
|
+
- vue-router (score: 0.82)
|
|
191
|
+
- ...
|
|
192
|
+
|
|
193
|
+
# All stores represented, good comparative view!
|
|
194
|
+
|
|
195
|
+
# If user wants deeper FastAPI focus:
|
|
196
|
+
search("routing implementation", stores=['fastapi', 'starlette'], limit=20)
|
|
197
|
+
→ More FastAPI/Starlette-specific results
|
|
198
|
+
→ Deeper exploration of Python framework routing
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Error Recovery
|
|
202
|
+
|
|
203
|
+
When operations fail, use these recovery patterns:
|
|
204
|
+
|
|
205
|
+
### Workflow: Handle Indexing Failures
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
1. create_store() fails or job_status shows 'failed'
|
|
209
|
+
→ Check error message
|
|
210
|
+
→ Common issues:
|
|
211
|
+
- Git auth required (private repo)
|
|
212
|
+
- Invalid URL/path
|
|
213
|
+
- Disk space
|
|
214
|
+
- Network timeout
|
|
215
|
+
|
|
216
|
+
2. Recovery actions:
|
|
217
|
+
- Auth issue: Provide credentials or use HTTPS
|
|
218
|
+
- Invalid path: Verify URL/path exists
|
|
219
|
+
- Disk space: delete_store() unused stores
|
|
220
|
+
- Network: Retry with smaller repo or use --shallow
|
|
221
|
+
|
|
222
|
+
3. Verify recovery:
|
|
223
|
+
list_stores() → Check store appeared
|
|
224
|
+
search(test_query, stores=[new_store]) → Verify searchable
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Example:**
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
create_store('https://github.com/private/repo', 'my-repo')
|
|
231
|
+
→ job_id: 'job_xyz'
|
|
232
|
+
|
|
233
|
+
check_job_status('job_xyz')
|
|
234
|
+
→ Status: failed
|
|
235
|
+
→ Error: "Authentication required for private repository"
|
|
236
|
+
|
|
237
|
+
# Recovery: Use authenticated URL or SSH
|
|
238
|
+
create_store('git@github.com:private/repo.git', 'my-repo')
|
|
239
|
+
→ job_id: 'job_xyz2'
|
|
240
|
+
|
|
241
|
+
check_job_status('job_xyz2')
|
|
242
|
+
→ Status: completed
|
|
243
|
+
→ Success!
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Combining Workflows
|
|
247
|
+
|
|
248
|
+
Real-world usage often combines these patterns:
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
User: "I need to understand how Express and Hono handle middleware differently"
|
|
252
|
+
|
|
253
|
+
1. list_stores() → check if both indexed
|
|
254
|
+
2. If not: create_store() for missing framework(s)
|
|
255
|
+
3. check_job_status() → wait for indexing
|
|
256
|
+
4. search("middleware implementation", stores=['express', 'hono'], detail='minimal')
|
|
257
|
+
5. Review summaries, identify key files
|
|
258
|
+
6. get_full_context() for 2-3 most relevant from each framework
|
|
259
|
+
7. Compare implementations with full context
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
This multi-step workflow is efficient, targeted, and conserves context.
|
|
263
|
+
|
|
264
|
+
## Best Practices
|
|
265
|
+
|
|
266
|
+
1. **Always start with detail='minimal'** - Get summaries first, full context selectively
|
|
267
|
+
2. **Monitor background jobs** - Don't search newly added stores until indexing completes
|
|
268
|
+
3. **Use intent parameter** - Helps ranking ('find-implementation' vs 'find-pattern' vs 'find-usage')
|
|
269
|
+
4. **Filter by stores when known** - Faster, more focused results
|
|
270
|
+
5. **Check relevance scores** - >0.7 is usually a strong match, <0.5 might be noise
|
|
271
|
+
6. **Progressive refinement** - Broad search → filter → narrow → full context
|
|
272
|
+
|
|
273
|
+
These workflows reduce token usage, minimize tool calls, and get you to the right answer faster.
|