opencode-froggy 0.11.0 → 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.
Files changed (46) hide show
  1. package/README.md +29 -9
  2. package/command/diff-summary.md +27 -8
  3. package/command/doc-changes.md +1 -0
  4. package/command/linear-stale-check.md +199 -0
  5. package/command/review-changes.md +1 -0
  6. package/command/review-pr.md +1 -0
  7. package/command/simplify-changes.md +1 -0
  8. package/dist/command-installer.d.ts +6 -0
  9. package/dist/command-installer.js +49 -0
  10. package/dist/command-installer.test.d.ts +1 -0
  11. package/dist/command-installer.test.js +58 -0
  12. package/dist/config-paths.d.ts +2 -0
  13. package/dist/config-paths.js +6 -0
  14. package/dist/config-paths.test.js +16 -0
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +326 -259
  17. package/dist/index.test.js +3 -3
  18. package/dist/loaders.d.ts +2 -0
  19. package/dist/loaders.js +1 -0
  20. package/dist/session-children.d.ts +14 -0
  21. package/dist/session-children.js +27 -0
  22. package/dist/session-children.test.d.ts +1 -0
  23. package/dist/session-children.test.js +25 -0
  24. package/dist/skill-activation.js +1 -1
  25. package/dist/tools/agent-promote.d.ts +38 -11
  26. package/dist/tools/agent-promote.js +35 -33
  27. package/dist/tools/blockchain/eth-address-balance.d.ts +18 -8
  28. package/dist/tools/blockchain/eth-address-balance.js +15 -14
  29. package/dist/tools/blockchain/eth-address-txs.d.ts +22 -10
  30. package/dist/tools/blockchain/eth-address-txs.js +19 -18
  31. package/dist/tools/blockchain/eth-token-transfers.d.ts +22 -10
  32. package/dist/tools/blockchain/eth-token-transfers.js +19 -18
  33. package/dist/tools/blockchain/eth-transaction.d.ts +30 -14
  34. package/dist/tools/blockchain/eth-transaction.js +24 -21
  35. package/dist/tools/gitingest.d.ts +27 -15
  36. package/dist/tools/gitingest.js +28 -21
  37. package/dist/tools/index.d.ts +1 -1
  38. package/dist/tools/index.js +1 -1
  39. package/dist/tools/list-child-sessions.d.ts +11 -7
  40. package/dist/tools/list-child-sessions.js +22 -17
  41. package/dist/tools/pdf-to-markdown.d.ts +18 -8
  42. package/dist/tools/pdf-to-markdown.js +20 -13
  43. package/dist/tools/prompt-session.d.ts +26 -11
  44. package/dist/tools/prompt-session.js +23 -28
  45. package/package.json +13 -5
  46. package/tui.ts +24 -0
package/README.md CHANGED
@@ -56,16 +56,18 @@ Add the plugin to your OpenCode configuration file (`opencode.json`):
56
56
  ```json
57
57
  {
58
58
  "$schema": "https://opencode.ai/config.json",
59
- "plugin": ["opencode-froggy"]
59
+ "plugins": ["opencode-froggy"]
60
60
  }
61
61
  ```
62
62
 
63
+ Requires OpenCode V2.
64
+
63
65
  ### From local files
64
66
 
65
67
  Alternatively, clone or copy the plugin files to one of these directories:
66
68
 
67
- - **Project-local**: `.opencode/plugin/opencode-froggy/`
68
- - **Global**: `~/.config/opencode/plugin/opencode-froggy/`
69
+ - **Project-local**: `.opencode/plugins/opencode-froggy/`
70
+ - **Global**: `~/.config/opencode/plugins/opencode-froggy/`
69
71
 
70
72
  ---
71
73
 
@@ -78,6 +80,7 @@ Alternatively, clone or copy the plugin files to one of these directories:
78
80
  | `/commit-push` | Stage, commit, and push changes with user confirmation | `build` |
79
81
  | `/diff-summary [source] [target]` | Show working tree changes or diff between branches | - |
80
82
  | `/doc-changes` | Update documentation based on uncommitted changes (new features only) | `doc-writer` |
83
+ | `/linear-stale-check` | Review open Linear issues for the configured team and report whether they are likely active, uncertain, or obsolete | `plan` |
81
84
  | `/review-changes` | Review uncommitted changes (staged, unstaged, untracked) | `code-reviewer` |
