solvdex 1.0.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/LICENSE +21 -0
- package/README.md +274 -0
- package/dist/hooks/error-lookup.d.ts +4 -0
- package/dist/hooks/error-lookup.d.ts.map +1 -0
- package/dist/hooks/error-lookup.js +92 -0
- package/dist/hooks/error-lookup.js.map +1 -0
- package/dist/hooks/post-task.d.ts +15 -0
- package/dist/hooks/post-task.d.ts.map +1 -0
- package/dist/hooks/post-task.js +246 -0
- package/dist/hooks/post-task.js.map +1 -0
- package/dist/hooks/prompt-enrich.d.ts +16 -0
- package/dist/hooks/prompt-enrich.d.ts.map +1 -0
- package/dist/hooks/prompt-enrich.js +141 -0
- package/dist/hooks/prompt-enrich.js.map +1 -0
- package/dist/hooks/session-start-cli.d.ts +3 -0
- package/dist/hooks/session-start-cli.d.ts.map +1 -0
- package/dist/hooks/session-start-cli.js +81 -0
- package/dist/hooks/session-start-cli.js.map +1 -0
- package/dist/hooks/session-start.d.ts +4 -0
- package/dist/hooks/session-start.d.ts.map +1 -0
- package/dist/hooks/session-start.js +134 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/src/audit.d.ts +63 -0
- package/dist/src/audit.d.ts.map +1 -0
- package/dist/src/audit.js +229 -0
- package/dist/src/audit.js.map +1 -0
- package/dist/src/cache.d.ts +54 -0
- package/dist/src/cache.d.ts.map +1 -0
- package/dist/src/cache.js +167 -0
- package/dist/src/cache.js.map +1 -0
- package/dist/src/config.d.ts +52 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +175 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/entry.d.ts +154 -0
- package/dist/src/entry.d.ts.map +1 -0
- package/dist/src/entry.js +469 -0
- package/dist/src/entry.js.map +1 -0
- package/dist/src/errors.d.ts +65 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +121 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/frontmatter.d.ts +28 -0
- package/dist/src/frontmatter.d.ts.map +1 -0
- package/dist/src/frontmatter.js +111 -0
- package/dist/src/frontmatter.js.map +1 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +188 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/maturity.d.ts +31 -0
- package/dist/src/maturity.d.ts.map +1 -0
- package/dist/src/maturity.js +96 -0
- package/dist/src/maturity.js.map +1 -0
- package/dist/src/quality.d.ts +23 -0
- package/dist/src/quality.d.ts.map +1 -0
- package/dist/src/quality.js +236 -0
- package/dist/src/quality.js.map +1 -0
- package/dist/src/search.d.ts +35 -0
- package/dist/src/search.d.ts.map +1 -0
- package/dist/src/search.js +263 -0
- package/dist/src/search.js.map +1 -0
- package/dist/src/similarity.d.ts +42 -0
- package/dist/src/similarity.d.ts.map +1 -0
- package/dist/src/similarity.js +111 -0
- package/dist/src/similarity.js.map +1 -0
- package/dist/src/stats.d.ts +56 -0
- package/dist/src/stats.d.ts.map +1 -0
- package/dist/src/stats.js +198 -0
- package/dist/src/stats.js.map +1 -0
- package/dist/src/templates.d.ts +63 -0
- package/dist/src/templates.d.ts.map +1 -0
- package/dist/src/templates.js +347 -0
- package/dist/src/templates.js.map +1 -0
- package/dist/src/transfer.d.ts +92 -0
- package/dist/src/transfer.d.ts.map +1 -0
- package/dist/src/transfer.js +215 -0
- package/dist/src/transfer.js.map +1 -0
- package/dist/src/types.d.ts +270 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +153 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/validate.d.ts +90 -0
- package/dist/src/validate.d.ts.map +1 -0
- package/dist/src/validate.js +295 -0
- package/dist/src/validate.js.map +1 -0
- package/hooks/error-lookup.ts +110 -0
- package/hooks/hooks.json +49 -0
- package/hooks/post-task.ts +309 -0
- package/hooks/prompt-enrich.ts +162 -0
- package/hooks/session-start-cli.ts +96 -0
- package/hooks/session-start.ts +159 -0
- package/package.json +40 -0
- package/scripts/error-lookup.py +64 -0
- package/scripts/post-task.py +60 -0
- package/scripts/prompt-enrich.py +64 -0
- package/scripts/session-start.py +64 -0
- package/skills/wiki/SKILL.md +61 -0
- package/skills/wiki-add/SKILL.md +90 -0
- package/skills/wiki-browse/SKILL.md +108 -0
- package/skills/wiki-capture/SKILL.md +265 -0
- package/skills/wiki-explorer/SKILL.md +223 -0
- package/skills/wiki-export/SKILL.md +101 -0
- package/skills/wiki-fix/SKILL.md +86 -0
- package/skills/wiki-flag/SKILL.md +47 -0
- package/skills/wiki-import/SKILL.md +128 -0
- package/skills/wiki-init/SKILL.md +72 -0
- package/skills/wiki-scan/SKILL.md +98 -0
- package/skills/wiki-search/SKILL.md +86 -0
- package/skills/wiki-stats/SKILL.md +129 -0
- package/skills/wiki-status/SKILL.md +78 -0
- package/skills/wiki-test-trigger/SKILL.md +173 -0
- package/skills/wiki-validate/SKILL.md +62 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wiki-browse
|
|
3
|
+
description: List and filter Solvdex wiki entries. Use to see all available knowledge organized by category.
|
|
4
|
+
argument-hint: [--category=<cat>] [--status=<status>] [--tag=<tag>]
|
|
5
|
+
user-invocable: true
|
|
6
|
+
disable-model-invocation: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Browse Solvdex Entries
|
|
10
|
+
|
|
11
|
+
List all wiki entries with optional filtering.
|
|
12
|
+
|
|
13
|
+
## Process
|
|
14
|
+
|
|
15
|
+
1. Read all entries from `.wiki/`
|
|
16
|
+
2. Apply filters (category, status, tag)
|
|
17
|
+
3. Group by category
|
|
18
|
+
4. Display summary
|
|
19
|
+
|
|
20
|
+
## Categories
|
|
21
|
+
|
|
22
|
+
| Category | Purpose |
|
|
23
|
+
|----------|---------|
|
|
24
|
+
| issues | Bug fixes, error solutions |
|
|
25
|
+
| patterns | Reusable code patterns |
|
|
26
|
+
| gotchas | Pitfalls, traps |
|
|
27
|
+
| testing | Test strategies, mocks |
|
|
28
|
+
| docs | Documentation templates |
|
|
29
|
+
| security | Auth, vulnerabilities |
|
|
30
|
+
| performance | Optimizations, profiling |
|
|
31
|
+
|
|
32
|
+
## Implementation
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { listEntries, wikiExists, DEFAULT_CATEGORIES } from 'solvdex';
|
|
36
|
+
|
|
37
|
+
const projectRoot = process.cwd();
|
|
38
|
+
|
|
39
|
+
if (!wikiExists(projectRoot)) {
|
|
40
|
+
console.log('No wiki found. Run `/wiki init` first.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const entries = listEntries(projectRoot, {
|
|
45
|
+
category: args.category,
|
|
46
|
+
status: args.status,
|
|
47
|
+
tags: args.tag ? [args.tag] : undefined
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (entries.length === 0) {
|
|
51
|
+
console.log('No entries found.');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Group by category
|
|
56
|
+
const byCategory: Record<string, typeof entries> = {};
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
if (!byCategory[entry.category]) {
|
|
59
|
+
byCategory[entry.category] = [];
|
|
60
|
+
}
|
|
61
|
+
byCategory[entry.category].push(entry);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(`Found ${entries.length} entries:\n`);
|
|
65
|
+
|
|
66
|
+
for (const category of DEFAULT_CATEGORIES) {
|
|
67
|
+
const items = byCategory[category];
|
|
68
|
+
if (!items || items.length === 0) continue;
|
|
69
|
+
|
|
70
|
+
console.log(`## ${category}/ (${items.length})`);
|
|
71
|
+
for (const entry of items) {
|
|
72
|
+
const status = entry.frontmatter.status === 'active' ? '' : ` [${entry.frontmatter.status}]`;
|
|
73
|
+
const conf = entry.frontmatter.confidence;
|
|
74
|
+
console.log(` - ${entry.frontmatter.title}${status} (${conf})`);
|
|
75
|
+
}
|
|
76
|
+
console.log('');
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Output
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Found 12 entries:
|
|
84
|
+
|
|
85
|
+
## issues/ (4)
|
|
86
|
+
- Auth Token Expiration Fix (80)
|
|
87
|
+
- Database Connection Timeout (50)
|
|
88
|
+
- NPM Permission Error [flagged] (60)
|
|
89
|
+
- Type Casting Bug (20)
|
|
90
|
+
|
|
91
|
+
## patterns/ (3)
|
|
92
|
+
- API Retry Pattern (80)
|
|
93
|
+
- React Hook Pattern (70)
|
|
94
|
+
- Error Boundary Pattern (50)
|
|
95
|
+
|
|
96
|
+
## gotchas/ (1)
|
|
97
|
+
- Environment Variable Gotcha (60)
|
|
98
|
+
|
|
99
|
+
## testing/ (2)
|
|
100
|
+
- Mock Database Strategy (70)
|
|
101
|
+
- E2E Test Setup (50)
|
|
102
|
+
|
|
103
|
+
## security/ (1)
|
|
104
|
+
- JWT Token Validation (80)
|
|
105
|
+
|
|
106
|
+
## performance/ (1)
|
|
107
|
+
- Query Optimization Pattern (60)
|
|
108
|
+
```
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wiki-capture
|
|
3
|
+
description: Intelligent agent that analyzes conversation context and extracts knowledge worth capturing as wiki entries.
|
|
4
|
+
argument-hint: [--category=<cat>] [--title=<title>] [--dry-run]
|
|
5
|
+
context: fork
|
|
6
|
+
agent: general-purpose
|
|
7
|
+
user-invocable: true
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
allowed-tools: Read, Write, Glob, Grep
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Wiki Capture Agent
|
|
13
|
+
|
|
14
|
+
An intelligent agent that analyzes the current conversation context, extracts valuable knowledge, and creates well-structured wiki entries.
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
- After solving a bug or error
|
|
19
|
+
- After implementing a pattern or approach
|
|
20
|
+
- After discovering a gotcha or pitfall
|
|
21
|
+
- After writing tests with useful patterns
|
|
22
|
+
- After configuring security or performance optimizations
|
|
23
|
+
- When user says "save this", "remember this", "document this"
|
|
24
|
+
|
|
25
|
+
## Agent Behavior
|
|
26
|
+
|
|
27
|
+
This agent will:
|
|
28
|
+
|
|
29
|
+
1. **Analyze conversation context** to identify:
|
|
30
|
+
- Problems encountered and their solutions
|
|
31
|
+
- Patterns or approaches used
|
|
32
|
+
- Gotchas discovered
|
|
33
|
+
- Code changes made
|
|
34
|
+
- Files modified
|
|
35
|
+
|
|
36
|
+
2. **Determine the best category** based on content:
|
|
37
|
+
- `issues` - Bug fixes, error solutions
|
|
38
|
+
- `patterns` - Reusable approaches
|
|
39
|
+
- `gotchas` - Pitfalls to avoid
|
|
40
|
+
- `testing` - Test strategies
|
|
41
|
+
- `docs` - Documentation guides
|
|
42
|
+
- `security` - Auth, vulnerabilities
|
|
43
|
+
- `performance` - Optimizations
|
|
44
|
+
|
|
45
|
+
3. **Extract structured content**:
|
|
46
|
+
- Title (concise, searchable)
|
|
47
|
+
- Tags (for discovery)
|
|
48
|
+
- Trigger pattern (for errors)
|
|
49
|
+
- Problem/Solution sections
|
|
50
|
+
- Related files
|
|
51
|
+
|
|
52
|
+
4. **Check for duplicates** before creating
|
|
53
|
+
|
|
54
|
+
5. **Create the entry** with proper confidence level
|
|
55
|
+
|
|
56
|
+
## Options
|
|
57
|
+
|
|
58
|
+
- `--category=<cat>` - Override auto-detected category
|
|
59
|
+
- `--title=<title>` - Override auto-generated title
|
|
60
|
+
- `--confidence=<0-100>` - Set confidence level (default: 50)
|
|
61
|
+
- `--dry-run` - Preview without creating
|
|
62
|
+
|
|
63
|
+
## Implementation
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// Agent: wiki-capture
|
|
67
|
+
// Tools: Read, Write, Glob, Grep
|
|
68
|
+
|
|
69
|
+
import {
|
|
70
|
+
wikiExists,
|
|
71
|
+
createEntryWithValidation,
|
|
72
|
+
checkDuplicate,
|
|
73
|
+
generateStubContent,
|
|
74
|
+
CATEGORY_TEMPLATES
|
|
75
|
+
} from 'solvdex';
|
|
76
|
+
|
|
77
|
+
const projectRoot = process.cwd();
|
|
78
|
+
const args = $ARGUMENTS.split(' ').filter(Boolean);
|
|
79
|
+
|
|
80
|
+
// Parse options
|
|
81
|
+
const categoryOverride = args.find(a => a.startsWith('--category='))?.split('=')[1];
|
|
82
|
+
const titleOverride = args.find(a => a.startsWith('--title='))?.split('=')[1];
|
|
83
|
+
const confidenceOverride = args.find(a => a.startsWith('--confidence='))?.split('=')[1];
|
|
84
|
+
const dryRun = args.includes('--dry-run');
|
|
85
|
+
|
|
86
|
+
if (!wikiExists(projectRoot)) {
|
|
87
|
+
console.log('No wiki found. Run `/wiki init` first.');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log('# Wiki Capture Agent\n');
|
|
92
|
+
|
|
93
|
+
// Analyze conversation context (this is provided by Claude Code)
|
|
94
|
+
const context = getConversationContext(); // Context comes from Claude
|
|
95
|
+
|
|
96
|
+
if (!context || !context.recentMessages) {
|
|
97
|
+
console.log('No conversation context available.');
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log('**Usage:**');
|
|
100
|
+
console.log('Run this after solving a problem or implementing something worth remembering.');
|
|
101
|
+
console.log('');
|
|
102
|
+
console.log('**Manual capture:**');
|
|
103
|
+
console.log('```');
|
|
104
|
+
console.log('/wiki add --category=issues --title="My Solution"');
|
|
105
|
+
console.log('```');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log('## Analyzing Conversation...\n');
|
|
110
|
+
|
|
111
|
+
// Extract signals from context
|
|
112
|
+
const signals = analyzeContext(context);
|
|
113
|
+
|
|
114
|
+
console.log(`**Detected signals:**`);
|
|
115
|
+
for (const signal of signals) {
|
|
116
|
+
console.log(`- ${signal.type}: ${signal.description}`);
|
|
117
|
+
}
|
|
118
|
+
console.log('');
|
|
119
|
+
|
|
120
|
+
// Determine category
|
|
121
|
+
const category = categoryOverride || detectCategory(signals, context);
|
|
122
|
+
console.log(`**Category:** ${category}\n`);
|
|
123
|
+
|
|
124
|
+
// Generate title
|
|
125
|
+
const title = titleOverride || generateTitle(signals, context);
|
|
126
|
+
console.log(`**Title:** ${title}\n`);
|
|
127
|
+
|
|
128
|
+
// Extract tags
|
|
129
|
+
const tags = extractTags(signals, context);
|
|
130
|
+
console.log(`**Tags:** ${tags.join(', ')}\n`);
|
|
131
|
+
|
|
132
|
+
// Check for duplicates
|
|
133
|
+
const dupCheck = await checkDuplicate(projectRoot, title, tags, category);
|
|
134
|
+
if (dupCheck.isDuplicate) {
|
|
135
|
+
console.log(`## Duplicate Detected\n`);
|
|
136
|
+
console.log(`Similar entry exists: "${dupCheck.matchedEntry.frontmatter.title}"`);
|
|
137
|
+
console.log(`Path: ${dupCheck.matchedEntry.path}`);
|
|
138
|
+
console.log(`Similarity: ${Math.round(dupCheck.similarity * 100)}%`);
|
|
139
|
+
console.log('');
|
|
140
|
+
console.log('**Options:**');
|
|
141
|
+
console.log('- Use `/wiki fix <path>` to update the existing entry');
|
|
142
|
+
console.log('- Use `--title="Different Title"` to create anyway');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Generate content structure
|
|
147
|
+
const content = generateContent(category, signals, context);
|
|
148
|
+
|
|
149
|
+
console.log('## Generated Content\n');
|
|
150
|
+
console.log('```markdown');
|
|
151
|
+
for (const [section, text] of Object.entries(content)) {
|
|
152
|
+
console.log(`# ${section}\n`);
|
|
153
|
+
console.log(text);
|
|
154
|
+
console.log('');
|
|
155
|
+
}
|
|
156
|
+
console.log('```\n');
|
|
157
|
+
|
|
158
|
+
// Extract trigger pattern if it's an error fix
|
|
159
|
+
let trigger = undefined;
|
|
160
|
+
if (category === 'issues' && signals.some(s => s.type === 'error')) {
|
|
161
|
+
trigger = extractTriggerPattern(signals);
|
|
162
|
+
if (trigger) {
|
|
163
|
+
console.log(`**Trigger pattern:** \`${trigger}\`\n`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Set confidence
|
|
168
|
+
const confidence = confidenceOverride ? parseInt(confidenceOverride) : 50;
|
|
169
|
+
|
|
170
|
+
if (dryRun) {
|
|
171
|
+
console.log('## Dry Run - No Entry Created\n');
|
|
172
|
+
console.log('Remove `--dry-run` to create the entry.');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Create the entry
|
|
177
|
+
console.log('## Creating Entry...\n');
|
|
178
|
+
|
|
179
|
+
const result = await createEntryWithValidation(projectRoot, {
|
|
180
|
+
category,
|
|
181
|
+
title,
|
|
182
|
+
tags,
|
|
183
|
+
content,
|
|
184
|
+
trigger,
|
|
185
|
+
confidence,
|
|
186
|
+
autoCapture: true,
|
|
187
|
+
context: 'Captured via /wiki capture agent'
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
console.log(`Entry created: **${result.entry.path}**`);
|
|
191
|
+
console.log(`Confidence: ${confidence}`);
|
|
192
|
+
|
|
193
|
+
if (result.qualityIssues.length > 0) {
|
|
194
|
+
console.log('\n**Quality suggestions:**');
|
|
195
|
+
for (const issue of result.qualityIssues) {
|
|
196
|
+
console.log(`- ${issue.message}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
console.log('\n---');
|
|
201
|
+
console.log('Use `/wiki browse` to see all entries');
|
|
202
|
+
console.log('Use `/wiki fix <path>` to improve it');
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Output Example
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
# Wiki Capture Agent
|
|
209
|
+
|
|
210
|
+
## Analyzing Conversation...
|
|
211
|
+
|
|
212
|
+
**Detected signals:**
|
|
213
|
+
- error_resolved: Fixed: ETIMEDOUT connecting to database...
|
|
214
|
+
- code_changed: Modified 2 files
|
|
215
|
+
- user_confirmed: User confirmed solution works
|
|
216
|
+
|
|
217
|
+
**Category:** issues
|
|
218
|
+
|
|
219
|
+
**Title:** Fix: ETIMEDOUT connecting to database
|
|
220
|
+
|
|
221
|
+
**Tags:** ts, js, auto-captured
|
|
222
|
+
|
|
223
|
+
## Generated Content
|
|
224
|
+
|
|
225
|
+
```markdown
|
|
226
|
+
# Problem
|
|
227
|
+
|
|
228
|
+
ETIMEDOUT connecting to database at 10.0.0.1:5432
|
|
229
|
+
|
|
230
|
+
# Cause
|
|
231
|
+
|
|
232
|
+
Connection pool exhausted due to unclosed connections.
|
|
233
|
+
|
|
234
|
+
# Solution
|
|
235
|
+
|
|
236
|
+
TODO: Fill in details
|
|
237
|
+
|
|
238
|
+
# Prevention
|
|
239
|
+
|
|
240
|
+
TODO: Fill in details
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Trigger pattern:** `ETIMEDOUT.*database`
|
|
244
|
+
|
|
245
|
+
## Creating Entry...
|
|
246
|
+
|
|
247
|
+
Entry created: **issues/fix-etimedout-connecting-to-database.md**
|
|
248
|
+
Confidence: 50
|
|
249
|
+
|
|
250
|
+
**Quality suggestions:**
|
|
251
|
+
- Solution section needs more detail
|
|
252
|
+
- Consider adding code examples
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
Use `/wiki browse` to see all entries
|
|
256
|
+
Use `/wiki fix <path>` to improve it
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Auto-Capture Integration
|
|
260
|
+
|
|
261
|
+
This agent is automatically triggered by the `Stop` hook when:
|
|
262
|
+
- An error was resolved during the session
|
|
263
|
+
- User explicitly confirms solution works
|
|
264
|
+
- User says "save to wiki" or "remember this"
|
|
265
|
+
- Workaround/HACK comments are added to code
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wiki-explorer
|
|
3
|
+
description: Deep search agent that explores wiki entries to find relevant knowledge for a given context or question.
|
|
4
|
+
argument-hint: <query>
|
|
5
|
+
context: fork
|
|
6
|
+
agent: Explore
|
|
7
|
+
allowed-tools: Read, Glob, Grep
|
|
8
|
+
user-invocable: true
|
|
9
|
+
disable-model-invocation: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Wiki Explorer Agent
|
|
13
|
+
|
|
14
|
+
An intelligent agent that deeply searches the Solvdex wiki to find relevant knowledge entries for a given question or context.
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
- Before answering questions about the codebase
|
|
19
|
+
- When troubleshooting errors
|
|
20
|
+
- When implementing features that may have existing patterns
|
|
21
|
+
- When uncertain about conventions or gotchas
|
|
22
|
+
|
|
23
|
+
## Agent Behavior
|
|
24
|
+
|
|
25
|
+
This agent will:
|
|
26
|
+
|
|
27
|
+
1. **Analyze the query** to understand intent and extract keywords
|
|
28
|
+
2. **Search across all categories** using multiple strategies:
|
|
29
|
+
- Full-text search on titles and content
|
|
30
|
+
- Tag matching
|
|
31
|
+
- Trigger pattern matching for errors
|
|
32
|
+
- Related entry discovery
|
|
33
|
+
3. **Rank and filter results** by relevance and confidence
|
|
34
|
+
4. **Present a summary** with actionable information
|
|
35
|
+
|
|
36
|
+
## Implementation
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// Agent: wiki-explorer
|
|
40
|
+
// Tools: Read, Glob, Grep
|
|
41
|
+
|
|
42
|
+
import { wikiExists, searchWiki, listEntries, matchTrigger, getBestMatch } from 'solvdex';
|
|
43
|
+
|
|
44
|
+
const projectRoot = process.cwd();
|
|
45
|
+
const query = $ARGUMENTS;
|
|
46
|
+
|
|
47
|
+
if (!query) {
|
|
48
|
+
console.log('Usage: /wiki explore <query>');
|
|
49
|
+
console.log('');
|
|
50
|
+
console.log('Examples:');
|
|
51
|
+
console.log(' /wiki explore database connection timeout');
|
|
52
|
+
console.log(' /wiki explore how to handle authentication');
|
|
53
|
+
console.log(' /wiki explore Error: ECONNREFUSED');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!wikiExists(projectRoot)) {
|
|
58
|
+
console.log('No wiki found. Run `/wiki init` first.');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(`# Wiki Explorer\n`);
|
|
63
|
+
console.log(`Query: "${query}"\n`);
|
|
64
|
+
|
|
65
|
+
// Strategy 1: Full-text search
|
|
66
|
+
const searchResults = await searchWiki(projectRoot, { query });
|
|
67
|
+
|
|
68
|
+
// Strategy 2: Check if query looks like an error (try trigger matching)
|
|
69
|
+
const isErrorLike = /error|exception|failed|cannot|unable/i.test(query);
|
|
70
|
+
let triggerResults = [];
|
|
71
|
+
if (isErrorLike) {
|
|
72
|
+
triggerResults = await matchTrigger(projectRoot, query);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Strategy 3: Search by category keywords
|
|
76
|
+
const categoryKeywords = {
|
|
77
|
+
issues: ['error', 'fix', 'bug', 'broken', 'fails'],
|
|
78
|
+
patterns: ['pattern', 'template', 'how to', 'approach'],
|
|
79
|
+
gotchas: ['careful', 'avoid', 'pitfall', 'watch out'],
|
|
80
|
+
testing: ['test', 'mock', 'fixture', 'spec'],
|
|
81
|
+
security: ['auth', 'token', 'permission', 'vulnerability'],
|
|
82
|
+
performance: ['slow', 'optimize', 'memory', 'latency']
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const relevantCategories = [];
|
|
86
|
+
const queryLower = query.toLowerCase();
|
|
87
|
+
for (const [category, keywords] of Object.entries(categoryKeywords)) {
|
|
88
|
+
if (keywords.some(kw => queryLower.includes(kw))) {
|
|
89
|
+
relevantCategories.push(category);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Combine and deduplicate results
|
|
94
|
+
const seen = new Set();
|
|
95
|
+
const allResults = [];
|
|
96
|
+
|
|
97
|
+
// Add trigger matches first (highest priority for errors)
|
|
98
|
+
for (const result of triggerResults) {
|
|
99
|
+
if (!seen.has(result.entry.path)) {
|
|
100
|
+
seen.add(result.entry.path);
|
|
101
|
+
allResults.push({ ...result, source: 'trigger' });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add search results
|
|
106
|
+
for (const result of searchResults) {
|
|
107
|
+
if (!seen.has(result.entry.path)) {
|
|
108
|
+
seen.add(result.entry.path);
|
|
109
|
+
allResults.push({ ...result, source: 'search' });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Output results
|
|
114
|
+
if (allResults.length === 0) {
|
|
115
|
+
console.log('## No Results Found\n');
|
|
116
|
+
console.log('No wiki entries match your query.\n');
|
|
117
|
+
|
|
118
|
+
if (relevantCategories.length > 0) {
|
|
119
|
+
console.log(`**Suggested categories to check:** ${relevantCategories.join(', ')}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log('\n**Tips:**');
|
|
123
|
+
console.log('- Try different keywords');
|
|
124
|
+
console.log('- Use `/wiki browse` to see all entries');
|
|
125
|
+
console.log('- Use `/wiki scan` to generate stubs from your project');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log(`## Found ${allResults.length} Relevant Entries\n`);
|
|
130
|
+
|
|
131
|
+
// Show top results with details
|
|
132
|
+
for (const result of allResults.slice(0, 5)) {
|
|
133
|
+
const entry = result.entry;
|
|
134
|
+
const fm = entry.frontmatter;
|
|
135
|
+
|
|
136
|
+
console.log(`### ${fm.title}`);
|
|
137
|
+
console.log(`- **Category:** ${entry.category}`);
|
|
138
|
+
console.log(`- **Confidence:** ${fm.confidence}`);
|
|
139
|
+
console.log(`- **Tags:** ${fm.tags.join(', ') || 'none'}`);
|
|
140
|
+
console.log(`- **Path:** ${entry.path}`);
|
|
141
|
+
|
|
142
|
+
if (result.source === 'trigger') {
|
|
143
|
+
console.log(`- **Match:** Trigger pattern matched`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Extract and show summary (first 150 chars of content after frontmatter)
|
|
147
|
+
const contentPreview = entry.content
|
|
148
|
+
.replace(/^#.*$/gm, '') // Remove headings
|
|
149
|
+
.trim()
|
|
150
|
+
.slice(0, 150);
|
|
151
|
+
|
|
152
|
+
if (contentPreview) {
|
|
153
|
+
console.log(`\n> ${contentPreview}...`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.log('');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Show additional results count
|
|
160
|
+
if (allResults.length > 5) {
|
|
161
|
+
console.log(`\n*... and ${allResults.length - 5} more entries*`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Suggest related categories
|
|
165
|
+
if (relevantCategories.length > 0) {
|
|
166
|
+
console.log(`\n## Related Categories`);
|
|
167
|
+
console.log(`Consider also checking: ${relevantCategories.join(', ')}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
console.log('\n---');
|
|
171
|
+
console.log('Use `/wiki search <query>` for simple search');
|
|
172
|
+
console.log('Use `/wiki browse` to view entries by category');
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Output Example
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
# Wiki Explorer
|
|
179
|
+
|
|
180
|
+
Query: "database connection timeout"
|
|
181
|
+
|
|
182
|
+
## Found 3 Relevant Entries
|
|
183
|
+
|
|
184
|
+
### Database Connection Timeout Fix
|
|
185
|
+
- **Category:** issues
|
|
186
|
+
- **Confidence:** 85
|
|
187
|
+
- **Tags:** database, timeout, postgres
|
|
188
|
+
- **Path:** issues/database-connection-timeout.md
|
|
189
|
+
- **Match:** Trigger pattern matched
|
|
190
|
+
|
|
191
|
+
> When connecting to PostgreSQL, timeouts can occur due to network issues
|
|
192
|
+
> or connection pool exhaustion. The default timeout of 30s may be...
|
|
193
|
+
|
|
194
|
+
### Connection Pool Best Practices
|
|
195
|
+
- **Category:** patterns
|
|
196
|
+
- **Confidence:** 80
|
|
197
|
+
- **Tags:** database, connection-pool
|
|
198
|
+
- **Path:** patterns/connection-pool-best-practices.md
|
|
199
|
+
|
|
200
|
+
> Always configure your connection pool size based on your workload...
|
|
201
|
+
|
|
202
|
+
### Database Configuration Gotchas
|
|
203
|
+
- **Category:** gotchas
|
|
204
|
+
- **Confidence:** 75
|
|
205
|
+
- **Tags:** database, config
|
|
206
|
+
- **Path:** gotchas/database-config-gotchas.md
|
|
207
|
+
|
|
208
|
+
> Watch out for these common database configuration mistakes...
|
|
209
|
+
|
|
210
|
+
## Related Categories
|
|
211
|
+
Consider also checking: issues, performance
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
Use `/wiki search <query>` for simple search
|
|
215
|
+
Use `/wiki browse` to view entries by category
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Integration
|
|
219
|
+
|
|
220
|
+
This agent is automatically invoked by hooks when:
|
|
221
|
+
- Session starts with relevant task description
|
|
222
|
+
- Errors are encountered (via PostToolUseFailure hook)
|
|
223
|
+
- Prompts contain wiki-related keywords
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wiki-export
|
|
3
|
+
description: Export Solvdex wiki to a portable JSON file for backup or migration.
|
|
4
|
+
argument-hint: [output-file] [--categories=cat1,cat2] [--include-deprecated]
|
|
5
|
+
user-invocable: true
|
|
6
|
+
disable-model-invocation: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Solvdex Export
|
|
10
|
+
|
|
11
|
+
Export wiki entries to a portable JSON format for backup or migration.
|
|
12
|
+
|
|
13
|
+
## Options
|
|
14
|
+
|
|
15
|
+
- `output-file`: Output file path (default: `wiki-export.json`)
|
|
16
|
+
- `--categories=cat1,cat2`: Only export specific categories
|
|
17
|
+
- `--include-deprecated`: Include deprecated entries
|
|
18
|
+
|
|
19
|
+
## Implementation
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { wikiExists, exportWikiToFile } from 'solvdex';
|
|
23
|
+
import * as path from 'path';
|
|
24
|
+
|
|
25
|
+
const projectRoot = process.cwd();
|
|
26
|
+
const args = $ARGUMENTS.split(' ').filter(Boolean);
|
|
27
|
+
|
|
28
|
+
if (!wikiExists(projectRoot)) {
|
|
29
|
+
console.log('No wiki found. Run `/wiki init` first.');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Parse args
|
|
34
|
+
const outputFile = args.find(a => !a.startsWith('--')) || 'wiki-export.json';
|
|
35
|
+
const categoriesArg = args.find(a => a.startsWith('--categories='));
|
|
36
|
+
const includeDeprecated = args.includes('--include-deprecated');
|
|
37
|
+
|
|
38
|
+
const categories = categoriesArg
|
|
39
|
+
? categoriesArg.replace('--categories=', '').split(',')
|
|
40
|
+
: undefined;
|
|
41
|
+
|
|
42
|
+
const outputPath = path.isAbsolute(outputFile)
|
|
43
|
+
? outputFile
|
|
44
|
+
: path.join(projectRoot, outputFile);
|
|
45
|
+
|
|
46
|
+
console.log('# Solvdex Export\n');
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await exportWikiToFile(projectRoot, outputPath, {
|
|
50
|
+
categories,
|
|
51
|
+
includeDeprecated
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.log(`Exported to: ${outputPath}`);
|
|
55
|
+
|
|
56
|
+
if (categories) {
|
|
57
|
+
console.log(`Categories: ${categories.join(', ')}`);
|
|
58
|
+
}
|
|
59
|
+
console.log(`Include deprecated: ${includeDeprecated}`);
|
|
60
|
+
console.log('\nExport complete!');
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(`Export failed: ${error.message}`);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Output
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
# Solvdex Export
|
|
70
|
+
|
|
71
|
+
Exported to: /path/to/project/wiki-export.json
|
|
72
|
+
Categories: all
|
|
73
|
+
Include deprecated: false
|
|
74
|
+
|
|
75
|
+
Export complete!
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Export Format
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"version": "1.0.0",
|
|
83
|
+
"exportedAt": "2025-01-20T10:30:00Z",
|
|
84
|
+
"projectName": "my-project",
|
|
85
|
+
"config": { ... },
|
|
86
|
+
"entries": [
|
|
87
|
+
{
|
|
88
|
+
"path": "issues/database-timeout.md",
|
|
89
|
+
"category": "issues",
|
|
90
|
+
"frontmatter": {
|
|
91
|
+
"title": "Database Connection Timeout",
|
|
92
|
+
"created": "2025-01-15",
|
|
93
|
+
"status": "active",
|
|
94
|
+
"confidence": 80,
|
|
95
|
+
"tags": ["database", "timeout"]
|
|
96
|
+
},
|
|
97
|
+
"content": "# Problem\n..."
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
```
|