Skip to content

Commit 0174d8b

Browse files
fix: normalize prompt file paths in config during bundle apply
When installing prompt files from bundles, the CLI now adjusts file references in the preset config from ./prompts/ to .opencode/prompts/ to match the target installation location. This ensures the config works correctly after installation regardless of the bundle's original path references. Add test: TestBundleApplyAdjustsPromptFilePaths Refs: qbicsoftware/opencode-config-bundle#11
1 parent f51e954 commit 0174d8b

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

cmd/bundle.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,13 @@ func runBundleInstall(sourceRef string, interactivePreset bool) error {
288288
}
289289
}
290290

291+
// Adjust prompt file paths in preset content from ./prompts/ to .opencode/prompts/
292+
// The CLI normalizes paths to the target installation location (local project)
293+
if bundleInstallAssets && len(bundlePresetEntry.PromptFiles) > 0 {
294+
adjustedContent := strings.ReplaceAll(string(presetContent), "./prompts/", ".opencode/prompts/")
295+
presetContent = []byte(adjustedContent)
296+
}
297+
291298
// Reuse the shared write semantics so bundle apply matches init/preset overwrite behavior.
292299
if err := configpreset.WriteConfig(outputPath, string(presetContent), bundleForce); err != nil {
293300
return fmt.Errorf("failed to write config: %w", err)
@@ -303,7 +310,7 @@ func runBundleInstall(sourceRef string, interactivePreset bool) error {
303310
}
304311
installedAssets = installed
305312

306-
for _, a := range installed {
313+
for _, a := range installedAssets {
307314
fmt.Printf("written: %s\n", a.Destination)
308315
}
309316
}

cmd/bundle_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,65 @@ func TestBundleApplyMissingPreset(t *testing.T) {
104104
}
105105
}
106106

107+
// TestBundleApplyAdjustsPromptFilePaths tests that CLI adjusts prompt paths
108+
func TestBundleApplyAdjustsPromptFilePaths(t *testing.T) {
109+
restore := saveRegistry(t)
110+
defer restore()
111+
112+
bundleDir := t.TempDir()
113+
114+
manifest := `{"manifest_version":"1.0.0","bundle_name":"test","bundle_version":"v1.0.0","presets":[{"name":"test","entrypoint":"test.json","description":"Test","prompt_files":["prompts/coder.md"]}]}`
115+
os.WriteFile(filepath.Join(bundleDir, "opencode-bundle.manifest.json"), []byte(manifest), 0644)
116+
117+
preset := `{"agents":{"coder":{"prompt":"{file:./prompts/coder.md}"}}}`
118+
os.WriteFile(filepath.Join(bundleDir, "test.json"), []byte(preset), 0644)
119+
120+
os.MkdirAll(filepath.Join(bundleDir, "prompts"), 0755)
121+
os.WriteFile(filepath.Join(bundleDir, "prompts", "coder.md"), []byte("# coder"), 0644)
122+
123+
reg, _ := source.LoadRegistry()
124+
reg.Sources = []source.Source{{ID: "tid", Name: "t", Type: source.SourceTypeLocalDirectory, Location: bundleDir}}
125+
source.SaveRegistry(reg)
126+
127+
origPreset := bundlePreset
128+
origAuto := bundleAuto
129+
origTTY := bundleInputIsTTY
130+
origRoot := bundleProjectRoot
131+
origForce := bundleForce
132+
origAssets := bundleInstallAssets
133+
defer func() {
134+
bundlePreset = origPreset
135+
bundleAuto = origAuto
136+
bundleInputIsTTY = origTTY
137+
bundleProjectRoot = origRoot
138+
bundleForce = origForce
139+
bundleInstallAssets = origAssets
140+
}()
141+
142+
bundlePreset = "test"
143+
bundleAuto = true
144+
bundleInputIsTTY = func() bool { return false }
145+
bundleProjectRoot = t.TempDir()
146+
bundleForce = true
147+
bundleInstallAssets = true
148+
149+
err := runBundleInstall("tid", false)
150+
if err != nil {
151+
t.Fatalf("runBundleInstall() error = %v", err)
152+
}
153+
154+
cfg, _ := os.ReadFile(filepath.Join(bundleProjectRoot, "opencode.json"))
155+
if strings.Contains(string(cfg), "./prompts/") {
156+
t.Errorf("config should not contain ./prompts/, got: %s", cfg)
157+
}
158+
if !strings.Contains(string(cfg), ".opencode/prompts/") {
159+
t.Errorf("config should contain .opencode/prompts/, got: %s", cfg)
160+
}
161+
if _, err := os.Stat(filepath.Join(bundleProjectRoot, ".opencode", "prompts", "coder.md")); err != nil {
162+
t.Errorf("prompt should be installed to .opencode/prompts/: %v", err)
163+
}
164+
}
165+
107166
// TestBundleStatusNoProvenance tests status command with no provenance
108167
func TestBundleStatusNoProvenance(t *testing.T) {
109168
origProjectRoot := bundleProjectRoot

0 commit comments

Comments
 (0)