Main no longer opens desktop business SQLite. A single utility-process
storage owner holds the Assistant, Knowledge, attachment, document-result,
remote-binding and native model-ledger databases and runs whole domain
transactions; Main and Runtime callers use explicit async domain operations.
- Remove the Main readWithFallback path and the supervision worker's
separate business write connection; manifests are scanned read-only and
committed by the sole writer.
- Remote events are ACKed only after commit; process loss reports
unconfirmed writes instead of replaying them.
- Use native utilityProcess messaging with one in-flight bound (32) and
ordered waiting instead of capacity rejection and retries.
- Start the storage process before the window so startup overlaps.
- Keep short tool output in memory and store full output once in owned
storage; paging, branching, restart and deletion reuse that copy.
- Put required runtime launch files under goodbuddy-prefixed owned temp
directories and reclaim confirmed stale ones; stop writing duplicate
parsed.md.
- Add lint guards for SQLite ownership and architecture, concurrency
acceptance fixtures, and maintenance/architecture documentation.
Validation: typecheck and lint pass. Alternating baseline (edf019aa) vs
candidate runs show no regression on single-session, C01, C02, C04 and a
5-minute C06; Main p99 drops from ~21 ms to ~16.7 ms under concurrency.
Fresh portable copy (1.75M events) upgrade content unchanged; real-model
output paging passes with 4 external requests. Full npm test runs had
1-9 different timing-sensitive failures per run that pass when rerun.
Not covered: C03 review publication, C07 source body, app-level C05.
413 lines
15 KiB
TypeScript
413 lines
15 KiB
TypeScript
import {
|
|
ModelAgentRuntime,
|
|
noModelTools,
|
|
type ModelRuntimeOptions
|
|
} from './model-runtime'
|
|
import { ContinueAgentRuntime } from './continue-runtime'
|
|
import { OpenCodeRuntime, type OpenCodeRuntimeOptions } from './opencode-runtime'
|
|
import type { LocalRuntimeRegistry } from './local-runtime-registry'
|
|
import {
|
|
DeepSeekHarnessRuntime,
|
|
type DeepSeekHarnessRuntimeOptions
|
|
} from './deepseek-harness-runtime'
|
|
import type { AgentRuntime } from './runtime'
|
|
import { UnconfiguredAgentRuntime } from './unconfigured-runtime'
|
|
import type {
|
|
ResolvedModelProfile,
|
|
ResolvedRuntimeSettings
|
|
} from '../runtime-settings-store'
|
|
import {
|
|
defaultRuntimeSettings,
|
|
isDeepSeekHarnessModelProfile,
|
|
isAgentRuntimeModelProtocol
|
|
} from '../../shared/contracts'
|
|
import type {
|
|
ResolvedMcpServer,
|
|
RuntimeSkillPackage
|
|
} from '../capabilities/capability-service'
|
|
import type { BundledRuntimePaths } from './bundled-runtimes'
|
|
import {
|
|
ContinueHostAdapter,
|
|
type ContinueHostLauncher
|
|
} from './continue-host-adapter'
|
|
import type { BrowserToolService } from '../browser/browser-model-tools'
|
|
import type { SubagentScheduler } from '../assistant/subagent-scheduler'
|
|
import type { KnowledgeMcpGateway } from './knowledge-mcp-gateway'
|
|
import { ModelToolProvider } from './model-tool-provider'
|
|
import type { ControlledHarnessExtensionPackage } from './deepseek-harness-extension-loader'
|
|
import {
|
|
LocalWorkspaceAccess,
|
|
type WorkspaceAccess
|
|
} from '../workspace'
|
|
import {
|
|
REMOTE_EXECUTION_SPACE_UNAVAILABLE,
|
|
type ExecutionSpaceDescriptor
|
|
} from '../execution-space'
|
|
import type { LaunchEnvironmentProvider } from '../local-tool-environment/launch-environment-provider'
|
|
import type { DesktopDiagnosticFailureObserver } from '../desktop-diagnostics'
|
|
export type AgentCapabilityContext = {
|
|
outputStore?: ModelRuntimeOptions['outputStore']
|
|
outputAdopt?: ModelRuntimeOptions['outputAdopt']
|
|
observeFailure?: DesktopDiagnosticFailureObserver
|
|
localRuntimeRegistry?: LocalRuntimeRegistry
|
|
skillInstructions?: string
|
|
skillPackages?: RuntimeSkillPackage[]
|
|
mcpServers?: ResolvedMcpServer[]
|
|
continueHostCacheRoot?: string
|
|
opencodeSharedCacheRoot?: string
|
|
bundledRuntimePaths?: BundledRuntimePaths
|
|
continueHostLauncher?: ContinueHostLauncher
|
|
deepseekHarnessLauncher?: DeepSeekHarnessRuntimeOptions['launch']
|
|
deepseekHarnessExtensions?: ControlledHarnessExtensionPackage[]
|
|
browserService?: BrowserToolService
|
|
knowledgeGateway?: KnowledgeMcpGateway
|
|
webSearchEnabled?: boolean
|
|
executionSpace?: ExecutionSpaceDescriptor
|
|
workspaceAccess?: WorkspaceAccess
|
|
directModelSubagentScheduler?: SubagentScheduler
|
|
launchEnvironmentProvider?: LaunchEnvironmentProvider
|
|
}
|
|
|
|
function resolveContextCompression(
|
|
settings: ResolvedRuntimeSettings,
|
|
currentProfile: ResolvedModelProfile | undefined
|
|
): ModelRuntimeOptions['contextCompression'] {
|
|
const compression =
|
|
settings.contextCompression ?? defaultRuntimeSettings.contextCompression
|
|
const source = compression.modelSource
|
|
const summaryProfile =
|
|
source.kind === 'profile'
|
|
? settings.modelProfiles.find(
|
|
(profile) =>
|
|
profile.id === source.profileId &&
|
|
isAgentRuntimeModelProtocol(profile.protocol)
|
|
)
|
|
: undefined
|
|
return {
|
|
settings: compression,
|
|
contextWindowTokens: currentProfile?.contextWindowTokens,
|
|
...(summaryProfile
|
|
? {
|
|
summaryModel: {
|
|
apiKey: summaryProfile.apiKey,
|
|
baseUrl: summaryProfile.baseUrl,
|
|
model: summaryProfile.modelName,
|
|
protocol: summaryProfile.protocol as Exclude<
|
|
typeof summaryProfile.protocol,
|
|
'openai-images-generations'
|
|
>,
|
|
authentication: summaryProfile.authentication,
|
|
contextWindowTokens: summaryProfile.contextWindowTokens,
|
|
maximumOutputTokens: summaryProfile.maximumOutputTokens,
|
|
requestHeaders: summaryProfile.requestHeaders,
|
|
requestBody: summaryProfile.requestBody
|
|
}
|
|
}
|
|
: {})
|
|
}
|
|
}
|
|
|
|
export function createDefaultModelRuntime(
|
|
defaultWorkspace: string,
|
|
settings: ResolvedRuntimeSettings
|
|
): AgentRuntime {
|
|
if (settings.modelProtocol === 'openai-images-generations') {
|
|
return new UnconfiguredAgentRuntime()
|
|
}
|
|
const currentProfile = settings.modelProfiles.find(
|
|
(profile) => profile.id === settings.defaultModelProfileId
|
|
)
|
|
return new ModelAgentRuntime({
|
|
apiKey: settings.apiKey,
|
|
baseUrl: settings.modelBaseUrl,
|
|
model: settings.modelName,
|
|
protocol: settings.modelProtocol,
|
|
authentication: settings.modelAuthentication,
|
|
requestHeaders: currentProfile?.requestHeaders,
|
|
requestBody: currentProfile?.requestBody,
|
|
supportsImageInput: settings.supportsImageInput,
|
|
maximumOutputTokens: currentProfile?.maximumOutputTokens,
|
|
defaultWorkspace: settings.workspacePath || defaultWorkspace,
|
|
contextCompression: resolveContextCompression(
|
|
settings,
|
|
currentProfile
|
|
),
|
|
toolProvider: noModelTools
|
|
})
|
|
}
|
|
|
|
export function createModelProfileRuntime(
|
|
defaultWorkspace: string,
|
|
settings: ResolvedRuntimeSettings,
|
|
profile: ResolvedModelProfile
|
|
): ModelAgentRuntime {
|
|
return new ModelAgentRuntime({
|
|
apiKey: profile.apiKey,
|
|
baseUrl: profile.baseUrl,
|
|
model: profile.modelName,
|
|
protocol: profile.protocol,
|
|
authentication: profile.authentication,
|
|
requestHeaders: profile.requestHeaders,
|
|
requestBody: profile.requestBody,
|
|
supportsImageInput: profile.supportsImageInput,
|
|
maximumOutputTokens: profile.maximumOutputTokens,
|
|
imageGenerationQuality:
|
|
profile.imageGenerationQuality ??
|
|
defaultRuntimeSettings.imageGenerationQuality,
|
|
contextCompression: resolveContextCompression(settings, profile),
|
|
defaultWorkspace: settings.workspacePath || defaultWorkspace,
|
|
toolProvider: noModelTools
|
|
})
|
|
}
|
|
|
|
export function createAgentRuntime(
|
|
defaultWorkspace: string,
|
|
settings?: ResolvedRuntimeSettings,
|
|
capabilities: AgentCapabilityContext = {}
|
|
): AgentRuntime {
|
|
const executionSpace = capabilities.executionSpace
|
|
const remote = executionSpace?.kind === 'ssh'
|
|
const baseUrl = (
|
|
settings?.opencodeBaseUrl ||
|
|
process.env.GOODBUDDY_OPENCODE_URL ||
|
|
''
|
|
).trim()
|
|
const embedded = !baseUrl
|
|
const workspace =
|
|
executionSpace?.kind === 'local'
|
|
? executionSpace.rootPath
|
|
: settings?.workspacePath || defaultWorkspace
|
|
const getWorkspaceAccess = (): WorkspaceAccess =>
|
|
capabilities.workspaceAccess ??
|
|
executionSpace?.workspaceAccess ??
|
|
new LocalWorkspaceAccess(workspace)
|
|
const provider = settings?.provider ?? defaultRuntimeSettings.provider
|
|
|
|
if (
|
|
remote &&
|
|
(provider === 'continue' ||
|
|
provider === 'opencode' ||
|
|
provider === 'deepseek-harness' ||
|
|
provider === 'auto')
|
|
) {
|
|
throw new Error(REMOTE_EXECUTION_SPACE_UNAVAILABLE)
|
|
}
|
|
|
|
if (provider === 'deepseek-harness') {
|
|
const profile = settings?.deepseekHarnessModelProfile
|
|
if (!profile || !isDeepSeekHarnessModelProfile(profile)) {
|
|
throw new Error(
|
|
'DeepSeek Harness 需要使用 API Key 的 OpenAI 兼容 Chat Completions 模型连接'
|
|
)
|
|
}
|
|
if (!profile.apiKey) {
|
|
throw new Error('DeepSeek Harness 模型连接未配置 API Key')
|
|
}
|
|
if (!capabilities.deepseekHarnessLauncher) {
|
|
throw new Error('DeepSeek Harness 受控 Host 启动器不可用')
|
|
}
|
|
const options: DeepSeekHarnessRuntimeOptions = {
|
|
defaultWorkspace: capabilities.localRuntimeRegistry ? defaultWorkspace : workspace,
|
|
baseUrl: profile.baseUrl,
|
|
model: profile.modelName,
|
|
supportsImageInput: profile.supportsImageInput === true,
|
|
requestHeaders: profile.requestHeaders,
|
|
launch: capabilities.deepseekHarnessLauncher,
|
|
credentialRefs: {
|
|
GOODBUDDY_HARNESS_MODEL_API_KEY: profile.apiKey
|
|
},
|
|
skillPackages: capabilities.skillPackages,
|
|
extensionPackages: capabilities.deepseekHarnessExtensions,
|
|
createToolProvider: (directory) => new ModelToolProvider(
|
|
new LocalWorkspaceAccess(directory), capabilities.mcpServers, undefined,
|
|
capabilities.knowledgeGateway, capabilities.webSearchEnabled === true,
|
|
{
|
|
runtimeTarget: 'deepseek-harness',
|
|
outputStore: capabilities.outputStore,
|
|
outputAdopt: capabilities.outputAdopt
|
|
}, capabilities.launchEnvironmentProvider
|
|
)
|
|
}
|
|
const create = () => new DeepSeekHarnessRuntime(options)
|
|
if (!capabilities.localRuntimeRegistry) return create()
|
|
const configuration = { ...options, defaultWorkspace: undefined, createToolProvider: undefined }
|
|
return capabilities.localRuntimeRegistry.acquire(
|
|
`deepseek-harness:${profile.id}`,
|
|
{
|
|
...configuration,
|
|
mcpServers: capabilities.mcpServers,
|
|
webSearchEnabled: capabilities.webSearchEnabled === true,
|
|
launchEnvironment: capabilities.launchEnvironmentProvider?.()
|
|
},
|
|
workspace,
|
|
create
|
|
)
|
|
}
|
|
|
|
if (provider === 'continue') {
|
|
if (
|
|
settings?.continueModelProfile &&
|
|
!isAgentRuntimeModelProtocol(
|
|
settings.continueModelProfile.protocol
|
|
)
|
|
) {
|
|
throw new Error(
|
|
'Continue 独立模型连接仅支持文本对话协议,不支持图像生成协议'
|
|
)
|
|
}
|
|
return new ContinueAgentRuntime({
|
|
binaryPath:
|
|
settings?.continueBinaryPath ??
|
|
process.env.GOODBUDDY_CONTINUE_BINARY?.trim() ??
|
|
process.env.GOODBUDDY_CONTINUE_COMMAND?.trim() ??
|
|
'',
|
|
bundledBinaryPath: capabilities.bundledRuntimePaths?.continue,
|
|
configPath:
|
|
settings?.continueConfigPath ??
|
|
process.env.GOODBUDDY_CONTINUE_CONFIG?.trim() ??
|
|
'',
|
|
modelProfile: settings?.continueModelProfile,
|
|
skillInstructions: capabilities.skillInstructions,
|
|
skillPackages: capabilities.skillPackages,
|
|
defaultWorkspace: workspace,
|
|
hostCacheRoot:
|
|
capabilities.continueHostCacheRoot ??
|
|
process.env.GOODBUDDY_CONTINUE_HOST_CACHE?.trim() ??
|
|
'',
|
|
launchHost: capabilities.continueHostLauncher,
|
|
createHostAdapter: capabilities.launchEnvironmentProvider
|
|
? (options) =>
|
|
new ContinueHostAdapter({
|
|
...options,
|
|
launchEnvironmentProvider:
|
|
capabilities.launchEnvironmentProvider
|
|
})
|
|
: undefined,
|
|
knowledgeGateway: capabilities.knowledgeGateway,
|
|
mcpServers: capabilities.mcpServers,
|
|
customization: settings?.runtimeCustomization.continue
|
|
})
|
|
}
|
|
|
|
if (provider === 'opencode' || (provider === 'auto' && (baseUrl || embedded))) {
|
|
if (
|
|
settings?.opencodeModelProfile &&
|
|
!isAgentRuntimeModelProtocol(
|
|
settings.opencodeModelProfile.protocol
|
|
)
|
|
) {
|
|
throw new Error(
|
|
'OpenCode 独立模型连接仅支持文本对话协议,不支持图像生成协议'
|
|
)
|
|
}
|
|
const options: OpenCodeRuntimeOptions = {
|
|
observeFailure: capabilities.observeFailure,
|
|
baseUrl,
|
|
embedded,
|
|
binaryPath:
|
|
settings?.opencodeBinaryPath ??
|
|
process.env.GOODBUDDY_OPENCODE_BINARY?.trim() ??
|
|
'',
|
|
bundledBinaryPath: capabilities.bundledRuntimePaths?.opencode,
|
|
bundledConfigPath:
|
|
capabilities.bundledRuntimePaths?.opencodeConfig,
|
|
configPath:
|
|
settings?.opencodeConfigPath ??
|
|
process.env.GOODBUDDY_OPENCODE_CONFIG?.trim() ??
|
|
'',
|
|
modelProfile: settings?.opencodeModelProfile,
|
|
skillInstructions: capabilities.skillInstructions,
|
|
skillPackages: capabilities.skillPackages,
|
|
sharedCacheRoot: capabilities.opencodeSharedCacheRoot,
|
|
defaultWorkspace: capabilities.localRuntimeRegistry ? defaultWorkspace : workspace,
|
|
knowledgeGateway: capabilities.knowledgeGateway,
|
|
mcpServers: capabilities.mcpServers,
|
|
customization: settings?.runtimeCustomization.opencode,
|
|
launchEnvironmentProvider:
|
|
capabilities.launchEnvironmentProvider
|
|
}
|
|
const create = () => new OpenCodeRuntime(options)
|
|
if (!capabilities.localRuntimeRegistry) return create()
|
|
const configuration = { ...options, defaultWorkspace: undefined }
|
|
return capabilities.localRuntimeRegistry.acquire(
|
|
`opencode:${settings?.opencodeModelProfile?.id ?? 'native'}`,
|
|
{
|
|
...configuration,
|
|
launchEnvironment: capabilities.launchEnvironmentProvider?.()
|
|
},
|
|
workspace,
|
|
create
|
|
)
|
|
}
|
|
|
|
const defaultModelProfile =
|
|
settings?.modelProfiles.find(
|
|
(profile) => profile.id === settings.defaultModelProfileId
|
|
) ?? settings?.modelProfiles[0]
|
|
const modelApiKey =
|
|
defaultModelProfile?.apiKey ||
|
|
settings?.apiKey ||
|
|
process.env.GOODBUDDY_MODEL_API_KEY?.trim() ||
|
|
process.env.GOODBUDDY_BIGTOKEN_API_KEY?.trim()
|
|
const modelAuthentication =
|
|
defaultModelProfile?.authentication ??
|
|
settings?.modelAuthentication ??
|
|
defaultRuntimeSettings.modelAuthentication
|
|
if (
|
|
provider === 'model' ||
|
|
(provider === 'auto' &&
|
|
(modelAuthentication === 'none' || modelApiKey))
|
|
) {
|
|
return new ModelAgentRuntime({
|
|
outputStore: capabilities.outputStore,
|
|
outputAdopt: capabilities.outputAdopt,
|
|
apiKey: modelApiKey ?? '',
|
|
baseUrl:
|
|
defaultModelProfile?.baseUrl ||
|
|
settings?.modelBaseUrl ||
|
|
process.env.GOODBUDDY_MODEL_BASE_URL?.trim() ||
|
|
process.env.GOODBUDDY_BIGTOKEN_BASE_URL?.trim() ||
|
|
defaultRuntimeSettings.modelBaseUrl,
|
|
model:
|
|
defaultModelProfile?.modelName ||
|
|
settings?.modelName ||
|
|
process.env.GOODBUDDY_MODEL_NAME?.trim() ||
|
|
process.env.GOODBUDDY_BIGTOKEN_MODEL?.trim() ||
|
|
defaultRuntimeSettings.modelName,
|
|
protocol:
|
|
defaultModelProfile?.protocol ??
|
|
settings?.modelProtocol ??
|
|
defaultRuntimeSettings.modelProtocol,
|
|
authentication: modelAuthentication,
|
|
requestHeaders: defaultModelProfile?.requestHeaders,
|
|
requestBody: defaultModelProfile?.requestBody,
|
|
supportsImageInput:
|
|
defaultModelProfile?.supportsImageInput ??
|
|
settings?.supportsImageInput ??
|
|
defaultRuntimeSettings.supportsImageInput,
|
|
maximumOutputTokens: defaultModelProfile?.maximumOutputTokens,
|
|
imageGenerationQuality:
|
|
defaultModelProfile?.imageGenerationQuality ??
|
|
settings?.imageGenerationQuality ??
|
|
defaultRuntimeSettings.imageGenerationQuality,
|
|
skillInstructions: capabilities.skillInstructions,
|
|
defaultWorkspace: workspace,
|
|
mcpServers: capabilities.mcpServers,
|
|
browserService: capabilities.browserService,
|
|
knowledgeGateway: capabilities.knowledgeGateway,
|
|
webSearchEnabled: capabilities.webSearchEnabled,
|
|
contextCompression: settings
|
|
? resolveContextCompression(settings, defaultModelProfile)
|
|
: undefined,
|
|
workspaceAccess: getWorkspaceAccess(),
|
|
directModelSubagentScheduler:
|
|
capabilities.directModelSubagentScheduler,
|
|
ripgrepExecutablePath: capabilities.bundledRuntimePaths?.ripgrep,
|
|
launchEnvironmentProvider:
|
|
capabilities.launchEnvironmentProvider
|
|
})
|
|
}
|
|
|
|
return new UnconfiguredAgentRuntime()
|
|
}
|