@fieldwangai/agentflow 0.1.134 → 0.1.136
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/bin/lib/ui-server.mjs +405 -40
- package/bin/lib/workflow-report.mjs +154 -9
- package/builtin/web-ui/dist/assets/index-HdswcJWY.js +565 -0
- package/builtin/web-ui/dist/assets/index-KIGufzQf.css +1 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/skills/agentflow-cli/SKILL.md +3 -70
- package/skills/agentflow-cli/agents/openai.yaml +2 -2
- package/skills/agentflow-cli/scripts/agentflow-cli.mjs +24 -4
- package/skills/agentflow-cli/scripts/workflow-report-client.mjs +68 -0
- package/skills/agentflow-workflow-report/SKILL.md +100 -0
- package/skills/agentflow-workflow-report/agents/openai.yaml +4 -0
- package/skills/agentflow-workflow-report/references/protocol.md +558 -0
- package/builtin/web-ui/dist/assets/index-CqXKONpd.js +0 -350
- package/builtin/web-ui/dist/assets/index-QDDFbZ_T.css +0 -1
|
@@ -21,6 +21,10 @@ function cleanString(value, max = 4000) {
|
|
|
21
21
|
return String(value ?? "").trim().slice(0, max);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function hasOwn(value, key) {
|
|
25
|
+
return Boolean(value && typeof value === "object" && Object.prototype.hasOwnProperty.call(value, key));
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
function stableValue(value) {
|
|
25
29
|
if (Array.isArray(value)) return value.map((item) => stableValue(item));
|
|
26
30
|
if (value && typeof value === "object") {
|
|
@@ -105,6 +109,93 @@ function normalizeWorkflowArtifact(value, index = 0, defaultScope = "action") {
|
|
|
105
109
|
};
|
|
106
110
|
}
|
|
107
111
|
|
|
112
|
+
export function normalizeWorkflowTimelineProjection(value, index = 0) {
|
|
113
|
+
const raw = plainObject(value);
|
|
114
|
+
const kind = cleanString(raw.kind || raw.type, 80).toLowerCase();
|
|
115
|
+
const id = cleanString(raw.id || raw.key, 240);
|
|
116
|
+
if (!kind || !id) return null;
|
|
117
|
+
const source = cleanString(raw.source || raw.namespace, 120).toLowerCase();
|
|
118
|
+
const date = cleanString(raw.date || raw.targetDate || raw.target_date, 80);
|
|
119
|
+
const dimensions = mergeWorkflowGlobalState({}, plainObject(raw.dimensions || raw.facets));
|
|
120
|
+
const key = cleanString(raw.key || [source, kind, id].filter(Boolean).join(":"), 500);
|
|
121
|
+
return {
|
|
122
|
+
...mergeWorkflowGlobalState({}, raw),
|
|
123
|
+
key: key || `${kind}:${id}`,
|
|
124
|
+
kind,
|
|
125
|
+
id,
|
|
126
|
+
title: cleanString(raw.title || raw.label || id, 500) || id,
|
|
127
|
+
...(source ? { source } : {}),
|
|
128
|
+
...(date ? { date } : {}),
|
|
129
|
+
dimensions,
|
|
130
|
+
order: Number.isFinite(Number(raw.order)) ? Number(raw.order) : index,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function normalizeWorkflowProjectionState(value = {}) {
|
|
135
|
+
const raw = mergeWorkflowGlobalState({}, plainObject(value));
|
|
136
|
+
if (Array.isArray(value?.timeline)) {
|
|
137
|
+
raw.timeline = value.timeline
|
|
138
|
+
.map((item, index) => normalizeWorkflowTimelineProjection(item, index))
|
|
139
|
+
.filter(Boolean)
|
|
140
|
+
.slice(0, 100);
|
|
141
|
+
} else {
|
|
142
|
+
delete raw.timeline;
|
|
143
|
+
}
|
|
144
|
+
return raw;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function normalizeWorkflowExtensions(value = {}) {
|
|
148
|
+
const raw = plainObject(value);
|
|
149
|
+
const out = {};
|
|
150
|
+
for (const [namespace, extension] of Object.entries(raw)) {
|
|
151
|
+
const key = cleanString(namespace, 120).toLowerCase();
|
|
152
|
+
if (!key || !/^[a-z][a-z0-9._-]{0,119}$/.test(key)) continue;
|
|
153
|
+
if (!extension || typeof extension !== "object" || Array.isArray(extension)) continue;
|
|
154
|
+
out[key] = mergeWorkflowGlobalState({}, extension);
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function materializeWorkflowExtensions(snapshot = {}, runtimeEvents = []) {
|
|
160
|
+
let extensions = normalizeWorkflowExtensions(
|
|
161
|
+
snapshot.extensions || snapshot.workflowExtensions || snapshot.workflow_extensions || {},
|
|
162
|
+
);
|
|
163
|
+
const events = [...(Array.isArray(runtimeEvents) ? runtimeEvents : [])]
|
|
164
|
+
.sort((left, right) => eventTime(left) - eventTime(right));
|
|
165
|
+
for (const event of events) {
|
|
166
|
+
const patch = event?.extensionsPatch || event?.extensions_patch;
|
|
167
|
+
if (!patch || typeof patch !== "object" || Array.isArray(patch)) continue;
|
|
168
|
+
extensions = mergeWorkflowGlobalState(extensions, normalizeWorkflowExtensions(patch));
|
|
169
|
+
}
|
|
170
|
+
return extensions;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function materializeWorkflowProjections(snapshot = {}, runtimeEvents = []) {
|
|
174
|
+
const base =
|
|
175
|
+
snapshot.projections ||
|
|
176
|
+
snapshot.workflowProjections ||
|
|
177
|
+
snapshot.workflow_projections ||
|
|
178
|
+
snapshot.raw?.projections ||
|
|
179
|
+
{};
|
|
180
|
+
let projections = normalizeWorkflowProjectionState(base);
|
|
181
|
+
const events = [...(Array.isArray(runtimeEvents) ? runtimeEvents : [])]
|
|
182
|
+
.sort((left, right) => eventTime(left) - eventTime(right));
|
|
183
|
+
for (const event of events) {
|
|
184
|
+
const next = event?.projections || event?.workflowProjections || event?.workflow_projections;
|
|
185
|
+
if (!next || typeof next !== "object" || Array.isArray(next) || !hasOwn(next, "timeline")) continue;
|
|
186
|
+
projections = {
|
|
187
|
+
...projections,
|
|
188
|
+
timeline: Array.isArray(next.timeline)
|
|
189
|
+
? next.timeline
|
|
190
|
+
.map((item, index) => normalizeWorkflowTimelineProjection(item, index))
|
|
191
|
+
.filter(Boolean)
|
|
192
|
+
.slice(0, 100)
|
|
193
|
+
: projections.timeline || [],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return projections;
|
|
197
|
+
}
|
|
198
|
+
|
|
108
199
|
export function mergeWorkflowGlobalState(base, patch) {
|
|
109
200
|
if (!patch || typeof patch !== "object" || Array.isArray(patch)) return plainObject(base);
|
|
110
201
|
const out = { ...plainObject(base) };
|
|
@@ -176,6 +267,24 @@ export function normalizeWorkflowReport(payload = {}) {
|
|
|
176
267
|
const workflow = normalizeWorkflowReference(payload);
|
|
177
268
|
if (workflow.error) return workflow;
|
|
178
269
|
const rawWorkflow = plainObject(payload.workflow);
|
|
270
|
+
const source = cleanString(payload.source || "agentflow-cli", 120).toLowerCase() || "agentflow-cli";
|
|
271
|
+
if (!/^[a-z][a-z0-9._-]{0,119}$/.test(source)) {
|
|
272
|
+
return { error: "Invalid workflow report source" };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const rawObservation = plainObject(payload.observation);
|
|
276
|
+
const hasObservation = Object.keys(rawObservation).length > 0;
|
|
277
|
+
const observationState = plainObject(rawObservation.state || rawObservation.facts || rawObservation.value);
|
|
278
|
+
if (hasObservation && !Object.keys(observationState).length) {
|
|
279
|
+
return { error: "observation requires state" };
|
|
280
|
+
}
|
|
281
|
+
const observation = hasObservation ? {
|
|
282
|
+
schema: cleanString(rawObservation.schema || rawObservation.model || "workflow-observation/v1", 160),
|
|
283
|
+
state: mergeWorkflowGlobalState({}, observationState),
|
|
284
|
+
observedAt: cleanString(rawObservation.observedAt || rawObservation.observed_at, 80),
|
|
285
|
+
clientId: cleanString(rawObservation.clientId || rawObservation.client_id, 160),
|
|
286
|
+
scope: cleanString(rawObservation.scope || "client", 80).toLowerCase() || "client",
|
|
287
|
+
} : null;
|
|
179
288
|
|
|
180
289
|
const rawAction = plainObject(payload.action);
|
|
181
290
|
const hasAction = Object.keys(rawAction).length > 0;
|
|
@@ -204,7 +313,33 @@ export function normalizeWorkflowReport(payload = {}) {
|
|
|
204
313
|
const rawArtifacts = Array.isArray(payload.artifacts) ? payload.artifacts : [];
|
|
205
314
|
const artifacts = rawArtifacts
|
|
206
315
|
.filter((item) => item && typeof item === "object" && !Array.isArray(item))
|
|
207
|
-
.map((item, index) =>
|
|
316
|
+
.map((item, index) => ({
|
|
317
|
+
...normalizeWorkflowArtifact(item, index, action ? "action" : "global"),
|
|
318
|
+
producer: source,
|
|
319
|
+
}));
|
|
320
|
+
|
|
321
|
+
const rawProjections = plainObject(payload.projections || payload.workflowProjections || payload.workflow_projections);
|
|
322
|
+
const hasProjections = Object.keys(rawProjections).length > 0 || hasOwn(payload, "projections");
|
|
323
|
+
if (hasProjections && !hasOwn(rawProjections, "timeline")) {
|
|
324
|
+
return { error: "projections requires timeline" };
|
|
325
|
+
}
|
|
326
|
+
if (hasProjections && !Array.isArray(rawProjections.timeline)) {
|
|
327
|
+
return { error: "projections.timeline must be an array" };
|
|
328
|
+
}
|
|
329
|
+
const invalidTimelineIndex = hasProjections
|
|
330
|
+
? rawProjections.timeline.findIndex((item, index) => !normalizeWorkflowTimelineProjection(item, index))
|
|
331
|
+
: -1;
|
|
332
|
+
if (invalidTimelineIndex >= 0) {
|
|
333
|
+
return { error: `projections.timeline[${invalidTimelineIndex}] requires kind and id` };
|
|
334
|
+
}
|
|
335
|
+
const projections = hasProjections ? normalizeWorkflowProjectionState(rawProjections) : null;
|
|
336
|
+
|
|
337
|
+
const rawExtensions = plainObject(payload.extensions);
|
|
338
|
+
const hasExtensions = Object.keys(rawExtensions).length > 0;
|
|
339
|
+
const extensions = hasExtensions ? normalizeWorkflowExtensions(rawExtensions) : null;
|
|
340
|
+
if (hasExtensions && !Object.keys(extensions).length) {
|
|
341
|
+
return { error: "extensions requires at least one valid namespace object" };
|
|
342
|
+
}
|
|
208
343
|
|
|
209
344
|
const rawGlobalState = plainObject(payload.globalState || payload.global_state);
|
|
210
345
|
const hasGlobalState = Object.keys(rawGlobalState).length > 0;
|
|
@@ -215,8 +350,8 @@ export function normalizeWorkflowReport(payload = {}) {
|
|
|
215
350
|
if (hasGlobalState && !Object.keys(globalStatePatch).length && !globalStateRemove.length) {
|
|
216
351
|
return { error: "globalState requires patch or remove" };
|
|
217
352
|
}
|
|
218
|
-
if (!action && !artifacts.length && !hasGlobalState) {
|
|
219
|
-
return { error: "Workflow report requires action, artifacts, or
|
|
353
|
+
if (!action && !artifacts.length && !hasGlobalState && !hasProjections && !hasExtensions && !hasObservation) {
|
|
354
|
+
return { error: "Workflow report requires observation, action, artifacts, globalState, projections, or extensions" };
|
|
220
355
|
}
|
|
221
356
|
|
|
222
357
|
const idempotencyKey = cleanString(
|
|
@@ -229,7 +364,7 @@ export function normalizeWorkflowReport(payload = {}) {
|
|
|
229
364
|
const event = {
|
|
230
365
|
schemaVersion,
|
|
231
366
|
type: "workflow-report",
|
|
232
|
-
source
|
|
367
|
+
source,
|
|
233
368
|
workflow,
|
|
234
369
|
workflowKey: workflow.key,
|
|
235
370
|
aggregateByStage: Boolean(action),
|
|
@@ -257,6 +392,8 @@ export function normalizeWorkflowReport(payload = {}) {
|
|
|
257
392
|
scope: "global",
|
|
258
393
|
}),
|
|
259
394
|
artifacts,
|
|
395
|
+
...(hasProjections ? { projections } : {}),
|
|
396
|
+
...(hasExtensions ? { extensionsPatch: extensions } : {}),
|
|
260
397
|
...(hasGlobalState ? {
|
|
261
398
|
globalStatePatch,
|
|
262
399
|
globalStateRemove,
|
|
@@ -268,6 +405,10 @@ export function normalizeWorkflowReport(payload = {}) {
|
|
|
268
405
|
workflow,
|
|
269
406
|
action,
|
|
270
407
|
artifacts,
|
|
408
|
+
projections,
|
|
409
|
+
extensions,
|
|
410
|
+
observation,
|
|
411
|
+
hasRuntimeUpdate: Boolean(action || artifacts.length || hasGlobalState || hasProjections || hasExtensions),
|
|
271
412
|
globalState: hasGlobalState ? {
|
|
272
413
|
mode: "merge",
|
|
273
414
|
patch: globalStatePatch,
|
|
@@ -408,20 +549,22 @@ export function mergeWorkflowArtifactLists(left = [], right = [], defaultScope =
|
|
|
408
549
|
};
|
|
409
550
|
const artifactAliases = (artifact) => {
|
|
410
551
|
const aliases = [];
|
|
552
|
+
const producer = cleanString(artifact?.producer || artifact?.reportSource || artifact?.report_source, 120).toLowerCase();
|
|
553
|
+
const ownedAlias = (alias) => producer ? `producer:${producer}:${alias}` : alias;
|
|
411
554
|
const explicitKey = cleanString(
|
|
412
555
|
artifact?.key || artifact?.artifactKey || artifact?.artifact_key,
|
|
413
556
|
500,
|
|
414
557
|
);
|
|
415
|
-
if (explicitKey) aliases.push(`key:${explicitKey}`);
|
|
558
|
+
if (explicitKey) aliases.push(ownedAlias(`key:${explicitKey}`));
|
|
416
559
|
const url = normalizedUrl(
|
|
417
560
|
artifact?.canonicalUrl
|
|
418
561
|
|| artifact?.canonical_url
|
|
419
562
|
|| artifact?.href
|
|
420
563
|
|| artifact?.url,
|
|
421
564
|
);
|
|
422
|
-
if (url) aliases.push(`url:${url}`);
|
|
565
|
+
if (url) aliases.push(ownedAlias(`url:${url}`));
|
|
423
566
|
const artifactPath = cleanString(artifact?.path, 4000);
|
|
424
|
-
if (artifactPath) aliases.push(`path:${artifactPath}`);
|
|
567
|
+
if (artifactPath) aliases.push(ownedAlias(`path:${artifactPath}`));
|
|
425
568
|
return aliases;
|
|
426
569
|
};
|
|
427
570
|
const add = (artifact) => {
|
|
@@ -448,7 +591,7 @@ export function mergeWorkflowArtifactLists(left = [], right = [], defaultScope =
|
|
|
448
591
|
return out;
|
|
449
592
|
}
|
|
450
593
|
|
|
451
|
-
export function workflowRuntimeRevision(globalState = {}, artifacts = [], runtimeEvents = []) {
|
|
594
|
+
export function workflowRuntimeRevision(globalState = {}, artifacts = [], runtimeEvents = [], projections = {}, extensions = {}) {
|
|
452
595
|
const events = (Array.isArray(runtimeEvents) ? runtimeEvents : []).map((event) => ({
|
|
453
596
|
id: event?.id || "",
|
|
454
597
|
action: event?.action || event?.actionId || "",
|
|
@@ -457,10 +600,12 @@ export function workflowRuntimeRevision(globalState = {}, artifacts = [], runtim
|
|
|
457
600
|
artifacts: event?.artifacts || [],
|
|
458
601
|
globalStatePatch: event?.globalStatePatch || {},
|
|
459
602
|
globalStateRemove: event?.globalStateRemove || [],
|
|
603
|
+
projections: event?.projections || {},
|
|
604
|
+
extensionsPatch: event?.extensionsPatch || {},
|
|
460
605
|
}));
|
|
461
606
|
const hash = crypto
|
|
462
607
|
.createHash("sha256")
|
|
463
|
-
.update(JSON.stringify(stableValue({ globalState, artifacts, events })))
|
|
608
|
+
.update(JSON.stringify(stableValue({ globalState, artifacts, projections, extensions, events })))
|
|
464
609
|
.digest("hex")
|
|
465
610
|
.slice(0, 24);
|
|
466
611
|
return `runtime:${hash}`;
|