Dax Raad пре 8 месеци
родитељ
комит
d6afebf22a

+ 12 - 0
packages/opencode/src/bus/index.ts

@@ -78,6 +78,18 @@ export namespace Bus {
     return raw(def.type, callback)
     return raw(def.type, callback)
   }
   }
 
 
+  export function once<Definition extends EventDefinition>(
+    def: Definition,
+    callback: (event: {
+      type: Definition["type"]
+      properties: z.infer<Definition["properties"]>
+    }) => "done" | undefined,
+  ) {
+    const unsub = subscribe(def, (event) => {
+      if (callback(event)) unsub()
+    })
+  }
+
   export function subscribeAll(callback: (event: any) => void) {
   export function subscribeAll(callback: (event: any) => void) {
     return raw("*", callback)
     return raw("*", callback)
   }
   }

+ 2 - 3
packages/opencode/src/cli/cmd/scrap.ts

@@ -12,9 +12,8 @@ export const ScrapCommand = cmd({
     await App.provide(
     await App.provide(
       { cwd: process.cwd(), version: VERSION, printLogs: true },
       { cwd: process.cwd(), version: VERSION, printLogs: true },
       async () => {
       async () => {
-        await LSP.file(args.file)
-        const diagnostics = await LSP.diagnostics()
-        console.log(diagnostics)
+        await LSP.touchFile(args.file, true)
+        await LSP.diagnostics()
       },
       },
     )
     )
   },
   },

+ 10 - 6
packages/opencode/src/lsp/client.ts

