import type { GoalSnapshot } from '#/features/goal/types'; import type { SessionStatusResponse } from './sessionProtocol'; import { LifecycleScope } from '#/app/scopes'; import { type IAgentScopeHandle, type ISessionScopeHandle, ScopeActivation, registerScopedService, } from '#/_base/di/scope'; import { IInstantiationService, type ServicesAccessor, } from '#/_base/di/instantiation'; import { ISessionTokenCountingService } from '#/session/tokenCounting/sessionTokenCounting'; import { IAgentGoalService } from '#/features/goal/goalService'; import { IAgentPermissionModeService } from '#/agent/permissionMode/permissionMode'; import { IAgentPlanService } from '#/features/plan/plan'; import { IAgentProfileService } from '#/agent/profile/profile'; import { IAgentSwarmService } from '#/features/swarm/agent/swarm'; import { IAgentTowerService } from '#/features/tower/tower'; import { agentContextOf } from '#/agent/scopeContext/scopeContext'; import { getLiveSessionById, resumeSessionById, } from '#/app/sessionManager/sessionLookup'; import { IModelCatalog } from '#/llm-adapter/model/catalog'; import { IModelService } from '#/llm-adapter/model/model'; import { ErrorCodes, Error2 } from '#/errors'; import { ensureMainAgent } from '#/session/agentLifecycle/mainAgent'; import { IAgentLifecycleService } from '#/session/agentLifecycle/agentLifecycle'; import { IAgentLoopService } from '#/agent/loop/loop'; import { IAgentTaskService } from '#/agent/task/task'; import { IAgentFullCompactionService } from '#/agent/fullCompaction/fullCompaction'; import { ISessionLegacyService } from './sessionLegacy'; export class SessionLegacyService implements ISessionLegacyService { declare readonly _serviceBrand: undefined; private readonly services: ServicesAccessor; constructor(@IInstantiationService instantiation: IInstantiationService) { this.services = { get: (id) => instantiation.invokeFunction((accessor) => accessor.get(id)), }; } private resume(sessionId: string): Promise { return resumeSessionById(this.services, sessionId); } private async resolveMainAgent(sessionId: string): Promise { const session = await this.resume(sessionId); if (session === undefined) { throw new Error2(ErrorCodes.SESSION_NOT_FOUND, `session ${sessionId} does not exist`); } const context = await ensureMainAgent(session); const handle = session.accessor.get(IAgentLifecycleService).handleOf(context.agentId); if (handle === undefined) { throw new Error2(ErrorCodes.AGENT_NOT_FOUND, 'Main agent was not found'); } return handle; } async status(sessionId: string): Promise { const agent = await this.resolveMainAgent(sessionId); return this.assembleStatus(sessionId, agent); } private async assembleStatus( sessionId: string, agent: IAgentScopeHandle, ): Promise { const profile = agent.accessor.get(IAgentProfileService); const tokenCounting = agent.accessor.get(ISessionTokenCountingService); const permission = agent.accessor.get(IAgentPermissionModeService); const plan = agent.accessor.get(IAgentPlanService); const swarm = agent.accessor.get(IAgentSwarmService); const tower = agent.accessor.get(IAgentTowerService); const model = profile.getModel(); const capabilities = profile.getModelCapabilities(); let maxTokens = capabilities.max_input_tokens ?? capabilities.max_context_tokens; if (maxTokens === 0 && model === '') { maxTokens = resolveDefaultModelContextTokens(agent) ?? 0; } const tokens = tokenCounting.statusSize(agentContextOf(agent)); const planData = await plan.status(); return { busy: this.readBusy(sessionId), model: model === '' ? undefined : model, thinking_level: model === '' ? '' : profile.getEffectiveThinkingLevel(), permission: permission.mode, plan_mode: planData !== null, swarm_mode: swarm.isActive, tower_mode: tower.isActive, context_tokens: tokens, max_context_tokens: maxTokens > 0 ? maxTokens : undefined, context_usage: maxTokens > 0 ? Math.min(1, tokens / maxTokens) : undefined, }; } private readBusy(sessionId: string): boolean { const handle = getLiveSessionById(this.services, sessionId); if (handle === undefined) return false; const agents = handle.accessor.get(IAgentLifecycleService); for (const agent of agents.list()) { const agentHandle = agents.handleOf(agent.agentId); if (agentHandle === undefined) continue; if (agentHandle.accessor.get(IAgentLoopService).snapshot().state === 'running') return true; const tasks = agentHandle.accessor.get(IAgentTaskService); if (tasks.list(true).length > 0) return true; if (agentHandle.accessor.get(IAgentFullCompactionService).compacting !== null) return true; } return false; } async goal(sessionId: string): Promise { const agent = await this.resolveMainAgent(sessionId); return agent.accessor.get(IAgentGoalService).getGoal().goal; } } function resolveDefaultModelContextTokens(agent: IAgentScopeHandle): number | undefined { const defaultModel = agent.accessor.get(IModelService).getDefaultModel(); if (defaultModel === undefined || defaultModel.length === 0) return undefined; try { const capabilities = agent.accessor.get(IModelCatalog).get(defaultModel).capabilities; return capabilities.max_input_tokens ?? capabilities.max_context_tokens; } catch { return undefined; } } registerScopedService( LifecycleScope.App, ISessionLegacyService, SessionLegacyService, ScopeActivation.OnScopeCreated, 'sessionLegacy', );