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:
2026-05-24 04:31:12 +00:00
parent 8ca7708a12
commit 02a2c00175
4 changed files with 27 additions and 26 deletions
+1 -3
View File
@@ -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
}); });
+6 -11
View File
@@ -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 {
+19 -11
View File
@@ -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) {
+1 -1
View File
@@ -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;