96 lines
2.8 KiB
TypeScript
96 lines
2.8 KiB
TypeScript
import { HttpModule } from "@nestjs/axios";
|
|
import { Logger, Module, OnModuleInit } from "@nestjs/common";
|
|
import type { AgentProviderConfig } from "@prisma/client";
|
|
import { PrismaModule } from "../../prisma/prisma.module";
|
|
import { PrismaService } from "../../prisma/prisma.service";
|
|
import { EncryptionService } from "../../security/encryption.service";
|
|
import { AgentProviderRegistry } from "../agents/agent-provider.registry";
|
|
import { AgentsModule } from "../agents/agents.module";
|
|
import { OpenClawProviderFactory } from "./openclaw/openclaw.provider-factory";
|
|
import { OpenClawSseBridge } from "./openclaw/openclaw-sse.bridge";
|
|
|
|
const OPENCLAW_PROVIDER_TYPE = "openclaw";
|
|
|
|
@Module({
|
|
imports: [
|
|
AgentsModule,
|
|
PrismaModule,
|
|
HttpModule.register({
|
|
timeout: 10000,
|
|
maxRedirects: 5,
|
|
}),
|
|
],
|
|
providers: [EncryptionService, OpenClawSseBridge, OpenClawProviderFactory],
|
|
})
|
|
export class ProvidersModule implements OnModuleInit {
|
|
private readonly logger = new Logger(ProvidersModule.name);
|
|
|
|
constructor(
|
|
private readonly prisma: PrismaService,
|
|
private readonly registry: AgentProviderRegistry,
|
|
private readonly openClawProviderFactory: OpenClawProviderFactory
|
|
) {}
|
|
|
|
async onModuleInit(): Promise<void> {
|
|
const configs = await this.prisma.agentProviderConfig.findMany({
|
|
where: {
|
|
provider: OPENCLAW_PROVIDER_TYPE,
|
|
isActive: true,
|
|
},
|
|
orderBy: [{ createdAt: "asc" }, { id: "asc" }],
|
|
});
|
|
|
|
for (const config of configs) {
|
|
await this.registerProvider(config);
|
|
}
|
|
}
|
|
|
|
private async registerProvider(config: AgentProviderConfig): Promise<void> {
|
|
const provider = this.openClawProviderFactory.createProvider(config);
|
|
|
|
try {
|
|
provider.validateBaseUrl();
|
|
} catch (error) {
|
|
this.logger.warn(
|
|
`Skipping OpenClaw provider ${config.name}: invalid configuration (${this.toErrorMessage(error)})`
|
|
);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
provider.validateToken();
|
|
} catch (error) {
|
|
this.logger.error(
|
|
`Skipping OpenClaw provider ${config.name}: token decryption failed (${this.toErrorMessage(error)})`
|
|
);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const available = await provider.isAvailable();
|
|
if (!available) {
|
|
this.logger.warn(
|
|
`Skipping OpenClaw provider ${config.name}: gateway ${config.gatewayUrl} is unreachable`
|
|
);
|
|
return;
|
|
}
|
|
} catch (error) {
|
|
this.logger.warn(
|
|
`Skipping OpenClaw provider ${config.name}: gateway ${config.gatewayUrl} is unreachable (${this.toErrorMessage(error)})`
|
|
);
|
|
return;
|
|
}
|
|
|
|
this.registry.registerProvider(provider);
|
|
this.logger.log(`Registered OpenClaw provider ${provider.providerId}`);
|
|
}
|
|
|
|
private toErrorMessage(error: unknown): string {
|
|
if (error instanceof Error) {
|
|
return error.message;
|
|
}
|
|
|
|
return String(error);
|
|
}
|
|
}
|