( initialPayload: Record<string, unknown>, context: StreamingContext, execContext: ExecutionContext, options: CopilotLifecycleOptions, initialRoute: string )
| 531 | // --------------------------------------------------------------------------- |
| 532 | |
| 533 | async function runCheckpointLoop( |
| 534 | initialPayload: Record<string, unknown>, |
| 535 | context: StreamingContext, |
| 536 | execContext: ExecutionContext, |
| 537 | options: CopilotLifecycleOptions, |
| 538 | initialRoute: string |
| 539 | ): Promise<void> { |
| 540 | let route = initialRoute |
| 541 | let payload: Record<string, unknown> = initialPayload |
| 542 | let resumeAttempt = 0 |
| 543 | const callerOnEvent = options.onEvent |
| 544 | const mothershipBaseURL = await getMothershipBaseURL({ userId: options.userId }) |
| 545 | const lifecycleWorkspaceId = nonBlankString(options.workspaceId) |
| 546 | |
| 547 | // Go's auth middleware re-validates every Sim -> Go request by reading |
| 548 | // workspaceId from the JSON body and forwarding it to Sim's validate route, |
| 549 | // where it is required for the per-member usage gate. Normalize the initial |
| 550 | // leg from the lifecycle option so callers that only set the option (not the |
| 551 | // raw payload) still send it on the first request. |
| 552 | if (lifecycleWorkspaceId && !nonBlankString(payload.workspaceId)) { |
| 553 | payload = { ...payload, workspaceId: lifecycleWorkspaceId } |
| 554 | } |
| 555 | |
| 556 | // Enterprise BYOK eligibility hint: set once on the initial mothership request |
| 557 | // so Go only attempts a BYOK lookup for entitled workspaces. This is only a |
| 558 | // gate — Go re-confirms entitlement authoritatively before using any key. |
| 559 | payload = await withByokEligibilityHint(payload, route, lifecycleWorkspaceId) |
| 560 | |
| 561 | for (;;) { |
| 562 | context.streamComplete = false |
| 563 | const isResume = route === '/api/tools/resume' |
| 564 | |
| 565 | if (isResume && isAborted(options, context)) { |
| 566 | cancelPendingTools(context) |
| 567 | context.awaitingAsyncContinuation = undefined |
| 568 | break |
| 569 | } |
| 570 | |
| 571 | const loopOptions = { |
| 572 | ...options, |
| 573 | onEvent: async (event: StreamEvent) => { |
| 574 | if ( |
| 575 | event.type === MothershipStreamV1EventType.run && |
| 576 | event.payload.kind === MothershipStreamV1RunKind.checkpoint_pause && |
| 577 | options.runId |
| 578 | ) { |
| 579 | try { |
| 580 | await updateRunStatus(options.runId, 'paused_waiting_for_tool') |
| 581 | } catch (error) { |
| 582 | logger.warn('Failed to mark run as paused_waiting_for_tool', { |
| 583 | runId: options.runId, |
| 584 | error: toError(error).message, |
| 585 | }) |
| 586 | } |
| 587 | } |
| 588 | await callerOnEvent?.(event) |
| 589 | }, |
| 590 | } |
no test coverage detected