Skip to content

Commit 4f31a24

Browse files
committed
Smarter partial merging of prompt components
1 parent 799d897 commit 4f31a24

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

src/shared/__tests__/modes-empty-prompt-component.spec.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe("getModeSelection with empty promptComponent", () => {
4040
expect(result.baseInstructions).toBe("Custom instructions")
4141
})
4242

43-
it("should use promptComponent when it has partial content", () => {
43+
it("should merge promptComponent with built-in mode when it has partial content", () => {
4444
const architectMode = modes.find((m) => m.slug === "architect")!
4545

4646
// Test with promptComponent that only has customInstructions
@@ -49,8 +49,49 @@ describe("getModeSelection with empty promptComponent", () => {
4949
}
5050
const result = getModeSelection("architect", partialPromptComponent, [])
5151

52-
// Should use promptComponent since it has some content
53-
expect(result.roleDefinition).toBe("") // No roleDefinition in promptComponent
54-
expect(result.baseInstructions).toBe("Only custom instructions")
52+
// Should merge: use promptComponent's customInstructions but fall back to built-in roleDefinition
53+
expect(result.roleDefinition).toBe(architectMode.roleDefinition) // Falls back to built-in
54+
expect(result.baseInstructions).toBe("Only custom instructions") // Uses promptComponent
55+
})
56+
57+
it("should merge promptComponent with built-in mode when it only has roleDefinition", () => {
58+
const debugMode = modes.find((m) => m.slug === "debug")!
59+
60+
// Test with promptComponent that only has roleDefinition
61+
const partialPromptComponent: PromptComponent = {
62+
roleDefinition: "Custom debug role",
63+
}
64+
const result = getModeSelection("debug", partialPromptComponent, [])
65+
66+
// Should merge: use promptComponent's roleDefinition but fall back to built-in customInstructions
67+
expect(result.roleDefinition).toBe("Custom debug role") // Uses promptComponent
68+
expect(result.baseInstructions).toBe(debugMode.customInstructions) // Falls back to built-in
69+
})
70+
71+
it("should handle promptComponent with both roleDefinition and customInstructions", () => {
72+
// Test with promptComponent that has both properties
73+
const fullPromptComponent: PromptComponent = {
74+
roleDefinition: "Full custom role",
75+
customInstructions: "Full custom instructions",
76+
}
77+
const result = getModeSelection("architect", fullPromptComponent, [])
78+
79+
// Should use promptComponent values for both
80+
expect(result.roleDefinition).toBe("Full custom role")
81+
expect(result.baseInstructions).toBe("Full custom instructions")
82+
})
83+
84+
it("should fall back to default mode when built-in mode is not found", () => {
85+
const defaultMode = modes[0] // First mode is the default
86+
87+
// Test with non-existent mode
88+
const partialPromptComponent: PromptComponent = {
89+
customInstructions: "Custom instructions for unknown mode",
90+
}
91+
const result = getModeSelection("non-existent-mode", partialPromptComponent, [])
92+
93+
// Should merge with default mode
94+
expect(result.roleDefinition).toBe(defaultMode.roleDefinition) // Falls back to default mode
95+
expect(result.baseInstructions).toBe("Custom instructions for unknown mode") // Uses promptComponent
5596
})
5697
})

src/shared/__tests__/modes.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,11 @@ describe("getModeSelection", () => {
443443
expect(selection.baseInstructions).toBe(newCustomMode.customInstructions)
444444
})
445445

446-
test("should return empty strings if slug does not exist in custom, prompt, or built-in modes", () => {
446+
test("should fall back to default mode if slug does not exist in custom, prompt, or built-in modes", () => {
447447
const selection = getModeSelection("non-existent-mode", undefined, customModesList)
448-
expect(selection.roleDefinition).toBe("")
449-
expect(selection.baseInstructions).toBe("")
448+
const defaultMode = modes[0] // First mode is the default
449+
expect(selection.roleDefinition).toBe(defaultMode.roleDefinition)
450+
expect(selection.baseInstructions).toBe(defaultMode.customInstructions || "")
450451
})
451452

452453
test("customMode's properties are used if customMode exists, ignoring promptComponent's properties", () => {

src/shared/modes.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,23 +183,29 @@ export function findModeBySlug(slug: string, modes: readonly ModeConfig[] | unde
183183
/**
184184
* Get the mode selection based on the provided mode slug, prompt component, and custom modes.
185185
* If a custom mode is found, it takes precedence over the built-in modes.
186-
* If no custom mode is found, the built-in mode is used.
186+
* If no custom mode is found, the built-in mode is used with partial merging from promptComponent.
187187
* If neither is found, the default mode is used.
188188
*/
189189
export function getModeSelection(mode: string, promptComponent?: PromptComponent, customModes?: ModeConfig[]) {
190190
const customMode = findModeBySlug(mode, customModes)
191191
const builtInMode = findModeBySlug(mode, modes)
192192

193-
const modeToUse = customMode || promptComponent || builtInMode
193+
// If we have a custom mode, use it entirely
194+
if (customMode) {
195+
return {
196+
roleDefinition: customMode.roleDefinition || "",
197+
baseInstructions: customMode.customInstructions || "",
198+
description: customMode.description || "",
199+
}
200+
}
194201

195-
const roleDefinition = modeToUse?.roleDefinition || ""
196-
const baseInstructions = modeToUse?.customInstructions || ""
197-
const description = (customMode || builtInMode)?.description || ""
202+
// Otherwise, use built-in mode as base and merge with promptComponent
203+
const baseMode = builtInMode || modes[0] // fallback to default mode
198204

199205
return {
200-
roleDefinition,
201-
baseInstructions,
202-
description,
206+
roleDefinition: promptComponent?.roleDefinition || baseMode.roleDefinition || "",
207+
baseInstructions: promptComponent?.customInstructions || baseMode.customInstructions || "",
208+
description: baseMode.description || "",
203209
}
204210
}
205211

0 commit comments

Comments
 (0)