import type { Skill } from "@mariozechner/pi-coding-agent"; import type { ChatType } from "../../channels/chat-type.js"; import type { ChannelId } from "../../channels/plugins/channel-id.types.js"; import type { DeliveryContext } from "../../utils/delivery-context.types.js"; import type { TtsAutoMode } from "../types.tts.js"; export type SessionScope = "per-sender" | "global"; export type SessionChannelId = ChannelId; export type SessionChatType = ChatType; export type SessionOrigin = { label?: string; provider?: string; surface?: string; chatType?: SessionChatType; from?: string; to?: string; nativeChannelId?: string; nativeDirectUserId?: string; accountId?: string; threadId?: string | number; }; export type SessionAcpIdentitySource = "ensure" | "status" | "event"; export type SessionAcpIdentityState = "pending" | "resolved"; export type SessionAcpIdentity = { state: SessionAcpIdentityState; acpxRecordId?: string; acpxSessionId?: string; agentSessionId?: string; source: SessionAcpIdentitySource; lastUpdatedAt: number; }; export type SessionAcpMeta = { backend: string; agent: string; runtimeSessionName: string; identity?: SessionAcpIdentity; mode: "persistent" | "oneshot"; runtimeOptions?: AcpSessionRuntimeOptions; cwd?: string; state: "idle" | "running" | "error"; lastActivityAt: number; lastError?: string; }; export type AcpSessionRuntimeOptions = { /** * ACP runtime mode set via session/set_mode (for example: "plan", "normal", "auto"). */ runtimeMode?: string; /** ACP runtime config option: model id. */ model?: string; /** ACP runtime config option: thinking/reasoning effort. */ thinking?: string; /** Working directory override for ACP session turns. */ cwd?: string; /** ACP runtime config option: permission profile id. */ permissionProfile?: string; /** ACP runtime config option: per-turn timeout in seconds. */ timeoutSeconds?: number; /** Backend-specific option bag mapped through session/set_config_option. */ backendExtras?: Record; }; export type CliSessionBinding = { sessionId: string; /** Trust an explicitly attached CLI session even when auth, prompt, or MCP fingerprints drift. */ forceReuse?: boolean; authProfileId?: string; authEpoch?: string; authEpochVersion?: number; extraSystemPromptHash?: string; mcpConfigHash?: string; mcpResumeHash?: string; }; export type SessionCompactionCheckpointReason = "manual" | "auto-threshold" | "overflow-retry" | "timeout-retry"; export type SessionCompactionTranscriptReference = { sessionId: string; sessionFile?: string; leafId?: string; entryId?: string; }; export type SessionCompactionCheckpoint = { checkpointId: string; sessionKey: string; sessionId: string; createdAt: number; reason: SessionCompactionCheckpointReason; tokensBefore?: number; tokensAfter?: number; summary?: string; firstKeptEntryId?: string; preCompaction: SessionCompactionTranscriptReference; postCompaction: SessionCompactionTranscriptReference; }; export type SessionPluginDebugEntry = { pluginId: string; lines: string[]; }; export type SessionPluginJsonValue = string | number | boolean | null | SessionPluginJsonValue[] | { [key: string]: SessionPluginJsonValue; }; export type SessionPluginNextTurnInjection = { id: string; pluginId: string; pluginName?: string; text: string; idempotencyKey?: string; placement: "prepend_context" | "append_context"; ttlMs?: number; createdAt: number; metadata?: SessionPluginJsonValue; }; export type SubagentRecoveryState = { /** Consecutive accepted automatic orphan-recovery resumes in the rapid re-wedge window. */ automaticAttempts?: number; /** Timestamp (ms) of the latest accepted automatic orphan-recovery resume. */ lastAttemptAt?: number; /** Registry run id that triggered the latest automatic orphan-recovery resume. */ lastRunId?: string; /** Timestamp (ms) when automatic recovery was tombstoned for this session. */ wedgedAt?: number; /** Human-readable reason automatic recovery was tombstoned. */ wedgedReason?: string; }; export type SessionEntry = { /** * Last delivered heartbeat payload (used to suppress duplicate heartbeat notifications). * Stored on the main session entry. */ lastHeartbeatText?: string; /** Timestamp (ms) when lastHeartbeatText was delivered. */ lastHeartbeatSentAt?: number; /** * Base session key for heartbeat-created isolated sessions. * When present, `:heartbeat` is a synthetic isolated session rather than * a real user/session-scoped key that merely happens to end with `:heartbeat`. */ heartbeatIsolatedBaseSessionKey?: string; /** Heartbeat task state (task name -> last run timestamp ms). */ heartbeatTaskState?: Record; /** Plugin-owned session state, grouped by plugin id then extension namespace. */ pluginExtensions?: Record>; /** Top-level SessionEntry mirror slots owned by plugin session extensions. */ pluginExtensionSlotKeys?: Record>; /** Durable one-shot prompt additions drained before the next agent turn. */ pluginNextTurnInjections?: Record; sessionId: string; updatedAt: number; sessionFile?: string; /** Parent session key that spawned this session (used for sandbox session-tool scoping). */ spawnedBy?: string; /** Workspace inherited by spawned sessions and reused on later turns for the same child session. */ spawnedWorkspaceDir?: string; /** Explicit parent session linkage for dashboard-created child sessions. */ parentSessionKey?: string; /** True after a thread/topic session has been forked from its parent transcript once. */ forkedFromParent?: boolean; /** Subagent spawn depth (0 = main, 1 = sub-agent, 2 = sub-sub-agent). */ spawnDepth?: number; /** Explicit role assigned at spawn time for subagent tool policy/control decisions. */ subagentRole?: "orchestrator" | "leaf"; /** Explicit control scope assigned at spawn time for subagent control decisions. */ subagentControlScope?: "children" | "none"; /** Plugin id that created this session through api.runtime.subagent. */ pluginOwnerId?: string; systemSent?: boolean; abortedLastRun?: boolean; /** Durable guard state for automatic subagent orphan recovery. */ subagentRecovery?: SubagentRecoveryState; /** Timestamp (ms) when the current sessionId first became active. */ sessionStartedAt?: number; /** Timestamp (ms) of the last user/channel interaction that should extend idle lifetime. */ lastInteractionAt?: number; /** Stable first-run start time for subagent sessions, persisted after completion. */ startedAt?: number; /** Latest completed run end time for subagent sessions, persisted after completion. */ endedAt?: number; /** Accumulated runtime across subagent follow-up runs, persisted after completion. */ runtimeMs?: number; /** Final persisted subagent run status, used after in-memory run archival. */ status?: "running" | "done" | "failed" | "killed" | "timeout"; /** * Session-level stop cutoff captured when /stop is received. * Messages at/before this boundary are skipped to avoid replaying * queued pre-stop backlog. */ abortCutoffMessageSid?: string; /** Epoch ms cutoff paired with abortCutoffMessageSid when available. */ abortCutoffTimestamp?: number; chatType?: SessionChatType; thinkingLevel?: string; fastMode?: boolean; verboseLevel?: string; traceLevel?: string; reasoningLevel?: string; elevatedLevel?: string; ttsAuto?: TtsAutoMode; /** Hash of the latest assistant reply that was sent through `/tts latest`. */ lastTtsReadLatestHash?: string; /** Timestamp (ms) when `/tts latest` last sent audio for this session. */ lastTtsReadLatestAt?: number; execHost?: string; execSecurity?: string; execAsk?: string; execNode?: string; responseUsage?: "on" | "off" | "tokens" | "full"; providerOverride?: string; modelOverride?: string; /** Session-scoped agent runtime/harness override selected with the model picker. */ agentRuntimeOverride?: string; /** * Tracks whether the persisted model override came from an explicit user * action (`/model`, `sessions.patch`) or from a temporary runtime fallback. * Resets only preserve user-driven overrides. */ modelOverrideSource?: "auto" | "user"; authProfileOverride?: string; authProfileOverrideSource?: "auto" | "user"; authProfileOverrideCompactionCount?: number; /** * Set on explicit user-driven session model changes (for example `/model` * and `sessions.patch`) during an active run. The embedded runner checks * this flag to decide whether to throw `LiveSessionModelSwitchError`. * System-initiated fallbacks (rate-limit retry rotation) never set this * flag, so they are never mistaken for user-initiated switches. */ liveModelSwitchPending?: boolean; groupActivation?: "mention" | "always"; groupActivationNeedsSystemIntro?: boolean; sendPolicy?: "allow" | "deny"; queueMode?: "steer" | "followup" | "collect" | "steer-backlog" | "steer+backlog" | "queue" | "interrupt"; queueDebounceMs?: number; queueCap?: number; queueDrop?: "old" | "new" | "summarize"; inputTokens?: number; outputTokens?: number; totalTokens?: number; /** Durable marker that final user reply delivery still needs a retry/resume pass. */ pendingFinalDelivery?: boolean; pendingFinalDeliveryCreatedAt?: number; pendingFinalDeliveryLastAttemptAt?: number; pendingFinalDeliveryAttemptCount?: number; pendingFinalDeliveryLastError?: string | null; /** Frozen reply text that needs delivery. */ pendingFinalDeliveryText?: string | null; /** Original delivery context (channel, recipient, etc). */ pendingFinalDeliveryContext?: DeliveryContext; /** * Whether totalTokens reflects a fresh context snapshot for the latest run. * Undefined means legacy/unknown freshness; false forces consumers to treat * totalTokens as stale/unknown for context-utilization displays. */ totalTokensFresh?: boolean; estimatedCostUsd?: number; cacheRead?: number; cacheWrite?: number; modelProvider?: string; model?: string; /** * Embedded agent harness selected for this session id. * Prevents config/env changes from moving an existing transcript between * incompatible runtime harnesses. */ agentHarnessId?: string; /** * Last selected/runtime model pair for which a fallback notice was emitted. * Used to avoid repeating the same fallback notice every turn. */ fallbackNoticeSelectedModel?: string; fallbackNoticeActiveModel?: string; fallbackNoticeReason?: string; contextTokens?: number; compactionCount?: number; compactionCheckpoints?: SessionCompactionCheckpoint[]; memoryFlushAt?: number; memoryFlushCompactionCount?: number; memoryFlushContextHash?: string; cliSessionIds?: Record; cliSessionBindings?: Record; claudeCliSessionId?: string; label?: string; displayName?: string; channel?: string; groupId?: string; subject?: string; groupChannel?: string; space?: string; origin?: SessionOrigin; deliveryContext?: DeliveryContext; lastChannel?: SessionChannelId; lastTo?: string; lastAccountId?: string; lastThreadId?: string | number; skillsSnapshot?: SessionSkillSnapshot; systemPromptReport?: SessionSystemPromptReport; /** * Generic plugin-owned runtime debug entries shown in verbose status surfaces. * Each plugin owns and may overwrite only its own entry between turns. */ pluginDebugEntries?: SessionPluginDebugEntry[]; acp?: SessionAcpMeta; }; export declare function resolveSessionPluginStatusLines(entry: Pick | undefined): string[]; export declare function resolveSessionPluginTraceLines(entry: Pick | undefined): string[]; export declare function normalizeSessionRuntimeModelFields(entry: SessionEntry): SessionEntry; export declare function setSessionRuntimeModel(entry: SessionEntry, runtime: { provider: string; model: string; }): boolean; export type SessionEntryMergePolicy = "touch-activity" | "preserve-activity"; type MergeSessionEntryOptions = { policy?: SessionEntryMergePolicy; now?: number; }; export declare function mergeSessionEntryWithPolicy(existing: SessionEntry | undefined, patch: Partial, options?: MergeSessionEntryOptions): SessionEntry; export declare function mergeSessionEntry(existing: SessionEntry | undefined, patch: Partial): SessionEntry; export declare function mergeSessionEntryPreserveActivity(existing: SessionEntry | undefined, patch: Partial): SessionEntry; export declare function resolveSessionTotalTokens(entry?: Pick | null): number | undefined; export declare function resolveFreshSessionTotalTokens(entry?: Pick | null): number | undefined; export declare function isSessionTotalTokensFresh(entry?: Pick | null): boolean; export type GroupKeyResolution = { key: string; channel?: string; id?: string; chatType?: SessionChatType; }; export type SessionSkillSnapshot = { prompt: string; skills: Array<{ name: string; primaryEnv?: string; requiredEnv?: string[]; }>; /** Normalized agent-level filter used to build this snapshot; undefined means unrestricted. */ skillFilter?: string[]; /** * Runtime-only, never persisted. Carries the full parsed Skill[] (including * each SKILL.md body) so the embedded runner can skip a workspace skill * scan within a turn. Stripped from sessions.json on every read and write * via normalizeSessionStore — see store-load.ts. On a cold session resume * this is undefined and src/agents/pi-embedded-runner/skills-runtime.ts * rebuilds it by reloading skill entries from disk. */ resolvedSkills?: Skill[]; version?: number; }; export type SessionSystemPromptReport = { source: "run" | "estimate"; generatedAt: number; sessionId?: string; sessionKey?: string; provider?: string; model?: string; workspaceDir?: string; bootstrapMaxChars?: number; bootstrapTotalMaxChars?: number; bootstrapTruncation?: { warningMode?: "off" | "once" | "always"; warningShown?: boolean; promptWarningSignature?: string; warningSignaturesSeen?: string[]; truncatedFiles?: number; nearLimitFiles?: number; totalNearLimit?: boolean; }; sandbox?: { mode?: string; sandboxed?: boolean; }; systemPrompt: { chars: number; projectContextChars: number; nonProjectContextChars: number; }; injectedWorkspaceFiles: Array<{ name: string; path: string; missing: boolean; rawChars: number; injectedChars: number; truncated: boolean; }>; skills: { promptChars: number; entries: Array<{ name: string; blockChars: number; }>; }; tools: { listChars: number; schemaChars: number; entries: Array<{ name: string; summaryChars: number; schemaChars: number; propertiesCount?: number | null; }>; }; }; export declare const DEFAULT_RESET_TRIGGER = "/new"; export declare const DEFAULT_RESET_TRIGGERS: string[]; export declare const DEFAULT_IDLE_MINUTES = 0; export {};