mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-03 17:51:58 +01:00
perf(runner): activate shared retained startup context (#18405)
This commit is contained in:
1 parent
58308a3e63
commit
3a7bb4dac6
9 files changed
+509
-44
No files matched your search
@@ -3,6 +3,7 @@ import { describe, expect, it, vi } from "vitest";
|
||||
import type { RunnerProviderLaunchRequirements } from "@paperclipai/paperclip-runner";
|
||||
import type { RunnerProcessLaunchSpec } from "../../vendor/paperclip-runner/index.js";
|
||||
import { createPluginRunnerTaskOwner } from "./plugin-runner-task.js";
|
||||
import { NativeExecutionContext } from "./native-execution-context.js";
|
||||
|
||||
const ingress = vi.hoisted(() => ({ connect: vi.fn() }));
|
||||
vi.mock("../../realtime/runner-prp-outbound.js", () => ({ connectRunnerPrpIngress: ingress.connect }));
|
||||
@@ -53,6 +54,20 @@ function provider() {
|
||||
}
|
||||
|
||||
describe("plugin native Runner ownership", () => {
|
||||
it.each(["finish", "rebind"])("does not send startup Stop after the context %s", mode => {
|
||||
const context = new NativeExecutionContext({ binding: { companyId: "company", agentId: "agent", runId: "run" } } as never, 1_000);
|
||||
const next = new NativeExecutionContext(context.execution, 1_000);
|
||||
const remove = vi.spyOn(context.signal, "removeEventListener");
|
||||
const { task } = provider();
|
||||
const input = { task, projectIds: [], harness: "codex", executionContext: context, adoptIdentity: requirements.identity };
|
||||
const owner = createPluginRunnerTaskOwner(input);
|
||||
try {
|
||||
if (mode === "finish") context.finish();
|
||||
else { owner.rebind({ ...input, executionContext: next }); expect(remove).toHaveBeenCalledWith("abort", expect.any(Function)); }
|
||||
context.abort(new Error("later lease loss"));
|
||||
expect(task).not.toHaveBeenCalled();
|
||||
} finally { context.finish(); next.finish(); }
|
||||
});
|
||||
it("rechecks revoked grants for unchanged project IDs before adopting retained resources", async () => {
|
||||
const { task } = provider();
|
||||
const perform = task.getMockImplementation()!;
|
||||
@@ -217,6 +232,22 @@ describe("plugin native Runner ownership", () => {
|
||||
await expect(prepared).rejects.toThrow("preparation cancelled");
|
||||
expect(task.mock.calls.some(([op]) => op.kind === "submit")).toBe(false);
|
||||
});
|
||||
it("sends Stop before a late preparation can publish a launch", async () => {
|
||||
const context = new NativeExecutionContext({ binding: { companyId: "company", agentId: "agent", runId: "run" } } as never, 1_000);
|
||||
const { task } = provider(), perform = task.getMockImplementation()!;
|
||||
let release!: () => void;
|
||||
const gate = new Promise<void>(resolve => { release = resolve; });
|
||||
task.mockImplementation(async operation => { if (operation.kind === "prepare") await gate; return perform(operation); });
|
||||
const owner = createPluginRunnerTaskOwner({ task, projectIds: [], harness: "codex", projectAuthCheckVersion: 1, executionContext: context });
|
||||
const preparing = prepare(owner);
|
||||
await vi.waitFor(() => expect(task).toHaveBeenCalledWith(expect.objectContaining({ kind: "prepare" })));
|
||||
context.abort(new Error("operator Stop"));
|
||||
expect(task).toHaveBeenCalledWith({ kind: "stop" });
|
||||
release();
|
||||
await expect(preparing).rejects.toThrow("preparation cancelled");
|
||||
expect(task.mock.calls.some(([operation]) => ["check_project_auth", "connection", "submit"].includes(operation.kind))).toBe(false);
|
||||
context.finish();
|
||||
});
|
||||
it.each(["unsupported", "denied", "wrong-configuration", "wrong-provider"])("withholds credentials when project validation is %s", async mode => {
|
||||
const { task } = provider(); const perform = task.getMockImplementation()!;
|
||||
task.mockImplementation(async op => op.kind === "check_project_auth"
|
||||
|
||||
Reference in new issue
Block a user