opencodekit 0.23.2 → 0.23.3
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/dist/index.js +1 -1
- package/dist/template/.opencode/AGENTS.md +3 -2
- package/dist/template/.opencode/plugin/codesearch.ts +730 -0
- package/dist/template/.opencode/plugin/memory/tools.ts +6 -6
- package/dist/template/.opencode/plugin/session-summary.ts +0 -2
- package/dist/template/.opencode/plugin/srcwalk.ts +22 -157
- package/dist/template/.opencode/skill/code-navigation/SKILL.md +10 -10
- package/dist/template/.opencode/skill/code-review-and-quality/SKILL.md +1 -1
- package/dist/template/.opencode/skill/debugging-and-error-recovery/SKILL.md +1 -1
- package/dist/template/.opencode/skill/deep-module-design/SKILL.md +1 -1
- package/dist/template/.opencode/skill/planning-and-task-breakdown/SKILL.md +1 -1
- package/dist/template/.opencode/skill/srcwalk/SKILL.md +10 -13
- package/dist/template/.opencode/skill/ubiquitous-language/SKILL.md +1 -1
- package/dist/template/.opencode/tool/grepsearch.ts +92 -103
- package/package.json +1 -1
|
@@ -3,19 +3,19 @@ import { tool } from "@opencode-ai/plugin";
|
|
|
3
3
|
const GREP_APP_API = "https://grep.app/api/search";
|
|
4
4
|
|
|
5
5
|
interface SearchResult {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
repo: string;
|
|
7
|
+
path: string;
|
|
8
|
+
content: { snippet: string };
|
|
9
|
+
total_matches: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
interface GrepResponse {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
hits: { hits: SearchResult[] };
|
|
14
|
+
time: number;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export default tool({
|
|
18
|
-
|
|
18
|
+
description: `Search real-world code examples from GitHub repositories via grep.app. Replaces asking "how do others use X?" — use this for finding production patterns and real-world API usage.
|
|
19
19
|
|
|
20
20
|
WHEN: Implementing unfamiliar APIs, looking for production patterns, understanding library integrations.
|
|
21
21
|
SKIP: Searching your own codebase (use grep/srcwalk), looking up docs (use context7), general research (use websearch).
|
|
@@ -31,113 +31,102 @@ Use when:
|
|
|
31
31
|
- Understanding library integrations - see how things work together
|
|
32
32
|
|
|
33
33
|
IMPORTANT: Search for **literal code patterns**, not keywords:
|
|
34
|
-
|
|
35
|
-
❌ Bad: "react tutorial", "best practices", "how to use"
|
|
34
|
+
Good: "useState(", "import React from", "async function"
|
|
36
35
|
|
|
36
|
+
Bad: "react tutorial", "best practices", "how to use"
|
|
37
37
|
Examples:
|
|
38
38
|
grepsearch({ query: "getServerSession", language: "TypeScript" })
|
|
39
39
|
grepsearch({ query: "CORS(", language: "Python", repo: "flask" })
|
|
40
40
|
grepsearch({ query: "export async function POST", path: "route.ts" })
|
|
41
41
|
`,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
.replace(/<[^>]*>/g, "") // Remove HTML tags
|
|
119
|
-
.replace(/</g, "<")
|
|
120
|
-
.replace(/>/g, ">")
|
|
121
|
-
.replace(/&/g, "&")
|
|
122
|
-
.replace(/"/g, '"')
|
|
123
|
-
.split("\n")
|
|
124
|
-
.slice(0, 8)
|
|
125
|
-
.join("\n")
|
|
126
|
-
.trim();
|
|
127
|
-
|
|
128
|
-
return `## ${i + 1}. ${repoName}
|
|
42
|
+
args: {
|
|
43
|
+
query: tool.schema.string().describe("Code pattern to search for (literal text)"),
|
|
44
|
+
language: tool.schema
|
|
45
|
+
.string()
|
|
46
|
+
.optional()
|
|
47
|
+
.describe("Filter by language: TypeScript, TSX, Python, Go, Rust, etc."),
|
|
48
|
+
repo: tool.schema.string().optional().describe("Filter by repo: 'owner/repo' or partial match"),
|
|
49
|
+
path: tool.schema.string().optional().describe("Filter by file path: 'src/', '.test.ts', etc."),
|
|
50
|
+
limit: tool.schema.number().optional().describe("Max results to return (default: 10, max: 20)"),
|
|
51
|
+
},
|
|
52
|
+
execute: async (args) => {
|
|
53
|
+
const { query, language, repo, path, limit = 10 } = args;
|
|
54
|
+
|
|
55
|
+
if (!query || query.trim() === "") {
|
|
56
|
+
return "Error: query is required";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Build URL with proper filter parameters
|
|
60
|
+
// grep.app uses filter[lang][0]=TypeScript format, NOT inline lang:TypeScript
|
|
61
|
+
const url = new URL(GREP_APP_API);
|
|
62
|
+
url.searchParams.set("q", query);
|
|
63
|
+
|
|
64
|
+
// Add language filter (grep.app uses filter[lang][0] format)
|
|
65
|
+
if (language) {
|
|
66
|
+
url.searchParams.set("filter[lang][0]", language);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Add repo filter
|
|
70
|
+
if (repo) {
|
|
71
|
+
url.searchParams.set("filter[repo][0]", repo);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Add path filter
|
|
75
|
+
if (path) {
|
|
76
|
+
url.searchParams.set("filter[path][0]", path);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(url.toString(), {
|
|
81
|
+
headers: {
|
|
82
|
+
Accept: "application/json",
|
|
83
|
+
"User-Agent": "OpenCode/1.0",
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
return `Error: grep.app API returned ${response.status}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const data = (await response.json()) as GrepResponse;
|
|
92
|
+
|
|
93
|
+
if (!data.hits?.hits?.length) {
|
|
94
|
+
return `No results found for: ${query}${language ? ` (${language})` : ""}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const maxResults = Math.min(limit, 20);
|
|
98
|
+
const results = data.hits.hits.slice(0, maxResults);
|
|
99
|
+
|
|
100
|
+
const formatted = results.map((hit, i) => {
|
|
101
|
+
const repoName = hit.repo || "unknown";
|
|
102
|
+
const filePath = hit.path || "unknown";
|
|
103
|
+
const snippet = hit.content?.snippet || "";
|
|
104
|
+
|
|
105
|
+
// Clean up HTML from snippet and extract text
|
|
106
|
+
const cleanCode = snippet
|
|
107
|
+
.replace(/<[^>]*>/g, "") // Remove HTML tags
|
|
108
|
+
.replace(/</g, "<")
|
|
109
|
+
.replace(/>/g, ">")
|
|
110
|
+
.replace(/&/g, "&")
|
|
111
|
+
.replace(/"/g, '"')
|
|
112
|
+
.split("\n")
|
|
113
|
+
.slice(0, 8)
|
|
114
|
+
.join("\n")
|
|
115
|
+
.trim();
|
|
116
|
+
|
|
117
|
+
return `## ${i + 1}. ${repoName}
|
|
129
118
|
**File**: ${filePath}
|
|
130
119
|
\`\`\`
|
|
131
120
|
${cleanCode}
|
|
132
121
|
\`\`\``;
|
|
133
|
-
|
|
122
|
+
});
|
|
134
123
|
|
|
135
|
-
|
|
124
|
+
return `Found ${data.hits.hits.length} results (showing ${results.length}) in ${data.time}ms:
|
|
136
125
|
|
|
137
126
|
${formatted.join("\n\n")}`;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
127
|
+
} catch (error: unknown) {
|
|
128
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
129
|
+
return `Error searching grep.app: ${message}`;
|
|
130
|
+
}
|
|
131
|
+
},
|
|
143
132
|
});
|