MCPcopy Create free account
hub / github.com/tiann/hapi / buildMigratorForRequest

Method buildMigratorForRequest

hub/src/sync/syncEngine.ts:553–602  ·  view source on GitHub ↗
(_request: CursorMigrateToAcpRequest)

Source from the content-addressed store, hash-verified

551 }
552
553 private buildMigratorForRequest(_request: CursorMigrateToAcpRequest): CursorLegacyMigrator {
554 const migratorOpts: CursorLegacyMigratorOptions = {}
555 return new CursorLegacyMigrator(migratorOpts, {
556 archiveSession: async (sessionId) => {
557 await this.archiveSession(sessionId)
558 },
559 // NOTE: no awaitSessionInactive injection — handleSessionEnd()
560 // synchronously sets cache.active=false inside archiveSession,
561 // so any cache-based poll would return immediately and provide
562 // false reassurance. The migrator now relies on
563 // awaitLockRelease's minimum-dwell + SQLite busy-probe +
564 // size-stability combination instead. Codex review #34 P1 v3.
565 getCurrentSession: (sessionId, namespace) => {
566 const s = this.sessionCache.getSessionByNamespace(sessionId, namespace)
567 if (!s) return null
568 return {
569 active: s.active === true,
570 lifecycleState: typeof s.metadata?.lifecycleState === 'string' ? s.metadata.lifecycleState : undefined,
571 cursorSessionProtocol: typeof s.metadata?.cursorSessionProtocol === 'string' ? s.metadata.cursorSessionProtocol : undefined
572 }
573 },
574 updateSessionAfterMigrate: (sessionId, namespace, lastUsedModel) => {
575 const result = this.flipCursorSessionProtocolToAcp(sessionId, namespace, lastUsedModel)
576 if (result.result === 'success') return { ok: true }
577 if (result.result === 'session-active') return { ok: false, reason: 'session_active' as const }
578 return { ok: false, reason: 'version_mismatch_or_missing' as const }
579 },
580 // tiann/hapi#872: size sanity check needs to compare HAPI's known
581 // message history against the candidate legacy store's blob
582 // count. The store-handle stays on the engine; we only thread
583 // the count through so the migrator stays free of a direct
584 // hub.Store dependency.
585 getHapiMessageCount: (sessionId, _namespace) => {
586 try {
587 return this.store.messages.countMessages(sessionId)
588 } catch (err) {
589 // tiann/hapi#873 cold review: a silent 0 here trips
590 // the migrator's "skip sanity" branch and chronically
591 // disables the floor. Warn so a broken countMessages
592 // (lock contention pattern, schema drift) is visible
593 // in journalctl.
594 console.warn('[auto-migrate] countMessages threw; size sanity skipped', {
595 sessionId,
596 err: err instanceof Error ? err.message : String(err)
597 })
598 return 0
599 }
600 }
601 })
602 }
603
604 async switchSession(sessionId: string, to: 'remote' | 'local'): Promise<void> {
605 await this.rpcGateway.switchSession(sessionId, to)

Calls 5

archiveSessionMethod · 0.95
countMessagesMethod · 0.80
warnMethod · 0.80
getSessionByNamespaceMethod · 0.45

Tested by

no test coverage detected