(
workspacePath: string,
expectedSessionId?: string,
forceRestart = false
)
| 319 | `post-bootstrap kilo session lookup end runtime=${runtimeKind} outcome=ok expectedSessionId=${expectedSessionId} returnedSessionId=${session.id} elapsedMs=${Date.now() - lookupStartedAt}` |
| 320 | ); |
| 321 | } catch (error) { |
| 322 | logToFile( |
| 323 | `post-bootstrap kilo session lookup end runtime=${runtimeKind} outcome=error expectedSessionId=${expectedSessionId} elapsedMs=${Date.now() - lookupStartedAt}` |
| 324 | ); |
| 325 | throw error; |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | const globalFeedManager = createGlobalFeedManager({ |
| 330 | canOpen: () => Boolean(runtime.kiloClient && state.currentSession), |
| 331 | open: () => { |
| 332 | const kiloClient = runtime.kiloClient; |
| 333 | if (!kiloClient) { |
| 334 | throw new Error('Cannot open Kilo global feed: no Kilo client'); |
| 335 | } |
| 336 | return openKiloGlobalFeed({ state, kiloClient }); |
| 337 | }, |
| 338 | onConnectionError: () => { |
| 339 | logToFile('kilo global feed failed'); |
| 340 | }, |
| 341 | onOpenError: () => { |
| 342 | logToFile('failed to start kilo global feed'); |
| 343 | }, |
| 344 | }); |
| 345 | |
| 346 | // Runtime transitions must not interleave: readySession, updateRuntimeEnvironment |
| 347 | // and restartKiloRuntime can each request one concurrently, and two bodies racing |
| 348 | // through the awaits in the runtime start would overwrite each other's |
| 349 | // connectionManager/lifecycleManager bindings, orphaning one of the freshly |
| 350 | // spawned kilo server processes. |
| 351 | runtime = createKiloRuntimeLifecycle({ |
| 352 | createKilo, |
| 353 | bindClient: (result, workspacePath) => |
| 354 | createWrapperKiloClient(result.client as SDKClient, result.server.url, workspacePath), |
| 355 | captureEnv: () => process.env, |
| 356 | getPlatform: () => serverConfig.platform, |
| 357 | log: logToFile, |
| 358 | chdir: workspacePath => process.chdir(workspacePath), |
| 359 | assignProcessEnv: env => { |
| 360 | Object.assign(process.env, env); |
| 361 | }, |
| 362 | isShuttingDown: () => isShuttingDown, |
| 363 | getKiloSessionId: () => kiloSessionId, |
| 364 | applyKiloSessionId: sessionId => { |
| 365 | kiloSessionId = sessionId; |
| 366 | serverConfig.sessionId = sessionId; |
| 367 | }, |
| 368 | verifyExistingKiloSession, |
| 369 | onBeforeSpawnTeardown: async () => { |
| 370 | globalFeedManager.close(); |
| 371 | lifecycleManager?.stop(); |
| 372 | await connectionManager?.close(); |
| 373 | serverDeps.kiloClient = unavailableKiloClient; |
| 374 | }, |
| 375 | onRuntimeStarted: ({ client, workspacePath, kiloSessionId: startedSessionId }) => { |
| 376 | serverDeps.kiloClient = client; |
| 377 | serverConfig.workspacePath = workspacePath; |
| 378 | serverConfig.sessionId = startedSessionId; |
no test coverage detected