MCPcopy Create free account
hub / github.com/agent-tower/core / start

Method start

packages/server/src/services/session-manager.ts:146–213  ·  view source on GitHub ↗
(id: string)

Source from the content-addressed store, hash-verified

144 private readonly eventBus: EventBus,
145 teamReconciler?: TeamReconcilerService,
146 runtimeRegistry?: RuntimeRegistry,
147 ) {
148 this.teamReconciler = teamReconciler ?? new TeamReconcilerService({
149 eventBus,
150 sessionMessenger: this,
151 // 续催/唤醒统一由 MemberHeartbeatScheduler 轮询驱动;这里关闭内部 setTimeout 避免双驱动重复触发。
152 // session 退出时的首次 reconcile(COMPLETED 判定 / 首次补催)仍即时执行,不依赖该定时器。
153 scheduleReminders: false,
154 });
155 this.runtimeCoordinator = new RuntimeCoordinator(
156 runtimeRegistry ?? new StaticRuntimeRegistry([
157 new CliRuntimeDriver(),
158 new AcpRuntimeDriver(),
159 ]),
160 {
161 onTurnEvent: (event) => this.handleRuntimeTurnEvent(event),
162 onRuntimeState: (state) => this.handleRuntimeState(state),
163 onProcessEvent: (event) => this.handleRuntimeProcessEvent(event),
164 onDriverSessionDisposed: (sessionId) => revokeAgentApiCredential(sessionId),
165 },
166 );
167
168 // Patches only mark the snapshot dirty. A low-frequency checkpoint keeps the
169 // hot stream away from SQLite while terminal paths still force a final flush.
170 this.eventBus.on('session:patch', ({ sessionId, patch }) => {
171 if (DEBUG_SNAPSHOT) {
172 const ops = (patch as Array<{ op?: string; path?: string }>).slice(0, 3)
173 .map((p) => `${p.op ?? '?'}:${p.path ?? '?'}`)
174 .join(', ');
175 console.log(
176 `[SessionManager:snapshot] patch sessionId=${sessionId} ops=${(patch as unknown[]).length} [${ops}]`
177 );
178 }
179 this.scheduleSnapshotPersist(sessionId);
180 // 仅 agent 侧真实进展用作 TeamRun 成员心跳信号(节流落库);本地 user_message(含唤醒)被过滤。
181 this.maybeRecordTeamRunHeartbeat(sessionId, patch);
182 });
183
184 this.eventBus.on('session:turn-completed', ({ sessionId }) => {
185 if (this.terminalSessions.has(sessionId)) return;
186 // The parser has already written raw stdout, the final assistant entry,
187 // usage and all other state from the turn.completed chunk at this point.
188 this.terminalSessions.set(sessionId, SessionStatus.COMPLETED);
189 this.startSessionFinalization(sessionId, 0, { logicalCompletion: true });
190 });
191
192 this.eventBus.on('session:turn-failed', ({ sessionId }) => {
193 if (this.terminalSessions.has(sessionId)) return;
194 // A turn failure is terminal even when the CLI wrapper later exits 0 or
195 // without an exit code. Use a synthetic non-zero code for the shared
196 // finalization path so success-only post-processing cannot run.
197 this.terminalSessions.set(sessionId, SessionStatus.FAILED);
198 this.startSessionFinalization(sessionId, 1, { logicalCompletion: true });
199 });
200
201 // NOTE: checkTaskAutoRevert is called directly (awaited) inside start()
202 // and sendMessage() to guarantee the task status is updated before the
203 // HTTP response is sent. A fire-and-forget EventBus listener here caused

Callers 9

buildAppFunction · 0.45
sessionRoutesFunction · 0.45
tunnelRoutesFunction · 0.45
startNextSessionsMethod · 0.45
triggerGenerationMethod · 0.45
createMethod · 0.45

Tested by

no test coverage detected