feat: add native runtime customization
OpenCode and Continue customization was previously planned but unavailable, and Runtime-native capabilities were not represented consistently across providers. GoodBuddy now provides secure Main-owned customization settings, truthful native inventories, OpenCode Agents and Commands, Continue Rules and Prompts, DSH Web Search/Fetch, MCP Prompt and Resource metadata, and manual compaction where supported. Native capabilities are presented in eleven accessible tabs with Tools separated from Commands, LSP, and Formatters. Tool source and Ask/Execute availability are explicit, external OpenCode remains connection-only, Continue reports unsupported static tool discovery instead of advertising unreachable Skills, and disposable inventory probes avoid retaining background runtimes. Ask remains read-only at the Runtime boundary, Execute keeps the existing authorization controls, and credentials remain confined to Main. Release note: 新增 OpenCode、Continue 与 DeepSeek Harness 的 Runtime 原生定制与真实能力清单;工具来源、Ask/Execute 可用性、上下文压缩和 MCP 元数据现在可清晰查看,同时继续保持 Main 进程凭据保护与现有权限边界。
This commit is contained in:
@@ -28,6 +28,13 @@ function stubAgentContext() {
|
||||
(...args: unknown[]) => unknown
|
||||
>()
|
||||
const extNotification = vi.fn(async () => undefined)
|
||||
const genuineDefinitions = new Map(
|
||||
['read', 'skill', 'web_search'].map((name) => [
|
||||
name,
|
||||
{ name }
|
||||
])
|
||||
)
|
||||
const resolvedDefinitions = new Map(genuineDefinitions)
|
||||
const handle = {
|
||||
agent: {
|
||||
session: {
|
||||
@@ -35,7 +42,14 @@ function stubAgentContext() {
|
||||
header: { id: 'session-output' },
|
||||
events: []
|
||||
},
|
||||
cancel: vi.fn()
|
||||
cancel: vi.fn(),
|
||||
ctx: {
|
||||
tools: {
|
||||
get: vi.fn((name: string) =>
|
||||
resolvedDefinitions.get(name)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const ctx = {
|
||||
@@ -68,6 +82,7 @@ function stubAgentContext() {
|
||||
string,
|
||||
{
|
||||
handle: typeof handle
|
||||
askToolDefinitions: Map<string, unknown>
|
||||
inflight: {
|
||||
requestId: string
|
||||
messageId: string
|
||||
@@ -85,6 +100,7 @@ function stubAgentContext() {
|
||||
internals.connection = { extNotification }
|
||||
internals.sessions.set('session-output', {
|
||||
handle,
|
||||
askToolDefinitions: genuineDefinitions,
|
||||
inflight: {
|
||||
requestId: 'request-output',
|
||||
messageId: 'message-output',
|
||||
@@ -96,7 +112,14 @@ function stubAgentContext() {
|
||||
}
|
||||
})
|
||||
internals.observeSessions()
|
||||
return { listeners, extNotification, handle, internals }
|
||||
return {
|
||||
listeners,
|
||||
extNotification,
|
||||
handle,
|
||||
internals,
|
||||
genuineDefinitions,
|
||||
resolvedDefinitions
|
||||
}
|
||||
}
|
||||
|
||||
describe('GoodBuddy Harness internal control plane', () => {
|
||||
@@ -236,8 +259,13 @@ describe('GoodBuddy Harness internal control plane', () => {
|
||||
).toBeGreaterThan(180)
|
||||
})
|
||||
|
||||
it('allows only the known read-only tools in Ask', async () => {
|
||||
const { listeners, handle } = stubAgentContext()
|
||||
it('allows genuine read, skill, and web definitions but rejects plugin name spoofs in Ask', async () => {
|
||||
const {
|
||||
listeners,
|
||||
handle,
|
||||
genuineDefinitions,
|
||||
resolvedDefinitions
|
||||
} = stubAgentContext()
|
||||
const executeTool = listeners.get('tools/execute')!
|
||||
const next = vi.fn(async () => ({
|
||||
isError: false,
|
||||
@@ -260,11 +288,22 @@ describe('GoodBuddy Harness internal control plane', () => {
|
||||
Promise.resolve(executeTool(request(name), next))
|
||||
).rejects.toThrow('Ask 模式不允许')
|
||||
}
|
||||
for (const name of ['read', 'skill']) {
|
||||
for (const name of ['read', 'skill', 'web_search']) {
|
||||
await expect(
|
||||
Promise.resolve(executeTool(request(name), next))
|
||||
).resolves.toMatchObject({ isError: false })
|
||||
}
|
||||
|
||||
for (const name of ['read', 'skill', 'web_search']) {
|
||||
resolvedDefinitions.set(name, { name })
|
||||
await expect(
|
||||
Promise.resolve(executeTool(request(name), next))
|
||||
).rejects.toThrow('Ask 模式不允许')
|
||||
resolvedDefinitions.set(
|
||||
name,
|
||||
genuineDefinitions.get(name)!
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('allows every registered tool in Execute', async () => {
|
||||
|
||||
Reference in New Issue
Block a user