1867
1868
shutdown(): Promise<void> {
1869
>
// Phase 6: drain provisional sessions FIRST so any in-flight
claudeAgent.ts
1870
>
// `await sdk.startup()` (kicked off by a racing `sendMessage`)
1871
>
// observes the abort and unwinds. Each provisional record's
1872
>
// AbortController is wired into Options.abortController at
1873
>
// materialize time, so aborting here flips the same signal the
1874
>
// SDK is racing on.
1875
>
//
1876
>
// Then drain the materialized sessions through the existing
1877
>
// per-session {@link _disposeSequencer} routing — that path
1878
>
// inherits Phase 6's real async teardown (`Query.interrupt()`,
1879
>
// in-flight metadata writes) once those land.
1880
>
//
1881
>
// The promise is memoized so concurrent callers share a single
1882
>
// drain pass — see `_shutdownPromise` JSDoc.
1883
>
// NOTE: declared sync (returns Promise<void>) rather than async
1884
>
// so that re-entrant calls return the cached promise *identity*,
1885
>
// not a fresh outer-async wrapper around it.
1886
>
return this._shutdownPromise ??= (async () => {
1887
>
for (const entry of this._sessions.values()) {
1888
// Provisional chats (a default or peer whose first send's
1889
// materialize is in-flight) race on their own abort controller —