@fieldwangai/agentflow 0.1.118 → 0.1.119

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.
@@ -7778,7 +7778,7 @@ function prdWorkflowReviewIdFromRequest(tapdId, payload = {}, durability = "temp
7778
7778
  return prdWorkflowSafeStateId(["review", tapdId, stageHead, digest].filter(Boolean).join("-")).slice(0, 64);
7779
7779
  }
7780
7780
 
7781
- function prdWorkflowReviewArtifactKey(tapdId, payload = {}, durability = "temporary") {
7781
+ function prdWorkflowReviewArtifactKey(tapdId, payload = {}) {
7782
7782
  const explicit = String(payload.artifactKey || payload.artifact_key || "").trim();
7783
7783
  if (explicit) return explicit.slice(0, 500);
7784
7784
  const issueKey = prdWorkflowSafeStateId(
@@ -7800,7 +7800,6 @@ function prdWorkflowReviewArtifactKey(tapdId, payload = {}, durability = "tempor
7800
7800
  issueKey,
7801
7801
  platform,
7802
7802
  stage,
7803
- String(durability || "temporary").trim().toLowerCase() || "temporary",
7804
7803
  ].join(":").slice(0, 500);
7805
7804
  }
7806
7805
 
@@ -9096,16 +9095,54 @@ function prdWorkflowNormalizeStoredRuntimeEvent(tapdId, event = {}) {
9096
9095
  const kind = String(item.kind || "").trim();
9097
9096
  const hasReviewUrl = /\/api\/prd-workflow\/review\//.test(String(item.url || item.href || ""));
9098
9097
  if (!kind && !hasReviewUrl) return item;
9098
+ const originalKey = String(item.key || item.artifactKey || item.artifact_key || "").trim();
9099
+ const logicalKey = /^prd-review:/i.test(originalKey)
9100
+ ? originalKey.replace(/:(?:temporary|durable)$/i, "")
9101
+ : originalKey && !/^(?:temporary-)?review:https?:/i.test(originalKey)
9102
+ ? originalKey
9103
+ : prdWorkflowReviewArtifactKey(tapdId, out);
9099
9104
  return {
9100
9105
  ...item,
9106
+ key: logicalKey,
9101
9107
  persistence: item.persistence || "runtime",
9102
9108
  source: item.source && typeof item.source === "object" && !Array.isArray(item.source) ? item.source : sourceArtifact,
9103
9109
  };
9104
9110
  };
9105
9111
  if (Array.isArray(out.artifacts)) out.artifacts = out.artifacts.map(normalizeReviewRef);
9106
9112
  if (Array.isArray(out.links)) out.links = out.links.map(normalizeReviewRef);
9107
- }
9113
+ const reviewArtifactKey = String(
9114
+ out.artifacts?.[0]?.key
9115
+ || out.links?.[0]?.key
9116
+ || "",
9117
+ ).trim();
9118
+ out.aggregateByStage = false;
9119
+ if (reviewArtifactKey) out.id = `review-link:${reviewArtifactKey}`;
9120
+ }
9121
+ const canonicalStage = prdWorkflowRuntimeEventCanonicalStage(out);
9122
+ const canonicalAction = prdWorkflowRuntimeEventCanonicalAction(canonicalStage);
9123
+ const rawStage = String(out.stageKey || out.stage_key || out.stage || "").trim();
9124
+ if (canonicalStage) {
9125
+ if (rawStage && rawStage !== canonicalStage) out.sourceStage = out.sourceStage || rawStage;
9126
+ out.stage = canonicalStage;
9127
+ out.stageKey = canonicalStage;
9128
+ }
9129
+ if (canonicalAction && (type === "workflow-marker" || String(out.action || "") === "mark")) {
9130
+ out.action = canonicalAction;
9131
+ out.actionId = canonicalAction;
9132
+ }
9133
+ if (type === "workflow-report" && !out.action && (
9134
+ String(out.artifactScope || out.artifact_scope || out.scope || "").toLowerCase() === "global"
9135
+ || out.aggregateByStage === false
9136
+ || out.aggregate_by_stage === false
9137
+ )) {
9138
+ out.auxiliary = true;
9139
+ }
9140
+ out.artifacts = prdWorkflowRuntimeOwnedArtifacts(out.artifacts, canonicalStage);
9141
+ out.links = prdWorkflowRuntimeOwnedArtifacts(out.links, canonicalStage);
9108
9142
  out.tapdId = String(out.tapdId || out.tapd_id || tapdId || "");
