feat: add opencode plugin with router integration and TypeScript definitions

- Implemented `createRouterAgentPluginFn` in `src/opencode.ts` to create a plugin that interacts with the router and filters routes based on metadata tags.
- Added support for executing routes with error handling and response formatting.
- Updated `rollup.config.js` to include build configurations for `opencode.js` and `opencode.d.ts`.
This commit is contained in:
2026-01-20 13:23:06 +08:00
parent 9b11ea5138
commit f4372ae55f
4 changed files with 294 additions and 141 deletions

72
src/opencode.ts Normal file
View File

@@ -0,0 +1,72 @@
import { useContextKey } from '@kevisual/context'
import { type QueryRouter, type Skill } from './route.ts'
import { type App } from './app.ts'
import { type Plugin } from "@opencode-ai/plugin"
import { filter } from '@kevisual/js-filter';
export const createRouterAgentPluginFn = (opts?: {
router?: QueryRouter,
//** 过滤比如WHERE metadata.tags includes 'opencode' */
query?: string
}) => {
let router = opts?.router
if (!router) {
const app = useContextKey<App>('app')
router = app.router
}
if (!router) {
throw new Error('Router 参数缺失')
}
const _routes = filter(router.routes, opts?.query || '')
const routes = _routes.filter(r => {
const metadata = r.metadata as Skill
if (metadata && metadata.tags && metadata.tags.includes('opencode')) {
return !!metadata.skill
}
return false
})
// opencode run "查看系统信息"
const AgentPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
'tool': {
...routes.reduce((acc, route) => {
const metadata = route.metadata as Skill
acc[metadata.skill!] = {
name: metadata.title || metadata.skill,
description: metadata.summary || '',
args: metadata.args || {},
async execute(args: Record<string, any>) {
const res = await router.run({
path: route.path,
key: route.key,
payload: args
},
{ appId: router.appId! });
if (res.code === 200) {
if (res.data?.content) {
return res.data.content;
}
if (res.data?.final) {
return '调用程序成功';
}
const str = JSON.stringify(res.data || res, null, 2);
if (str.length > 10000) {
return str.slice(0, 10000) + '... (truncated)';
}
return str;
}
return `Error: ${res?.message || '无法获取结果'}`;
}
}
return acc;
}, {} as Record<string, any>)
},
'tool.execute.before': async (opts) => {
// console.log('CnbPlugin: tool.execute.before', opts.tool);
// delete toolSkills['cnb-login-verify']
}
}
}
return AgentPlugin
}