scenarioAgentRun function

Future<void> scenarioAgentRun(
  1. FakeServer server,
  2. WorldSeed w,
  3. ScenarioClient client
)

04 16.5: a mention of the agent Robin starts a run; the live box follows the coalesced patches, a follow-up is delivered and absorbed, the agent replies and the run ends; the live box document is discarded at the end.

The script pauses longer than the coalescing window of the fake (GatewayTimings.runPatchCoalesce), so each patch reaches the client before the next step.

Implementation

Future<void> scenarioAgentRun(
  FakeServer server,
  WorldSeed w,
  ScenarioClient client,
) async {
  final stepId = server.world.nextId();
  final base = AgentScript.followUpRun(
    stepId,
    server.world.stamp(),
    reply: 'Here is the summary.',
  );
  final agent = server.addAgent(
    w.robin.id,
    AgentScript(base.steps, pause: server.gateway.timings.runPatchCoalesce * 3),
  );
  await client.start();
  await client.focusThread(w.releaseNotes);
  final trigger = await client.send(
    w.releaseNotes,
    'Robin, summarize the notes',
    mentionIds: [w.robin.id],
  );
  await waitFor('the run', () => agent.runIds.isNotEmpty);
  final runId = agent.runIds.single;
  await client.focusRun(runId, w.releaseNotes);
  await waitFor('the live step', () {
    final steps = client.runDocument(runId)?['steps'];
    return steps is Map && steps.containsKey(stepId);
  });
  final followup = await client.send(w.releaseNotes, 'Also mention the budget');
  String? followupState() {
    final f = client.runDocument(runId)?['followups'];
    if (f is! Map) return null;
    for (final v in f.values) {
      if (v is Map) return v['state'] as String?;
    }
    return null;
  }

  await waitFor('the absorbed follow-up', () => followupState() == 'absorbed');
  await waitFor(
    'the reply',
    () async =>
        (await client.messages(w.releaseNotes))
            .any((m) => m.authorId == w.robin.id),
  );
  await waitFor(
    'the run end',
    () async => await client.runState(runId) == 'completed',
  );
  await waitFor(
    'the discarded document',
    () => client.runDocument(runId) == null,
  );
  await waitFor(
    'trigger state done',
    () async =>
        (await _withId(client, w.releaseNotes, trigger)).single.triggerState ==
        'done',
  );
  _check(
    (await _withId(client, w.releaseNotes, followup)).single.triggerState ==
        'followup_delivered',
    'the follow-up reached the agent',
  );
  _contract(server);
}