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
+50 -1
View File
@@ -57,6 +57,32 @@ export async function testMcpServer(
)
const version = client.getServerVersion()
const capabilities = client.getServerCapabilities()
const promptsSupported = Boolean(capabilities?.prompts)
const resourcesSupported = Boolean(capabilities?.resources)
const promptResult = promptsSupported
? await runWithInactivityLimit(() =>
client.listPrompts(undefined, {
timeout: MCP_TEST_INACTIVITY_TIMEOUT_MS,
signal: controller.signal
})
).catch((error: unknown) => {
controller.signal.throwIfAborted()
void error
return undefined
})
: undefined
const resourceResult = resourcesSupported
? await runWithInactivityLimit(() =>
client.listResources(undefined, {
timeout: MCP_TEST_INACTIVITY_TIMEOUT_MS,
signal: controller.signal
})
).catch((error: unknown) => {
controller.signal.throwIfAborted()
void error
return undefined
})
: undefined
return {
serverName: version?.name.slice(0, 120),
serverVersion: version?.version.slice(0, 64),
@@ -66,7 +92,30 @@ export async function testMcpServer(
tools: result.tools.slice(0, 100).map((tool) => ({
name: tool.name.slice(0, 128),
description: tool.description?.slice(0, 500)
}))
})),
promptsSupported,
promptCount: promptResult?.prompts.length,
prompts: promptResult?.prompts.slice(0, 100).map((prompt) => ({
name: prompt.name.slice(0, 128),
description: prompt.description?.slice(0, 500),
arguments: (prompt.arguments ?? [])
.slice(0, 32)
.map((argument) => ({
name: argument.name.slice(0, 128),
description: argument.description?.slice(0, 500),
required: argument.required === true
}))
})),
resourcesSupported,
resourceCount: resourceResult?.resources.length,
resources: resourceResult?.resources
.slice(0, 100)
.map((resource) => ({
name: resource.name.slice(0, 200),
uri: resource.uri.slice(0, 2_048),
description: resource.description?.slice(0, 500),
mimeType: resource.mimeType?.slice(0, 200)
}))
}
} catch (error) {
if (signal?.aborted && !timedOut) {