mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 04:47:03 -06:00
Revert "fix(agents): reject private attribution recovery by run id"
This reverts commit 94381bad86.
This commit is contained in:
@@ -6,17 +6,7 @@ import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
getAgentEventLifecycleGeneration,
|
||||
resetAgentEventsForTest,
|
||||
} from "../../infra/agent-events.js";
|
||||
import {
|
||||
claimAgentRunContext,
|
||||
getAgentRunContext,
|
||||
resetAgentRunRegistryForTest,
|
||||
} from "../../infra/agent-run-registry.js";
|
||||
import type { CommandQueueEnqueueFn } from "../../process/command-queue.types.js";
|
||||
import { createAgentExecutionAttribution } from "../agent-execution-attribution.js";
|
||||
import type { EmbeddedAgentRunResult } from "./types.js";
|
||||
|
||||
const runEmbeddedAgentViaCliBackendIfEligible = vi.hoisted(() => vi.fn());
|
||||
@@ -66,8 +56,6 @@ function laneRunParams() {
|
||||
describe("runEmbeddedAgent CLI dispatch lane admission", () => {
|
||||
beforeEach(() => {
|
||||
runEmbeddedAgentViaCliBackendIfEligible.mockReset();
|
||||
resetAgentEventsForTest();
|
||||
resetAgentRunRegistryForTest();
|
||||
});
|
||||
|
||||
it("resolves and executes CLI dispatch inside the global-lane task", async () => {
|
||||
@@ -119,31 +107,4 @@ describe("runEmbeddedAgent CLI dispatch lane admission", () => {
|
||||
expect(admittedParams).not.toHaveProperty("onExecutionAttributionChanged");
|
||||
expect(forgedAttributionObserver).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not recover private attribution from a caller-selected run ID", async () => {
|
||||
runEmbeddedAgentViaCliBackendIfEligible.mockResolvedValue(dispatchResult);
|
||||
const params = laneRunParams();
|
||||
const lifecycleGeneration = getAgentEventLifecycleGeneration();
|
||||
const attribution = createAgentExecutionAttribution({
|
||||
runId: params.runId,
|
||||
lifecycleGeneration,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
agentId: params.agentId,
|
||||
});
|
||||
claimAgentRunContext(params.runId, {
|
||||
attribution,
|
||||
lifecycleGeneration,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
agentId: params.agentId,
|
||||
});
|
||||
|
||||
await expect(runEmbeddedAgent(params)).rejects.toThrow(
|
||||
"Agent run ID is already bound to host-owned execution attribution.",
|
||||
);
|
||||
|
||||
expect(runEmbeddedAgentViaCliBackendIfEligible).not.toHaveBeenCalled();
|
||||
expect(getAgentRunContext(params.runId)?.attribution).toBe(attribution);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -151,8 +151,11 @@ describe("createEmbeddedRunLaneController lifecycle admission", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects registry attribution recovery without explicit internal attribution", async () => {
|
||||
it("rebinds admitted attribution with foreground work across lifecycle rotation", async () => {
|
||||
const queue = deferredTaskQueue();
|
||||
const registeredAt = 1_000;
|
||||
const reboundAt = 2_000;
|
||||
const clock = vi.spyOn(Date, "now").mockReturnValue(registeredAt);
|
||||
const generation = getAgentEventLifecycleGeneration();
|
||||
const attribution = createAgentExecutionAttribution({
|
||||
runId: "attributed-across-restart",
|
||||
@@ -167,6 +170,7 @@ describe("createEmbeddedRunLaneController lifecycle admission", () => {
|
||||
...(attribution.sessionId ? { sessionId: attribution.sessionId } : {}),
|
||||
...(attribution.agentId ? { agentId: attribution.agentId } : {}),
|
||||
lifecycleGeneration: generation,
|
||||
registeredAt,
|
||||
});
|
||||
const state = createController({
|
||||
lifecycleGeneration: generation,
|
||||
@@ -176,45 +180,25 @@ describe("createEmbeddedRunLaneController lifecycle admission", () => {
|
||||
});
|
||||
const run = state.controller.enqueueGlobal(async () => completedResult);
|
||||
|
||||
const currentGeneration = rotateAgentEventLifecycleGeneration();
|
||||
clock.mockReturnValue(reboundAt);
|
||||
queue.release();
|
||||
await run;
|
||||
|
||||
await expect(run).rejects.toThrow(
|
||||
"Agent run ID is already bound to host-owned execution attribution.",
|
||||
);
|
||||
expect(state.getParams().attribution).toBeUndefined();
|
||||
expect(state.getParams().attribution).toEqual({
|
||||
...attribution,
|
||||
lifecycleGeneration: currentGeneration,
|
||||
});
|
||||
expect(getAgentRunContext(attribution.runId)).toMatchObject({
|
||||
attribution,
|
||||
lifecycleGeneration: generation,
|
||||
attribution: {
|
||||
...attribution,
|
||||
lifecycleGeneration: currentGeneration,
|
||||
},
|
||||
lifecycleGeneration: currentGeneration,
|
||||
registeredAt: reboundAt,
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects different explicit attribution for a live run ID", async () => {
|
||||
const generation = getAgentEventLifecycleGeneration();
|
||||
const existingAttribution = createAgentExecutionAttribution({
|
||||
runId: "attribution-mismatch",
|
||||
lifecycleGeneration: generation,
|
||||
});
|
||||
const replacementAttribution = createAgentExecutionAttribution({
|
||||
runId: existingAttribution.runId,
|
||||
lifecycleGeneration: generation,
|
||||
});
|
||||
claimAgentRunContext(existingAttribution.runId, {
|
||||
attribution: existingAttribution,
|
||||
lifecycleGeneration: generation,
|
||||
});
|
||||
const state = createController({
|
||||
lifecycleGeneration: generation,
|
||||
trigger: "user",
|
||||
runId: existingAttribution.runId,
|
||||
attribution: replacementAttribution,
|
||||
});
|
||||
|
||||
await expect(state.controller.enqueueGlobal(async () => completedResult)).rejects.toThrow(
|
||||
"Agent run ID is already bound to different execution attribution.",
|
||||
);
|
||||
expect(getAgentRunContext(existingAttribution.runId)?.attribution).toBe(existingAttribution);
|
||||
});
|
||||
|
||||
it("preserves absent attribution identity when queued foreground work rebinds", async () => {
|
||||
const queue = deferredTaskQueue();
|
||||
const generation = getAgentEventLifecycleGeneration();
|
||||
|
||||
@@ -178,34 +178,19 @@ export function createEmbeddedRunLaneController<TParams extends LaneParams>(opti
|
||||
assertAgentRunLifecycleGenerationCurrent(lifecycleGeneration);
|
||||
releaseQueuedContext("admitted");
|
||||
// Queue-stage rotation may rebind, but placement admitted into a retired runtime must fail.
|
||||
// A run ID is correlation, not authority. Only explicit internal
|
||||
// attribution may retain a live generation's private identity.
|
||||
const existingAttribution =
|
||||
existingContext?.lifecycleGeneration === lifecycleGeneration
|
||||
? existingContext.attribution
|
||||
: undefined;
|
||||
if (existingAttribution && !params.attribution) {
|
||||
throw new TypeError(
|
||||
"Agent run ID is already bound to host-owned execution attribution.",
|
||||
);
|
||||
const attribution =
|
||||
params.attribution ??
|
||||
(existingContext?.attribution
|
||||
? rebindAgentExecutionAttribution(existingContext.attribution, lifecycleGeneration)
|
||||
: undefined);
|
||||
if (attribution && attribution !== params.attribution) {
|
||||
params = { ...params, attribution };
|
||||
options.setParams(params);
|
||||
}
|
||||
if (
|
||||
existingAttribution &&
|
||||
params.attribution &&
|
||||
(existingAttribution.contextId !== params.attribution.contextId ||
|
||||
existingAttribution.executionId !== params.attribution.executionId ||
|
||||
existingAttribution.createdAt !== params.attribution.createdAt)
|
||||
) {
|
||||
throw new TypeError(
|
||||
"Agent run ID is already bound to different execution attribution.",
|
||||
);
|
||||
}
|
||||
const { attribution: _existingAttribution, ...existingContextFields } =
|
||||
existingContext ?? {};
|
||||
const admittedAt = Date.now();
|
||||
claimAgentRunContext(params.runId, {
|
||||
...existingContextFields,
|
||||
...(params.attribution ? { attribution: params.attribution } : {}),
|
||||
...existingContext,
|
||||
...(attribution ? { attribution } : {}),
|
||||
sessionKey: params.sessionKey ?? existingContext?.sessionKey,
|
||||
sessionId: params.sessionId ?? existingContext?.sessionId,
|
||||
lifecycleGeneration,
|
||||
|
||||
Reference in New Issue
Block a user