9143
+ const canonicalId = prdWorkflowRuntimeEventId(out);
9144
+ if (out.id && out.id !== canonicalId) out.sourceEventId = out.sourceEventId || out.id;
9145
+ out.id = canonicalId;
9109
9146
  return out;
9110
9147
  }
9111
9148
 
@@ -9158,15 +9195,63 @@ function prdWorkflowRuntimeEventStatus(type, status) {
9158
9195
  function prdWorkflowRuntimeEventCanonicalStage(event = {}) {
9159
9196
  const issue = String(event.issueKey || event.issue_key || event.issue || "").trim();
9160
9197
  const action = String(event.action || event.actionId || event.action_id || "").trim();
9161
- const rawStage = String(event.stage || event.stageKey || event.stage_key || event.phase || event.code || action || "").trim();
9162
- const text = [rawStage, action, event.code, event.type, event.title].map((value) => String(value || "")).join(" ").toLowerCase();
9198
+ const rawStage = String(event.stageKey || event.stage_key || event.stage || event.phase || event.code || action || "").trim();
9199
+ const normalizedStage = rawStage.toLowerCase();
9200
+ const tokens = [rawStage, action, event.code, event.type]
9201
+ .map((value) => String(value || "").trim().toLowerCase())
9202
+ .filter(Boolean);
9163
9203
  if (issue) {
9164
- if (/plan_draft_local|submit-plan|plan-doc/.test(text)) return `issue-plan:${issue}`;
9165
- if (/gitlab_issue_missing|ensure-gitlab-issue/.test(text)) return `issue-gitlab:${issue}`;
9204
+ if (/^(?:issue-plan|issue-gitlab|implementation|bugfix|integration):/.test(normalizedStage)) return rawStage;
9205
+ if (tokens.some((value) => /^code-review(?::|$)/.test(value) || value === "code_review_completed")) {
9206
+ return `implementation:${issue}`;
9207
+ }
9208
+ if (tokens.some((value) => /plan_draft_local|submit-plan|plan-doc/.test(value) || ["plan_mr", "plan_approved", "issue-plan"].includes(value))) {
9209
+ return `issue-plan:${issue}`;
9210
+ }
9211
+ if (tokens.some((value) => /gitlab_issue_missing|ensure-gitlab-issue/.test(value) || value === "issue-gitlab")) {
9212
+ return `issue-gitlab:${issue}`;
9213
+ }
9214
+ if (tokens.some((value) => ["fix_mr", "bugfix"].includes(value))) return `bugfix:${issue}`;
9215
+ if (tokens.some((value) => ["integration_mr", "integrated", "integration"].includes(value))) return `integration:${issue}`;
9216
+ if (tokens.some((value) => [
9217
+ "implementation_mr",
9218
+ "implementation_done",
9219
+ "implementation_merged",
9220
+ "impl_mr",
9221
+ "impl_done",
9222
+ "impl_merged",
9223
+ "runtime_marker",
9224
+ "status",
9225
+ "implementation",
9226
+ ].includes(value))) {
9227
+ return `implementation:${issue}`;
9228
+ }
9166
9229
  }
9167
9230
  return rawStage || action;
9168
9231
  }
9169
9232
 
9233
+ function prdWorkflowRuntimeEventCanonicalAction(stage = "") {
9234
+ const prefix = String(stage || "").trim().split(":", 1)[0];
9235
+ return ["issue-plan", "issue-gitlab", "implementation", "bugfix", "integration"].includes(prefix)
9236
+ ? prefix
9237
+ : "";
9238
+ }
9239
+
9240
+ function prdWorkflowRuntimeOwnedArtifacts(values, stage = "") {
9241
+ if (!Array.isArray(values)) return values;
9242
+ const ownsOnlyChangedArtifact = /^(?:issue-plan|implementation|bugfix|integration):/.test(String(stage || ""));
9243
+ if (!ownsOnlyChangedArtifact) return values;
9244
+ return values.filter((item) => {
9245
+ if (!item || typeof item !== "object" || Array.isArray(item)) return true;
9246
+ const kind = String(item.kind || item.type || "").trim().toLowerCase();
9247
+ const key = String(item.key || item.artifactKey || item.artifact_key || "").trim().toLowerCase();
9248
+ return !(
9249
+ ["gitlab-epic", "gitlab-issue"].includes(kind)
9250
+ || /^(?:gitlab-epic|gitlab-issue):/.test(key)
9251
+ );
9252
+ });
9253
+ }
9254
+
9170
9255
  function prdWorkflowRuntimeEventId(event = {}) {
9171
9256
  const stage = prdWorkflowRuntimeEventCanonicalStage(event);
9172
9257
  const action = String(event.action || event.actionId || event.action_id || "").trim();
@@ -9203,8 +9288,13 @@ function prdWorkflowCompactRuntimeValue(value, maxChars = 24000) {
9203
9288
  function prdWorkflowNormalizeRuntimeEvent(tapdId, event = {}) {
9204
9289
  const now = new Date().toISOString();
9205
9290
  const type = String(event.type || event.kind || "workflow-event").trim().slice(0, 120);
9206
- const action = String(event.action || event.actionId || event.action_id || "").trim().slice(0, 160);
9207
- const stage = String(event.stage || event.stageKey || event.stage_key || event.phase || action || "").trim().slice(0, 160);
9291
+ const rawAction = String(event.action || event.actionId || event.action_id || "").trim().slice(0, 160);
9292
+ const rawStage = String(event.stageKey || event.stage_key || event.stage || event.phase || rawAction || "").trim().slice(0, 160);
9293
+ const stage = prdWorkflowRuntimeEventCanonicalStage(event).slice(0, 160);
9294
+ const canonicalAction = prdWorkflowRuntimeEventCanonicalAction(stage);
9295
+ const action = canonicalAction && (type === "workflow-marker" || rawAction === "mark")
9296
+ ? canonicalAction
9297
+ : rawAction;
9208
9298
  const scope = String(event.scope || "").trim().slice(0, 80);
9209
9299
  const platform = String(event.platform || "").trim().slice(0, 80);
9210
9300
  const status = prdWorkflowRuntimeEventStatus(type, event.status);
@@ -9230,6 +9320,7 @@ function prdWorkflowNormalizeRuntimeEvent(tapdId, event = {}) {
9230
9320
  authority,
9231
9321
  updatedAt: now,
9232
9322
  };
9323
+ if (rawStage && rawStage !== stage) entry.sourceStage = rawStage;
9233
9324
  const sourceEventId = String(event.id || event.eventId || event.event_id || "").trim();
9234
9325
  if (sourceEventId && sourceEventId !== entry.id) entry.sourceEventId = sourceEventId.slice(0, 160);
9235
9326
  if (action) {
@@ -9238,8 +9329,10 @@ function prdWorkflowNormalizeRuntimeEvent(tapdId, event = {}) {
9238
9329
  }
9239
9330
  if (stage) {
9240
9331
  entry.stage = stage;
9241
- entry.stageKey = String(event.stageKey || event.stage_key || stage);
9332
+ entry.stageKey = stage;
9242
9333
  }
9334
+ entry.artifacts = prdWorkflowRuntimeOwnedArtifacts(entry.artifacts, stage);
9335
+ entry.links = prdWorkflowRuntimeOwnedArtifacts(entry.links, stage);
9243
9336
  if (scope) entry.scope = scope;
9244
9337
  if (platform) entry.platform = platform;
9245
9338
  if (!entry.createdAt) entry.createdAt = event.startedAt || now;
@@ -9258,26 +9351,50 @@ function prdWorkflowNormalizeRuntimeEvent(tapdId, event = {}) {
9258
9351
  function prdWorkflowMergeRuntimeEventArrays(left, right) {
9259
9352
  const out = [];
9260
9353
  const seen = new Map();
9354
+ const aliasesFor = (value) => {
9355
+ if (typeof value === "string") return [`value:${value}`];
9356
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
9357
+ const aliases = [];
9358
+ const explicitKey = String(value.key || value.artifactKey || value.artifact_key || "").trim();
9359
+ if (explicitKey) aliases.push(`key:${explicitKey}`);
9360
+ const rawUrl = String(
9361
+ value.canonicalUrl
9362
+ || value.canonical_url
9363
+ || value.href
9364
+ || value.url
9365
+ || "",
9366
+ ).trim();
9367
+ if (rawUrl) {
9368
+ try {
9369
+ const parsed = new URL(rawUrl, "http://agentflow.local");
9370
+ aliases.push(`url:${parsed.origin}${parsed.pathname.replace(/\/+$/, "") || "/"}`);
9371
+ } catch {
9372
+ aliases.push(`url:${rawUrl.split(/[?#]/)[0].replace(/\/+$/, "")}`);
9373
+ }
9374
+ }
9375
+ const itemPath = String(value.path || "").trim();
9376
+ if (itemPath) aliases.push(`path:${itemPath}`);
9377
+ if (!aliases.length) {
9378
+ try {
9379
+ aliases.push(`value:${JSON.stringify(value)}`);
9380
+ } catch {
9381
+ aliases.push(`value:${String(value)}`);
9382
+ }
9383
+ }
9384
+ return aliases;
9385
+ };
9261
9386
  for (const value of [...(Array.isArray(left) ? left : []), ...(Array.isArray(right) ? right : [])]) {
9262
9387
  if (value == null) continue;
9263
- const explicitKey = value && typeof value === "object" && !Array.isArray(value)
9264
- ? String(value.key || value.artifactKey || value.artifact_key || "").trim()
9265
- : "";
9266
- let key = explicitKey ? `key:${explicitKey}` : "";
9267
- try {
9268
- if (!key) key = typeof value === "string" ? value : JSON.stringify(value);
9269
- } catch {
9270
- key = String(value);
9271
- }
9272
- const index = seen.get(key);
9388
+ const aliases = aliasesFor(value);
9389
+ const index = aliases.map((alias) => seen.get(alias)).find((candidate) => candidate != null);
9273
9390
  if (index == null) {
9274
- seen.set(key, out.length);
9391
+ const nextIndex = out.length;
9275
9392
  out.push(value);
9393
+ aliases.forEach((alias) => seen.set(alias, nextIndex));
9276
9394
  continue;
9277
9395
  }
9278
- if (explicitKey) {
9279
- out[index] = value;
9280
- }
9396
+ out[index] = value;
9397
+ aliasesFor(value).forEach((alias) => seen.set(alias, index));
9281
9398
  }
9282
9399
  return out;
9283
9400
  }
@@ -12368,7 +12485,15 @@ export function startUiServer({
12368
12485
  const shortUrl = shortLink?.shortUrl || "";
12369
12486
  const displayUrl = shortUrl || reviewUrl;
12370
12487
  const durability = review.durability || "temporary";
12371
- const artifactKey = prdWorkflowReviewArtifactKey(tapdId, payload, durability);
12488
+ const artifactKey = prdWorkflowReviewArtifactKey(tapdId, payload);
12489
+ const reviewStageKey = prdWorkflowRuntimeEventCanonicalStage(payload)
12490
+ || payload.stageKey
12491
+ || payload.stage_key
12492
+ || payload.stage
12493
+ || "review";
12494
+ const reviewMrUrl = String(payload.mrUrl || payload.mr_url || "").trim();
12495
+ const reviewMrIid = String(payload.mrIid || payload.mr_iid || "").trim();
12496
+ const reviewCommitSha = String(payload.commitSha || payload.commit_sha || "").trim();
12372
12497
  const reviewSource = review.source && typeof review.source === "object" && !Array.isArray(review.source)
12373
12498
  ? review.source
12374
12499
  : { kind: durability === "durable" ? "ai-doc" : "local-draft", durability };
@@ -12387,19 +12512,32 @@ export function startUiServer({
12387
12512
  canonicalUrl: reviewUrl,
12388
12513
  shortUrl,
12389
12514
  expiresAt: review.expiresAt || "",
12515
+ issueKey: payload.issueKey || payload.issue_key || "",
12516
+ platform: payload.platform || "",
12517
+ stageKey: reviewStageKey,
12518
+ ...(reviewMrUrl ? { mrUrl: reviewMrUrl } : {}),
12519
+ ...(reviewMrIid ? { mrIid: reviewMrIid } : {}),
12520
+ ...(reviewCommitSha ? { commitSha: reviewCommitSha } : {}),
12390
12521
  };
12391
12522
  const event = prdWorkflowAppendRuntimeEvent(scopedRoot, tapdId, {
12523
+ id: `review-link:${artifactKey}`,
12392
12524
  type: "review-link",
12393
12525
  auxiliary: true,
12526
+ aggregateByStage: false,
12394
12527
  conflictOnArtifact: false,
12395
12528
  truth: "runtime_event",
12396
12529
  persistence: "runtime",
12397
12530
  action: payload.action || payload.actionId || "",
12398
- stage: payload.stage || payload.stageKey || payload.stage_key || "review",
12531
+ stage: reviewStageKey,
12532
+ stageKey: reviewStageKey,
12399
12533
  title: payload.title || "临时 Markdown Review",
12400
12534
  detail: "已生成临时 Markdown review 链接",
12401
12535
  status: "current",
12402
12536
  issueKey: payload.issueKey || payload.issue_key || "",
12537
+ platform: payload.platform || "",
12538
+ ...(reviewMrUrl ? { mrUrl: reviewMrUrl } : {}),
12539
+ ...(reviewMrIid ? { mrIid: reviewMrIid } : {}),
12540
+ ...(reviewCommitSha ? { commitSha: reviewCommitSha } : {}),
12403
12541
  idempotencyKey,
12404
12542
  durability,
12405
12543
  sourceArtifact: reviewSource,
@@ -12416,6 +12554,12 @@ export function startUiServer({
12416
12554
  durability,
12417
12555
  source: reviewSource,
12418
12556
  expiresAt: review.expiresAt || "",
12557
+ issueKey: artifact.issueKey,
12558
+ platform: artifact.platform,
12559
+ stageKey: artifact.stageKey,
12560
+ ...(artifact.mrUrl ? { mrUrl: artifact.mrUrl } : {}),
12561
+ ...(artifact.mrIid ? { mrIid: artifact.mrIid } : {}),
12562
+ ...(artifact.commitSha ? { commitSha: artifact.commitSha } : {}),
12419
12563
  }],
12420
12564
  reviewId: review.id,
12421
12565
  reviewShortCode: shortLink?.shortCode || "",
@@ -233,6 +233,7 @@ export function normalizeWorkflowReport(payload = {}) {
233
233
  workflow,
234
234
  workflowKey: workflow.key,
235
235
  aggregateByStage: Boolean(action),
236
+ auxiliary: !action,
236
237
  conflictOnArtifact: payload.conflictOnArtifact === true || payload.conflict_on_artifact === true,
237
238
  artifactScope: action ? "action" : "global",
238
239
  ...(action ? {
@@ -395,16 +396,51 @@ export function mergeWorkflowArtifacts(baseArtifacts = [], runtimeEvents = []) {
395
396
  export function mergeWorkflowArtifactLists(left = [], right = [], defaultScope = "action") {
396
397
  const out = [];
397
398
  const seen = new Map();
399
+ const normalizedUrl = (value) => {
400
+ const raw = cleanString(value, 4000);
401
+ if (!raw) return "";
402
+ try {
403
+ const parsed = new URL(raw, "http://agentflow.local");
404
+ return `${parsed.origin}${parsed.pathname.replace(/\/+$/, "") || "/"}`;
405
+ } catch {
406
+ return raw.split(/[?#]/)[0].replace(/\/+$/, "");
407
+ }
408
+ };
409
+ const artifactAliases = (artifact) => {
410
+ const aliases = [];
411
+ const explicitKey = cleanString(
412
+ artifact?.key || artifact?.artifactKey || artifact?.artifact_key,
413
+ 500,
414
+ );
415
+ if (explicitKey) aliases.push(`key:${explicitKey}`);
416
+ const url = normalizedUrl(
417
+ artifact?.canonicalUrl
418
+ || artifact?.canonical_url
419
+ || artifact?.href
420
+ || artifact?.url,
421
+ );
422
+ if (url) aliases.push(`url:${url}`);
423
+ const artifactPath = cleanString(artifact?.path, 4000);
424
+ if (artifactPath) aliases.push(`path:${artifactPath}`);
425
+ return aliases;
426
+ };
398
427
  const add = (artifact) => {
399
428
  if (!artifact || typeof artifact !== "object" || Array.isArray(artifact)) return;
429
+ const rawAliases = artifactAliases(artifact);
400
430
  const normalized = normalizeWorkflowArtifact(artifact, out.length, defaultScope);
401
- const key = normalized.key || normalized.url || `${normalized.type}:${normalized.title}`;
402
- const existing = seen.get(key);
431
+ const aliases = uniqueValues([
432
+ ...rawAliases,
433
+ ...artifactAliases(normalized),
434
+ ...(!rawAliases.length ? [`value:${normalized.type}:${normalized.title}`] : []),
435
+ ]);
436
+ const existing = aliases.map((alias) => seen.get(alias)).find((value) => value != null);
403
437
  if (existing == null) {
404
- seen.set(key, out.length);
438
+ const index = out.length;
405
439
  out.push(normalized);
440
+ aliases.forEach((alias) => seen.set(alias, index));
406
441
  } else {
407
442
  out[existing] = { ...out[existing], ...normalized };
443
+ artifactAliases(out[existing]).forEach((alias) => seen.set(alias, existing));
408
444
  }
409
445
  };
410
446
  for (const artifact of Array.isArray(left) ? left : []) add(artifact);