Refactor runtime around isolated bot instances
This commit is contained in:
+29
-35
@@ -1,51 +1,45 @@
|
||||
import crypto from "node:crypto";
|
||||
import type { AppConfig, RoleConfig } from "../config.js";
|
||||
import type { AppConfig, BotConfig } from "../config.js";
|
||||
import { SkillLoader, type LoadedSkill } from "./skill-loader.js";
|
||||
|
||||
export interface ResolvedRole extends RoleConfig {
|
||||
const BOOTSTRAP_SCHEMA_VERSION = 1;
|
||||
|
||||
export interface ResolvedBot extends BotConfig {
|
||||
loadedSkills: LoadedSkill[];
|
||||
fingerprint: string;
|
||||
bootstrap: string;
|
||||
}
|
||||
|
||||
export class RoleRegistry {
|
||||
private readonly roles = new Map<string, ResolvedRole>();
|
||||
export class BotProfileResolver {
|
||||
readonly bot: ResolvedBot;
|
||||
|
||||
constructor(private readonly config: AppConfig) {
|
||||
const loader = new SkillLoader(config.skills);
|
||||
for (const role of config.roles) {
|
||||
const loadedSkills = role.skills.map((id) => loader.load(id));
|
||||
const fingerprint = crypto.createHash("sha256").update(JSON.stringify({
|
||||
id: role.id,
|
||||
backend: role.backend,
|
||||
workspace: role.workspace,
|
||||
persona: role.persona,
|
||||
policy: role.policy,
|
||||
skills: loadedSkills.map(({ id, file, hash }) => ({ id, file, hash }))
|
||||
})).digest("hex");
|
||||
this.roles.set(role.id, { ...role, loadedSkills, fingerprint, bootstrap: buildBootstrap(role, loadedSkills) });
|
||||
}
|
||||
constructor(config: AppConfig) {
|
||||
const loadedSkills = config.bot.skills.map((skill) => new SkillLoader(config.bot.skills).load(skill.id));
|
||||
const fingerprint = crypto.createHash("sha256").update(JSON.stringify({
|
||||
bootstrapSchemaVersion: BOOTSTRAP_SCHEMA_VERSION,
|
||||
id: config.bot.id,
|
||||
workspace: config.bot.workspace,
|
||||
persona: config.bot.persona,
|
||||
agent: config.bot.agent,
|
||||
permissions: config.bot.permissions,
|
||||
skills: loadedSkills.map(({ id, file, hash }) => ({ id, file, hash }))
|
||||
})).digest("hex");
|
||||
this.bot = {
|
||||
...config.bot,
|
||||
loadedSkills,
|
||||
fingerprint,
|
||||
bootstrap: buildBootstrap(config.bot, loadedSkills)
|
||||
};
|
||||
}
|
||||
|
||||
get(id?: string): ResolvedRole {
|
||||
const roleId = id || this.config.defaultRole;
|
||||
const role = this.roles.get(roleId);
|
||||
if (!role) throw new Error(`Unknown role: ${roleId}`);
|
||||
return role;
|
||||
}
|
||||
|
||||
has(id: string): boolean { return this.roles.has(id); }
|
||||
list(): string[] { return [...this.roles.keys()].sort(); }
|
||||
defaultId(): string { return this.config.defaultRole; }
|
||||
}
|
||||
|
||||
function buildBootstrap(role: RoleConfig, skills: LoadedSkill[]): string {
|
||||
function buildBootstrap(bot: BotConfig, skills: LoadedSkill[]): string {
|
||||
return [
|
||||
"Initialize this ACP session with the following role. Treat these instructions as persistent context. Reply only with READY.",
|
||||
`Role: ${role.id}`,
|
||||
`Workspace: ${role.workspace}`,
|
||||
role.persona ? `Persona:\n${role.persona}` : "Persona: general coding assistant",
|
||||
`Permission policy enforced by the ACP client: ${JSON.stringify(role.policy)}`,
|
||||
`Initialize this ACP session with gori-agent bootstrap schema v${BOOTSTRAP_SCHEMA_VERSION}. Treat these instructions as persistent context. Reply only with READY.`,
|
||||
`Bot: ${bot.id}`,
|
||||
`Workspace: ${bot.workspace}`,
|
||||
bot.persona ? `Persona:\n${bot.persona}` : "Persona: general coding assistant",
|
||||
`Permission policy enforced by the ACP client: ${JSON.stringify(bot.permissions)}`,
|
||||
...skills.map((skill) => `Skill ${skill.id} (${skill.file}):\n${skill.content}`)
|
||||
].join("\n\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user