@codemation/core 0.6.0 → 0.8.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/CHANGELOG.md +31 -0
- package/dist/{EngineRuntimeRegistration.types-Dm129RJ6.d.ts → EngineRuntimeRegistration.types-BP6tsaNP.d.ts} +4 -2
- package/dist/{EngineWorkflowRunnerService-Bf88QtwB.d.cts → EngineWorkflowRunnerService-DzOCa1BW.d.cts} +4 -2
- package/dist/{InMemoryRunDataFactory-Dyl4p2s8.d.cts → InMemoryRunDataFactory-1iz7_SnO.d.cts} +27 -7
- package/dist/{workflowActivationPolicy-6V3OJD3N.cjs → InMemoryRunEventBusRegistry-B0_C4OnP.cjs} +1 -16
- package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs.map +1 -0
- package/dist/{workflowActivationPolicy-Td9HTOuD.js → InMemoryRunEventBusRegistry-C2U83Hmv.js} +2 -11
- package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js.map +1 -0
- package/dist/{RunIntentService-BDiodxhf.d.ts → RunIntentService-BqhmdoA1.d.ts} +258 -21
- package/dist/{RunIntentService-B1Y3v1H6.d.cts → RunIntentService-S-1lW-gS.d.cts} +209 -5
- package/dist/bootstrap/index.cjs +4 -2
- package/dist/bootstrap/index.d.cts +26 -7
- package/dist/bootstrap/index.d.ts +4 -4
- package/dist/bootstrap/index.js +3 -3
- package/dist/{bootstrap-DVL2ue5v.cjs → bootstrap-BaN6hZ5I.cjs} +7 -4
- package/dist/bootstrap-BaN6hZ5I.cjs.map +1 -0
- package/dist/{bootstrap-DdeiJ8cd.js → bootstrap-d_BMaDT4.js} +7 -4
- package/dist/bootstrap-d_BMaDT4.js.map +1 -0
- package/dist/{index-C2af8ssM.d.ts → index-CVs9rVhl.d.ts} +44 -13
- package/dist/index.cjs +59 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -22
- package/dist/index.d.ts +3 -3
- package/dist/index.js +33 -75
- package/dist/index.js.map +1 -1
- package/dist/{runtime-7Xh9z3dw.js → runtime-DUW6tIJ1.js} +454 -64
- package/dist/runtime-DUW6tIJ1.js.map +1 -0
- package/dist/{runtime-DVBwxFvX.cjs → runtime-Dvo2ru5A.cjs} +589 -73
- package/dist/runtime-Dvo2ru5A.cjs.map +1 -0
- package/dist/testing.cjs +6 -6
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -3
- package/package.json +1 -1
- package/src/ai/AgentConfigInspectorFactory.ts +2 -2
- package/src/ai/AgentMessageConfigNormalizerFactory.ts +3 -3
- package/src/ai/AiHost.ts +4 -2
- package/src/ai/CallableToolConfig.ts +28 -3
- package/src/authoring/defineNode.types.ts +35 -9
- package/src/authoring/index.ts +1 -0
- package/src/bootstrap/index.ts +6 -1
- package/src/bootstrap/runtime/EngineRuntimeRegistrar.ts +4 -3
- package/src/bootstrap/runtime/EngineRuntimeRegistration.types.ts +3 -0
- package/src/contracts/CodemationTelemetryAttributeNames.ts +12 -0
- package/src/contracts/CodemationTelemetryMetricNames.ts +7 -0
- package/src/contracts/CostCatalogContract.ts +16 -0
- package/src/contracts/CostTrackingTelemetryContract.ts +47 -0
- package/src/contracts/GenAiTelemetryAttributeNames.ts +10 -0
- package/src/contracts/NoOpCostTrackingTelemetry.ts +16 -0
- package/src/contracts/NoOpCostTrackingTelemetryFactory.ts +9 -0
- package/src/contracts/NoOpExecutionTelemetry.ts +26 -0
- package/src/contracts/NoOpExecutionTelemetryFactory.ts +16 -0
- package/src/contracts/NoOpNodeExecutionTelemetry.ts +15 -0
- package/src/contracts/NoOpTelemetryArtifactReference.ts +9 -0
- package/src/contracts/NoOpTelemetrySpanScope.ts +22 -0
- package/src/contracts/index.ts +3 -1
- package/src/contracts/{itemValue.ts → itemExpr.ts} +31 -32
- package/src/contracts/params.ts +10 -0
- package/src/contracts/runTypes.ts +4 -1
- package/src/contracts/runtimeTypes.ts +7 -0
- package/src/contracts/telemetryTypes.ts +105 -0
- package/src/contracts/workflowTypes.ts +20 -2
- package/src/events/EventPublishingWorkflowExecutionRepository.ts +1 -1
- package/src/execution/CatalogBackedCostTrackingTelemetry.ts +81 -0
- package/src/execution/CatalogBackedCostTrackingTelemetryFactory.ts +12 -0
- package/src/execution/DefaultExecutionContextFactory.ts +23 -0
- package/src/execution/ExecutionTelemetryCostTrackingDecoratorFactory.ts +84 -0
- package/src/execution/{ItemValueResolver.ts → ItemExprResolver.ts} +5 -5
- package/src/execution/NodeActivationRequestComposer.ts +1 -0
- package/src/execution/NodeExecutionSnapshotFactory.ts +2 -0
- package/src/execution/NodeExecutor.ts +6 -6
- package/src/execution/StaticCostCatalog.ts +22 -0
- package/src/execution/WorkflowRunExecutionContextFactory.ts +2 -0
- package/src/execution/index.ts +5 -1
- package/src/index.ts +1 -1
- package/src/orchestration/NodeExecutionRequestHandlerService.ts +1 -0
- package/src/orchestration/RunContinuationService.ts +4 -0
- package/src/orchestration/RunStartService.ts +2 -0
- package/src/policies/storage/RunPolicySnapshotFactory.ts +9 -0
- package/src/runStorage/InMemoryRunData.ts +9 -5
- package/src/runStorage/InMemoryWorkflowExecutionRepository.ts +4 -2
- package/src/types/index.ts +7 -1
- package/src/workflowSnapshots/WorkflowSnapshotCodec.ts +1 -1
- package/dist/bootstrap-DVL2ue5v.cjs.map +0 -1
- package/dist/bootstrap-DdeiJ8cd.js.map +0 -1
- package/dist/runtime-7Xh9z3dw.js.map +0 -1
- package/dist/runtime-DVBwxFvX.cjs.map +0 -1
- package/dist/workflowActivationPolicy-6V3OJD3N.cjs.map +0 -1
- package/dist/workflowActivationPolicy-Td9HTOuD.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CostTrackingPriceQuote,
|
|
3
|
+
CostTrackingTelemetry,
|
|
4
|
+
CostTrackingUsageRecord,
|
|
5
|
+
} from "./CostTrackingTelemetryContract";
|
|
6
|
+
import type { TelemetryScope } from "./telemetryTypes";
|
|
7
|
+
|
|
8
|
+
export class NoOpCostTrackingTelemetry implements CostTrackingTelemetry {
|
|
9
|
+
async captureUsage(_: CostTrackingUsageRecord): Promise<CostTrackingPriceQuote | undefined> {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
forScope(_: TelemetryScope): CostTrackingTelemetry {
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CostTrackingTelemetry, CostTrackingTelemetryFactory } from "./CostTrackingTelemetryContract";
|
|
2
|
+
import type { ExecutionTelemetry } from "./telemetryTypes";
|
|
3
|
+
import { NoOpCostTrackingTelemetry } from "./NoOpCostTrackingTelemetry";
|
|
4
|
+
|
|
5
|
+
export class NoOpCostTrackingTelemetryFactory implements CostTrackingTelemetryFactory {
|
|
6
|
+
create(_: Readonly<{ telemetry: ExecutionTelemetry }>): CostTrackingTelemetry {
|
|
7
|
+
return new NoOpCostTrackingTelemetry();
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExecutionTelemetry,
|
|
3
|
+
NodeExecutionTelemetry,
|
|
4
|
+
TelemetryArtifactAttachment,
|
|
5
|
+
TelemetryArtifactReference,
|
|
6
|
+
TelemetryMetricRecord,
|
|
7
|
+
TelemetrySpanEventRecord,
|
|
8
|
+
} from "./telemetryTypes";
|
|
9
|
+
import type { NodeActivationId, NodeId } from "./workflowTypes";
|
|
10
|
+
import { NoOpNodeExecutionTelemetry } from "./NoOpNodeExecutionTelemetry";
|
|
11
|
+
import { NoOpTelemetryArtifactReference } from "./NoOpTelemetryArtifactReference";
|
|
12
|
+
|
|
13
|
+
export class NoOpExecutionTelemetry {
|
|
14
|
+
static readonly value: ExecutionTelemetry = {
|
|
15
|
+
traceId: "00000000000000000000000000000000",
|
|
16
|
+
spanId: "0000000000000000",
|
|
17
|
+
addSpanEvent(_: TelemetrySpanEventRecord): void {},
|
|
18
|
+
recordMetric(_: TelemetryMetricRecord): void {},
|
|
19
|
+
attachArtifact(_: TelemetryArtifactAttachment): TelemetryArtifactReference {
|
|
20
|
+
return NoOpTelemetryArtifactReference.value;
|
|
21
|
+
},
|
|
22
|
+
forNode(_: Readonly<{ nodeId: NodeId; activationId: NodeActivationId }>): NodeExecutionTelemetry {
|
|
23
|
+
return NoOpNodeExecutionTelemetry.value;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ParentExecutionRef, PersistedRunPolicySnapshot, RunId, WorkflowId } from "./workflowTypes";
|
|
2
|
+
import type { ExecutionTelemetry, ExecutionTelemetryFactory } from "./telemetryTypes";
|
|
3
|
+
import { NoOpExecutionTelemetry } from "./NoOpExecutionTelemetry";
|
|
4
|
+
|
|
5
|
+
export class NoOpExecutionTelemetryFactory implements ExecutionTelemetryFactory {
|
|
6
|
+
create(
|
|
7
|
+
_: Readonly<{
|
|
8
|
+
runId: RunId;
|
|
9
|
+
workflowId: WorkflowId;
|
|
10
|
+
parent?: ParentExecutionRef;
|
|
11
|
+
policySnapshot?: PersistedRunPolicySnapshot;
|
|
12
|
+
}>,
|
|
13
|
+
): ExecutionTelemetry {
|
|
14
|
+
return NoOpExecutionTelemetry.value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { NodeActivationId, NodeId } from "./workflowTypes";
|
|
2
|
+
import type { NodeExecutionTelemetry, TelemetryChildSpanStart, TelemetrySpanScope } from "./telemetryTypes";
|
|
3
|
+
import { NoOpTelemetrySpanScope } from "./NoOpTelemetrySpanScope";
|
|
4
|
+
|
|
5
|
+
export class NoOpNodeExecutionTelemetry {
|
|
6
|
+
static readonly value: NodeExecutionTelemetry = {
|
|
7
|
+
...NoOpTelemetrySpanScope.value,
|
|
8
|
+
forNode(_: Readonly<{ nodeId: NodeId; activationId: NodeActivationId }>): NodeExecutionTelemetry {
|
|
9
|
+
return NoOpNodeExecutionTelemetry.value;
|
|
10
|
+
},
|
|
11
|
+
startChildSpan(_: TelemetryChildSpanStart): TelemetrySpanScope {
|
|
12
|
+
return NoOpTelemetrySpanScope.value;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TelemetryArtifactReference } from "./telemetryTypes";
|
|
2
|
+
|
|
3
|
+
export class NoOpTelemetryArtifactReference {
|
|
4
|
+
static readonly value: TelemetryArtifactReference = {
|
|
5
|
+
artifactId: "telemetry-artifact-noop",
|
|
6
|
+
traceId: undefined,
|
|
7
|
+
spanId: undefined,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TelemetryArtifactAttachment,
|
|
3
|
+
TelemetryArtifactReference,
|
|
4
|
+
TelemetryMetricRecord,
|
|
5
|
+
TelemetrySpanEnd,
|
|
6
|
+
TelemetrySpanEventRecord,
|
|
7
|
+
TelemetrySpanScope,
|
|
8
|
+
} from "./telemetryTypes";
|
|
9
|
+
import { NoOpTelemetryArtifactReference } from "./NoOpTelemetryArtifactReference";
|
|
10
|
+
|
|
11
|
+
export class NoOpTelemetrySpanScope {
|
|
12
|
+
static readonly value: TelemetrySpanScope = {
|
|
13
|
+
traceId: "00000000000000000000000000000000",
|
|
14
|
+
spanId: "0000000000000000",
|
|
15
|
+
addSpanEvent(_: TelemetrySpanEventRecord): void {},
|
|
16
|
+
recordMetric(_: TelemetryMetricRecord): void {},
|
|
17
|
+
attachArtifact(_: TelemetryArtifactAttachment): TelemetryArtifactReference {
|
|
18
|
+
return NoOpTelemetryArtifactReference.value;
|
|
19
|
+
},
|
|
20
|
+
end(_: TelemetrySpanEnd = {}): void {},
|
|
21
|
+
};
|
|
22
|
+
}
|
package/src/contracts/index.ts
CHANGED
|
@@ -2,8 +2,10 @@ export * from "./credentialTypes";
|
|
|
2
2
|
export * from "./emitPorts";
|
|
3
3
|
export * from "./executionPersistenceContracts";
|
|
4
4
|
export * from "./itemMeta";
|
|
5
|
-
export * from "./
|
|
5
|
+
export * from "./params";
|
|
6
|
+
export * from "./itemExpr";
|
|
6
7
|
export * from "./runtimeTypes";
|
|
8
|
+
export * from "./telemetryTypes";
|
|
7
9
|
export * from "./runFinishedAtFactory";
|
|
8
10
|
export * from "./runTypes";
|
|
9
11
|
export * from "./webhookTypes";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { NodeExecutionContext } from "./runtimeTypes";
|
|
2
2
|
import type { Item, Items, NodeActivationId, NodeId, RunDataSnapshot, RunId, WorkflowId } from "./workflowTypes";
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const ITEM_EXPR_BRAND = Symbol.for("codemation.itemExpr");
|
|
5
5
|
|
|
6
|
-
export type
|
|
6
|
+
export type ItemExprResolvedContext = Readonly<{
|
|
7
7
|
runId: RunId;
|
|
8
8
|
workflowId: WorkflowId;
|
|
9
9
|
nodeId: NodeId;
|
|
@@ -14,52 +14,51 @@ export type ItemValueResolvedContext = Readonly<{
|
|
|
14
14
|
/**
|
|
15
15
|
* Context aligned with former {@link ItemInputMapperContext} — use **`data`** to read any completed upstream node.
|
|
16
16
|
*/
|
|
17
|
-
export type
|
|
17
|
+
export type ItemExprContext = ItemExprResolvedContext;
|
|
18
18
|
|
|
19
|
-
export type
|
|
19
|
+
export type ItemExprArgs<TItemJson = unknown> = Readonly<{
|
|
20
20
|
item: Item<TItemJson>;
|
|
21
21
|
itemIndex: number;
|
|
22
22
|
items: Items<TItemJson>;
|
|
23
|
-
ctx:
|
|
23
|
+
ctx: ItemExprContext;
|
|
24
24
|
}>;
|
|
25
25
|
|
|
26
|
-
export type
|
|
26
|
+
export type ItemExprCallback<T, TItemJson = unknown> = (args: ItemExprArgs<TItemJson>) => T | Promise<T>;
|
|
27
27
|
|
|
28
|
-
export type
|
|
29
|
-
readonly [
|
|
30
|
-
readonly fn:
|
|
28
|
+
export type ItemExpr<T, TItemJson = unknown> = Readonly<{
|
|
29
|
+
readonly [ITEM_EXPR_BRAND]: true;
|
|
30
|
+
readonly fn: ItemExprCallback<T, TItemJson>;
|
|
31
31
|
}>;
|
|
32
32
|
|
|
33
|
-
export function
|
|
34
|
-
return { [
|
|
33
|
+
export function itemExpr<T, TItemJson = unknown>(fn: ItemExprCallback<T, TItemJson>): ItemExpr<T, TItemJson> {
|
|
34
|
+
return { [ITEM_EXPR_BRAND]: true, fn };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export function
|
|
37
|
+
export function isItemExpr<T, TItemJson = unknown>(value: unknown): value is ItemExpr<T, TItemJson> {
|
|
38
38
|
if (typeof value !== "object" || value === null) {
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
41
|
const v = value as Record<PropertyKey, unknown>;
|
|
42
|
-
if (v[
|
|
42
|
+
if (v[ITEM_EXPR_BRAND] === true) {
|
|
43
43
|
return true;
|
|
44
44
|
}
|
|
45
|
-
// Support snapshot-hydrated
|
|
45
|
+
// Support snapshot-hydrated itemExpr wrappers where the symbol brand was lost but the callback survived.
|
|
46
46
|
// Workflow snapshot hydration currently restores function-valued fields (like `fn`) but may drop symbol-keyed brands.
|
|
47
|
-
// We treat the minimal `{ fn: Function }` shape as an
|
|
47
|
+
// We treat the minimal `{ fn: Function }` shape as an itemExpr wrapper to keep runnable configs working.
|
|
48
48
|
const keys = Object.keys(v);
|
|
49
49
|
if (keys.length === 1 && keys[0] === "fn" && typeof (v as { fn?: unknown }).fn === "function") {
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
52
|
-
// Support legacy module-local Symbol("codemation.itemValue") brands (e.g. duplicate module graphs).
|
|
53
52
|
for (const sym of Object.getOwnPropertySymbols(v)) {
|
|
54
|
-
if (sym.description === "codemation.
|
|
53
|
+
if (sym.description === "codemation.itemExpr" && v[sym] === true) {
|
|
55
54
|
return true;
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
return false;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
function
|
|
62
|
-
if (
|
|
60
|
+
function containsItemExprInUnknown(value: unknown, seen: WeakSet<object> = new WeakSet()): boolean {
|
|
61
|
+
if (isItemExpr(value)) {
|
|
63
62
|
return true;
|
|
64
63
|
}
|
|
65
64
|
if (value === null || typeof value !== "object") {
|
|
@@ -70,10 +69,10 @@ function containsItemValueInUnknown(value: unknown, seen: WeakSet<object> = new
|
|
|
70
69
|
}
|
|
71
70
|
seen.add(value as object);
|
|
72
71
|
if (Array.isArray(value)) {
|
|
73
|
-
return value.some((entry) =>
|
|
72
|
+
return value.some((entry) => containsItemExprInUnknown(entry, seen));
|
|
74
73
|
}
|
|
75
74
|
for (const entry of Object.values(value as Record<string, unknown>)) {
|
|
76
|
-
if (
|
|
75
|
+
if (containsItemExprInUnknown(entry, seen)) {
|
|
77
76
|
return true;
|
|
78
77
|
}
|
|
79
78
|
}
|
|
@@ -81,14 +80,14 @@ function containsItemValueInUnknown(value: unknown, seen: WeakSet<object> = new
|
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/**
|
|
84
|
-
* Deep-resolves {@link
|
|
83
|
+
* Deep-resolves {@link itemExpr} leaves. Returns a new graph (does not mutate the original config object).
|
|
85
84
|
*/
|
|
86
|
-
export async function
|
|
85
|
+
export async function resolveItemExprsInUnknown(
|
|
87
86
|
value: unknown,
|
|
88
|
-
args:
|
|
87
|
+
args: ItemExprArgs,
|
|
89
88
|
seen: WeakSet<object> = new WeakSet(),
|
|
90
89
|
): Promise<unknown> {
|
|
91
|
-
if (
|
|
90
|
+
if (isItemExpr(value)) {
|
|
92
91
|
return await Promise.resolve(value.fn(args));
|
|
93
92
|
}
|
|
94
93
|
if (value === null || typeof value !== "object") {
|
|
@@ -101,7 +100,7 @@ export async function resolveItemValuesInUnknown(
|
|
|
101
100
|
if (Array.isArray(value)) {
|
|
102
101
|
const out: unknown[] = [];
|
|
103
102
|
for (let i = 0; i < value.length; i++) {
|
|
104
|
-
out.push(await
|
|
103
|
+
out.push(await resolveItemExprsInUnknown(value[i], args, seen));
|
|
105
104
|
}
|
|
106
105
|
return out;
|
|
107
106
|
}
|
|
@@ -113,22 +112,22 @@ export async function resolveItemValuesInUnknown(
|
|
|
113
112
|
}
|
|
114
113
|
const out = Object.create(proto) as Record<string, unknown>;
|
|
115
114
|
for (const [k, v] of entries) {
|
|
116
|
-
out[k] = await
|
|
115
|
+
out[k] = await resolveItemExprsInUnknown(v, args, seen);
|
|
117
116
|
}
|
|
118
117
|
return out;
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
/**
|
|
122
|
-
* Clones runnable config (best-effort) so per-item {@link
|
|
121
|
+
* Clones runnable config (best-effort) so per-item {@link itemExpr} resolution never mutates shared instances.
|
|
123
122
|
*/
|
|
124
|
-
export async function
|
|
123
|
+
export async function resolveItemExprsForExecution(
|
|
125
124
|
config: unknown,
|
|
126
125
|
nodeCtx: NodeExecutionContext,
|
|
127
126
|
item: Item,
|
|
128
127
|
itemIndex: number,
|
|
129
128
|
items: Items,
|
|
130
129
|
): Promise<unknown | undefined> {
|
|
131
|
-
const
|
|
130
|
+
const exprArgs: ItemExprArgs = {
|
|
132
131
|
item,
|
|
133
132
|
itemIndex,
|
|
134
133
|
items,
|
|
@@ -140,8 +139,8 @@ export async function resolveItemValuesForExecution(
|
|
|
140
139
|
data: nodeCtx.data,
|
|
141
140
|
},
|
|
142
141
|
};
|
|
143
|
-
if (!
|
|
142
|
+
if (!containsItemExprInUnknown(config)) {
|
|
144
143
|
return undefined;
|
|
145
144
|
}
|
|
146
|
-
return await
|
|
145
|
+
return await resolveItemExprsInUnknown(config, exprArgs);
|
|
147
146
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ItemExpr } from "./itemExpr";
|
|
2
|
+
|
|
3
|
+
export type Expr<T, TItemJson = unknown> = ItemExpr<T, TItemJson>;
|
|
4
|
+
|
|
5
|
+
export type Param<T, TItemJson = unknown> = T | Expr<T, TItemJson>;
|
|
6
|
+
|
|
7
|
+
export type ParamDeep<T, TItemJson = unknown> =
|
|
8
|
+
| Expr<T, TItemJson>
|
|
9
|
+
| (T extends readonly (infer U)[] ? ReadonlyArray<ParamDeep<U, TItemJson>> : never)
|
|
10
|
+
| (T extends object ? { [K in keyof T]: ParamDeep<T[K], TItemJson> } : T);
|
|
@@ -112,6 +112,7 @@ export interface NodeExecutionError {
|
|
|
112
112
|
message: string;
|
|
113
113
|
name?: string;
|
|
114
114
|
stack?: string;
|
|
115
|
+
details?: JsonValue;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
export interface NodeExecutionSnapshot {
|
|
@@ -291,7 +292,9 @@ export interface RunPruneCandidate {
|
|
|
291
292
|
}
|
|
292
293
|
|
|
293
294
|
export interface WorkflowExecutionPruneRepository {
|
|
294
|
-
listRunsOlderThan(
|
|
295
|
+
listRunsOlderThan(
|
|
296
|
+
args: Readonly<{ nowIso: string; defaultRetentionSeconds: number; limit?: number }>,
|
|
297
|
+
): Promise<ReadonlyArray<RunPruneCandidate>>;
|
|
295
298
|
}
|
|
296
299
|
|
|
297
300
|
export type RunResult =
|
|
@@ -2,6 +2,7 @@ import type { ReadableStream as BinaryReadableStream } from "node:stream/web";
|
|
|
2
2
|
import type { TypeToken } from "../di";
|
|
3
3
|
import type { RunEventBus } from "../events/runEvents";
|
|
4
4
|
import type { CredentialSessionService } from "./credentialTypes";
|
|
5
|
+
import type { ExecutionTelemetry, ExecutionTelemetryFactory, NodeExecutionTelemetry } from "./telemetryTypes";
|
|
5
6
|
import type {
|
|
6
7
|
ConnectionInvocationAppendArgs,
|
|
7
8
|
NodeInputsByPort,
|
|
@@ -28,6 +29,7 @@ import type {
|
|
|
28
29
|
RunnableNodeConfig,
|
|
29
30
|
OutputPortKey,
|
|
30
31
|
ParentExecutionRef,
|
|
32
|
+
PersistedRunPolicySnapshot,
|
|
31
33
|
RunDataFactory,
|
|
32
34
|
RunDataSnapshot,
|
|
33
35
|
RunId,
|
|
@@ -149,6 +151,7 @@ export interface ExecutionContext {
|
|
|
149
151
|
now: () => Date;
|
|
150
152
|
data: RunDataSnapshot;
|
|
151
153
|
nodeState?: NodeExecutionStatePublisher;
|
|
154
|
+
telemetry: ExecutionTelemetry;
|
|
152
155
|
binary: ExecutionBinaryService;
|
|
153
156
|
getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
|
|
154
157
|
}
|
|
@@ -158,11 +161,13 @@ export interface ExecutionContextFactory {
|
|
|
158
161
|
runId: RunId;
|
|
159
162
|
workflowId: WorkflowId;
|
|
160
163
|
parent?: ParentExecutionRef;
|
|
164
|
+
policySnapshot?: PersistedRunPolicySnapshot;
|
|
161
165
|
subworkflowDepth: number;
|
|
162
166
|
engineMaxNodeActivations: number;
|
|
163
167
|
engineMaxSubworkflowDepth: number;
|
|
164
168
|
data: RunDataSnapshot;
|
|
165
169
|
nodeState?: NodeExecutionStatePublisher;
|
|
170
|
+
telemetry?: ExecutionTelemetry;
|
|
166
171
|
getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
|
|
167
172
|
}): ExecutionContext;
|
|
168
173
|
}
|
|
@@ -171,6 +176,7 @@ export interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfi
|
|
|
171
176
|
nodeId: NodeId;
|
|
172
177
|
activationId: NodeActivationId;
|
|
173
178
|
config: TConfig;
|
|
179
|
+
telemetry: NodeExecutionTelemetry;
|
|
174
180
|
binary: NodeBinaryAttachmentService;
|
|
175
181
|
}
|
|
176
182
|
|
|
@@ -416,6 +422,7 @@ export interface EngineDeps {
|
|
|
416
422
|
activationScheduler: NodeActivationScheduler;
|
|
417
423
|
runDataFactory: RunDataFactory;
|
|
418
424
|
executionContextFactory: ExecutionContextFactory;
|
|
425
|
+
executionTelemetryFactory?: ExecutionTelemetryFactory;
|
|
419
426
|
nodeExecutor: NodeExecutor;
|
|
420
427
|
eventBus?: RunEventBus;
|
|
421
428
|
tokenRegistry: PersistedWorkflowTokenRegistryLike;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
JsonValue,
|
|
3
|
+
NodeActivationId,
|
|
4
|
+
NodeId,
|
|
5
|
+
ParentExecutionRef,
|
|
6
|
+
PersistedRunPolicySnapshot,
|
|
7
|
+
RunId,
|
|
8
|
+
WorkflowId,
|
|
9
|
+
} from "./workflowTypes";
|
|
10
|
+
import type { CostTrackingTelemetry } from "./CostTrackingTelemetryContract";
|
|
11
|
+
|
|
12
|
+
export type TelemetryAttributePrimitive = string | number | boolean | null;
|
|
13
|
+
|
|
14
|
+
export interface TelemetryAttributes {
|
|
15
|
+
readonly [key: string]: TelemetryAttributePrimitive | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TelemetryMetricRecord {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly value: number;
|
|
21
|
+
readonly unit?: string;
|
|
22
|
+
readonly attributes?: TelemetryAttributes;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TelemetrySpanEventRecord {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly occurredAt?: Date;
|
|
28
|
+
readonly attributes?: TelemetryAttributes;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TelemetryArtifactAttachment {
|
|
32
|
+
readonly kind: string;
|
|
33
|
+
readonly contentType: string;
|
|
34
|
+
readonly previewText?: string;
|
|
35
|
+
readonly previewJson?: JsonValue;
|
|
36
|
+
readonly payloadText?: string;
|
|
37
|
+
readonly payloadJson?: JsonValue;
|
|
38
|
+
readonly bytes?: number;
|
|
39
|
+
readonly truncated?: boolean;
|
|
40
|
+
readonly expiresAt?: Date;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface TelemetryArtifactReference {
|
|
44
|
+
readonly artifactId: string;
|
|
45
|
+
readonly traceId?: string;
|
|
46
|
+
readonly spanId?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface TelemetrySpanEnd {
|
|
50
|
+
readonly status?: "ok" | "error";
|
|
51
|
+
readonly statusMessage?: string;
|
|
52
|
+
readonly endedAt?: Date;
|
|
53
|
+
readonly attributes?: TelemetryAttributes;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface TelemetryChildSpanStart {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly kind?: "internal" | "client";
|
|
59
|
+
readonly startedAt?: Date;
|
|
60
|
+
readonly attributes?: TelemetryAttributes;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface TelemetryScope {
|
|
64
|
+
readonly traceId?: string;
|
|
65
|
+
readonly spanId?: string;
|
|
66
|
+
readonly costTracking?: CostTrackingTelemetry;
|
|
67
|
+
addSpanEvent(args: TelemetrySpanEventRecord): Promise<void> | void;
|
|
68
|
+
recordMetric(args: TelemetryMetricRecord): Promise<void> | void;
|
|
69
|
+
attachArtifact(args: TelemetryArtifactAttachment): Promise<TelemetryArtifactReference> | TelemetryArtifactReference;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface TelemetrySpanScope extends TelemetryScope {
|
|
73
|
+
readonly traceId: string;
|
|
74
|
+
readonly spanId: string;
|
|
75
|
+
end(args?: TelemetrySpanEnd): Promise<void> | void;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface NodeExecutionTelemetry extends ExecutionTelemetry, TelemetrySpanScope {
|
|
79
|
+
startChildSpan(args: TelemetryChildSpanStart): TelemetrySpanScope;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ExecutionTelemetry extends TelemetryScope {
|
|
83
|
+
readonly traceId: string;
|
|
84
|
+
readonly spanId: string;
|
|
85
|
+
forNode(args: Readonly<{ nodeId: NodeId; activationId: NodeActivationId }>): NodeExecutionTelemetry;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ExecutionTelemetryFactory {
|
|
89
|
+
create(
|
|
90
|
+
args: Readonly<{
|
|
91
|
+
runId: RunId;
|
|
92
|
+
workflowId: WorkflowId;
|
|
93
|
+
parent?: ParentExecutionRef;
|
|
94
|
+
policySnapshot?: PersistedRunPolicySnapshot;
|
|
95
|
+
}>,
|
|
96
|
+
): ExecutionTelemetry;
|
|
97
|
+
}
|
|
98
|
+
export { NoOpTelemetryArtifactReference } from "./NoOpTelemetryArtifactReference";
|
|
99
|
+
export { NoOpTelemetrySpanScope } from "./NoOpTelemetrySpanScope";
|
|
100
|
+
export { NoOpNodeExecutionTelemetry } from "./NoOpNodeExecutionTelemetry";
|
|
101
|
+
export { NoOpExecutionTelemetry } from "./NoOpExecutionTelemetry";
|
|
102
|
+
export { NoOpExecutionTelemetryFactory } from "./NoOpExecutionTelemetryFactory";
|
|
103
|
+
export { CodemationTelemetryAttributeNames } from "./CodemationTelemetryAttributeNames";
|
|
104
|
+
export { GenAiTelemetryAttributeNames } from "./GenAiTelemetryAttributeNames";
|
|
105
|
+
export { CodemationTelemetryMetricNames } from "./CodemationTelemetryMetricNames";
|
|
@@ -6,6 +6,7 @@ import type { RetryPolicySpec } from "./retryPolicySpec.types";
|
|
|
6
6
|
|
|
7
7
|
export type WorkflowId = string;
|
|
8
8
|
export type NodeId = string;
|
|
9
|
+
export type NodeIdRef<TJson = unknown> = NodeId & Readonly<{ __codemationNodeJson?: TJson }>;
|
|
9
10
|
export type OutputPortKey = string;
|
|
10
11
|
export type InputPortKey = string;
|
|
11
12
|
export type PersistedTokenId = string;
|
|
@@ -154,6 +155,10 @@ export interface NodeRef {
|
|
|
154
155
|
name?: string;
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
export function nodeRef<TJson>(nodeId: NodeId): NodeIdRef<TJson> {
|
|
159
|
+
return nodeId as NodeIdRef<TJson>;
|
|
160
|
+
}
|
|
161
|
+
|
|
157
162
|
export type PairedItemRef = Readonly<{ nodeId: NodeId; output: OutputPortKey; itemIndex: number }>;
|
|
158
163
|
|
|
159
164
|
export type BinaryPreviewKind = "image" | "audio" | "video" | "download";
|
|
@@ -204,8 +209,12 @@ export interface ParentExecutionRef {
|
|
|
204
209
|
|
|
205
210
|
export interface RunDataSnapshot {
|
|
206
211
|
getOutputs(nodeId: NodeId): NodeOutputs | undefined;
|
|
207
|
-
getOutputItems(nodeId: NodeId
|
|
208
|
-
getOutputItem
|
|
212
|
+
getOutputItems<TJson = unknown>(nodeId: NodeId | NodeIdRef<TJson>, output?: OutputPortKey): Items<TJson>;
|
|
213
|
+
getOutputItem<TJson = unknown>(
|
|
214
|
+
nodeId: NodeId | NodeIdRef<TJson>,
|
|
215
|
+
itemIndex: number,
|
|
216
|
+
output?: OutputPortKey,
|
|
217
|
+
): Item<TJson> | undefined;
|
|
209
218
|
}
|
|
210
219
|
|
|
211
220
|
export interface MutableRunData extends RunDataSnapshot {
|
|
@@ -260,11 +269,17 @@ export interface WorkflowStoragePolicyDecisionArgs {
|
|
|
260
269
|
export interface WorkflowPrunePolicySpec {
|
|
261
270
|
readonly runDataRetentionSeconds?: number;
|
|
262
271
|
readonly binaryRetentionSeconds?: number;
|
|
272
|
+
readonly telemetrySpanRetentionSeconds?: number;
|
|
273
|
+
readonly telemetryArtifactRetentionSeconds?: number;
|
|
274
|
+
readonly telemetryMetricRetentionSeconds?: number;
|
|
263
275
|
}
|
|
264
276
|
|
|
265
277
|
export interface PersistedRunPolicySnapshot {
|
|
266
278
|
readonly retentionSeconds?: number;
|
|
267
279
|
readonly binaryRetentionSeconds?: number;
|
|
280
|
+
readonly telemetrySpanRetentionSeconds?: number;
|
|
281
|
+
readonly telemetryArtifactRetentionSeconds?: number;
|
|
282
|
+
readonly telemetryMetricRetentionSeconds?: number;
|
|
268
283
|
readonly storagePolicy: WorkflowStoragePolicyMode;
|
|
269
284
|
}
|
|
270
285
|
|
|
@@ -302,5 +317,8 @@ export type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandle
|
|
|
302
317
|
export interface WorkflowPolicyRuntimeDefaults {
|
|
303
318
|
readonly retentionSeconds?: number;
|
|
304
319
|
readonly binaryRetentionSeconds?: number;
|
|
320
|
+
readonly telemetrySpanRetentionSeconds?: number;
|
|
321
|
+
readonly telemetryArtifactRetentionSeconds?: number;
|
|
322
|
+
readonly telemetryMetricRetentionSeconds?: number;
|
|
305
323
|
readonly storagePolicy?: WorkflowStoragePolicyMode;
|
|
306
324
|
}
|
|
@@ -63,7 +63,7 @@ export class EventPublishingWorkflowExecutionRepository
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
async listRunsOlderThan(
|
|
66
|
-
args: Readonly<{
|
|
66
|
+
args: Readonly<{ nowIso: string; defaultRetentionSeconds: number; limit?: number }>,
|
|
67
67
|
): Promise<ReadonlyArray<RunPruneCandidate>> {
|
|
68
68
|
const pruneRepository = this.inner as unknown as Partial<WorkflowExecutionPruneRepository>;
|
|
69
69
|
if (!pruneRepository.listRunsOlderThan) return [];
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { CostCatalog } from "../contracts/CostCatalogContract";
|
|
2
|
+
import {
|
|
3
|
+
CostTrackingTelemetryAttributeNames,
|
|
4
|
+
CostTrackingTelemetryMetricNames,
|
|
5
|
+
type CostTrackingPriceQuote,
|
|
6
|
+
type CostTrackingTelemetry,
|
|
7
|
+
type CostTrackingUsageRecord,
|
|
8
|
+
} from "../contracts/CostTrackingTelemetryContract";
|
|
9
|
+
import type { TelemetryAttributes, TelemetryScope } from "../types";
|
|
10
|
+
|
|
11
|
+
export class CatalogBackedCostTrackingTelemetry implements CostTrackingTelemetry {
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly currentScope: TelemetryScope,
|
|
14
|
+
private readonly costCatalog: CostCatalog,
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
async captureUsage(args: CostTrackingUsageRecord): Promise<CostTrackingPriceQuote | undefined> {
|
|
18
|
+
const usageAttributes = this.createUsageAttributes(args);
|
|
19
|
+
await this.currentScope.recordMetric({
|
|
20
|
+
name: CostTrackingTelemetryMetricNames.usage,
|
|
21
|
+
value: args.quantity,
|
|
22
|
+
unit: args.usageUnit,
|
|
23
|
+
attributes: usageAttributes,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const catalogEntry = this.costCatalog.findEntry(args);
|
|
27
|
+
if (!catalogEntry) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const estimatedAmountMinor = Math.round(args.quantity * catalogEntry.pricePerUnitMinor);
|
|
32
|
+
const costAttributes = this.createCostAttributes(args, catalogEntry.currency, catalogEntry.currencyScale);
|
|
33
|
+
await this.currentScope.recordMetric({
|
|
34
|
+
name: CostTrackingTelemetryMetricNames.estimatedCost,
|
|
35
|
+
value: estimatedAmountMinor,
|
|
36
|
+
unit: catalogEntry.currency,
|
|
37
|
+
attributes: costAttributes,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
currency: catalogEntry.currency,
|
|
42
|
+
currencyScale: catalogEntry.currencyScale,
|
|
43
|
+
estimatedAmountMinor,
|
|
44
|
+
estimateKind: "catalog",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
forScope(scope: TelemetryScope): CostTrackingTelemetry {
|
|
49
|
+
// eslint-disable-next-line codemation/no-manual-di-new
|
|
50
|
+
return new CatalogBackedCostTrackingTelemetry(scope, this.costCatalog);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private createUsageAttributes(args: CostTrackingUsageRecord): TelemetryAttributes {
|
|
54
|
+
return {
|
|
55
|
+
...args.attributes,
|
|
56
|
+
[CostTrackingTelemetryAttributeNames.component]: args.component,
|
|
57
|
+
[CostTrackingTelemetryAttributeNames.provider]: args.provider,
|
|
58
|
+
[CostTrackingTelemetryAttributeNames.operation]: args.operation,
|
|
59
|
+
[CostTrackingTelemetryAttributeNames.pricingKey]: args.pricingKey,
|
|
60
|
+
[CostTrackingTelemetryAttributeNames.usageUnit]: args.usageUnit,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private createCostAttributes(
|
|
65
|
+
args: CostTrackingUsageRecord,
|
|
66
|
+
currency: string,
|
|
67
|
+
currencyScale: number,
|
|
68
|
+
): TelemetryAttributes {
|
|
69
|
+
return {
|
|
70
|
+
...args.attributes,
|
|
71
|
+
[CostTrackingTelemetryAttributeNames.component]: args.component,
|
|
72
|
+
[CostTrackingTelemetryAttributeNames.provider]: args.provider,
|
|
73
|
+
[CostTrackingTelemetryAttributeNames.operation]: args.operation,
|
|
74
|
+
[CostTrackingTelemetryAttributeNames.pricingKey]: args.pricingKey,
|
|
75
|
+
[CostTrackingTelemetryAttributeNames.usageUnit]: args.usageUnit,
|
|
76
|
+
[CostTrackingTelemetryAttributeNames.currency]: currency,
|
|
77
|
+
[CostTrackingTelemetryAttributeNames.currencyScale]: currencyScale,
|
|
78
|
+
[CostTrackingTelemetryAttributeNames.estimateKind]: "catalog",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CostCatalog } from "../contracts/CostCatalogContract";
|
|
2
|
+
import type { CostTrackingTelemetry, CostTrackingTelemetryFactory } from "../contracts/CostTrackingTelemetryContract";
|
|
3
|
+
import type { ExecutionTelemetry } from "../contracts/telemetryTypes";
|
|
4
|
+
import { CatalogBackedCostTrackingTelemetry } from "./CatalogBackedCostTrackingTelemetry";
|
|
5
|
+
|
|
6
|
+
export class CatalogBackedCostTrackingTelemetryFactory implements CostTrackingTelemetryFactory {
|
|
7
|
+
constructor(private readonly costCatalog: CostCatalog) {}
|
|
8
|
+
|
|
9
|
+
create(args: Readonly<{ telemetry: ExecutionTelemetry }>): CostTrackingTelemetry {
|
|
10
|
+
return new CatalogBackedCostTrackingTelemetry(args.telemetry, this.costCatalog);
|
|
11
|
+
}
|
|
12
|
+
}
|