refactor: replace UWF_EDGE_PROMPT env var with named CLI args
Agent adapters now use named parameters: uwf-<agent> --thread <id> --role <role> --prompt <text> Instead of positional args + env var: UWF_EDGE_PROMPT=... uwf-<agent> <thread-id> <role> Changes: - workflow-agent-kit/src/run.ts: parseArgv uses named --thread/--role/--prompt - workflow-agent-kit/src/context.ts: edgePrompt passed as parameter, not read from env - cli-workflow/src/commands/thread.ts: spawnAgent passes named args 小橘 <xiaoju@shazhou.work>
This commit is contained in:
@@ -804,13 +804,11 @@ function spawnAgent(
|
|||||||
role: string,
|
role: string,
|
||||||
edgePrompt: string,
|
edgePrompt: string,
|
||||||
): CasRef {
|
): CasRef {
|
||||||
const argv = [...agent.args, threadId, role];
|
const argv = [...agent.args, "--thread", threadId, "--role", role, "--prompt", edgePrompt];
|
||||||
const env = { ...process.env, UWF_EDGE_PROMPT: edgePrompt };
|
|
||||||
let stdout: string;
|
let stdout: string;
|
||||||
try {
|
try {
|
||||||
stdout = execFileSync(agent.command, argv, {
|
stdout = execFileSync(agent.command, argv, {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
env,
|
|
||||||
stdio: ["ignore", "pipe", "pipe"],
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
maxBuffer: 50 * 1024 * 1024, // 50 MB — stream-json output can be large
|
maxBuffer: 50 * 1024 * 1024, // 50 MB — stream-json output can be large
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,14 +21,6 @@ function fail(message: string): never {
|
|||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readEdgePrompt(): string {
|
|
||||||
const value = process.env.UWF_EDGE_PROMPT;
|
|
||||||
if (value === undefined || value === "") {
|
|
||||||
fail("UWF_EDGE_PROMPT environment variable is required");
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function walkChain(store: Store, schemas: AgentStore["schemas"], headHash: CasRef): ChainState {
|
function walkChain(store: Store, schemas: AgentStore["schemas"], headHash: CasRef): ChainState {
|
||||||
const headNode = store.get(headHash);
|
const headNode = store.get(headHash);
|
||||||
if (headNode === null) {
|
if (headNode === null) {
|
||||||
@@ -123,7 +115,11 @@ async function loadWorkflow(store: Store, schemas: AgentStore["schemas"], workfl
|
|||||||
* Build agent execution context from thread head in threads.yaml.
|
* Build agent execution context from thread head in threads.yaml.
|
||||||
* Walks the CAS chain from head to StartNode and expands step outputs.
|
* Walks the CAS chain from head to StartNode and expands step outputs.
|
||||||
*/
|
*/
|
||||||
export async function buildContext(threadId: ThreadId, role: string): Promise<AgentContext> {
|
export async function buildContext(
|
||||||
|
threadId: ThreadId,
|
||||||
|
role: string,
|
||||||
|
edgePrompt: string,
|
||||||
|
): Promise<AgentContext> {
|
||||||
const storageRoot = resolveStorageRoot();
|
const storageRoot = resolveStorageRoot();
|
||||||
const agentStore = await createAgentStore(storageRoot);
|
const agentStore = await createAgentStore(storageRoot);
|
||||||
const { store, schemas } = agentStore;
|
const { store, schemas } = agentStore;
|
||||||
@@ -142,7 +138,6 @@ export async function buildContext(threadId: ThreadId, role: string): Promise<Ag
|
|||||||
}
|
}
|
||||||
|
|
||||||
const steps = await buildHistory(store, chain.stepsNewestFirst);
|
const steps = await buildHistory(store, chain.stepsNewestFirst);
|
||||||
const edgePrompt = readEdgePrompt();
|
|
||||||
const isFirstVisit = !steps.some((s) => s.role === role);
|
const isFirstVisit = !steps.some((s) => s.role === role);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -172,6 +167,7 @@ export type BuildContextMeta = {
|
|||||||
export async function buildContextWithMeta(
|
export async function buildContextWithMeta(
|
||||||
threadId: ThreadId,
|
threadId: ThreadId,
|
||||||
role: string,
|
role: string,
|
||||||
|
edgePrompt: string,
|
||||||
): Promise<AgentContext & { meta: BuildContextMeta }> {
|
): Promise<AgentContext & { meta: BuildContextMeta }> {
|
||||||
const storageRoot = resolveStorageRoot();
|
const storageRoot = resolveStorageRoot();
|
||||||
const agentStore = await createAgentStore(storageRoot);
|
const agentStore = await createAgentStore(storageRoot);
|
||||||
@@ -191,7 +187,6 @@ export async function buildContextWithMeta(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const steps = await buildHistory(store, chain.stepsNewestFirst);
|
const steps = await buildHistory(store, chain.stepsNewestFirst);
|
||||||
const edgePrompt = readEdgePrompt();
|
|
||||||
const isFirstVisit = !steps.some((s) => s.role === role);
|
const isFirstVisit = !steps.some((s) => s.role === role);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -22,16 +22,24 @@ function agentLabel(name: string): string {
|
|||||||
return `uwf-${name}`;
|
return `uwf-${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseArgv(argv: string[]): { threadId: ThreadId; role: string } {
|
const USAGE = "usage: <agent-cli> --thread <id> --role <role> --prompt <text>";
|
||||||
const threadId = argv[2];
|
|
||||||
const role = argv[3];
|
function getNamedArg(argv: string[], name: string): string {
|
||||||
if (threadId === undefined || threadId === "") {
|
const idx = argv.indexOf(name);
|
||||||
fail("usage: <agent-cli> <thread-id> <role>");
|
if (idx === -1 || idx + 1 >= argv.length) {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
if (role === undefined || role === "") {
|
return argv[idx + 1];
|
||||||
fail("usage: <agent-cli> <thread-id> <role>");
|
}
|
||||||
}
|
|
||||||
return { threadId: threadId as ThreadId, role };
|
function parseArgv(argv: string[]): { threadId: ThreadId; role: string; prompt: string } {
|
||||||
|
const threadId = getNamedArg(argv, "--thread");
|
||||||
|
const role = getNamedArg(argv, "--role");
|
||||||
|
const prompt = getNamedArg(argv, "--prompt");
|
||||||
|
if (threadId === "") fail(USAGE);
|
||||||
|
if (role === "") fail(USAGE);
|
||||||
|
if (prompt === "") fail(USAGE);
|
||||||
|
return { threadId: threadId as ThreadId, role, prompt };
|
||||||
}
|
}
|
||||||
|
|
||||||
function runWithMessage<T>(label: string, fn: () => Promise<T>): Promise<T> {
|
function runWithMessage<T>(label: string, fn: () => Promise<T>): Promise<T> {
|
||||||
@@ -103,11 +111,11 @@ async function persistStep(options: {
|
|||||||
|
|
||||||
export function createAgent(options: AgentOptions): () => Promise<void> {
|
export function createAgent(options: AgentOptions): () => Promise<void> {
|
||||||
return async function main(): Promise<void> {
|
return async function main(): Promise<void> {
|
||||||
const { threadId, role } = parseArgv(process.argv);
|
const { threadId, role, prompt } = parseArgv(process.argv);
|
||||||
const storageRoot = resolveStorageRoot();
|
const storageRoot = resolveStorageRoot();
|
||||||
loadDotenv({ path: getEnvPath(storageRoot) });
|
loadDotenv({ path: getEnvPath(storageRoot) });
|
||||||
|
|
||||||
const ctx = await runWithMessage("context", () => buildContextWithMeta(threadId, role));
|
const ctx = await runWithMessage("context", () => buildContextWithMeta(threadId, role, prompt));
|
||||||
|
|
||||||
const roleDef = ctx.workflow.roles[role];
|
const roleDef = ctx.workflow.roles[role];
|
||||||
if (roleDef === undefined) {
|
if (roleDef === undefined) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export type AgentContext = ModeratorContext & {
|
|||||||
*/
|
*/
|
||||||
outputFormatInstruction: string;
|
outputFormatInstruction: string;
|
||||||
/**
|
/**
|
||||||
* Edge prompt from the graph transition that led to this role (UWF_EDGE_PROMPT).
|
* Edge prompt from the graph transition that led to this role (--prompt CLI arg).
|
||||||
* Always the real moderator instruction for this step.
|
* Always the real moderator instruction for this step.
|
||||||
*/
|
*/
|
||||||
edgePrompt: string;
|
edgePrompt: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user