agent-workflow
Version:
A powerful workflow engine supporting DAG (Directed Acyclic Graph) task scheduling, dynamic task generation, and intelligent strategy systems.
1,187 lines (1,184 loc) • 35.5 kB
JavaScript
class ContextManager {
constructor() {
this.context = {};
}
// 获取上下文中的数据
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
get(key) {
return this.context[key];
}
// 设置上下文中的数据
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
set(key, value) {
this.context[key] = value;
}
// 获取完整上下文
getAll() {
return this.context;
}
// 清除上下文
clear() {
this.context = {};
}
}
class DAGTask {
constructor(dependencies = []) {
this.dependsOn = [];
this.dependsOn = dependencies;
}
}
class StreamingDAGTask extends DAGTask {
}
class AISDKStreamingTask extends DAGTask {
}
class WorkflowBuilder {
// 🔒 私有构造函数 - 防止直接实例化
constructor() {
this.config = {};
this.staticTasks = [];
this.dynamicStrategies = [];
}
// 🏭 工厂方法 - 唯一创建实例的方式
static create() {
return new WorkflowBuilder();
}
// 配置方法
withConfig(config) {
this.config = { ...this.config, ...config };
return this;
}
withRetry(attempts) {
this.config.retryAttempts = attempts;
return this;
}
withTimeout(timeoutMs) {
this.config.timeoutMs = timeoutMs;
return this;
}
// 静态任务构建
addTask(task) {
this.staticTasks.push(task);
return this;
}
addTasks(tasks) {
this.staticTasks.push(...tasks);
return this;
}
// 添加动态策略
addDynamicStrategy(strategy) {
this.dynamicStrategies.push(strategy);
return this;
}
// 条件任务生成 - 语法糖
whenCondition(condition, taskGenerator) {
return this.addDynamicStrategy({
name: `condition-${this.dynamicStrategies.length}`,
condition: (context) => {
const history = context.getExecutionHistory();
const completedTasks = history.filter((h) => h.status === "completed");
if (completedTasks.length > 0) {
return condition(context);
}
return false;
},
generator: taskGenerator,
once: true
});
}
// 基于结果的任务生成
onTaskComplete(taskName, resultProcessor) {
return this.addDynamicStrategy({
name: `on-complete-${taskName}`,
condition: (context) => {
const history = context.getExecutionHistory();
return history.some(
(h) => h.taskName === taskName && h.status === "completed"
);
},
generator: async (context) => {
const history = context.getExecutionHistory();
const taskResult = history.find((h) => h.taskName === taskName);
return resultProcessor(taskResult == null ? void 0 : taskResult.output, context);
},
once: true
});
}
// 基于上下文变化的任务生成
onContextChange(contextKey, taskGenerator) {
return this.addDynamicStrategy({
name: `on-context-${contextKey}`,
condition: (context) => {
const value = context.get(contextKey);
return value !== void 0;
},
generator: async (context) => {
const value = context.get(contextKey);
return taskGenerator(value, context);
},
once: true
});
}
// 构建工作流实例
build() {
if (this.dynamicStrategies.length > 0) {
return new StrategyBasedWorkflow(
this.config,
this.staticTasks,
this.dynamicStrategies
);
}
return new StaticWorkflow(this.config, this.staticTasks);
}
// 🌊 构建流式工作流实例
buildStreaming() {
this.config.enableStreaming = true;
if (this.dynamicStrategies.length > 0) {
return new StreamingStrategyBasedWorkflow(
this.config,
this.staticTasks,
this.dynamicStrategies
);
}
return new StreamingStaticWorkflow(this.config, this.staticTasks);
}
// 🤖 构建AI SDK兼容的流式工作流
buildAISDKStreaming() {
this.config.enableStreaming = true;
if (this.dynamicStrategies.length > 0) {
return new AISDKStreamingStrategyWorkflow(
this.config,
this.staticTasks,
this.dynamicStrategies
);
}
return new AISDKStreamingStaticWorkflow(this.config, this.staticTasks);
}
}
class EnhancedWorkflowContext {
constructor() {
this.executionHistory = [];
this.internalContext = new ContextManager();
}
get data() {
return this.internalContext.getAll();
}
get(key) {
return this.internalContext.get(key);
}
set(key, value) {
this.internalContext.set(key, value);
}
getAll() {
return this.internalContext.getAll();
}
clear() {
this.internalContext.clear();
this.executionHistory = [];
}
getExecutionHistory() {
return [...this.executionHistory];
}
getLastResult() {
const lastExecution = this.executionHistory[this.executionHistory.length - 1];
return lastExecution == null ? void 0 : lastExecution.output;
}
addExecutionResult(result) {
this.executionHistory.push(result);
}
// 内部方法,用于访问原始ContextManager
getInternalContext() {
return this.internalContext;
}
}
class BaseWorkflow {
constructor(config) {
this.startTime = 0;
this.taskResults = /* @__PURE__ */ new Map();
this.config = config;
this.context = new EnhancedWorkflowContext();
}
getContext() {
return this.context;
}
getResults() {
return new Map(this.taskResults);
}
async executeTask(task) {
const taskStartTime = Date.now();
try {
const input = this.context.getAll();
const output = await task.execute(input);
const taskName = task.name || "";
this.context.set(taskName, output);
for (const [key, value] of Object.entries(output)) {
this.context.set(key, value);
}
let uniqueKey = taskName;
let counter = 1;
while (this.taskResults.has(uniqueKey)) {
uniqueKey = `${taskName}_${counter}`;
counter++;
}
const result = {
taskName,
status: "completed",
output,
duration: Date.now() - taskStartTime,
timestamp: Date.now()
};
this.taskResults.set(uniqueKey, result);
this.context.addExecutionResult(result);
} catch (error) {
const taskName = task.name || "";
let uniqueKey = taskName;
let counter = 1;
while (this.taskResults.has(uniqueKey)) {
uniqueKey = `${taskName}_${counter}`;
counter++;
}
const result = {
taskName,
status: "failed",
error: error instanceof Error ? error.message : String(error),
duration: Date.now() - taskStartTime,
timestamp: Date.now()
};
this.taskResults.set(uniqueKey, result);
this.context.addExecutionResult(result);
throw error;
}
}
}
class StaticWorkflow extends BaseWorkflow {
constructor(config, tasks) {
super(config);
this.tasks = tasks;
}
async execute(input = {}) {
this.startTime = Date.now();
try {
Object.entries(input).forEach(([key, value]) => {
this.context.set(key, value);
});
await this.executeDAG();
return {
success: true,
data: this.context.getAll(),
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults
};
} catch (error) {
return {
success: false,
error,
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults
};
}
}
async executeDAG() {
const levels = this.computeExecutionLevels();
let hasError = false;
let lastError;
for (const level of levels) {
const results = await Promise.allSettled(
level.map((task) => this.executeTask(task))
);
for (const result of results) {
if (result.status === "rejected") {
hasError = true;
lastError = result.reason;
}
}
}
if (hasError && lastError) {
throw lastError;
}
}
computeExecutionLevels() {
var _a;
const graph = /* @__PURE__ */ new Map();
const inDegree = /* @__PURE__ */ new Map();
for (const task of this.tasks) {
graph.set(task, []);
inDegree.set(task, 0);
}
for (const task of this.tasks) {
if (task.dependsOn) {
for (const dep of task.dependsOn) {
(_a = graph.get(dep)) == null ? void 0 : _a.push(task);
inDegree.set(task, (inDegree.get(task) || 0) + 1);
}
}
}
const levels = [];
const queue = this.tasks.filter((task) => inDegree.get(task) === 0);
let processedCount = 0;
while (queue.length > 0) {
const currentLevel = [...queue];
levels.push(currentLevel);
processedCount += currentLevel.length;
queue.length = 0;
for (const task of currentLevel) {
for (const next of graph.get(task) || []) {
const newDegree = (inDegree.get(next) || 0) - 1;
inDegree.set(next, newDegree);
if (newDegree === 0) {
queue.push(next);
}
}
}
}
if (processedCount < this.tasks.length) {
throw new Error(
"Circular dependency detected, unable to execute workflow"
);
}
return levels;
}
}
class StrategyBasedWorkflow extends BaseWorkflow {
constructor(config, tasks, strategies) {
super(config);
this.dynamicTasksGenerated = 0;
this.currentStep = 0;
this.usedStrategies = /* @__PURE__ */ new Set();
this.tasks = [...tasks];
this.strategies = strategies;
}
async execute(input = {}) {
this.startTime = Date.now();
this.dynamicTasksGenerated = 0;
this.currentStep = 0;
this.usedStrategies.clear();
try {
Object.entries(input).forEach(([key, value]) => {
this.context.set(key, value);
});
while (this.hasTasksToExecute() && this.shouldContinue()) {
this.currentStep++;
await this.executeCurrentBatch();
await this.evaluateStrategiesAndGenerateTasks();
}
if (!this.hasTasksToExecute() && this.shouldContinue()) {
const processedTaskNames = new Set(
this.context.getExecutionHistory().filter(
(h) => h.status === "completed" || h.status === "failed" || h.status === "skipped"
).map((h) => h.taskName)
);
const unprocessedTasks = this.tasks.filter(
(task) => !processedTaskNames.has(task.name || "")
);
if (unprocessedTasks.length > 0) {
throw new Error(
"Circular dependency detected, unable to execute workflow"
);
}
}
return {
success: true,
data: this.context.getAll(),
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults,
dynamicTasksGenerated: this.dynamicTasksGenerated,
totalSteps: this.currentStep
};
} catch (error) {
return {
success: false,
error,
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults,
dynamicTasksGenerated: this.dynamicTasksGenerated,
totalSteps: this.currentStep
};
}
}
hasTasksToExecute() {
const readyTasks = this.getReadyTasks();
return readyTasks.length > 0;
}
shouldContinue() {
const maxSteps = this.config.maxDynamicSteps || 50;
return this.currentStep < maxSteps;
}
async executeCurrentBatch() {
const readyTasks = this.getReadyTasks();
if (readyTasks.length === 0) return;
const results = await Promise.allSettled(
readyTasks.map((task) => this.executeTask(task))
);
for (const result of results) {
if (result.status === "rejected") {
console.warn("Task execution failed:", result.reason);
}
}
}
getReadyTasks() {
const processedTaskNames = new Set(
this.context.getExecutionHistory().filter(
(h) => h.status === "completed" || h.status === "failed" || h.status === "skipped"
).map((h) => h.taskName)
);
return this.tasks.filter((task) => {
if (processedTaskNames.has(task.name || "")) {
return false;
}
if (task.dependsOn) {
return task.dependsOn.every(
(dep) => processedTaskNames.has(dep.name || "")
);
}
return true;
});
}
async evaluateStrategiesAndGenerateTasks() {
const sortedStrategies = [...this.strategies].sort(
(a, b) => (b.priority || 0) - (a.priority || 0)
);
for (const strategy of sortedStrategies) {
if (strategy.once && this.usedStrategies.has(strategy.name)) {
continue;
}
try {
const lastResult = this.context.getLastResult();
if (strategy.condition(this.context, lastResult)) {
const newTasks = await strategy.generator(this.context);
if (newTasks.length > 0) {
this.tasks.push(...newTasks);
this.dynamicTasksGenerated += newTasks.length;
if (strategy.once) {
this.usedStrategies.add(strategy.name);
}
console.log(
`🎯 Strategy "${strategy.name}" generated ${newTasks.length} new tasks`
);
}
}
} catch (error) {
console.error(`Strategy "${strategy.name}" execution failed:`, error);
}
}
}
}
class StreamingStaticWorkflow extends StaticWorkflow {
executeStream(input = {}) {
this.streamResult = void 0;
const stream = this.createExecutionStream(input);
const resultPromise = (async () => {
for await (const chunk of stream) {
}
return this.streamResult || {
success: false,
error: new Error("Streaming execution not completed"),
executionTime: 0,
taskResults: /* @__PURE__ */ new Map()
};
})();
return {
stream: this.createExecutionStream(input),
getResult: () => resultPromise
};
}
async *createExecutionStream(input) {
this.startTime = Date.now();
try {
Object.entries(input).forEach(([key, value]) => {
this.context.set(key, value);
});
yield {
type: "progress",
taskName: "workflow",
content: "Workflow execution started",
progress: 0,
timestamp: Date.now()
};
yield* this.executeDAGStream();
const result = {
success: true,
data: this.context.getAll(),
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults
};
this.streamResult = result;
yield {
type: "complete",
taskName: "workflow",
content: "Workflow execution completed",
progress: 100,
timestamp: Date.now()
};
return result;
} catch (error) {
const errorResult = {
success: false,
error,
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults
};
this.streamResult = errorResult;
yield {
type: "error",
taskName: "workflow",
content: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
return errorResult;
}
}
async *executeDAGStream() {
const levels = this.computeExecutionLevels();
const totalTasks = this.tasks.length;
let completedTasks = 0;
for (const level of levels) {
const taskPromises = level.map((task) => this.executeTaskStream(task));
for await (const taskStream of taskPromises) {
for await (const chunk of taskStream) {
yield chunk;
if (chunk.type === "complete") {
completedTasks++;
yield {
type: "progress",
taskName: "workflow",
content: `Completed ${completedTasks}/${totalTasks} tasks`,
progress: Math.round(completedTasks / totalTasks * 100),
timestamp: Date.now()
};
}
}
}
}
}
async *executeTaskStream(task) {
const taskStartTime = Date.now();
try {
yield {
type: "progress",
taskName: task.name,
content: `Starting task execution: ${task.name}`,
progress: 0,
timestamp: Date.now()
};
const input = this.context.getAll();
let output;
if (task.isStreaming && task.executeStream) {
const generator = task.executeStream(input);
let finalResult = {};
try {
while (true) {
const { value, done } = await generator.next();
if (done) {
finalResult = value || {};
break;
}
yield value;
}
} catch (error) {
throw error;
}
output = finalResult;
} else {
output = await task.execute(input);
}
const taskName = task.name || "";
this.context.set(taskName, output);
for (const [key, value] of Object.entries(output)) {
this.context.set(key, value);
}
let uniqueKey = taskName;
let counter = 1;
while (this.taskResults.has(uniqueKey)) {
uniqueKey = `${taskName}_${counter}`;
counter++;
}
const result = {
taskName,
status: "completed",
output,
duration: Date.now() - taskStartTime,
timestamp: Date.now()
};
this.taskResults.set(uniqueKey, result);
this.context.addExecutionResult(result);
yield {
type: "complete",
taskName: task.name,
content: `Task completed: ${task.name}`,
progress: 100,
timestamp: Date.now(),
metadata: { duration: result.duration }
};
} catch (error) {
const taskName = task.name || "";
let uniqueKey = taskName;
let counter = 1;
while (this.taskResults.has(uniqueKey)) {
uniqueKey = `${taskName}_${counter}`;
counter++;
}
const result = {
taskName,
status: "failed",
error: error instanceof Error ? error.message : String(error),
duration: Date.now() - taskStartTime,
timestamp: Date.now()
};
this.taskResults.set(uniqueKey, result);
this.context.addExecutionResult(result);
yield {
type: "error",
taskName: task.name,
content: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
}
}
class StreamingStrategyBasedWorkflow extends StrategyBasedWorkflow {
executeStream(input = {}) {
this.streamResult = void 0;
const stream = this.createDynamicExecutionStream(input);
const resultPromise = (async () => {
for await (const chunk of stream) {
}
return this.streamResult || {
success: false,
error: new Error("Streaming execution not completed"),
executionTime: 0,
taskResults: /* @__PURE__ */ new Map()
};
})();
return {
stream: this.createDynamicExecutionStream(input),
getResult: () => resultPromise
};
}
async *createDynamicExecutionStream(input) {
this.startTime = Date.now();
this.dynamicTasksGenerated = 0;
this.currentStep = 0;
this.usedStrategies.clear();
try {
Object.entries(input).forEach(([key, value]) => {
this.context.set(key, value);
});
yield {
type: "progress",
taskName: "workflow",
content: "Dynamic workflow execution started",
progress: 0,
timestamp: Date.now()
};
while (this.hasTasksToExecute() && this.shouldContinue()) {
this.currentStep++;
yield {
type: "progress",
taskName: "workflow",
content: `Executing step ${this.currentStep}`,
progress: Math.min(
this.currentStep / (this.config.maxDynamicSteps || 50) * 100,
90
),
timestamp: Date.now()
};
const readyTasks = this.getReadyTasks();
for (const task of readyTasks) {
yield* this.executeTaskStreamForStrategy(task);
}
await this.evaluateStrategiesAndGenerateTasks();
if (this.dynamicTasksGenerated > 0) {
yield {
type: "data",
taskName: "strategy",
content: `Dynamically generated ${this.dynamicTasksGenerated} new tasks`,
timestamp: Date.now()
};
}
}
const result = {
success: true,
data: this.context.getAll(),
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults,
dynamicTasksGenerated: this.dynamicTasksGenerated,
totalSteps: this.currentStep
};
this.streamResult = result;
yield {
type: "complete",
taskName: "workflow",
content: "Dynamic workflow execution completed",
progress: 100,
timestamp: Date.now()
};
return result;
} catch (error) {
const errorResult = {
success: false,
error,
executionTime: Date.now() - this.startTime,
taskResults: this.taskResults,
dynamicTasksGenerated: this.dynamicTasksGenerated,
totalSteps: this.currentStep
};
this.streamResult = errorResult;
yield {
type: "error",
taskName: "workflow",
content: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
return errorResult;
}
}
async *executeTaskStreamForStrategy(task) {
const taskStartTime = Date.now();
try {
yield {
type: "progress",
taskName: task.name,
content: `Starting dynamic task execution: ${task.name}`,
progress: 0,
timestamp: Date.now()
};
const input = this.context.getAll();
let output;
if (task.isStreaming && task.executeStream) {
const generator = task.executeStream(input);
let finalResult = {};
try {
while (true) {
const { value, done } = await generator.next();
if (done) {
finalResult = value || {};
break;
}
yield value;
}
} catch (error) {
throw error;
}
output = finalResult;
} else {
output = await task.execute(input);
}
const taskName = task.name || "";
this.context.set(taskName, output);
for (const [key, value] of Object.entries(output)) {
this.context.set(key, value);
}
let uniqueKey = taskName;
let counter = 1;
while (this.taskResults.has(uniqueKey)) {
uniqueKey = `${taskName}_${counter}`;
counter++;
}
const result = {
taskName,
status: "completed",
output,
duration: Date.now() - taskStartTime,
timestamp: Date.now()
};
this.taskResults.set(uniqueKey, result);
this.context.addExecutionResult(result);
yield {
type: "complete",
taskName: task.name,
content: `Dynamic task completed: ${task.name}`,
progress: 100,
timestamp: Date.now(),
metadata: { duration: result.duration }
};
} catch (error) {
console.warn("Dynamic task execution failed:", error);
const taskName = task.name || "";
let uniqueKey = taskName;
let counter = 1;
while (this.taskResults.has(uniqueKey)) {
uniqueKey = `${taskName}_${counter}`;
counter++;
}
const result = {
taskName,
status: "failed",
error: error instanceof Error ? error.message : String(error),
duration: Date.now() - taskStartTime,
timestamp: Date.now()
};
this.taskResults.set(uniqueKey, result);
this.context.addExecutionResult(result);
yield {
type: "error",
taskName: task.name,
content: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
}
}
class AISDKStreamingStaticWorkflow extends StaticWorkflow {
executeStreamAISDK(input = {}) {
const resultPromise = this.execute(input);
const combinedStreams = this.createCombinedAISDKStreams(input);
return {
textStream: combinedStreams.textStream,
fullStream: combinedStreams.fullStream,
toDataStreamResponse: () => combinedStreams.toDataStreamResponse(),
toReadableStream: () => combinedStreams.toReadableStream(),
getResult: () => resultPromise
};
}
createCombinedAISDKStreams(input) {
const textChunks = [];
const dataChunks = [];
const self = this;
const textStreamGenerator = async function* () {
try {
Object.entries(input).forEach(([key, value]) => {
self.context.set(key, value);
});
const levels = self.computeExecutionLevels();
for (const level of levels) {
for (const task of level) {
const aiTask = task;
if (aiTask.isAISDKStreaming && aiTask.executeStreamAI) {
const streamResult = await aiTask.executeStreamAI(
self.context.getAll()
);
if (streamResult.textStream) {
for await (const chunk of streamResult.textStream) {
textChunks.push(chunk);
yield chunk;
}
}
} else {
const statusText = `[${task.name}] Task completed
`;
textChunks.push(statusText);
yield statusText;
await self.executeTask(task);
}
}
}
} catch (error) {
const errorText = `Error: ${error instanceof Error ? error.message : String(error)}
`;
textChunks.push(errorText);
yield errorText;
}
};
const fullStreamGenerator = async function* () {
try {
Object.entries(input).forEach(([key, value]) => {
self.context.set(key, value);
});
yield { type: "workflow-start", data: { status: "starting" } };
const levels = self.computeExecutionLevels();
for (const level of levels) {
for (const task of level) {
const aiTask = task;
yield { type: "task-start", data: { taskName: task.name } };
if (aiTask.isAISDKStreaming && aiTask.executeStreamAI) {
const streamResult = await aiTask.executeStreamAI(
self.context.getAll()
);
if (streamResult.fullStream) {
for await (const chunk of streamResult.fullStream) {
dataChunks.push(chunk);
yield { type: "ai-chunk", data: chunk };
}
}
} else {
await self.executeTask(task);
yield {
type: "task-complete",
data: {
taskName: task.name,
result: self.context.get(task.name)
}
};
}
}
}
yield {
type: "workflow-complete",
data: {
status: "completed",
finalResult: self.context.getAll()
}
};
} catch (error) {
yield {
type: "workflow-error",
data: {
error: error instanceof Error ? error.message : String(error)
}
};
}
};
return {
get textStream() {
return textStreamGenerator();
},
get fullStream() {
return fullStreamGenerator();
},
toDataStreamResponse() {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
try {
for await (const chunk of fullStreamGenerator()) {
const data = `data: ${JSON.stringify(chunk)}
`;
controller.enqueue(encoder.encode(data));
}
controller.close();
} catch (error) {
controller.error(error);
}
}
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive"
}
});
},
toReadableStream() {
const encoder = new TextEncoder();
return new ReadableStream({
async start(controller) {
try {
for await (const textChunk of textStreamGenerator()) {
controller.enqueue(encoder.encode(textChunk));
}
controller.close();
} catch (error) {
controller.error(error);
}
}
});
}
};
}
}
class AISDKStreamingStrategyWorkflow extends StrategyBasedWorkflow {
executeStreamAISDK(input = {}) {
const resultPromise = this.execute(input);
const combinedStreams = this.createDynamicCombinedAISDKStreams(input);
return {
textStream: combinedStreams.textStream,
fullStream: combinedStreams.fullStream,
toDataStreamResponse: () => combinedStreams.toDataStreamResponse(),
toReadableStream: () => combinedStreams.toReadableStream(),
getResult: () => resultPromise
};
}
createDynamicCombinedAISDKStreams(input) {
const textChunks = [];
const dataChunks = [];
const self = this;
const textStreamGenerator = async function* () {
try {
Object.entries(input).forEach(([key, value]) => {
self.context.set(key, value);
});
self.currentStep = 0;
self.dynamicTasksGenerated = 0;
self.usedStrategies.clear();
while (self.hasTasksToExecute() && self.shouldContinue()) {
self.currentStep++;
const readyTasks = self.getReadyTasks();
for (const task of readyTasks) {
const aiTask = task;
if (aiTask.isAISDKStreaming && aiTask.executeStreamAI) {
const streamResult = await aiTask.executeStreamAI(
self.context.getAll()
);
if (streamResult.textStream) {
for await (const chunk of streamResult.textStream) {
textChunks.push(chunk);
yield chunk;
}
}
} else {
const statusText = `[${task.name}] Task completed
`;
textChunks.push(statusText);
yield statusText;
await self.executeTask(task);
}
}
await self.evaluateStrategiesAndGenerateTasks();
}
} catch (error) {
const errorText = `Error: ${error instanceof Error ? error.message : String(error)}
`;
textChunks.push(errorText);
yield errorText;
}
};
const fullStreamGenerator = async function* () {
try {
Object.entries(input).forEach(([key, value]) => {
self.context.set(key, value);
});
yield { type: "dynamic-workflow-start", data: { status: "starting" } };
self.currentStep = 0;
self.dynamicTasksGenerated = 0;
self.usedStrategies.clear();
while (self.hasTasksToExecute() && self.shouldContinue()) {
self.currentStep++;
yield {
type: "dynamic-step",
data: {
step: self.currentStep,
maxSteps: self.config.maxDynamicSteps || 50
}
};
const readyTasks = self.getReadyTasks();
for (const task of readyTasks) {
const aiTask = task;
yield { type: "task-start", data: { taskName: task.name } };
if (aiTask.isAISDKStreaming && aiTask.executeStreamAI) {
const streamResult = await aiTask.executeStreamAI(
self.context.getAll()
);
if (streamResult.fullStream) {
for await (const chunk of streamResult.fullStream) {
dataChunks.push(chunk);
yield { type: "ai-chunk", data: chunk };
}
}
} else {
await self.executeTask(task);
yield {
type: "task-complete",
data: {
taskName: task.name,
result: self.context.get(task.name)
}
};
}
}
const beforeCount = self.tasks.length;
await self.evaluateStrategiesAndGenerateTasks();
const afterCount = self.tasks.length;
if (afterCount > beforeCount) {
yield {
type: "dynamic-tasks-generated",
data: {
newTasks: afterCount - beforeCount,
totalGenerated: self.dynamicTasksGenerated
}
};
}
}
yield {
type: "dynamic-workflow-complete",
data: {
status: "completed",
totalSteps: self.currentStep,
dynamicTasksGenerated: self.dynamicTasksGenerated,
finalResult: self.context.getAll()
}
};
} catch (error) {
yield {
type: "dynamic-workflow-error",
data: {
error: error instanceof Error ? error.message : String(error)
}
};
}
};
return {
get textStream() {
return textStreamGenerator();
},
get fullStream() {
return fullStreamGenerator();
},
toDataStreamResponse() {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
try {
for await (const chunk of fullStreamGenerator()) {
const data = `data: ${JSON.stringify(chunk)}
`;
controller.enqueue(encoder.encode(data));
}
controller.close();
} catch (error) {
controller.error(error);
}
}
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive"
}
});
},
toReadableStream() {
const encoder = new TextEncoder();
return new ReadableStream({
async start(controller) {
try {
for await (const textChunk of textStreamGenerator()) {
controller.enqueue(encoder.encode(textChunk));
}
controller.close();
} catch (error) {
controller.error(error);
}
}
});
}
};
}
}
class TaskRegistry {
constructor() {
this.tasks = /* @__PURE__ */ new Map();
}
static getInstance() {
if (!TaskRegistry.instance) {
TaskRegistry.instance = new TaskRegistry();
}
return TaskRegistry.instance;
}
registerTask(definition) {
this.tasks.set(definition.name, definition);
}
getTask(name) {
return this.tasks.get(name);
}
getAllTasks() {
return Array.from(this.tasks.values());
}
getTasksByCapability(capability) {
return this.getAllTasks().filter(
(task) => task.capabilities.includes(capability)
);
}
clear() {
this.tasks.clear();
}
}
export {
AISDKStreamingTask,
ContextManager,
DAGTask,
StreamingDAGTask,
TaskRegistry,
WorkflowBuilder
};
//# sourceMappingURL=agent-workflow.js.map