summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorRafał Krzyważnia <[email protected]>2025-11-12 02:38:50 +0100
committerGitHub <[email protected]>2025-11-11 19:38:50 -0600
commit491a2adf8d61cb52aa5d8a6c3b3e5fe0ef073a73 (patch)
treef5b6c3d1d915f22264e5ff6bf37d71e349913276 /packages
parentc07d6487a85420b13832caef258bdd1d6550af33 (diff)
downloadopencode-491a2adf8d61cb52aa5d8a6c3b3e5fe0ef073a73.tar.gz
opencode-491a2adf8d61cb52aa5d8a6c3b3e5fe0ef073a73.zip
fix: resolve @file references in slash commands with subagents (#4221)
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/session/prompt.ts94
-rw-r--r--packages/opencode/src/tool/task.ts9
2 files changed, 51 insertions, 52 deletions
diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts
index 10a9727a0..f4dc84be5 100644
--- a/packages/opencode/src/session/prompt.ts
+++ b/packages/opencode/src/session/prompt.ts
@@ -145,6 +145,54 @@ export namespace SessionPrompt {
),
})
export type PromptInput = z.infer<typeof PromptInput>
+
+ export async function resolvePromptParts(template: string): Promise<PromptInput["parts"]> {
+ const parts: PromptInput["parts"] = [
+ {
+ type: "text",
+ text: template,
+ },
+ ]
+ const files = ConfigMarkdown.files(template)
+ await Promise.all(
+ files.map(async (match) => {
+ const name = match[1]
+ const filepath = name.startsWith("~/")
+ ? path.join(os.homedir(), name.slice(2))
+ : path.resolve(Instance.worktree, name)
+
+ const stats = await fs.stat(filepath).catch(() => undefined)
+ if (!stats) {
+ const agent = await Agent.get(name)
+ if (agent) {
+ parts.push({
+ type: "agent",
+ name: agent.name,
+ })
+ }
+ return
+ }
+
+ if (stats.isDirectory()) {
+ parts.push({
+ type: "file",
+ url: `file://${filepath}`,
+ filename: name,
+ mime: "application/x-directory",
+ })
+ return
+ }
+
+ parts.push({
+ type: "file",
+ url: `file://${filepath}`,
+ filename: name,
+ mime: "text/plain",
+ })
+ }),
+ )
+ return parts
+ }
export async function prompt(input: PromptInput): Promise<MessageV2.WithParts> {
const l = log.clone().tag("session", input.sessionID)
l.info("prompt")
@@ -1605,51 +1653,7 @@ export namespace SessionPrompt {
}
template = template.trim()
- const parts = [
- {
- type: "text",
- text: template,
- },
- ] as PromptInput["parts"]
-
- const files = ConfigMarkdown.files(template)
- await Promise.all(
- files.map(async (match) => {
- const name = match[1]
- const filepath = name.startsWith("~/")
- ? path.join(os.homedir(), name.slice(2))
- : path.resolve(Instance.worktree, name)
-
- const stats = await fs.stat(filepath).catch(() => undefined)
- if (!stats) {
- const agent = await Agent.get(name)
- if (agent) {
- parts.push({
- type: "agent",
- name: agent.name,
- })
- }
- return
- }
-
- if (stats.isDirectory()) {
- parts.push({
- type: "file",
- url: `file://${filepath}`,
- filename: name,
- mime: "application/x-directory",
- })
- return
- }
-
- parts.push({
- type: "file",
- url: `file://${filepath}`,
- filename: name,
- mime: "text/plain",
- })
- }),
- )
+ const parts = await resolvePromptParts(template)
const model = await (async () => {
if (command.model) {
diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts
index 845a0e8c8..a5369d335 100644
--- a/packages/opencode/src/tool/task.ts
+++ b/packages/opencode/src/tool/task.ts
@@ -65,6 +65,7 @@ export const TaskTool = Tool.define("task", async () => {
ctx.abort.addEventListener("abort", () => {
SessionLock.abort(session.id)
})
+ const promptParts = await SessionPrompt.resolvePromptParts(params.prompt)
const result = await SessionPrompt.prompt({
messageID,
sessionID: session.id,
@@ -79,13 +80,7 @@ export const TaskTool = Tool.define("task", async () => {
task: false,
...agent.tools,
},
- parts: [
- {
- id: Identifier.ascending("part"),
- type: "text",
- text: params.prompt,
- },
- ],
+ parts: promptParts,
})
unsub()
let all