opencode-ask-github 0.1.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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +128 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/commands/ask.d.ts +7 -0
  8. package/dist/src/commands/ask.d.ts.map +1 -0
  9. package/dist/src/commands/ask.js +139 -0
  10. package/dist/src/commands/ask.js.map +1 -0
  11. package/dist/src/commands/list.d.ts +7 -0
  12. package/dist/src/commands/list.d.ts.map +1 -0
  13. package/dist/src/commands/list.js +48 -0
  14. package/dist/src/commands/list.js.map +1 -0
  15. package/dist/src/commands/remove.d.ts +7 -0
  16. package/dist/src/commands/remove.d.ts.map +1 -0
  17. package/dist/src/commands/remove.js +34 -0
  18. package/dist/src/commands/remove.js.map +1 -0
  19. package/dist/src/config.d.ts +10 -0
  20. package/dist/src/config.d.ts.map +1 -0
  21. package/dist/src/config.js +56 -0
  22. package/dist/src/config.js.map +1 -0
  23. package/dist/src/notification.d.ts +19 -0
  24. package/dist/src/notification.d.ts.map +1 -0
  25. package/dist/src/notification.js +28 -0
  26. package/dist/src/notification.js.map +1 -0
  27. package/dist/src/repo-manager.d.ts +32 -0
  28. package/dist/src/repo-manager.d.ts.map +1 -0
  29. package/dist/src/repo-manager.js +147 -0
  30. package/dist/src/repo-manager.js.map +1 -0
  31. package/dist/src/repo-parser.d.ts +19 -0
  32. package/dist/src/repo-parser.d.ts.map +1 -0
  33. package/dist/src/repo-parser.js +116 -0
  34. package/dist/src/repo-parser.js.map +1 -0
  35. package/dist/src/types.d.ts +36 -0
  36. package/dist/src/types.d.ts.map +1 -0
  37. package/dist/src/types.js +2 -0
  38. package/dist/src/types.js.map +1 -0
  39. package/package.json +49 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 JosXa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # opencode-ask-github
