kimi-code / packages /agent-core-v2 /src /app /feature /featureManagerService.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
f0634fb verified
Raw History Blame Contribute Delete
3.44 kB
import type { CollectionView } from '#/_base/di/collection';
import { Emitter, type Event } from '#/_base/event';
import type {
FiberHandle,
FiberProvideOptions,
RecipeStatics,
ServiceClassRecipe,
ServiceRecipe,
} from '#/_base/di/fiber';
import { LifecycleScope } from '#/app/scopes';
import { ScopeActivation, registerScopedService } from '#/_base/di/scope';
import { isServiceIdentifier, type ServiceIdentifier } from '#/_base/di/instantiation';
import { Service } from '#/_base/di/service';
import {
IFeatureManager,
type ManagedUnitInfo,
} from './featureManager';
import {
FeatureServiceContribution,
type ContributedFeatureService,
} from './featureServiceContribution';
export class FeatureManagerService extends Service implements IFeatureManager {
declare readonly _serviceBrand: undefined;
private readonly _units = new Map<
string,
{ handle: FiberHandle; meta: Record<string, unknown> }
>();
private readonly _onDidChangeUnits = new Emitter<void>();
readonly onDidChangeUnits: Event<void> = this._onDidChangeUnits.event;
constructor(
@FeatureServiceContribution
private readonly _contributedServices: CollectionView<ContributedFeatureService>,
) {
super();
this._register(this._onDidChangeUnits);
}
provideUnit(recipe: ServiceRecipe, opts?: FiberProvideOptions): FiberHandle;
provideUnit<T>(
id: ServiceIdentifier<T>,
recipe: ServiceClassRecipe,
opts?: FiberProvideOptions,
): FiberHandle<T>;
provideUnit(
first: ServiceRecipe | ServiceIdentifier<any>,
second?: any,
third?: FiberProvideOptions,
): FiberHandle {
const handle = isServiceIdentifier(first)
? this.provide(first, second as ServiceClassRecipe, third)
: this.provide(first as ServiceRecipe, second as FiberProvideOptions | undefined);
const name = handle.name;
const previous = this._units.get(name);
if (previous !== undefined && previous.handle !== handle) {
void previous.handle.dispose();
}
const statics = (isServiceIdentifier(first) ? second : first) as RecipeStatics;
this._units.set(name, { handle, meta: Object.freeze({ ...statics.meta }) });
this._onDidChangeUnits.fire();
return handle;
}
async unprovideUnit(name: string): Promise<void> {
const entry = this._units.get(name);
if (entry === undefined) {
return;
}
this._units.delete(name);
try {
await entry.handle.dispose();
} finally {
this._onDidChangeUnits.fire();
}
}
async updateUnit(name: string, config?: unknown): Promise<void> {
const entry = this._units.get(name);
if (entry === undefined) {
throw new Error(`feature unit '${name}' is not managed by this FeatureManager`);
}
await entry.handle.update(config);
this._onDidChangeUnits.fire();
}
units(): readonly ManagedUnitInfo[] {
const infos: ManagedUnitInfo[] = [];
for (const [name, entry] of this._units) {
let uid: number | undefined;
try {
uid = entry.handle.uid;
} catch {
uid = undefined;
}
infos.push({ name, state: entry.handle.state, uid, meta: entry.meta });
}
return infos;
}
contributedServices(): readonly ContributedFeatureService[] {
return this._contributedServices.items;
}
}
registerScopedService(
LifecycleScope.App,
IFeatureManager,
FeatureManagerService,
ScopeActivation.OnScopeCreated,
'feature',
);