MCPcopy Create free account
hub / github.com/simstudioai/sim / driveOneChildChain

Function driveOneChildChain

apps/sim/lib/copilot/request/lifecycle/run.ts:400–470  ·  view source on GitHub ↗
(
  frame: ResumeFrame,
  context: StreamingContext,
  execContext: ExecutionContext,
  options: CopilotLifecycleOptions,
  baseURL: string,
  workspaceId?: string
)

Source from the content-addressed store, hash-verified

398// null. Re-pause vs follow-on is disambiguated by checkpoint id: a re-pause keeps
399// the same child id; the join continuation is a different (orchestrator) id.
400async function driveOneChildChain(
401 frame: ResumeFrame,
402 context: StreamingContext,
403 execContext: ExecutionContext,
404 options: CopilotLifecycleOptions,
405 baseURL: string,
406 workspaceId?: string
407): Promise<AsyncContinuation | null> {
408 // ParentToolCallID is the SAME subagent's stable identity across re-pauses;
409 // the checkpoint id rotates each re-pause (the prior one is already claimed).
410 const parentToolCallId = frame.parentToolCallId
411 // Guarded (not cast): a per-subagent frame always carries its own checkpointId
412 // (isPerSubagentContinuation requires it), but a local guard keeps this driver
413 // correct on its own terms rather than trusting a caller-side invariant.
414 if (!frame.checkpointId) return null
415 let checkpointId = frame.checkpointId
416 let toolIds = frame.pendingToolIds
417
418 for (;;) {
419 if (isAborted(options, context)) return null
420
421 await waitForToolIds(context, toolIds)
422 const results = collectResultsForToolIds(context, toolIds, checkpointId)
423
424 const leg = makeResumeLegContext(context)
425 await runResumeLegWithRetry(
426 `${baseURL}/api/tools/resume`,
427 {
428 streamId: context.messageId,
429 checkpointId,
430 userId: options.userId,
431 ...(workspaceId ? { workspaceId } : {}),
432 results,
433 },
434 leg,
435 execContext,
436 options
437 )
438 mergeResumeLegOutputs(context, leg)
439
440 const cont = leg.awaitingAsyncContinuation
441 if (!cont) {
442 // The last finisher's leg, whose join continuation streamed the
443 // orchestrator to completion (done): nothing more to drive on this leg.
444 return null
445 }
446 // A NON-last finisher folds with a TERMINAL pause carrying the join id but
447 // NO pending tools and NO frames — the child's work is done and the join
448 // wakes on whichever sibling finishes last. End this leg cleanly; do NOT
449 // mistake the join id for an orchestrator follow-on and try to resume it.
450 const hasPending = (cont.pendingToolCallIds?.length ?? 0) > 0
451 const hasFrames = (cont.frames?.length ?? 0) > 0
452 if (!hasPending && !hasFrames) {
453 return null
454 }
455 // Re-pause is identified by THIS subagent's stable parentToolCallId (the
456 // checkpoint id rotates each re-pause). If present, keep driving this child
457 // with its new id + leaves.

Callers 1

driveSubagentChainsFunction · 0.85

Calls 6

isAbortedFunction · 0.85
waitForToolIdsFunction · 0.85
collectResultsForToolIdsFunction · 0.85
makeResumeLegContextFunction · 0.85
runResumeLegWithRetryFunction · 0.85
mergeResumeLegOutputsFunction · 0.85

Tested by

no test coverage detected