2
+
3
+ GitHub repository management plugin for OpenCode. Automatically clones repositories and delegates analysis to AI subagents.
4
+
5
+ ## Features
6
+
7
+ - **Auto-clone**: Repositories are cloned on-demand with shallow clone for speed
8
+ - **AI Analysis**: Delegates to the `explore` subagent for codebase analysis
9
+ - **Aliases**: Configure shortcuts for frequently used repositories
10
+ - **Cache Management**: List and remove cloned repositories
11
+
12
+ ## Installation
13
+
14
+ Add to your OpenCode configuration (`~/.config/opencode/config.json`):
15
+
16
+ ```json
17
+ {
18
+ "plugins": ["D:/projects/opencode-ask-github"]
19
+ }
20
+ ```
21
+
22
+ ## Commands
23
+
24
+ ### `/github-ask <repo> [question]`
25
+
26
+ Clone/locate a repository and analyze it with AI.
27
+
28
+ ```
29
+ /github-ask sveltejs/svelte how is the component compiler structured?
30
+ /github-ask https://github.com/tailwindlabs/tailwindcss what's the CLI architecture?
31
+ /github-ask sv explain the reactivity system
32
+ ```
33
+
34
+ **Supported input formats:**
35
+
36
+ - GitHub URLs: `https://github.com/owner/repo`
37
+ - owner/repo pairs: `sveltejs/svelte`
38
+ - Aliases: `sv` (if configured)
39
+
40
+ ### `/github-list`
41
+
42
+ List all cloned repositories and configured aliases.
43
+
44
+ ### `/github-remove <repo>`
45
+
46
+ Remove a cloned repository from the cache.
47
+
48
+ ## Configuration
49
+
50
+ Aliases are stored in `~/.config/opencode/ask-github.json`:
51
+
52
+ ```json
53
+ {
54
+ "aliases": {
55
+ "sv": "sveltejs/svelte",
56
+ "tw": "tailwindlabs/tailwindcss"
57
+ }
58
+ }
59
+ ```
60
+
61
+ You can also manage aliases by asking the AI:
62
+
63
+ - "Add a GitHub alias 'react' for facebook/react"
64
+ - "List my GitHub aliases"
65
+ - "Remove the 'sv' alias"
66
+
67
+ ## Storage
68
+
69
+ Repositories are cloned to `~/.cache/opencode-github/{owner}/{repo}/`.
70
+
71
+ ## AI Tools
72
+
73
+ The plugin provides these tools for the AI to use:
74
+
75
+ | Tool | Description |
76
+ | --------------------- | --------------------------- |
77
+ | `github-alias-add` | Add a repository alias |
78
+ | `github-alias-remove` | Remove an alias |
79
+ | `github-alias-list` | List all aliases |
80
+ | `github-repo-info` | Get info about a repository |
81
+
82
+ ## License
83
+
84
+ MIT
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export declare const AskGithubPlugin: Plugin;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAuBlD,eAAO,MAAM,eAAe,EAAE,MAmI7B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,128 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import { handleAsk } from "./src/commands/ask";
3
+ import { handleList } from "./src/commands/list";
4
+ import { handleRemove } from "./src/commands/remove";
5
+ import { loadConfig, saveConfig } from "./src/config";
6
+ import { getRepoPath, isCloned, listClonedRepos } from "./src/repo-manager";
7
+ import { parseRepoInput } from "./src/repo-parser";
8
+ /** Marker error to indicate command was handled */
9
+ const COMMAND_HANDLED_MARKER = "__GH_COMMAND_HANDLED__";
10
+ export const AskGithubPlugin = async ({ client, $, directory }) => {
11
+ return {
12
+ config: async (cfg) => {
13
+ cfg.command ??= {};
14
+ cfg.command["gh-ask"] = {
15
+ template: "",
16
+ description: "Clone/locate a GitHub repo and analyze with AI",
17
+ };
18
+ cfg.command["gh-list"] = {
19
+ template: "",
20
+ description: "List cloned GitHub repositories and aliases",
21
+ };
22
+ cfg.command["gh-remove"] = {
23
+ template: "",
24
+ description: "Remove a cloned GitHub repository from cache",
25
+ };
26
+ },
27
+ "command.execute.before": async (input, output) => {
28
+ const ctx = {
29
+ client,
30
+ $,
31
+ directory,
32
+ sessionId: input.sessionID,
33
+ };
34
+ try {
35
+ if (input.command === "gh-ask") {
36
+ await handleAsk(input.arguments, ctx);
37
+ output.parts.length = 0;
38
+ throw new Error(COMMAND_HANDLED_MARKER);
39
+ }
40
+ if (input.command === "gh-list") {
41
+ await handleList(ctx);
42
+ output.parts.length = 0;
43
+ throw new Error(COMMAND_HANDLED_MARKER);
44
+ }
45
+ if (input.command === "gh-remove") {
46
+ await handleRemove(input.arguments, ctx);
47
+ output.parts.length = 0;
48
+ throw new Error(COMMAND_HANDLED_MARKER);
49
+ }
50
+ }
51
+ catch (error) {
52
+ // Re-throw marker error to signal command was handled
53
+ if (error instanceof Error && error.message === COMMAND_HANDLED_MARKER) {
54
+ throw error;
55
+ }
56
+ // Re-throw other errors
57
+ throw error;
58
+ }
59
+ },
60
+ tool: {
61
+ "gh-alias-add": tool({
62
+ description: "Add a GitHub repository alias for quick access with /gh-ask",
63
+ args: {
64
+ alias: tool.schema.string("Short name for the alias (e.g., 'sv')"),
65
+ target: tool.schema.string("Repository in owner/repo format (e.g., 'sveltejs/svelte')"),
66
+ },
67
+ async execute(args) {
68
+ const config = loadConfig();
69
+ config.aliases[args.alias] = args.target;
70
+ saveConfig(config);
71
+ return `Added alias: ${args.alias} → ${args.target}`;
72
+ },
73
+ }),
74
+ "gh-alias-remove": tool({
75
+ description: "Remove a GitHub repository alias",
76
+ args: {
77
+ alias: tool.schema.string("The alias to remove"),
78
+ },
79
+ async execute(args) {
80
+ const config = loadConfig();
81
+ if (!config.aliases[args.alias]) {
82
+ return `Alias '${args.alias}' not found`;
83
+ }
84
+ delete config.aliases[args.alias];
85
+ saveConfig(config);
86
+ return `Removed alias: ${args.alias}`;
87
+ },
88
+ }),
89
+ "gh-alias-list": tool({
90
+ description: "List all configured GitHub repository aliases",
91
+ args: {},
92
+ async execute() {
93
+ const config = loadConfig();
94
+ const entries = Object.entries(config.aliases);
95
+ if (entries.length === 0) {
96
+ return "No aliases configured";
97
+ }
98
+ return entries.map(([alias, repo]) => `${alias} → ${repo}`).join("\n");
99
+ },
100
+ }),
101
+ "gh-repo-info": tool({
102
+ description: "Get information about a GitHub repository (whether cloned, local path)",
103
+ args: {
104
+ repo: tool.schema.string("Repository URL, owner/repo, or alias"),
105
+ },
106
+ async execute(args) {
107
+ const config = loadConfig();
108
+ const clonedRepos = listClonedRepos();
109
+ const result = parseRepoInput(args.repo, config.aliases, clonedRepos);
110
+ if (!result.repoInfo) {
111
+ return `Could not parse: ${args.repo}`;
112
+ }
113
+ const info = result.repoInfo;
114
+ const cloned = isCloned(info);
115
+ const path = getRepoPath(info);
116
+ return JSON.stringify({
117
+ owner: info.owner,
118
+ repo: info.repo,
119
+ url: info.url,
120
+ cloned,
121
+ localPath: cloned ? path : null,
122
+ }, null, 2);
123
+ },
124
+ }),
125
+ },
126
+ };
127
+ };
128
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { CommandContext } from "../types";
2
+ /**
3
+ * Handle /github-ask command.
4
+ * Clone repo if needed, then delegate to explore subagent.
5
+ */
6
+ export declare function handleAsk(args: string, ctx: CommandContext): Promise<void>;
7
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../../src/commands/ask.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CA8Jf"}
@@ -0,0 +1,139 @@
1
+ import { getPromptConfig, loadConfig } from "../config";
2
+ import { showToast } from "../notification";
3
+ import { cloneRepo, getRepoPath, isCloned, listClonedRepos, updateRepo, } from "../repo-manager";
4
+ import { formatRepo, parseRepoInput } from "../repo-parser";
5
+ /**
6
+ * Handle /github-ask command.
7
+ * Clone repo if needed, then delegate to explore subagent.
8
+ */
9
+ export async function handleAsk(args, ctx) {
10
+ const { client, directory, sessionId } = ctx;
11
+ const config = loadConfig();
12
+ // Parse args: first token is repo, rest is question
13
+ const tokens = args.trim().split(/\s+/);
14
+ const repoInput = tokens[0];
15
+ const question = tokens.slice(1).join(" ") || "provide an overview of this repository";
16
+ if (!repoInput) {
17
+ await injectMessage(client, sessionId, directory, `Usage: /github-ask <repo> [question]
18
+
19
+ **repo** can be:
20
+ - GitHub URL: \`https://github.com/owner/repo\`
21
+ - owner/repo: \`sveltejs/svelte\`
22
+ - alias: \`sv\` (if configured)
23
+
24
+ **Configured aliases:**
25
+ ${formatAliases(config.aliases)}`);
26
+ return;
27
+ }
28
+ // Parse the repo input (with cloned repos for substring matching)
29
+ const clonedRepos = listClonedRepos();
30
+ const parseResult = parseRepoInput(repoInput, config.aliases, clonedRepos);
31
+ if (!parseResult.repoInfo) {
32
+ const errorMsg = `Could not parse repository: \`${repoInput}\`
33
+
34
+ Expected formats:
35
+ - \`https://github.com/owner/repo\`
36
+ - \`owner/repo\`
37
+ - Configured alias
38
+ - Substring of a cloned repo name
39
+
40
+ **Configured aliases:**
41
+ ${formatAliases(config.aliases)}
42
+
43
+ _Tip: You can add an alias for quick access using the github-alias-add tool._`;
44
+ await injectMessage(client, sessionId, directory, errorMsg);
45
+ return;
46
+ }
47
+ const repoInfo = parseResult.repoInfo;
48
+ const repoDisplay = formatRepo(repoInfo);
49
+ const localPath = getRepoPath(repoInfo);
50
+ const alreadyCloned = isCloned(repoInfo);
51
+ // Prepare the repo (clone or update)
52
+ if (!alreadyCloned) {
53
+ // Clone flow
54
+ await injectMessage(client, sessionId, directory, `Preparing ${repoDisplay}...`, true);
55
+ await showToast(ctx, {
56
+ message: `Cloning ${repoDisplay}...`,
57
+ variant: "info",
58
+ });
59
+ const result = await cloneRepo(repoInfo);
60
+ if (!result.success) {
61
+ await showToast(ctx, {
62
+ title: "Clone failed",
63
+ message: result.error ?? "Unknown error",
64
+ variant: "error",
65
+ });
66
+ await injectMessage(client, sessionId, directory, `Failed to clone ${repoDisplay}:\n\`\`\`\n${result.error}\n\`\`\``);
67
+ return;
68
+ }
69
+ await showToast(ctx, {
70
+ title: "Cloned",
71
+ message: repoDisplay,
72
+ variant: "success",
73
+ duration: 3000,
74
+ });
75
+ }
76
+ else {
77
+ // Update flow
78
+ await injectMessage(client, sessionId, directory, `Preparing ${repoDisplay}...`, true);
79
+ await showToast(ctx, {
80
+ message: `Updating ${repoDisplay}...`,
81
+ variant: "info",
82
+ });
83
+ const result = await updateRepo(repoInfo);
84
+ if (!result.success) {
85
+ await showToast(ctx, {
86
+ title: "Update failed",
87
+ message: result.error ?? "Unknown error",
88
+ variant: "error",
89
+ });
90
+ await injectMessage(client, sessionId, directory, `Failed to update ${repoDisplay}:\n\`\`\`\n${result.error}\n\`\`\``);
91
+ return;
92
+ }
93
+ await showToast(ctx, {
94
+ title: "Updated",
95
+ message: repoDisplay,
96
+ variant: "success",
97
+ duration: 3000,
98
+ });
99
+ }
100
+ // Delegate to explore subagent
101
+ const promptConfig = getPromptConfig(config);
102
+ const instruction = promptConfig.delegateInstruction.replace("{path}", localPath);
103
+ const explorePrompt = promptConfig.exploreTemplate.replace("{question}", question);
104
+ await client.session.prompt({
105
+ path: { id: sessionId },
106
+ body: {
107
+ parts: [
108
+ {
109
+ type: "text",
110
+ text: `${instruction}
111
+ ---
112
+ ${explorePrompt}
113
+ ---`,
114
+ },
115
+ ],
116
+ },
117
+ query: { directory },
118
+ });
119
+ }
120
+ function formatAliases(aliases) {
121
+ const entries = Object.entries(aliases);
122
+ if (entries.length === 0) {
123
+ return "_No aliases configured_";
124
+ }
125
+ return entries
126
+ .map(([alias, repo]) => `- \`${alias}\` → \`${repo}\``)
127
+ .join("\n");
128
+ }
129
+ async function injectMessage(client, sessionId, directory, text, noReply = false) {
130
+ await client.session.prompt({
131
+ path: { id: sessionId },
132
+ body: {
133
+ noReply,
134
+ parts: [{ type: "text", text }],
135
+ },
136
+ query: { directory },
137
+ });
138
+ }
139
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../src/commands/ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { CommandContext } from "../types";
2
+ /**
3
+ * Handle /github-list command.
4
+ * List all cloned repos and configured aliases.
5
+ */
6
+ export declare function handleList(ctx: CommandContext): Promise<void>;
7
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BnE"}
@@ -0,0 +1,48 @@
1
+ import { loadConfig } from "../config";
2
+ import { sendIgnoredMessage } from "../notification";
3
+ import { listClonedRepos } from "../repo-manager";
4
+ /**
5
+ * Handle /github-list command.
6
+ * List all cloned repos and configured aliases.
7
+ */
8
+ export async function handleList(ctx) {
9
+ const config = loadConfig();
10
+ const repos = listClonedRepos();
11
+ const lines = ["**Cloned repositories:**"];
12
+ if (repos.length === 0) {
13
+ lines.push("_No repositories cloned yet_");
14
+ }
15
+ else {
16
+ for (const repo of repos) {
17
+ const age = formatAge(repo.lastModified);
18
+ lines.push(`- \`${repo.owner}/${repo.repo}\` (${age})`);
19
+ }
20
+ }
21
+ lines.push("");
22
+ lines.push("**Configured aliases:**");
23
+ const aliases = Object.entries(config.aliases);
24
+ if (aliases.length === 0) {
25
+ lines.push("_No aliases configured_");
26
+ }
27
+ else {
28
+ for (const [alias, target] of aliases) {
29
+ lines.push(`- \`${alias}\` → \`${target}\``);
30
+ }
31
+ }
32
+ await sendIgnoredMessage(ctx, lines.join("\n"));
33
+ }
34
+ function formatAge(date) {
35
+ const now = Date.now();
36
+ const diff = now - date.getTime();
37
+ const minutes = Math.floor(diff / 60000);
38
+ const hours = Math.floor(minutes / 60);
39
+ const days = Math.floor(hours / 24);
40
+ if (days > 0)
41
+ return `${days} day${days > 1 ? "s" : ""} ago`;
42
+ if (hours > 0)
43
+ return `${hours} hour${hours > 1 ? "s" : ""} ago`;
44
+ if (minutes > 0)
45
+ return `${minutes} min${minutes > 1 ? "s" : ""} ago`;
46
+ return "just now";
47
+ }
48
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAmB;IAClD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAEhC,MAAM,KAAK,GAAa,CAAC,0BAA0B,CAAC,CAAC;IAErD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,OAAO,GAAG,GAAG,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,MAAM,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,SAAS,CAAC,IAAU;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAEpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,IAAI,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IAC7D,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACjE,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,GAAG,OAAO,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACtE,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { CommandContext } from "../types";
2
+ /**
3
+ * Handle /github-remove command.
4
+ * Remove a cloned repository from the cache.
5
+ */
6
+ export declare function handleRemove(args: string, ctx: CommandContext): Promise<void>;
7
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../src/commands/remove.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCnF"}
@@ -0,0 +1,34 @@
1
+ import { loadConfig } from "../config";
2
+ import { sendIgnoredMessage } from "../notification";
3
+ import { isCloned, listClonedRepos, removeRepo } from "../repo-manager";
4
+ import { formatRepo, parseRepoInput } from "../repo-parser";
5
+ /**
6
+ * Handle /github-remove command.
7
+ * Remove a cloned repository from the cache.
8
+ */
9
+ export async function handleRemove(args, ctx) {
10
+ const config = loadConfig();
11
+ const repoInput = args.trim();
12
+ if (!repoInput) {
13
+ await sendIgnoredMessage(ctx, "Usage: `/gh-remove <repo>`");
14
+ return;
15
+ }
16
+ const clonedRepos = listClonedRepos();
17
+ const result = parseRepoInput(repoInput, config.aliases, clonedRepos);
18
+ if (!result.repoInfo) {
19
+ await sendIgnoredMessage(ctx, `Could not parse repository: \`${repoInput}\``);
20
+ return;
21
+ }
22
+ const repoInfo = result.repoInfo;
23
+ const repoDisplay = formatRepo(repoInfo);
24
+ if (!isCloned(repoInfo)) {
25
+ await sendIgnoredMessage(ctx, `Repository \`${repoDisplay}\` is not cloned.`);
26
+ return;
27
+ }
28
+ const removed = removeRepo(repoInfo);
29
+ const message = removed
30
+ ? `Removed \`${repoDisplay}\` from cache.`
31
+ : `Failed to remove \`${repoDisplay}\`.`;
32
+ await sendIgnoredMessage(ctx, message);
33
+ }
34
+ //# sourceMappingURL=remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG5D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,GAAmB;IAClE,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAE9B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,kBAAkB,CAAC,GAAG,EAAE,4BAA4B,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEtE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,kBAAkB,CAAC,GAAG,EAAE,iCAAiC,SAAS,IAAI,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,MAAM,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,WAAW,mBAAmB,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,OAAO;QACrB,CAAC,CAAC,aAAa,WAAW,gBAAgB;QAC1C,CAAC,CAAC,sBAAsB,WAAW,KAAK,CAAC;IAE3C,MAAM,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Config, PromptConfig } from "./types";
2
+ export declare function getConfigPath(): string;
3
+ export declare function getCacheDir(): string;
4
+ export declare function getConfigDir(): string;
5
+ export declare function getDefaultPrompt(): PromptConfig;
6
+ export declare function loadConfig(): Config;
7
+ export declare function getPromptConfig(config: Config): PromptConfig;
8
+ export declare function saveConfig(config: Config): void;
9
+ export declare function ensureCacheDir(): void;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAWpD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAE/C;AAQD,wBAAgB,UAAU,IAAI,MAAM,CAWnC;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAO5D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK/C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAIrC"}
@@ -0,0 +1,56 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const CONFIG_DIR = join(homedir(), ".config", "opencode");
5
+ const CONFIG_FILE = join(CONFIG_DIR, "ask-github.json");
6
+ const CACHE_DIR = join(homedir(), ".cache", "opencode-github");
7
+ const DEFAULT_PROMPT = {
8
+ delegateInstruction: "Use a subagent to explore `{path}` and answer:",
9
+ exploreTemplate: "{question}",
10
+ };
11
+ export function getConfigPath() {
12
+ return CONFIG_FILE;
13
+ }
14
+ export function getCacheDir() {
15
+ return CACHE_DIR;
16
+ }
17
+ export function getConfigDir() {
18
+ return CONFIG_DIR;
19
+ }
20
+ export function getDefaultPrompt() {
21
+ return { ...DEFAULT_PROMPT };
22
+ }
23
+ function defaultConfig() {
24
+ return {
25
+ aliases: {},
26
+ };
27
+ }
28
+ export function loadConfig() {
29
+ if (!existsSync(CONFIG_FILE)) {
30
+ return defaultConfig();
31
+ }
32
+ const content = readFileSync(CONFIG_FILE, "utf-8");
33
+ const parsed = JSON.parse(content);
34
+ return {
35
+ aliases: parsed.aliases ?? {},
36
+ prompt: parsed.prompt,
37
+ };
38
+ }
39
+ export function getPromptConfig(config) {
40
+ return {
41
+ delegateInstruction: config.prompt?.delegateInstruction ?? DEFAULT_PROMPT.delegateInstruction,
42
+ exploreTemplate: config.prompt?.exploreTemplate ?? DEFAULT_PROMPT.exploreTemplate,
43
+ };
44
+ }
45
+ export function saveConfig(config) {
46
+ if (!existsSync(CONFIG_DIR)) {
47
+ mkdirSync(CONFIG_DIR, { recursive: true });
48
+ }
49
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
50
+ }
51
+ export function ensureCacheDir() {
52
+ if (!existsSync(CACHE_DIR)) {
53
+ mkdirSync(CACHE_DIR, { recursive: true });
54
+ }
55
+ }
56
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AACxD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAE/D,MAAM,cAAc,GAAiB;IACnC,mBAAmB,EAAE,gDAAgD;IACrE,eAAe,EAAE,YAAY;CAC9B,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,aAAa;IACpB,OAAO;QACL,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,OAAO,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO;QACL,mBAAmB,EACjB,MAAM,CAAC,MAAM,EAAE,mBAAmB,IAAI,cAAc,CAAC,mBAAmB;QAC1E,eAAe,EACb,MAAM,CAAC,MAAM,EAAE,eAAe,IAAI,cAAc,CAAC,eAAe;KACnE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { CommandContext } from "./types";
2
+ type ToastVariant = "info" | "success" | "warning" | "error";
3
+ interface ToastOptions {
4
+ title?: string;
5
+ message: string;
6
+ variant?: ToastVariant;
7
+ duration?: number;
8
+ }
9
+ /**
10
+ * Show a toast notification in the TUI.
11
+ */
12
+ export declare function showToast(ctx: CommandContext, options: ToastOptions): Promise<void>;
13
+ /**
14
+ * Sends a message that will be displayed but ignored by the AI.
15
+ * Used for command output that shouldn't trigger AI responses.
16
+ */
17
+ export declare function sendIgnoredMessage(ctx: CommandContext, text: string): Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=notification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/notification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,KAAK,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7D,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CASzF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASzF"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Show a toast notification in the TUI.
3
+ */
4
+ export async function showToast(ctx, options) {
5
+ await ctx.client.tui.showToast({
6
+ body: {
7
+ title: options.title,
8
+ message: options.message,
9
+ variant: options.variant ?? "info",
10
+ duration: options.duration,
11
+ },
12
+ });
13
+ }
14
+ /**
15
+ * Sends a message that will be displayed but ignored by the AI.
16
+ * Used for command output that shouldn't trigger AI responses.
17
+ */
18
+ export async function sendIgnoredMessage(ctx, text) {
19
+ await ctx.client.session.prompt({
20
+ path: { id: ctx.sessionId },
21
+ body: {
22
+ noReply: true,
23
+ parts: [{ type: "text", text, ignored: true }],
24
+ },
25
+ query: { directory: ctx.directory },
26
+ });
27
+ }
28
+ //# sourceMappingURL=notification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.js","sourceRoot":"","sources":["../../src/notification.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAmB,EAAE,OAAqB;IACxE,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QAC7B,IAAI,EAAE;YACJ,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,MAAM;YAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAmB,EAAE,IAAY;IACxE,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,SAAS,EAAE;QAC3B,IAAI,EAAE;YACJ,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;SAC/C;QACD,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE;KACpC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { ClonedRepo, RepoInfo } from "./types";
2
+ /**
3
+ * Get the local path for a repository.
4
+ */
5
+ export declare function getRepoPath(info: RepoInfo): string;
6
+ /**
7
+ * Check if a repository is already cloned.
8
+ */
9
+ export declare function isCloned(info: RepoInfo): boolean;
10
+ /**
11
+ * Clone a repository using shallow clone for speed.
12
+ */
13
+ export declare function cloneRepo(info: RepoInfo): Promise<{
14
+ success: boolean;
15
+ error?: string;
16
+ }>;
17
+ /**
18
+ * Update an existing repository by fetching and resetting to the default branch.
19
+ */
20
+ export declare function updateRepo(info: RepoInfo): Promise<{
21
+ success: boolean;
22
+ error?: string;
23
+ }>;
24
+ /**
25
+ * Remove a cloned repository.
26
+ */
27
+ export declare function removeRepo(info: RepoInfo): boolean;
28
+ /**
29
+ * List all cloned repositories.
30
+ */
31
+ export declare function listClonedRepos(): ClonedRepo[];
32
+ //# sourceMappingURL=repo-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-manager.d.ts","sourceRoot":"","sources":["../../src/repo-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEpD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAGhD;AA4BD;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB7F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoD9F;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CASlD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,UAAU,EAAE,CAmC9C"}
@@ -0,0 +1,147 @@
1
+ import { existsSync, mkdirSync, readdirSync, rmSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { ensureCacheDir, getCacheDir } from "./config";
4
+ /**
5
+ * Get the local path for a repository.
6
+ */
7
+ export function getRepoPath(info) {
8
+ return join(getCacheDir(), info.owner, info.repo);
9
+ }
10
+ /**
11
+ * Check if a repository is already cloned.
12
+ */
13
+ export function isCloned(info) {
14
+ const path = getRepoPath(info);
15
+ return existsSync(join(path, ".git"));
16
+ }
17
+ /**
18
+ * Run a git command with stdout/stderr suppressed.
19
+ * Returns { success, error } result object.
20
+ */
21
+ async function runGitCommand(args) {
22
+ const proc = Bun.spawn(["git", ...args], {
23
+ stdout: "pipe",
24
+ stderr: "pipe",
25
+ });
26
+ const [stdout, stderr] = await Promise.all([
27
+ new Response(proc.stdout).text(),
28
+ new Response(proc.stderr).text(),
29
+ ]);
30
+ const exitCode = await proc.exited;
31
+ return {
32
+ success: exitCode === 0,
33
+ stdout,
34
+ stderr,
35
+ };
36
+ }
37
+ /**
38
+ * Clone a repository using shallow clone for speed.
39
+ */
40
+ export async function cloneRepo(info) {
41
+ ensureCacheDir();
42
+ const path = getRepoPath(info);
43
+ const ownerDir = join(getCacheDir(), info.owner);
44
+ // Ensure owner directory exists
45
+ if (!existsSync(ownerDir)) {
46
+ mkdirSync(ownerDir, { recursive: true });
47
+ }
48
+ const result = await runGitCommand(["clone", "--depth", "1", `${info.url}.git`, path]);
49
+ if (!result.success) {
50
+ return {
51
+ success: false,
52
+ error: result.stderr,
53
+ };
54
+ }
55
+ return { success: true };
56
+ }
57
+ /**
58
+ * Update an existing repository by fetching and resetting to the default branch.
59
+ */
60
+ export async function updateRepo(info) {
61
+ const path = getRepoPath(info);
62
+ // Fetch latest from origin
63
+ const fetchResult = await runGitCommand(["-C", path, "fetch", "--depth", "1", "origin"]);
64
+ if (!fetchResult.success) {
65
+ return {
66
+ success: false,
67
+ error: fetchResult.stderr,
68
+ };
69
+ }
70
+ // Get the default branch name from remote HEAD
71
+ const defaultBranchResult = await runGitCommand([
72
+ "-C",
73
+ path,
74
+ "symbolic-ref",
75
+ "refs/remotes/origin/HEAD",
76
+ "--short",
77
+ ]);
78
+ if (!defaultBranchResult.success) {
79
+ // Fallback: try to reset to origin/main or origin/master
80
+ const resetMain = await runGitCommand(["-C", path, "reset", "--hard", "origin/main"]);
81
+ if (resetMain.success) {
82
+ return { success: true };
83
+ }
84
+ const resetMaster = await runGitCommand(["-C", path, "reset", "--hard", "origin/master"]);
85
+ if (resetMaster.success) {
86
+ return { success: true };
87
+ }
88
+ return {
89
+ success: false,
90
+ error: "Could not determine default branch",
91
+ };
92
+ }
93
+ // Reset to the default branch (e.g., "origin/main" -> reset to that)
94
+ const defaultBranch = defaultBranchResult.stdout.trim();
95
+ const resetResult = await runGitCommand(["-C", path, "reset", "--hard", defaultBranch]);
96
+ if (!resetResult.success) {
97
+ return {
98
+ success: false,
99
+ error: resetResult.stderr,
100
+ };
101
+ }
102
+ return { success: true };
103
+ }
104
+ /**
105
+ * Remove a cloned repository.
106
+ */
107
+ export function removeRepo(info) {
108
+ const path = getRepoPath(info);
109
+ if (!existsSync(path)) {
110
+ return false;
111
+ }
112
+ rmSync(path, { recursive: true, force: true });
113
+ return true;
114
+ }
115
+ /**
116
+ * List all cloned repositories.
117
+ */
118
+ export function listClonedRepos() {
119
+ const cacheDir = getCacheDir();
120
+ const repos = [];
121
+ if (!existsSync(cacheDir)) {
122
+ return repos;
123
+ }
124
+ const owners = readdirSync(cacheDir);
125
+ for (const owner of owners) {
126
+ const ownerPath = join(cacheDir, owner);
127
+ const stat = statSync(ownerPath);
128
+ if (!stat.isDirectory())
129
+ continue;
130
+ const repoNames = readdirSync(ownerPath);
131
+ for (const repo of repoNames) {
132
+ const repoPath = join(ownerPath, repo);
133
+ const gitPath = join(repoPath, ".git");
134
+ if (existsSync(gitPath)) {
135
+ const repoStat = statSync(repoPath);
136
+ repos.push({
137
+ owner,
138
+ repo,
139
+ path: repoPath,
140
+ lastModified: repoStat.mtime,
141
+ });
142
+ }
143
+ }
144
+ }
145
+ return repos.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
146
+ }
147
+ //# sourceMappingURL=repo-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-manager.js","sourceRoot":"","sources":["../../src/repo-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { AliasMap, ClonedRepo, RepoInfo } from "./types.ts";
2
+ export interface ParseResult {
3
+ repoInfo: RepoInfo | null;
4
+ matchedAlias?: {
5
+ alias: string;
6
+ target: string;
7
+ };
8
+ matchedClonedRepo?: ClonedRepo;
9
+ }
10
+ /**
11
+ * Parse various input formats into RepoInfo.
12
+ * Supports: GitHub URLs, owner/repo pairs, aliases, and substring matches against cloned repos.
13
+ */
14
+ export declare function parseRepoInput(input: string, aliases: AliasMap, clonedRepos?: ClonedRepo[]): ParseResult;
15
+ /**
16
+ * Format a RepoInfo as owner/repo string.
17
+ */
18
+ export declare function formatRepo(info: RepoInfo): string;
19
+ //# sourceMappingURL=repo-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-parser.d.ts","sourceRoot":"","sources":["../../src/repo-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiBjE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,iBAAiB,CAAC,EAAE,UAAU,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,QAAQ,EACjB,WAAW,GAAE,UAAU,EAAO,GAC7B,WAAW,CAmFb;AAyBD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,116 @@
1
+ const GITHUB_URL_REGEX = /^(?:https?:\/\/)?(?:www\.)?github\.com\/([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)/;
2
+ const OWNER_REPO_REGEX = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/;
3
+ /**
4
+ * Normalize a GitHub URL by stripping trailing .git, /tree/..., /blob/..., etc.
5
+ */
6
+ function _normalizeUrl(url) {
7
+ return url
8
+ .replace(/\.git$/, "")
9
+ .replace(/\/(tree|blob)\/[^/]+.*$/, "")
10
+ .replace(/\/$/, "");
11
+ }
12
+ /**
13
+ * Parse various input formats into RepoInfo.
14
+ * Supports: GitHub URLs, owner/repo pairs, aliases, and substring matches against cloned repos.
15
+ */
16
+ export function parseRepoInput(input, aliases, clonedRepos = []) {
17
+ const trimmed = input.trim().toLowerCase();
18
+ // Check if it's an exact alias match
19
+ const exactAlias = Object.keys(aliases).find((a) => a.toLowerCase() === trimmed);
20
+ if (exactAlias) {
21
+ const target = aliases[exactAlias];
22
+ const result = parseRepoInputSimple(target);
23
+ return {
24
+ repoInfo: result,
25
+ matchedAlias: { alias: exactAlias, target },
26
+ };
27
+ }
28
+ // Try GitHub URL format
29
+ const urlMatch = input.trim().match(GITHUB_URL_REGEX);
30
+ if (urlMatch) {
31
+ const owner = urlMatch[1];
32
+ const repo = urlMatch[2].replace(/\.git$/, "");
33
+ return {
34
+ repoInfo: {
35
+ owner,
36
+ repo,
37
+ url: `https://github.com/${owner}/${repo}`,
38
+ },
39
+ };
40
+ }
41
+ // Try owner/repo format
42
+ const ownerRepoMatch = input.trim().match(OWNER_REPO_REGEX);
43
+ if (ownerRepoMatch) {
44
+ const owner = ownerRepoMatch[1];
45
+ const repo = ownerRepoMatch[2];
46
+ return {
47
+ repoInfo: {
48
+ owner,
49
+ repo,
50
+ url: `https://github.com/${owner}/${repo}`,
51
+ },
52
+ };
53
+ }
54
+ // Only do substring matching if there's no slash in the input
55
+ // (slash indicates explicit owner/repo format that didn't match above)
56
+ const hasSlash = input.includes("/");
57
+ if (!hasSlash) {
58
+ // Try substring match against cloned repos
59
+ const matchingRepos = clonedRepos.filter((r) => {
60
+ const repoLower = r.repo.toLowerCase();
61
+ return repoLower.includes(trimmed);
62
+ });
63
+ if (matchingRepos.length === 1) {
64
+ const match = matchingRepos[0];
65
+ return {
66
+ repoInfo: {
67
+ owner: match.owner,
68
+ repo: match.repo,
69
+ url: `https://github.com/${match.owner}/${match.repo}`,
70
+ },
71
+ matchedClonedRepo: match,
72
+ };
73
+ }
74
+ // Try substring match against aliases
75
+ const matchingAliases = Object.entries(aliases).filter(([alias, target]) => {
76
+ const aliasLower = alias.toLowerCase();
77
+ const repoName = target.split("/")[1]?.toLowerCase() || "";
78
+ return aliasLower.includes(trimmed) || repoName.includes(trimmed);
79
+ });
80
+ if (matchingAliases.length === 1) {
81
+ const [alias, target] = matchingAliases[0];
82
+ const result = parseRepoInputSimple(target);
83
+ return {
84
+ repoInfo: result,
85
+ matchedAlias: { alias, target },
86
+ };
87
+ }
88
+ }
89
+ return { repoInfo: null };
90
+ }
91
+ /**
92
+ * Simple parse without suggestions (used internally for alias targets).
93
+ */
94
+ function parseRepoInputSimple(input) {
95
+ const trimmed = input.trim();
96
+ const urlMatch = trimmed.match(GITHUB_URL_REGEX);
97
+ if (urlMatch) {
98
+ const owner = urlMatch[1];
99
+ const repo = urlMatch[2].replace(/\.git$/, "");
100
+ return { owner, repo, url: `https://github.com/${owner}/${repo}` };
101
+ }
102
+ const ownerRepoMatch = trimmed.match(OWNER_REPO_REGEX);
103
+ if (ownerRepoMatch) {
104
+ const owner = ownerRepoMatch[1];
105
+ const repo = ownerRepoMatch[2];
106
+ return { owner, repo, url: `https://github.com/${owner}/${repo}` };
107
+ }
108
+ return null;
109
+ }
110
+ /**
111
+ * Format a RepoInfo as owner/repo string.
112
+ */
113
+ export function formatRepo(info) {
114
+ return `${info.owner}/${info.repo}`;
115
+ }
116
+ //# sourceMappingURL=repo-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-parser.js","sourceRoot":"","sources":["../../src/repo-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ export type AliasMap = Record<string, string>;
3
+ export interface PromptConfig {
4
+ /**
5
+ * The instruction that tells the AI how to delegate. Use {path} placeholder.
6
+ * Default: "Delegate to an @explore subagent to answer the following question about the repository at `{path}`:"
7
+ */
8
+ delegateInstruction: string;
9
+ /**
10
+ * Template for the explore prompt. Use {question} placeholder.
11
+ * Default: "{question}"
12
+ */
13
+ exploreTemplate: string;
14
+ }
15
+ export interface Config {
16
+ aliases: AliasMap;
17
+ prompt?: Partial<PromptConfig>;
18
+ }
19
+ export interface RepoInfo {
20
+ owner: string;
21
+ repo: string;
22
+ url: string;
23
+ }
24
+ export interface ClonedRepo {
25
+ owner: string;
26
+ repo: string;
27
+ path: string;
28
+ lastModified: Date;
29
+ }
30
+ export interface CommandContext {
31
+ client: PluginInput["client"];
32
+ $: PluginInput["$"];
33
+ directory: string;
34
+ sessionId: string;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "opencode-ask-github",
3
+ "version": "0.1.0",
4
+ "description": "GitHub repository management plugin for OpenCode - auto-clone repos and analyze with AI",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/JosXa/opencode-ask-github.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/JosXa/opencode-ask-github/issues"
14
+ },
15
+ "homepage": "https://github.com/JosXa/opencode-ask-github#readme",
16
+ "author": "JosXa",
17
+ "license": "MIT",
18
+ "keywords": [
19
+ "opencode",
20
+ "opencode-plugin",
21
+ "github",
22
+ "ai",
23
+ "code-analysis",
24
+ "repository"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "engines": {
30
+ "bun": ">=1.0.0"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc -p tsconfig.build.json",
34
+ "typecheck": "tsc --noEmit",
35
+ "format:check": "biome check .",
36
+ "format:fix": "biome check --write ."
37
+ },
38
+ "files": [
39
+ "dist"
40
+ ],
41
+ "devDependencies": {
42
+ "@biomejs/biome": "^2.0.0",
43
+ "@types/bun": "^1.2.0",
44
+ "typescript": "^5.8.0"
45
+ },
46
+ "peerDependencies": {
47
+ "@opencode-ai/plugin": ">=1.0.0"
48
+ }
49
+ }