2
0
Dax Raad 10 сар өмнө
parent
commit
e97ed735d9

+ 1 - 1
.gitignore

@@ -2,4 +2,4 @@ node_modules
 .opencode
 .opencode
 .sst
 .sst
 app.log
 app.log
-
+.env

+ 1 - 0
bun.lock

@@ -28,6 +28,7 @@
         "ai": "catalog:",
         "ai": "catalog:",
         "cac": "6.7.14",
         "cac": "6.7.14",
         "decimal.js": "10.5.0",
         "decimal.js": "10.5.0",
+        "diff": "8.0.2",
         "env-paths": "3.0.0",
         "env-paths": "3.0.0",
         "hono": "4.7.10",
         "hono": "4.7.10",
         "hono-openapi": "0.4.8",
         "hono-openapi": "0.4.8",

+ 8 - 8
packages/function/sst-env.d.ts

@@ -6,20 +6,20 @@
 import "sst"
 import "sst"
 declare module "sst" {
 declare module "sst" {
   export interface Resource {
   export interface Resource {
-    Web: {
-      type: "sst.cloudflare.StaticSite"
-      url: string
+    "Web": {
+      "type": "sst.cloudflare.StaticSite"
+      "url": string
     }
     }
   }
   }
 }
 }
-// cloudflare
-import * as cloudflare from "@cloudflare/workers-types"
+// cloudflare 
+import * as cloudflare from "@cloudflare/workers-types";
 declare module "sst" {
 declare module "sst" {
   export interface Resource {
   export interface Resource {
-    Api: cloudflare.Service
-    Bucket: cloudflare.R2Bucket
+    "Api": cloudflare.Service
+    "Bucket": cloudflare.R2Bucket
   }
   }
 }
 }
 
 
 import "sst"
 import "sst"
-export {}
+export {}

+ 1 - 0
packages/opencode/package.json

@@ -25,6 +25,7 @@
     "ai": "catalog:",
     "ai": "catalog:",
     "cac": "6.7.14",
     "cac": "6.7.14",
     "decimal.js": "10.5.0",
     "decimal.js": "10.5.0",
+    "diff": "8.0.2",
     "env-paths": "3.0.0",
     "env-paths": "3.0.0",
     "hono": "4.7.10",
     "hono": "4.7.10",
     "hono-openapi": "0.4.8",
     "hono-openapi": "0.4.8",

+ 14 - 7
packages/opencode/src/tool/edit.ts

@@ -3,6 +3,7 @@ import * as path from "path"
 import { Tool } from "./tool"
 import { Tool } from "./tool"
 import { FileTimes } from "./util/file-times"
 import { FileTimes } from "./util/file-times"
 import { LSP } from "../lsp"
 import { LSP } from "../lsp"
+import { diffLines } from "diff"
 
 
 const DESCRIPTION = `Edits files by replacing text, creating new files, or deleting content. For moving or renaming files, use the Bash tool with the 'mv' command instead. For larger file edits, use the FileWrite tool to overwrite files.
 const DESCRIPTION = `Edits files by replacing text, creating new files, or deleting content. For moving or renaming files, use the Bash tool with the 'mv' command instead. For larger file edits, use the FileWrite tool to overwrite files.
 
 
@@ -70,8 +71,11 @@ export const EditTool = Tool.define({
       filePath = path.join(process.cwd(), filePath)
       filePath = path.join(process.cwd(), filePath)
     }
     }
 
 
