import type { Message } from './types.js'; export interface SessionMeta { id: string; /** * When the file was last written, not when the session began. The id carries the start time, so * "where I left off" needs a separate figure — a session resumed and worked in for an hour is * more recent than one abandoned after a minute, however their ids sort. */ updatedAt?: string; /** * A name someone gave this session. * * The id is a timestamp, which tells you when and nothing else. After a week of sessions the * picker is a wall of near-identical numbers and the only way to find the one you want is to * resume each in turn. A name is how anybody actually refers to their own work. */ name?: string; /** * Hidden from the picker without being deleted. * * The alternative people reach for is deleting, which is not the same thing at all: an * abandoned experiment is worth keeping and not worth seeing every day. */ archived?: boolean; /** * The plan as it stood when the session was saved. * * Resuming without it means the model reads its own history and writes a new plan from * scratch — the same forgetting that made "continue" restart a job it was halfway through. */ plan?: { steps: Array<{ text: string; state: string; note?: string; }>; }; /** * The outcome the developer asked KONECK to keep in view for this session. * * Stored beside the plan rather than inferred from old prompts: an explicit goal must survive * resume and fork even when the original briefing has been compacted away. */ goal?: string; /** Interactive execution posture, restored with the conversation rather than guessed anew. */ mode?: 'auto' | 'edits' | 'careful' | 'plan'; effort?: 'low' | 'medium' | 'high' | 'max'; requireApproval?: boolean; /** * The git branch the work was on. * * What a person actually uses to tell two sessions apart when both say "fix the tests" — the * timestamp in the id says when, and says nothing about which piece of work it belongs to. */ branch?: string; /** * How large the session file is. * * A rough measure of how much was done, and free: the listing already stats every file to sort * by modification time. */ sizeBytes?: number; /** The session this was forked from, when it was. */ forkedFrom?: string; task: string; provider: string; model: string; cwd: string; startedAt: string; turns: number; /** * Model requests made, which is the number the token count actually tracks. * * A session showing "5 turns · 20,911,077 tokens" reads as a bug; the same session showing "289 * requests" reads as what it was — a long agentic run re-sending a large conversation. The figure * that explains a cost belongs beside the cost. */ requests?: number; totalTokens: number; } /** * Session files are durable, portable records. No caller may accidentally turn them into a * credential store, including by putting a token in a tool argument or trajectory detail. * * OpenAI messages and trajectory events are JSON-shaped, so recursively masking every string is * both safer than maintaining a fragile list of `content` fields and preserves their structure * for a later resume. */ export declare function redactSessionData(value: T): T; /** * A sortable, legible, unique session id. * * The suffix used to be `getTime() % 0xffff` — a function of the same clock as the timestamp in * front of it, so two ids minted in the same millisecond came out identical and `/clear` "starting * a new session" quietly kept writing to the file of the one it replaced. * * Two halves now, because the two kinds of collision have different causes: the counter makes ids * from one process distinct from each other with certainty rather than with high probability, and * the random half keeps concurrent processes apart, where no shared counter exists. */ export declare function generateSessionId(): string; export declare function saveSession(cwd: string, id: string, meta: SessionMeta, messages: Message[], /** * What happened and when, if the caller kept it. * * The messages say what was said; only this says where the time went. It was held in memory and * discarded at exit, which meant "twenty-five minutes, of which nineteen were waiting for first * tokens" was answerable while a session ran and unanswerable a second later. Written last so an * older KONECK reading this file simply does not recognise the line and skips it. */ trajectory?: readonly unknown[]): Promise; export declare function loadSession(cwd: string, id: string): Promise<{ meta: SessionMeta; messages: Message[]; }>; /** * Saved sessions, most recently worked in first. * * Ordered by when each file was last written, not by the timestamp in its name. A session that was * resumed and worked in for an hour still carries the id it was born with, so ordering by name put * the session you were just in below ones you had not touched for days — and picking the top entry * gave you the oldest work rather than the newest. */ export declare function listSessions(cwd: string, limit?: number, includeArchived?: boolean): Promise; /** Gives a session a name, or clears it when given nothing. */ export declare function renameSession(cwd: string, id: string, name: string): Promise; /** Hides a session from the picker, or brings it back. */ export declare function archiveSession(cwd: string, id: string, archived?: boolean): Promise; export declare function deleteSession(cwd: string, id: string): Promise; /** * Copies a session so it can be continued without touching the original. * * For trying a second approach to the same problem: the point of a branch is that the first one * survives being wrong. Both halves keep the full history, since a fork whose past was summarised * away is not the same conversation. */ export declare function forkSession(cwd: string, id: string, name?: string): Promise<{ id: string; meta: SessionMeta; }>; /** * Finds a session by id, or by name when the name is unambiguous. * * Names are what people remember. An ambiguous one is reported rather than guessed at, because * resuming the wrong session is only obvious several turns later. */ export declare function findSession(cwd: string, query: string): Promise<{ id: string; } | { error: string; }>; /** "just now", "4 minutes ago", "2 days ago" — how recent a session is, as people say it. */ export declare function relativeAge(iso: string | undefined, now?: number): string; /** * Turns and requests, counted from what actually happened. * * Cheap: one pass over events the caller already holds. Zero when there is no trajectory, so a * caller that keeps none is never given a figure invented on its behalf. */ export declare function countFromTrajectory(trajectory: readonly unknown[] | undefined): { turns: number; requests: number; }; //# sourceMappingURL=session.d.ts.map