mirror of
https://github.com/harivansh-afk/clanker-agent.git
synced 2026-04-19 06:01:17 +00:00
grind mode baby
This commit is contained in:
parent
aa70afbd7e
commit
ff6e39dd10
17 changed files with 1232 additions and 8 deletions
132
packages/pi-grind/src/state.ts
Normal file
132
packages/pi-grind/src/state.ts
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
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,
|
||||
consecutiveControllerFailures: 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.consecutiveControllerFailures === "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,
|
||||
consecutiveControllerFailures: 0,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export function withControllerFailure(state: GrindRunState, note: string): GrindRunState {
|
||||
return {
|
||||
...state,
|
||||
status: "blocked",
|
||||
lastCheckpoint: note,
|
||||
lastNextAction: null,
|
||||
pendingRepair: false,
|
||||
consecutiveControllerFailures: state.consecutiveControllerFailures + 1,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue