mirror of
https://github.com/sst/opencode.git
synced 2025-08-22 22:14:14 +00:00
slash commands
This commit is contained in:
parent
6dae463c52
commit
e7ddaa2cf5
2 changed files with 22 additions and 5 deletions
|
@ -1,3 +1,4 @@
|
||||||
hey there $ARGUMENTS
|
hey there $ARGUMENTS
|
||||||
|
|
||||||
|
!`ls`
|
||||||
check out @README.md
|
check out @README.md
|
||||||
|
|
|
@ -48,6 +48,7 @@ import { Wildcard } from "../util/wildcard"
|
||||||
import { ulid } from "ulid"
|
import { ulid } from "ulid"
|
||||||
import { defer } from "../util/defer"
|
import { defer } from "../util/defer"
|
||||||
import { Command } from "../command"
|
import { Command } from "../command"
|
||||||
|
import { $ } from "bun"
|
||||||
|
|
||||||
export namespace Session {
|
export namespace Session {
|
||||||
const log = Log.create({ service: "session" })
|
const log = Log.create({ service: "session" })
|
||||||
|
@ -484,7 +485,6 @@ export namespace Session {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "file:":
|
case "file:":
|
||||||
log.info("file", { url })
|
|
||||||
// have to normalize, symbol search returns absolute paths
|
// have to normalize, symbol search returns absolute paths
|
||||||
// Decode the pathname since URL constructor doesn't automatically decode it
|
// Decode the pathname since URL constructor doesn't automatically decode it
|
||||||
const filePath = decodeURIComponent(url.pathname)
|
const filePath = decodeURIComponent(url.pathname)
|
||||||
|
@ -525,7 +525,6 @@ export namespace Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const args = { filePath, offset, limit }
|
const args = { filePath, offset, limit }
|
||||||
log.info("file", args)
|
|
||||||
const result = await ReadTool.init().then((t) =>
|
const result = await ReadTool.init().then((t) =>
|
||||||
t.execute(args, {
|
t.execute(args, {
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
|
@ -1167,6 +1166,9 @@ export namespace Session {
|
||||||
command: z.string(),
|
command: z.string(),
|
||||||
})
|
})
|
||||||
export type CommandInput = z.infer<typeof CommandInput>
|
export type CommandInput = z.infer<typeof CommandInput>
|
||||||
|
const bashRegex = /!`([^`]+)`/g
|
||||||
|
const fileRegex = /@([^\s]+)/g
|
||||||
|
|
||||||
export async function command(input: CommandInput) {
|
export async function command(input: CommandInput) {
|
||||||
const command = await Command.get(input.command)
|
const command = await Command.get(input.command)
|
||||||
const agent = input.agent ?? command.agent ?? "build"
|
const agent = input.agent ?? command.agent ?? "build"
|
||||||
|
@ -1176,6 +1178,22 @@ export namespace Session {
|
||||||
(await Agent.get(agent).then((x) => (x.model ? `${x.model.providerID}/${x.model.modelID}` : undefined))) ??
|
(await Agent.get(agent).then((x) => (x.model ? `${x.model.providerID}/${x.model.modelID}` : undefined))) ??
|
||||||
(await Provider.defaultModel().then((x) => `${x.providerID}/${x.modelID}`))
|
(await Provider.defaultModel().then((x) => `${x.providerID}/${x.modelID}`))
|
||||||
let template = command.template.replace("$ARGUMENTS", input.arguments)
|
let template = command.template.replace("$ARGUMENTS", input.arguments)
|
||||||
|
|
||||||
|
const bash = Array.from(template.matchAll(bashRegex))
|
||||||
|
if (bash.length > 0) {
|
||||||
|
const results = await Promise.all(
|
||||||
|
bash.map(async ([, cmd]) => {
|
||||||
|
try {
|
||||||
|
return await $`${{ raw: cmd }}`.nothrow().text()
|
||||||
|
} catch (error) {
|
||||||
|
return `Error executing command: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
let index = 0
|
||||||
|
template = template.replace(bashRegex, () => results[index++])
|
||||||
|
}
|
||||||
|
|
||||||
const parts = [
|
const parts = [
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
|
@ -1183,13 +1201,11 @@ export namespace Session {
|
||||||
},
|
},
|
||||||
] as ChatInput["parts"]
|
] as ChatInput["parts"]
|
||||||
|
|
||||||
const pattern = /@([^\s]+)/g
|
const matches = template.matchAll(fileRegex)
|
||||||
const matches = template.matchAll(pattern)
|
|
||||||
const app = App.info()
|
const app = App.info()
|
||||||
|
|
||||||
for (const match of matches) {
|
for (const match of matches) {
|
||||||
const file = path.join(app.path.cwd, match[1])
|
const file = path.join(app.path.cwd, match[1])
|
||||||
log.info("file", { file })
|
|
||||||
parts.push({
|
parts.push({
|
||||||
type: "file",
|
type: "file",
|
||||||
url: `file://${file}`,
|
url: `file://${file}`,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue