mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
config: add shared app config and repo for execution profile
- add shared AppConfig schema and export from shared index - introduce config repo that reads ~/.rowboat/config/config.json - register config repo in init and conditionally bind execution services - remove unused execution factory exports and file
This commit is contained in:
parent
1a82226ea6
commit
47b399a4f5
7 changed files with 74 additions and 37 deletions
|
|
@ -3,6 +3,7 @@ import type { IModelConfigRepo } from "../models/repo.js";
|
|||
import type { IMcpConfigRepo } from "../mcp/repo.js";
|
||||
import type { IAgentScheduleRepo } from "../agent-schedule/repo.js";
|
||||
import type { IAgentScheduleStateRepo } from "../agent-schedule/state-repo.js";
|
||||
import type { IConfigRepo } from "./repo.js";
|
||||
import { ensureSecurityConfig } from "./security.js";
|
||||
|
||||
/**
|
||||
|
|
@ -15,12 +16,14 @@ export async function initConfigs(): Promise<void> {
|
|||
const mcpConfigRepo = container.resolve<IMcpConfigRepo>("mcpConfigRepo");
|
||||
const agentScheduleRepo = container.resolve<IAgentScheduleRepo>("agentScheduleRepo");
|
||||
const agentScheduleStateRepo = container.resolve<IAgentScheduleStateRepo>("agentScheduleStateRepo");
|
||||
const configRepo = container.resolve<IConfigRepo>("configRepo");
|
||||
|
||||
await Promise.all([
|
||||
modelConfigRepo.ensureConfig(),
|
||||
mcpConfigRepo.ensureConfig(),
|
||||
agentScheduleRepo.ensureConfig(),
|
||||
agentScheduleStateRepo.ensureState(),
|
||||
configRepo.ensureConfig(),
|
||||
ensureSecurityConfig(),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
40
apps/x/packages/core/src/config/repo.ts
Normal file
40
apps/x/packages/core/src/config/repo.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import fs from "fs";
|
||||
import fsp from "fs/promises";
|
||||
import path from "path";
|
||||
import { AppConfig } from "@x/shared/dist/config.js";
|
||||
import { WorkDir } from "./config.js";
|
||||
import type z from "zod";
|
||||
|
||||
export interface IConfigRepo {
|
||||
ensureConfig(): Promise<void>;
|
||||
getConfigSync(): z.infer<typeof AppConfig>;
|
||||
setConfig(config: z.infer<typeof AppConfig>): Promise<void>;
|
||||
}
|
||||
|
||||
const defaultConfig: z.infer<typeof AppConfig> = {
|
||||
executionProfile: { mode: "local" },
|
||||
};
|
||||
|
||||
export class FSConfigRepo implements IConfigRepo {
|
||||
private readonly configPath = path.join(WorkDir, "config", "config.json");
|
||||
|
||||
async ensureConfig(): Promise<void> {
|
||||
try {
|
||||
await fsp.access(this.configPath);
|
||||
} catch {
|
||||
await fsp.writeFile(this.configPath, JSON.stringify(defaultConfig, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
getConfigSync(): z.infer<typeof AppConfig> {
|
||||
if (!fs.existsSync(this.configPath)) {
|
||||
fs.writeFileSync(this.configPath, JSON.stringify(defaultConfig, null, 2));
|
||||
}
|
||||
const raw = fs.readFileSync(this.configPath, "utf8");
|
||||
return AppConfig.parse(JSON.parse(raw));
|
||||
}
|
||||
|
||||
async setConfig(config: z.infer<typeof AppConfig>): Promise<void> {
|
||||
await fsp.writeFile(this.configPath, JSON.stringify(config, null, 2));
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import { FSGranolaConfigRepo, IGranolaConfigRepo } from "../knowledge/granola/re
|
|||
import { IAbortRegistry, InMemoryAbortRegistry } from "../runs/abort-registry.js";
|
||||
import { FSAgentScheduleRepo, IAgentScheduleRepo } from "../agent-schedule/repo.js";
|
||||
import { FSAgentScheduleStateRepo, IAgentScheduleStateRepo } from "../agent-schedule/state-repo.js";
|
||||
import { FSConfigRepo, IConfigRepo } from "../config/repo.js";
|
||||
import type { ILlmService } from "../execution/llm-service.js";
|
||||
import type { IGmailService } from "../execution/gmail-service.js";
|
||||
import type { ISttService } from "../execution/stt-service.js";
|
||||
|
|
@ -46,10 +47,24 @@ container.register({
|
|||
agentScheduleRepo: asClass<IAgentScheduleRepo>(FSAgentScheduleRepo).singleton(),
|
||||
agentScheduleStateRepo: asClass<IAgentScheduleStateRepo>(FSAgentScheduleStateRepo).singleton(),
|
||||
|
||||
llmService: asClass<ILlmService>(LocalLlmService).singleton(),
|
||||
gmailService: asClass<IGmailService>(LocalGmailService).singleton(),
|
||||
sttService: asClass<ISttService>(LocalSttService).singleton(),
|
||||
composioService: asClass<IComposioService>(LocalComposioService).singleton(),
|
||||
configRepo: asClass<IConfigRepo>(FSConfigRepo).singleton(),
|
||||
});
|
||||
|
||||
export default container;
|
||||
const appConfig = container.resolve<IConfigRepo>("configRepo").getConfigSync();
|
||||
|
||||
switch (appConfig.executionProfile.mode) {
|
||||
case "local":
|
||||
container.register({
|
||||
llmService: asClass<ILlmService>(LocalLlmService).singleton(),
|
||||
gmailService: asClass<IGmailService>(LocalGmailService).singleton(),
|
||||
sttService: asClass<ISttService>(LocalSttService).singleton(),
|
||||
composioService: asClass<IComposioService>(LocalComposioService).singleton(),
|
||||
});
|
||||
break;
|
||||
case "cloud":
|
||||
throw new Error("Cloud execution profile not supported yet. Configure {\"executionProfile\":{\"mode\":\"local\"}}.");
|
||||
default:
|
||||
throw new Error(`Unsupported execution profile mode: ${(appConfig.executionProfile as { mode: string }).mode}`);
|
||||
}
|
||||
|
||||
export default container;
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
import { ExecutionProfile } from "@x/shared/dist/execution-profile.js";
|
||||
import { ILlmService } from "./llm-service.js";
|
||||
import { IGmailService } from "./gmail-service.js";
|
||||
import { ISttService } from "./stt-service.js";
|
||||
import { IComposioService } from "./composio-service.js";
|
||||
import { LocalLlmService } from "./local/local-llm-service.js";
|
||||
import { LocalGmailService } from "./local/local-gmail-service.js";
|
||||
import { LocalSttService } from "./local/local-stt-service.js";
|
||||
import { LocalComposioService } from "./local/local-composio-service.js";
|
||||
|
||||
export interface ExecutionServices {
|
||||
llm: ILlmService;
|
||||
gmail: IGmailService;
|
||||
stt: ISttService;
|
||||
composio: IComposioService;
|
||||
}
|
||||
|
||||
export function createServices(profile: ExecutionProfile): ExecutionServices {
|
||||
switch (profile.mode) {
|
||||
case "local":
|
||||
return {
|
||||
llm: new LocalLlmService(),
|
||||
gmail: new LocalGmailService(),
|
||||
stt: new LocalSttService(),
|
||||
composio: new LocalComposioService(),
|
||||
};
|
||||
default:
|
||||
throw new Error(`Unsupported execution profile mode: ${(profile as { mode: string }).mode}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@ export type { ILlmService } from "./llm-service.js";
|
|||
export type { IGmailService } from "./gmail-service.js";
|
||||
export type { ISttService } from "./stt-service.js";
|
||||
export type { IComposioService } from "./composio-service.js";
|
||||
export { createServices } from "./factory.js";
|
||||
export type { ExecutionServices } from "./factory.js";
|
||||
|
||||
// Local implementations
|
||||
export { LocalLlmService } from "./local/local-llm-service.js";
|
||||
|
|
|
|||
10
apps/x/packages/shared/src/config.ts
Normal file
10
apps/x/packages/shared/src/config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { z } from "zod";
|
||||
import { ExecutionProfile } from "./execution-profile.js";
|
||||
|
||||
export const AppConfig = z
|
||||
.object({
|
||||
executionProfile: ExecutionProfile,
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
export type AppConfig = z.infer<typeof AppConfig>;
|
||||
|
|
@ -8,4 +8,5 @@ export * as agentSchedule from './agent-schedule.js';
|
|||
export * as agentScheduleState from './agent-schedule-state.js';
|
||||
export * as serviceEvents from './service-events.js';
|
||||
export * as executionProfile from './execution-profile.js';
|
||||
export * as config from './config.js';
|
||||
export { PrefixLogger };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue