feat: add four-phase role description (identity/prepare/execute/report)
- Extend RoleDefinition with identity, prepare, execute, report fields - Make systemPrompt optional (nullable) for four-phase workflows - Update ROLE_DEFINITION JSON Schema (all new fields optional) - Update validate.ts to accept new fields - Update workflow.ts to strip null fields before CAS storage - Update thread read to prefer identity over systemPrompt - Add --version flag to uwf CLI - Bump all packages to 0.5.0 Refs #359
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/cli-workflow",
|
"name": "@uncaged/cli-workflow",
|
||||||
"version": "0.1.0",
|
"version": "0.5.0",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ function runAction(action: () => Promise<void>): void {
|
|||||||
|
|
||||||
const program = new Command();
|
const program = new Command();
|
||||||
|
|
||||||
program.name("uwf").description("Stateless workflow CLI");
|
// eslint-disable-next-line -- dynamic import for version
|
||||||
|
const pkg = await import("../package.json", { with: { type: "json" } });
|
||||||
|
program.name("uwf").description("Stateless workflow CLI").version(pkg.default.version, "-V, --version");
|
||||||
program.option("--format <fmt>", "Output format: json or yaml", "json");
|
program.option("--format <fmt>", "Output format: json or yaml", "json");
|
||||||
|
|
||||||
const workflow = program.command("workflow").description("Workflow registry and CAS");
|
const workflow = program.command("workflow").description("Workflow registry and CAS");
|
||||||
|
|||||||
@@ -500,7 +500,8 @@ function formatThreadReadMarkdown(options: {
|
|||||||
];
|
];
|
||||||
const roleDef = workflow.roles[item.payload.role];
|
const roleDef = workflow.roles[item.payload.role];
|
||||||
if (roleDef) {
|
if (roleDef) {
|
||||||
stepLines.push("", "### Prompt", "", roleDef.systemPrompt);
|
const prompt = roleDef.identity ?? roleDef.systemPrompt ?? "";
|
||||||
|
stepLines.push("", "### Prompt", "", prompt);
|
||||||
}
|
}
|
||||||
if (item.payload.detail) {
|
if (item.payload.detail) {
|
||||||
const content = extractLastAssistantContent(uwf, item.payload.detail);
|
const content = extractLastAssistantContent(uwf, item.payload.detail);
|
||||||
|
|||||||
@@ -67,11 +67,22 @@ async function materializeWorkflowPayload(
|
|||||||
`${raw.name}.${roleName}`,
|
`${raw.name}.${roleName}`,
|
||||||
role.outputSchema,
|
role.outputSchema,
|
||||||
);
|
);
|
||||||
roles[roleName] = {
|
const roleDef: RoleDefinition = {
|
||||||
description: role.description,
|
description: role.description,
|
||||||
systemPrompt: role.systemPrompt,
|
systemPrompt: role.systemPrompt ?? null,
|
||||||
|
identity: role.identity ?? null,
|
||||||
|
prepare: role.prepare ?? null,
|
||||||
|
execute: role.execute ?? null,
|
||||||
|
report: role.report ?? null,
|
||||||
outputSchema,
|
outputSchema,
|
||||||
};
|
};
|
||||||
|
// Strip null fields so CAS payload stays lean and schema-valid
|
||||||
|
for (const key of ["systemPrompt", "identity", "prepare", "execute", "report"] as const) {
|
||||||
|
if (roleDef[key] === null) {
|
||||||
|
delete (roleDef as Record<string, unknown>)[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roles[roleName] = roleDef;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: raw.name,
|
name: raw.name,
|
||||||
|
|||||||
@@ -16,9 +16,17 @@ function isRoleDefinition(value: unknown): boolean {
|
|||||||
}
|
}
|
||||||
const outputSchema = value.outputSchema;
|
const outputSchema = value.outputSchema;
|
||||||
const schemaOk = isRecord(outputSchema) && typeof outputSchema.type === "string";
|
const schemaOk = isRecord(outputSchema) && typeof outputSchema.type === "string";
|
||||||
return (
|
const hasSystemPrompt =
|
||||||
typeof value.description === "string" && typeof value.systemPrompt === "string" && schemaOk
|
value.systemPrompt === undefined || value.systemPrompt === null || typeof value.systemPrompt === "string";
|
||||||
);
|
const hasIdentity =
|
||||||
|
value.identity === undefined || value.identity === null || typeof value.identity === "string";
|
||||||
|
const hasPrepare =
|
||||||
|
value.prepare === undefined || value.prepare === null || typeof value.prepare === "string";
|
||||||
|
const hasExecute =
|
||||||
|
value.execute === undefined || value.execute === null || typeof value.execute === "string";
|
||||||
|
const hasReport =
|
||||||
|
value.report === undefined || value.report === null || typeof value.report === "string";
|
||||||
|
return typeof value.description === "string" && hasSystemPrompt && hasIdentity && hasPrepare && hasExecute && hasReport && schemaOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isConditionDefinition(value: unknown): boolean {
|
function isConditionDefinition(value: unknown): boolean {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/workflow-agent-hermes",
|
"name": "@uncaged/workflow-agent-hermes",
|
||||||
"version": "0.1.0",
|
"version": "0.5.0",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/workflow-agent-kit",
|
"name": "@uncaged/workflow-agent-kit",
|
||||||
"version": "0.1.0",
|
"version": "0.5.0",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/workflow-moderator",
|
"name": "@uncaged/workflow-moderator",
|
||||||
"version": "0.1.0",
|
"version": "0.5.0",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/workflow-protocol",
|
"name": "@uncaged/workflow-protocol",
|
||||||
"version": "0.1.0",
|
"version": "0.5.0",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -2,10 +2,14 @@ import type { JSONSchema } from "@uncaged/json-cas";
|
|||||||
|
|
||||||
const ROLE_DEFINITION: JSONSchema = {
|
const ROLE_DEFINITION: JSONSchema = {
|
||||||
type: "object",
|
type: "object",
|
||||||
required: ["description", "systemPrompt", "outputSchema"],
|
required: ["description", "outputSchema"],
|
||||||
properties: {
|
properties: {
|
||||||
description: { type: "string" },
|
description: { type: "string" },
|
||||||
systemPrompt: { type: "string" },
|
systemPrompt: { type: "string" },
|
||||||
|
identity: { type: "string" },
|
||||||
|
prepare: { type: "string" },
|
||||||
|
execute: { type: "string" },
|
||||||
|
report: { type: "string" },
|
||||||
outputSchema: { type: "string", format: "cas_ref" },
|
outputSchema: { type: "string", format: "cas_ref" },
|
||||||
},
|
},
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ export type StepRecord = {
|
|||||||
|
|
||||||
export type RoleDefinition = {
|
export type RoleDefinition = {
|
||||||
description: string;
|
description: string;
|
||||||
systemPrompt: string;
|
systemPrompt: string | null;
|
||||||
|
identity: string | null;
|
||||||
|
prepare: string | null;
|
||||||
|
execute: string | null;
|
||||||
|
report: string | null;
|
||||||
outputSchema: CasRef;
|
outputSchema: CasRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/workflow-util",
|
"name": "@uncaged/workflow-util",
|
||||||
"version": "0.5.0-alpha.4",
|
"version": "0.5.0",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
Reference in New Issue
Block a user