@phren/cli
Version:
Knowledge layer for AI agents - CLI, MCP server, and data layer
89 lines (88 loc) • 4 kB
TypeScript
import { z } from "zod";
import { type Provider } from "./protocol.js";
/** Longest final reply kept from a Stop payload, in UTF-8 bytes (the receipt's limit). */
export declare const TURN_REPLY_LIMIT = 4000;
declare const turnRecordSchema: z.ZodObject<{
terminal: z.ZodString;
source: z.ZodEnum<{
claude: "claude";
codex: "codex";
copilot: "copilot";
opencode: "opencode";
phren: "phren";
}>;
session: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
seq: z.ZodNumber;
dispatch: z.ZodOptional<z.ZodString>;
startedAt: z.ZodOptional<z.ZodString>;
prompt: z.ZodOptional<z.ZodObject<{
seq: z.ZodNumber;
at: z.ZodString;
}, z.core.$strip>>;
stop: z.ZodOptional<z.ZodObject<{
seq: z.ZodNumber;
at: z.ZodString;
background: z.ZodOptional<z.ZodNumber>;
reply: z.ZodOptional<z.ZodString>;
truncated: z.ZodOptional<z.ZodBoolean>;
cwd: z.ZodOptional<z.ZodString>;
}, z.core.$strip>>;
at: z.ZodString;
}, z.core.$strip>;
export type TurnRecord = z.infer<typeof turnRecordSchema>;
export interface TurnEvent {
event: string;
terminal: string;
source: Provider;
session: string;
/** SessionStart / UserPromptSubmit: the dispatch id the worker's hook named. */
dispatch?: string;
/** Stop only: the harness's count of in-flight background tasks, when it reports one. */
background?: number;
/** Stop only: the harness's last assistant message, when it reports one. */
reply?: string;
/** Stop only: the agent's working directory, as its hook payload names it. */
cwd?: string;
at?: number;
}
export declare const turnPath: (server: string, pane: string) => string;
/** `value` cut to at most `limit` UTF-8 bytes on a character boundary. */
export declare function truncateUtf8(value: string, limit?: number): {
text: string;
truncated: boolean;
};
/** The record after one lifecycle event; undefined for events that say nothing about turns.
* Another conversation or terminal in the pane starts a fresh record. */
export declare function nextTurn(previous: TurnRecord | undefined, event: TurnEvent): TurnRecord | undefined;
export type TurnPhase = {
phase: "unprompted";
} | {
phase: "working";
since: string;
} | {
phase: "ended";
at: string;
background?: number;
reply?: string;
truncated?: boolean;
};
/** Where the recorded conversation is: no prompt yet, a prompt with no Stop
* after it, or a turn that stopped. A Stop with no recorded prompt (hooks
* installed mid-conversation) still ended a turn. */
export declare function turnPhase(record: TurnRecord): TurnPhase;
/** The background tasks of a Stop at `stoppedAt` still running: the Stop's
* count less the tasks whose finish the transcript recorded after it
* (`FinalTurn.finishedTasks`). No turn ran since that Stop, so every task
* finishing after it is one the count included; a finish does not always
* bring a new Stop (its notification can wait in an idle session's queue). */
export declare function backgroundLeft(count: number | undefined, stoppedAt: string, finishedTasks?: readonly string[]): number;
/** Record one lifecycle event for `pane`. Writes run one at a time, so a Stop
* and the next prompt arriving together keep their order. */
export declare function noteTurn(server: string, pane: string, event: TurnEvent): Promise<TurnRecord | undefined>;
/** The recorded turns of `pane`'s latest conversation, if its hooks reported any. */
export declare function readTurn(server: string, pane: string): Promise<TurnRecord | undefined>;
/** OpenCode's turns for a pane running `pids`, from the stamps phren's OpenCode
* plugin writes on session.status busy / session.idle; undefined for an older
* plugin that writes none. `terminal` is the pane's, since the PIDs are. */
export declare function opencodeTurn(pids: number[], terminal: string): Promise<TurnRecord | undefined>;
export {};