82
85
  | `/review-pr <source> <target>` | Review diff from source branch into target branch | `code-reviewer` |
83
86
  | `/send-to [agent] <message>` | Send a message to a child session (subagent) to continue the conversation | - |
@@ -104,6 +107,24 @@ Shows staged changes, unstaged changes, and untracked file contents.
104
107
  ```
105
108
  Shows stats overview, commits, files changed, and full diff between branches.
106
109
 
110
+ ### /linear-stale-check
111
+
112
+ Analyzes open Linear issues for the team configured in `AGENTS.md` with:
113
+
114
+ ```text
115
+ Linear team: <name>
116
+ ```
117
+
118
+ If no team is configured, the command lists available Linear teams and asks which one to use for the current run.
119
+
120
+ The command is read-only. It fetches open issues, investigates related code, skips code investigation for issues already `In Progress`, and outputs a single report grouped by verdict:
121
+
122
+ - 🔴 Likely obsolete
123
+ - 🟡 Uncertain
124
+ - 🟢 Likely active
125
+
126
+ It does not modify Linear issues, add comments, or update project files.
127
+
107
128
  ---
108
129
 
109
130
  ## Agents
@@ -121,7 +142,7 @@ Shows stats overview, commits, files changed, and full diff between branches.
121
142
 
122
143
  ## Skills
123
144
 
124
- Skills are contextual instructions loaded on demand via the `skill` tool. The agent invokes `skill({ name: "skill-name" })` to load the instructions when needed.
145
+ Skills are contextual instructions loaded on demand via the `skill` tool. The agent invokes `skill({ id: "skill-name" })` to load the instructions when needed.
125
146
 
126
147
  ### Overview
127
148
 
@@ -251,7 +272,7 @@ A skill without `name` or `description` will be ignored.
251
272
  If a skill defines `use_when`, a directive is injected into the system prompt:
252
273
 
253
274
  ```
254
- MANDATORY: Call skill({ name: "my-skill" }) <use_when content>
275
+ MANDATORY: Call skill({ id: "my-skill" }) <use_when content>
255
276
  ```
256
277
 
257
278
  This instructs the agent to load the skill when the specified condition is met.
@@ -342,8 +363,8 @@ promptSession({
342
363
 
343
364
  #### Behavior
344
365
 
345
- - If `sessionId` is not provided, the tool automatically targets the most recently created child session
346
- - Returns the text response from the child session
366
+ - If `sessionId` is not provided, the tool targets the most recently created child session tracked since the plugin loaded (pass `sessionId` explicitly for older sessions)
367
+ - Returns a confirmation once the message is admitted to the child session
347
368
  - Returns an error message if no child session exists for the current session
348
369
 
349
370
  ---
@@ -449,8 +470,7 @@ Promote an agent to primary (default) or specify a grade.
449
470
  #### Notes
450
471
 
451
472
  - Only agents from this plugin can be promoted (see [Agents](#agents) table)
452
- - Changes persist in memory until OpenCode restarts
453
- - After promotion, use `Tab` or `<leader>a` to select the agent
473
+ - Changes apply immediately and persist across restarts via plugin storage
454
474
 
455
475
  ---
456
476
 
@@ -4,30 +4,49 @@ description: Show working tree changes or diff between branches ($1=source, $2=t
4
4
 
5
5
  # Diff Summary
6
6
 
7
+ Branch arguments (if provided): source=$1 target=$2
8
+
7
9
  !`bash -c '
8
10
  SOURCE="$1"
9
11
  TARGET="$2"
10
12
  TARGET="${TARGET:-HEAD}"
11
13
 
14
+ valid_ref() {
15
+ case "$REF" in
16
+ ""|-*) return 1 ;;
17
+ esac
18
+ git rev-parse --verify --quiet "$REF^{commit}" >/dev/null
19
+ }
20
+
12
21
  if [ -n "$SOURCE" ]; then
22
+ REF="$SOURCE"
23
+ if ! valid_ref; then
24
+ echo "Invalid source ref: $SOURCE"
25
+ exit 0
26
+ fi
27
+ REF="$TARGET"
28
+ if ! valid_ref; then
29
+ echo "Invalid target ref: $TARGET"
30
+ exit 0
31
+ fi
13
32
  echo "## Branch Comparison: $SOURCE → $TARGET"
