diff --git a/src/index.runtime.test.ts b/src/index.runtime.test.ts index d4e245c..40de2b0 100644 --- a/src/index.runtime.test.ts +++ b/src/index.runtime.test.ts @@ -331,6 +331,81 @@ describe('OpenCodeRulesPlugin', () => { expect(result.system).toContain('Rule Content'); }); + it('should consolidate array system messages into single string', async () => { + const { testDir, globalRulesDir } = getTestDirs(); + writeFileSync(path.join(globalRulesDir, 'rule.md'), '# My Rule'); + process.env.XDG_CONFIG_HOME = path.join(testDir, '.config'); + + const { + default: { server: plugin }, + } = await import('./index.js'); + const mockInput = createMockPluginInput({ testDir }); + + const hooks = await plugin( + mockInput as unknown as Parameters[0] + ); + const systemTransform = hooks['experimental.chat.system.transform'] as ( + input: unknown, + output: { system: string[] } + ) => Promise<{ system: string }>; + const result = await systemTransform( + {}, + { system: ['First message.', 'Second message.'] } + ); + + expect(typeof result.system).toBe('string'); + expect(result.system).toContain('First message.'); + expect(result.system).toContain('Second message.'); + expect(result.system).toContain('My Rule'); + }); + + it('should handle empty array system messages', async () => { + const { testDir, globalRulesDir } = getTestDirs(); + writeFileSync(path.join(globalRulesDir, 'rule.md'), '# My Rule'); + process.env.XDG_CONFIG_HOME = path.join(testDir, '.config'); + + const { + default: { server: plugin }, + } = await import('./index.js'); + const mockInput = createMockPluginInput({ testDir }); + + const hooks = await plugin( + mockInput as unknown as Parameters[0] + ); + const systemTransform = hooks['experimental.chat.system.transform'] as ( + input: unknown, + output: { system: string[] } + ) => Promise<{ system: string }>; + const result = await systemTransform({}, { system: [] }); + + expect(typeof result.system).toBe('string'); + expect(result.system).toContain('My Rule'); + }); + + it('should handle single-element array system message', async () => { + const { testDir, globalRulesDir } = getTestDirs(); + writeFileSync(path.join(globalRulesDir, 'rule.md'), '# My Rule'); + process.env.XDG_CONFIG_HOME = path.join(testDir, '.config'); + + const { + default: { server: plugin }, + } = await import('./index.js'); + const mockInput = createMockPluginInput({ testDir }); + + const hooks = await plugin( + mockInput as unknown as Parameters[0] + ); + const systemTransform = hooks['experimental.chat.system.transform'] as ( + input: unknown, + output: { system: string[] } + ) => Promise<{ system: string }>; + const result = await systemTransform({}, { system: ['Only message.'] }); + + expect(typeof result.system).toBe('string'); + expect(result.system).toContain('Only message.'); + expect(result.system).toContain('My Rule'); + }); + it('should not modify messages in messages.transform hook', async () => { const { testDir, globalRulesDir } = getTestDirs(); writeFileSync(path.join(globalRulesDir, 'rule.md'), '# Rule'); diff --git a/src/runtime.ts b/src/runtime.ts index 27dab6c..0582d9e 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -37,7 +37,7 @@ interface SystemTransformInput { } interface SystemTransformOutput { - system?: string | string[]; + system?: string; } interface OpenCodeRulesRuntimeOptions { @@ -324,7 +324,10 @@ export class OpenCodeRulesRuntime { } if (Array.isArray(output.system)) { - output.system.push(combinedSystem); + output.system = + output.system.join('\n\n') + + (output.system.length > 0 ? '\n\n' : '') + + combinedSystem; } else { output.system = output.system ? `${output.system}\n\n${combinedSystem}`