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:
@@ -1342,8 +1342,10 @@ export function McpSettingsSection({
|
||||
</div>
|
||||
<span className="mcp-server-card__summary">
|
||||
{result
|
||||
? t('mcp.builtin.toolCount', {
|
||||
count: result.toolCount
|
||||
? t('mcp.custom.contentCounts', {
|
||||
tools: result.toolCount,
|
||||
prompts: result.promptCount ?? 0,
|
||||
resources: result.resourceCount ?? 0
|
||||
})
|
||||
: t('mcp.custom.toolsUndetected')}
|
||||
<ChevronDown
|
||||
@@ -1466,6 +1468,93 @@ export function McpSettingsSection({
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
<section
|
||||
aria-label={t('mcp.custom.promptsAriaLabel', {
|
||||
name: server.name
|
||||
})}
|
||||
className="mcp-server-tools"
|
||||
>
|
||||
<div className="mcp-server-tools__heading">
|
||||
<strong>{t('mcp.custom.prompts')}</strong>
|
||||
<small>
|
||||
{result.promptsSupported
|
||||
? t('mcp.custom.promptCount', {
|
||||
count: result.promptCount ?? 0
|
||||
})
|
||||
: t('mcp.custom.notSupported')}
|
||||
</small>
|
||||
</div>
|
||||
{result.prompts?.length ? (
|
||||
<ul>
|
||||
{result.prompts.map((prompt) => (
|
||||
<li key={prompt.name}>
|
||||
<div>
|
||||
<code>{prompt.name}</code>
|
||||
</div>
|
||||
{prompt.description && (
|
||||
<p>{prompt.description}</p>
|
||||
)}
|
||||
{prompt.arguments.length > 0 && (
|
||||
<small>
|
||||
{t('mcp.custom.promptArguments', {
|
||||
names: prompt.arguments
|
||||
.map((argument) =>
|
||||
argument.required
|
||||
? `${argument.name}*`
|
||||
: argument.name
|
||||
)
|
||||
.join(', ')
|
||||
})}
|
||||
</small>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : result.promptsSupported ? (
|
||||
<p className="settings-empty">
|
||||
{t('mcp.custom.noPrompts')}
|
||||
</p>
|
||||
) : null}
|
||||
</section>
|
||||
<section
|
||||
aria-label={t('mcp.custom.resourcesAriaLabel', {
|
||||
name: server.name
|
||||
})}
|
||||
className="mcp-server-tools"
|
||||
>
|
||||
<div className="mcp-server-tools__heading">
|
||||
<strong>{t('mcp.custom.resources')}</strong>
|
||||
<small>
|
||||
{result.resourcesSupported
|
||||
? t('mcp.custom.resourceCount', {
|
||||
count: result.resourceCount ?? 0
|
||||
})
|
||||
: t('mcp.custom.notSupported')}
|
||||
</small>
|
||||
</div>
|
||||
{result.resources?.length ? (
|
||||
<ul>
|
||||
{result.resources.map((resource) => (
|
||||
<li key={`${resource.uri}\0${resource.name}`}>
|
||||
<div>
|
||||
<strong>{resource.name}</strong>
|
||||
{resource.mimeType && (
|
||||
<small>{resource.mimeType}</small>
|
||||
)}
|
||||
</div>
|
||||
<code>{resource.uri}</code>
|
||||
{resource.description && (
|
||||
<p>{resource.description}</p>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : result.resourcesSupported ? (
|
||||
<p className="settings-empty">
|
||||
{t('mcp.custom.noResources')}
|
||||
</p>
|
||||
) : null}
|
||||
</section>
|
||||
</>
|
||||
) : (
|
||||
<p className="settings-empty">
|
||||
|
||||
Reference in New Issue
Block a user