14
33
  echo ""
15
34
  git fetch --all --prune 2>/dev/null || true
16
-
35
+
17
36
  echo "### Stats Overview"
18
- git diff --stat "$TARGET"..."$SOURCE"
19
-
37
+ git diff --stat "$TARGET"..."$SOURCE" --
38
+
20
39
  echo ""
21
40
  echo "### Commits"
22
- git log --oneline --no-merges "$TARGET".."$SOURCE"
23
-
41
+ git log --oneline --no-merges "$TARGET".."$SOURCE" --
42
+
24
43
  echo ""
25
44
  echo "### Files Changed"
26
- git diff --name-only "$TARGET"..."$SOURCE"
27
-
45
+ git diff --name-only "$TARGET"..."$SOURCE" --
46
+
28
47
  echo ""
29
48
  echo "### Full Diff"
30
- git diff "$TARGET"..."$SOURCE"
49
+ git diff "$TARGET"..."$SOURCE" --
31
50
  else
32
51
  echo "## Status"
33
52
  git status --porcelain
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Update documentation based on uncommitted changes (new features only)
3
3
  agent: doc-writer
4
+ subagent: true
4
5
  ---
5
6
 
6
7
  ## Analysis Phase
@@ -0,0 +1,199 @@
1
+ ---
2
+ description: Review open Linear issues to check if they are still relevant
3
+ agent: plan
4
+ ---
5
+
6
+ ## Your task
7
+
8
+ Analyze the team's open Linear issues, diagnose each one by combining Linear
9
+ metadata with codebase investigation, and present a single report.
10
+
11
+ This command is read-only:
12
+ - Do not ask the user questions except when `AGENTS.md` does not define a
13
+ Linear team.
14
+ - Do not modify any Linear issue.
15
+ - Do not add comments to Linear issues.
16
+ - Do not modify `AGENTS.md` or any other project file.
17
+ - Do not start an iterative review loop.
18
+
19
+ The user will read the report and decide what to do next.
20
+
21
+ ## 1. Resolve the Linear team
22
+
23
+ Read `AGENTS.md` from the current project and look for a plain-text line:
24
+
25
+ ```text
26
+ Linear team: <name>
27
+ ```
28
+
29
+ If the line exists, use `<name>` as the Linear team.
30
+
31
+ If the line does not exist:
32
+ - Use `linear_list_teams` to list available teams.
33
+ - Ask the user to choose one of the available teams with the `question` tool.
34
+ - Use the selected team for this run.
35
+ - Continue the stale-check report normally.
36
+ - Do not write to `AGENTS.md` yourself.
37
+
38
+ ## 2. Fetch open issues
39
+
40
+ Use `linear_list_issues` for the resolved team:
41
+ - `team`: resolved Linear team name
42
+ - omit `state` entirely; do not pass `uncompleted`, `backlog`, `unstarted`,
43
+ `started`, an empty string, or any other status-type alias
44
+ - omit `priority` entirely; do not pass `priority: 0` because that filters to
45
+ issues with no priority
46
+ - `orderBy`: `updatedAt`, oldest first
47
+ - fetch all matching issues by paginating until there are no more pages
48
+
49
+ Only pass filters that are intentionally active. For unused filters, omit the
50
+ field entirely instead of passing an empty, zero, or placeholder value. In
51
+ particular, `priority: 0` is an active Linear filter for "No priority" and
52
+ will exclude Medium, High, and Urgent issues.
53
+
54
+ After fetching all team issues, filter locally:
55
+ - keep issues whose `statusType` is not `completed`
56
+ - keep issues whose `statusType` is not `canceled`
57
+
58
+ Do not rely on Linear state-type aliases for this command. They can return
59
+ incomplete results. Fetch broadly for the team, then filter locally by
60
+ `statusType`.
61
+
62
+ For each retained issue, load detailed data with `linear_get_issue` and include relations:
63
+ - title
64
+ - description
65
+ - URL
66
+ - state
67
+ - priority
68
+ - assignee
69
+ - labels
70
+ - project
71
+ - createdAt
72
+ - updatedAt
73
+ - blocking and blocked-by relations
74
+
75
+ ## 3. Diagnose each issue
76
+
77
+ Diagnose every fetched issue before producing the final report.
78
+
79
+ ### Linear signals
80
+
81
+ Compute these signals for every issue:
82
+ - Days since last update.
83
+ - No assignee.
84
+ - No project.
85
+ - No useful description.
86
+ - `In Progress` but inactive for more than 30 days.
87
+ - Blockers are already closed or canceled.
88
+
89
+ ### Code investigation
90
+
91
+ Run code investigation for every issue except issues whose state is exactly
92
+ `In Progress`.
93
+
94
+ For `In Progress` issues, set code signals to:
95
+
96
+ ```text
97
+ skipped (in progress)
98
+ ```
99
+
100
+ For all other issues, investigate the codebase directly with read-only search
101
+ tools and git history commands. Run searches in parallel batches when possible.
102
+
103
+ For each issue, use:
104
+ - the Linear identifier
105
+ - the title
106
+ - a concise description excerpt
107
+ - candidate keywords from the title and description
108
+
109
+ Candidate keywords should include:
110
+ - mentioned files or modules
111
+ - function, class, type, command, hook, or config names
112
+ - the Linear identifier itself
113
+ - meaningful product or domain terms
114
+
115
+ Search for relevance signals and keep the result to 3-5 concise lines:
116
+ - Does the mentioned code or feature still exist?
117
+ - Is the Linear identifier referenced in code, comments, TODOs, branches, or recent commits?
118
+ - Is there recent git activity on related files or symbols?
119
+ - Are there signs the feature was removed, renamed, or replaced?
120
+
121
+ Summarize the returned investigation as code signals:
122
+ - code or feature found
123
+ - code or feature not found
124
+ - identifier referenced
125
+ - recent git activity found
126
+ - no recent git activity found
127
+ - no code correlation found
128
+
129
+ ## 4. Assign a verdict
130
+
131
+ Assign exactly one verdict per issue:
132
+
133
+ - 🔴 Likely obsolete
134
+ - 🟡 Uncertain
135
+ - 🟢 Likely active
136
+
137
+ Use these rules as guidance, but apply judgment based on the full evidence.
138
+
139
+ For `In Progress` issues, base the verdict on update age only:
140
+ - updated less than 30 days ago: 🟢 Likely active
141
+ - updated 30-90 days ago: 🟡 Uncertain
142
+ - updated more than 90 days ago: 🔴 Likely obsolete
143
+
144
+ For other issues:
145
+ - Use 🟢 Likely active when the issue is referenced in code, has recent related git activity, or clearly describes current code.
146
+ - Use 🟡 Uncertain when signals are mixed or weak.
147
+ - Use 🔴 Likely obsolete when mentioned code is missing, the feature appears removed or replaced, or the issue has weak Linear signals and no code correlation.
148
+
149
+ ## 5. Output a single report
150
+
151
+ Output one report only. Sort by verdict in this order:
152
+ 1. 🔴 Likely obsolete
153
+ 2. 🟡 Uncertain
154
+ 3. 🟢 Likely active
155
+
156
+ Use this structure:
157
+
158
+ ```markdown
159
+ # Linear Stale-Check Report
160
+
161
+ Team: <team>
162
+ Issues analyzed: <count>
163
+
164
+ ## 🔴 Likely Obsolete (<count>)
165
+
166
+ ### LIN-123 — Issue title
167
+
168
+ URL: <Linear URL>
169
+ State: <state> | Priority: <priority> | Assignee: <assignee or none> | Updated: <N>d ago
170
+ Project: <project or none> | Labels: <labels or none>
171
+
172
+ Summary: <1-2 line summary of the issue>
173
+
174
+ Linear signals:
175
+ - <signal>
176
+ - <signal>
177
+
178
+ Code signals:
179
+ - <signal>
180
+ - <signal>
181
+
182
+ Verdict: 🔴 Likely obsolete — <short reason>
183
+
184
+ ## 🟡 Uncertain (<count>)
185
+
186
+ ...
187
+
188
+ ## 🟢 Likely Active (<count>)
189
+
190
+ ...
191
+ ```
192
+
193
+ Keep each issue concise. Prefer useful evidence over speculation.
194
+
195
+ End the report with:
196
+
197
+ ```text
198
+ End of report. No issues were modified.
199
+ ```
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Review uncommitted changes (staged + unstaged, incl. untracked diffs)
3
3
  agent: code-reviewer
