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 { IMcpConfigRepo } from "../mcp/repo.js";
|
||||||
import type { IAgentScheduleRepo } from "../agent-schedule/repo.js";
|
import type { IAgentScheduleRepo } from "../agent-schedule/repo.js";
|
||||||
import type { IAgentScheduleStateRepo } from "../agent-schedule/state-repo.js";
|
import type { IAgentScheduleStateRepo } from "../agent-schedule/state-repo.js";
|
||||||
|
import type { IConfigRepo } from "./repo.js";
|
||||||
import { ensureSecurityConfig } from "./security.js";
|
import { ensureSecurityConfig } from "./security.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,12 +16,14 @@ export async function initConfigs(): Promise<void> {
|
||||||
const mcpConfigRepo = container.resolve<IMcpConfigRepo>("mcpConfigRepo");
|
const mcpConfigRepo = container.resolve<IMcpConfigRepo>("mcpConfigRepo");
|
||||||
const agentScheduleRepo = container.resolve<IAgentScheduleRepo>("agentScheduleRepo");
|
const agentScheduleRepo = container.resolve<IAgentScheduleRepo>("agentScheduleRepo");
|
||||||
const agentScheduleStateRepo = container.resolve<IAgentScheduleStateRepo>("agentScheduleStateRepo");
|
const agentScheduleStateRepo = container.resolve<IAgentScheduleStateRepo>("agentScheduleStateRepo");
|
||||||
|
const configRepo = container.resolve<IConfigRepo>("configRepo");
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
modelConfigRepo.ensureConfig(),
|
modelConfigRepo.ensureConfig(),
|
||||||
mcpConfigRepo.ensureConfig(),
|
mcpConfigRepo.ensureConfig(),
|
||||||
agentScheduleRepo.ensureConfig(),
|
agentScheduleRepo.ensureConfig(),
|
||||||
agentScheduleStateRepo.ensureState(),
|
agentScheduleStateRepo.ensureState(),
|
||||||
|
configRepo.ensureConfig(),
|
||||||
ensureSecurityConfig(),
|
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 { IAbortRegistry, InMemoryAbortRegistry } from "../runs/abort-registry.js";
|
||||||
import { FSAgentScheduleRepo, IAgentScheduleRepo } from "../agent-schedule/repo.js";
|
import { FSAgentScheduleRepo, IAgentScheduleRepo } from "../agent-schedule/repo.js";
|
||||||
import { FSAgentScheduleStateRepo, IAgentScheduleStateRepo } from "../agent-schedule/state-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 { ILlmService } from "../execution/llm-service.js";
|
||||||
import type { IGmailService } from "../execution/gmail-service.js";
|
import type { IGmailService } from "../execution/gmail-service.js";
|
||||||
import type { ISttService } from "../execution/stt-service.js";
|
import type { ISttService } from "../execution/stt-service.js";
|
||||||
|
|
@ -46,10 +47,24 @@ container.register({
|
||||||
agentScheduleRepo: asClass<IAgentScheduleRepo>(FSAgentScheduleRepo).singleton(),
|
agentScheduleRepo: asClass<IAgentScheduleRepo>(FSAgentScheduleRepo).singleton(),
|
||||||
agentScheduleStateRepo: asClass<IAgentScheduleStateRepo>(FSAgentScheduleStateRepo).singleton(),
|
agentScheduleStateRepo: asClass<IAgentScheduleStateRepo>(FSAgentScheduleStateRepo).singleton(),
|
||||||
|
|
||||||
llmService: asClass<ILlmService>(LocalLlmService).singleton(),
|
configRepo: asClass<IConfigRepo>(FSConfigRepo).singleton(),
|
||||||
gmailService: asClass<IGmailService>(LocalGmailService).singleton(),
|
|
||||||
sttService: asClass<ISttService>(LocalSttService).singleton(),
|
|
||||||
composioService: asClass<IComposioService>(LocalComposioService).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 { IGmailService } from "./gmail-service.js";
|
||||||
export type { ISttService } from "./stt-service.js";
|
export type { ISttService } from "./stt-service.js";
|
||||||
export type { IComposioService } from "./composio-service.js";
|
export type { IComposioService } from "./composio-service.js";
|
||||||
export { createServices } from "./factory.js";
|
|
||||||
export type { ExecutionServices } from "./factory.js";
|
|
||||||
|
|
||||||
// Local implementations
|
// Local implementations
|
||||||
export { LocalLlmService } from "./local/local-llm-service.js";
|
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 agentScheduleState from './agent-schedule-state.js';
|
||||||
export * as serviceEvents from './service-events.js';
|
export * as serviceEvents from './service-events.js';
|
||||||
export * as executionProfile from './execution-profile.js';
|
export * as executionProfile from './execution-profile.js';
|
||||||
|
export * as config from './config.js';
|
||||||
export { PrefixLogger };
|
export { PrefixLogger };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue