Assistant node, and the Control tab as one conversation (openpanel V5)
run_turn takes its tools, system prompt and tool caller; the chat passes the MCP tools as before. The assistant node offers one tool per wired target, reads its other inputs as context, streams its reply a sentence at a time, warms the provider on `listening` and says so when the provider is not there. Completions share the per-server HTTP client. wren replies when nothing reads `unhandled`, stt shows a note when nothing was heard. /ai/control lists one conversation per entry node with the messages to watch.
This commit is contained in:
@@ -34,9 +34,9 @@ export const aiStatusQueryOptions = () =>
|
||||
})
|
||||
|
||||
/**
|
||||
* The wren nodes the Control tab can talk to. Under the flows prefix: the
|
||||
* socket invalidates it on every rebuild, so a node published anywhere shows
|
||||
* up without a reload.
|
||||
* The conversations the Control tab can hold, one per wren or assistant node a
|
||||
* command reaches first. Under the flows prefix: the socket invalidates it on
|
||||
* every rebuild, so a node published anywhere shows up without a reload.
|
||||
*/
|
||||
export const controlNodesQueryOptions = () =>
|
||||
queryOptions({
|
||||
@@ -45,8 +45,8 @@ export const controlNodesQueryOptions = () =>
|
||||
})
|
||||
|
||||
/**
|
||||
* What the panel is for: building flows with the assistant, or commanding a
|
||||
* wren node in one. A tab is there when there is something behind it, and the
|
||||
* What the panel is for: building flows with the assistant, or commanding the
|
||||
* wren and assistant nodes in one. A tab is there when there is something behind it, and the
|
||||
* strip only draws once there is a choice to make.
|
||||
*/
|
||||
const TABS: readonly (readonly [ChatTab, string])[] = [
|
||||
@@ -103,7 +103,7 @@ function fromTranscript(transcript: ChatItem[]): Item[] {
|
||||
}
|
||||
|
||||
/**
|
||||
* The way into the Control tab from Home, there only while a wren node is.
|
||||
* The way into the Control tab from Home, there only while a conversation is.
|
||||
* Shaped like the sidebar trigger, which it mirrors on a phone.
|
||||
*/
|
||||
export function ControlTrigger({ className }: { className?: string }) {
|
||||
@@ -371,7 +371,7 @@ export function ChatPanel() {
|
||||
{shown.length === 0 && !waiting ? (
|
||||
<p className="py-8 text-center text-sm text-muted-foreground">
|
||||
{controlling
|
||||
? "Type a command, like turn on the lights in the kitchen. What it did comes back here."
|
||||
? "Type a command, like turn on the kitchen light. What was said to the flow and what it did show up here."
|
||||
: "Describe a flow to build, a change to make, or ask what a failure means. Drafts land in the editor for you to publish."}
|
||||
</p>
|
||||
) : null}
|
||||
@@ -407,6 +407,18 @@ function Message({ item }: { item: Item }) {
|
||||
</Suspense>
|
||||
</div>
|
||||
)
|
||||
case "heard":
|
||||
return (
|
||||
<div className="max-w-[85%] self-end whitespace-pre-wrap break-words rounded-lg bg-muted px-3 py-1.5 text-sm text-muted-foreground">
|
||||
{item.text}
|
||||
</div>
|
||||
)
|
||||
case "reply":
|
||||
return (
|
||||
<div className="min-w-0 max-w-full self-start whitespace-pre-wrap break-words px-1 text-sm">
|
||||
{item.text}
|
||||
</div>
|
||||
)
|
||||
case "error":
|
||||
return <div className="px-1 text-xs text-destructive">{item.text}</div>
|
||||
case "actions":
|
||||
@@ -431,7 +443,7 @@ function Message({ item }: { item: Item }) {
|
||||
}
|
||||
}
|
||||
|
||||
/** A wren node's answer: each call, where it went, and whether it was applied. */
|
||||
/** What a node set: each call, where it went, and whether it was applied. */
|
||||
function Actions({ actions }: { actions: Action[] }) {
|
||||
if (actions.length === 0) {
|
||||
return (
|
||||
@@ -462,9 +474,11 @@ function Actions({ actions }: { actions: Action[] }) {
|
||||
: " (nothing wired for it)"}
|
||||
</div>
|
||||
))}
|
||||
<div className="text-muted-foreground">
|
||||
confidence {actions[0].confidence.toFixed(2)}
|
||||
</div>
|
||||
{typeof actions[0].confidence === "number" ? (
|
||||
<div className="text-muted-foreground">
|
||||
confidence {actions[0].confidence.toFixed(2)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user