| 1581 | */ |
| 1582 | |
| 1583 | export async function command(input: CommandInput) { |
| 1584 | log.info("command", input) |
| 1585 | if (input.command === "usage") { |
| 1586 | const modelRef = input.model ? Provider.parseModel(input.model) : await lastModel(input.sessionID) |
| 1587 | return SessionUsage.run({ |
| 1588 | sessionID: input.sessionID, |
| 1589 | agent: input.agent ?? "build", |
| 1590 | model: modelRef, |
| 1591 | }) |
| 1592 | } |
| 1593 | |
| 1594 | const command = await Command.get(input.command) |
| 1595 | if (!command) { |
| 1596 | throw new Error(`Command not found: ${input.command}`) |
| 1597 | } |
| 1598 | const agentName = command.agent ?? input.agent ?? "build" |
| 1599 | |
| 1600 | const raw = input.arguments.match(argsRegex) ?? [] |
| 1601 | const args = raw.map((arg) => arg.replace(quoteTrimRegex, "")) |
| 1602 | |
| 1603 | const placeholders = command.template.match(placeholderRegex) ?? [] |
| 1604 | let last = 0 |
| 1605 | for (const item of placeholders) { |
| 1606 | const value = Number(item.slice(1)) |
| 1607 | if (value > last) last = value |
| 1608 | } |
| 1609 | |
| 1610 | // Let the final placeholder swallow any extra arguments so prompts read naturally |
| 1611 | const withArgs = command.template.replaceAll(placeholderRegex, (_, index) => { |
| 1612 | const position = Number(index) |
| 1613 | const argIndex = position - 1 |
| 1614 | if (argIndex >= args.length) return "" |
| 1615 | if (position === last) return args.slice(argIndex).join(" ") |
| 1616 | return args[argIndex] |
| 1617 | }) |
| 1618 | let template = withArgs.replaceAll("$ARGUMENTS", input.arguments) |
| 1619 | if (placeholders.length === 0 && !command.template.includes("$ARGUMENTS") && input.arguments.trim().length > 0) { |
| 1620 | template = `${template}\n\n${input.arguments}`.trim() |
| 1621 | } |
| 1622 | |
| 1623 | const shell = ConfigMarkdown.shell(template) |
| 1624 | if (shell.length > 0) { |
| 1625 | const results = await Promise.all( |
| 1626 | shell.map(async ([, cmd]) => { |
| 1627 | try { |
| 1628 | return await $`${{ raw: cmd }}`.nothrow().text() |
| 1629 | } catch (error) { |
| 1630 | return `Error executing command: ${error instanceof Error ? error.message : String(error)}` |
| 1631 | } |
| 1632 | }), |
| 1633 | ) |
| 1634 | let index = 0 |
| 1635 | template = template.replace(bashRegex, () => results[index++]) |
| 1636 | } |
| 1637 | template = template.trim() |
| 1638 | |
| 1639 | const model = await (async () => { |
| 1640 | if (command.model) { |