oc-browser-relay 1.0.1 → 1.0.2
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/bundled-relay/index.js +654 -209
- package/bundled-relay/public/configs/pages/index.json +1 -0
- package/bundled-relay/public/configs/pages/sycm-taobao-home.json +124 -0
- package/bundled-relay/public/configs/pages/taobao-item-detail.json +8 -11
- package/bundled-relay/public/configs/pages/xiaohongshu-creator-publish.json +35 -9
- package/bundled-relay/public/configs/pages/xiaohongshu-web-explore.json +7 -7
- package/bundled-relay/public/configs/pages/xiaohongshu-web-search-result.json +7 -7
- package/bundled-relay/public/configs/sites/index.json +2 -1
- package/bundled-relay/public/configs/sites/sycm-taobao.json +13 -0
- package/bundled-relay/public/configs/task-templates/index.json +1 -1
- package/bundled-relay/public/configs/task-templates/sycm-taobao-home-live-metrics.json +99 -0
- package/bundled-relay/public/configs/task-templates/taobao-item-detail-comments.json +24 -11
- package/bundled-relay/public/configs/task-templates/xiaohongshu-creator-publish.json +6 -6
- package/bundled-relay/public/configs/task-templates/xiaohongshu-creator-save-draft.json +6 -6
- package/bundled-relay/public/configs/task-templates/xiaohongshu-web-search-notes.json +26 -15
- package/index.js +1 -1
- package/package.json +3 -3
- package/skills/oc-browser-relay-taobao/SKILL.md +13 -17
- package/skills/oc-browser-relay-xiaohongshu/SKILL.md +56 -28
- package/skills/oc-sycm-live-metrics/SKILL.md +109 -0
- package/bundled-relay/public/configs/task-templates/xiaohongshu_open_website.json +0 -24
package/bundled-relay/index.js
CHANGED
|
@@ -22641,6 +22641,7 @@ var ERROR_CODES = {
|
|
|
22641
22641
|
// 页面类
|
|
22642
22642
|
ERR_PAGE_NOT_SUPPORTED: "ERR_PAGE_NOT_SUPPORTED",
|
|
22643
22643
|
ERR_PAGE_NOT_READY: "ERR_PAGE_NOT_READY",
|
|
22644
|
+
ERR_PAGE_BLOCKED: "ERR_PAGE_BLOCKED",
|
|
22644
22645
|
ERR_PAGE_CHANGED: "ERR_PAGE_CHANGED",
|
|
22645
22646
|
ERR_FIELD_NOT_FOUND: "ERR_FIELD_NOT_FOUND",
|
|
22646
22647
|
ERR_ACTION_NOT_FOUND: "ERR_ACTION_NOT_FOUND",
|
|
@@ -23060,20 +23061,6 @@ var TemplateExecutor = class _TemplateExecutor {
|
|
|
23060
23061
|
}
|
|
23061
23062
|
return obj;
|
|
23062
23063
|
}
|
|
23063
|
-
evaluateCondition(condition, data) {
|
|
23064
|
-
try {
|
|
23065
|
-
if (condition.includes(".length")) {
|
|
23066
|
-
const fieldName = condition.replace(".length", "").trim();
|
|
23067
|
-
const value2 = data[fieldName];
|
|
23068
|
-
return Array.isArray(value2) ? value2.length > 0 : false;
|
|
23069
|
-
}
|
|
23070
|
-
const value = data[condition];
|
|
23071
|
-
return value !== void 0 && value !== null && value !== "";
|
|
23072
|
-
} catch (err) {
|
|
23073
|
-
console.error("[TemplateExecutor] \u6761\u4EF6\u5224\u65AD\u5931\u8D25:", condition, err);
|
|
23074
|
-
return false;
|
|
23075
|
-
}
|
|
23076
|
-
}
|
|
23077
23064
|
coerceArrayFields(template, data) {
|
|
23078
23065
|
const requiredFields = template.requiredFields ?? [];
|
|
23079
23066
|
const optionalFields = template.optionalFields ?? [];
|
|
@@ -23178,30 +23165,16 @@ ${topicLine}`;
|
|
|
23178
23165
|
resolvedData = this.mergeXiaohongshuTopicsIntoContent(template, resolvedData);
|
|
23179
23166
|
this.validateRequiredFields(template, resolvedData);
|
|
23180
23167
|
this.validateRules(template, resolvedData);
|
|
23181
|
-
const
|
|
23182
|
-
|
|
23183
|
-
|
|
23184
|
-
const shouldExecute = this.evaluateCondition(workflowStep.condition, resolvedData);
|
|
23185
|
-
if (!shouldExecute) continue;
|
|
23186
|
-
}
|
|
23187
|
-
steps.push({
|
|
23188
|
-
stepId: workflowStep.stepId,
|
|
23189
|
-
name: workflowStep.name || workflowStep.stepId,
|
|
23190
|
-
goal: workflowStep.goal,
|
|
23191
|
-
tool: workflowStep.tool,
|
|
23192
|
-
args: this.replaceObjectVariables(workflowStep.args, resolvedData),
|
|
23193
|
-
onFailure: workflowStep.onFailure,
|
|
23194
|
-
preconditions: workflowStep.preconditions,
|
|
23195
|
-
expectedObservation: workflowStep.expectedObservation,
|
|
23196
|
-
status: "pending"
|
|
23197
|
-
});
|
|
23168
|
+
const nodes = Array.isArray(template.nodes) ? this.replaceObjectVariables(template.nodes, resolvedData) : [];
|
|
23169
|
+
if (nodes.length === 0) {
|
|
23170
|
+
throw new Error("\u4EFB\u52A1\u6A21\u677F\u7F3A\u5C11 nodes \u5B9A\u4E49");
|
|
23198
23171
|
}
|
|
23199
23172
|
return {
|
|
23200
23173
|
taskType: template.taskType,
|
|
23201
23174
|
platform: template.platform,
|
|
23202
23175
|
payload: resolvedData,
|
|
23203
23176
|
context: template.siteId ? { siteId: template.siteId } : void 0,
|
|
23204
|
-
|
|
23177
|
+
nodes
|
|
23205
23178
|
};
|
|
23206
23179
|
}
|
|
23207
23180
|
async executePublishItem(template, item) {
|
|
@@ -23281,7 +23254,7 @@ function isActionRequiredWaitReason(waitReason) {
|
|
|
23281
23254
|
return false;
|
|
23282
23255
|
}
|
|
23283
23256
|
}
|
|
23284
|
-
function
|
|
23257
|
+
function mapTaskStatusToCurrentNodeStatus(status) {
|
|
23285
23258
|
switch (status) {
|
|
23286
23259
|
case "queued":
|
|
23287
23260
|
return "pending";
|
|
@@ -23312,8 +23285,8 @@ function mapToolNameToTaskOperation(tool) {
|
|
|
23312
23285
|
case "switch_tab":
|
|
23313
23286
|
case "apply_search_filters":
|
|
23314
23287
|
return "click";
|
|
23315
|
-
case "
|
|
23316
|
-
case "
|
|
23288
|
+
case "collect_search_list":
|
|
23289
|
+
case "collect_search_item_details":
|
|
23317
23290
|
case "collect_structured_data":
|
|
23318
23291
|
return "capture_response";
|
|
23319
23292
|
case "validate_page":
|
|
@@ -23324,12 +23297,12 @@ function mapToolNameToTaskOperation(tool) {
|
|
|
23324
23297
|
return "unknown";
|
|
23325
23298
|
}
|
|
23326
23299
|
}
|
|
23327
|
-
function buildTaskProgressView(
|
|
23328
|
-
if (!Array.isArray(
|
|
23300
|
+
function buildTaskProgressView(entries, currentEntryId, status, hint) {
|
|
23301
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
23329
23302
|
return void 0;
|
|
23330
23303
|
}
|
|
23331
|
-
const total =
|
|
23332
|
-
const currentIndex = typeof
|
|
23304
|
+
const total = entries.length;
|
|
23305
|
+
const currentIndex = typeof currentEntryId === "string" ? entries.findIndex((entry) => entry.nodeId === currentEntryId) : -1;
|
|
23333
23306
|
let current = 0;
|
|
23334
23307
|
if (currentIndex >= 0) {
|
|
23335
23308
|
current = currentIndex + 1;
|
|
@@ -23346,13 +23319,19 @@ function buildTaskProgressView(steps, currentStepId, status, hint) {
|
|
|
23346
23319
|
}
|
|
23347
23320
|
function buildTaskStatusView(input) {
|
|
23348
23321
|
const waitReason = input.waitReason ?? mapTaskStatusToWaitReason(input.status);
|
|
23349
|
-
const
|
|
23350
|
-
const
|
|
23351
|
-
|
|
23352
|
-
|
|
23353
|
-
|
|
23354
|
-
|
|
23355
|
-
|
|
23322
|
+
const progressEntries = Array.isArray(input.nodes) && input.nodes.length > 0 ? input.nodes.map((node) => ({ nodeId: node.nodeId })) : input.progressEntries;
|
|
23323
|
+
const progress = buildTaskProgressView(
|
|
23324
|
+
progressEntries,
|
|
23325
|
+
input.currentNodeId,
|
|
23326
|
+
input.status,
|
|
23327
|
+
input.progressHint
|
|
23328
|
+
);
|
|
23329
|
+
const resolvedCurrentNodeStatus = input.currentNodeStatus ?? mapTaskStatusToCurrentNodeStatus(input.status);
|
|
23330
|
+
const currentNode = input.currentNodeId && resolvedCurrentNodeStatus ? {
|
|
23331
|
+
nodeId: input.currentNodeId,
|
|
23332
|
+
tool: input.currentNodeTool,
|
|
23333
|
+
name: input.currentNodeName,
|
|
23334
|
+
status: resolvedCurrentNodeStatus
|
|
23356
23335
|
} : void 0;
|
|
23357
23336
|
return {
|
|
23358
23337
|
status: mapTaskStatusToViewStatus(input.status),
|
|
@@ -23360,13 +23339,120 @@ function buildTaskStatusView(input) {
|
|
|
23360
23339
|
capability: input.capability,
|
|
23361
23340
|
currentOperation: input.currentOperation,
|
|
23362
23341
|
progress,
|
|
23363
|
-
|
|
23342
|
+
currentNode,
|
|
23343
|
+
browsingContext: input.browsingContext,
|
|
23364
23344
|
captureWindow: input.captureWindow,
|
|
23365
23345
|
lastArtifact: input.lastArtifact ?? null
|
|
23366
23346
|
};
|
|
23367
23347
|
}
|
|
23368
23348
|
|
|
23349
|
+
// relay/src/runtime-node-execution.ts
|
|
23350
|
+
function deriveNodeIdempotency(node) {
|
|
23351
|
+
if (node.idempotency) {
|
|
23352
|
+
return node.idempotency;
|
|
23353
|
+
}
|
|
23354
|
+
switch (node.tool) {
|
|
23355
|
+
case "get_page_state":
|
|
23356
|
+
case "validate_page":
|
|
23357
|
+
case "list_tabs":
|
|
23358
|
+
case "collect_search_list":
|
|
23359
|
+
case "collect_search_item_details":
|
|
23360
|
+
case "collect_structured_data":
|
|
23361
|
+
return "safe_retry";
|
|
23362
|
+
case "trigger_action":
|
|
23363
|
+
case "fill_field":
|
|
23364
|
+
case "switch_tab":
|
|
23365
|
+
case "open_tab":
|
|
23366
|
+
return "conditional_retry";
|
|
23367
|
+
case "upload_assets":
|
|
23368
|
+
case "ensure_publish_ready":
|
|
23369
|
+
return "non_idempotent";
|
|
23370
|
+
default:
|
|
23371
|
+
return "conditional_retry";
|
|
23372
|
+
}
|
|
23373
|
+
}
|
|
23374
|
+
function buildRecoveryAnchor(task, nodeId, status) {
|
|
23375
|
+
const activeContext = Array.isArray(task.browsingContexts) && task.currentContextId ? task.browsingContexts.find((context) => context.contextId === task.currentContextId) ?? null : null;
|
|
23376
|
+
return {
|
|
23377
|
+
nodeId,
|
|
23378
|
+
status,
|
|
23379
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23380
|
+
contextId: task.currentContextId,
|
|
23381
|
+
pageId: activeContext?.pageId ?? task.currentPageId,
|
|
23382
|
+
pageSignature: activeContext?.pageSignature ?? null,
|
|
23383
|
+
tabId: activeContext?.tabId ?? task.currentTabId,
|
|
23384
|
+
windowId: activeContext?.windowId,
|
|
23385
|
+
url: activeContext?.url
|
|
23386
|
+
};
|
|
23387
|
+
}
|
|
23388
|
+
function ensureTaskNodeResults(task) {
|
|
23389
|
+
task.payload.nodeResults = task.payload.nodeResults || {};
|
|
23390
|
+
const nodes = Array.isArray(task.payload.nodes) ? task.payload.nodes : [];
|
|
23391
|
+
for (const node of nodes) {
|
|
23392
|
+
const previous = task.payload.nodeResults[node.nodeId];
|
|
23393
|
+
task.payload.nodeResults[node.nodeId] = {
|
|
23394
|
+
nodeId: node.nodeId,
|
|
23395
|
+
status: previous?.status ?? "pending",
|
|
23396
|
+
attempts: previous?.attempts ?? 0,
|
|
23397
|
+
lastUpdatedAt: previous?.lastUpdatedAt,
|
|
23398
|
+
idempotency: previous?.idempotency ?? deriveNodeIdempotency(node),
|
|
23399
|
+
recoveryAnchor: previous?.recoveryAnchor ?? null,
|
|
23400
|
+
error: previous?.error ?? null,
|
|
23401
|
+
result: previous?.result ?? null
|
|
23402
|
+
};
|
|
23403
|
+
}
|
|
23404
|
+
return task.payload.nodeResults;
|
|
23405
|
+
}
|
|
23406
|
+
function markNodeDispatched(task, node) {
|
|
23407
|
+
const nodeResults = ensureTaskNodeResults(task);
|
|
23408
|
+
const previous = nodeResults[node.nodeId];
|
|
23409
|
+
nodeResults[node.nodeId] = {
|
|
23410
|
+
nodeId: node.nodeId,
|
|
23411
|
+
status: "running",
|
|
23412
|
+
attempts: (previous?.attempts ?? 0) + 1,
|
|
23413
|
+
lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23414
|
+
idempotency: previous?.idempotency ?? deriveNodeIdempotency(node),
|
|
23415
|
+
recoveryAnchor: buildRecoveryAnchor(task, node.nodeId, "running"),
|
|
23416
|
+
error: null,
|
|
23417
|
+
result: previous?.result ?? null
|
|
23418
|
+
};
|
|
23419
|
+
}
|
|
23420
|
+
function updateNodeExecutionStatus(task, nodeId, status, options) {
|
|
23421
|
+
const nodeResults = ensureTaskNodeResults(task);
|
|
23422
|
+
const previous = nodeResults[nodeId];
|
|
23423
|
+
if (!previous) {
|
|
23424
|
+
return;
|
|
23425
|
+
}
|
|
23426
|
+
nodeResults[nodeId] = {
|
|
23427
|
+
...previous,
|
|
23428
|
+
status,
|
|
23429
|
+
lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23430
|
+
recoveryAnchor: buildRecoveryAnchor(task, nodeId, status),
|
|
23431
|
+
error: options?.error ?? previous.error ?? null,
|
|
23432
|
+
result: options?.result ?? previous.result ?? null
|
|
23433
|
+
};
|
|
23434
|
+
}
|
|
23435
|
+
|
|
23369
23436
|
// relay/src/task-status-view.ts
|
|
23437
|
+
function buildMirroredSteps(task) {
|
|
23438
|
+
const nodes = Array.isArray(task.payload?.nodes) ? task.payload.nodes : [];
|
|
23439
|
+
const nodeResults = task.payload?.nodeResults || {};
|
|
23440
|
+
return nodes.map((node) => {
|
|
23441
|
+
const nodeResult = nodeResults[node.nodeId];
|
|
23442
|
+
return {
|
|
23443
|
+
nodeId: node.nodeId,
|
|
23444
|
+
name: node.name || node.nodeId,
|
|
23445
|
+
goal: node.goal,
|
|
23446
|
+
tool: node.tool,
|
|
23447
|
+
args: node.args,
|
|
23448
|
+
onFailure: node.onFailure,
|
|
23449
|
+
preconditions: node.preconditions,
|
|
23450
|
+
expectedObservation: node.expectedObservation,
|
|
23451
|
+
status: nodeResult?.status === "pending" ? "pending" : nodeResult?.status === "running" ? "running" : nodeResult?.status === "skipped" ? "skipped" : nodeResult?.status === "failed" ? "failed" : "success",
|
|
23452
|
+
result: nodeResult?.result ?? null
|
|
23453
|
+
};
|
|
23454
|
+
});
|
|
23455
|
+
}
|
|
23370
23456
|
function resolveTaskCapability(task, captureCapability) {
|
|
23371
23457
|
if (captureCapability) {
|
|
23372
23458
|
return captureCapability;
|
|
@@ -23374,7 +23460,6 @@ function resolveTaskCapability(task, captureCapability) {
|
|
|
23374
23460
|
switch (task.type) {
|
|
23375
23461
|
case "publish_note":
|
|
23376
23462
|
case "save_note_draft":
|
|
23377
|
-
case "open_website":
|
|
23378
23463
|
case "browser_action":
|
|
23379
23464
|
case "search_notes":
|
|
23380
23465
|
return "browser";
|
|
@@ -23395,22 +23480,44 @@ function isCaptureOperation(operation) {
|
|
|
23395
23480
|
return false;
|
|
23396
23481
|
}
|
|
23397
23482
|
}
|
|
23483
|
+
function mapProcessStatusToRuntimeNodeStatus(status) {
|
|
23484
|
+
switch (status) {
|
|
23485
|
+
case "running":
|
|
23486
|
+
case "waiting":
|
|
23487
|
+
return "running";
|
|
23488
|
+
case "succeeded":
|
|
23489
|
+
return "success";
|
|
23490
|
+
case "failed":
|
|
23491
|
+
return "failed";
|
|
23492
|
+
case "skipped":
|
|
23493
|
+
return "skipped";
|
|
23494
|
+
default:
|
|
23495
|
+
return "pending";
|
|
23496
|
+
}
|
|
23497
|
+
}
|
|
23398
23498
|
function applyTaskStatusView(task, overrides) {
|
|
23399
|
-
const
|
|
23400
|
-
const
|
|
23401
|
-
const
|
|
23402
|
-
const
|
|
23499
|
+
const nodes = Array.isArray(task.payload?.nodes) ? task.payload.nodes : [];
|
|
23500
|
+
const steps = buildMirroredSteps(task);
|
|
23501
|
+
const currentNodeId = overrides?.currentNodeId ?? task.currentNodeId;
|
|
23502
|
+
const matchedStep = currentNodeId ? steps.find((step) => step.nodeId === currentNodeId) : void 0;
|
|
23503
|
+
const matchedNode = currentNodeId ? nodes.find((node) => node.nodeId === currentNodeId) : void 0;
|
|
23504
|
+
const nextOperation = overrides?.currentOperation ?? mapToolNameToTaskOperation(overrides?.currentNodeTool ?? matchedStep?.tool);
|
|
23403
23505
|
const captureWindow = overrides?.captureWindow ?? task.statusView?.captureWindow;
|
|
23404
23506
|
task.statusView = buildTaskStatusView({
|
|
23405
23507
|
status: task.status,
|
|
23406
|
-
steps,
|
|
23407
|
-
|
|
23408
|
-
|
|
23409
|
-
|
|
23410
|
-
|
|
23508
|
+
progressEntries: steps,
|
|
23509
|
+
nodes,
|
|
23510
|
+
currentNodeId: matchedNode?.nodeId ?? currentNodeId,
|
|
23511
|
+
currentNodeTool: overrides?.currentNodeTool ?? matchedStep?.tool,
|
|
23512
|
+
currentNodeName: overrides?.currentNodeName ?? matchedNode?.name ?? matchedStep?.name,
|
|
23513
|
+
currentNodeStatus: overrides?.currentNodeStatus,
|
|
23411
23514
|
capability: resolveTaskCapability(task, captureWindow?.capability),
|
|
23412
23515
|
currentOperation: nextOperation,
|
|
23413
23516
|
waitReason: overrides?.waitReason,
|
|
23517
|
+
browsingContext: task.browsingContexts?.length ? {
|
|
23518
|
+
activeContextId: task.currentContextId,
|
|
23519
|
+
contexts: task.browsingContexts
|
|
23520
|
+
} : void 0,
|
|
23414
23521
|
captureWindow,
|
|
23415
23522
|
lastArtifact: overrides?.lastArtifact ?? task.statusView?.lastArtifact,
|
|
23416
23523
|
progressHint: overrides?.progressHint
|
|
@@ -23428,25 +23535,22 @@ function resolveCaptureWindowForStepProcess(task, currentOperation) {
|
|
|
23428
23535
|
}
|
|
23429
23536
|
return captureWindow;
|
|
23430
23537
|
}
|
|
23431
|
-
function
|
|
23432
|
-
const
|
|
23433
|
-
const
|
|
23434
|
-
|
|
23435
|
-
|
|
23436
|
-
|
|
23437
|
-
|
|
23438
|
-
|
|
23439
|
-
|
|
23440
|
-
|
|
23441
|
-
} else if (payload.status === "skipped") {
|
|
23442
|
-
matchedStep.status = "skipped";
|
|
23443
|
-
}
|
|
23538
|
+
function applyTaskNodeProcessView(task, payload) {
|
|
23539
|
+
const nodes = Array.isArray(task.payload?.nodes) ? task.payload.nodes : [];
|
|
23540
|
+
const steps = buildMirroredSteps(task);
|
|
23541
|
+
const matchedStep = steps.find((step) => step.nodeId === payload.nodeId);
|
|
23542
|
+
const matchedNode = nodes.find((node) => node.nodeId === payload.nodeId);
|
|
23543
|
+
if (matchedNode) {
|
|
23544
|
+
task.currentNodeId = matchedNode.nodeId;
|
|
23545
|
+
}
|
|
23546
|
+
if (matchedNode) {
|
|
23547
|
+
updateNodeExecutionStatus(task, payload.nodeId, mapProcessStatusToRuntimeNodeStatus(payload.status));
|
|
23444
23548
|
}
|
|
23445
23549
|
applyTaskStatusView(task, {
|
|
23446
|
-
|
|
23447
|
-
|
|
23448
|
-
|
|
23449
|
-
|
|
23550
|
+
currentNodeId: payload.nodeId,
|
|
23551
|
+
currentNodeTool: payload.tool ?? matchedStep?.tool,
|
|
23552
|
+
currentNodeName: payload.name ?? matchedNode?.name ?? matchedStep?.name,
|
|
23553
|
+
currentNodeStatus: payload.status,
|
|
23450
23554
|
currentOperation: payload.currentOperation,
|
|
23451
23555
|
waitReason: "waitReason" in payload ? payload.waitReason : void 0,
|
|
23452
23556
|
captureWindow: resolveCaptureWindowForStepProcess(task, payload.currentOperation)
|
|
@@ -23454,10 +23558,10 @@ function applyTaskStepProcessView(task, payload) {
|
|
|
23454
23558
|
if (!task.statusView) {
|
|
23455
23559
|
return;
|
|
23456
23560
|
}
|
|
23457
|
-
task.statusView.
|
|
23458
|
-
|
|
23561
|
+
task.statusView.currentNode = {
|
|
23562
|
+
nodeId: payload.nodeId,
|
|
23459
23563
|
tool: payload.tool ?? matchedStep?.tool,
|
|
23460
|
-
name: payload.name ?? matchedStep?.name,
|
|
23564
|
+
name: payload.name ?? matchedNode?.name ?? matchedStep?.name,
|
|
23461
23565
|
status: payload.status
|
|
23462
23566
|
};
|
|
23463
23567
|
task.statusView.currentOperation = payload.currentOperation ?? task.statusView.currentOperation;
|
|
@@ -23555,28 +23659,28 @@ var TaskReadyRegistry = class {
|
|
|
23555
23659
|
}
|
|
23556
23660
|
};
|
|
23557
23661
|
|
|
23558
|
-
// relay/src/
|
|
23559
|
-
function
|
|
23662
|
+
// relay/src/node-result-guard.ts
|
|
23663
|
+
function guardNodeResult(task, orchestrator, result) {
|
|
23560
23664
|
if (!task) {
|
|
23561
23665
|
return { accept: false, reason: "task_missing" };
|
|
23562
23666
|
}
|
|
23563
23667
|
if (!orchestrator) {
|
|
23564
23668
|
return { accept: false, reason: "orchestrator_missing" };
|
|
23565
23669
|
}
|
|
23566
|
-
const
|
|
23567
|
-
if (!
|
|
23568
|
-
return { accept: false, reason: "
|
|
23670
|
+
const expectedNode = task.payload?.nodes?.[orchestrator.currentStepIndex];
|
|
23671
|
+
if (!expectedNode) {
|
|
23672
|
+
return { accept: false, reason: "node_missing" };
|
|
23569
23673
|
}
|
|
23570
|
-
if (
|
|
23674
|
+
if (expectedNode.nodeId !== result.nodeId) {
|
|
23571
23675
|
return {
|
|
23572
23676
|
accept: false,
|
|
23573
|
-
reason: "
|
|
23574
|
-
|
|
23677
|
+
reason: "node_mismatch",
|
|
23678
|
+
expectedNodeId: expectedNode.nodeId
|
|
23575
23679
|
};
|
|
23576
23680
|
}
|
|
23577
23681
|
return {
|
|
23578
23682
|
accept: true,
|
|
23579
|
-
|
|
23683
|
+
expectedNodeId: expectedNode.nodeId
|
|
23580
23684
|
};
|
|
23581
23685
|
}
|
|
23582
23686
|
|
|
@@ -23585,6 +23689,8 @@ function isTerminalTaskStatus(status) {
|
|
|
23585
23689
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
23586
23690
|
}
|
|
23587
23691
|
function buildTaskFinalResult(task) {
|
|
23692
|
+
const nodes = task.payload?.nodes || [];
|
|
23693
|
+
const nodeResults = task.payload?.nodeResults || {};
|
|
23588
23694
|
return {
|
|
23589
23695
|
taskId: task.taskId,
|
|
23590
23696
|
type: task.type,
|
|
@@ -23592,40 +23698,327 @@ function buildTaskFinalResult(task) {
|
|
|
23592
23698
|
status: task.status,
|
|
23593
23699
|
statusView: task.statusView,
|
|
23594
23700
|
lastError: task.lastError ?? null,
|
|
23595
|
-
|
|
23701
|
+
currentNodeId: task.currentNodeId,
|
|
23702
|
+
currentContextId: task.currentContextId,
|
|
23703
|
+
resolvedContextId: task.resolvedContextId,
|
|
23704
|
+
candidateChildContextIds: task.candidateChildContextIds ?? [],
|
|
23705
|
+
lastTriggeredNavigation: task.lastTriggeredNavigation ?? null,
|
|
23706
|
+
browsingContexts: task.browsingContexts ?? [],
|
|
23596
23707
|
updatedAt: task.updatedAt,
|
|
23597
|
-
steps:
|
|
23598
|
-
|
|
23599
|
-
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
|
|
23603
|
-
|
|
23708
|
+
steps: nodes.map((node) => {
|
|
23709
|
+
const nodeResult = nodeResults[node.nodeId];
|
|
23710
|
+
return {
|
|
23711
|
+
nodeId: node.nodeId,
|
|
23712
|
+
name: node.name,
|
|
23713
|
+
tool: node.tool,
|
|
23714
|
+
status: nodeResult?.status === "pending" ? "pending" : nodeResult?.status === "running" ? "running" : nodeResult?.status === "skipped" ? "skipped" : nodeResult?.status === "failed" ? "failed" : "success",
|
|
23715
|
+
result: nodeResult?.result ?? null
|
|
23716
|
+
};
|
|
23717
|
+
}),
|
|
23718
|
+
nodes: nodes.map((node) => {
|
|
23719
|
+
const mirroredNodeResult = nodeResults[node.nodeId];
|
|
23720
|
+
return {
|
|
23721
|
+
nodeId: node.nodeId,
|
|
23722
|
+
name: node.name,
|
|
23723
|
+
tool: node.tool,
|
|
23724
|
+
status: mirroredNodeResult?.status ?? "pending",
|
|
23725
|
+
attempts: mirroredNodeResult?.attempts ?? 0,
|
|
23726
|
+
lastUpdatedAt: mirroredNodeResult?.lastUpdatedAt,
|
|
23727
|
+
idempotency: mirroredNodeResult?.idempotency,
|
|
23728
|
+
recoveryAnchor: mirroredNodeResult?.recoveryAnchor ?? null,
|
|
23729
|
+
error: mirroredNodeResult?.error ?? null,
|
|
23730
|
+
result: mirroredNodeResult?.result ?? null
|
|
23731
|
+
};
|
|
23732
|
+
}),
|
|
23604
23733
|
lastArtifact: task.statusView?.lastArtifact ?? null
|
|
23605
23734
|
};
|
|
23606
23735
|
}
|
|
23607
23736
|
|
|
23608
|
-
//
|
|
23609
|
-
function
|
|
23737
|
+
// shared/node-template-compiler.ts
|
|
23738
|
+
function deriveOnFailurePolicyFromRetry(node) {
|
|
23739
|
+
if (node.onFailure) {
|
|
23740
|
+
return node.onFailure;
|
|
23741
|
+
}
|
|
23742
|
+
if (!node.retry || node.retry.attempts <= 1) {
|
|
23743
|
+
return void 0;
|
|
23744
|
+
}
|
|
23745
|
+
if (node.retry.attempts === 2) {
|
|
23746
|
+
return { policy: "retry_once" };
|
|
23747
|
+
}
|
|
23748
|
+
return { policy: "retry_twice" };
|
|
23749
|
+
}
|
|
23750
|
+
function buildRuntimeNodeMeta(node) {
|
|
23751
|
+
const runtimeNodeMeta = {};
|
|
23752
|
+
if (node.inputs?.length) {
|
|
23753
|
+
runtimeNodeMeta.inputs = node.inputs;
|
|
23754
|
+
}
|
|
23755
|
+
if (node.outputs?.length) {
|
|
23756
|
+
runtimeNodeMeta.outputs = node.outputs;
|
|
23757
|
+
}
|
|
23758
|
+
if (node.fromContext && Object.keys(node.fromContext).length > 0) {
|
|
23759
|
+
runtimeNodeMeta.fromContext = node.fromContext;
|
|
23760
|
+
}
|
|
23761
|
+
if (typeof node.storeAs === "string" && node.storeAs.length > 0) {
|
|
23762
|
+
runtimeNodeMeta.storeAs = node.storeAs;
|
|
23763
|
+
}
|
|
23764
|
+
if (typeof node.outputScope === "string" && node.outputScope.length > 0) {
|
|
23765
|
+
runtimeNodeMeta.outputScope = node.outputScope;
|
|
23766
|
+
}
|
|
23767
|
+
if (typeof node.timeoutMs === "number" && Number.isFinite(node.timeoutMs) && node.timeoutMs > 0) {
|
|
23768
|
+
runtimeNodeMeta.timeoutMs = node.timeoutMs;
|
|
23769
|
+
}
|
|
23770
|
+
if (typeof node.optional === "boolean") {
|
|
23771
|
+
runtimeNodeMeta.optional = node.optional;
|
|
23772
|
+
}
|
|
23773
|
+
if (node.assert?.length) {
|
|
23774
|
+
runtimeNodeMeta.assert = node.assert;
|
|
23775
|
+
}
|
|
23776
|
+
if (node.fallback) {
|
|
23777
|
+
runtimeNodeMeta.fallback = node.fallback;
|
|
23778
|
+
}
|
|
23779
|
+
if (node.retry) {
|
|
23780
|
+
runtimeNodeMeta.retry = node.retry;
|
|
23781
|
+
}
|
|
23782
|
+
if (typeof node.when === "string" && node.when.trim().length > 0) {
|
|
23783
|
+
runtimeNodeMeta.when = node.when;
|
|
23784
|
+
}
|
|
23785
|
+
return Object.keys(runtimeNodeMeta).length > 0 ? runtimeNodeMeta : void 0;
|
|
23786
|
+
}
|
|
23787
|
+
function compileNodeToExecution(node) {
|
|
23788
|
+
const runtimeNodeMeta = buildRuntimeNodeMeta(node);
|
|
23789
|
+
return {
|
|
23790
|
+
nodeId: node.nodeId,
|
|
23791
|
+
name: node.name || node.nodeId,
|
|
23792
|
+
goal: node.goal,
|
|
23793
|
+
tool: node.tool,
|
|
23794
|
+
args: runtimeNodeMeta ? {
|
|
23795
|
+
...node.args,
|
|
23796
|
+
__runtimeNode: runtimeNodeMeta
|
|
23797
|
+
} : node.args,
|
|
23798
|
+
onFailure: deriveOnFailurePolicyFromRetry(node),
|
|
23799
|
+
preconditions: node.preconditions,
|
|
23800
|
+
expectedObservation: node.expectedObservation,
|
|
23801
|
+
status: "pending"
|
|
23802
|
+
};
|
|
23803
|
+
}
|
|
23804
|
+
|
|
23805
|
+
// relay/src/runtime-node-fallback.ts
|
|
23806
|
+
function readRuntimeNodeFallback(task, stepIndex) {
|
|
23807
|
+
const node = task.payload?.nodes?.[stepIndex];
|
|
23808
|
+
return node?.fallback ?? null;
|
|
23809
|
+
}
|
|
23810
|
+
function resolveFallbackStepIndex(task, currentStepIndex, result) {
|
|
23811
|
+
if (result.ok) {
|
|
23812
|
+
return null;
|
|
23813
|
+
}
|
|
23814
|
+
const fallback = readRuntimeNodeFallback(task, currentStepIndex);
|
|
23815
|
+
if (!fallback || fallback.policy === "abort") {
|
|
23816
|
+
return null;
|
|
23817
|
+
}
|
|
23818
|
+
if (fallback.nodeId) {
|
|
23819
|
+
const nextIndex = Array.isArray(task.payload?.nodes) ? task.payload.nodes.findIndex((node) => node.nodeId === fallback.nodeId) : -1;
|
|
23820
|
+
return nextIndex >= 0 ? nextIndex : null;
|
|
23821
|
+
}
|
|
23822
|
+
if (fallback.policy === "continue") {
|
|
23823
|
+
return currentStepIndex + 1;
|
|
23824
|
+
}
|
|
23825
|
+
return null;
|
|
23826
|
+
}
|
|
23827
|
+
|
|
23828
|
+
// relay/src/task-node-result.ts
|
|
23829
|
+
function mapNodeResultToExecutionStatus(result) {
|
|
23610
23830
|
return result.ok ? "success" : "failed";
|
|
23611
23831
|
}
|
|
23612
|
-
function
|
|
23832
|
+
function normalizeNodeResult(result, normalizedError) {
|
|
23613
23833
|
return {
|
|
23614
23834
|
...result,
|
|
23615
23835
|
error: normalizedError
|
|
23616
23836
|
};
|
|
23617
23837
|
}
|
|
23618
|
-
function
|
|
23619
|
-
const
|
|
23620
|
-
const
|
|
23621
|
-
if (!
|
|
23838
|
+
function persistNodeResultOnTask(task, result) {
|
|
23839
|
+
const nodes = Array.isArray(task.payload?.nodes) ? task.payload.nodes : [];
|
|
23840
|
+
const matchedNode = nodes.find((node) => node.nodeId === result.nodeId);
|
|
23841
|
+
if (!matchedNode) {
|
|
23622
23842
|
return false;
|
|
23623
23843
|
}
|
|
23624
|
-
|
|
23625
|
-
|
|
23844
|
+
updateNodeExecutionStatus(task, result.nodeId, mapNodeResultToExecutionStatus(result), {
|
|
23845
|
+
result,
|
|
23846
|
+
error: result.error
|
|
23847
|
+
});
|
|
23626
23848
|
return true;
|
|
23627
23849
|
}
|
|
23628
23850
|
|
|
23851
|
+
// relay/src/runtime-task-orchestrator.ts
|
|
23852
|
+
function createTaskOrchestrator(task) {
|
|
23853
|
+
const executionLength = getTaskExecutionLength(task);
|
|
23854
|
+
if (executionLength === 0) {
|
|
23855
|
+
return null;
|
|
23856
|
+
}
|
|
23857
|
+
const recovery = resolveNodeExecutionRecovery(task);
|
|
23858
|
+
return {
|
|
23859
|
+
currentStepIndex: recovery?.index ?? 0,
|
|
23860
|
+
recovery: recovery?.state ?? null
|
|
23861
|
+
};
|
|
23862
|
+
}
|
|
23863
|
+
function hydrateTaskFromRecoveryAnchor(task, anchor) {
|
|
23864
|
+
if (!anchor) {
|
|
23865
|
+
return;
|
|
23866
|
+
}
|
|
23867
|
+
if (anchor.contextId) {
|
|
23868
|
+
task.currentContextId = anchor.contextId;
|
|
23869
|
+
}
|
|
23870
|
+
if (typeof anchor.tabId === "number") {
|
|
23871
|
+
task.currentTabId = anchor.tabId;
|
|
23872
|
+
}
|
|
23873
|
+
if (anchor.pageId) {
|
|
23874
|
+
task.currentPageId = anchor.pageId;
|
|
23875
|
+
}
|
|
23876
|
+
if (!anchor.contextId || typeof anchor.tabId !== "number") {
|
|
23877
|
+
return;
|
|
23878
|
+
}
|
|
23879
|
+
const browsingContexts = Array.isArray(task.browsingContexts) ? [...task.browsingContexts] : [];
|
|
23880
|
+
const existingIndex = browsingContexts.findIndex((context) => context.contextId === anchor.contextId);
|
|
23881
|
+
const nextContext = {
|
|
23882
|
+
contextId: anchor.contextId,
|
|
23883
|
+
tabId: anchor.tabId,
|
|
23884
|
+
windowId: anchor.windowId,
|
|
23885
|
+
url: anchor.url,
|
|
23886
|
+
pageId: anchor.pageId,
|
|
23887
|
+
pageSignature: anchor.pageSignature ?? null,
|
|
23888
|
+
role: "active",
|
|
23889
|
+
origin: "detected",
|
|
23890
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
23891
|
+
};
|
|
23892
|
+
if (existingIndex >= 0) {
|
|
23893
|
+
browsingContexts[existingIndex] = {
|
|
23894
|
+
...browsingContexts[existingIndex],
|
|
23895
|
+
...nextContext
|
|
23896
|
+
};
|
|
23897
|
+
} else {
|
|
23898
|
+
browsingContexts.push(nextContext);
|
|
23899
|
+
}
|
|
23900
|
+
task.browsingContexts = browsingContexts;
|
|
23901
|
+
}
|
|
23902
|
+
function resolveNodeExecutionRecovery(task) {
|
|
23903
|
+
const nodes = Array.isArray(task.payload?.nodes) ? task.payload.nodes : [];
|
|
23904
|
+
if (nodes.length === 0) {
|
|
23905
|
+
return {
|
|
23906
|
+
index: 0,
|
|
23907
|
+
state: null
|
|
23908
|
+
};
|
|
23909
|
+
}
|
|
23910
|
+
const nodeResults = ensureTaskNodeResults(task);
|
|
23911
|
+
for (let index = 0; index < nodes.length; index += 1) {
|
|
23912
|
+
const node = nodes[index];
|
|
23913
|
+
const nodeResult = nodeResults[node.nodeId];
|
|
23914
|
+
const status = nodeResult?.status ?? "pending";
|
|
23915
|
+
if (status === "success" || status === "skipped") {
|
|
23916
|
+
continue;
|
|
23917
|
+
}
|
|
23918
|
+
const anchor = nodeResult?.recoveryAnchor ?? null;
|
|
23919
|
+
hydrateTaskFromRecoveryAnchor(task, anchor);
|
|
23920
|
+
if (status === "running") {
|
|
23921
|
+
return {
|
|
23922
|
+
index,
|
|
23923
|
+
state: {
|
|
23924
|
+
nodeId: node.nodeId,
|
|
23925
|
+
anchor,
|
|
23926
|
+
reason: "resume_running"
|
|
23927
|
+
}
|
|
23928
|
+
};
|
|
23929
|
+
}
|
|
23930
|
+
if (status === "failed") {
|
|
23931
|
+
return {
|
|
23932
|
+
index,
|
|
23933
|
+
state: {
|
|
23934
|
+
nodeId: node.nodeId,
|
|
23935
|
+
anchor,
|
|
23936
|
+
reason: "retry_failed"
|
|
23937
|
+
}
|
|
23938
|
+
};
|
|
23939
|
+
}
|
|
23940
|
+
return {
|
|
23941
|
+
index,
|
|
23942
|
+
state: index > 0 ? {
|
|
23943
|
+
nodeId: node.nodeId,
|
|
23944
|
+
anchor,
|
|
23945
|
+
reason: "resume_after_completed_prefix"
|
|
23946
|
+
} : null
|
|
23947
|
+
};
|
|
23948
|
+
}
|
|
23949
|
+
return {
|
|
23950
|
+
index: nodes.length,
|
|
23951
|
+
state: null
|
|
23952
|
+
};
|
|
23953
|
+
}
|
|
23954
|
+
function getTaskExecutionLength(task) {
|
|
23955
|
+
return Array.isArray(task.payload?.nodes) ? task.payload.nodes.length : 0;
|
|
23956
|
+
}
|
|
23957
|
+
function resolveTaskExecutionStep(task, index) {
|
|
23958
|
+
const node = task.payload?.nodes?.[index];
|
|
23959
|
+
if (!node) {
|
|
23960
|
+
return null;
|
|
23961
|
+
}
|
|
23962
|
+
const compiledNode = compileNodeToExecution(node);
|
|
23963
|
+
const nodeResults = ensureTaskNodeResults(task);
|
|
23964
|
+
const nodeResult = nodeResults[node.nodeId];
|
|
23965
|
+
return {
|
|
23966
|
+
...compiledNode,
|
|
23967
|
+
status: nodeResult?.status === "pending" ? "pending" : nodeResult?.status === "running" ? "running" : nodeResult?.status === "skipped" ? "skipped" : nodeResult?.status === "failed" ? "failed" : "success",
|
|
23968
|
+
result: nodeResult?.result ?? null
|
|
23969
|
+
};
|
|
23970
|
+
}
|
|
23971
|
+
function resolveCurrentTaskExecutionStep(task, orchestrator) {
|
|
23972
|
+
return resolveTaskExecutionStep(task, orchestrator.currentStepIndex);
|
|
23973
|
+
}
|
|
23974
|
+
function markTaskExecutionDispatch(task, orchestrator) {
|
|
23975
|
+
const step = resolveCurrentTaskExecutionStep(task, orchestrator);
|
|
23976
|
+
if (!step) {
|
|
23977
|
+
return null;
|
|
23978
|
+
}
|
|
23979
|
+
task.status = "running";
|
|
23980
|
+
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23981
|
+
const activeNode = task.payload?.nodes?.[orchestrator.currentStepIndex];
|
|
23982
|
+
if (activeNode) {
|
|
23983
|
+
task.currentNodeId = activeNode.nodeId;
|
|
23984
|
+
ensureTaskNodeResults(task);
|
|
23985
|
+
markNodeDispatched(task, activeNode);
|
|
23986
|
+
}
|
|
23987
|
+
return step;
|
|
23988
|
+
}
|
|
23989
|
+
function advanceTaskOrchestrator(orchestrator, nextStepIndex) {
|
|
23990
|
+
if (typeof nextStepIndex === "number" && Number.isFinite(nextStepIndex) && nextStepIndex >= 0) {
|
|
23991
|
+
orchestrator.currentStepIndex = nextStepIndex;
|
|
23992
|
+
} else {
|
|
23993
|
+
orchestrator.currentStepIndex += 1;
|
|
23994
|
+
}
|
|
23995
|
+
return orchestrator.currentStepIndex;
|
|
23996
|
+
}
|
|
23997
|
+
function applyTaskExecutionResult(task, orchestrator, result) {
|
|
23998
|
+
const observationError = typeof result.observation?.error === "string" ? result.observation.error : void 0;
|
|
23999
|
+
const normalizedNodeError = result.error || (!result.ok ? {
|
|
24000
|
+
code: "ERR_STEP_EXECUTION_FAILED",
|
|
24001
|
+
message: observationError || "Step execution failed"
|
|
24002
|
+
} : null);
|
|
24003
|
+
const persistedNodeResult = normalizeNodeResult(result, normalizedNodeError);
|
|
24004
|
+
persistNodeResultOnTask(task, persistedNodeResult);
|
|
24005
|
+
const fallbackStepIndex = resolveFallbackStepIndex(
|
|
24006
|
+
task,
|
|
24007
|
+
orchestrator.currentStepIndex,
|
|
24008
|
+
persistedNodeResult
|
|
24009
|
+
);
|
|
24010
|
+
task.status = result.ok || fallbackStepIndex != null ? "running" : "failed";
|
|
24011
|
+
task.currentNodeId = result.nodeId;
|
|
24012
|
+
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
24013
|
+
task.lastError = result.ok || fallbackStepIndex != null ? null : normalizedNodeError;
|
|
24014
|
+
return {
|
|
24015
|
+
persistedNodeResult,
|
|
24016
|
+
fallbackStepIndex,
|
|
24017
|
+
shouldContinue: result.ok || fallbackStepIndex != null,
|
|
24018
|
+
nextStepIndex: result.ok ? orchestrator.currentStepIndex + 1 : fallbackStepIndex
|
|
24019
|
+
};
|
|
24020
|
+
}
|
|
24021
|
+
|
|
23629
24022
|
// relay/src/index.ts
|
|
23630
24023
|
var app = (0, import_express.default)();
|
|
23631
24024
|
var server = createServer(app);
|
|
@@ -23755,8 +24148,8 @@ function requireTaskRuntimeId(task) {
|
|
|
23755
24148
|
function updateTaskStatusView(task, overrides) {
|
|
23756
24149
|
applyTaskStatusView(task, overrides);
|
|
23757
24150
|
}
|
|
23758
|
-
function
|
|
23759
|
-
|
|
24151
|
+
function updateTaskNodeProcessView(task, payload) {
|
|
24152
|
+
applyTaskNodeProcessView(task, payload);
|
|
23760
24153
|
}
|
|
23761
24154
|
function removeBatchJobFromQueues(batchJobId, targetRuntimeId) {
|
|
23762
24155
|
if (targetRuntimeId) {
|
|
@@ -23843,13 +24236,32 @@ async function loadTaskTemplate(platform, taskType, siteId) {
|
|
|
23843
24236
|
});
|
|
23844
24237
|
throw new Error(`TaskTemplate not found: ${missingTemplateKey}`);
|
|
23845
24238
|
}
|
|
23846
|
-
function
|
|
23847
|
-
|
|
23848
|
-
|
|
23849
|
-
|
|
23850
|
-
|
|
23851
|
-
|
|
23852
|
-
}));
|
|
24239
|
+
async function hydrateTaskSubmissionWithTemplate(taskConfig) {
|
|
24240
|
+
if (Array.isArray(taskConfig.nodes) && taskConfig.nodes.length > 0) {
|
|
24241
|
+
return taskConfig;
|
|
24242
|
+
}
|
|
24243
|
+
const siteId = taskConfig.context?.siteId;
|
|
24244
|
+
const template = await loadTaskTemplate(taskConfig.platform, taskConfig.taskType, siteId);
|
|
24245
|
+
const baseSubmission = TemplateExecutor.isPublishItemTemplate(template) ? await templateExecutor.executePublishItem(template, TemplateExecutor.buildPublishItemInput(taskConfig.payload || {})) : await templateExecutor.execute(template, taskConfig.payload || {});
|
|
24246
|
+
return {
|
|
24247
|
+
...baseSubmission,
|
|
24248
|
+
taskType: taskConfig.taskType,
|
|
24249
|
+
platform: taskConfig.platform,
|
|
24250
|
+
targetRuntimeId: taskConfig.targetRuntimeId,
|
|
24251
|
+
sourceClientId: taskConfig.sourceClientId,
|
|
24252
|
+
context: {
|
|
24253
|
+
...baseSubmission.context,
|
|
24254
|
+
...taskConfig.context
|
|
24255
|
+
},
|
|
24256
|
+
payload: {
|
|
24257
|
+
...baseSubmission.payload || {},
|
|
24258
|
+
...taskConfig.payload || {}
|
|
24259
|
+
},
|
|
24260
|
+
options: {
|
|
24261
|
+
...baseSubmission.options,
|
|
24262
|
+
...taskConfig.options
|
|
24263
|
+
}
|
|
24264
|
+
};
|
|
23853
24265
|
}
|
|
23854
24266
|
function resolveImageRefs(noteSource, payload) {
|
|
23855
24267
|
const imageRefs = Array.isArray(payload.imageRefs) ? payload.imageRefs.map(String) : null;
|
|
@@ -23884,11 +24296,19 @@ async function prepareResolvedAssets(filePaths) {
|
|
|
23884
24296
|
}
|
|
23885
24297
|
return assets;
|
|
23886
24298
|
}
|
|
23887
|
-
function
|
|
24299
|
+
function extractDirectAssetPaths(taskConfig) {
|
|
24300
|
+
const payloadImageRefs = Array.isArray(taskConfig.payload?.imageRefs) ? taskConfig.payload.imageRefs.filter((value) => typeof value === "string") : [];
|
|
24301
|
+
if (payloadImageRefs.length > 0) {
|
|
24302
|
+
return payloadImageRefs;
|
|
24303
|
+
}
|
|
24304
|
+
const payloadImages = Array.isArray(taskConfig.payload?.images) ? taskConfig.payload.images.filter((value) => typeof value === "string") : [];
|
|
24305
|
+
if (payloadImages.length > 0) {
|
|
24306
|
+
return payloadImages;
|
|
24307
|
+
}
|
|
23888
24308
|
const paths = [];
|
|
23889
|
-
for (const
|
|
23890
|
-
if (
|
|
23891
|
-
for (const asset of
|
|
24309
|
+
for (const node of taskConfig.nodes || []) {
|
|
24310
|
+
if (node.tool === "upload_assets" && Array.isArray(node.args?.assets)) {
|
|
24311
|
+
for (const asset of node.args.assets) {
|
|
23892
24312
|
if (typeof asset === "string") {
|
|
23893
24313
|
paths.push(asset);
|
|
23894
24314
|
}
|
|
@@ -23897,14 +24317,14 @@ function extractLegacyUploadPaths(taskConfig) {
|
|
|
23897
24317
|
}
|
|
23898
24318
|
return paths;
|
|
23899
24319
|
}
|
|
23900
|
-
function
|
|
24320
|
+
function rewriteUploadNodesWithAssetIds(nodes, assets) {
|
|
23901
24321
|
const assetIds = assets.map((asset) => asset.fileId || asset.id);
|
|
23902
|
-
return
|
|
23903
|
-
if (
|
|
24322
|
+
return (nodes || []).map((node) => {
|
|
24323
|
+
if (node.tool !== "upload_assets") return node;
|
|
23904
24324
|
return {
|
|
23905
|
-
...
|
|
24325
|
+
...node,
|
|
23906
24326
|
args: {
|
|
23907
|
-
...
|
|
24327
|
+
...node.args,
|
|
23908
24328
|
assets: assetIds
|
|
23909
24329
|
}
|
|
23910
24330
|
};
|
|
@@ -23943,11 +24363,11 @@ async function assembleTaskFromSubmission(taskConfig, source) {
|
|
|
23943
24363
|
const relativeImages = resolveImageRefs(noteSource, normalizedPayload);
|
|
23944
24364
|
resolvedFilePaths = relativeImages.map((relativePath) => path3.resolve(workspace.rootDir, relativePath));
|
|
23945
24365
|
} else {
|
|
23946
|
-
resolvedFilePaths =
|
|
24366
|
+
resolvedFilePaths = extractDirectAssetPaths(taskConfig);
|
|
23947
24367
|
}
|
|
23948
24368
|
console.log(`[Relay] \u89E3\u6790\u7684\u6587\u4EF6\u8DEF\u5F84:`, resolvedFilePaths);
|
|
23949
24369
|
const assets = await prepareResolvedAssets(resolvedFilePaths);
|
|
23950
|
-
const
|
|
24370
|
+
const rewrittenNodes = rewriteUploadNodesWithAssetIds(taskConfig.nodes, assets);
|
|
23951
24371
|
const taskId = `task_${Date.now()}`;
|
|
23952
24372
|
const task = {
|
|
23953
24373
|
taskId,
|
|
@@ -23956,7 +24376,7 @@ async function assembleTaskFromSubmission(taskConfig, source) {
|
|
|
23956
24376
|
platform: taskConfig.platform,
|
|
23957
24377
|
payload: {
|
|
23958
24378
|
...normalizedPayload,
|
|
23959
|
-
|
|
24379
|
+
nodes: Array.isArray(rewrittenNodes) ? rewrittenNodes : void 0
|
|
23960
24380
|
},
|
|
23961
24381
|
assets,
|
|
23962
24382
|
options: {
|
|
@@ -23972,6 +24392,7 @@ async function assembleTaskFromSubmission(taskConfig, source) {
|
|
|
23972
24392
|
context: taskConfig.context,
|
|
23973
24393
|
lastError: null
|
|
23974
24394
|
};
|
|
24395
|
+
ensureTaskNodeResults(task);
|
|
23975
24396
|
updateTaskStatusView(task);
|
|
23976
24397
|
return task;
|
|
23977
24398
|
}
|
|
@@ -23987,14 +24408,13 @@ async function buildBatchItemSubmission(batchJob, item, itemIndex) {
|
|
|
23987
24408
|
images: item.images,
|
|
23988
24409
|
metadata: item.metadata
|
|
23989
24410
|
}));
|
|
23990
|
-
const steps = reindexSubmissionSteps(baseSubmission.steps || []);
|
|
23991
24411
|
console.log("[Relay] \u6279\u91CF\u6761\u76EE\u6D3E\u751F\u7ED3\u679C:", {
|
|
23992
24412
|
batchJobId: batchJob.batchJobId,
|
|
23993
24413
|
itemIndex,
|
|
23994
24414
|
noteSourceId: item.noteSourceId,
|
|
23995
24415
|
topicCount: Array.isArray(item.topics) ? item.topics.length : 0,
|
|
23996
24416
|
topics: item.topics || [],
|
|
23997
|
-
|
|
24417
|
+
nodeTools: (baseSubmission.nodes || []).map((node) => `${node.nodeId}:${node.tool}`),
|
|
23998
24418
|
contentTailPreview: typeof baseSubmission.payload?.content === "string" ? baseSubmission.payload.content.slice(-160) : ""
|
|
23999
24419
|
});
|
|
24000
24420
|
return {
|
|
@@ -24024,8 +24444,7 @@ async function buildBatchItemSubmission(batchJob, item, itemIndex) {
|
|
|
24024
24444
|
humanLike: true,
|
|
24025
24445
|
allowFallback: true,
|
|
24026
24446
|
requireConfirmation: false
|
|
24027
|
-
}
|
|
24028
|
-
steps
|
|
24447
|
+
}
|
|
24029
24448
|
};
|
|
24030
24449
|
}
|
|
24031
24450
|
async function dispatchTask(task) {
|
|
@@ -24045,7 +24464,7 @@ async function dispatchTask(task) {
|
|
|
24045
24464
|
siteId: task.context?.siteId,
|
|
24046
24465
|
batchJobId: task.context?.batchJobId,
|
|
24047
24466
|
batchItemIndex: task.context?.batchItemIndex,
|
|
24048
|
-
|
|
24467
|
+
nodeTools: task.payload?.nodes?.map((node) => `${node.nodeId}:${node.tool}`) || []
|
|
24049
24468
|
});
|
|
24050
24469
|
const taskMessage = {
|
|
24051
24470
|
type: "task.submit",
|
|
@@ -24245,7 +24664,8 @@ async function registerAndDispatchTask(task) {
|
|
|
24245
24664
|
return task;
|
|
24246
24665
|
}
|
|
24247
24666
|
async function submitTaskSubmission(taskConfig, source) {
|
|
24248
|
-
const
|
|
24667
|
+
const hydratedTaskConfig = await hydrateTaskSubmissionWithTemplate(taskConfig);
|
|
24668
|
+
const task = await assembleTaskFromSubmission(hydratedTaskConfig, source);
|
|
24249
24669
|
await registerAndDispatchTask(task);
|
|
24250
24670
|
return task;
|
|
24251
24671
|
}
|
|
@@ -24261,11 +24681,11 @@ async function handleRuntimeMessage(msg) {
|
|
|
24261
24681
|
case "task.status":
|
|
24262
24682
|
handleTaskStatus(msg);
|
|
24263
24683
|
break;
|
|
24264
|
-
case "
|
|
24265
|
-
|
|
24684
|
+
case "node.started":
|
|
24685
|
+
handleNodeStarted(msg);
|
|
24266
24686
|
break;
|
|
24267
|
-
case "
|
|
24268
|
-
|
|
24687
|
+
case "node.status":
|
|
24688
|
+
handleNodeStatus(msg);
|
|
24269
24689
|
break;
|
|
24270
24690
|
case "capture.started":
|
|
24271
24691
|
handleCaptureStarted(msg);
|
|
@@ -24276,8 +24696,8 @@ async function handleRuntimeMessage(msg) {
|
|
|
24276
24696
|
case "artifact.created":
|
|
24277
24697
|
handleArtifactCreated(msg);
|
|
24278
24698
|
break;
|
|
24279
|
-
case "
|
|
24280
|
-
|
|
24699
|
+
case "node.result":
|
|
24700
|
+
handleNodeResult(msg);
|
|
24281
24701
|
break;
|
|
24282
24702
|
case "runtime.query.result":
|
|
24283
24703
|
handleRuntimeQueryResult(msg);
|
|
@@ -24313,75 +24733,84 @@ function handleArtifactCreated(msg) {
|
|
|
24313
24733
|
}
|
|
24314
24734
|
applyArtifactCreatedToTask(task, payload);
|
|
24315
24735
|
}
|
|
24316
|
-
function
|
|
24736
|
+
function handleNodeStarted(msg) {
|
|
24317
24737
|
const payload = msg.payload;
|
|
24318
24738
|
const task = tasks.get(payload.taskId);
|
|
24319
24739
|
if (!task) {
|
|
24320
24740
|
return;
|
|
24321
24741
|
}
|
|
24322
|
-
task.
|
|
24742
|
+
task.currentNodeId = payload.nodeId;
|
|
24323
24743
|
task.updatedAt = payload.updatedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
24324
|
-
|
|
24744
|
+
updateTaskNodeProcessView(task, {
|
|
24745
|
+
taskId: payload.taskId,
|
|
24746
|
+
nodeId: payload.nodeId,
|
|
24747
|
+
tool: payload.tool,
|
|
24748
|
+
name: payload.name,
|
|
24749
|
+
status: payload.status,
|
|
24750
|
+
updatedAt: payload.updatedAt,
|
|
24751
|
+
currentOperation: payload.currentOperation
|
|
24752
|
+
});
|
|
24325
24753
|
}
|
|
24326
|
-
function
|
|
24754
|
+
function handleNodeStatus(msg) {
|
|
24327
24755
|
const payload = msg.payload;
|
|
24328
24756
|
const task = tasks.get(payload.taskId);
|
|
24329
24757
|
if (!task) {
|
|
24330
24758
|
return;
|
|
24331
24759
|
}
|
|
24332
|
-
task.
|
|
24760
|
+
task.currentNodeId = payload.nodeId;
|
|
24333
24761
|
task.updatedAt = payload.updatedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
24334
|
-
|
|
24762
|
+
updateTaskNodeProcessView(task, {
|
|
24763
|
+
taskId: payload.taskId,
|
|
24764
|
+
nodeId: payload.nodeId,
|
|
24765
|
+
tool: payload.tool,
|
|
24766
|
+
name: payload.name,
|
|
24767
|
+
status: payload.status,
|
|
24768
|
+
updatedAt: payload.updatedAt,
|
|
24769
|
+
currentOperation: payload.currentOperation,
|
|
24770
|
+
waitReason: payload.waitReason,
|
|
24771
|
+
message: payload.message
|
|
24772
|
+
});
|
|
24335
24773
|
}
|
|
24336
|
-
function
|
|
24337
|
-
const
|
|
24338
|
-
logRelayFlow("Received
|
|
24339
|
-
taskId:
|
|
24340
|
-
|
|
24341
|
-
ok:
|
|
24342
|
-
status:
|
|
24343
|
-
error:
|
|
24344
|
-
observation:
|
|
24774
|
+
function handleNodeResult(msg) {
|
|
24775
|
+
const rawResult = msg.payload;
|
|
24776
|
+
logRelayFlow("Received node result", {
|
|
24777
|
+
taskId: rawResult.taskId,
|
|
24778
|
+
nodeId: rawResult.nodeId,
|
|
24779
|
+
ok: rawResult.ok,
|
|
24780
|
+
status: rawResult.status,
|
|
24781
|
+
error: rawResult.error?.message,
|
|
24782
|
+
observation: rawResult.observation
|
|
24345
24783
|
});
|
|
24346
|
-
const task = tasks.get(
|
|
24347
|
-
const orchestrator = orchestrators.get(
|
|
24348
|
-
const decision =
|
|
24784
|
+
const task = tasks.get(rawResult.taskId);
|
|
24785
|
+
const orchestrator = orchestrators.get(rawResult.taskId);
|
|
24786
|
+
const decision = guardNodeResult(task, orchestrator, rawResult);
|
|
24349
24787
|
if (!decision.accept) {
|
|
24350
24788
|
if (decision.reason === "task_missing") {
|
|
24351
|
-
console.warn(`[Relay] \u5FFD\u7565
|
|
24789
|
+
console.warn(`[Relay] \u5FFD\u7565 node.result\uFF1A\u4EFB\u52A1\u4E0D\u5B58\u5728 (${rawResult.taskId})`);
|
|
24352
24790
|
} else if (decision.reason === "orchestrator_missing") {
|
|
24353
|
-
console.warn(`[Relay] \u5FFD\u7565
|
|
24354
|
-
} else if (decision.reason === "
|
|
24355
|
-
console.warn(`[Relay] \u5FFD\u7565
|
|
24791
|
+
console.warn(`[Relay] \u5FFD\u7565 node.result\uFF1A\u7F16\u6392\u5668\u4E0D\u5B58\u5728\uFF0C\u53EF\u80FD\u662F\u8FDF\u5230/\u91CD\u590D\u7ED3\u679C (${rawResult.taskId}/${rawResult.nodeId})`);
|
|
24792
|
+
} else if (decision.reason === "node_missing") {
|
|
24793
|
+
console.warn(`[Relay] \u5FFD\u7565 node.result\uFF1A\u5F53\u524D\u65E0\u53EF\u6267\u884C\u8282\u70B9\uFF0C\u53EF\u80FD\u662F\u8FDF\u5230\u7ED3\u679C (${rawResult.taskId}/${rawResult.nodeId})`);
|
|
24356
24794
|
} else {
|
|
24357
24795
|
console.warn(
|
|
24358
|
-
`[Relay] \u5FFD\u7565
|
|
24796
|
+
`[Relay] \u5FFD\u7565 node.result\uFF1Anode \u4E0D\u5339\u914D\uFF0Cexpected=${decision.expectedNodeId}, got=${rawResult.nodeId}, task=${rawResult.taskId}`
|
|
24359
24797
|
);
|
|
24360
24798
|
}
|
|
24361
24799
|
return;
|
|
24362
24800
|
}
|
|
24363
24801
|
const resolvedTask = task;
|
|
24364
|
-
const
|
|
24365
|
-
const
|
|
24366
|
-
code: ERROR_CODES.ERR_STEP_EXECUTION_FAILED,
|
|
24367
|
-
message: observationError || "Step execution failed"
|
|
24368
|
-
} : null);
|
|
24369
|
-
const persistedStepResult = normalizeStepResult(result, normalizedStepError);
|
|
24370
|
-
persistStepResultOnTask(resolvedTask, persistedStepResult);
|
|
24371
|
-
resolvedTask.status = result.ok ? "running" : "failed";
|
|
24372
|
-
resolvedTask.currentStepId = result.stepId;
|
|
24373
|
-
resolvedTask.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
24374
|
-
resolvedTask.lastError = result.ok ? null : normalizedStepError;
|
|
24802
|
+
const resolvedOrchestrator = orchestrator;
|
|
24803
|
+
const appliedResult = applyTaskExecutionResult(resolvedTask, resolvedOrchestrator, rawResult);
|
|
24375
24804
|
updateTaskStatusView(resolvedTask, {
|
|
24376
|
-
|
|
24377
|
-
|
|
24805
|
+
currentNodeId: rawResult.nodeId,
|
|
24806
|
+
currentNodeStatus: appliedResult.persistedNodeResult.ok ? "succeeded" : "failed"
|
|
24378
24807
|
});
|
|
24379
|
-
if (
|
|
24380
|
-
continueOrchestrator(
|
|
24808
|
+
if (appliedResult.shouldContinue) {
|
|
24809
|
+
continueOrchestrator(rawResult.taskId, rawResult.nodeId, appliedResult.nextStepIndex ?? void 0);
|
|
24381
24810
|
} else {
|
|
24382
|
-
orchestrators.delete(
|
|
24811
|
+
orchestrators.delete(rawResult.taskId);
|
|
24383
24812
|
notifyRuntimeTaskFinalized(resolvedTask, "failed");
|
|
24384
|
-
void handleBatchTaskTerminal(
|
|
24813
|
+
void handleBatchTaskTerminal(rawResult.taskId, "failed", resolvedTask.lastError);
|
|
24385
24814
|
}
|
|
24386
24815
|
}
|
|
24387
24816
|
function handleTaskStatus(msg) {
|
|
@@ -24391,21 +24820,26 @@ function handleTaskStatus(msg) {
|
|
|
24391
24820
|
logRelayFlow("Received task status", {
|
|
24392
24821
|
taskId: status.taskId,
|
|
24393
24822
|
status: status.status,
|
|
24394
|
-
|
|
24823
|
+
currentNodeId: status.currentNodeId,
|
|
24395
24824
|
currentPageId: status.currentPageId,
|
|
24396
24825
|
currentTabId: status.currentTabId,
|
|
24397
24826
|
error: status.lastError?.message
|
|
24398
24827
|
});
|
|
24399
24828
|
task.status = status.status;
|
|
24400
24829
|
task.lastError = status.lastError ?? task.lastError ?? null;
|
|
24401
|
-
task.
|
|
24830
|
+
task.currentNodeId = status.currentNodeId ?? task.currentNodeId;
|
|
24402
24831
|
task.currentPageId = status.currentPageId ?? task.currentPageId;
|
|
24403
24832
|
task.currentTabId = status.currentTabId ?? task.currentTabId;
|
|
24833
|
+
task.currentContextId = status.currentContextId ?? task.currentContextId;
|
|
24834
|
+
task.resolvedContextId = status.resolvedContextId ?? task.resolvedContextId;
|
|
24835
|
+
task.candidateChildContextIds = Array.isArray(status.candidateChildContextIds) ? status.candidateChildContextIds : task.candidateChildContextIds;
|
|
24836
|
+
task.lastTriggeredNavigation = status.lastTriggeredNavigation ?? task.lastTriggeredNavigation;
|
|
24837
|
+
task.browsingContexts = Array.isArray(status.browsingContexts) ? status.browsingContexts : task.browsingContexts;
|
|
24404
24838
|
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
24405
24839
|
task.statusView = status.statusView ?? task.statusView;
|
|
24406
24840
|
if (!task.statusView) {
|
|
24407
24841
|
updateTaskStatusView(task, {
|
|
24408
|
-
|
|
24842
|
+
currentNodeId: status.currentNodeId
|
|
24409
24843
|
});
|
|
24410
24844
|
}
|
|
24411
24845
|
if (status.status === "queued") {
|
|
@@ -24936,12 +25370,11 @@ app.post("/api/tools/:toolName/execute", async (req, res) => {
|
|
|
24936
25370
|
taskType: "browser_action",
|
|
24937
25371
|
platform: "browser",
|
|
24938
25372
|
payload: input,
|
|
24939
|
-
|
|
24940
|
-
|
|
25373
|
+
nodes: [{
|
|
25374
|
+
nodeId: toolName,
|
|
24941
25375
|
name: toolName,
|
|
24942
25376
|
tool: toolName,
|
|
24943
|
-
args: input
|
|
24944
|
-
status: "pending"
|
|
25377
|
+
args: input
|
|
24945
25378
|
}],
|
|
24946
25379
|
targetRuntimeId: effectiveRuntimeId
|
|
24947
25380
|
};
|
|
@@ -24964,7 +25397,7 @@ app.post("/api/tasks", async (req, res) => {
|
|
|
24964
25397
|
try {
|
|
24965
25398
|
const taskConfig = req.body;
|
|
24966
25399
|
console.log("[Relay] \u6536\u5230HTTP\u4EFB\u52A1\u63D0\u4EA4:", taskConfig);
|
|
24967
|
-
const task = await submitTaskSubmission(taskConfig, "
|
|
25400
|
+
const task = await submitTaskSubmission(taskConfig, "api");
|
|
24968
25401
|
const taskId = task.taskId;
|
|
24969
25402
|
console.log(`[Relay] \u4EFB\u52A1\u5DF2\u521B\u5EFA: ${taskId}\uFF0C\u5305\u542B ${task.assets.length} \u4E2A\u6587\u4EF6`);
|
|
24970
25403
|
res.json({ success: true, taskId, channel: "http" });
|
|
@@ -25068,12 +25501,14 @@ function startOrchestrator(taskId) {
|
|
|
25068
25501
|
console.error(`[Relay] \u4EFB\u52A1\u4E0D\u5B58\u5728: ${taskId}`);
|
|
25069
25502
|
return;
|
|
25070
25503
|
}
|
|
25071
|
-
|
|
25072
|
-
|
|
25504
|
+
const orchestrator = createTaskOrchestrator(task);
|
|
25505
|
+
if (!orchestrator) {
|
|
25506
|
+
console.error(`[Relay] \u4EFB\u52A1\u6CA1\u6709\u53EF\u6267\u884C\u8282\u70B9/\u6B65\u9AA4: ${taskId}`);
|
|
25073
25507
|
return;
|
|
25074
25508
|
}
|
|
25075
|
-
|
|
25076
|
-
|
|
25509
|
+
const executionLength = getTaskExecutionLength(task);
|
|
25510
|
+
console.log(`[Relay] \u4EFB\u52A1\u6309 nodes \u6267\u884C\uFF0C\u5171 ${executionLength} \u4E2A\u8282\u70B9`);
|
|
25511
|
+
orchestrators.set(taskId, orchestrator);
|
|
25077
25512
|
void sendNextStep(taskId);
|
|
25078
25513
|
}
|
|
25079
25514
|
async function sendNextStep(taskId) {
|
|
@@ -25088,17 +25523,17 @@ async function sendNextStep(taskId) {
|
|
|
25088
25523
|
console.error(`[Relay] \u7F16\u6392\u5668\u4E0D\u5B58\u5728: ${taskId}`);
|
|
25089
25524
|
return;
|
|
25090
25525
|
}
|
|
25091
|
-
|
|
25092
|
-
|
|
25526
|
+
const executionLength = getTaskExecutionLength(task);
|
|
25527
|
+
if (executionLength === 0) {
|
|
25528
|
+
console.error(`[Relay] \u4EFB\u52A1\u6CA1\u6709\u53EF\u6267\u884C\u8282\u70B9`);
|
|
25093
25529
|
return;
|
|
25094
25530
|
}
|
|
25095
|
-
|
|
25096
|
-
|
|
25097
|
-
if (orch.currentStepIndex >= steps.length) {
|
|
25531
|
+
console.log(`[Relay] \u5F53\u524D\u8282\u70B9\u7D22\u5F15: ${orch.currentStepIndex}, \u603B\u8282\u70B9\u6570: ${executionLength}`);
|
|
25532
|
+
if (orch.currentStepIndex >= executionLength) {
|
|
25098
25533
|
task.status = "completed";
|
|
25099
25534
|
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25100
25535
|
updateTaskStatusView(task, {
|
|
25101
|
-
|
|
25536
|
+
currentNodeId: task.currentNodeId
|
|
25102
25537
|
});
|
|
25103
25538
|
orchestrators.delete(taskId);
|
|
25104
25539
|
console.log(`[Relay] Task ${taskId} completed`);
|
|
@@ -25106,20 +25541,30 @@ async function sendNextStep(taskId) {
|
|
|
25106
25541
|
void handleBatchTaskTerminal(taskId, "completed", null);
|
|
25107
25542
|
return;
|
|
25108
25543
|
}
|
|
25109
|
-
const step =
|
|
25110
|
-
|
|
25111
|
-
|
|
25112
|
-
|
|
25544
|
+
const step = markTaskExecutionDispatch(task, orch);
|
|
25545
|
+
if (!step) {
|
|
25546
|
+
task.status = "failed";
|
|
25547
|
+
task.lastError = {
|
|
25548
|
+
code: ERROR_CODES.ERR_INVALID_TASK,
|
|
25549
|
+
message: `Unable to resolve executable node at index ${orch.currentStepIndex}`
|
|
25550
|
+
};
|
|
25551
|
+
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25552
|
+
updateTaskStatusView(task);
|
|
25553
|
+
orchestrators.delete(taskId);
|
|
25554
|
+
notifyRuntimeTaskFinalized(task, "failed");
|
|
25555
|
+
void handleBatchTaskTerminal(taskId, "failed", task.lastError);
|
|
25556
|
+
return;
|
|
25557
|
+
}
|
|
25113
25558
|
updateTaskStatusView(task, {
|
|
25114
|
-
|
|
25115
|
-
|
|
25116
|
-
|
|
25559
|
+
currentNodeId: task.currentNodeId ?? step.nodeId,
|
|
25560
|
+
currentNodeTool: step.tool,
|
|
25561
|
+
currentNodeName: step.name
|
|
25117
25562
|
});
|
|
25118
25563
|
const stepMessage = {
|
|
25119
|
-
type: "
|
|
25120
|
-
requestId: `
|
|
25564
|
+
type: "node.submit",
|
|
25565
|
+
requestId: `node_${taskId}_${orch.currentStepIndex}`,
|
|
25121
25566
|
timestamp: Date.now(),
|
|
25122
|
-
payload: { taskId, step }
|
|
25567
|
+
payload: { taskId, node: step }
|
|
25123
25568
|
};
|
|
25124
25569
|
let targetRuntimeId;
|
|
25125
25570
|
try {
|
|
@@ -25153,17 +25598,17 @@ async function sendNextStep(taskId) {
|
|
|
25153
25598
|
void handleBatchTaskTerminal(taskId, "failed", task.lastError);
|
|
25154
25599
|
return;
|
|
25155
25600
|
}
|
|
25156
|
-
console.log(`[Relay] Sent
|
|
25601
|
+
console.log(`[Relay] Sent node ${orch.currentStepIndex + 1}/${executionLength} for task ${taskId}`);
|
|
25157
25602
|
}
|
|
25158
|
-
function continueOrchestrator(taskId,
|
|
25159
|
-
console.log(`[Relay] continueOrchestrator \u88AB\u8C03\u7528: ${taskId},
|
|
25603
|
+
function continueOrchestrator(taskId, completedNodeId, nextStepIndex) {
|
|
25604
|
+
console.log(`[Relay] continueOrchestrator \u88AB\u8C03\u7528: ${taskId}, nodeId: ${completedNodeId}`);
|
|
25160
25605
|
const orch = orchestrators.get(taskId);
|
|
25161
25606
|
if (!orch) {
|
|
25162
25607
|
console.error(`[Relay] \u7F16\u6392\u5668\u4E0D\u5B58\u5728: ${taskId}`);
|
|
25163
25608
|
return;
|
|
25164
25609
|
}
|
|
25165
|
-
orch
|
|
25166
|
-
console.log(`[Relay] \
|
|
25610
|
+
advanceTaskOrchestrator(orch, nextStepIndex);
|
|
25611
|
+
console.log(`[Relay] \u8282\u70B9\u7D22\u5F15\u9012\u589E\u81F3: ${orch.currentStepIndex}`);
|
|
25167
25612
|
setTimeout(() => {
|
|
25168
25613
|
void sendNextStep(taskId);
|
|
25169
25614
|
}, STEP_DISPATCH_INTERVAL_MS);
|