mode-validator.test.ts 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { isToolAllowedForMode, validateToolUse } from '../mode-validator'
  2. import { codeMode, architectMode, askMode } from '../prompts/system'
  3. import { CODE_ALLOWED_TOOLS, READONLY_ALLOWED_TOOLS, ToolName } from '../tool-lists'
  4. // For testing purposes, we need to handle the 'unknown_tool' case
  5. type TestToolName = ToolName | 'unknown_tool';
  6. // Helper function to safely cast string to TestToolName for testing
  7. function asTestTool(str: string): TestToolName {
  8. return str as TestToolName;
  9. }
  10. describe('mode-validator', () => {
  11. describe('isToolAllowedForMode', () => {
  12. describe('code mode', () => {
  13. it('allows all code mode tools', () => {
  14. CODE_ALLOWED_TOOLS.forEach(tool => {
  15. expect(isToolAllowedForMode(tool, codeMode)).toBe(true)
  16. })
  17. })
  18. it('disallows unknown tools', () => {
  19. expect(isToolAllowedForMode(asTestTool('unknown_tool'), codeMode)).toBe(false)
  20. })
  21. })
  22. describe('architect mode', () => {
  23. it('allows only read-only and MCP tools', () => {
  24. // Test allowed tools
  25. READONLY_ALLOWED_TOOLS.forEach(tool => {
  26. expect(isToolAllowedForMode(tool, architectMode)).toBe(true)
  27. })
  28. // Test specific disallowed tools that we know are in CODE_ALLOWED_TOOLS but not in READONLY_ALLOWED_TOOLS
  29. const disallowedTools = ['execute_command', 'write_to_file', 'apply_diff'] as const;
  30. disallowedTools.forEach(tool => {
  31. expect(isToolAllowedForMode(tool as ToolName, architectMode)).toBe(false)
  32. })
  33. })
  34. })
  35. describe('ask mode', () => {
  36. it('allows only read-only and MCP tools', () => {
  37. // Test allowed tools
  38. READONLY_ALLOWED_TOOLS.forEach(tool => {
  39. expect(isToolAllowedForMode(tool, askMode)).toBe(true)
  40. })
  41. // Test specific disallowed tools that we know are in CODE_ALLOWED_TOOLS but not in READONLY_ALLOWED_TOOLS
  42. const disallowedTools = ['execute_command', 'write_to_file', 'apply_diff'] as const;
  43. disallowedTools.forEach(tool => {
  44. expect(isToolAllowedForMode(tool as ToolName, askMode)).toBe(false)
  45. })
  46. })
  47. })
  48. })
  49. describe('validateToolUse', () => {
  50. it('throws error for disallowed tools in architect mode', () => {
  51. expect(() => validateToolUse('write_to_file' as ToolName, architectMode)).toThrow(
  52. 'Tool "write_to_file" is not allowed in architect mode.'
  53. )
  54. })
  55. it('throws error for disallowed tools in ask mode', () => {
  56. expect(() => validateToolUse('execute_command' as ToolName, askMode)).toThrow(
  57. 'Tool "execute_command" is not allowed in ask mode.'
  58. )
  59. })
  60. it('throws error for unknown tools in code mode', () => {
  61. expect(() => validateToolUse(asTestTool('unknown_tool'), codeMode)).toThrow(
  62. 'Tool "unknown_tool" is not allowed in code mode.'
  63. )
  64. })
  65. it('does not throw for allowed tools', () => {
  66. // Code mode
  67. expect(() => validateToolUse('write_to_file' as ToolName, codeMode)).not.toThrow()
  68. // Architect mode
  69. expect(() => validateToolUse('read_file' as ToolName, architectMode)).not.toThrow()
  70. // Ask mode
  71. expect(() => validateToolUse('browser_action' as ToolName, askMode)).not.toThrow()
  72. })
  73. })
  74. })