upulse-engine/templates/workflow.ts.tmpl

84 lines
2.2 KiB
Cheetah

/**
* {{WORKFLOW_NAME}} workflow
*
* {{DESCRIPTION}}
*
* 小橘 🍊 (NEKO Team)
*/
import { END, START, type Role, type WorkflowType } from '@uncaged/pulse';
// ── Role meta types ───────────────────────────────────────────
// Define a type for each role's meta output.
// Keep meta small — only what moderator and downstream roles need.
type Step1Meta = {
// e.g. result: string;
};
type Step2Meta = {
// e.g. summary: string;
};
// ── Roles type map ────────────────────────────────────────────
type {{WORKFLOW_ROLES_TYPE}} = {
step1: Role<Step1Meta>;
step2: Role<Step2Meta>;
};
// ── Workflow definition ───────────────────────────────────────
export const {{WORKFLOW_EXPORT}}: WorkflowType<{{WORKFLOW_ROLES_TYPE}}> = {
name: '{{WORKFLOW_NAME}}',
roles: {
/**
* Step 1: first role in the pipeline.
* Receives the full message chain (including __start__).
*/
step1: async (chain) => {
const start = chain.find((m) => m.role === '__start__');
const input = start?.content ?? '';
// TODO: implement role logic
const result = `processed: ${input}`;
return {
content: result,
meta: { /* step1 meta */ } as Step1Meta,
};
},
/**
* Step 2: second role, receives chain including step1 output.
*/
step2: async (chain) => {
const prev = chain.find((m) => m.role === 'step1');
// TODO: implement role logic
const summary = `done: ${prev?.content ?? ''}`;
return {
content: summary,
meta: { /* step2 meta */ } as Step2Meta,
};
},
},
/**
* Moderator: state machine that decides the next role.
*
* Input.role is the LAST completed role (or START for new topics).
* Return the next role name, or END to finish.
*/
moderator: (output) => {
switch (output.role) {
case START: return 'step1';
case 'step1': return 'step2';
case 'step2': return END;
default: return END;
}
},
};