Files
goodbuddy/src/main/agent/native-dsh-web-policy.ts
T
mesalogo f81f342cde feat: open local runtime clients from the composer
Add composer shortcuts for local Continue and OpenCode terminals and the official DeepSeek Harness Web client, using the current project and model bridge. Manage browser service reuse, stop actions and terminal cleanup. Upgrade DeepSeek Harness to 0.1.7-rc.2 and Cordis to 4.0.4.

Include the coordinated IPC handler extraction and related tests and documentation. Remote native-client coordinator wiring, managed Node consolidation, Ask MCP mappings and full desktop/package acceptance remain unfinished; this commit records the implemented local workflow and supporting SSH groundwork.

Validation: typecheck and lint passed; 267 focused tests passed and 5 skipped. No new real-provider calls were made for this commit. Prior real-model evidence and remaining acceptance work are documented in the feature progress files.

Release note: 本地项目选择 Continue 或 OpenCode 后,可从输入框下方打开原生终端;选择 DS 后,可打开使用当前项目和模型的官方 Web 客户端。客户端使用独立会话,DS 网页关闭后服务继续运行,可在 GoodBuddy 中停止;远程入口尚未完成。
2026-09-27 08:38:00 +08:00

75 lines
2.9 KiB
TypeScript

import { createHash } from 'node:crypto'
// Official dsh-mcp-client 0.1.7-rc.2 naming contract; its helper is private.
export function nativeDshMcpToolName(serverName: string, rawName: string): string {
const joined = `mcp__${serverName}__${rawName}`
const normalized = joined.replace(/[^A-Za-z0-9_-]/gu, '_')
if (joined === normalized && normalized.length <= 64) return joined
const hash = createHash('sha256').update(`${serverName}\0${rawName}`).digest('hex').slice(0, 12)
return `${normalized.slice(0, 51)}_${hash}`
}
export type NativeDshMcpServer = {
serverName: string
readOnlyTools?: string[]
} & (
| { transport: 'stdio'; command: string; args?: string[]; env?: Record<string, string>; cwd?: string }
| { transport: 'streamable-http'; url: string; headers?: Record<string, string> }
)
// Loaded by the official Cordis loader, outside Electron and its ASAR bundle.
// The launch mode applies to every session, including delegated agents.
export const nativeDshWebPolicySource = `
export const name = 'goodbuddy-native-mode';
export function apply(ctx, config) {
const allowed = new Set(['read', 'skill', ...config.readOnlyTools]);
ctx.on('tools/execute', (exec, next) => {
if (config.workMode === 'ask' && !allowed.has(exec.name)) {
throw new Error('GoodBuddy Ask mode does not allow tool: ' + exec.name);
}
return next();
});
}
`
export function nativeDshWebPatch(options: {
model: string
api: string
baseURL: string
workMode: 'ask' | 'execute'
policyPath: string
skillDirectories: string[]
mcpServers: NativeDshMcpServer[]
readOnlyTools: string[]
}): unknown[] {
return [
{
id: 'llm-pi-ai',
config: { providers: { goodbuddy: {
displayName: 'GoodBuddy', api: options.api,
apiKeyEnv: 'GOODBUDDY_DSH_MODEL_KEY', baseURL: options.baseURL,
models: [{ id: options.model, name: options.model }]
} } }
},
{ id: 'agent-default-model', config: { provider: 'goodbuddy', model: options.model } },
{ id: 'sandbox-policy', config: { mode: 'danger-full-access' } },
{ id: 'approval', config: { policy: 'never' } },
// The launch mode owns permissions. Native Plan remains a planning aid.
{ id: 'ui-permission', disabled: true },
{ insert: [
{ id: 'goodbuddy-native-mode', name: options.policyPath,
config: { workMode: options.workMode, readOnlyTools: options.readOnlyTools } },
...(options.skillDirectories.length ? [{
id: 'goodbuddy-skills', name: '@deepseek-ai/dsh-skill-filesystem',
config: { providerName: 'goodbuddy', includeDefaultRoots: false,
customSkillDirs: options.skillDirectories }
}] : []),
...options.mcpServers.map((server, index) => {
const config = { ...server, failOnStartupError: true }
delete config.readOnlyTools
return { id: `goodbuddy-mcp-${index}`, name: '@deepseek-ai/dsh-mcp-client', config }
})
] }
]
}