opencode-wrapper.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /**
  2. * OpenCode Tool Wrapper - 供 Python 调用的命令行接口
  3. *
  4. * 用法:
  5. * bun run tool-wrapper.ts <tool_name> <args_json>
  6. *
  7. * 示例:
  8. * bun run tool-wrapper.ts read '{"filePath": "config.py"}'
  9. *
  10. * 支持的工具:
  11. * - read: 读取文件
  12. * - edit: 编辑文件
  13. * - write: 写入文件
  14. * - bash: 执行命令
  15. * - glob: 文件匹配
  16. * - grep: 内容搜索
  17. * - webfetch: 抓取网页
  18. * - lsp: LSP 诊断
  19. */
  20. import { resolve } from 'path'
  21. // 动态导入工具(避免编译时依赖)
  22. async function loadTool(toolName: string) {
  23. // 从 agent/tools/adapters/ 定位到 vendor/opencode
  24. const toolPath = resolve(__dirname, '../../../../vendor/opencode/packages/opencode/src/tool')
  25. switch (toolName) {
  26. case 'read':
  27. return (await import(`${toolPath}/read.ts`)).ReadTool
  28. case 'edit':
  29. return (await import(`${toolPath}/edit.ts`)).EditTool
  30. case 'write':
  31. return (await import(`${toolPath}/write.ts`)).WriteTool
  32. case 'bash':
  33. return (await import(`${toolPath}/bash.ts`)).BashTool
  34. case 'glob':
  35. return (await import(`${toolPath}/glob.ts`)).GlobTool
  36. case 'grep':
  37. return (await import(`${toolPath}/grep.ts`)).GrepTool
  38. case 'webfetch':
  39. return (await import(`${toolPath}/webfetch.ts`)).WebFetchTool
  40. case 'lsp':
  41. return (await import(`${toolPath}/lsp.ts`)).LspTool
  42. default:
  43. throw new Error(`Unknown tool: ${toolName}`)
  44. }
  45. }
  46. async function main() {
  47. const toolName = process.argv[2]
  48. const argsJson = process.argv[3]
  49. if (!toolName || !argsJson) {
  50. console.error('Usage: bun run tool-wrapper.ts <tool_name> <args_json>')
  51. console.error('Example: bun run tool-wrapper.ts read \'{"filePath": "test.py"}\'')
  52. process.exit(1)
  53. }
  54. try {
  55. // 解析参数
  56. const args = JSON.parse(argsJson)
  57. // 加载工具
  58. const Tool = await loadTool(toolName)
  59. // 构造最小化的 context(Python 调用不需要完整 context)
  60. const context = {
  61. sessionID: 'python-adapter',
  62. messageID: 'python-adapter',
  63. agent: 'python',
  64. abort: new AbortController().signal,
  65. messages: [],
  66. metadata: () => {},
  67. ask: async () => {}, // 跳过权限检查(由 Python 层处理)
  68. }
  69. // 初始化工具
  70. const toolInfo = await Tool.init()
  71. // 执行工具
  72. const result = await toolInfo.execute(args, context)
  73. // 输出 JSON 结果
  74. const output = {
  75. title: result.title,
  76. output: result.output,
  77. metadata: result.metadata || {},
  78. attachments: result.attachments || []
  79. }
  80. console.log(JSON.stringify(output))
  81. } catch (error: any) {
  82. // 输出错误信息
  83. const errorOutput = {
  84. title: 'Error',
  85. output: `Tool execution failed: ${error.message}`,
  86. metadata: {
  87. error: error.message,
  88. stack: error.stack
  89. }
  90. }
  91. console.error(JSON.stringify(errorOutput))
  92. process.exit(1)
  93. }
  94. }
  95. main().catch((error) => {
  96. console.error(JSON.stringify({
  97. title: 'Fatal Error',
  98. output: `Fatal error: ${error.message}`,
  99. metadata: {
  100. error: error.message,
  101. stack: error.stack
  102. }
  103. }))
  104. process.exit(1)
  105. })