(params, ctx)
| 80 | .optional(), |
| 81 | }), |
| 82 | async execute(params, ctx) { |
| 83 | const cwd = params.workdir || Instance.directory |
| 84 | if (params.timeout !== undefined && params.timeout < 0) { |
| 85 | throw new Error(`Invalid timeout value: ${params.timeout}. Timeout must be a positive number.`) |
| 86 | } |
| 87 | const timeout = params.timeout ?? DEFAULT_TIMEOUT |
| 88 | const tree = await parser().then((p) => p.parse(params.command)) |
| 89 | if (!tree) { |
| 90 | throw new Error("Failed to parse command") |
| 91 | } |
| 92 | const agent = await Agent.get(ctx.agent) |
| 93 | |
| 94 | const checkExternalDirectory = async (dir: string) => { |
| 95 | if (Filesystem.contains(Instance.directory, dir)) return |
| 96 | if (await Permission.isBypassEnabled()) return |
| 97 | const title = `This command references paths outside of ${Instance.directory}` |
| 98 | if (agent.permission.external_directory === "ask") { |
| 99 | await Permission.ask({ |
| 100 | type: "external_directory", |
| 101 | pattern: [dir, path.join(dir, "*")], |
| 102 | sessionID: ctx.sessionID, |
| 103 | messageID: ctx.messageID, |
| 104 | callID: ctx.callID, |
| 105 | title, |
| 106 | metadata: { |
| 107 | command: params.command, |
| 108 | }, |
| 109 | }) |
| 110 | } else if (agent.permission.external_directory === "deny") { |
| 111 | throw new Permission.RejectedError( |
| 112 | ctx.sessionID, |
| 113 | "external_directory", |
| 114 | ctx.callID, |
| 115 | { |
| 116 | command: params.command, |
| 117 | }, |
| 118 | `${title} so this command is not allowed to be executed.`, |
| 119 | ) |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | await checkExternalDirectory(cwd) |
| 124 | |
| 125 | const permissions = agent.permission.bash |
| 126 | |
| 127 | const nodes = tree.rootNode.descendantsOfType("command") |
| 128 | |
| 129 | const askPatterns = new Set<string>() |
| 130 | for (const node of nodes) { |
| 131 | if (!node) continue |
| 132 | const command = [] |
| 133 | for (let i = 0; i < node.childCount; i++) { |
| 134 | const child = node.child(i) |
| 135 | if (!child) continue |
| 136 | if ( |
| 137 | child.type !== "command_name" && |
| 138 | child.type !== "word" && |
| 139 | child.type !== "string" && |
nothing calls this directly
no test coverage detected