Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion docs/api_to_audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ protocol`'s `assembler`, `conformance`, and `testing` subpaths.
(`turnId`, `itemId`, `id`, `parentToolCallId`) and drops
`providerCheckpointId`. Confirm the defaults against a third-party
bridge's goldens before fixing them.
3. **Surface size.** 33 value exports plus 43 types. The JSON-RPC harness
3. **Surface size.** 33 value exports plus 57 types. The JSON-RPC harness
duplicates a little of the bridge kit's envelope parsing; fold or keep
deliberately.
4. **Replay profile shape.** `ReplayProviderProfile` is the three seams the
Expand All @@ -676,6 +676,21 @@ protocol`'s `assembler`, `conformance`, and `testing` subpaths.
recording. It is a textual substitution of a unique temp path; confirm
no bridge emits that path in a form the substitution misses (URL-encoded,
JSON-escaped backslashes on Windows).
7. **The canonical event vocabulary by name.** The kit exports `ThreadEvent`,
`ThreadEventItem`, `ThreadEventItemPresentation` (+ its label, icon and
tint parts) and the named item kinds (`ThreadEventDelegationItem`,
`ThreadEventExtensionItem`, `ThreadEventFileReadItem`,
`ThreadEventSearchItem`, `ThreadEventPlanStepsItem`,
`ThreadEventWebSearchItem`, `ThreadEventWebFetchItem`,
`ThreadEventBackgroundTaskItem`) as types, re-exported from `@bb/domain`
and inlined into the bundled declarations. Before this a plugin test named
the event type as `ReturnType<BridgeDeltaEventCollector["assembleMessage"]>[number]`.
They are types only: a bridge never constructs an event (the assembler
does), so no `experimental_` value ships with them. Audit: the persisted
vocabulary now has a second public home beside `ProviderInfo` on the root
entry; a breaking change to an item shape is a breaking change to the kit.
Decide whether the kit should pin a grammar version in its exports (the
assembler already names `ASSEMBLER_GRAMMAR_VERSIONS`) before stabilizing.

## `app.experimental_useProviders` (`@get-bb/plugin-sdk/app`)

Expand Down
18 changes: 6 additions & 12 deletions examples/plugins/echo-provider/provider-bridge.stream.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type {
BridgeJsonRpcObject,
BridgeJsonRpcOutputMessage,
BridgeJsonRpcTestHarness,
ThreadEvent,
} from "@get-bb/plugin-sdk/provider-bridge/testing";

import { handleLine } from "./src/provider-bridge.js";
Expand All @@ -45,16 +46,9 @@ import {
ECHO_STAMP_TOOL_PRESENTATION,
} from "./src/vocabulary.js";

/**
* The canonical event type, derived from the kit's collector. The kit does
* not export `ThreadEvent` by name (its vocabulary lives in bb's private
* domain package), so a plugin test names it this way.
*/
type AssembledEvent = ReturnType<
BridgeDeltaEventCollector["assembleMessage"]
>[number];
/** An item lifecycle event: what the assembler builds from `item.open`/`item.close`. */
type ItemEvent = Extract<
AssembledEvent,
ThreadEvent,
{ type: "item/started" | "item/completed" }
>;

Expand Down Expand Up @@ -160,21 +154,21 @@ function answerToolCall(
return params;
}

function assembledEvents(): AssembledEvent[] {
function assembledEvents(): ThreadEvent[] {
return harness.messages.flatMap((message) =>
collector.assembleMessage(message),
);
}

function itemEvents(events: AssembledEvent[]): ItemEvent[] {
function itemEvents(events: ThreadEvent[]): ItemEvent[] {
return events.filter(
(event): event is ItemEvent =>
event.type === "item/started" || event.type === "item/completed",
);
}

function completedItem<T extends ItemEvent["item"]["type"]>(
events: AssembledEvent[],
events: ThreadEvent[],
type: T,
): Extract<ItemEvent["item"], { type: T }> {
const event = itemEvents(events).find(
Expand Down
29 changes: 29 additions & 0 deletions packages/plugin-sdk/src/__tests__/bundled-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,33 @@ describe("bundled plugin SDK declarations", () => {
);
expect(declarations[5]).toContain("interface ExperimentalHostEntryHarness");
});

it("names the canonical event vocabulary in the provider-bridge testing kit", async () => {
// A bridge's tests assert on what the assembler built; the types they
// narrow to are re-exported from @bb/domain and must arrive inlined, not
// as an import a plugin cannot resolve.
const testing = await readFile(
new URL(
"../../bundled-types/bb-plugin-sdk-provider-bridge-testing.d.ts",
import.meta.url,
),
"utf8",
);
expect(testing).not.toMatch(/from ['"]@bb\//u);
expect(testing).not.toMatch(/import\(['"]@bb\//u);
for (const name of [
"ThreadEvent",
"ThreadEventItem",
"ThreadEventItemPresentation",
"ThreadEventDelegationItem",
"ThreadEventExtensionItem",
]) {
expect(testing).toMatch(
new RegExp(`(?:type|interface) ${name}\\b`, "u"),
);
expect(testing).toMatch(
new RegExp(`export type \\{[^}]*\\b${name}\\b[^}]*\\}`, "u"),
);
}
});
});
23 changes: 23 additions & 0 deletions packages/plugin-sdk/src/provider-bridge-testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,26 @@ export type {
BridgeRecordingDirection,
BridgeRecordingEntry,
} from "@bb/provider-bridge-protocol/bridge-kit";

// The canonical event vocabulary, by name. A bridge never constructs these
// (the assembler does), but a bridge's tests assert on what the assembler
// built — `ThreadEvent` is what every collector, replay and parity function
// here returns, and the item and presentation types are what an assertion
// narrows to. Re-exported from bb's domain package and inlined into the
// published declarations, like `PromptInput` on the root entry.
export type {
ThreadEvent,
ThreadEventBackgroundTaskItem,
ThreadEventDelegationItem,
ThreadEventExtensionItem,
ThreadEventFileReadItem,
ThreadEventItem,
ThreadEventItemPresentation,
ThreadEventItemPresentationIcon,
ThreadEventItemPresentationLabel,
ThreadEventItemPresentationTint,
ThreadEventPlanStepsItem,
ThreadEventSearchItem,
ThreadEventWebFetchItem,
ThreadEventWebSearchItem,
} from "@bb/domain";
Loading