11import { describe , it , expect } from "bun:test" ;
2+ import { mkdtempSync , readFileSync , realpathSync , rmSync } from "fs" ;
3+ import { tmpdir } from "os" ;
4+ import { join } from "path" ;
25import { CursorPlugin } from "../../src/plugin" ;
36import type { PluginInput } from "@opencode-ai/plugin" ;
47
8+ function createMockInput ( directory : string ) : PluginInput {
9+ return {
10+ directory,
11+ worktree : directory ,
12+ serverUrl : new URL ( "http://localhost:8080" ) ,
13+ client : {
14+ tool : {
15+ list : async ( ) => [ ] ,
16+ } ,
17+ } as any ,
18+ project : { } as any ,
19+ $ : { } as any ,
20+ } ;
21+ }
22+
23+ function createToolContext ( directory : string ) : any {
24+ return {
25+ sessionID : "test-session" ,
26+ messageID : "test-message" ,
27+ agent : "test-agent" ,
28+ directory,
29+ worktree : directory ,
30+ abort : new AbortController ( ) . signal ,
31+ metadata : ( ) => { } ,
32+ ask : async ( ) => { } ,
33+ } ;
34+ }
35+
536describe ( "Plugin tool hook" , ( ) => {
637 it ( "should register default tools via tool hook" , async ( ) => {
7- // Mock PluginInput
8- const mockInput : PluginInput = {
9- directory : "/test/dir" ,
10- worktree : "/test/dir" ,
11- serverUrl : new URL ( "http://localhost:8080" ) ,
12- client : {
13- tool : {
14- list : async ( ) => [ ] ,
15- } ,
16- } as any ,
17- project : { } as any ,
18- $ : { } as any ,
19- } ;
38+ const mockInput = createMockInput ( "/test/dir" ) ;
2039
2140 // Initialize plugin
2241 const hooks = await CursorPlugin ( mockInput ) ;
@@ -42,4 +61,41 @@ describe("Plugin tool hook", () => {
4261 expect ( bashTool ?. args ) . toBeDefined ( ) ;
4362 expect ( typeof bashTool ?. execute ) . toBe ( "function" ) ;
4463 } ) ;
64+
65+ it ( "resolves relative write paths against context directory" , async ( ) => {
66+ const projectDir = mkdtempSync ( join ( tmpdir ( ) , "plugin-hook-write-" ) ) ;
67+ try {
68+ const hooks = await CursorPlugin ( createMockInput ( projectDir ) ) ;
69+ const out = await hooks . tool ?. write ?. execute (
70+ {
71+ path : "nested/output.txt" ,
72+ content : "hello from context" ,
73+ } ,
74+ createToolContext ( projectDir ) ,
75+ ) ;
76+
77+ const expectedPath = join ( projectDir , "nested/output.txt" ) ;
78+ expect ( readFileSync ( expectedPath , "utf-8" ) ) . toBe ( "hello from context" ) ;
79+ expect ( out ) . toContain ( expectedPath ) ;
80+ } finally {
81+ rmSync ( projectDir , { recursive : true , force : true } ) ;
82+ }
83+ } ) ;
84+
85+ it ( "defaults bash cwd to context directory" , async ( ) => {
86+ const projectDir = mkdtempSync ( join ( tmpdir ( ) , "plugin-hook-bash-" ) ) ;
87+ try {
88+ const hooks = await CursorPlugin ( createMockInput ( projectDir ) ) ;
89+ const out = await hooks . tool ?. bash ?. execute (
90+ {
91+ command : "pwd" ,
92+ } ,
93+ createToolContext ( projectDir ) ,
94+ ) ;
95+
96+ expect ( realpathSync ( ( out || "" ) . trim ( ) ) ) . toBe ( realpathSync ( projectDir ) ) ;
97+ } finally {
98+ rmSync ( projectDir , { recursive : true , force : true } ) ;
99+ }
100+ } ) ;
45101} ) ;
0 commit comments