Skip to content

Commit 458001b

Browse files
sakirrSiddhesh2377
authored andcommitted
feat(web-sdk): add typed provider registry to ExtensionPoint
registerProvider<T> and getProvider<T> replace the globalThis key-value pattern that LlamaCpp and ONNX packages used to share singletons. The registry throws early if a provider hasn't been registered, making missing setup failures obvious instead of cryptic.
1 parent 1d129af commit 458001b

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

sdk/runanywhere-web/packages/core/src/Infrastructure/ExtensionPoint.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*/
2222

2323
import { SDKLogger } from '../Foundation/SDKLogger';
24+
import type { ProviderCapability, ProviderMap } from './ProviderTypes';
2425

2526
const logger = new SDKLogger('ExtensionPoint');
2627

@@ -150,6 +151,70 @@ class ExtensionPointImpl {
150151
}
151152
}
152153

154+
// -------------------------------------------------------------------------
155+
// Provider Registry — typed cross-package provider access (issue #371)
156+
// -------------------------------------------------------------------------
157+
158+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
159+
private providers: Map<ProviderCapability, any> = new Map();
160+
161+
/**
162+
* Register a typed provider implementation for a capability.
163+
*
164+
* Backend packages call this during their registration phase:
165+
* ```ts
166+
* ExtensionPoint.registerProvider('llm', TextGeneration);
167+
* ExtensionPoint.registerProvider('stt', STT);
168+
* ```
169+
*/
170+
registerProvider<K extends ProviderCapability>(
171+
capability: K,
172+
implementation: ProviderMap[K],
173+
): void {
174+
if (this.providers.has(capability)) {
175+
logger.debug(`Provider '${capability}' already registered, overwriting`);
176+
}
177+
this.providers.set(capability, implementation);
178+
logger.debug(`Provider '${capability}' registered`);
179+
}
180+
181+
/**
182+
* Retrieve a registered provider by capability.
183+
* Returns undefined if no provider is registered for the given capability.
184+
*/
185+
getProvider<K extends ProviderCapability>(
186+
capability: K,
187+
): ProviderMap[K] | undefined {
188+
return this.providers.get(capability) as ProviderMap[K] | undefined;
189+
}
190+
191+
/**
192+
* Retrieve a registered provider or throw a descriptive error.
193+
* Use in code that requires a specific backend to be registered.
194+
*/
195+
requireProvider<K extends ProviderCapability>(
196+
capability: K,
197+
packageHint?: string,
198+
): ProviderMap[K] {
199+
const provider = this.providers.get(capability);
200+
if (!provider) {
201+
const hint = packageHint ?? (
202+
capability === 'stt' || capability === 'tts'
203+
? '@runanywhere/web-onnx'
204+
: '@runanywhere/web-llamacpp'
205+
);
206+
throw new Error(
207+
`Provider '${capability}' not available. Install and register the ${hint} package.`,
208+
);
209+
}
210+
return provider as ProviderMap[K];
211+
}
212+
213+
/** Remove a registered provider. */
214+
removeProvider(capability: ProviderCapability): void {
215+
this.providers.delete(capability);
216+
}
217+
153218
// -------------------------------------------------------------------------
154219
// Service Registry — typed singleton access for cross-package communication
155220
// -------------------------------------------------------------------------
@@ -218,6 +283,7 @@ class ExtensionPointImpl {
218283
this.backends.clear();
219284
this.capabilityMap.clear();
220285
this.services.clear();
286+
this.providers.clear();
221287
}
222288
}
223289

sdk/runanywhere-web/packages/core/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ export { ExtensionRegistry } from './Infrastructure/ExtensionRegistry';
7070
export type { SDKExtension } from './Infrastructure/ExtensionRegistry';
7171
export { ExtensionPoint, BackendCapability, ServiceKey } from './Infrastructure/ExtensionPoint';
7272
export type { BackendExtension } from './Infrastructure/ExtensionPoint';
73+
export type {
74+
ProviderCapability,
75+
ProviderMap,
76+
LLMProvider,
77+
STTProvider,
78+
TTSProvider,
79+
} from './Infrastructure/ProviderTypes';
7380
export type { ModelLoadContext, LLMModelLoader, STTModelLoader, TTSModelLoader, VADModelLoader } from './Infrastructure/ModelLoaderTypes';
7481
export { extractTarGz } from './Infrastructure/ArchiveUtility';
7582
export { LocalFileStorage } from './Infrastructure/LocalFileStorage';

0 commit comments

Comments
 (0)