singularity-forge/src/resources/extensions/sf/workflow-dispatch.js
2026-05-08 01:34:07 +02:00

72 lines
2.5 KiB
JavaScript

/**
* workflow-dispatch.ts — Shared dispatchers for workflow plugins.
*
* Called by both `/start <template>` (existing markdown path) and
* `/workflow <name>` (new direct dispatch). Keeps the prompt-build
* logic in one place so md template behavior stays consistent.
*/
import { readFileSync } from "node:fs";
import { loadPrompt } from "./prompt-loader.js";
// ─── Oneshot dispatch ────────────────────────────────────────────────────
/**
* Strip the `<template_meta>` block from markdown content so it's not
* repeated in the prompt body.
*/
function stripTemplateMeta(content) {
return content.replace(/<template_meta>[\s\S]*?<\/template_meta>\s*/, "");
}
/**
* For a oneshot YAML plugin, extract the single-step prompt.
* For multi-step YAML defined as oneshot, concatenate step prompts.
*/
function extractYamlOneshotPrompt(yamlContent) {
// Simple: just include the raw YAML so the model can follow it.
// This keeps the oneshot format flexible without re-parsing.
return `\`\`\`yaml\n${yamlContent}\n\`\`\``;
}
/**
* Dispatch a oneshot workflow: load the prompt, inject the body, send.
* No STATE.json, no branch switch, no auto-loop.
*/
export function dispatchOneshot(plugin, pi, userArgs) {
const raw = readFileSync(plugin.path, "utf-8");
const body =
plugin.format === "yaml"
? extractYamlOneshotPrompt(raw)
: stripTemplateMeta(raw);
const prompt = loadPrompt("workflow-oneshot", {
name: plugin.name,
displayName: plugin.meta.displayName,
body,
userArgs: userArgs || "(none)",
});
pi.sendMessage(
{ customType: "sf-workflow-oneshot", content: prompt, display: false },
{ triggerTurn: true },
);
}
/**
* Build and dispatch the `workflow-start.md` prompt for a markdown-phase plugin.
* Returns the prompt that was sent (useful for tests).
*/
export function dispatchMarkdownPhase(opts, pi) {
const prompt = loadPrompt("workflow-start", {
templateId: opts.templateId,
templateName: opts.templateName,
templateDescription: opts.templateDescription,
phases: opts.phases.join(" → "),
complexity: opts.complexity,
artifactDir: opts.artifactDir || "(none)",
branch: opts.branch,
description: opts.description || "(none provided)",
issueRef: opts.issueRef || "(none)",
date: opts.date,
workflowContent: opts.workflowContent,
});
pi.sendMessage(
{ customType: "sf-workflow-template", content: prompt, display: false },
{ triggerTurn: true },
);
return prompt;
}