+    let contentOld = ""
+    let contentNew = ""
     await (async () => {
     await (async () => {
       if (params.oldString === "") {
       if (params.oldString === "") {
+        contentNew = params.newString
         await Bun.write(filePath, params.newString)
         await Bun.write(filePath, params.newString)
         return
         return
       }
       }
@@ -91,26 +95,28 @@ export const EditTool = Tool.define({
           `File ${filePath} has been modified since it was last read.\nLast modification: ${read.toISOString()}\nLast read: ${stats.mtime.toISOString()}\n\nPlease read the file again before modifying it.`,
           `File ${filePath} has been modified since it was last read.\nLast modification: ${read.toISOString()}\nLast read: ${stats.mtime.toISOString()}\n\nPlease read the file again before modifying it.`,
         )
         )
 
 
-      const content = await file.text()
-      const index = content.indexOf(params.oldString)
+      contentOld = await file.text()
+      const index = contentOld.indexOf(params.oldString)
       if (index === -1)
       if (index === -1)
         throw new Error(
         throw new Error(
           `oldString not found in file. Make sure it matches exactly, including whitespace and line breaks`,
           `oldString not found in file. Make sure it matches exactly, including whitespace and line breaks`,
         )
         )
-      const lastIndex = content.lastIndexOf(params.oldString)
+      const lastIndex = contentOld.lastIndexOf(params.oldString)
       if (index !== lastIndex)
       if (index !== lastIndex)
         throw new Error(
         throw new Error(
           `oldString appears multiple times in the file. Please provide more context to ensure a unique match`,
           `oldString appears multiple times in the file. Please provide more context to ensure a unique match`,
         )
         )
 
 
-      const newContent =
-        content.substring(0, index) +
+      contentNew =
+        contentOld.substring(0, index) +
         params.newString +
         params.newString +
-        content.substring(index + params.oldString.length)
+        contentOld.substring(index + params.oldString.length)
 
 
-      await file.write(newContent)
+      await file.write(contentNew)
     })()
     })()
 
 
+    const changes = diffLines(contentOld, contentNew)
+
     FileTimes.write(filePath)
     FileTimes.write(filePath)
     FileTimes.read(filePath)
     FileTimes.read(filePath)
 
 
