mirror of
https://github.com/harivansh-afk/clanker-agent.git
synced 2026-04-18 20:03:36 +00:00
Restore the bedrock provider import through an explicit workspace path mapping, align pi-grind package metadata with the existing package manifests, remove the unused controller-failure state path, and parse bare ISO dates in local time. Co-authored-by: Codex <noreply@openai.com>
117 lines
3.1 KiB
TypeScript
117 lines
3.1 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
import type { SessionEntry } from "@mariozechner/pi-coding-agent";
|
|
import {
|
|
GRIND_STATE_ENTRY_TYPE,
|
|
type GrindActivation,
|
|
type GrindRunState,
|
|
type GrindRunStatus,
|
|
type GrindStatusPayload,
|
|
} from "./types.js";
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return value !== null && typeof value === "object";
|
|
}
|
|
|
|
function isGrindRunStatus(value: unknown): value is GrindRunStatus {
|
|
return (
|
|
value === "active" ||
|
|
value === "paused" ||
|
|
value === "done" ||
|
|
value === "blocked" ||
|
|
value === "expired" ||
|
|
value === "stopped"
|
|
);
|
|
}
|
|
|
|
function isGrindActivation(value: unknown): value is GrindActivation {
|
|
return value === "explicit" || value === "command";
|
|
}
|
|
|
|
function isNullableString(value: unknown): value is string | null {
|
|
return typeof value === "string" || value === null;
|
|
}
|
|
|
|
export function createRunState(input: {
|
|
activation: GrindActivation;
|
|
goal: string;
|
|
sourcePrompt: string;
|
|
deadlineAt: string | null;
|
|
completionCriterion: string | null;
|
|
}): GrindRunState {
|
|
const now = new Date().toISOString();
|
|
return {
|
|
version: 1,
|
|
runId: randomUUID(),
|
|
activation: input.activation,
|
|
status: "active",
|
|
goal: input.goal,
|
|
sourcePrompt: input.sourcePrompt,
|
|
deadlineAt: input.deadlineAt,
|
|
completionCriterion: input.completionCriterion,
|
|
lastCheckpoint: null,
|
|
lastNextAction: null,
|
|
pendingRepair: false,
|
|
consecutiveParseFailures: 0,
|
|
updatedAt: now,
|
|
};
|
|
}
|
|
|
|
export function isValidRunState(value: unknown): value is GrindRunState {
|
|
if (!isRecord(value)) {
|
|
return false;
|
|
}
|
|
|
|
return (
|
|
value.version === 1 &&
|
|
typeof value.runId === "string" &&
|
|
isGrindActivation(value.activation) &&
|
|
isGrindRunStatus(value.status) &&
|
|
typeof value.goal === "string" &&
|
|
typeof value.sourcePrompt === "string" &&
|
|
isNullableString(value.deadlineAt) &&
|
|
isNullableString(value.completionCriterion) &&
|
|
isNullableString(value.lastCheckpoint) &&
|
|
isNullableString(value.lastNextAction) &&
|
|
typeof value.pendingRepair === "boolean" &&
|
|
typeof value.consecutiveParseFailures === "number" &&
|
|
typeof value.updatedAt === "string"
|
|
);
|
|
}
|
|
|
|
export function getLatestRunState(entries: readonly SessionEntry[]): GrindRunState | null {
|
|
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
const entry = entries[index];
|
|
if (entry.type !== "custom" || entry.customType !== GRIND_STATE_ENTRY_TYPE) {
|
|
continue;
|
|
}
|
|
if (isValidRunState(entry.data)) {
|
|
return entry.data;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function withStatus(
|
|
state: GrindRunState,
|
|
status: GrindRunStatus,
|
|
overrides: Partial<GrindRunState> = {},
|
|
): GrindRunState {
|
|
return {
|
|
...state,
|
|
...overrides,
|
|
status,
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
export function withLoopStatus(state: GrindRunState, payload: GrindStatusPayload): GrindRunState {
|
|
return {
|
|
...state,
|
|
status: payload.state === "continue" ? "active" : payload.state === "done" ? "done" : "blocked",
|
|
lastCheckpoint: payload.summary,
|
|
lastNextAction: payload.nextAction ?? null,
|
|
pendingRepair: false,
|
|
consecutiveParseFailures: 0,
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
}
|