feat: expand multi-runtime workflows for 0.10.0

GoodBuddy previously exposed Runtime capabilities, MCP assignments, plugin controls, context compaction, usage reporting, and task-completion behavior through incomplete or inconsistent paths. This release unifies managed OpenCode, Continue, and DeepSeek Harness controls; adds DSH plugin and image workflows; strengthens MCP and Runtime lifecycle bounds; fixes Windows notification activation; validates cross-architecture packages; and presents the approved bilingual four-section release notes.

The DSH plugin marketplace remains a default-off preview whose trusted third-party code runs with current-user permissions. Ask remains read-only, Execute keeps approval controls, and context compaction may use the selected model without deleting GoodBuddy chat history.

Release note: GoodBuddy 0.10.0 重点完善多 Runtime 工作流,统一 OpenCode、Continue 与 DeepSeek Harness 的能力、MCP、插件和上下文管理,并提升长对话、多会话与任务通知的连贯性。
This commit is contained in:
mesalogo
2026-08-17 12:57:12 +08:00
parent f5ee9b2198
commit cbbe30896e
50 changed files with 4077 additions and 605 deletions
+34 -13
View File
@@ -41,6 +41,7 @@ import type { KnowledgeMcpGateway } from './knowledge-mcp-gateway'
import {
createMcpToolName,
isValidMcpToolName,
listAllMcpTools,
normalizeMcpToolSchema
} from './mcp-tool-utils'
@@ -736,6 +737,7 @@ export class ModelToolProvider implements ModelToolProviderLike {
clientScope: Set<Client> = this.customMcpClients
): Promise<ConnectedMcp> {
let connection: ConnectedMcp | undefined
let dynamicToolsChangeVersion = 0
const client = new Client(
{
name: 'goodbuddy-direct-model',
@@ -748,8 +750,11 @@ export class ModelToolProvider implements ModelToolProviderLike {
autoRefresh: false,
debounceMs: 0,
onChanged: (error) => {
if (!error && connection) {
connection.dynamicToolsChanged = true
if (!error) {
dynamicToolsChangeVersion += 1
if (connection) {
connection.dynamicToolsChanged = true
}
}
}
}
@@ -764,18 +769,27 @@ export class ModelToolProvider implements ModelToolProviderLike {
timeout: MCP_TIMEOUT_MS,
signal
})
const result = await client.listTools(undefined, {
timeout: MCP_TIMEOUT_MS,
signal
})
const listedAtChangeVersion = dynamicToolsChangeVersion
const tools = await listAllMcpTools(
client,
server.name,
signal,
{
maximumTools:
MAX_MODEL_TOOLS - this.getReservedToolCount(),
pageTimeoutMs: MCP_TIMEOUT_MS,
totalTimeoutMs: MCP_CALL_MAX_TOTAL_TIMEOUT_MS
}
)
connection = {
client,
server,
tools: this.createMcpBindings(client, server, result.tools),
tools: this.createMcpBindings(client, server, tools),
dynamicToolsSupported:
server.allowDynamicTools &&
client.getServerCapabilities()?.tools?.listChanged === true,
dynamicToolsChanged: false
dynamicToolsChanged:
dynamicToolsChangeVersion !== listedAtChangeVersion
}
return connection
} catch (error) {
@@ -863,14 +877,21 @@ export class ModelToolProvider implements ModelToolProviderLike {
}
connection.dynamicToolsChanged = false
try {
const result = await connection.client.listTools(undefined, {
timeout: MCP_TIMEOUT_MS,
signal
})
const tools = await listAllMcpTools(
connection.client,
connection.server.name,
signal,
{
maximumTools:
MAX_MODEL_TOOLS - this.getReservedToolCount(),
pageTimeoutMs: MCP_TIMEOUT_MS,
totalTimeoutMs: MCP_CALL_MAX_TOTAL_TIMEOUT_MS
}
)
connection.tools = this.createMcpBindings(
connection.client,
connection.server,
result.tools
tools
)
} catch (error) {
connection.dynamicToolsChanged = true