Skip to content

Commit

Permalink
[shared-ui] Introduce ChatController, an abstraction to manage chat s…
Browse files Browse the repository at this point in the history
…tate.

- **Sketch out `ChatController`.**
- **Plumb the icon infomation to `ChatController`.**
- **Plumb the `updating` flag.**
- **Simplify chat state data structure.**
- **Make `ChatController` update icons and titles when the underlying
graph entries are updated.**
- **docs(changeset): Introduce ChatController, an abstraction to manage
chat state.**
  • Loading branch information
dglazkov authored Jan 24, 2025
1 parent a5568fb commit 3af8f62
Show file tree
Hide file tree
Showing 14 changed files with 403 additions and 21 deletions.
8 changes: 8 additions & 0 deletions .changeset/chatty-scissors-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@breadboard-ai/shared-ui": minor
"@breadboard-ai/visual-editor": patch
"@google-labs/breadboard": patch
"@breadboard-ai/a2": patch
---

Introduce ChatController, an abstraction to manage chat state.
6 changes: 4 additions & 2 deletions packages/a2/bgl/text-workbench.bgl.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"visual": {
"x": 100,
"y": -59.999999999999886,
"collapsed": "expanded"
"collapsed": "expanded",
"outputHeight": 44
},
"title": "Text",
"logLevel": "info"
Expand All @@ -33,7 +34,8 @@
"visual": {
"x": 440,
"y": -60,
"collapsed": "expanded"
"collapsed": "expanded",
"outputHeight": 44
},
"title": "Text",
"logLevel": "info"
Expand Down
62 changes: 48 additions & 14 deletions packages/breadboard/src/inspector/graph-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Sandbox } from "@breadboard-ai/jsandbox";
import {
GraphDescriptor,
GraphIdentifier,
Expand All @@ -15,34 +16,33 @@ import {
EditableGraphOptions,
Result,
} from "../editor/types.js";
import { createLoader } from "../loader/index.js";
import { getGraphUrl, getGraphUrlComponents } from "../loader/loader.js";
import {
GraphLoader,
GraphLoaderContext,
GraphLoaderResult,
} from "../loader/types.js";
import { Kit, NodeHandlerContext, NodeHandlerMetadata } from "../types.js";
import { graphUrlLike } from "../utils/graph-url-like.js";
import { hash } from "../utils/hash.js";
import { SnapshotUpdater } from "../utils/snapshot-updater.js";
import { UpdateEvent } from "./graph/event.js";
import { createBuiltInKit } from "./graph/kits.js";
import { MutableGraphImpl } from "./graph/mutable-graph.js";
import {
GraphStoreEntry,
AddResult,
GraphStoreArgs,
GraphStoreEntry,
GraphStoreEventTarget,
InspectableGraph,
InspectableGraphOptions,
MainGraphIdentifier,
MutableGraph,
MutableGraphStore,
AddResult,
} from "./types.js";
import { hash } from "../utils/hash.js";
import { Kit, NodeHandlerContext, NodeHandlerMetadata } from "../types.js";
import { Sandbox } from "@breadboard-ai/jsandbox";
import { createLoader } from "../loader/index.js";
import { SnapshotUpdater } from "../utils/snapshot-updater.js";
import { UpdateEvent } from "./graph/event.js";
import { createBuiltInKit } from "./graph/kits.js";
import { graphUrlLike } from "../utils/graph-url-like.js";
import { getGraphUrl, getGraphUrlComponents } from "../loader/loader.js";

export { GraphStore, makeTerribleOptions, contextFromMutableGraph };
export { contextFromMutableGraph, GraphStore, makeTerribleOptions };

function contextFromMutableGraph(mutable: MutableGraph): NodeHandlerContext {
const store = mutable.store;
Expand Down Expand Up @@ -93,12 +93,42 @@ class GraphStore
this.#legacyKits = this.#populateLegacyKits(args.kits);
}

getEntryByDescriptor(
descriptor: GraphDescriptor,
graphId: GraphIdentifier
): GraphStoreEntry | undefined {
const getting = this.getOrAdd(descriptor, false);
if (!getting.success) {
return;
}
const mutable = getting.result;
const mainGraphMetadata = filterEmptyValues({
title: descriptor.title,
description: descriptor.description,
icon: descriptor.metadata?.icon,
url: descriptor.url,
tags: descriptor.metadata?.tags,
help: descriptor.metadata?.help,
id: mutable.id,
});
let metadata;
if (graphId) {
metadata = entryFromExport(mutable, `#${graphId}`, mutable.id);
} else {
metadata = mainGraphMetadata;
}
return {
updating: false,
mainGraph: mainGraphMetadata,
...metadata,
};
}

graphs(): GraphStoreEntry[] {
const graphs = [...this.#mutables.entries()]
.flatMap(([mainGraphId, snapshot]) => {
const mutable = snapshot.current();
const descriptor = mutable.graph;
// TODO: Support exports and main module
const mainGraphMetadata = filterEmptyValues({
title: descriptor.title,
description: descriptor.description,
Expand All @@ -114,11 +144,13 @@ class GraphStore
const metadata = entryFromExport(mutable, e, mainGraphId);
exports.push({
mainGraph: mainGraphMetadata,
updating: false,
...metadata,
});
}
} else {
exports.push({
updating: false,
mainGraph:
(mutable.legacyKitMetadata as KitDescriptor & {
id: MainGraphIdentifier;
Expand Down Expand Up @@ -452,7 +484,7 @@ function entryFromExport(
mutable: MutableGraph,
id: string,
mainGraphId: MainGraphIdentifier
): NodeHandlerMetadata | null {
): (NodeHandlerMetadata & { updating: boolean }) | null {
const graph = mutable.graph;
const url = `${graph.url}${id}`;
const { current, updating } = mutable.describe.getByType(url);
Expand All @@ -473,6 +505,7 @@ function entryFromExport(
tags: ["component"],
help: help ?? module.metadata?.help,
id: mainGraphId,
updating,
});
} else {
const graphId = id.slice(1);
Expand All @@ -486,6 +519,7 @@ function entryFromExport(
tags: ["component"],
help: help ?? descriptor.metadata?.help,
id: mainGraphId,
updating,
});
}
}
Expand Down
11 changes: 10 additions & 1 deletion packages/breadboard/src/inspector/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ export type MainGraphIdentifier = UUID;

export type GraphStoreEntry = NodeHandlerMetadata & {
mainGraph: NodeHandlerMetadata & { id: MainGraphIdentifier };
updating: boolean;
};

export type GraphStoreArgs = Required<InspectableGraphOptions>;
Expand Down Expand Up @@ -747,7 +748,15 @@ export type MutableGraphStore = TypedEventTargetType<GraphsStoreEventMap> &
readonly loader: GraphLoader;

graphs(): GraphStoreEntry[];

/**
* This is a hacky API. Ideally, there's a list of graph entries
* that is queriable and `graphs()` returns it, and this method
* goes onto it.
*/
getEntryByDescriptor(
descriptor: GraphDescriptor,
graphId: GraphIdentifier
): GraphStoreEntry | undefined;
/**
* Registers a Kit with the GraphStore.
* Currently, only Kits that contain Graph URL-like types
Expand Down
8 changes: 8 additions & 0 deletions packages/shared-ui/src/elements/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,20 @@ import { UserInput } from "../elements.js";
import { markdown } from "../../directives/markdown.js";
import { SettingsStore } from "../../data/settings-store.js";
import { formatError } from "../../utils/format-error.js";
import { ChatState } from "../../state/types.js";

@customElement("bb-chat")
export class Chat extends LitElement {
@property({ reflect: false })
graph: GraphDescriptor | null = null;

/**
* Provides an up-to-date model of the chat state.
* See `ChatController` for the implementation that manages the model.
*/
@property()
state: ChatState | null = null;

@property({ reflect: false })
run: InspectableRun | null = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import {
} from "../../utils/behaviors.js";
import { cache, CacheDirective } from "lit/directives/cache.js";
import { DirectiveResult } from "lit/directive.js";
import { ChatController } from "../../state/chat-controller.js";

const SIDE_NAV_ITEM_KEY = "bb-ui-side-nav-item";
const POPOUT_STATE = "bb-ui-popout-state";
Expand Down Expand Up @@ -164,6 +165,9 @@ export class UI extends LitElement {
@property()
showBoardReferenceMarkers = false;

@property()
chatController: ChatController | null = null;

@state()
debugEvent: InspectableRunEvent | null = null;

Expand Down Expand Up @@ -676,6 +680,7 @@ export class UI extends LitElement {
class=${classMap({ collapsed: this.debugEvent !== null })}
.run=${run}
.events=${events}
.state=${this.chatController?.state()}
.eventPosition=${eventPosition}
.inputsFromLastRun=${inputsFromLastRun}
.showExtendedInfo=${true}
Expand Down
1 change: 1 addition & 0 deletions packages/shared-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export * as Plugins from "./plugins/plugins.js";
export * as Types from "./types/types.js";
export * as Utils from "./utils/utils.js";
export * as Strings from "./strings/helper.js";
export * as State from "./state/index.js";
Loading

0 comments on commit 3af8f62

Please sign in to comment.