yaml-flow 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -0
- package/dist/{constants-DcCDDQON.d.ts → constants-BEbO2_OK.d.ts} +1 -1
- package/dist/{constants-Dbk6ArN5.d.cts → constants-BNjeIlZ8.d.cts} +1 -1
- package/dist/continuous-event-graph/index.d.cts +5 -135
- package/dist/continuous-event-graph/index.d.ts +5 -135
- package/dist/event-graph/index.d.cts +3 -3
- package/dist/event-graph/index.d.ts +3 -3
- package/dist/index.cjs +259 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +254 -1
- package/dist/index.js.map +1 -1
- package/dist/inference/index.cjs +450 -0
- package/dist/inference/index.cjs.map +1 -0
- package/dist/inference/index.d.cts +229 -0
- package/dist/inference/index.d.ts +229 -0
- package/dist/inference/index.js +443 -0
- package/dist/inference/index.js.map +1 -0
- package/dist/types-C2lOwquM.d.cts +135 -0
- package/dist/{types-CTu8RqY0.d.cts → types-DAI_a2as.d.cts} +11 -0
- package/dist/{types-CTu8RqY0.d.ts → types-DAI_a2as.d.ts} +11 -0
- package/dist/types-mS_pPftm.d.ts +135 -0
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var child_process = require('child_process');
|
|
4
|
+
|
|
3
5
|
// src/step-machine/reducer.ts
|
|
4
6
|
function applyStepResult(flow, state, stepName, stepResult) {
|
|
5
7
|
const stepConfig = flow.steps[stepName];
|
|
@@ -3029,6 +3031,257 @@ function getDownstream(live, nodeName) {
|
|
|
3029
3031
|
return { nodeName, nodes, tokens: [...tokenSet] };
|
|
3030
3032
|
}
|
|
3031
3033
|
|
|
3034
|
+
// src/inference/core.ts
|
|
3035
|
+
var DEFAULT_THRESHOLD = 0.5;
|
|
3036
|
+
var DEFAULT_SYSTEM_PROMPT = `You are a workflow completion analyzer. Given a graph of tasks with their current states, evidence, and inference hints, determine which tasks appear to be completed based on the available evidence.
|
|
3037
|
+
|
|
3038
|
+
For each task you analyze, provide a JSON response. Be conservative \u2014 only mark tasks as completed when the evidence strongly supports it.`;
|
|
3039
|
+
function buildInferencePrompt(live, options = {}) {
|
|
3040
|
+
const { scope, context, systemPrompt } = options;
|
|
3041
|
+
const graphTasks = getAllTasks(live.config);
|
|
3042
|
+
const { state } = live;
|
|
3043
|
+
const candidates = getAnalyzableCandidates(live, scope);
|
|
3044
|
+
if (candidates.length === 0) {
|
|
3045
|
+
return "";
|
|
3046
|
+
}
|
|
3047
|
+
const lines = [];
|
|
3048
|
+
lines.push(systemPrompt || DEFAULT_SYSTEM_PROMPT);
|
|
3049
|
+
lines.push("");
|
|
3050
|
+
lines.push("## Graph State");
|
|
3051
|
+
lines.push("");
|
|
3052
|
+
lines.push(`Available tokens: ${state.availableOutputs.length > 0 ? state.availableOutputs.join(", ") : "(none)"}`);
|
|
3053
|
+
lines.push("");
|
|
3054
|
+
const completedTasks = Object.entries(state.tasks).filter(([_, ts]) => ts.status === "completed").map(([name]) => name);
|
|
3055
|
+
if (completedTasks.length > 0) {
|
|
3056
|
+
lines.push(`Completed tasks: ${completedTasks.join(", ")}`);
|
|
3057
|
+
lines.push("");
|
|
3058
|
+
}
|
|
3059
|
+
lines.push("## Tasks to Analyze");
|
|
3060
|
+
lines.push("");
|
|
3061
|
+
for (const taskName of candidates) {
|
|
3062
|
+
const taskConfig = graphTasks[taskName];
|
|
3063
|
+
const taskState = state.tasks[taskName];
|
|
3064
|
+
lines.push(`### ${taskName}`);
|
|
3065
|
+
if (taskConfig.description) {
|
|
3066
|
+
lines.push(`Description: ${taskConfig.description}`);
|
|
3067
|
+
}
|
|
3068
|
+
const requires = getRequires(taskConfig);
|
|
3069
|
+
const provides = getProvides(taskConfig);
|
|
3070
|
+
if (requires.length > 0) lines.push(`Requires: ${requires.join(", ")}`);
|
|
3071
|
+
if (provides.length > 0) lines.push(`Provides: ${provides.join(", ")}`);
|
|
3072
|
+
lines.push(`Current status: ${taskState?.status || "not-started"}`);
|
|
3073
|
+
const hints = taskConfig.inference;
|
|
3074
|
+
if (hints) {
|
|
3075
|
+
if (hints.criteria) lines.push(`Completion criteria: ${hints.criteria}`);
|
|
3076
|
+
if (hints.keywords?.length) lines.push(`Keywords: ${hints.keywords.join(", ")}`);
|
|
3077
|
+
if (hints.suggestedChecks?.length) lines.push(`Suggested checks: ${hints.suggestedChecks.join("; ")}`);
|
|
3078
|
+
}
|
|
3079
|
+
lines.push("");
|
|
3080
|
+
}
|
|
3081
|
+
if (context) {
|
|
3082
|
+
lines.push("## Additional Context / Evidence");
|
|
3083
|
+
lines.push("");
|
|
3084
|
+
lines.push(context);
|
|
3085
|
+
lines.push("");
|
|
3086
|
+
}
|
|
3087
|
+
lines.push("## Response Format");
|
|
3088
|
+
lines.push("");
|
|
3089
|
+
lines.push("Respond with a JSON array of objects, one per task you have evidence for:");
|
|
3090
|
+
lines.push("```json");
|
|
3091
|
+
lines.push("[");
|
|
3092
|
+
lines.push(" {");
|
|
3093
|
+
lines.push(' "taskName": "task-name",');
|
|
3094
|
+
lines.push(' "confidence": 0.0 to 1.0,');
|
|
3095
|
+
lines.push(' "reasoning": "explanation of why you believe this task is complete or not"');
|
|
3096
|
+
lines.push(" }");
|
|
3097
|
+
lines.push("]");
|
|
3098
|
+
lines.push("```");
|
|
3099
|
+
lines.push("");
|
|
3100
|
+
lines.push("Rules:");
|
|
3101
|
+
lines.push('- Only include tasks from the "Tasks to Analyze" section');
|
|
3102
|
+
lines.push("- confidence 0.0 = no evidence of completion, 1.0 = certain it is complete");
|
|
3103
|
+
lines.push("- If you have no evidence for a task, omit it from the array");
|
|
3104
|
+
lines.push("- Be conservative \u2014 require clear evidence before high confidence");
|
|
3105
|
+
lines.push("- Respond ONLY with the JSON array, no additional text");
|
|
3106
|
+
return lines.join("\n");
|
|
3107
|
+
}
|
|
3108
|
+
async function inferCompletions(live, adapter, options = {}) {
|
|
3109
|
+
options.threshold ?? DEFAULT_THRESHOLD;
|
|
3110
|
+
const analyzedNodes = getAnalyzableCandidates(live, options.scope);
|
|
3111
|
+
if (analyzedNodes.length === 0) {
|
|
3112
|
+
return { suggestions: [], promptUsed: "", rawResponse: "", analyzedNodes: [] };
|
|
3113
|
+
}
|
|
3114
|
+
const prompt = buildInferencePrompt(live, options);
|
|
3115
|
+
const rawResponse = await adapter.analyze(prompt);
|
|
3116
|
+
const suggestions = parseInferenceResponse(rawResponse, analyzedNodes);
|
|
3117
|
+
return {
|
|
3118
|
+
suggestions,
|
|
3119
|
+
promptUsed: prompt,
|
|
3120
|
+
rawResponse,
|
|
3121
|
+
analyzedNodes
|
|
3122
|
+
};
|
|
3123
|
+
}
|
|
3124
|
+
function applyInferences(live, result, threshold = DEFAULT_THRESHOLD) {
|
|
3125
|
+
let current = live;
|
|
3126
|
+
for (const suggestion of result.suggestions) {
|
|
3127
|
+
if (suggestion.confidence < threshold) continue;
|
|
3128
|
+
const taskState = current.state.tasks[suggestion.taskName];
|
|
3129
|
+
if (!taskState) continue;
|
|
3130
|
+
if (taskState.status === "completed" || taskState.status === "running") continue;
|
|
3131
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3132
|
+
current = applyEvent(current, {
|
|
3133
|
+
type: "task-started",
|
|
3134
|
+
taskName: suggestion.taskName,
|
|
3135
|
+
timestamp: now
|
|
3136
|
+
});
|
|
3137
|
+
current = applyEvent(current, {
|
|
3138
|
+
type: "task-completed",
|
|
3139
|
+
taskName: suggestion.taskName,
|
|
3140
|
+
timestamp: now,
|
|
3141
|
+
result: "llm-inferred"
|
|
3142
|
+
});
|
|
3143
|
+
}
|
|
3144
|
+
return current;
|
|
3145
|
+
}
|
|
3146
|
+
async function inferAndApply(live, adapter, options = {}) {
|
|
3147
|
+
const threshold = options.threshold ?? DEFAULT_THRESHOLD;
|
|
3148
|
+
const inference = await inferCompletions(live, adapter, options);
|
|
3149
|
+
const updated = applyInferences(live, inference, threshold);
|
|
3150
|
+
const applied = inference.suggestions.filter((s) => s.confidence >= threshold);
|
|
3151
|
+
const skipped = inference.suggestions.filter((s) => s.confidence < threshold);
|
|
3152
|
+
return {
|
|
3153
|
+
live: updated,
|
|
3154
|
+
inference,
|
|
3155
|
+
applied,
|
|
3156
|
+
skipped
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3159
|
+
function getAnalyzableCandidates(live, scope) {
|
|
3160
|
+
const graphTasks = getAllTasks(live.config);
|
|
3161
|
+
const { state } = live;
|
|
3162
|
+
const candidates = [];
|
|
3163
|
+
for (const [name, config] of Object.entries(graphTasks)) {
|
|
3164
|
+
const taskState = state.tasks[name];
|
|
3165
|
+
if (taskState?.status === "completed" || taskState?.status === "running") continue;
|
|
3166
|
+
if (scope) {
|
|
3167
|
+
if (scope.includes(name)) candidates.push(name);
|
|
3168
|
+
} else {
|
|
3169
|
+
if (config.inference?.autoDetectable) candidates.push(name);
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
return candidates;
|
|
3173
|
+
}
|
|
3174
|
+
function parseInferenceResponse(rawResponse, validNodes, _threshold) {
|
|
3175
|
+
const validSet = new Set(validNodes);
|
|
3176
|
+
try {
|
|
3177
|
+
const jsonStr = extractJson(rawResponse);
|
|
3178
|
+
if (!jsonStr) return [];
|
|
3179
|
+
const parsed = JSON.parse(jsonStr);
|
|
3180
|
+
if (!Array.isArray(parsed)) return [];
|
|
3181
|
+
const suggestions = [];
|
|
3182
|
+
for (const item of parsed) {
|
|
3183
|
+
if (!item || typeof item !== "object") continue;
|
|
3184
|
+
if (typeof item.taskName !== "string") continue;
|
|
3185
|
+
if (typeof item.confidence !== "number") continue;
|
|
3186
|
+
if (!validSet.has(item.taskName)) continue;
|
|
3187
|
+
const confidence = Math.max(0, Math.min(1, item.confidence));
|
|
3188
|
+
suggestions.push({
|
|
3189
|
+
taskName: item.taskName,
|
|
3190
|
+
confidence,
|
|
3191
|
+
reasoning: typeof item.reasoning === "string" ? item.reasoning : "",
|
|
3192
|
+
detectionMethod: "llm-inferred"
|
|
3193
|
+
});
|
|
3194
|
+
}
|
|
3195
|
+
return suggestions;
|
|
3196
|
+
} catch {
|
|
3197
|
+
return [];
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
function extractJson(text) {
|
|
3201
|
+
if (!text || typeof text !== "string") return null;
|
|
3202
|
+
const trimmed = text.trim();
|
|
3203
|
+
const fenceMatch = trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
|
|
3204
|
+
if (fenceMatch) return fenceMatch[1].trim();
|
|
3205
|
+
const firstBracket = trimmed.indexOf("[");
|
|
3206
|
+
const lastBracket = trimmed.lastIndexOf("]");
|
|
3207
|
+
if (firstBracket !== -1 && lastBracket > firstBracket) {
|
|
3208
|
+
return trimmed.slice(firstBracket, lastBracket + 1);
|
|
3209
|
+
}
|
|
3210
|
+
if (trimmed.startsWith("[")) return trimmed;
|
|
3211
|
+
return null;
|
|
3212
|
+
}
|
|
3213
|
+
function createCliAdapter(opts) {
|
|
3214
|
+
const timeout = opts.timeout ?? 6e4;
|
|
3215
|
+
return {
|
|
3216
|
+
analyze: (prompt) => {
|
|
3217
|
+
return new Promise((resolve, reject) => {
|
|
3218
|
+
const args = opts.args(prompt);
|
|
3219
|
+
const child = child_process.execFile(
|
|
3220
|
+
opts.command,
|
|
3221
|
+
opts.stdin ? opts.args("") : args,
|
|
3222
|
+
{
|
|
3223
|
+
timeout,
|
|
3224
|
+
cwd: opts.cwd,
|
|
3225
|
+
env: opts.env ? { ...process.env, ...opts.env } : void 0,
|
|
3226
|
+
maxBuffer: 10 * 1024 * 1024
|
|
3227
|
+
// 10MB
|
|
3228
|
+
},
|
|
3229
|
+
(error, stdout, stderr) => {
|
|
3230
|
+
if (error) {
|
|
3231
|
+
reject(new Error(
|
|
3232
|
+
`CLI adapter failed: ${opts.command} exited with ${error.code ?? "error"}` + (stderr ? `
|
|
3233
|
+
stderr: ${stderr.slice(0, 500)}` : "") + `
|
|
3234
|
+
${error.message}`
|
|
3235
|
+
));
|
|
3236
|
+
} else {
|
|
3237
|
+
resolve(stdout);
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
);
|
|
3241
|
+
if (opts.stdin && child.stdin) {
|
|
3242
|
+
child.stdin.write(prompt);
|
|
3243
|
+
child.stdin.end();
|
|
3244
|
+
}
|
|
3245
|
+
});
|
|
3246
|
+
}
|
|
3247
|
+
};
|
|
3248
|
+
}
|
|
3249
|
+
function createHttpAdapter(opts) {
|
|
3250
|
+
const timeout = opts.timeout ?? 6e4;
|
|
3251
|
+
return {
|
|
3252
|
+
analyze: async (prompt) => {
|
|
3253
|
+
const body = opts.buildBody ? opts.buildBody(prompt) : { prompt };
|
|
3254
|
+
const controller = new AbortController();
|
|
3255
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
3256
|
+
try {
|
|
3257
|
+
const response = await fetch(opts.url, {
|
|
3258
|
+
method: "POST",
|
|
3259
|
+
headers: {
|
|
3260
|
+
"Content-Type": "application/json",
|
|
3261
|
+
...opts.headers ?? {}
|
|
3262
|
+
},
|
|
3263
|
+
body: JSON.stringify(body),
|
|
3264
|
+
signal: controller.signal
|
|
3265
|
+
});
|
|
3266
|
+
if (!response.ok) {
|
|
3267
|
+
const text = await response.text().catch(() => "");
|
|
3268
|
+
throw new Error(`HTTP ${response.status}: ${text.slice(0, 500)}`);
|
|
3269
|
+
}
|
|
3270
|
+
const json = await response.json();
|
|
3271
|
+
if (opts.extractResponse) {
|
|
3272
|
+
return opts.extractResponse(json);
|
|
3273
|
+
}
|
|
3274
|
+
if (typeof json.response === "string") return json.response;
|
|
3275
|
+
if (typeof json.text === "string") return json.text;
|
|
3276
|
+
if (typeof json.content === "string") return json.content;
|
|
3277
|
+
return JSON.stringify(json);
|
|
3278
|
+
} finally {
|
|
3279
|
+
clearTimeout(timer);
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
};
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3032
3285
|
exports.COMPLETION_STRATEGIES = COMPLETION_STRATEGIES;
|
|
3033
3286
|
exports.CONFLICT_STRATEGIES = CONFLICT_STRATEGIES;
|
|
3034
3287
|
exports.DEFAULTS = DEFAULTS;
|
|
@@ -3047,13 +3300,17 @@ exports.addRequires = addRequires;
|
|
|
3047
3300
|
exports.apply = apply;
|
|
3048
3301
|
exports.applyAll = applyAll;
|
|
3049
3302
|
exports.applyEvent = applyEvent;
|
|
3303
|
+
exports.applyInferences = applyInferences;
|
|
3050
3304
|
exports.applyStepResult = applyStepResult;
|
|
3051
3305
|
exports.batch = batch;
|
|
3306
|
+
exports.buildInferencePrompt = buildInferencePrompt;
|
|
3052
3307
|
exports.checkCircuitBreaker = checkCircuitBreaker;
|
|
3053
3308
|
exports.computeAvailableOutputs = computeAvailableOutputs;
|
|
3054
3309
|
exports.computeStepInput = computeStepInput;
|
|
3310
|
+
exports.createCliAdapter = createCliAdapter;
|
|
3055
3311
|
exports.createDefaultTaskState = createDefaultTaskState;
|
|
3056
3312
|
exports.createEngine = createStepMachine;
|
|
3313
|
+
exports.createHttpAdapter = createHttpAdapter;
|
|
3057
3314
|
exports.createInitialExecutionState = createInitialExecutionState;
|
|
3058
3315
|
exports.createInitialState = createInitialState;
|
|
3059
3316
|
exports.createLiveGraph = createLiveGraph;
|
|
@@ -3078,6 +3335,8 @@ exports.getUnreachableTokens = getUnreachableTokens;
|
|
|
3078
3335
|
exports.getUpstream = getUpstream;
|
|
3079
3336
|
exports.graphToMermaid = graphToMermaid;
|
|
3080
3337
|
exports.hasTask = hasTask;
|
|
3338
|
+
exports.inferAndApply = inferAndApply;
|
|
3339
|
+
exports.inferCompletions = inferCompletions;
|
|
3081
3340
|
exports.injectTokens = injectTokens;
|
|
3082
3341
|
exports.inspect = inspect;
|
|
3083
3342
|
exports.isExecutionComplete = isExecutionComplete;
|