@@ -129,6 +135,7 @@ export const EditTool = Tool.define({
     return {
     return {
       metadata: {
       metadata: {
         diagnostics,
         diagnostics,
+        changes,
       },
       },
       output,
       output,
     }
     }

+ 0 - 0
packages/opencode/src/util/event.ts


+ 3 - 0
packages/opencode/src/util/log.ts

@@ -53,6 +53,9 @@ export namespace Log {
       error(message?: any, extra?: Record<string, any>) {
       error(message?: any, extra?: Record<string, any>) {
         write.err(build(message, extra))
         write.err(build(message, extra))
       },
       },
+      warn(message?: any, extra?: Record<string, any>) {
+        write.err(build(message, extra))
+      },
       tag(key: string, value: string) {
       tag(key: string, value: string) {
         if (tags) tags[key] = value
         if (tags) tags[key] = value
         return result
         return result

+ 5 - 0
packages/opencode/src/util/scrap.ts

@@ -1,5 +1,10 @@
 export const foo: string = "42"
 export const foo: string = "42"
+export const bar: number = 123
 
 
 export function dummyFunction(): void {
 export function dummyFunction(): void {
   console.log("This is a dummy function")
   console.log("This is a dummy function")
 }
 }
+
+export function randomHelper(): boolean {
+  return Math.random() > 0.5
+}

+ 10 - 14
packages/web/src/components/DiffView.tsx

@@ -1,5 +1,5 @@
-import { type Component, createSignal, onMount } from "solid-js"
-import { diffLines } from "diff"
+import { type Component, createMemo, createSignal, onMount } from "solid-js"
+import { diffLines, type ChangeObject } from "diff"
 import CodeBlock from "./CodeBlock"
 import CodeBlock from "./CodeBlock"
 import styles from "./diffview.module.css"
 import styles from "./diffview.module.css"
 
 
@@ -10,33 +10,29 @@ type DiffRow = {
 }
 }
 
 
 interface DiffViewProps {
 interface DiffViewProps {
-  oldCode: string
-  newCode: string
+  changes: ChangeObject<string>[]
   lang?: string
   lang?: string
   class?: string
   class?: string
 }
 }
 
 
 const DiffView: Component<DiffViewProps> = (props) => {
 const DiffView: Component<DiffViewProps> = (props) => {
-  const [rows, setRows] = createSignal<DiffRow[]>([])
-
-  onMount(() => {
-    const chunks = diffLines(props.oldCode, props.newCode)
+  const rows = createMemo(() => {
     const diffRows: DiffRow[] = []
     const diffRows: DiffRow[] = []
 
 
-    for (const chunk of chunks) {
-      const lines = chunk.value.split(/\r?\n/)
+    for (const item of props.changes) {
+      const lines = item.value.split(/\r?\n/)
       if (lines.at(-1) === "") lines.pop()
       if (lines.at(-1) === "") lines.pop()
 
 
       for (const line of lines) {
       for (const line of lines) {
         diffRows.push({
         diffRows.push({
-          left: chunk.removed ? line : chunk.added ? "" : line,
-          right: chunk.added ? line : chunk.removed ? "" : line,
-          type: chunk.added ? "added" : chunk.removed ? "removed" : "unchanged",
+          left: item.removed ? line : item.added ? "" : line,
+          right: item.added ? line : item.removed ? "" : line,
+          type: item.added ? "added" : item.removed ? "removed" : "unchanged",
         })
         })
       }
       }
     }
     }
 
 
-    setRows(diffRows)
+    return diffRows
   })
   })
 
 
   return (
   return (

+ 5 - 5
packages/web/src/components/Share.tsx

@@ -53,7 +53,7 @@ type SessionMessage = UIMessage<{
   tool: Record<
   tool: Record<
     string,
     string,
     {
     {
-      properties: Record<string, any>
+      [key: string]: any
       time: {
       time: {
         start: number
         start: number
         end: number
         end: number
@@ -596,11 +596,12 @@ export default function Share(props: { api: string }) {
                           when={
                           when={
                             msg.role === "assistant" &&
                             msg.role === "assistant" &&
                             part.type === "tool-invocation" &&
                             part.type === "tool-invocation" &&
-                            part.toolInvocation.toolName === "edit" &&
+                            part.toolInvocation.toolName === "opencode_edit" &&
                             part
                             part
                           }
                           }
                         >
                         >
                           {(part) => {
                           {(part) => {
+                            const metadata = createMemo(() => msg.metadata?.tool[part().toolInvocation.toolCallId])
                             const args = part().toolInvocation.args
                             const args = part().toolInvocation.args
                             const filePath = args.filePath
                             const filePath = args.filePath
                             return (
                             return (
@@ -622,8 +623,7 @@ export default function Share(props: { api: string }) {
                                     <div data-part-tool-edit>
                                     <div data-part-tool-edit>
                                       <DiffView
                                       <DiffView
                                         class={styles["code-block"]}
                                         class={styles["code-block"]}
-                                        oldCode={args.oldString}
-                                        newCode={args.newString}
+                                        changes={metadata()?.changes || []}
                                         lang={getFileType(filePath)}
                                         lang={getFileType(filePath)}
                                       />
                                       />
                                     </div>
                                     </div>
@@ -680,7 +680,7 @@ export default function Share(props: { api: string }) {
                                     <Match
                                     <Match
                                       when={
                                       when={
                                         part().toolInvocation.state ===
                                         part().toolInvocation.state ===
-                                          "result" &&
+                                        "result" &&
                                         part().toolInvocation.result
                                         part().toolInvocation.result
                                       }
                                       }
                                     >
                                     >

+ 1 - 1
packages/web/sst-env.d.ts

@@ -6,4 +6,4 @@
 /// <reference path="../../sst-env.d.ts" />
 /// <reference path="../../sst-env.d.ts" />
 
 
 import "sst"
 import "sst"
-export {}
+export {}

+ 9 - 9
sst-env.d.ts

@@ -5,20 +5,20 @@
 
 
 declare module "sst" {
 declare module "sst" {
   export interface Resource {
   export interface Resource {
-    Api: {
-      type: "sst.cloudflare.Worker"
-      url: string
+    "Api": {
+      "type": "sst.cloudflare.Worker"
+      "url": string
     }
     }
-    Bucket: {
-      type: "sst.cloudflare.Bucket"
+    "Bucket": {
+      "type": "sst.cloudflare.Bucket"
     }
     }
-    Web: {
-      type: "sst.cloudflare.StaticSite"
-      url: string
+    "Web": {
+      "type": "sst.cloudflare.StaticSite"
+      "url": string
     }
     }
   }
   }
 }
 }
 /// <reference path="sst-env.d.ts" />
 /// <reference path="sst-env.d.ts" />
 
 
 import "sst"
 import "sst"
-export {}
+export {}