BMO: a living desktop buddy with a Claude brain
Standalone React + Vite app where BMO lives in a little garden: - Redrawn avatar (src/avatar) with depth, cartoon controls and expressive faces; original bmo-preview avatar and scenery kept in src/bmo - Idle life: wandering, chatter, boredom, sleep, pokes, weather and time-of-day reactions - Chat via a local Node server streaming Claude replies (Haiku by default), with live scene awareness and tools to change color, outfit, sky, weather, move and perform - Side menu for API key, appearance, environment and chat log Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
// Names shared by the page and the brain server: what BMO can wear, how the
|
||||
// world can look, and what BMO can do. The page owns the actual palettes and
|
||||
// renders the scene; the server uses these lists for tool schemas and to
|
||||
// validate what the model asks for.
|
||||
|
||||
export const COLOR_NAMES = [
|
||||
"Classic",
|
||||
"Ocean",
|
||||
"Forest",
|
||||
"Ember",
|
||||
"Midnight",
|
||||
"Sky",
|
||||
"Grape",
|
||||
"Honey",
|
||||
"Bubblegum",
|
||||
] as const;
|
||||
export type ColorName = (typeof COLOR_NAMES)[number];
|
||||
|
||||
export const OUTFIT_NAMES = ["None", "Royal", "Hacker", "Inspector", "Dapper"] as const;
|
||||
export type OutfitName = (typeof OUTFIT_NAMES)[number];
|
||||
|
||||
/** What each outfit looks like, so BMO can describe itself. */
|
||||
export const OUTFIT_LOOKS: Record<OutfitName, string> = {
|
||||
None: "no accessories",
|
||||
Royal: "a gold crown and a cape",
|
||||
Hacker: "big headphones and glasses",
|
||||
Inspector: "a badge and cool sunglasses",
|
||||
Dapper: "a top hat and a bow tie",
|
||||
};
|
||||
|
||||
/** Plain-language color descriptions for the palettes in the page. */
|
||||
export const COLOR_LOOKS: Record<ColorName, string> = {
|
||||
Classic: "classic minty teal",
|
||||
Ocean: "deep ocean teal",
|
||||
Forest: "forest green",
|
||||
Ember: "dark ember red",
|
||||
Midnight: "midnight indigo",
|
||||
Sky: "slate sky blue",
|
||||
Grape: "grape purple",
|
||||
Honey: "honey gold",
|
||||
Bubblegum: "bubblegum pink",
|
||||
};
|
||||
|
||||
export const TIME_MODES = ["auto", "day", "dusk", "night"] as const;
|
||||
export type TimeModeName = (typeof TIME_MODES)[number];
|
||||
|
||||
export const WEATHER_MODES = ["auto", "none", "rain", "snow", "falling-leaves"] as const;
|
||||
export type WeatherModeName = (typeof WEATHER_MODES)[number];
|
||||
|
||||
export const SPOTS = ["left", "center", "right"] as const;
|
||||
export type Spot = (typeof SPOTS)[number];
|
||||
|
||||
export const PERFORMANCES = ["dance", "celebrate", "idea", "confused", "love", "dizzy", "look_around", "nap"] as const;
|
||||
export type Performance = (typeof PERFORMANCES)[number];
|
||||
|
||||
/** Live state the page sends with every chat message. */
|
||||
export interface SceneState {
|
||||
color: ColorName;
|
||||
outfit: OutfitName;
|
||||
timeOfDay: "day" | "dusk" | "night";
|
||||
timeMode: TimeModeName;
|
||||
weather: "none" | "rain" | "snow" | "falling-leaves";
|
||||
weatherMode: WeatherModeName;
|
||||
/** Where BMO is standing on its little stage. */
|
||||
spot: Spot;
|
||||
/** The user's local time, e.g. "9:41 PM". */
|
||||
localTime: string;
|
||||
}
|
||||
|
||||
/** An action BMO decided to take, sent from the server to the page. */
|
||||
export type BmoAction =
|
||||
| { type: "set_color"; color: ColorName }
|
||||
| { type: "set_outfit"; outfit: OutfitName }
|
||||
| { type: "set_time_of_day"; time: TimeModeName }
|
||||
| { type: "set_weather"; weather: WeatherModeName }
|
||||
| { type: "move"; to: Spot }
|
||||
| { type: "perform"; action: Performance };
|
||||
Reference in New Issue
Block a user