@nebulaos/core 0.1.1
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 +206 -0
- package/dist/__tests__/mocks/mock-provider.d.ts +15 -0
- package/dist/__tests__/mocks/mock-provider.js +44 -0
- package/dist/agent/Agent.d.ts +96 -0
- package/dist/agent/Agent.js +861 -0
- package/dist/agent/BaseAgent.d.ts +53 -0
- package/dist/agent/BaseAgent.js +126 -0
- package/dist/agent/events/events.d.ts +14 -0
- package/dist/agent/events/events.js +2 -0
- package/dist/agent/events/events.spec.d.ts +1 -0
- package/dist/agent/events/events.spec.js +75 -0
- package/dist/agent/instruction/index.d.ts +23 -0
- package/dist/agent/instruction/index.js +76 -0
- package/dist/agent/memory/in-memory.d.ts +24 -0
- package/dist/agent/memory/in-memory.js +78 -0
- package/dist/agent/memory/index.d.ts +2 -0
- package/dist/agent/memory/index.js +18 -0
- package/dist/agent/memory/memory.d.ts +43 -0
- package/dist/agent/memory/memory.js +7 -0
- package/dist/agent/provider/file-parts.spec.d.ts +1 -0
- package/dist/agent/provider/file-parts.spec.js +83 -0
- package/dist/agent/provider/index.d.ts +130 -0
- package/dist/agent/provider/index.js +8 -0
- package/dist/agent/skills/index.d.ts +61 -0
- package/dist/agent/skills/index.js +9 -0
- package/dist/agent/tools/index.d.ts +35 -0
- package/dist/agent/tools/index.js +87 -0
- package/dist/cost/add-cost.d.ts +10 -0
- package/dist/cost/add-cost.js +80 -0
- package/dist/cost/add-cost.spec.d.ts +1 -0
- package/dist/cost/add-cost.spec.js +36 -0
- package/dist/cost/index.d.ts +1 -0
- package/dist/cost/index.js +17 -0
- package/dist/domain-events/index.d.ts +16 -0
- package/dist/domain-events/index.js +38 -0
- package/dist/eval/index.d.ts +19 -0
- package/dist/eval/index.js +24 -0
- package/dist/events/base.d.ts +5 -0
- package/dist/events/base.js +2 -0
- package/dist/events/schemas.d.ts +3463 -0
- package/dist/events/schemas.js +244 -0
- package/dist/execution-context/index.d.ts +21 -0
- package/dist/execution-context/index.js +17 -0
- package/dist/index.cjs +2958 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3425 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/lgpd/index.d.ts +7 -0
- package/dist/lgpd/index.js +21 -0
- package/dist/logger/agent-logger.d.ts +16 -0
- package/dist/logger/agent-logger.js +110 -0
- package/dist/logger/formatters.d.ts +32 -0
- package/dist/logger/formatters.js +146 -0
- package/dist/logger/index.d.ts +30 -0
- package/dist/logger/index.js +88 -0
- package/dist/logger/styles.d.ts +46 -0
- package/dist/logger/styles.js +53 -0
- package/dist/logger/workflow-logger.d.ts +16 -0
- package/dist/logger/workflow-logger.js +79 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.d.ts +16 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.js +54 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.spec.d.ts +1 -0
- package/dist/multi-agent/agent-as-tool/AgentAsTool.spec.js +76 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.d.ts +16 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.js +150 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.spec.d.ts +1 -0
- package/dist/multi-agent/committee-team/CommitteeTeam.spec.js +43 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.d.ts +16 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.js +185 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.spec.d.ts +1 -0
- package/dist/multi-agent/handoff-team/HandoffTeam.spec.js +105 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.d.ts +18 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.js +164 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.spec.d.ts +1 -0
- package/dist/multi-agent/hierarchical-team/HierarchicalTeam.spec.js +53 -0
- package/dist/multi-agent/index.d.ts +10 -0
- package/dist/multi-agent/index.js +26 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.d.ts +13 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.js +104 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.spec.d.ts +1 -0
- package/dist/multi-agent/pipeline-team/PipelineTeam.spec.js +54 -0
- package/dist/multi-agent/router-team/RouterTeam.d.ts +15 -0
- package/dist/multi-agent/router-team/RouterTeam.js +153 -0
- package/dist/multi-agent/router-team/RouterTeam.spec.d.ts +1 -0
- package/dist/multi-agent/router-team/RouterTeam.spec.js +69 -0
- package/dist/multi-agent/types/index.d.ts +349 -0
- package/dist/multi-agent/types/index.js +79 -0
- package/dist/multi-agent/utils/guardrails.d.ts +6 -0
- package/dist/multi-agent/utils/guardrails.js +34 -0
- package/dist/multi-agent/utils/memory.d.ts +8 -0
- package/dist/multi-agent/utils/memory.js +40 -0
- package/dist/multi-agent/utils/prompts.d.ts +4 -0
- package/dist/multi-agent/utils/prompts.js +25 -0
- package/dist/tracing/index.d.ts +89 -0
- package/dist/tracing/index.js +188 -0
- package/dist/tsup.config.d.ts +2 -0
- package/dist/tsup.config.js +11 -0
- package/dist/utils/schema-to-zod.d.ts +7 -0
- package/dist/utils/schema-to-zod.js +36 -0
- package/dist/workflow/Workflow.d.ts +106 -0
- package/dist/workflow/Workflow.js +204 -0
- package/dist/workflow/adapters.d.ts +61 -0
- package/dist/workflow/adapters.js +29 -0
- package/dist/workflow/definition/DefinitionBuilder.d.ts +9 -0
- package/dist/workflow/definition/DefinitionBuilder.js +91 -0
- package/dist/workflow/definition/DefinitionBuilder.spec.d.ts +1 -0
- package/dist/workflow/definition/DefinitionBuilder.spec.js +66 -0
- package/dist/workflow/definition/DefinitionHasher.d.ts +8 -0
- package/dist/workflow/definition/DefinitionHasher.js +11 -0
- package/dist/workflow/definition/DefinitionHasher.spec.d.ts +1 -0
- package/dist/workflow/definition/DefinitionHasher.spec.js +28 -0
- package/dist/workflow/definition/types.d.ts +27 -0
- package/dist/workflow/definition/types.js +2 -0
- package/dist/workflow/events.d.ts +9 -0
- package/dist/workflow/events.js +2 -0
- package/dist/workflow/execution/AgentNodeIntegration.spec.d.ts +1 -0
- package/dist/workflow/execution/AgentNodeIntegration.spec.js +50 -0
- package/dist/workflow/execution/NodeExecutor.d.ts +9 -0
- package/dist/workflow/execution/NodeExecutor.js +43 -0
- package/dist/workflow/execution/NodeExecutor.spec.d.ts +1 -0
- package/dist/workflow/execution/NodeExecutor.spec.js +45 -0
- package/dist/workflow/execution/WorkflowEventBus.d.ts +14 -0
- package/dist/workflow/execution/WorkflowEventBus.js +42 -0
- package/dist/workflow/execution/WorkflowEventBus.spec.d.ts +1 -0
- package/dist/workflow/execution/WorkflowEventBus.spec.js +78 -0
- package/dist/workflow/execution/WorkflowRunner.d.ts +26 -0
- package/dist/workflow/execution/WorkflowRunner.js +212 -0
- package/dist/workflow/execution/WorkflowRunner.spec.d.ts +1 -0
- package/dist/workflow/execution/WorkflowRunner.spec.js +92 -0
- package/dist/workflow/execution/WorkflowTelemetry.d.ts +13 -0
- package/dist/workflow/execution/WorkflowTelemetry.js +43 -0
- package/dist/workflow/execution/WorkflowTelemetry.spec.d.ts +1 -0
- package/dist/workflow/execution/WorkflowTelemetry.spec.js +31 -0
- package/dist/workflow/graph/NodeNameRegistry.d.ts +20 -0
- package/dist/workflow/graph/NodeNameRegistry.js +21 -0
- package/dist/workflow/graph/NodeNameRegistry.spec.d.ts +1 -0
- package/dist/workflow/graph/NodeNameRegistry.spec.js +18 -0
- package/dist/workflow/graph/WorkflowGraph.d.ts +14 -0
- package/dist/workflow/graph/WorkflowGraph.js +23 -0
- package/dist/workflow/graph/nodes.d.ts +26 -0
- package/dist/workflow/graph/nodes.js +2 -0
- package/dist/workflow/queue/WorkflowQueueService.d.ts +22 -0
- package/dist/workflow/queue/WorkflowQueueService.js +47 -0
- package/dist/workflow/state/WorkflowStateService.d.ts +7 -0
- package/dist/workflow/state/WorkflowStateService.js +20 -0
- package/dist/workflow/types.d.ts +16 -0
- package/dist/workflow/types.js +2 -0
- package/package.json +56 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Tracing = exports.ActiveSpan = void 0;
|
|
4
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// ActiveSpan
|
|
8
|
+
// =============================================================================
|
|
9
|
+
class ActiveSpan {
|
|
10
|
+
traceId;
|
|
11
|
+
spanId;
|
|
12
|
+
parentSpanId;
|
|
13
|
+
kind;
|
|
14
|
+
name;
|
|
15
|
+
correlationId;
|
|
16
|
+
executionId;
|
|
17
|
+
exporter;
|
|
18
|
+
ended = false;
|
|
19
|
+
constructor(traceId, spanId, parentSpanId, kind, name, correlationId, executionId, exporter) {
|
|
20
|
+
this.traceId = traceId;
|
|
21
|
+
this.spanId = spanId;
|
|
22
|
+
this.parentSpanId = parentSpanId;
|
|
23
|
+
this.kind = kind;
|
|
24
|
+
this.name = name;
|
|
25
|
+
this.correlationId = correlationId;
|
|
26
|
+
this.executionId = executionId;
|
|
27
|
+
this.exporter = exporter;
|
|
28
|
+
}
|
|
29
|
+
async end(input) {
|
|
30
|
+
if (this.ended)
|
|
31
|
+
return;
|
|
32
|
+
this.ended = true;
|
|
33
|
+
const event = {
|
|
34
|
+
v: 1,
|
|
35
|
+
type: "telemetry:span:end",
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
|
+
trace: {
|
|
38
|
+
traceId: this.traceId,
|
|
39
|
+
spanId: this.spanId,
|
|
40
|
+
parentSpanId: this.parentSpanId,
|
|
41
|
+
},
|
|
42
|
+
correlationId: this.correlationId,
|
|
43
|
+
executionId: this.executionId,
|
|
44
|
+
status: input.status,
|
|
45
|
+
span: {
|
|
46
|
+
kind: this.kind,
|
|
47
|
+
name: this.name,
|
|
48
|
+
// The contract expects a kind-specific shape, but we keep this generic here.
|
|
49
|
+
// The callers are responsible for providing kind-specific keys.
|
|
50
|
+
data: input.data,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
try {
|
|
54
|
+
await this.exporter.exportBatch([event]);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Telemetry must never break execution.
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
get isEnded() {
|
|
61
|
+
return this.ended;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.ActiveSpan = ActiveSpan;
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// Internal helpers
|
|
67
|
+
// =============================================================================
|
|
68
|
+
const storage = new node_async_hooks_1.AsyncLocalStorage();
|
|
69
|
+
/** Generate a W3C-compliant trace ID (32 hex chars). */
|
|
70
|
+
function generateTraceId() {
|
|
71
|
+
return (0, node_crypto_1.randomBytes)(16).toString("hex");
|
|
72
|
+
}
|
|
73
|
+
/** Generate a W3C-compliant span ID (16 hex chars). */
|
|
74
|
+
function generateSpanId() {
|
|
75
|
+
return (0, node_crypto_1.randomBytes)(8).toString("hex");
|
|
76
|
+
}
|
|
77
|
+
class NoopTelemetryExporter {
|
|
78
|
+
async exportBatch(_events) {
|
|
79
|
+
// noop
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// =============================================================================
|
|
83
|
+
// Tracing (static facade)
|
|
84
|
+
// =============================================================================
|
|
85
|
+
class Tracing {
|
|
86
|
+
static exporter = new NoopTelemetryExporter();
|
|
87
|
+
static provider = null;
|
|
88
|
+
static setExporter(exporter) {
|
|
89
|
+
this.exporter = exporter;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Injects an external tracing provider (e.g. OpenTelemetry).
|
|
93
|
+
* When set, `getContext()` and `withSpan()` delegate to the provider
|
|
94
|
+
* so that span IDs originate from OTel and the hierarchy is preserved.
|
|
95
|
+
*/
|
|
96
|
+
static setProvider(provider) {
|
|
97
|
+
this.provider = provider;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Gets the current trace context.
|
|
101
|
+
* Returns undefined if called outside of a traced execution.
|
|
102
|
+
*/
|
|
103
|
+
static getContext() {
|
|
104
|
+
if (this.provider) {
|
|
105
|
+
return this.provider.getContext();
|
|
106
|
+
}
|
|
107
|
+
return storage.getStore();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Gets the current trace context or creates a dummy one if none exists.
|
|
111
|
+
* Useful for logging where you always want *some* ID.
|
|
112
|
+
*/
|
|
113
|
+
static getContextOrDummy() {
|
|
114
|
+
const context = this.getContext();
|
|
115
|
+
if (context)
|
|
116
|
+
return context;
|
|
117
|
+
return {
|
|
118
|
+
traceId: "no-trace",
|
|
119
|
+
spanId: "no-span",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Runs a function inside a new telemetry span and exports span lifecycle events.
|
|
124
|
+
*
|
|
125
|
+
* When a provider is set, delegates entirely to the provider so that the
|
|
126
|
+
* span IDs come from the external tracing system (e.g. OpenTelemetry).
|
|
127
|
+
* Otherwise, falls back to the built-in implementation that uses the
|
|
128
|
+
* ITelemetryExporter.
|
|
129
|
+
*/
|
|
130
|
+
static async withSpan(input, fn) {
|
|
131
|
+
if (this.provider) {
|
|
132
|
+
return this.provider.withSpan(input, fn);
|
|
133
|
+
}
|
|
134
|
+
return this.defaultWithSpan(input, fn);
|
|
135
|
+
}
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// Default (built-in) implementation – used when no provider is set
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
static async defaultWithSpan(input, fn) {
|
|
140
|
+
const parent = storage.getStore();
|
|
141
|
+
const traceId = parent?.traceId ?? generateTraceId();
|
|
142
|
+
const parentSpanId = parent?.spanId;
|
|
143
|
+
const spanId = generateSpanId();
|
|
144
|
+
const startedAt = new Date().toISOString();
|
|
145
|
+
const startEvent = {
|
|
146
|
+
v: 1,
|
|
147
|
+
type: "telemetry:span:start",
|
|
148
|
+
timestamp: startedAt,
|
|
149
|
+
trace: {
|
|
150
|
+
traceId,
|
|
151
|
+
spanId,
|
|
152
|
+
parentSpanId,
|
|
153
|
+
},
|
|
154
|
+
correlationId: input.correlationId,
|
|
155
|
+
executionId: input.executionId,
|
|
156
|
+
span: {
|
|
157
|
+
kind: input.kind,
|
|
158
|
+
name: input.name,
|
|
159
|
+
data: (input.data ?? {}),
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
try {
|
|
163
|
+
await this.exporter.exportBatch([startEvent]);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Telemetry must never break execution.
|
|
167
|
+
}
|
|
168
|
+
const context = {
|
|
169
|
+
traceId,
|
|
170
|
+
spanId,
|
|
171
|
+
parentId: parentSpanId,
|
|
172
|
+
};
|
|
173
|
+
const activeSpan = new ActiveSpan(traceId, spanId, parentSpanId, input.kind, input.name, input.correlationId, input.executionId, this.exporter);
|
|
174
|
+
return storage.run(context, async () => {
|
|
175
|
+
try {
|
|
176
|
+
const result = await fn(activeSpan);
|
|
177
|
+
if (!activeSpan.isEnded)
|
|
178
|
+
await activeSpan.end({ status: "success" });
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
await activeSpan.end({ status: "error" });
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
exports.Tracing = Tracing;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tsup_1 = require("tsup");
|
|
4
|
+
exports.default = (0, tsup_1.defineConfig)({
|
|
5
|
+
entry: ["index.ts"],
|
|
6
|
+
format: ["cjs", "esm"],
|
|
7
|
+
dts: true,
|
|
8
|
+
splitting: false,
|
|
9
|
+
sourcemap: true,
|
|
10
|
+
clean: true,
|
|
11
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.schemaToZod = schemaToZod;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
function schemaToZod(shape) {
|
|
6
|
+
const zodShape = {};
|
|
7
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
8
|
+
if (typeof value === 'string') {
|
|
9
|
+
let schema = zod_1.z.any();
|
|
10
|
+
const isOptional = value.endsWith('?');
|
|
11
|
+
const type = isOptional ? value.slice(0, -1) : value;
|
|
12
|
+
switch (type) {
|
|
13
|
+
case 'string':
|
|
14
|
+
schema = zod_1.z.string();
|
|
15
|
+
break;
|
|
16
|
+
case 'number':
|
|
17
|
+
schema = zod_1.z.number();
|
|
18
|
+
break;
|
|
19
|
+
case 'boolean':
|
|
20
|
+
schema = zod_1.z.boolean();
|
|
21
|
+
break;
|
|
22
|
+
case 'array':
|
|
23
|
+
schema = zod_1.z.array(zod_1.z.any());
|
|
24
|
+
break; // Simplificado
|
|
25
|
+
default: schema = zod_1.z.any();
|
|
26
|
+
}
|
|
27
|
+
if (isOptional)
|
|
28
|
+
schema = schema.optional();
|
|
29
|
+
zodShape[key] = schema;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
zodShape[key] = value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return zod_1.z.object(zodShape);
|
|
36
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { ZodSchema } from "zod";
|
|
2
|
+
import type { Agent } from "../agent/Agent.js";
|
|
3
|
+
import type { IWorkflowQueue, IWorkflowStateStore, RetryPolicy, WorkflowState } from "./adapters.js";
|
|
4
|
+
import type { WorkflowEventMap, WorkflowEventName } from "./events.js";
|
|
5
|
+
import type { WorkflowAgentNodeOptions, WorkflowNodeHandler, WorkflowRunOptions } from "./types.js";
|
|
6
|
+
import type { WorkflowDefinition } from "./definition/types.js";
|
|
7
|
+
import { SharedNodeNameRegistry } from "./graph/NodeNameRegistry.js";
|
|
8
|
+
import type { InternalNode } from "./graph/nodes.js";
|
|
9
|
+
export interface WorkflowConfig<Input = any, Output = any> {
|
|
10
|
+
id: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
inputSchema?: ZodSchema<Input>;
|
|
14
|
+
outputSchema?: ZodSchema<Output>;
|
|
15
|
+
maxSteps?: number;
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
stateStore?: IWorkflowStateStore;
|
|
18
|
+
queueAdapter?: IWorkflowQueue;
|
|
19
|
+
retryPolicy?: RetryPolicy;
|
|
20
|
+
logLevel?: "debug" | "info" | "warn" | "error" | "none";
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
* The root workflow ID for sub-workflows (parallel/branch).
|
|
24
|
+
* Used to ensure all events are emitted with the registered workflow ID.
|
|
25
|
+
*/
|
|
26
|
+
rootWorkflowId?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class Workflow<Input = any, Output = any> {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly name?: string;
|
|
31
|
+
readonly description?: string;
|
|
32
|
+
private readonly config;
|
|
33
|
+
private readonly emitter;
|
|
34
|
+
private readonly events;
|
|
35
|
+
private readonly graph;
|
|
36
|
+
private readonly stateService;
|
|
37
|
+
private readonly telemetry;
|
|
38
|
+
private readonly nodeExecutor;
|
|
39
|
+
private readonly runner;
|
|
40
|
+
private readonly queue;
|
|
41
|
+
private cachedDefinition?;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the workflow ID to use for events and telemetry.
|
|
44
|
+
* For sub-workflows (parallel/branch), this returns the root workflow ID.
|
|
45
|
+
*/
|
|
46
|
+
get registeredWorkflowId(): string;
|
|
47
|
+
constructor(config: WorkflowConfig<Input, Output>, internal?: {
|
|
48
|
+
registry?: SharedNodeNameRegistry;
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Exports a stable workflow graph definition suitable for visualization.
|
|
52
|
+
*/
|
|
53
|
+
describe(): WorkflowDefinition;
|
|
54
|
+
private allocateNodeId;
|
|
55
|
+
start<TOut = Input>(name: string, handler: WorkflowNodeHandler<Input, TOut>): this;
|
|
56
|
+
step<TIn = any, TOut = any>(name: string, handler: WorkflowNodeHandler<TIn, TOut>): this;
|
|
57
|
+
/**
|
|
58
|
+
* Adds an agent as a first-class node in the workflow graph.
|
|
59
|
+
*/
|
|
60
|
+
agent(name: string, agent: Agent, options?: WorkflowAgentNodeOptions): this;
|
|
61
|
+
/**
|
|
62
|
+
* Branch node. The selector returns the branch key to execute.
|
|
63
|
+
*/
|
|
64
|
+
branch<TIn = any>(name: string, selector: WorkflowNodeHandler<TIn, string>, branches: Record<string, (wf: Workflow<TIn, any>) => void>): this;
|
|
65
|
+
/**
|
|
66
|
+
* Parallel node. Executes multiple sub-workflows concurrently and returns an array of outputs.
|
|
67
|
+
*/
|
|
68
|
+
parallel<TIn = any>(name: string, workflows: Array<(wf: Workflow<TIn, any>) => void>): this;
|
|
69
|
+
finish(name: string, handler: WorkflowNodeHandler<any, Output>): this;
|
|
70
|
+
on<E extends WorkflowEventName>(event: E, listener: (data: WorkflowEventMap[E]) => void): this;
|
|
71
|
+
once<E extends WorkflowEventName>(event: E, listener: (data: WorkflowEventMap[E]) => void): this;
|
|
72
|
+
off<E extends WorkflowEventName>(event: E, listener: (data: WorkflowEventMap[E]) => void): this;
|
|
73
|
+
run(input: Input, options?: WorkflowRunOptions): Promise<Output>;
|
|
74
|
+
enqueue(input: Input): Promise<{
|
|
75
|
+
executionId: string;
|
|
76
|
+
}>;
|
|
77
|
+
getStatus(executionId: string): Promise<{
|
|
78
|
+
status: WorkflowState["status"];
|
|
79
|
+
currentStep?: string;
|
|
80
|
+
progress?: number;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* @internal
|
|
84
|
+
* Exposes the internal node list for definition traversal (read-only).
|
|
85
|
+
*/
|
|
86
|
+
__internalNodes(): readonly InternalNode[];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* @internal
|
|
90
|
+
* Exposes internal nodes for DefinitionBuilder (read-only).
|
|
91
|
+
*/
|
|
92
|
+
export interface WorkflowInternalAccess {
|
|
93
|
+
__internalNodes(): readonly InternalNode[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* @internal
|
|
97
|
+
* Used by DefinitionBuilder to traverse the graph without breaking encapsulation.
|
|
98
|
+
*/
|
|
99
|
+
export interface WorkflowInternalNodeAccess {
|
|
100
|
+
__internalNodes(): readonly InternalNode[];
|
|
101
|
+
}
|
|
102
|
+
export declare class WorkflowInternal {
|
|
103
|
+
static nodes(wf: Workflow<any, any>): readonly InternalNode[];
|
|
104
|
+
}
|
|
105
|
+
export type { WorkflowNodeHandler, WorkflowRunOptions, WorkflowAgentNodeOptions } from "./types.js";
|
|
106
|
+
export type { WorkflowDefinition, WorkflowDefinitionNode, WorkflowDefinitionEdge, WorkflowNodeType, } from "./definition/types.js";
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WorkflowInternal = exports.Workflow = void 0;
|
|
4
|
+
const node_events_1 = require("node:events");
|
|
5
|
+
const index_js_1 = require("../logger/index.js");
|
|
6
|
+
const DefinitionBuilder_js_1 = require("./definition/DefinitionBuilder.js");
|
|
7
|
+
const DefinitionHasher_js_1 = require("./definition/DefinitionHasher.js");
|
|
8
|
+
const NodeNameRegistry_js_1 = require("./graph/NodeNameRegistry.js");
|
|
9
|
+
const WorkflowGraph_js_1 = require("./graph/WorkflowGraph.js");
|
|
10
|
+
const WorkflowEventBus_js_1 = require("./execution/WorkflowEventBus.js");
|
|
11
|
+
const WorkflowTelemetry_js_1 = require("./execution/WorkflowTelemetry.js");
|
|
12
|
+
const WorkflowStateService_js_1 = require("./state/WorkflowStateService.js");
|
|
13
|
+
const NodeExecutor_js_1 = require("./execution/NodeExecutor.js");
|
|
14
|
+
const WorkflowRunner_js_1 = require("./execution/WorkflowRunner.js");
|
|
15
|
+
const WorkflowQueueService_js_1 = require("./queue/WorkflowQueueService.js");
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Workflow
|
|
18
|
+
// =============================================================================
|
|
19
|
+
class Workflow {
|
|
20
|
+
id;
|
|
21
|
+
name;
|
|
22
|
+
description;
|
|
23
|
+
config;
|
|
24
|
+
emitter = new node_events_1.EventEmitter();
|
|
25
|
+
events = new WorkflowEventBus_js_1.WorkflowEventBus(this.emitter);
|
|
26
|
+
graph;
|
|
27
|
+
stateService;
|
|
28
|
+
telemetry = new WorkflowTelemetry_js_1.WorkflowTelemetry();
|
|
29
|
+
nodeExecutor = new NodeExecutor_js_1.NodeExecutor();
|
|
30
|
+
runner;
|
|
31
|
+
queue;
|
|
32
|
+
cachedDefinition;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the workflow ID to use for events and telemetry.
|
|
35
|
+
* For sub-workflows (parallel/branch), this returns the root workflow ID.
|
|
36
|
+
*/
|
|
37
|
+
get registeredWorkflowId() {
|
|
38
|
+
return this.config.rootWorkflowId ?? this.id;
|
|
39
|
+
}
|
|
40
|
+
constructor(config, internal) {
|
|
41
|
+
this.config = config;
|
|
42
|
+
this.id = config.id;
|
|
43
|
+
this.name = config.name;
|
|
44
|
+
this.description = config.description;
|
|
45
|
+
const registry = internal?.registry ?? new NodeNameRegistry_js_1.SharedNodeNameRegistry();
|
|
46
|
+
this.graph = new WorkflowGraph_js_1.WorkflowGraph(registry);
|
|
47
|
+
this.stateService = new WorkflowStateService_js_1.WorkflowStateService(this.config.stateStore);
|
|
48
|
+
this.runner = new WorkflowRunner_js_1.WorkflowRunner(this.config, this.events, this.telemetry, this.stateService, this.nodeExecutor);
|
|
49
|
+
this.queue = new WorkflowQueueService_js_1.WorkflowQueueService(this.config.queueAdapter, this.stateService);
|
|
50
|
+
if (this.config.logLevel && this.config.logLevel !== "none") {
|
|
51
|
+
const logger = new index_js_1.ConsoleLogger(this.config.logLevel);
|
|
52
|
+
new index_js_1.WorkflowLogger(this, logger);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Definition / builder
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Exports a stable workflow graph definition suitable for visualization.
|
|
60
|
+
*/
|
|
61
|
+
describe() {
|
|
62
|
+
if (this.cachedDefinition)
|
|
63
|
+
return this.cachedDefinition;
|
|
64
|
+
const builder = new DefinitionBuilder_js_1.DefinitionBuilder();
|
|
65
|
+
const { nodes, edges } = builder.build(this);
|
|
66
|
+
const version = new DefinitionHasher_js_1.DefinitionHasher().hash({ workflowId: this.id, nodes, edges });
|
|
67
|
+
this.cachedDefinition = {
|
|
68
|
+
workflowId: this.id,
|
|
69
|
+
name: this.name,
|
|
70
|
+
description: this.description,
|
|
71
|
+
version,
|
|
72
|
+
nodes,
|
|
73
|
+
edges,
|
|
74
|
+
};
|
|
75
|
+
return this.cachedDefinition;
|
|
76
|
+
}
|
|
77
|
+
allocateNodeId(name) {
|
|
78
|
+
// Invalidate cached definition on any mutation.
|
|
79
|
+
this.cachedDefinition = undefined;
|
|
80
|
+
return this.graph.allocateId(name);
|
|
81
|
+
}
|
|
82
|
+
start(name, handler) {
|
|
83
|
+
const { id, displayName } = this.allocateNodeId(name);
|
|
84
|
+
this.graph.add({ id, displayName, type: "start", handler });
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
step(name, handler) {
|
|
88
|
+
const { id, displayName } = this.allocateNodeId(name);
|
|
89
|
+
this.graph.add({ id, displayName, type: "step", handler });
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Adds an agent as a first-class node in the workflow graph.
|
|
94
|
+
*/
|
|
95
|
+
agent(name, agent, options) {
|
|
96
|
+
const { id, displayName } = this.allocateNodeId(name);
|
|
97
|
+
this.graph.add({ id, displayName, type: "agent", agent, toInput: options?.toInput });
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Branch node. The selector returns the branch key to execute.
|
|
102
|
+
*/
|
|
103
|
+
branch(name, selector, branches) {
|
|
104
|
+
const { id, displayName } = this.allocateNodeId(name);
|
|
105
|
+
const branchWorkflows = {};
|
|
106
|
+
for (const [key, build] of Object.entries(branches)) {
|
|
107
|
+
const wf = new Workflow({ id: `${this.id}/branch/${key}`, rootWorkflowId: this.registeredWorkflowId }, { registry: this.graph.getRegistry() });
|
|
108
|
+
build(wf);
|
|
109
|
+
branchWorkflows[key] = wf;
|
|
110
|
+
}
|
|
111
|
+
this.graph.add({ id, displayName, type: "branch", selector, branches: branchWorkflows });
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parallel node. Executes multiple sub-workflows concurrently and returns an array of outputs.
|
|
116
|
+
*/
|
|
117
|
+
parallel(name, workflows) {
|
|
118
|
+
const { id, displayName } = this.allocateNodeId(name);
|
|
119
|
+
const parallelWorkflows = workflows.map((build, index) => {
|
|
120
|
+
const wf = new Workflow({ id: `${this.id}/parallel/${index}`, rootWorkflowId: this.registeredWorkflowId }, { registry: this.graph.getRegistry() });
|
|
121
|
+
build(wf);
|
|
122
|
+
return wf;
|
|
123
|
+
});
|
|
124
|
+
this.graph.add({ id, displayName, type: "parallel", workflows: parallelWorkflows });
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
finish(name, handler) {
|
|
128
|
+
const { id, displayName } = this.allocateNodeId(name);
|
|
129
|
+
this.graph.add({ id, displayName, type: "finish", handler });
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Event API
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
on(event, listener) {
|
|
136
|
+
this.events.on(event, listener);
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
once(event, listener) {
|
|
140
|
+
this.events.once(event, listener);
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
off(event, listener) {
|
|
144
|
+
this.events.off(event, listener);
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// Execution
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
async run(input, options = {}) {
|
|
151
|
+
if (this.config.inputSchema) {
|
|
152
|
+
const parsed = this.config.inputSchema.safeParse(input);
|
|
153
|
+
if (!parsed.success)
|
|
154
|
+
throw new Error(`Input validation failed: ${parsed.error.message}`);
|
|
155
|
+
}
|
|
156
|
+
const definition = this.describe();
|
|
157
|
+
const out = await this.runner.run({
|
|
158
|
+
workflowId: this.registeredWorkflowId,
|
|
159
|
+
workflowNameForTelemetry: `workflow:${this.id}`,
|
|
160
|
+
definition,
|
|
161
|
+
nodes: this.graph.list(),
|
|
162
|
+
input,
|
|
163
|
+
options,
|
|
164
|
+
});
|
|
165
|
+
return out;
|
|
166
|
+
}
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Queue (placeholder adapter wiring)
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
async enqueue(input) {
|
|
171
|
+
const definition = this.describe();
|
|
172
|
+
return this.queue.enqueue({
|
|
173
|
+
workflowId: this.registeredWorkflowId,
|
|
174
|
+
definition,
|
|
175
|
+
nodes: this.graph.list(),
|
|
176
|
+
rawInput: input,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
async getStatus(executionId) {
|
|
180
|
+
if (this.config.queueAdapter?.getStatus)
|
|
181
|
+
return this.config.queueAdapter.getStatus(executionId);
|
|
182
|
+
if (!this.config.stateStore)
|
|
183
|
+
throw new Error("Queue adapter or state store is required for getStatus()");
|
|
184
|
+
const state = await this.config.stateStore.load(executionId);
|
|
185
|
+
if (!state)
|
|
186
|
+
throw new Error(`Execution ${executionId} not found`);
|
|
187
|
+
return { status: state.status, currentStep: state.currentNodeId, progress: undefined };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* @internal
|
|
191
|
+
* Exposes the internal node list for definition traversal (read-only).
|
|
192
|
+
*/
|
|
193
|
+
__internalNodes() {
|
|
194
|
+
return this.graph.list();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
exports.Workflow = Workflow;
|
|
198
|
+
// Implementation for internal access (kept public but marked @internal)
|
|
199
|
+
class WorkflowInternal {
|
|
200
|
+
static nodes(wf) {
|
|
201
|
+
return wf.__internalNodes();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.WorkflowInternal = WorkflowInternal;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Adapters - Interfaces for State and Queue management
|
|
3
|
+
*/
|
|
4
|
+
export interface WorkflowState {
|
|
5
|
+
workflowId: string;
|
|
6
|
+
executionId: string;
|
|
7
|
+
definitionVersion: string;
|
|
8
|
+
status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'truncated';
|
|
9
|
+
currentNodeId?: string;
|
|
10
|
+
nodeStates: Record<string, {
|
|
11
|
+
status: 'pending' | 'running' | 'success' | 'error';
|
|
12
|
+
startedAt?: Date;
|
|
13
|
+
endedAt?: Date;
|
|
14
|
+
durationMs?: number;
|
|
15
|
+
attempt?: number;
|
|
16
|
+
input?: any;
|
|
17
|
+
output?: any;
|
|
18
|
+
error?: string;
|
|
19
|
+
}>;
|
|
20
|
+
input: any;
|
|
21
|
+
output?: any;
|
|
22
|
+
startedAt: Date;
|
|
23
|
+
updatedAt: Date;
|
|
24
|
+
completedAt?: Date;
|
|
25
|
+
error?: string;
|
|
26
|
+
retryCount?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface IWorkflowStateStore {
|
|
29
|
+
save(executionId: string, state: WorkflowState): Promise<void>;
|
|
30
|
+
load(executionId: string): Promise<WorkflowState | null>;
|
|
31
|
+
delete(executionId: string): Promise<void>;
|
|
32
|
+
listActive(workflowId?: string): Promise<string[]>;
|
|
33
|
+
}
|
|
34
|
+
export interface WorkflowJob {
|
|
35
|
+
executionId: string;
|
|
36
|
+
workflowId: string;
|
|
37
|
+
nodeId: string;
|
|
38
|
+
nodeName: string;
|
|
39
|
+
input: any;
|
|
40
|
+
attempt: number;
|
|
41
|
+
createdAt: Date;
|
|
42
|
+
}
|
|
43
|
+
export interface IWorkflowQueue {
|
|
44
|
+
enqueue(job: WorkflowJob): Promise<void>;
|
|
45
|
+
process(handler: (job: WorkflowJob) => Promise<void>): void;
|
|
46
|
+
close(): Promise<void>;
|
|
47
|
+
getStatus?(executionId: string): Promise<{
|
|
48
|
+
status: WorkflowState['status'];
|
|
49
|
+
currentStep?: string;
|
|
50
|
+
progress?: number;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
export interface RetryPolicy {
|
|
54
|
+
maxAttempts: number;
|
|
55
|
+
backoff: 'exponential' | 'linear' | 'fixed';
|
|
56
|
+
initialDelay: number;
|
|
57
|
+
maxDelay?: number;
|
|
58
|
+
retryableErrors?: string[];
|
|
59
|
+
}
|
|
60
|
+
export declare function calculateRetryDelay(policy: RetryPolicy, attempt: number): number;
|
|
61
|
+
export declare function isRetryableError(error: Error, policy: RetryPolicy): boolean;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Workflow Adapters - Interfaces for State and Queue management
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.calculateRetryDelay = calculateRetryDelay;
|
|
7
|
+
exports.isRetryableError = isRetryableError;
|
|
8
|
+
function calculateRetryDelay(policy, attempt) {
|
|
9
|
+
const { backoff, initialDelay, maxDelay = 60000 } = policy;
|
|
10
|
+
let delay;
|
|
11
|
+
switch (backoff) {
|
|
12
|
+
case 'exponential':
|
|
13
|
+
delay = initialDelay * Math.pow(2, attempt - 1);
|
|
14
|
+
break;
|
|
15
|
+
case 'linear':
|
|
16
|
+
delay = initialDelay * attempt;
|
|
17
|
+
break;
|
|
18
|
+
case 'fixed':
|
|
19
|
+
default:
|
|
20
|
+
delay = initialDelay;
|
|
21
|
+
}
|
|
22
|
+
return Math.min(delay, maxDelay);
|
|
23
|
+
}
|
|
24
|
+
function isRetryableError(error, policy) {
|
|
25
|
+
if (!policy.retryableErrors || policy.retryableErrors.length === 0) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return policy.retryableErrors.some((pattern) => error.message.includes(pattern) || error.name.includes(pattern));
|
|
29
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Workflow } from "../Workflow.js";
|
|
2
|
+
import type { WorkflowDefinitionEdge, WorkflowDefinitionNode } from "./types.js";
|
|
3
|
+
export declare class DefinitionBuilder {
|
|
4
|
+
build(root: Workflow<any, any>): {
|
|
5
|
+
nodes: WorkflowDefinitionNode[];
|
|
6
|
+
edges: WorkflowDefinitionEdge[];
|
|
7
|
+
};
|
|
8
|
+
private findTerminalNodeIds;
|
|
9
|
+
}
|