4
+ subagent: true
4
5
  ---
5
6
 
6
7
  # Review: Working Tree → HEAD
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Review changes from source branch into target branch
3
3
  agent: code-reviewer
4
+ subagent: true
4
5
  ---
5
6
 
6
7
  # Review: $1 → $2
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Simplify uncommitted changes (staged + unstaged, incl. untracked diffs)
3
3
  agent: code-simplifier
4
+ subagent: true
4
5
  ---
5
6
 
6
7
  # Simplify: Working Tree → HEAD
@@ -0,0 +1,6 @@
1
+ export interface InstallFilesResult {
2
+ installed: string[];
3
+ skipped: string[];
4
+ updated: string[];
5
+ }
6
+ export declare function installBundledFiles(sourceDir: string, targetDir: string): InstallFilesResult;
@@ -0,0 +1,49 @@
1
+ import { constants, copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { log } from "./logger";
4
+ export function installBundledFiles(sourceDir, targetDir) {
5
+ const installed = [];
6
+ const skipped = [];
7
+ const updated = [];
8
+ if (!existsSync(sourceDir))
9
+ return { installed, skipped, updated };
10
+ try {
11
+ mkdirSync(targetDir, { recursive: true });
12
+ }
13
+ catch (error) {
14
+ log("[commands] failed to prepare target dir", { targetDir, error: String(error) });
15
+ return { installed, skipped, updated };
16
+ }
17
+ let files;
18
+ try {
19
+ files = readdirSync(sourceDir);
20
+ }
21
+ catch (error) {
22
+ log("[commands] failed to read bundled files", { sourceDir, error: String(error) });
23
+ return { installed, skipped, updated };
24
+ }
25
+ for (const file of files) {
26
+ if (!file.endsWith(".md"))
27
+ continue;
28
+ const source = join(sourceDir, file);
29
+ const target = join(targetDir, file);
30
+ try {
31
+ const content = readFileSync(source, "utf-8");
32
+ if (!existsSync(target)) {
33
+ copyFileSync(source, target, constants.COPYFILE_EXCL);
34
+ installed.push(file);
35
+ continue;
36
+ }
37
+ if (readFileSync(target, "utf-8") !== content) {
38
+ copyFileSync(source, target);
39
+ updated.push(file);
40
+ continue;
41
+ }
42
+ skipped.push(file);
43
+ }
44
+ catch (error) {
45
+ log("[commands] failed to install bundled file", { file, error: String(error) });
46
+ }
47
+ }
48
+ return { installed, skipped, updated };
49
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,58 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
+ import { installBundledFiles } from "./command-installer";
6
+ describe("installBundledFiles", () => {
7
+ let sourceDir;
8
+ let targetDir;
9
+ beforeEach(() => {
10
+ const base = join(tmpdir(), `froggy-files-${Date.now()}-${Math.random().toString(16).slice(2)}`);
11
+ sourceDir = join(base, "source");
12
+ targetDir = join(base, "target");
13
+ mkdirSync(sourceDir, { recursive: true });
14
+ });
15
+ afterEach(() => {
16
+ rmSync(join(sourceDir, ".."), { recursive: true, force: true });
17
+ });
18
+ it("installs missing files", () => {
19
+ writeFileSync(join(sourceDir, "review-pr.md"), "# review");
20
+ const result = installBundledFiles(sourceDir, targetDir);
21
+ expect(result.installed).toEqual(["review-pr.md"]);
22
+ expect(readFileSync(join(targetDir, "review-pr.md"), "utf-8")).toBe("# review");
23
+ });
24
+ it("skips existing files with identical content", () => {
25
+ writeFileSync(join(sourceDir, "review-pr.md"), "# bundled");
26
+ mkdirSync(targetDir, { recursive: true });
27
+ writeFileSync(join(targetDir, "review-pr.md"), "# bundled");
28
+ const result = installBundledFiles(sourceDir, targetDir);
29
+ expect(result.skipped).toEqual(["review-pr.md"]);
30
+ expect(readFileSync(join(targetDir, "review-pr.md"), "utf-8")).toBe("# bundled");
31
+ });
32
+ it("updates an existing file when the bundled content differs", () => {
33
+ writeFileSync(join(sourceDir, "review-pr.md"), "# v2");
34
+ mkdirSync(targetDir, { recursive: true });
35
+ writeFileSync(join(targetDir, "review-pr.md"), "# v1");
36
+ const result = installBundledFiles(sourceDir, targetDir);
37
+ expect(result.updated).toEqual(["review-pr.md"]);
38
+ expect(readFileSync(join(targetDir, "review-pr.md"), "utf-8")).toBe("# v2");
39
+ });
40
+ it("never deletes a user-customized file", () => {
41
+ writeFileSync(join(sourceDir, "review-pr.md"), "# bundled");
42
+ mkdirSync(targetDir, { recursive: true });
43
+ writeFileSync(join(targetDir, "review-pr.md"), "# user customization");
44
+ const result = installBundledFiles(sourceDir, targetDir);
45
+ expect(result.updated).toEqual(["review-pr.md"]);
46
+ expect(existsSync(join(targetDir, "review-pr.md"))).toBe(true);
47
+ });
48
+ it("ignores non-markdown files", () => {
49
+ writeFileSync(join(sourceDir, "notes.txt"), "notes");
50
+ const result = installBundledFiles(sourceDir, targetDir);
51
+ expect(result.installed).toEqual([]);
52
+ expect(existsSync(join(targetDir, "notes.txt"))).toBe(false);
53
+ });
54
+ it("returns empty result for missing source dir", () => {
55
+ const result = installBundledFiles(join(sourceDir, "missing"), targetDir);
56
+ expect(result).toEqual({ installed: [], skipped: [], updated: [] });
57
+ });
58
+ });
@@ -9,3 +9,5 @@
9
9
  export declare function getUserConfigDir(): string;
10
10
  export declare function getGlobalHookDir(): string;
11
11
  export declare function getProjectHookDir(directory: string): string;
12
+ export declare function getGlobalCommandDir(): string;
13
+ export declare function getGlobalAgentDir(): string;
@@ -30,3 +30,9 @@ export function getGlobalHookDir() {
30
30
  export function getProjectHookDir(directory) {
31
31
  return join(directory, ".opencode", "hook");
32
32
  }
33
+ export function getGlobalCommandDir() {
34
+ return join(getUserConfigDir(), "opencode", "commands");
35
+ }
36
+ export function getGlobalAgentDir() {
37
+ return join(getUserConfigDir(), "opencode", "agents");
38
+ }
@@ -86,6 +86,22 @@ describe("config-paths", () => {
86
86
  expect(getGlobalHookDir()).toBe("/custom/config/opencode/hook");
87
87
  });
88
88
  });
89
+ describe("getGlobalCommandDir", () => {
90
+ it("should return correct path on Linux", async () => {
91
+ Object.defineProperty(process, "platform", { value: "linux" });
92
+ delete process.env.XDG_CONFIG_HOME;
93
+ const { getGlobalCommandDir } = await import("./config-paths");
94
+ expect(getGlobalCommandDir()).toBe(join(homedir(), ".config", "opencode", "commands"));
95
+ });
96
+ });
97
+ describe("getGlobalAgentDir", () => {
98
+ it("should return correct path on Linux", async () => {
99
+ Object.defineProperty(process, "platform", { value: "linux" });
100
+ delete process.env.XDG_CONFIG_HOME;
101
+ const { getGlobalAgentDir } = await import("./config-paths");
102
+ expect(getGlobalAgentDir()).toBe(join(homedir(), ".config", "opencode", "agents"));
103
+ });
104
+ });
89
105
  describe("getProjectHookDir", () => {
90
106
  it("should return correct path for project directory", async () => {
91
107
  const { getProjectHookDir } = await import("./config-paths");
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { type Plugin } from "@opencode-ai/plugin";
1
+ import { Plugin } from "@opencode/plugin";
2
2
  export { parseFrontmatter, loadAgents, loadCommands, type LoadedSkill } from "./loaders";
3
3
  export { buildSkillActivationBlock } from "./skill-activation";
4
- declare const SmartfrogPlugin: Plugin;
5
- export default SmartfrogPlugin;
4
+ declare const _default: Plugin.Plugin;
5
+ export default _default;