mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Mark completed hook runs as completed
This commit is contained in:
parent
6a5fcc67df
commit
b68f2d1fb8
4 changed files with 40 additions and 1 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { definedProp } from "../../../../../utils";
|
||||
import type { HookMessageStreamItem } from "../../../domain/message-stream/items";
|
||||
import type { ExecutionState, HookMessageStreamItem } from "../../../domain/message-stream/items";
|
||||
|
||||
interface MessageStreamHookRun {
|
||||
id: string;
|
||||
|
|
@ -10,6 +10,17 @@ interface MessageStreamHookRun {
|
|||
entries: readonly { kind: string; text: string }[];
|
||||
}
|
||||
|
||||
type MessageStreamExecutionState = Exclude<ExecutionState, null>;
|
||||
type ExecutionStateByStatus = Readonly<Record<string, MessageStreamExecutionState>>;
|
||||
|
||||
const HOOK_RUN_STATES = {
|
||||
running: "running",
|
||||
completed: "completed",
|
||||
failed: "failed",
|
||||
blocked: "failed",
|
||||
stopped: "failed",
|
||||
} as const satisfies ExecutionStateByStatus;
|
||||
|
||||
export function hookRunMessageStreamItem(run: MessageStreamHookRun, turnId: string | null, status: string): HookMessageStreamItem | null {
|
||||
if (run.id.length === 0) return null;
|
||||
const eventName = hookEventName(run.eventName);
|
||||
|
|
@ -25,6 +36,7 @@ export function hookRunMessageStreamItem(run: MessageStreamHookRun, turnId: stri
|
|||
sourceItemId: displayId,
|
||||
provenance: { source: "appServer", channel: "notification", event: "hookRun", sourceItemId: displayId },
|
||||
status,
|
||||
executionState: hookRunExecutionState(status),
|
||||
hookRun: {
|
||||
eventName,
|
||||
...definedProp("statusMessage", run.statusMessage ?? undefined),
|
||||
|
|
@ -35,6 +47,14 @@ export function hookRunMessageStreamItem(run: MessageStreamHookRun, turnId: stri
|
|||
};
|
||||
}
|
||||
|
||||
function hookRunExecutionState(status: string): ExecutionState {
|
||||
return executionStateFromStatus(status, HOOK_RUN_STATES);
|
||||
}
|
||||
|
||||
function executionStateFromStatus(status: string, states: ExecutionStateByStatus): ExecutionState {
|
||||
return states[status] ?? null;
|
||||
}
|
||||
|
||||
function hookRunDisplayId(run: MessageStreamHookRun): string {
|
||||
return `hook-${run.id}-${run.startedAt.toString()}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
createAutoReviewResultItem,
|
||||
createReviewResultItem,
|
||||
} from "../../../../src/features/chat/app-server/mappers/message-stream/review-result-items";
|
||||
import { hookRunMessageStreamItem } from "../../../../src/features/chat/app-server/mappers/message-stream/hook-run-items";
|
||||
import {
|
||||
messageStreamItemFromTurnItem,
|
||||
messageStreamItemsFromTurns,
|
||||
|
|
@ -1437,6 +1438,8 @@ describe("execution state uses typed status adapters before rendered text", () =
|
|||
).toMatchObject({ executionState: "running" });
|
||||
expect(autoReviewItem("approved")).toMatchObject({ executionState: "completed" });
|
||||
expect(autoReviewItem("timedOut")).toMatchObject({ executionState: "failed" });
|
||||
expect(hookRunMessageStreamItem(hookRun(), "turn", "completed")).toMatchObject({ executionState: "completed" });
|
||||
expect(hookRunMessageStreamItem(hookRun(), "turn", "stopped")).toMatchObject({ executionState: "failed" });
|
||||
expect(collabAgentStateExecutionState("inProgress")).toBe("running");
|
||||
expect(collabAgentStateExecutionState("failed")).toBe("failed");
|
||||
});
|
||||
|
|
@ -1569,3 +1572,14 @@ function autoReviewItem(status: string): MessageStreamItem {
|
|||
action: { type: "applyPatch", cwd: "/vault", files: ["/vault/src/main.ts"] },
|
||||
});
|
||||
}
|
||||
|
||||
function hookRun() {
|
||||
return {
|
||||
id: "hook-1",
|
||||
eventName: "postToolUse",
|
||||
statusMessage: "Formatted 1 file.",
|
||||
startedAt: 1n,
|
||||
durationMs: 1n,
|
||||
entries: [{ kind: "feedback", text: "ok" }],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ describe("ChatInboundController", () => {
|
|||
operation: "postToolUse",
|
||||
primaryTarget: { kind: "value", value: "Formatted 1 file." },
|
||||
status: "completed",
|
||||
executionState: "completed",
|
||||
output: "",
|
||||
hookRun: {
|
||||
eventName: "postToolUse",
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ describe("work log renderer decisions", () => {
|
|||
toolName: "hook",
|
||||
turnId: "turn",
|
||||
status: "completed",
|
||||
executionState: "completed",
|
||||
hookRun: {
|
||||
eventName: "postToolUse",
|
||||
statusMessage: "Formatted 1 file.",
|
||||
|
|
@ -276,6 +277,7 @@ describe("work log renderer decisions", () => {
|
|||
const element = renderMessageBlockElement(block);
|
||||
|
||||
expect(topLevelDetailsSummaries(element)).toEqual(["hook"]);
|
||||
expect(element.classList.contains("codex-panel__execution--completed")).toBe(true);
|
||||
expect([...element.querySelectorAll("details summary")].map((summary) => summary.textContent)).toEqual(["hook"]);
|
||||
expect(element.querySelector(".codex-panel__tool-summary")?.textContent).toBe("postToolUse: Formatted 1 file.");
|
||||
expect(element.textContent).not.toContain("Details");
|
||||
|
|
@ -302,6 +304,7 @@ describe("work log renderer decisions", () => {
|
|||
toolName: "hook",
|
||||
turnId: "turn",
|
||||
status: "completed",
|
||||
executionState: "completed",
|
||||
hookRun: {
|
||||
eventName: "postToolUse",
|
||||
statusMessage: "Formatted 1 file.",
|
||||
|
|
@ -328,6 +331,7 @@ describe("work log renderer decisions", () => {
|
|||
|
||||
expect(element).toBeDefined();
|
||||
expect(element.querySelector(":scope > summary")?.textContent).toBe("Work details: hook");
|
||||
expect(element.querySelector(".codex-panel__tool-item--hook")?.classList.contains("codex-panel__execution--completed")).toBe(true);
|
||||
expect(element.querySelector(".codex-panel__tool-summary")?.textContent).toBe("postToolUse: Formatted 1 file.");
|
||||
expect(element.querySelector(".codex-panel__meta-grid")?.textContent).toContain("statuscompleted");
|
||||
expect(element.querySelector(".codex-panel__meta-grid")?.textContent).toContain("eventpostToolUse");
|
||||
|
|
|
|||
Loading…
Reference in a new issue