chore: prepare GoodBuddy 0.8.2
Cross-platform packages / Validate source (push) Waiting to run
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, macos, macos-15-intel) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / Publish GitHub Release (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions
Cross-platform packages / Validate source (push) Waiting to run
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, macos, macos-15-intel) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / Publish GitHub Release (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import {
|
||||
agentRuntimeSelectionKey,
|
||||
type AgentRuntimeSelection
|
||||
} from '../../shared/runtime-selection-contracts'
|
||||
import type { AgentRuntimeStatus } from '../../shared/contracts'
|
||||
import type { AgentRuntime } from './runtime'
|
||||
import { AgentRuntimeController } from './runtime-controller'
|
||||
|
||||
export type SelectedRuntimeResolver = {
|
||||
getRuntime(selection: AgentRuntimeSelection): Promise<AgentRuntime>
|
||||
getStatus(
|
||||
selection: AgentRuntimeSelection
|
||||
): Promise<AgentRuntimeStatus>
|
||||
testStatus(
|
||||
selection: AgentRuntimeSelection
|
||||
): Promise<AgentRuntimeStatus>
|
||||
releaseConversation(conversationId: string): Promise<void>
|
||||
}
|
||||
|
||||
export class SelectedRuntimeManager implements SelectedRuntimeResolver {
|
||||
private readonly entries = new Map<
|
||||
string,
|
||||
Promise<AgentRuntimeController>
|
||||
>()
|
||||
private disposed = false
|
||||
private readonly retiring = new Set<Promise<void>>()
|
||||
private readonly tests = new Set<Promise<AgentRuntimeStatus>>()
|
||||
|
||||
constructor(
|
||||
private readonly createRuntime: (
|
||||
selection: AgentRuntimeSelection
|
||||
) => Promise<AgentRuntime>
|
||||
) {}
|
||||
|
||||
async getRuntime(
|
||||
selection: AgentRuntimeSelection
|
||||
): Promise<AgentRuntime> {
|
||||
if (this.disposed) {
|
||||
throw new Error('Agent Runtime 正在关闭')
|
||||
}
|
||||
const key = agentRuntimeSelectionKey(selection)
|
||||
const existing = this.entries.get(key)
|
||||
if (existing) {
|
||||
return existing
|
||||
}
|
||||
const operation = this.createRuntime(selection).then(async (runtime) => {
|
||||
if (this.disposed || this.entries.get(key) !== operation) {
|
||||
await runtime.dispose()
|
||||
throw new Error('Runtime 设置已更改,请重新选择')
|
||||
}
|
||||
return new AgentRuntimeController(runtime)
|
||||
})
|
||||
this.entries.set(key, operation)
|
||||
try {
|
||||
return await operation
|
||||
} catch (error) {
|
||||
if (this.entries.get(key) === operation) {
|
||||
this.entries.delete(key)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async getStatus(
|
||||
selection: AgentRuntimeSelection
|
||||
): Promise<AgentRuntimeStatus> {
|
||||
return (await this.getRuntime(selection)).getStatus()
|
||||
}
|
||||
|
||||
async testStatus(
|
||||
selection: AgentRuntimeSelection
|
||||
): Promise<AgentRuntimeStatus> {
|
||||
if (this.disposed) {
|
||||
throw new Error('Agent Runtime 正在关闭')
|
||||
}
|
||||
const operation = this.runConnectionTest(selection)
|
||||
this.tests.add(operation)
|
||||
try {
|
||||
return await operation
|
||||
} finally {
|
||||
this.tests.delete(operation)
|
||||
}
|
||||
}
|
||||
|
||||
async releaseConversation(conversationId: string): Promise<void> {
|
||||
const controllers = await Promise.allSettled([
|
||||
...this.entries.values()
|
||||
])
|
||||
await Promise.allSettled(
|
||||
controllers.flatMap((result) =>
|
||||
result.status === 'fulfilled'
|
||||
? [result.value.releaseConversation(conversationId)]
|
||||
: []
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
async reset(): Promise<void> {
|
||||
const entries = [...this.entries.values()]
|
||||
this.entries.clear()
|
||||
await Promise.allSettled(
|
||||
entries.map((entry) => this.startRetiring(entry, false))
|
||||
)
|
||||
}
|
||||
|
||||
async dispose(): Promise<void> {
|
||||
this.disposed = true
|
||||
const entries = [...this.entries.values()]
|
||||
this.entries.clear()
|
||||
await Promise.allSettled(
|
||||
entries.map((entry) => this.startRetiring(entry, true))
|
||||
)
|
||||
await Promise.allSettled([...this.tests])
|
||||
await Promise.allSettled([...this.retiring])
|
||||
}
|
||||
|
||||
private async runConnectionTest(
|
||||
selection: AgentRuntimeSelection
|
||||
): Promise<AgentRuntimeStatus> {
|
||||
const runtime = await this.createRuntime(selection)
|
||||
try {
|
||||
if (this.disposed) {
|
||||
throw new Error('Agent Runtime 正在关闭')
|
||||
}
|
||||
return (
|
||||
(await runtime.testConnection?.()) ??
|
||||
(await runtime.getStatus())
|
||||
)
|
||||
} finally {
|
||||
await runtime.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
private async startRetiring(
|
||||
entry: Promise<AgentRuntimeController>,
|
||||
waitForDisposal: boolean
|
||||
): Promise<void> {
|
||||
try {
|
||||
const controller = await entry
|
||||
const disposal = controller.dispose()
|
||||
this.retiring.add(disposal)
|
||||
void disposal.then(
|
||||
() => this.retiring.delete(disposal),
|
||||
() => this.retiring.delete(disposal)
|
||||
)
|
||||
if (waitForDisposal) {
|
||||
await disposal
|
||||
}
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user