fix(agentrun): 收敛 Target 派单输出
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
import { readFileSync, rmSync } from "node:fs";
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { parseAgentRunClientConfigYaml, resolveAgentRunAuth, runAgentRunCommand, stripAgentRunResourceWrapperArgs } from "./agentrun";
|
||||
import {
|
||||
parseAgentRunClientConfigYaml,
|
||||
parseResourceOptions,
|
||||
renderMutationSummary,
|
||||
resolveAgentRunAuth,
|
||||
runAgentRunCommand,
|
||||
stripAgentRunResourceWrapperArgs,
|
||||
} from "./agentrun";
|
||||
import { resolveAgentRunLaneTarget } from "./agentrun-lanes";
|
||||
import { agentRunToolCredentialRefs } from "./agentrun/config";
|
||||
import { autoDispatchTargetTask, targetTaskDispatchDryRunPlan } from "./agentrun/rest-bridge";
|
||||
@@ -318,6 +325,200 @@ describe("Artificer Target one-command dispatch", () => {
|
||||
rmSync(tempConfigPath, { force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps Target live human, JSON, and YAML output bounded while retaining dispatch identities", () => {
|
||||
const outputConfig = Bun.YAML.parse(
|
||||
readFileSync(new URL("../../config/unidesk-cli.yaml", import.meta.url), "utf8"),
|
||||
) as { output?: { maxStdoutBytes?: number } };
|
||||
const maxStdoutBytes = outputConfig.output?.maxStdoutBytes;
|
||||
if (typeof maxStdoutBytes !== "number") throw new Error("expected YAML-first output.maxStdoutBytes");
|
||||
const hugePrompt = "PROMPT_SHOULD_NOT_BE_RENDERED_".repeat(500);
|
||||
expect(Buffer.byteLength(hugePrompt, "utf8")).toBeGreaterThan(maxStdoutBytes);
|
||||
|
||||
const identity = {
|
||||
taskId: "qt_compact_target",
|
||||
taskState: "running",
|
||||
attemptId: "qat_compact_target",
|
||||
runId: "run_compact_target",
|
||||
commandId: "cmd_compact_target",
|
||||
runnerJobId: "rjob_compact_target",
|
||||
sessionId: "sess_compact_target",
|
||||
valuesPrinted: false,
|
||||
};
|
||||
const autoDispatch = {
|
||||
enabled: true,
|
||||
decision: "dispatched",
|
||||
mutation: true,
|
||||
duplicateDispatchPrevented: false,
|
||||
identity,
|
||||
valuesPrinted: false,
|
||||
};
|
||||
const raw = {
|
||||
ok: true,
|
||||
action: "queue-submit-auto-dispatch",
|
||||
data: {
|
||||
...identity,
|
||||
attemptState: "running",
|
||||
runState: "running",
|
||||
commandState: "running",
|
||||
runnerState: "claimed",
|
||||
sessionState: "active",
|
||||
mutation: true,
|
||||
autoDispatch,
|
||||
task: {
|
||||
id: identity.taskId,
|
||||
state: identity.taskState,
|
||||
prompt: hugePrompt,
|
||||
payload: { prompt: hugePrompt },
|
||||
latestAttempt: {
|
||||
attemptId: identity.attemptId,
|
||||
state: "running",
|
||||
runnerJobId: identity.runnerJobId,
|
||||
runnerState: "claimed",
|
||||
sessionId: identity.sessionId,
|
||||
},
|
||||
},
|
||||
run: {
|
||||
id: identity.runId,
|
||||
state: "running",
|
||||
sessionRef: { sessionId: identity.sessionId, state: "active" },
|
||||
},
|
||||
command: { id: identity.commandId, state: "running", payload: { prompt: hugePrompt } },
|
||||
latestAttempt: {
|
||||
attemptId: identity.attemptId,
|
||||
state: "running",
|
||||
runId: identity.runId,
|
||||
commandId: identity.commandId,
|
||||
runnerJobId: identity.runnerJobId,
|
||||
runnerState: "claimed",
|
||||
sessionId: identity.sessionId,
|
||||
},
|
||||
session: { id: identity.sessionId, state: "active", prompt: hugePrompt },
|
||||
valuesPrinted: false,
|
||||
},
|
||||
targetTask: {
|
||||
mdtodoId: "R6.4",
|
||||
target: "NC01",
|
||||
targetWorkspace: "/root/.worktrees/unidesk/artificer-compact-output",
|
||||
targetRoute: "NC01:/root/.worktrees/unidesk/artificer-compact-output",
|
||||
projectId: "pikasTech/unidesk",
|
||||
repository: "pikasTech/unidesk",
|
||||
ref: "fix/artificer-compact-output",
|
||||
verifiedCommit: "a".repeat(40),
|
||||
refRelation: "branch-and-head-match-remote-ref",
|
||||
workspace: {
|
||||
branch: "fix/artificer-compact-output",
|
||||
headCommit: "a".repeat(40),
|
||||
clean: true,
|
||||
},
|
||||
prompt: hugePrompt,
|
||||
},
|
||||
aipodBinding: {
|
||||
aipod: "Artificer",
|
||||
node: "NC01",
|
||||
lane: "nc01-v02",
|
||||
namespace: "agentrun-v01",
|
||||
projectId: "pikasTech/unidesk",
|
||||
providerId: "NC01",
|
||||
backendProfile: "sub2api",
|
||||
workspaceRef: { kind: "opaque", path: ".", valid: true },
|
||||
resourceBundleRef: {
|
||||
kind: "gitbundle",
|
||||
repoUrl: "https://credential-must-be-redacted@github.com/pikasTech/unidesk.git",
|
||||
ref: "fix/artificer-compact-output",
|
||||
inheritedFromAipod: true,
|
||||
credentialRefPresent: true,
|
||||
},
|
||||
session: { sessionId: identity.sessionId, identitySource: "task" },
|
||||
providerCredentials: [{
|
||||
profile: "sub2api",
|
||||
secretRef: { namespace: "agentrun-v01", name: "agentrun-provider", keys: ["auth.json"] },
|
||||
bindingPresent: true,
|
||||
value: hugePrompt,
|
||||
}],
|
||||
toolCredentials: [{
|
||||
tool: "github",
|
||||
purpose: "pull-request",
|
||||
secretRef: { namespace: "agentrun-v01", name: "agentrun-github", keys: ["GH_TOKEN"] },
|
||||
bindingPresent: true,
|
||||
value: hugePrompt,
|
||||
}],
|
||||
prompt: hugePrompt,
|
||||
},
|
||||
autoDispatch,
|
||||
valuesPrinted: false,
|
||||
};
|
||||
expect(Buffer.byteLength(JSON.stringify(raw), "utf8")).toBeGreaterThan(maxStdoutBytes);
|
||||
|
||||
const variants = [
|
||||
{ name: "human", args: [] },
|
||||
{ name: "json", args: ["-o", "json"] },
|
||||
{ name: "yaml", args: ["-o", "yaml"] },
|
||||
];
|
||||
for (const variant of variants) {
|
||||
const rendered = renderMutationSummary(
|
||||
"agentrun queue submit",
|
||||
raw,
|
||||
parseResourceOptions(variant.args),
|
||||
"Queue task submitted",
|
||||
);
|
||||
const text = renderedTextOf(rendered);
|
||||
expect(Buffer.byteLength(text, "utf8"), variant.name).toBeLessThan(maxStdoutBytes);
|
||||
expect(text).not.toContain("PROMPT_SHOULD_NOT_BE_RENDERED_");
|
||||
expect(text).not.toContain("credential-must-be-redacted");
|
||||
for (const value of Object.values(identity).filter((item): item is string => typeof item === "string")) {
|
||||
expect(text, `${variant.name}:${value}`).toContain(value);
|
||||
}
|
||||
expect(text).toContain("R6.4");
|
||||
expect(text).toContain("dispatched");
|
||||
}
|
||||
|
||||
const jsonText = renderedTextOf(renderMutationSummary(
|
||||
"agentrun queue submit",
|
||||
raw,
|
||||
parseResourceOptions(["-o", "json"]),
|
||||
"Queue task submitted",
|
||||
));
|
||||
const json = JSON.parse(jsonText) as Record<string, unknown>;
|
||||
const jsonData = json.data as Record<string, unknown>;
|
||||
const jsonNext = json.next as Record<string, unknown>;
|
||||
const jsonCredentials = (json.aipodBinding as Record<string, unknown>).credentialRefs as Record<string, unknown>;
|
||||
expect(jsonData).toMatchObject({
|
||||
taskId: identity.taskId,
|
||||
taskState: "running",
|
||||
attemptId: identity.attemptId,
|
||||
attemptState: "running",
|
||||
runId: identity.runId,
|
||||
runState: "running",
|
||||
commandId: identity.commandId,
|
||||
commandState: "running",
|
||||
runnerJobId: identity.runnerJobId,
|
||||
runnerState: "claimed",
|
||||
sessionId: identity.sessionId,
|
||||
sessionState: "active",
|
||||
});
|
||||
expect((json.autoDispatch as Record<string, unknown>).decision).toBe("dispatched");
|
||||
expect((json.targetTask as Record<string, unknown>).mdtodoId).toBe("R6.4");
|
||||
expect(jsonCredentials).toMatchObject({ totalCount: 2, allPresent: true });
|
||||
expect((jsonCredentials.provider as Record<string, unknown>).presentCount).toBe(1);
|
||||
expect((jsonCredentials.tool as Record<string, unknown>).presentCount).toBe(1);
|
||||
expect(jsonNext.result).toBe(
|
||||
`bun scripts/cli.ts agentrun result run/${identity.runId} --command ${identity.commandId} --target NC01 --lane nc01-v02`,
|
||||
);
|
||||
expect(jsonNext.logs).toBe(
|
||||
`bun scripts/cli.ts agentrun logs session/${identity.sessionId} --tail 120 --target NC01 --lane nc01-v02`,
|
||||
);
|
||||
|
||||
const yamlText = renderedTextOf(renderMutationSummary(
|
||||
"agentrun queue submit",
|
||||
raw,
|
||||
parseResourceOptions(["-o", "yaml"]),
|
||||
"Queue task submitted",
|
||||
));
|
||||
const yaml = Bun.YAML.parse(yamlText) as Record<string, unknown>;
|
||||
expect(yaml.data).toMatchObject(json.data as object);
|
||||
expect(yaml.next).toMatchObject(json.next as object);
|
||||
});
|
||||
});
|
||||
|
||||
describe("AgentRun default transport contract", () => {
|
||||
|
||||
Reference in New Issue
Block a user