| ... | @@ -175,6 +175,7 @@ interface GrokSessionContext { | ... | @@ -175,6 +175,7 @@ interface GrokSessionContext { |
| 175 | currentModelId: string | undefined; | 175 | currentModelId: string | undefined; |
| 176 | currentReasoningEffort: string | undefined; | 176 | currentReasoningEffort: string | undefined; |
| 177 | stopped: boolean; | 177 | stopped: boolean; |
| | 178 | terminated: boolean; |
| 178 | /** Live monitor/shell identities and their originating turns. */ | 179 | /** Live monitor/shell identities and their originating turns. */ |
| 179 | readonly backgroundTasks: Map<string, GrokBackgroundTaskRecord>; | 180 | readonly backgroundTasks: Map<string, GrokBackgroundTaskRecord>; |
| 180 | } | 181 | } |
| ... | @@ -345,6 +346,7 @@ export function grokPromptSettlementBelongsToContext(input: { | ... | @@ -345,6 +346,7 @@ export function grokPromptSettlementBelongsToContext(input: { |
| 345 | | 346 | |
| 346 | export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapterLiveOptions) { | 347 | export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapterLiveOptions) { |
| 347 | return Effect.gen(function* () { | 348 | return Effect.gen(function* () { |
| | 349 | const ownerScope = yield* Effect.scope; |
| 348 | const boundInstanceId = options?.instanceId ?? ProviderInstanceId.make("grok"); | 350 | const boundInstanceId = options?.instanceId ?? ProviderInstanceId.make("grok"); |
| 349 | const fileSystem = yield* FileSystem.FileSystem; | 351 | const fileSystem = yield* FileSystem.FileSystem; |
| 350 | const path = yield* Path.Path; | 352 | const path = yield* Path.Path; |
| ... | @@ -922,7 +924,7 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte | ... | @@ -922,7 +924,7 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte |
| 922 | threadId: ThreadId, | 924 | threadId: ThreadId, |
| 923 | ): Effect.Effect<GrokSessionContext, ProviderAdapterSessionNotFoundError> => { | 925 | ): Effect.Effect<GrokSessionContext, ProviderAdapterSessionNotFoundError> => { |
| 924 | const ctx = sessions.get(threadId); | 926 | const ctx = sessions.get(threadId); |
| 925 | if (!ctx || ctx.stopped) { | 927 | if (!ctx || ctx.stopped || ctx.terminated) { |
| 926 | return Effect.fail( | 928 | return Effect.fail( |
| 927 | new ProviderAdapterSessionNotFoundError({ provider: PROVIDER, threadId }), | 929 | new ProviderAdapterSessionNotFoundError({ provider: PROVIDER, threadId }), |
| 928 | ); | 930 | ); |
| ... | @@ -946,7 +948,7 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte | ... | @@ -946,7 +948,7 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte |
| 946 | ...(yield* makeEventStamp()), | 948 | ...(yield* makeEventStamp()), |
| 947 | provider: PROVIDER, | 949 | provider: PROVIDER, |
| 948 | threadId: ctx.threadId, | 950 | threadId: ctx.threadId, |
| 949 | payload: { exitKind: "graceful" }, | 951 | payload: { exitKind: ctx.terminated ? "error" : "graceful" }, |
| 950 | }); | 952 | }); |
| 951 | }); | 953 | }); |
| 952 | | 954 | |
| ... | @@ -1316,12 +1318,35 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte | ... | @@ -1316,12 +1318,35 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte |
| 1316 | ? normalizeGrokReasoningEffort(requestedStartReasoningEffort) | 1318 | ? normalizeGrokReasoningEffort(requestedStartReasoningEffort) |
| 1317 | : currentStartReasoningEffort, | 1319 | : currentStartReasoningEffort, |
| 1318 | stopped: false, | 1320 | stopped: false, |
| | 1321 | terminated: false, |
| 1319 | backgroundTasks: new Map(), | 1322 | backgroundTasks: new Map(), |
| 1320 | }; | 1323 | }; |
| 1321 | | 1324 | |
| 1322 | const nf = yield* Stream.runDrain( | 1325 | const nf = yield* Stream.runDrain( |
| 1323 | Stream.mapEffect(acp.getEvents(), (event) => | 1326 | Stream.mapEffect(acp.getEvents(), (event) => |
| 1324 | Effect.gen(function* () { | 1327 | Effect.gen(function* () { |
| | 1328 | if (event._tag === "ConnectionTerminated") { |
| | 1329 | ctx.terminated = true; |
| | 1330 | yield* withThreadLock( |
| | 1331 | ctx.threadId, |
| | 1332 | Effect.gen(function* () { |
| | 1333 | if (sessions.get(ctx.threadId) !== ctx) return; |
| | 1334 | if (ctx.activeTurnId) { |
| | 1335 | yield* settlePromptInFlight( |
| | 1336 | ctx.threadId, |
| | 1337 | ctx.activeTurnId, |
| | 1338 | ctx.acpSessionId, |
| | 1339 | { |
| | 1340 | errorMessage: "Grok connection terminated.", |
| | 1341 | settleAllPrompts: true, |
| | 1342 | }, |
| | 1343 | ); |
| | 1344 | } |
| | 1345 | yield* stopSessionInternal(ctx); |
| | 1346 | }), |
| | 1347 | ).pipe(Effect.forkIn(ownerScope)); |
| | 1348 | return; |
| | 1349 | } |
| 1325 | if (event._tag === "EventStreamBarrier") { | 1350 | if (event._tag === "EventStreamBarrier") { |
| 1326 | yield* Deferred.succeed(event.acknowledge, undefined); | 1351 | yield* Deferred.succeed(event.acknowledge, undefined); |
| 1327 | return; | 1352 | return; |
| ... | @@ -2165,12 +2190,16 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte | ... | @@ -2165,12 +2190,16 @@ export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapte |
| 2165 | ); | 2190 | ); |
| 2166 | | 2191 | |
| 2167 | const listSessions: GrokAdapterShape["listSessions"] = () => | 2192 | const listSessions: GrokAdapterShape["listSessions"] = () => |
| 2168 | Effect.sync(() => Array.from(sessions.values(), (c) => ({ ...c.session }))); | 2193 | Effect.sync(() => |
| | 2194 | Array.from(sessions.values()) |
| | 2195 | .filter((c) => !c.terminated) |
| | 2196 | .map((c) => ({ ...c.session })), |
| | 2197 | ); |
| 2169 | | 2198 | |
| 2170 | const hasSession: GrokAdapterShape["hasSession"] = (threadId) => | 2199 | const hasSession: GrokAdapterShape["hasSession"] = (threadId) => |
| 2171 | Effect.sync(() => { | 2200 | Effect.sync(() => { |
| 2172 | const c = sessions.get(threadId); | 2201 | const c = sessions.get(threadId); |
| 2173 | return c !== undefined && !c.stopped; | 2202 | return c !== undefined && !c.stopped && !c.terminated; |
| 2174 | }); | 2203 | }); |
| 2175 | | 2204 | |
| 2176 | const stopAll: GrokAdapterShape["stopAll"] = () => | 2205 | const stopAll: GrokAdapterShape["stopAll"] = () => |