Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions packages/types/src/mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ export const groupOptionsSchema = z.object({
},
{ message: "Invalid regular expression pattern" },
),
commandRegex: z
.string()
.optional()
.refine(
(pattern) => {
if (!pattern) {
return true // Optional, so empty is valid.
}

try {
new RegExp(pattern)
return true
} catch {
return false
}
},
{ message: "Invalid regular expression pattern" },
),
description: z.string().optional(),
})

Expand Down
49 changes: 49 additions & 0 deletions src/core/config/__tests__/ModeConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,55 @@ describe("CustomModeSchema", () => {
})
})

describe("commandRegex", () => {
it("validates a mode with command restrictions and descriptions", () => {
const modeWithJustRegex = {
slug: "npm-only",
name: "NPM Only",
roleDefinition: "NPM command mode",
groups: ["read", ["command", { commandRegex: "^npm\\s" }]],
}

const modeWithDescription = {
slug: "package-manager",
name: "Package Manager",
roleDefinition: "Package manager command mode",
groups: [
"read",
["command", { commandRegex: "^(npm|yarn|pnpm)\\s", description: "Package manager commands only" }],
],
}

expect(() => modeConfigSchema.parse(modeWithJustRegex)).not.toThrow()
expect(() => modeConfigSchema.parse(modeWithDescription)).not.toThrow()
})

it("validates command regex patterns", () => {
const validPatterns = ["^npm\\s", "^git\\s", ".*", "npm|yarn|pnpm", "^docker\\s+", "[a-z]+"]
const invalidPatterns = ["[", "(unclosed", "\\", "*", "+*", "?"]

validPatterns.forEach((pattern) => {
const mode = {
slug: "test",
name: "Test",
roleDefinition: "Test",
groups: ["read", ["command", { commandRegex: pattern }]],
}
expect(() => modeConfigSchema.parse(mode)).not.toThrow()
})

invalidPatterns.forEach((pattern) => {
const mode = {
slug: "test",
name: "Test",
roleDefinition: "Test",
groups: ["read", ["command", { commandRegex: pattern }]],
}
expect(() => modeConfigSchema.parse(mode)).toThrow()
})
})
})

const validBaseMode = {
slug: "123e4567-e89b-12d3-a456-426614174000",
name: "Test Mode",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/core/prompts/sections/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ RULES
- You cannot \`cd\` into a different directory to complete a task. You are stuck operating from '${cwd.toPosix()}', so be sure to pass in the correct 'path' parameter when using tools that require a path.
- Do not use the ~ character or $HOME to refer to the home directory.
- Before using the execute_command tool, you must first think about the SYSTEM INFORMATION context provided to understand the user's environment and tailor your commands to ensure they are compatible with their system. You must also consider if the command you need to run should be executed in a specific directory outside of the current working directory '${cwd.toPosix()}', and if so prepend with \`cd\`'ing into that directory ${chainOp} then executing the command (as one command since you are stuck operating from '${cwd.toPosix()}'). For example, if you needed to run \`npm install\` in a project outside of '${cwd.toPosix()}', you would need to prepend with a \`cd\` i.e. pseudocode for this would be \`cd (path to project) ${chainOp} (command, in this case npm install)\`.${chainNote ? ` ${chainNote}` : ""}
- Some modes have restrictions on which files they can edit. If you attempt to edit a restricted file, the operation will be rejected with a FileRestrictionError that will specify which file patterns are allowed for the current mode.
- Some modes have restrictions on which files can be edited or commands that can be executed. If you attempt to edit a restricted file or execute a restricted command, the operation will be rejected with a restriction error that will specify which patterns are allowed for this mode.
- Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write.
* For example, in architect mode trying to edit app.js would be rejected because architect mode can only edit files matching "\\.md$"
- When making changes to code, always consider the context in which the code is being used. Ensure that your changes are compatible with the existing codebase and that they follow the project's coding standards and best practices.
Expand Down
Loading
Loading