113 lines
4.7 KiB
TypeScript
113 lines
4.7 KiB
TypeScript
// SPEC: PJ2026-010205 HWLAB接入 draft-2026-06-25-p0-session-warm-runner-contract.
|
|
// Responsibility: AgentRun warm-runner reuse regressions for HWLAB Code Agent turns.
|
|
|
|
import assert from "node:assert/strict";
|
|
import { test } from "bun:test";
|
|
|
|
import { submitAgentRunChatTurn } from "./code-agent-agentrun-adapter.ts";
|
|
import { createCodeAgentTraceStore } from "./code-agent-trace-store.ts";
|
|
|
|
test("AgentRun adapter reuses a claimed session run without creating another runner Job", async () => {
|
|
const traceId = "trc_agentrun_reuse_warm_runner";
|
|
const calls = [];
|
|
const leaseExpiresAt = new Date(Date.now() + 120_000).toISOString();
|
|
const traceStore = createCodeAgentTraceStore();
|
|
|
|
const result = await submitAgentRunChatTurn({
|
|
traceId,
|
|
traceStore,
|
|
params: {
|
|
sessionId: "ses_reuse_warm_runner",
|
|
conversationId: "cnv_reuse_warm_runner",
|
|
message: "reuse warm runner",
|
|
providerProfile: "deepseek"
|
|
},
|
|
options: {
|
|
env: {
|
|
AGENTRUN_MGR_URL: "http://127.0.0.1:65535",
|
|
HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
|
|
HWLAB_CODE_AGENT_AGENTRUN_HTTP_TIMEOUT_MS: "1000",
|
|
HWLAB_CODE_AGENT_AGENTRUN_DISPATCH_RETRY_MAX: "0",
|
|
HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
|
|
HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "0123456789abcdef0123456789abcdef01234567",
|
|
HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "deepseek"
|
|
},
|
|
accessController: {
|
|
async getAgentSession(sessionId) {
|
|
assert.equal(sessionId, "ses_reuse_warm_runner");
|
|
return {
|
|
ownerUserId: null,
|
|
session: {
|
|
agentRun: {
|
|
adapter: "agentrun-v01",
|
|
managerUrl: "http://127.0.0.1:65535",
|
|
backendProfile: "deepseek",
|
|
providerId: "D601",
|
|
runId: "run_reuse_warm_runner",
|
|
commandId: "cmd_previous_turn",
|
|
runnerId: "runner_warm",
|
|
jobName: "agentrun-v01-runner-warm",
|
|
namespace: "agentrun-v01",
|
|
status: "runner-job-created",
|
|
runStatus: "claimed",
|
|
sessionId: "ses_agentrun_reuse_warm_runner",
|
|
conversationId: "cnv_reuse_warm_runner",
|
|
threadId: "thr_reuse_warm_runner",
|
|
reuseEligible: true,
|
|
runnerJobCount: 1
|
|
}
|
|
}
|
|
};
|
|
}
|
|
},
|
|
async fetchImpl(url, init = {}) {
|
|
const parsed = new URL(url);
|
|
const method = init.method ?? "GET";
|
|
const body = init.body ? JSON.parse(String(init.body)) : null;
|
|
calls.push({ method, path: parsed.pathname, body });
|
|
|
|
const send = (data) => new Response(JSON.stringify({ ok: true, data }), { status: 200, headers: { "content-type": "application/json" } });
|
|
if (method === "GET" && parsed.pathname === "/api/v1/runs/run_reuse_warm_runner") {
|
|
return send({
|
|
id: "run_reuse_warm_runner",
|
|
status: "claimed",
|
|
claimedBy: "runner_warm",
|
|
leaseExpiresAt,
|
|
sessionRef: {
|
|
sessionId: "ses_agentrun_reuse_warm_runner",
|
|
conversationId: "cnv_reuse_warm_runner",
|
|
threadId: "thr_reuse_warm_runner"
|
|
}
|
|
});
|
|
}
|
|
if (method === "POST" && parsed.pathname === "/api/v1/runs/run_reuse_warm_runner/commands") {
|
|
return send({ id: "cmd_reused_turn", runId: "run_reuse_warm_runner", state: "pending", type: "turn", seq: 2 });
|
|
}
|
|
throw new Error(`unexpected AgentRun call ${method} ${parsed.pathname}`);
|
|
}
|
|
}
|
|
});
|
|
|
|
assert.equal(result.status, "running");
|
|
assert.equal(result.agentRun.reused, true);
|
|
assert.equal(result.agentRun.runnerReused, true);
|
|
assert.equal(result.agentRun.runId, "run_reuse_warm_runner");
|
|
assert.equal(result.agentRun.commandId, "cmd_reused_turn");
|
|
assert.equal(result.agentRun.runnerJobCount, 1);
|
|
assert.deepEqual(calls.map((call) => `${call.method} ${call.path}`), [
|
|
"GET /api/v1/runs/run_reuse_warm_runner",
|
|
"POST /api/v1/runs/run_reuse_warm_runner/commands"
|
|
]);
|
|
assert.equal(calls[1].body.type, "turn");
|
|
assert.equal(calls[1].body.payload.sessionId, "ses_agentrun_reuse_warm_runner");
|
|
assert.equal(calls[1].body.payload.hwlabSessionId, "ses_reuse_warm_runner");
|
|
assert.equal(calls[1].body.payload.threadId, "thr_reuse_warm_runner");
|
|
assert.equal(calls[1].body.idempotencyKey, traceId);
|
|
assert.equal(calls.some((call) => call.path.endsWith("/runner-jobs")), false);
|
|
|
|
const labels = traceStore.snapshot(traceId).events.map((event) => event.label);
|
|
assert.ok(labels.includes("agentrun:run:reuse-enabled"));
|
|
assert.ok(labels.includes("agentrun:runner-job:reused"));
|
|
assert.equal(labels.includes("agentrun:run:reuse-disabled"), false);
|
|
});
|