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:
mesalogo
2026-08-16 17:08:46 +08:00
parent ff61b5f81d
commit b56b0f8826
55 changed files with 9059 additions and 433 deletions
@@ -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 () => {