refactor(sdk): add runtime bridge seam for query dispatch

This commit is contained in:
Tom Boucher
2026-05-05 19:21:31 -04:00
parent a7ce59f0fc
commit 98dd9e4afb
3 changed files with 83 additions and 17 deletions

View File

@@ -15,13 +15,12 @@ import type { InitNewProjectInfo, PhaseOpInfo, PhasePlanIndex, RoadmapAnalysis }
import type { GSDEventStream } from './event-stream.js';
import { toToolsErrorFromUnknown } from './query-tools-error-factory.js';
import { GSDToolsError } from './gsd-tools-error.js';
import { resolveQueryCommand, type QueryCommandResolution } from './query/query-command-resolution-strategy.js';
import { QueryExecutionPolicy } from './query-execution-policy.js';
import { QueryNativeHotpathAdapter } from './query-native-hotpath-adapter.js';
import type { QueryCommandResolution } from './query/query-command-resolution-strategy.js';
import { resolveGsdToolsPath } from './query-gsd-tools-path.js';
import { createGSDToolsRuntime } from './query-gsd-tools-runtime.js';
import { QueryCommandExecutor } from './query-command-executor.js';
import { QueryHotpathMethods } from './query-hotpath-methods.js';
import { QueryRuntimeBridge } from './query-runtime-bridge.js';
export { GSDToolsError } from './gsd-tools-error.js';
@@ -35,10 +34,8 @@ export class GSDTools {
private readonly gsdToolsPath: string;
private readonly timeoutMs: number;
private readonly workstream?: string;
private readonly registry: ReturnType<typeof createGSDToolsRuntime>['registry'];
private readonly bridge: QueryRuntimeBridge;
private readonly preferNativeQuery: boolean;
private readonly executionPolicy: QueryExecutionPolicy;
private readonly nativeHotpathAdapter: QueryNativeHotpathAdapter;
private readonly commandExecutor: QueryCommandExecutor;
private readonly hotpathMethods: QueryHotpathMethods;
@@ -76,12 +73,10 @@ export class GSDTools {
execRawFallback: (legacyCommand, legacyArgs) => this.execRaw(legacyCommand, legacyArgs),
});
this.registry = runtime.registry;
this.executionPolicy = runtime.executionPolicy;
this.nativeHotpathAdapter = runtime.nativeHotpathAdapter;
this.bridge = runtime.bridge;
this.commandExecutor = new QueryCommandExecutor({
nativeMatch: (command, args) => this.nativeMatch(command, args),
execute: async (input) => this.executionPolicy.execute({
execute: async (input) => this.bridge.execute({
legacyCommand: input.legacyCommand,
legacyArgs: input.legacyArgs,
registryCommand: input.registryCommand,
@@ -89,7 +84,6 @@ export class GSDTools {
mode: input.mode,
projectDir: this.projectDir,
workstream: this.workstream,
preferNativeQuery: this.shouldUseNativeQuery(),
}),
});
@@ -104,7 +98,7 @@ export class GSDTools {
}
private nativeMatch(command: string, args: string[]): QueryCommandResolution | null {
return resolveQueryCommand(command, args, this.registry);
return this.bridge.resolve(command, args);
}
private async dispatchNativeHotpath(
@@ -115,7 +109,7 @@ export class GSDTools {
mode: 'json' | 'raw',
): Promise<unknown> {
return this.executeWithToolsError(legacyCommand, legacyArgs, () =>
this.nativeHotpathAdapter.dispatch(
this.bridge.dispatchHotpath(
legacyCommand,
legacyArgs,
registryCommand,

View File

@@ -7,11 +7,10 @@ import { QueryNativeDirectAdapter } from './query-native-direct-adapter.js';
import { QueryNativeHotpathAdapter } from './query-native-hotpath-adapter.js';
import { formatQueryRawOutput } from './query-raw-output-projection.js';
import { createQueryNativeErrorFactory, createQueryToolsErrorFactory } from './query-tools-error-factory.js';
import { QueryRuntimeBridge } from './query-runtime-bridge.js';
export interface GSDToolsRuntime {
registry: ReturnType<typeof createRegistry>;
executionPolicy: QueryExecutionPolicy;
nativeHotpathAdapter: QueryNativeHotpathAdapter;
bridge: QueryRuntimeBridge;
}
export function createGSDToolsRuntime(opts: {
@@ -65,5 +64,12 @@ export function createGSDToolsRuntime(opts: {
opts.execRawFallback,
);
return { registry, executionPolicy, nativeHotpathAdapter };
const bridge = new QueryRuntimeBridge(
registry,
executionPolicy,
nativeHotpathAdapter,
opts.shouldUseNativeQuery,
);
return { bridge };
}

View File

@@ -0,0 +1,66 @@
import type { QueryRegistry } from './query/registry.js';
import type { TransportMode } from './gsd-transport-policy.js';
import type { QueryCommandResolution } from './query/query-command-resolution-strategy.js';
import { resolveQueryCommand } from './query/query-command-resolution-strategy.js';
import { QueryExecutionPolicy } from './query-execution-policy.js';
import { QueryNativeHotpathAdapter } from './query-native-hotpath-adapter.js';
export interface RuntimeBridgeExecuteInput {
legacyCommand: string;
legacyArgs: string[];
registryCommand: string;
registryArgs: string[];
mode: TransportMode;
projectDir: string;
workstream?: string;
}
/**
* SDK Runtime Bridge Module.
* Owns dispatch routing through the execution policy seam and hotpath/native fallback behavior.
*/
export class QueryRuntimeBridge {
constructor(
private readonly registry: QueryRegistry,
private readonly executionPolicy: QueryExecutionPolicy,
private readonly nativeHotpathAdapter: QueryNativeHotpathAdapter,
private readonly shouldUseNativeQuery: () => boolean,
) {}
getRegistry(): QueryRegistry {
return this.registry;
}
resolve(command: string, args: string[]): QueryCommandResolution | null {
return resolveQueryCommand(command, args, this.registry);
}
async execute(input: RuntimeBridgeExecuteInput): Promise<unknown> {
return this.executionPolicy.execute({
legacyCommand: input.legacyCommand,
legacyArgs: input.legacyArgs,
registryCommand: input.registryCommand,
registryArgs: input.registryArgs,
mode: input.mode,
projectDir: input.projectDir,
workstream: input.workstream,
preferNativeQuery: this.shouldUseNativeQuery(),
});
}
async dispatchHotpath(
legacyCommand: string,
legacyArgs: string[],
registryCommand: string,
registryArgs: string[],
mode: TransportMode,
): Promise<unknown> {
return this.nativeHotpathAdapter.dispatch(
legacyCommand,
legacyArgs,
registryCommand,
registryArgs,
mode,
);
}
}