perf: speed up model/agent readiness on the initial draft

Load startup config under the owning project's directory key (resolving from a
worktree directory when needed) so the auto-opened draft, which activates the
project, finds a ready providers/agents snapshot instead of triggering a second
load. Also dedupe app.agents: listAgents now takes the directory directly and
shares an in-flight request, so the config store and agents store no longer
issue duplicate agent fetches at startup.
This commit is contained in:
Bohdan Triapitsyn
2026-06-14 22:04:32 +03:00
parent 9111611bdc
commit 296177357b
4 changed files with 56 additions and 12 deletions
+28 -7
View File
@@ -229,6 +229,7 @@ class OpencodeService {
private currentDirectory: string | undefined = undefined;
private directoryContextQueue: Promise<void> = Promise.resolve();
private listDirectoryInFlight: Map<string, Promise<FilesystemEntry[]>> = new Map();
private listAgentsInFlight: Map<string, Promise<Agent[]>> = new Map();
private listDirectoryCache: Map<string, { entries: FilesystemEntry[]; expiresAt: number }> = new Map();
constructor(baseUrl: string = DEFAULT_BASE_URL) {
@@ -1294,14 +1295,34 @@ class OpencodeService {
* useAgentsStore) can observe failure and retry; silently returning an
* empty list would defeat retries and clear the cached agent list.
*/
async listAgents(): Promise<Agent[]> {
const response = await this.client.app.agents(
this.currentDirectory ? { directory: this.currentDirectory } : undefined
);
if (response.error) {
throw new Error(`app.agents failed: ${formatSdkError(response.error)}`);
async listAgents(directory?: string | null): Promise<Agent[]> {
// Pass the directory explicitly so we don't depend on (and serialize behind)
// withDirectory's shared context queue. Concurrent callers for the same
// directory (e.g. config store + agents store at startup) share one request.
const effectiveDirectory = this.normalizeCandidatePath(directory) ?? directory ?? this.currentDirectory ?? undefined;
const key = effectiveDirectory ?? '';
const existing = this.listAgentsInFlight.get(key);
if (existing) {
return existing;
}
const request = (async () => {
const response = await this.client.app.agents(
effectiveDirectory ? { directory: effectiveDirectory } : undefined
);
if (response.error) {
throw new Error(`app.agents failed: ${formatSdkError(response.error)}`);
}
return response.data || [];
})();
this.listAgentsInFlight.set(key, request);
try {
return await request;
} finally {
this.listAgentsInFlight.delete(key);
}
return response.data || [];
}
// SSE infrastructure removed — EventPipeline in sync/event-pipeline.ts handles