duplicate-pr.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/env bun
  2. import path from "path"
  3. import { pathToFileURL } from "bun"
  4. import { createOpencode } from "@opencode-ai/sdk"
  5. import { parseArgs } from "util"
  6. async function main() {
  7. const { values, positionals } = parseArgs({
  8. args: Bun.argv.slice(2),
  9. options: {
  10. file: { type: "string", short: "f" },
  11. help: { type: "boolean", short: "h", default: false },
  12. },
  13. allowPositionals: true,
  14. })
  15. if (values.help) {
  16. console.log(`
  17. Usage: bun script/duplicate-pr.ts [options] <message>
  18. Options:
  19. -f, --file <path> File to attach to the prompt
  20. -h, --help Show this help message
  21. Examples:
  22. bun script/duplicate-pr.ts -f pr_info.txt "Check the attached file for PR details"
  23. `)
  24. process.exit(0)
  25. }
  26. const message = positionals.join(" ")
  27. if (!message) {
  28. console.error("Error: message is required")
  29. process.exit(1)
  30. }
  31. const opencode = await createOpencode({ port: 0 })
  32. try {
  33. const parts: Array<{ type: "text"; text: string } | { type: "file"; url: string; filename: string; mime: string }> =
  34. []
  35. if (values.file) {
  36. const resolved = path.resolve(process.cwd(), values.file)
  37. const file = Bun.file(resolved)
  38. if (!(await file.exists())) {
  39. console.error(`Error: file not found: ${values.file}`)
  40. process.exit(1)
  41. }
  42. parts.push({
  43. type: "file",
  44. url: pathToFileURL(resolved).href,
  45. filename: path.basename(resolved),
  46. mime: "text/plain",
  47. })
  48. }
  49. parts.push({ type: "text", text: message })
  50. const session = await opencode.client.session.create()
  51. const result = await opencode.client.session
  52. .prompt({
  53. path: { id: session.data!.id },
  54. body: {
  55. agent: "duplicate-pr",
  56. parts,
  57. },
  58. signal: AbortSignal.timeout(120_000),
  59. })
  60. .then((x) => x.data?.parts?.find((y) => y.type === "text")?.text ?? "")
  61. console.log(result.trim())
  62. } finally {
  63. opencode.server.close()
  64. }
  65. }
  66. main()