Files
inkreach-agent/apps/desktop/scripts/smoke-tools.mjs
T

67 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* v0.4.0 冒烟:业务工具注册 / 手动直调(D2 双模式路径)/ tool_call 拦截契约
* 说明:审批拦截逻辑与 src/main/pi/approval.ts 保持一致(此处内联同构实现,
* 因冒烟脚本无法直接加载 TS 源文件;拦截契约由 pi 的 ExtensionHandler 类型保证)。
*/
import { createAgentSessionFromServices, createAgentSessionServices, defineTool, getAgentDir, SessionManager } from '@earendil-works/pi-coding-agent'
import { Type } from '@earendil-works/pi-ai'
import { homedir } from 'node:os'
const cwd = homedir()
const agentDir = getAgentDir()
// 与 src/main/tools/demo-tools.ts 同构的工具定义
const hotwordLookup = defineTool({
name: 'hotword_lookup',
label: '热点词查询(演示)',
description: 'demo',
parameters: Type.Object({ query: Type.String(), limit: Type.Optional(Type.Number()) }),
async execute(_id, params) {
return {
content: [{ type: 'text', text: `热点词查询结果(演示数据源,query="${params.query}"):ok` }],
details: { source: 'demo' }
}
}
})
// ---- 1) 工具注册检查(customTools 路径) ----
const services = await createAgentSessionServices({ cwd, agentDir })
const { session } = await createAgentSessionFromServices({
services,
sessionManager: SessionManager.inMemory(cwd),
customTools: [hotwordLookup]
})
const all = session.getAllTools()
console.log('[smoke4] registered tools:', all.map((t) => t.name).join(', '))
console.log('[smoke4] hotword_lookup registered:', all.some((t) => t.name === 'hotword_lookup'))
// ---- 2) 手动直调(双模式共用能力的证明,不经 LLM) ----
const result = await hotwordLookup.execute('smoke-call', { query: '宠物' }, undefined, undefined, {})
console.log('[smoke4] manual execute text:', JSON.stringify(result.content[0]?.text?.slice(0, 60)))
// ---- 3) tool_call 拦截契约(模拟 ExtensionAPI 捕获 handler) ----
const handlers = {}
const fakePi = { on: (event, handler) => { handlers[event] = handler } }
const needsApproval = new Set(['price_check', 'bash'])
let decision = false
fakePi.on('tool_call', async (event) => {
if (!needsApproval.has(event.toolName)) return
const approved = decision
if (!approved) return { block: true, reason: '用户拒绝了本次工具调用审批' }
return
})
const passthrough = await handlers['tool_call']({ type: 'tool_call', toolName: 'read', input: { path: 'x' } })
console.log('[smoke4] read(不在名单)放行:', passthrough === undefined)
decision = false
const denied = await handlers['tool_call']({ type: 'tool_call', toolName: 'price_check', input: { product_id: 'P1', target_price: 9.9 } })
console.log('[smoke4] price_check 拒绝 -> block:', JSON.stringify(denied))
decision = true
const approvedRes = await handlers['tool_call']({ type: 'tool_call', toolName: 'bash', input: { command: 'ls' } })
console.log('[smoke4] bash 批准 -> 放行:', approvedRes === undefined)
console.log('[smoke4] done')
process.exit(0)