char-slop/berry

multipurpose self-modifiable agentic harness

git clone https://git.t4t.associates/char-slop/berry

Charlotte Somweb: keep tool elapsed time accurate across navigation86bd162

main
2.7 KiB73 linesraw
1import { assert, assertEquals } from "@std/assert";
2import { BACKGROUND_CONTEXT as context } from "@earendil-works/chord/context";
3import type { ConversationView } from "@earendil-works/pi-durable";
4import { fauxAssistantMessage, fauxToolCall } from "@earendil-works/pi-ai/providers/faux";
5import { Type } from "@earendil-works/pi-ai";
6import { defineExtension, type JsonValue } from "@berry/api";
7import { setup } from "./fixture.ts";
8
9Deno.test("joining a running tool receives its execution start independently of progress details", async () => {
10  await using harness = await setup();
11  const { berry, model, faux } = harness;
12  const entered = Promise.withResolvers<(details: JsonValue) => void>();
13  const release = Promise.withResolvers<string>();
14  await berry.install(defineExtension({
15    name: "timed",
16    initial: () => null,
17    setup(ext) {
18      ext.tool({
19        name: "wait",
20        description: "wait",
21        expose: "model",
22        parameters: Type.Object({}),
23        execute(_, ctx) {
24          entered.resolve(ctx.progress);
25          return release.promise;
26        },
27      });
28    },
29  }));
30  const tid = await berry.create({ extensions: { timed: {} }, model });
31  const conversation = (await berry.conversation(tid))!;
32  faux.setResponses([
33    fauxAssistantMessage(fauxToolCall("wait", {}, { id: "waiting" }), { stopReason: "toolUse" }),
34    fauxAssistantMessage("done"),
35  ]);
36  const before = Date.now();
37  const submission = await conversation.submit({ type: "input", content: "go" }, context);
38  try {
39    const progress = await entered.promise;
40    const feed = (await berry.watch(tid))!;
41    const slot = (view: unknown) =>
42      ((view as ConversationView).docs["pi.live"].tools as {
43        callId: string;
44        startedAt?: number;
45        details?: JsonValue;
46      }[]).find((slot) => slot.callId === "waiting")!;
47    const start = slot(feed.value).startedAt;
48    assert(typeof start === "number" && start >= before && start <= Date.now());
49    const updated = Promise.withResolvers<void>();
50    await feed.start((view) => {
51      const current = slot(view);
52      if (Array.isArray(current?.details)) {
53        assertEquals(current.startedAt, start);
54        assertEquals(current.details, ["still running"]);
55        updated.resolve();
56      }
57      return Promise.resolve();
58    });
59    try {
60      progress(["still running"]);
61      await updated.promise;
62      const rejoined = (await berry.watch(tid))!;
63      assertEquals(slot(rejoined.value).startedAt, start);
64      await rejoined.stop();
65    } finally {
66      await feed.stop();
67    }
68  } finally {
69    release.resolve("done");
70    await submission.wait(context);
71    await conversation.waitForIdle(context);
72  }
73});