opencode stuff
This commit is contained in:
123
profiles/opencode/skill/librarian/SKILL.md
Normal file
123
profiles/opencode/skill/librarian/SKILL.md
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
name: librarian
|
||||
description: Multi-repository codebase exploration. Research library internals, find code patterns, understand architecture, compare implementations across GitHub/npm/PyPI/crates. Use when needing deep understanding of how libraries work, finding implementations across open source, or exploring remote repository structure.
|
||||
references:
|
||||
- references/tool-routing.md
|
||||
- references/opensrc-api.md
|
||||
- references/opensrc-examples.md
|
||||
- references/linking.md
|
||||
- references/diagrams.md
|
||||
---
|
||||
|
||||
# Librarian Skill
|
||||
|
||||
Deep codebase exploration across remote repositories.
|
||||
|
||||
## How to Use This Skill
|
||||
|
||||
### Reference Structure
|
||||
|
||||
| File | Purpose | When to Read |
|
||||
|------|---------|--------------|
|
||||
| `tool-routing.md` | Tool selection decision trees | **Always read first** |
|
||||
| `opensrc-api.md` | API reference, types | Writing opensrc code |
|
||||
| `opensrc-examples.md` | JavaScript patterns, workflows | Implementation examples |
|
||||
| `linking.md` | GitHub URL patterns | Formatting responses |
|
||||
| `diagrams.md` | Mermaid patterns | Visualizing architecture |
|
||||
|
||||
### Reading Order
|
||||
|
||||
1. **Start** with `tool-routing.md` → choose tool strategy
|
||||
2. **If using opensrc:**
|
||||
- Read `opensrc-api.md` for API details
|
||||
- Read `opensrc-examples.md` for patterns
|
||||
3. **Before responding:** `linking.md` + `diagrams.md` for output formatting
|
||||
|
||||
## Tool Arsenal
|
||||
|
||||
| Tool | Best For | Limitations |
|
||||
|------|----------|-------------|
|
||||
| **grep_app** | Find patterns across ALL public GitHub | Literal search only |
|
||||
| **context7** | Library docs, API examples, usage | Known libraries only |
|
||||
| **opensrc** | Fetch full source for deep exploration | Must fetch before read |
|
||||
|
||||
## Quick Decision Trees
|
||||
|
||||
### "How does X work?"
|
||||
|
||||
```
|
||||
Known library?
|
||||
├─ Yes → context7.resolve-library-id → context7.query-docs
|
||||
│ └─ Need internals? → opensrc.fetch → read source
|
||||
└─ No → grep_app search → opensrc.fetch top result
|
||||
```
|
||||
|
||||
### "Find pattern X"
|
||||
|
||||
```
|
||||
Specific repo?
|
||||
├─ Yes → opensrc.fetch → opensrc.grep → read matches
|
||||
└─ No → grep_app (broad) → opensrc.fetch interesting repos
|
||||
```
|
||||
|
||||
### "Explore repo structure"
|
||||
|
||||
```
|
||||
1. opensrc.fetch(target)
|
||||
2. opensrc.tree(source.name) → quick overview
|
||||
3. opensrc.files(source.name, "**/*.ts") → detailed listing
|
||||
4. Read: README, package.json, src/index.*
|
||||
5. Create architecture diagram (see diagrams.md)
|
||||
```
|
||||
|
||||
### "Compare X vs Y"
|
||||
|
||||
```
|
||||
1. opensrc.fetch(["X", "Y"])
|
||||
2. Use source.name from results for subsequent calls
|
||||
3. opensrc.grep(pattern, { sources: [nameX, nameY] })
|
||||
4. Read comparable files, synthesize differences
|
||||
```
|
||||
|
||||
## Critical: Source Naming Convention
|
||||
|
||||
**After fetching, always use `source.name` for subsequent calls:**
|
||||
|
||||
```javascript
|
||||
const [{ source }] = await opensrc.fetch("vercel/ai");
|
||||
const files = await opensrc.files(source.name, "**/*.ts");
|
||||
```
|
||||
|
||||
| Type | Fetch Spec | Source Name |
|
||||
|------|------------|-------------|
|
||||
| npm | `"zod"` | `"zod"` |
|
||||
| npm scoped | `"@tanstack/react-query"` | `"@tanstack/react-query"` |
|
||||
| pypi | `"pypi:requests"` | `"requests"` |
|
||||
| crates | `"crates:serde"` | `"serde"` |
|
||||
| GitHub | `"vercel/ai"` | `"github.com/vercel/ai"` |
|
||||
| GitLab | `"gitlab:org/repo"` | `"gitlab.com/org/repo"` |
|
||||
|
||||
## When NOT to Use opensrc
|
||||
|
||||
| Scenario | Use Instead |
|
||||
|----------|-------------|
|
||||
| Simple library API questions | context7 |
|
||||
| Finding examples across many repos | grep_app |
|
||||
| Very large monorepos (>10GB) | Clone locally |
|
||||
| Private repositories | Direct access |
|
||||
|
||||
## Output Guidelines
|
||||
|
||||
1. **Comprehensive final message** - only last message returns to main agent
|
||||
2. **Parallel tool calls** - maximize efficiency
|
||||
3. **Link every file reference** - see `linking.md`
|
||||
4. **Diagram complex relationships** - see `diagrams.md`
|
||||
5. **Never mention tool names** - say "I'll search" not "I'll use opensrc"
|
||||
|
||||
## References
|
||||
|
||||
- [Tool Routing Decision Trees](references/tool-routing.md)
|
||||
- [opensrc API Reference](references/opensrc-api.md)
|
||||
- [opensrc Code Examples](references/opensrc-examples.md)
|
||||
- [GitHub Linking Patterns](references/linking.md)
|
||||
- [Mermaid Diagram Patterns](references/diagrams.md)
|
||||
51
profiles/opencode/skill/librarian/references/diagrams.md
Normal file
51
profiles/opencode/skill/librarian/references/diagrams.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Mermaid Diagram Patterns
|
||||
|
||||
Create diagrams for:
|
||||
- Architecture (component relationships)
|
||||
- Data flow (request → response)
|
||||
- Dependencies (import graph)
|
||||
- Sequences (step-by-step processes)
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Client] --> B[API Gateway]
|
||||
B --> C[Auth Service]
|
||||
B --> D[Data Service]
|
||||
D --> E[(Database)]
|
||||
```
|
||||
|
||||
## Flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Input --> Parse --> Validate --> Transform --> Output
|
||||
```
|
||||
|
||||
## Sequence
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
Client->>+Server: Request
|
||||
Server->>+DB: Query
|
||||
DB-->>-Server: Result
|
||||
Server-->>-Client: Response
|
||||
```
|
||||
|
||||
## When to Use
|
||||
|
||||
| Type | Use For |
|
||||
|------|---------|
|
||||
| `graph TD` | Component hierarchy, dependencies |
|
||||
| `flowchart LR` | Data transformation, pipelines |
|
||||
| `sequenceDiagram` | Request/response, multi-party interaction |
|
||||
| `classDiagram` | Type relationships, inheritance |
|
||||
| `stateDiagram` | State machines, lifecycle |
|
||||
|
||||
## Tips
|
||||
|
||||
- Keep nodes short (3-4 words max)
|
||||
- Use subgraphs for grouping related components
|
||||
- Arrow labels for relationship types
|
||||
- Prefer LR (left-right) for flows, TD (top-down) for hierarchies
|
||||
61
profiles/opencode/skill/librarian/references/linking.md
Normal file
61
profiles/opencode/skill/librarian/references/linking.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# GitHub Linking Patterns
|
||||
|
||||
All file/dir/code refs → fluent markdown links. Never raw URLs.
|
||||
|
||||
## URL Formats
|
||||
|
||||
### File
|
||||
```
|
||||
https://github.com/{owner}/{repo}/blob/{ref}/{path}
|
||||
```
|
||||
|
||||
### File + Lines
|
||||
```
|
||||
https://github.com/{owner}/{repo}/blob/{ref}/{path}#L{start}-L{end}
|
||||
```
|
||||
|
||||
### Directory
|
||||
```
|
||||
https://github.com/{owner}/{repo}/tree/{ref}/{path}
|
||||
```
|
||||
|
||||
### GitLab (note `/-/blob/`)
|
||||
```
|
||||
https://gitlab.com/{owner}/{repo}/-/blob/{ref}/{path}
|
||||
```
|
||||
|
||||
## Ref Resolution
|
||||
|
||||
| Source | Use as ref |
|
||||
|--------|------------|
|
||||
| Known version | `v{version}` |
|
||||
| Default branch | `main` or `master` |
|
||||
| opensrc fetch | ref from result |
|
||||
| Specific commit | full SHA |
|
||||
|
||||
## Examples
|
||||
|
||||
### Correct
|
||||
```markdown
|
||||
The [`parseAsync`](https://github.com/colinhacks/zod/blob/main/src/types.ts#L450-L480) method handles...
|
||||
```
|
||||
|
||||
### Wrong
|
||||
```markdown
|
||||
See https://github.com/colinhacks/zod/blob/main/src/types.ts#L100
|
||||
The parseAsync method in src/types.ts handles...
|
||||
```
|
||||
|
||||
## Line Numbers
|
||||
|
||||
- Single: `#L42`
|
||||
- Range: `#L42-L50`
|
||||
- Prefer ranges for context (2-5 lines around key code)
|
||||
|
||||
## Registry → GitHub
|
||||
|
||||
| Registry | Find repo in |
|
||||
|----------|--------------|
|
||||
| npm | `package.json` → `repository` |
|
||||
| PyPI | `pyproject.toml` or setup.py |
|
||||
| crates | `Cargo.toml` |
|
||||
235
profiles/opencode/skill/librarian/references/opensrc-api.md
Normal file
235
profiles/opencode/skill/librarian/references/opensrc-api.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# opensrc API Reference
|
||||
|
||||
## Tool
|
||||
|
||||
Use the **opensrc MCP server** via single tool:
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| `opensrc_execute` | All operations (fetch, read, grep, files, remove, etc.) |
|
||||
|
||||
Takes a `code` parameter: JavaScript async arrow function executed server-side. Source trees stay on server, only results return.
|
||||
|
||||
## API Surface
|
||||
|
||||
### Read Operations
|
||||
|
||||
```typescript
|
||||
// List all fetched sources
|
||||
opensrc.list(): Source[]
|
||||
|
||||
// Check if source exists
|
||||
opensrc.has(name: string, version?: string): boolean
|
||||
|
||||
// Get source metadata
|
||||
opensrc.get(name: string): Source | undefined
|
||||
|
||||
// List files with optional glob
|
||||
opensrc.files(sourceName: string, glob?: string): Promise<FileEntry[]>
|
||||
|
||||
// Get directory tree structure (default depth: 3)
|
||||
opensrc.tree(sourceName: string, options?: { depth?: number }): Promise<TreeNode>
|
||||
|
||||
// Regex search file contents
|
||||
opensrc.grep(pattern: string, options?: GrepOptions): Promise<GrepResult[]>
|
||||
|
||||
// AST-based semantic code search
|
||||
opensrc.astGrep(sourceName: string, pattern: string, options?: AstGrepOptions): Promise<AstGrepMatch[]>
|
||||
|
||||
// Read single file
|
||||
opensrc.read(sourceName: string, filePath: string): Promise<string>
|
||||
|
||||
// Batch read multiple files (supports globs!)
|
||||
opensrc.readMany(sourceName: string, paths: string[]): Promise<Record<string, string>>
|
||||
|
||||
// Parse fetch spec
|
||||
opensrc.resolve(spec: string): Promise<ParsedSpec>
|
||||
```
|
||||
|
||||
### Mutation Operations
|
||||
|
||||
```typescript
|
||||
// Fetch packages/repos
|
||||
opensrc.fetch(specs: string | string[], options?: { modify?: boolean }): Promise<FetchedSource[]>
|
||||
|
||||
// Remove sources
|
||||
opensrc.remove(names: string[]): Promise<RemoveResult>
|
||||
|
||||
// Clean by type
|
||||
opensrc.clean(options?: CleanOptions): Promise<RemoveResult>
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
### Source
|
||||
|
||||
```typescript
|
||||
interface Source {
|
||||
type: "npm" | "pypi" | "crates" | "repo";
|
||||
name: string; // Use this for all subsequent calls
|
||||
version?: string;
|
||||
ref?: string;
|
||||
path: string;
|
||||
fetchedAt: string;
|
||||
repository: string;
|
||||
}
|
||||
```
|
||||
|
||||
### FetchedSource
|
||||
|
||||
```typescript
|
||||
interface FetchedSource {
|
||||
source: Source; // IMPORTANT: use source.name for subsequent calls
|
||||
alreadyExists: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### GrepOptions
|
||||
|
||||
```typescript
|
||||
interface GrepOptions {
|
||||
sources?: string[]; // Filter to specific sources
|
||||
include?: string; // File glob pattern (e.g., "*.ts")
|
||||
maxResults?: number; // Limit results (default: 100)
|
||||
}
|
||||
```
|
||||
|
||||
### GrepResult
|
||||
|
||||
```typescript
|
||||
interface GrepResult {
|
||||
source: string;
|
||||
file: string;
|
||||
line: number;
|
||||
content: string;
|
||||
}
|
||||
```
|
||||
|
||||
### AstGrepOptions
|
||||
|
||||
```typescript
|
||||
interface AstGrepOptions {
|
||||
glob?: string; // File glob pattern (e.g., "**/*.ts")
|
||||
lang?: string | string[]; // Language(s): "js", "ts", "tsx", "html", "css"
|
||||
limit?: number; // Max results (default: 1000)
|
||||
}
|
||||
```
|
||||
|
||||
### AstGrepMatch
|
||||
|
||||
```typescript
|
||||
interface AstGrepMatch {
|
||||
file: string;
|
||||
line: number;
|
||||
column: number;
|
||||
endLine: number;
|
||||
endColumn: number;
|
||||
text: string; // Matched code text
|
||||
metavars: Record<string, string>; // Captured $VAR → text
|
||||
}
|
||||
```
|
||||
|
||||
#### AST Pattern Syntax
|
||||
|
||||
| Pattern | Matches |
|
||||
|---------|---------|
|
||||
| `$NAME` | Single node, captures to metavars |
|
||||
| `$$$ARGS` | Zero or more nodes (variadic), captures |
|
||||
| `$_` | Single node, no capture |
|
||||
| `$$$` | Zero or more nodes, no capture |
|
||||
|
||||
### FileEntry
|
||||
|
||||
```typescript
|
||||
interface FileEntry {
|
||||
path: string;
|
||||
size: number;
|
||||
isDirectory: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### TreeNode
|
||||
|
||||
```typescript
|
||||
interface TreeNode {
|
||||
name: string;
|
||||
type: "file" | "dir";
|
||||
children?: TreeNode[]; // only for dirs
|
||||
}
|
||||
```
|
||||
|
||||
### CleanOptions
|
||||
|
||||
```typescript
|
||||
interface CleanOptions {
|
||||
packages?: boolean;
|
||||
repos?: boolean;
|
||||
npm?: boolean;
|
||||
pypi?: boolean;
|
||||
crates?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### RemoveResult
|
||||
|
||||
```typescript
|
||||
interface RemoveResult {
|
||||
success: boolean;
|
||||
removed: string[];
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Operations throw on errors. Wrap in try/catch if needed:
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
try {
|
||||
const content = await opensrc.read("zod", "missing.ts");
|
||||
return content;
|
||||
} catch (e) {
|
||||
return { error: e.message };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`readMany` returns errors as string values prefixed with `[Error:`:
|
||||
|
||||
```javascript
|
||||
const files = await opensrc.readMany("zod", ["exists.ts", "missing.ts"]);
|
||||
// { "exists.ts": "content...", "missing.ts": "[Error: ENOENT...]" }
|
||||
|
||||
// Filter successful reads
|
||||
const successful = Object.entries(files)
|
||||
.filter(([_, content]) => !content.startsWith("[Error:"));
|
||||
```
|
||||
|
||||
## Package Spec Formats
|
||||
|
||||
| Format | Example | Source Name After Fetch |
|
||||
|--------|---------|------------------------|
|
||||
| `<name>` | `"zod"` | `"zod"` |
|
||||
| `<name>@<version>` | `"zod@3.22.0"` | `"zod"` |
|
||||
| `pypi:<name>` | `"pypi:requests"` | `"requests"` |
|
||||
| `crates:<name>` | `"crates:serde"` | `"serde"` |
|
||||
| `owner/repo` | `"vercel/ai"` | `"github.com/vercel/ai"` |
|
||||
| `owner/repo@ref` | `"vercel/ai@v1.0.0"` | `"github.com/vercel/ai"` |
|
||||
| `gitlab:owner/repo` | `"gitlab:org/repo"` | `"gitlab.com/org/repo"` |
|
||||
|
||||
## Critical Pattern
|
||||
|
||||
**Always capture `source.name` from fetch results:**
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("vercel/ai");
|
||||
|
||||
// GitHub repos: "vercel/ai" → "github.com/vercel/ai"
|
||||
const sourceName = source.name;
|
||||
|
||||
// Use sourceName for ALL subsequent calls
|
||||
const files = await opensrc.files(sourceName, "src/**/*.ts");
|
||||
return files;
|
||||
}
|
||||
```
|
||||
336
profiles/opencode/skill/librarian/references/opensrc-examples.md
Normal file
336
profiles/opencode/skill/librarian/references/opensrc-examples.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# opensrc Code Examples
|
||||
|
||||
## Workflow: Fetch → Explore
|
||||
|
||||
### Basic Fetch and Explore with tree()
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("vercel/ai");
|
||||
// Get directory structure first
|
||||
const tree = await opensrc.tree(source.name, { depth: 2 });
|
||||
return tree;
|
||||
}
|
||||
```
|
||||
|
||||
### Fetch and Read Key Files
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("vercel/ai");
|
||||
const sourceName = source.name; // "github.com/vercel/ai"
|
||||
|
||||
const files = await opensrc.readMany(sourceName, [
|
||||
"package.json",
|
||||
"README.md",
|
||||
"src/index.ts"
|
||||
]);
|
||||
|
||||
return { sourceName, files };
|
||||
}
|
||||
```
|
||||
|
||||
### readMany with Globs
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("zod");
|
||||
// Read all package.json files in monorepo
|
||||
const files = await opensrc.readMany(source.name, [
|
||||
"packages/*/package.json" // globs supported!
|
||||
]);
|
||||
return Object.keys(files);
|
||||
}
|
||||
```
|
||||
|
||||
### Batch Fetch Multiple Packages
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const results = await opensrc.fetch(["zod", "valibot", "yup"]);
|
||||
const names = results.map(r => r.source.name);
|
||||
|
||||
// Compare how each handles string validation
|
||||
const comparisons = {};
|
||||
for (const name of names) {
|
||||
const matches = await opensrc.grep("string.*validate|validateString", {
|
||||
sources: [name],
|
||||
include: "*.ts",
|
||||
maxResults: 10
|
||||
});
|
||||
comparisons[name] = matches.map(m => `${m.file}:${m.line}`);
|
||||
}
|
||||
return comparisons;
|
||||
}
|
||||
```
|
||||
|
||||
## Search Patterns
|
||||
|
||||
### Grep → Read Context
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const matches = await opensrc.grep("export function parse\\(", {
|
||||
sources: ["zod"],
|
||||
include: "*.ts"
|
||||
});
|
||||
|
||||
if (matches.length === 0) return "No matches";
|
||||
|
||||
const match = matches[0];
|
||||
const content = await opensrc.read(match.source, match.file);
|
||||
const lines = content.split("\n");
|
||||
|
||||
// Return 40 lines starting from match
|
||||
return {
|
||||
file: match.file,
|
||||
code: lines.slice(match.line - 1, match.line + 39).join("\n")
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Search Across All Fetched Sources
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const sources = opensrc.list();
|
||||
const results = {};
|
||||
|
||||
for (const source of sources) {
|
||||
const errorHandling = await opensrc.grep("throw new|catch \\(|\\.catch\\(", {
|
||||
sources: [source.name],
|
||||
include: "*.ts",
|
||||
maxResults: 20
|
||||
});
|
||||
results[source.name] = {
|
||||
type: source.type,
|
||||
errorPatterns: errorHandling.length
|
||||
};
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
```
|
||||
|
||||
## AST-Based Search
|
||||
|
||||
Use `astGrep` for semantic code search with pattern matching.
|
||||
|
||||
### Find Function Declarations
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("lodash");
|
||||
|
||||
const fns = await opensrc.astGrep(source.name, "function $NAME($$$ARGS) { $$$BODY }", {
|
||||
lang: "js",
|
||||
limit: 20
|
||||
});
|
||||
|
||||
return fns.map(m => ({
|
||||
file: m.file,
|
||||
line: m.line,
|
||||
name: m.metavars.NAME
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
### Find React Hooks Usage
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("vercel/ai");
|
||||
|
||||
const stateHooks = await opensrc.astGrep(
|
||||
source.name,
|
||||
"const [$STATE, $SETTER] = useState($$$INIT)",
|
||||
{ lang: ["ts", "tsx"], limit: 50 }
|
||||
);
|
||||
|
||||
return stateHooks.map(m => ({
|
||||
file: m.file,
|
||||
state: m.metavars.STATE,
|
||||
setter: m.metavars.SETTER
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
### Find Class Definitions with Context
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const [{ source }] = await opensrc.fetch("zod");
|
||||
|
||||
const classes = await opensrc.astGrep(source.name, "class $NAME", {
|
||||
glob: "**/*.ts"
|
||||
});
|
||||
|
||||
const details = [];
|
||||
for (const cls of classes.slice(0, 5)) {
|
||||
const content = await opensrc.read(source.name, cls.file);
|
||||
const lines = content.split("\n");
|
||||
details.push({
|
||||
name: cls.metavars.NAME,
|
||||
file: cls.file,
|
||||
preview: lines.slice(cls.line - 1, cls.line + 9).join("\n")
|
||||
});
|
||||
}
|
||||
return details;
|
||||
}
|
||||
```
|
||||
|
||||
### Compare Export Patterns Across Libraries
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const results = await opensrc.fetch(["zod", "valibot"]);
|
||||
const names = results.map(r => r.source.name);
|
||||
|
||||
const exports = {};
|
||||
for (const name of names) {
|
||||
const matches = await opensrc.astGrep(name, "export const $NAME = $_", {
|
||||
lang: "ts",
|
||||
limit: 30
|
||||
});
|
||||
exports[name] = matches.map(m => m.metavars.NAME);
|
||||
}
|
||||
return exports;
|
||||
}
|
||||
```
|
||||
|
||||
### grep vs astGrep
|
||||
|
||||
| Use Case | Tool |
|
||||
|----------|------|
|
||||
| Text/regex pattern | `grep` |
|
||||
| Function declarations | `astGrep`: `function $NAME($$$) { $$$ }` |
|
||||
| Arrow functions | `astGrep`: `const $N = ($$$) => $_` |
|
||||
| Class definitions | `astGrep`: `class $NAME extends $PARENT` |
|
||||
| Import statements | `astGrep`: `import { $$$IMPORTS } from "$MOD"` |
|
||||
| JSX components | `astGrep`: `<$COMP $$$PROPS />` |
|
||||
|
||||
## Repository Exploration
|
||||
|
||||
### Find Entry Points
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const name = "github.com/vercel/ai";
|
||||
|
||||
const allFiles = await opensrc.files(name, "**/*.{ts,js}");
|
||||
const entryPoints = allFiles.filter(f =>
|
||||
f.path.match(/^(src\/)?(index|main|mod)\.(ts|js)$/) ||
|
||||
f.path.includes("/index.ts")
|
||||
);
|
||||
|
||||
// Read all entry points
|
||||
const contents = {};
|
||||
for (const ep of entryPoints.slice(0, 5)) {
|
||||
contents[ep.path] = await opensrc.read(name, ep.path);
|
||||
}
|
||||
|
||||
return {
|
||||
totalFiles: allFiles.length,
|
||||
entryPoints: entryPoints.map(f => f.path),
|
||||
contents
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Explore Package Structure
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const name = "zod";
|
||||
|
||||
// Get all TypeScript files
|
||||
const tsFiles = await opensrc.files(name, "**/*.ts");
|
||||
|
||||
// Group by directory
|
||||
const byDir = {};
|
||||
for (const f of tsFiles) {
|
||||
const dir = f.path.split("/").slice(0, -1).join("/") || ".";
|
||||
byDir[dir] = (byDir[dir] || 0) + 1;
|
||||
}
|
||||
|
||||
// Read key files
|
||||
const pkg = await opensrc.read(name, "package.json");
|
||||
const readme = await opensrc.read(name, "README.md");
|
||||
|
||||
return {
|
||||
structure: byDir,
|
||||
package: JSON.parse(pkg),
|
||||
readmePreview: readme.slice(0, 500)
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Batch Operations
|
||||
|
||||
### Read Many with Error Handling
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const files = await opensrc.readMany("zod", [
|
||||
"src/index.ts",
|
||||
"src/types.ts",
|
||||
"src/ZodError.ts",
|
||||
"src/helpers/parseUtil.ts"
|
||||
]);
|
||||
|
||||
// files is Record<string, string> - errors start with "[Error:"
|
||||
const successful = Object.entries(files)
|
||||
.filter(([_, content]) => !content.startsWith("[Error:"))
|
||||
.map(([path, content]) => ({ path, lines: content.split("\n").length }));
|
||||
|
||||
return successful;
|
||||
}
|
||||
```
|
||||
|
||||
### Parallel Grep Across Multiple Sources
|
||||
|
||||
```javascript
|
||||
async () => {
|
||||
const targets = ["zod", "valibot"];
|
||||
const pattern = "export (type|interface)";
|
||||
|
||||
const results = await Promise.all(
|
||||
targets.map(async (name) => {
|
||||
const matches = await opensrc.grep(pattern, {
|
||||
sources: [name],
|
||||
include: "*.ts",
|
||||
maxResults: 50
|
||||
});
|
||||
return { name, count: matches.length, matches };
|
||||
})
|
||||
);
|
||||
|
||||
return results;
|
||||
}
|
||||
```
|
||||
|
||||
## Workflow Checklist
|
||||
|
||||
### Comprehensive Repository Analysis
|
||||
|
||||
```
|
||||
Repository Analysis Progress:
|
||||
- [ ] 1. Fetch repository
|
||||
- [ ] 2. Read package.json + README
|
||||
- [ ] 3. Identify entry points (src/index.*)
|
||||
- [ ] 4. Read main entry file
|
||||
- [ ] 5. Map exports and public API
|
||||
- [ ] 6. Trace key functionality
|
||||
- [ ] 7. Create architecture diagram
|
||||
```
|
||||
|
||||
### Library Comparison
|
||||
|
||||
```
|
||||
Comparison Progress:
|
||||
- [ ] 1. Fetch all libraries
|
||||
- [ ] 2. Grep for target pattern in each
|
||||
- [ ] 3. Read matching implementations
|
||||
- [ ] 4. Create comparison table
|
||||
- [ ] 5. Synthesize findings
|
||||
```
|
||||
109
profiles/opencode/skill/librarian/references/tool-routing.md
Normal file
109
profiles/opencode/skill/librarian/references/tool-routing.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Tool Routing
|
||||
|
||||
## Decision Flowchart
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Q[User Query] --> T{Query Type?}
|
||||
T -->|Understand/Explain| U[UNDERSTAND]
|
||||
T -->|Find/Search| F[FIND]
|
||||
T -->|Explore/Architecture| E[EXPLORE]
|
||||
T -->|Compare| C[COMPARE]
|
||||
|
||||
U --> U1{Known library?}
|
||||
U1 -->|Yes| U2[context7.resolve-library-id]
|
||||
U2 --> U3[context7.query-docs]
|
||||
U3 --> U4{Need source?}
|
||||
U4 -->|Yes| U5[opensrc.fetch → read]
|
||||
U1 -->|No| U6[grep_app → opensrc.fetch]
|
||||
|
||||
F --> F1{Specific repo?}
|
||||
F1 -->|Yes| F2[opensrc.fetch → grep → read]
|
||||
F1 -->|No| F3[grep_app broad search]
|
||||
F3 --> F4[opensrc.fetch interesting repos]
|
||||
|
||||
E --> E1[opensrc.fetch]
|
||||
E1 --> E2[opensrc.files]
|
||||
E2 --> E3[Read entry points]
|
||||
E3 --> E4[Create diagram]
|
||||
|
||||
C --> C1["opensrc.fetch([X, Y])"]
|
||||
C1 --> C2[grep same pattern]
|
||||
C2 --> C3[Read comparable files]
|
||||
C3 --> C4[Synthesize comparison]
|
||||
```
|
||||
|
||||
## Query Type Detection
|
||||
|
||||
| Keywords | Query Type | Start With |
|
||||
|----------|------------|------------|
|
||||
| "how does", "why does", "explain", "purpose of" | UNDERSTAND | context7 |
|
||||
| "find", "where is", "implementations of", "examples of" | FIND | grep_app |
|
||||
| "explore", "walk through", "architecture", "structure" | EXPLORE | opensrc |
|
||||
| "compare", "vs", "difference between" | COMPARE | opensrc |
|
||||
|
||||
## UNDERSTAND Queries
|
||||
|
||||
```
|
||||
Known library? → context7.resolve-library-id → context7.query-docs
|
||||
└─ Need source? → opensrc.fetch → read
|
||||
|
||||
Unknown? → grep_app search → opensrc.fetch top result → read
|
||||
```
|
||||
|
||||
**When to transition context7 → opensrc:**
|
||||
- Need implementation details (not just API docs)
|
||||
- Question about internals/private methods
|
||||
- Tracing code flow through library
|
||||
|
||||
## FIND Queries
|
||||
|
||||
```
|
||||
Specific repo? → opensrc.fetch → opensrc.grep → read matches
|
||||
|
||||
Broad search? → grep_app → analyze → opensrc.fetch interesting repos
|
||||
```
|
||||
|
||||
**grep_app query tips:**
|
||||
- Use literal code patterns: `useState(` not "react hooks"
|
||||
- Filter by language: `language: ["TypeScript"]`
|
||||
- Narrow by repo: `repo: "vercel/"` for org
|
||||
|
||||
## EXPLORE Queries
|
||||
|
||||
```
|
||||
1. opensrc.fetch(target)
|
||||
2. opensrc.files → understand structure
|
||||
3. Identify entry points: README, package.json, src/index.*
|
||||
4. Read entry → internals
|
||||
5. Create architecture diagram
|
||||
```
|
||||
|
||||
## COMPARE Queries
|
||||
|
||||
```
|
||||
1. opensrc.fetch([X, Y])
|
||||
2. Extract source.name from each result
|
||||
3. opensrc.grep same pattern in both
|
||||
4. Read comparable files
|
||||
5. Synthesize → comparison table
|
||||
```
|
||||
|
||||
## Tool Capabilities
|
||||
|
||||
| Tool | Best For | Not For |
|
||||
|------|----------|---------|
|
||||
| **grep_app** | Broad search, unknown scope, finding repos | Semantic queries |
|
||||
| **context7** | Library APIs, best practices, common patterns | Library internals |
|
||||
| **opensrc** | Deep exploration, reading internals, tracing flow | Initial discovery |
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
| Don't | Do |
|
||||
|-------|-----|
|
||||
| grep_app for known library docs | context7 first |
|
||||
| opensrc.fetch before knowing target | grep_app to discover |
|
||||
| Multiple small reads | opensrc.readMany batch |
|
||||
| Describe without linking | Link every file ref |
|
||||
| Text for complex relationships | Mermaid diagram |
|
||||
| Use tool names in responses | "I'll search..." not "I'll use opensrc" |
|
||||
Reference in New Issue
Block a user