summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/opencode/src/cli/cmd/debug.ts37
-rw-r--r--packages/opencode/src/cli/cmd/scrap.ts15
-rw-r--r--packages/opencode/src/file/fzf.ts (renamed from packages/opencode/src/external/fzf.ts)21
-rw-r--r--packages/opencode/src/file/ripgrep.ts (renamed from packages/opencode/src/external/ripgrep.ts)100
-rw-r--r--packages/opencode/src/index.ts4
-rw-r--r--packages/opencode/src/server/server.ts2
-rw-r--r--packages/opencode/src/session/system.ts64
-rw-r--r--packages/opencode/src/tool/glob.ts2
-rw-r--r--packages/opencode/src/tool/grep.ts2
9 files changed, 153 insertions, 94 deletions
diff --git a/packages/opencode/src/cli/cmd/debug.ts b/packages/opencode/src/cli/cmd/debug.ts
new file mode 100644
index 000000000..ed81c1186
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/debug.ts
@@ -0,0 +1,37 @@
+import { App } from "../../app/app"
+import { Ripgrep } from "../../file/ripgrep"
+import { LSP } from "../../lsp"
+import { cmd } from "./cmd"
+
+export const DebugCommand = cmd({
+ command: "debug",
+ builder: (yargs) =>
+ yargs.command(DiagnosticsCommand).command(TreeCommand).demandCommand(),
+ async handler() {},
+})
+
+const DiagnosticsCommand = cmd({
+ command: "diagnostics <file>",
+ builder: (yargs) =>
+ yargs.positional("file", { type: "string", demandOption: true }),
+ async handler(args) {
+ await App.provide({ cwd: process.cwd() }, async () => {
+ await LSP.touchFile(args.file, true)
+ console.log(await LSP.diagnostics())
+ })
+ },
+})
+
+const TreeCommand = cmd({
+ command: "tree",
+ builder: (yargs) =>
+ yargs.option("limit", {
+ type: "number",
+ }),
+ async handler(args) {
+ await App.provide({ cwd: process.cwd() }, async () => {
+ const app = App.info()
+ console.log(await Ripgrep.tree({ cwd: app.path.cwd, limit: args.limit }))
+ })
+ },
+})
diff --git a/packages/opencode/src/cli/cmd/scrap.ts b/packages/opencode/src/cli/cmd/scrap.ts
deleted file mode 100644
index 20b0f52a3..000000000
--- a/packages/opencode/src/cli/cmd/scrap.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { App } from "../../app/app"
-import { LSP } from "../../lsp"
-import { cmd } from "./cmd"
-
-export const ScrapCommand = cmd({
- command: "scrap <file>",
- builder: (yargs) =>
- yargs.positional("file", { type: "string", demandOption: true }),
- async handler(args) {
- await App.provide({ cwd: process.cwd() }, async () => {
- await LSP.touchFile(args.file, true)
- console.log(await LSP.diagnostics())
- })
- },
-})
diff --git a/packages/opencode/src/external/fzf.ts b/packages/opencode/src/file/fzf.ts
index e77975786..6d52702fe 100644
--- a/packages/opencode/src/external/fzf.ts
+++ b/packages/opencode/src/file/fzf.ts
@@ -5,7 +5,6 @@ import { z } from "zod"
import { NamedError } from "../util/error"
import { lazy } from "../util/lazy"
import { Log } from "../util/log"
-import { $ } from "bun"
export namespace Fzf {
const log = Log.create({ service: "fzf" })
@@ -115,24 +114,4 @@ export namespace Fzf {
const { filepath } = await state()
return filepath
}
-
- export async function search(input: {
- cwd: string
- query: string
- limit?: number
- }) {
- const results = await $`${await filepath()} --filter=${input.query}`
- .quiet()
- .throws(false)
- .cwd(input.cwd)
- .text()
- const split = results
- .trim()
- .split("\n")
- .filter((line) => line.length > 0)
- log.info("results", {
- count: split.length,
- })
- return split
- }
}
diff --git a/packages/opencode/src/external/ripgrep.ts b/packages/opencode/src/file/ripgrep.ts
index 1b4f40580..280e03b01 100644
--- a/packages/opencode/src/external/ripgrep.ts
+++ b/packages/opencode/src/file/ripgrep.ts
@@ -129,4 +129,104 @@ export namespace Ripgrep {
const result = await $`${{ raw: joined }}`.cwd(input.cwd).nothrow().text()
return result.split("\n").filter(Boolean)
}
+
+ export async function tree(input: { cwd: string; limit?: number }) {
+ const files = await Ripgrep.files({ cwd: input.cwd })
+ interface Node {
+ path: string[]
+ children: Node[]
+ }
+
+ function getPath(node: Node, parts: string[], create: boolean) {
+ if (parts.length === 0) return node
+ let current = node
+ for (const part of parts) {
+ let existing = current.children.find((x) => x.path.at(-1) === part)
+ if (!existing) {
+ if (!create) return
+ existing = {
+ path: current.path.concat(part),
+ children: [],
+ }
+ current.children.push(existing)
+ }
+ current = existing
+ }
+ return current
+ }
+
+ const root: Node = {
+ path: [],
+ children: [],
+ }
+ for (const file of files) {
+ const parts = file.split(path.sep)
+ getPath(root, parts, true)
+ }
+
+ function sort(node: Node) {
+ node.children.sort((a, b) => {
+ if (!a.children.length && b.children.length) return 1
+ if (!b.children.length && a.children.length) return -1
+ return a.path.at(-1)!.localeCompare(b.path.at(-1)!)
+ })
+ for (const child of node.children) {
+ sort(child)
+ }
+ }
+ sort(root)
+
+ let current = [root]
+ const result: Node = {
+ path: [],
+ children: [],
+ }
+
+ let processed = 0
+ const limit = input.limit ?? 50
+ while (current.length > 0) {
+ const next = []
+ for (const node of current) {
+ if (node.children.length) next.push(...node.children)
+ }
+ const max = Math.max(...current.map((x) => x.children.length))
+ for (let i = 0; i < max && processed < limit; i++) {
+ for (const node of current) {
+ const child = node.children[i]
+ if (!child) continue
+ getPath(result, child.path, true)
+ processed++
+ if (processed >= limit) break
+ }
+ }
+ if (processed >= limit) {
+ for (const node of [...current, ...next]) {
+ const compare = getPath(result, node.path, false)
+ if (!compare) continue
+ if (compare?.children.length !== node.children.length) {
+ const diff = node.children.length - compare.children.length
+ compare.children.push({
+ path: compare.path.concat(`[${diff} truncated]`),
+ children: [],
+ })
+ }
+ }
+ break
+ }
+ current = next
+ }
+
+ const lines: string[] = []
+
+ function render(node: Node, depth: number) {
+ const indent = "\t".repeat(depth)
+ lines.push(indent + node.path.at(-1) + (node.children.length ? "/" : ""))
+ for (const child of node.children) {
+ render(child, depth + 1)
+ }
+ }
+ result.children.map((x) => render(x, 0))
+
+ return lines.join("\n")
+ }
}
diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts
index 8a684ae91..3ca40ce70 100644
--- a/packages/opencode/src/index.ts
+++ b/packages/opencode/src/index.ts
@@ -3,7 +3,6 @@ import yargs from "yargs"
import { hideBin } from "yargs/helpers"
import { RunCommand } from "./cli/cmd/run"
import { GenerateCommand } from "./cli/cmd/generate"
-import { ScrapCommand } from "./cli/cmd/scrap"
import { Log } from "./util/log"
import { AuthCommand } from "./cli/cmd/auth"
import { UpgradeCommand } from "./cli/cmd/upgrade"
@@ -14,6 +13,7 @@ import { NamedError } from "./util/error"
import { FormatError } from "./cli/error"
import { ServeCommand } from "./cli/cmd/serve"
import { TuiCommand } from "./cli/cmd/tui"
+import { DebugCommand } from "./cli/cmd/debug"
const cancel = new AbortController()
@@ -49,7 +49,7 @@ const cli = yargs(hideBin(process.argv))
.command(TuiCommand)
.command(RunCommand)
.command(GenerateCommand)
- .command(ScrapCommand)
+ .command(DebugCommand)
.command(AuthCommand)
.command(UpgradeCommand)
.command(ServeCommand)
diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts
index 34349dedd..d636e5c64 100644
--- a/packages/opencode/src/server/server.ts
+++ b/packages/opencode/src/server/server.ts
@@ -12,7 +12,7 @@ import { App } from "../app/app"
import { mapValues } from "remeda"
import { NamedError } from "../util/error"
import { ModelsDev } from "../provider/models"
-import { Ripgrep } from "../external/ripgrep"
+import { Ripgrep } from "../file/ripgrep"
import { Config } from "../config/config"
const ERRORS = {
diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts
index 0823443b7..1c77824b1 100644
--- a/packages/opencode/src/session/system.ts
+++ b/packages/opencode/src/session/system.ts
@@ -1,5 +1,5 @@
import { App } from "../app/app"
-import { Ripgrep } from "../external/ripgrep"
+import { Ripgrep } from "../file/ripgrep"
import { Global } from "../global"
import { Filesystem } from "../util/filesystem"
import path from "path"
@@ -27,55 +27,6 @@ export namespace SystemPrompt {
export async function environment() {
const app = App.info()
-
- ;async () => {
- const files = await Ripgrep.files({
- cwd: app.path.cwd,
- })
- type Node = {
- children: Record<string, Node>
- }
- const root: Node = {
- children: {},
- }
- for (const file of files) {
- const parts = file.split("/")
- let node = root
- for (const part of parts) {
- const existing = node.children[part]
- if (existing) {
- node = existing
- continue
- }
- node.children[part] = {
- children: {},
- }
- node = node.children[part]
- }
- }
-
- function render(path: string[], node: Node): string {
- // if (path.length === 3) return "\t".repeat(path.length) + "..."
- const lines: string[] = []
- const entries = Object.entries(node.children).sort(([a], [b]) =>
- a.localeCompare(b),
- )
-
- for (const [name, child] of entries) {
- const currentPath = [...path, name]
- const indent = "\t".repeat(path.length)
- const hasChildren = Object.keys(child.children).length > 0
- lines.push(`${indent}${name}` + (hasChildren ? "/" : ""))
-
- if (hasChildren) lines.push(render(currentPath, child))
- }
-
- return lines.join("\n")
- }
- const result = render([], root)
- return result
- }
-
return [
[
`Here is some useful information about the environment you are running in:`,
@@ -85,9 +36,16 @@ export namespace SystemPrompt {
` Platform: ${process.platform}`,
` Today's date: ${new Date().toDateString()}`,
`</env>`,
- // `<project>`,
- // ` ${app.git ? await tree() : ""}`,
- // `</project>`,
+ `<project>`,
+ ` ${
+ app.git
+ ? await Ripgrep.tree({
+ cwd: app.path.cwd,
+ limit: 200,
+ })
+ : ""
+ }`,
+ `</project>`,
].join("\n"),
]
}
diff --git a/packages/opencode/src/tool/glob.ts b/packages/opencode/src/tool/glob.ts
index 93912db78..70d5df471 100644
--- a/packages/opencode/src/tool/glob.ts
+++ b/packages/opencode/src/tool/glob.ts
@@ -3,7 +3,7 @@ import path from "path"
import { Tool } from "./tool"
import { App } from "../app/app"
import DESCRIPTION from "./glob.txt"
-import { Ripgrep } from "../external/ripgrep"
+import { Ripgrep } from "../file/ripgrep"
export const GlobTool = Tool.define({
id: "glob",
diff --git a/packages/opencode/src/tool/grep.ts b/packages/opencode/src/tool/grep.ts
index 1142136b4..e4ceec5e8 100644
--- a/packages/opencode/src/tool/grep.ts
+++ b/packages/opencode/src/tool/grep.ts
@@ -1,7 +1,7 @@
import { z } from "zod"
import { Tool } from "./tool"
import { App } from "../app/app"
-import { Ripgrep } from "../external/ripgrep"
+import { Ripgrep } from "../file/ripgrep"
import DESCRIPTION from "./grep.txt"