feat: add assistant proposal worker runtime
This commit is contained in:
@@ -2,12 +2,13 @@ import crypto from "node:crypto";
|
||||
import type { AppConfig, BotConfig } from "../config.js";
|
||||
import { SkillLoader, type LoadedSkill } from "./skill-loader.js";
|
||||
|
||||
const BOOTSTRAP_SCHEMA_VERSION = 1;
|
||||
const BOOTSTRAP_SCHEMA_VERSION = 4;
|
||||
|
||||
export interface ResolvedBot extends BotConfig {
|
||||
loadedSkills: LoadedSkill[];
|
||||
fingerprint: string;
|
||||
bootstrap: string;
|
||||
assistantBootstrap: string;
|
||||
workerBootstrap: string;
|
||||
}
|
||||
|
||||
export class BotProfileResolver {
|
||||
@@ -28,18 +29,35 @@ export class BotProfileResolver {
|
||||
...config.bot,
|
||||
loadedSkills,
|
||||
fingerprint,
|
||||
bootstrap: buildBootstrap(config.bot, loadedSkills)
|
||||
assistantBootstrap: buildAssistantBootstrap(config.bot),
|
||||
workerBootstrap: buildWorkerBootstrap(config.bot, loadedSkills)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function buildBootstrap(bot: BotConfig, skills: LoadedSkill[]): string {
|
||||
function buildAssistantBootstrap(bot: BotConfig): string {
|
||||
return [
|
||||
`Initialize this ACP session with gori-agent bootstrap schema v${BOOTSTRAP_SCHEMA_VERSION}. Treat these instructions as persistent context. Reply only with READY.`,
|
||||
`Initialize this ACP session with gori-agent assistant 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",
|
||||
"You are the user-facing Assistant. You have no tools and cannot inspect files, run commands, call Skills or MCP. You chat with the user, propose work, and explain worker feedback. Never claim to have executed anything yourself.",
|
||||
"Every reply must end with exactly one hidden action envelope: <GORI_ASSISTANT_ACTION_V1>{\"reply\":\"...\",\"actions\":[...]}</GORI_ASSISTANT_ACTION_V1>. Put the user-facing text in the JSON \"reply\" field, not outside the envelope.",
|
||||
"Supported actions: {\"type\":\"create_proposal\",\"title\":\"...\",\"goal\":\"...\",\"steps\":[\"...\"]}; {\"type\":\"confirm\",\"id\":\"optional\",\"answer\":\"optional\"}; {\"type\":\"start_next\"}; {\"type\":\"cancel\",\"id\":\"optional\"}; {\"type\":\"stop\"}. Use an empty actions array when no state change is needed.",
|
||||
"A proposal only starts after the user confirms it. Confirming a proposal whose worker reported SUCCESS marks it completed; confirming a FAILED proposal marks it failed; to retry a failed proposal, confirm with answer \"retry\". When a worker asks a question (NEEDS_CONFIRMATION), confirm with the user's answer to continue the same worker. \"stop\" terminates the active worker and cancels its proposal; \"start_next\" starts the oldest confirmed queued proposal. Never invent other actions or statuses."
|
||||
].join("\n\n");
|
||||
}
|
||||
|
||||
function buildWorkerBootstrap(bot: BotConfig, skills: LoadedSkill[]): string {
|
||||
return [
|
||||
`Initialize this ACP session with gori-agent worker 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)}`,
|
||||
"You are the Worker. You execute exactly one confirmed proposal in the configured workspace and never talk to the user directly.",
|
||||
"For every turn, end your response with exactly one hidden result envelope: <GORI_WORKER_RESULT_V1>{\"status\":\"SUCCESS\",\"summary\":\"...\"}</GORI_WORKER_RESULT_V1>. Status is SUCCESS only when the proposal is fully done, FAILED when it cannot be completed, or NEEDS_CONFIRMATION when you must ask the user before continuing (for example a dirty or unexpected target). Optional fields: \"question\", \"nextStep\", \"dirty\". Always include a short user-readable \"summary\". Never emit any other status or text after the envelope.",
|
||||
"Keep every command and tool process attached to this ACP worker. Never daemonize, call setsid, use nohup, create a detached process, or leave a background process running after the turn.",
|
||||
...skills.map((skill) => `Skill ${skill.id} (${skill.file}):\n${skill.content}`)
|
||||
].join("\n\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user