From 3bb3caa6500971a207caa81caeef1fcc2761e6a8 Mon Sep 17 00:00:00 2001 From: JAE Date: Fri, 27 Mar 2026 07:31:07 +0000 Subject: [PATCH] fix: replace broken agent.on() with subscribe() API, add favicon, fix page title - agent.on() does not exist - replaced all 3 calls with single agent.subscribe() handler - Maps AgentEvent types: agent_start/end, turn_start/end, tool_execution_start, message_start/end - Cost tracking now reads usage from message_end event message.usage field - Added favicon.ico and apple-touch-icon.png from mascot - Fixed page title from Pi Web UI to Agent JAE --- packages/web-ui/example/index.html | 6 +- .../example/public/apple-touch-icon.png | Bin 0 -> 32185 bytes packages/web-ui/example/public/favicon.ico | Bin 0 -> 2878 bytes packages/web-ui/example/src/main.ts | 112 ++++++++++-------- 4 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 packages/web-ui/example/public/apple-touch-icon.png create mode 100644 packages/web-ui/example/public/favicon.ico diff --git a/packages/web-ui/example/index.html b/packages/web-ui/example/index.html index e462448..66edc66 100644 --- a/packages/web-ui/example/index.html +++ b/packages/web-ui/example/index.html @@ -1,10 +1,12 @@ + + - Pi Web UI - Example - + Agent JAE +
diff --git a/packages/web-ui/example/public/apple-touch-icon.png b/packages/web-ui/example/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..11bd06ca4a634f72d679f8b27900c959a7f21cfd GIT binary patch literal 32185 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 =6$ox+Tn&IsbHWgXCAJ2 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 AVgLXD literal 0 HcmV?d00001 diff --git a/packages/web-ui/example/src/main.ts b/packages/web-ui/example/src/main.ts index 4d3af13..d330e2e 100644 --- a/packages/web-ui/example/src/main.ts +++ b/packages/web-ui/example/src/main.ts @@ -258,22 +258,38 @@ async function createAgent(initialState?: AgentState) { currentModel = model.modelId || "llama-3.3-70b"; currentProvider = model.provider || "venice"; - // Listen for agent messages to track state - agent.on("message", (msg: AgentMessage) => { - if (!hasMessages && msg.role === "assistant") { - hasMessages = true; - renderApp(); - } - // Track tool usage for mood and auto-open panels - if (msg.role === "assistant" && msg.toolCalls) { - for (const tc of msg.toolCalls) { - if (tc.name === "browser" || tc.name === "web_fetch" || tc.name === "navigate") { + // Subscribe to agent events for UI state tracking + agent.subscribe((event) => { + const typing = document.querySelector("jae-typing-indicator") as JaeTypingIndicator; + const mood = document.querySelector("jae-mood-indicator") as JaeMoodIndicator; + + switch (event.type) { + case "agent_start": + if (typing) typing.show("high"); + break; + + case "agent_end": + if (typing) typing.hide(); + break; + + case "turn_start": + if (typing) typing.show("high"); + break; + + case "turn_end": + if (typing) typing.hide(); + break; + + case "tool_execution_start": + if (typing) typing.show("medium"); + // Auto-open panels based on tool usage + if (event.toolName === "browser" || event.toolName === "web_fetch" || event.toolName === "navigate") { if (rightPanel !== "browser") { rightPanel = "browser"; renderApp(); } } - if (tc.name === "bash") { + if (event.toolName === "bash") { if (rightPanel !== "terminal") { rightPanel = "terminal"; renderApp(); @@ -283,46 +299,46 @@ async function createAgent(initialState?: AgentState) { }); } } - } - } - // Auto-learn from user messages - if (msg.role === "user" && typeof msg.content === "string") { - processMessageForMemory("user", msg.content); - } - // Update mood based on content - const mood = document.querySelector("jae-mood-indicator") as JaeMoodIndicator; - if (mood && msg.role === "assistant" && typeof msg.content === "string") { - const text = msg.content.toLowerCase(); - if (text.includes("error") || text.includes("failed") || text.includes("cannot")) { - mood.setMood("frustrated"); - } else if (text.includes("!") || text.includes("great") || text.includes("success") || text.includes("done")) { - mood.setMood("excited"); - } else if (text.includes("warning") || text.includes("careful") || text.includes("caution")) { - mood.setMood("warning"); - } else { - mood.setMood("focused"); - } - } - }); + break; - agent.on("stateChange", (state: string) => { - const typing = document.querySelector("jae-typing-indicator") as JaeTypingIndicator; - if (typing) { - if (state === "thinking" || state === "running") { - typing.show("high"); - } else if (state === "tool_calling") { - typing.show("medium"); - } else { - typing.hide(); + case "message_start": { + const msg = event.message; + if (!hasMessages && msg.role === "assistant") { + hasMessages = true; + renderApp(); + } + // Auto-learn from user messages + if (msg.role === "user" && typeof msg.content === "string") { + processMessageForMemory("user", msg.content); + } + break; } - } - }); - // Track cost - agent.on("usage", (usage: { inputTokens: number; outputTokens: number; totalTokens: number }) => { - const costEl = document.querySelector("jae-cost-tracker") as CostTracker; - if (costEl && usage) { - costEl.addUsage(usage.inputTokens || 0, usage.outputTokens || 0); + case "message_end": { + const msg = event.message; + // Update mood based on assistant content + if (mood && msg.role === "assistant" && typeof msg.content === "string") { + const text = msg.content.toLowerCase(); + if (text.includes("error") || text.includes("failed") || text.includes("cannot")) { + mood.setMood("frustrated"); + } else if (text.includes("!") || text.includes("great") || text.includes("success") || text.includes("done")) { + mood.setMood("excited"); + } else if (text.includes("warning") || text.includes("careful") || text.includes("caution")) { + mood.setMood("warning"); + } else { + mood.setMood("focused"); + } + } + // Track cost from usage data on the message + const usage = (msg as any).usage; + if (usage) { + const costEl = document.querySelector("jae-cost-tracker") as CostTracker; + if (costEl) { + costEl.addUsage(usage.input || 0, usage.output || 0); + } + } + break; + } } });