@@ -117,6 +117,7 @@ export namespace LSPClient {
         textDocument: {
         textDocument: {
           synchronization: {
           synchronization: {
             didOpen: true,
             didOpen: true,
+            didChange: true,
           },
           },
           publishDiagnostics: {
           publishDiagnostics: {
             versionSupport: true,
             versionSupport: true,
@@ -127,7 +128,9 @@ export namespace LSPClient {
     await connection.sendNotification("initialized", {})
     await connection.sendNotification("initialized", {})
     log.info("initialized")
     log.info("initialized")
 
 
-    const files = new Set<string>()
+    const files: {
+      [path: string]: number
+    } = {}
 
 
     const result = {
     const result = {
       get clientID() {
       get clientID() {
@@ -143,8 +146,8 @@ export namespace LSPClient {
             : path.resolve(app.path.cwd, input.path)
             : path.resolve(app.path.cwd, input.path)
           const file = Bun.file(input.path)
           const file = Bun.file(input.path)
           const text = await file.text()
           const text = await file.text()
-          const opened = files.has(input.path)
-          if (!opened) {
+          const version = files[input.path]
+          if (version === undefined) {
             log.info("textDocument/didOpen", input)
             log.info("textDocument/didOpen", input)
             diagnostics.delete(input.path)
             diagnostics.delete(input.path)
             const extension = path.extname(input.path)
             const extension = path.extname(input.path)
@@ -153,11 +156,11 @@ export namespace LSPClient {
               textDocument: {
               textDocument: {
                 uri: `file://` + input.path,
                 uri: `file://` + input.path,
                 languageId,
                 languageId,
-                version: Date.now(),
+                version: 0,
                 text,
                 text,
               },
               },
             })
             })
-            files.add(input.path)
+            files[input.path] = 0
             return
             return
           }
           }
 
 
@@ -166,7 +169,7 @@ export namespace LSPClient {
           await connection.sendNotification("textDocument/didChange", {
           await connection.sendNotification("textDocument/didChange", {
             textDocument: {
             textDocument: {
               uri: `file://` + input.path,
               uri: `file://` + input.path,
-              version: Date.now(),
+              version: ++files[input.path],
             },
             },
             contentChanges: [
             contentChanges: [
               {
               {
@@ -213,6 +216,7 @@ export namespace LSPClient {
         log.info("shutting down")
         log.info("shutting down")
         connection.end()
         connection.end()
         connection.dispose()
         connection.dispose()
+        server.kill()
       },
       },
     }
     }
 
 

+ 8 - 6
packages/opencode/src/lsp/index.ts

@@ -23,7 +23,7 @@ export namespace LSP {
     },
     },
   )
   )
 
 
-  export async function file(input: string) {
+  export async function touchFile(input: string, waitForDiagnostics?: boolean) {
     const extension = path.parse(input).ext
     const extension = path.parse(input).ext
     const s = await state()
     const s = await state()
     const matches = AUTO.filter((x) => x.extensions.includes(extension))
     const matches = AUTO.filter((x) => x.extensions.includes(extension))
@@ -40,11 +40,13 @@ export namespace LSP {
       })
       })
       s.clients.set(match.id, client)
       s.clients.set(match.id, client)
     }
     }
-    await run(async (client) => {
-      const wait = client.waitForDiagnostics({ path: input })
-      await client.notify.open({ path: input })
-      return wait
-    })
+    if (waitForDiagnostics) {
+      await run(async (client) => {
+        const wait = client.waitForDiagnostics({ path: input })
+        await client.notify.open({ path: input })
+        return wait
+      })
+    }
   }
   }
 
 
   export async function diagnostics() {
   export async function diagnostics() {

+ 1 - 1
packages/opencode/src/tool/edit.ts

@@ -90,7 +90,7 @@ export const EditTool = Tool.define({
     FileTimes.read(ctx.sessionID, filepath)
     FileTimes.read(ctx.sessionID, filepath)
 
 
     let output = ""
     let output = ""
-    await LSP.file(filepath)
+    await LSP.touchFile(filepath, true)
     const diagnostics = await LSP.diagnostics()
     const diagnostics = await LSP.diagnostics()
     for (const [file, issues] of Object.entries(diagnostics)) {
     for (const [file, issues] of Object.entries(diagnostics)) {
       if (issues.length === 0) continue
       if (issues.length === 0) continue

+ 1 - 1
packages/opencode/src/tool/lsp-diagnostics.ts

@@ -16,7 +16,7 @@ export const LspDiagnosticTool = Tool.define({
     const normalized = path.isAbsolute(args.path)
     const normalized = path.isAbsolute(args.path)
       ? args.path
       ? args.path
       : path.join(app.path.cwd, args.path)
       : path.join(app.path.cwd, args.path)
-    await LSP.file(normalized)
+    await LSP.touchFile(normalized, true)
     const diagnostics = await LSP.diagnostics()
     const diagnostics = await LSP.diagnostics()
     const file = diagnostics[normalized]
     const file = diagnostics[normalized]
     return {
     return {

+ 2 - 2
packages/opencode/src/tool/lsp-hover.ts

@@ -18,12 +18,12 @@ export const LspHoverTool = Tool.define({
     const file = path.isAbsolute(args.file)
     const file = path.isAbsolute(args.file)
       ? args.file
       ? args.file
       : path.join(app.path.cwd, args.file)
       : path.join(app.path.cwd, args.file)
-    await LSP.file(file)
+    await LSP.touchFile(file, true)
     const result = await LSP.hover({
     const result = await LSP.hover({
       ...args,
       ...args,
       file,
       file,
     })
     })
-    console.log(result)
+
     return {
     return {
       metadata: {
       metadata: {
         result,
         result,

+ 1 - 1
packages/opencode/src/tool/read.ts

@@ -88,7 +88,7 @@ export const ReadTool = Tool.define({
     output += "\n</file>"
     output += "\n</file>"
 
 
     // just warms the lsp client
     // just warms the lsp client
-    LSP.file(filePath)
+    await LSP.touchFile(filePath, true)
     FileTimes.read(ctx.sessionID, filePath)
     FileTimes.read(ctx.sessionID, filePath)
 
 
     return {
     return {

+ 1 - 1
packages/opencode/src/tool/write.ts

@@ -43,7 +43,7 @@ export const WriteTool = Tool.define({
     FileTimes.read(ctx.sessionID, filepath)
     FileTimes.read(ctx.sessionID, filepath)
 
 
     let output = ""
     let output = ""
-    await LSP.file(filepath)
+    await LSP.touchFile(filepath, true)
     const diagnostics = await LSP.diagnostics()
     const diagnostics = await LSP.diagnostics()
     for (const [file, issues] of Object.entries(diagnostics)) {
     for (const [file, issues] of Object.entries(diagnostics)) {
       if (issues.length === 0) continue
       if (issues.length === 0) continue