fix(tasks): prefer ACP spawn metadata on merge

This commit is contained in:
Vincent Koc 2026-03-30 08:41:29 +09:00
parent c1137ef00d
commit 0da610a8ec
3 changed files with 61 additions and 2 deletions

View File

@ -962,6 +962,7 @@ export async function spawnAcpDirect(
runId: childRunId,
label: params.label,
task: params.task,
preferMetadata: true,
status: "running",
deliveryStatus: requesterInternalKey.trim() ? "pending" : "parent_missing",
startedAt: Date.now(),
@ -993,6 +994,7 @@ export async function spawnAcpDirect(
runId: childRunId,
label: params.label,
task: params.task,
preferMetadata: true,
status: "running",
deliveryStatus: requesterInternalKey.trim() ? "pending" : "parent_missing",
startedAt: Date.now(),

View File

@ -548,6 +548,7 @@ describe("task-registry", () => {
childSessionKey: "agent:main:acp:child",
runId: "run-shared-delivery",
task: "Spawn ACP child",
preferMetadata: true,
status: "succeeded",
deliveryStatus: "pending",
});
@ -561,11 +562,56 @@ describe("task-registry", () => {
);
expect(findTaskByRunId("run-shared-delivery")).toMatchObject({
taskId: directTask.taskId,
task: "Spawn ACP child",
deliveryStatus: "delivered",
});
});
});
it("adopts preferred ACP spawn metadata when collapsing onto an earlier direct record", async () => {
await withTempDir({ prefix: "openclaw-task-registry-" }, async (root) => {
process.env.OPENCLAW_STATE_DIR = root;
resetTaskRegistryForTests();
const directTask = createTaskRecord({
runtime: "acp",
requesterSessionKey: "agent:main:main",
requesterOrigin: {
channel: "telegram",
to: "telegram:123",
},
childSessionKey: "agent:main:acp:child",
runId: "run-collapse-preferred",
task: "Direct ACP child",
status: "running",
deliveryStatus: "pending",
});
const spawnedTask = createTaskRecord({
runtime: "acp",
requesterSessionKey: "agent:main:main",
requesterOrigin: {
channel: "telegram",
to: "telegram:123",
},
childSessionKey: "agent:main:acp:child",
runId: "run-collapse-preferred",
label: "Quant patch",
task: "Implement the feature and report back",
preferMetadata: true,
status: "running",
deliveryStatus: "pending",
});
expect(spawnedTask.taskId).toBe(directTask.taskId);
expect(findTaskByRunId("run-collapse-preferred")).toMatchObject({
taskId: directTask.taskId,
label: "Quant patch",
task: "Implement the feature and report back",
});
});
});
it("collapses ACP run-owned task creation onto the existing spawned task", async () => {
await withTempDir({ prefix: "openclaw-task-registry-" }, async (root) => {
process.env.OPENCLAW_STATE_DIR = root;

View File

@ -247,6 +247,7 @@ function mergeExistingTaskForCreate(
agentId?: string;
label?: string;
task: string;
preferMetadata?: boolean;
deliveryStatus?: TaskDeliveryStatus;
notifyPolicy?: TaskNotifyPolicy;
},
@ -265,8 +266,17 @@ function mergeExistingTaskForCreate(
if (params.agentId?.trim() && !existing.agentId?.trim()) {
patch.agentId = params.agentId.trim();
}
if (params.label?.trim() && !existing.label?.trim()) {
patch.label = params.label.trim();
const nextLabel = params.label?.trim();
if (params.preferMetadata) {
if (nextLabel && normalizeComparableText(existing.label) !== nextLabel) {
patch.label = nextLabel;
}
const nextTask = params.task.trim();
if (nextTask && normalizeComparableText(existing.task) !== nextTask) {
patch.task = nextTask;
}
} else if (nextLabel && !existing.label?.trim()) {
patch.label = nextLabel;
}
if (params.deliveryStatus === "pending" && existing.deliveryStatus !== "delivered") {
patch.deliveryStatus = "pending";
@ -752,6 +762,7 @@ export function createTaskRecord(params: {
runId?: string;
label?: string;
task: string;
preferMetadata?: boolean;
status?: TaskStatus;
deliveryStatus?: TaskDeliveryStatus;
notifyPolicy?: TaskNotifyPolicy;