import type { SessionSummary as V2SessionSummary } from '@moonshot-ai/agent-core-v2'; import type { GoalChange, GoalSnapshot } from '@moonshot-ai/agent-core-v2/features/goal/types'; import type { PlanData } from '@moonshot-ai/agent-core-v2/features/plan/plan'; import type { ModelCapability, ProviderConfig } from '@moonshot-ai/kosong'; import type { CompactionResult } from '@moonshot-ai/agent-core-v2/agent/fullCompaction/types'; import type { UsageStatus } from '@moonshot-ai/agent-core-v2/agent/usage/usage'; import type { AgentContextData, ContextMessage } from '#/context'; import type { PermissionApprovalResultRecord, PermissionData, PermissionMode } from '#/permission'; import type { BackgroundTaskInfo } from '#/task'; import type { ToolInfo } from '#/tool'; export type AgentType = 'main' | 'sub' | 'independent'; export interface AgentConfigData { cwd: string; provider?: ProviderConfig; modelAlias?: string; modelCapabilities: ModelCapability; profileName?: string; subagentNames?: readonly string[]; thinkingEffort: string; systemPrompt: string; } export type AgentConfigUpdateData = Partial<{ cwd: string; modelAlias: string; profileName: string; subagentNames: readonly string[]; thinkingEffort: string; systemPrompt: string; }>; export interface AgentMeta { readonly homedir?: string; readonly type: AgentType; readonly parentAgentId?: string | null; readonly swarmItem?: string; } export interface SessionMeta { createdAt: string; updatedAt: string; title: string; isCustomTitle: boolean; lastPrompt?: string; forkedFrom?: string; workDir?: string; additionalDirs?: string[]; agents: Record; custom: Record; } export type AgentReplayRecordPayload = | { type: 'message'; message: ContextMessage } | { type: 'compaction'; result?: CompactionResult | 'cancelled'; instruction?: string } | { type: 'goal_updated'; snapshot: GoalSnapshot; change: GoalChange | { readonly kind: 'created' }; } | { type: 'plan_updated'; enabled: boolean } | { type: 'config_updated'; config: AgentConfigUpdateData } | { type: 'permission_updated'; mode: PermissionMode } | { type: 'approval_result'; record: PermissionApprovalResultRecord }; export type AgentReplayRecord = { readonly time: number } & AgentReplayRecordPayload; export interface ResumedAgentState { readonly type: AgentType; readonly config: AgentConfigData; readonly context: AgentContextData; readonly replay: readonly AgentReplayRecord[]; readonly permission: PermissionData; readonly plan: PlanData; readonly swarmMode?: boolean | undefined; readonly usage: UsageStatus; readonly tools: readonly ToolInfo[]; readonly toolStore?: Readonly>; readonly background: readonly BackgroundTaskInfo[]; } export interface ResumeSessionResult extends V2SessionSummary { readonly sessionMetadata: SessionMeta; readonly agents: Readonly>; readonly warning?: string | undefined; } export function limitAgentReplayByTurns( records: readonly AgentReplayRecord[], maxTurns?: number, ): readonly AgentReplayRecord[] { if (maxTurns === undefined) return records; if (maxTurns <= 0) return []; const turnStarts = records.flatMap((record, index) => isAgentReplayUserTurnRecord(record) ? [index] : [], ); if (turnStarts.length <= maxTurns) return records; return records.slice(turnStarts[turnStarts.length - maxTurns]); } function isAgentReplayUserTurnRecord(record: AgentReplayRecord): boolean { if (record.type !== 'message') return false; const { message } = record; if (message.role !== 'user') return false; switch (message.origin?.kind) { case undefined: case 'user': return true; case 'skill_activation': return message.origin.trigger === 'user-slash'; case 'plugin_command': return message.origin.trigger === 'user-slash'; case 'shell_command': return message.origin.phase === 'input'; case 'cron_job': case 'cron_missed': return true; case 'background_task': case 'compaction_summary': case 'hook_result': case 'injection': case 'retry': return false; case 'system_trigger': return message.origin.name === 'goal_continuation'; } }