-
Notifications
You must be signed in to change notification settings - Fork 1
chore(poc): explore intents #833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
653293c
a82a9e6
76ea9f2
14903fb
26ddfc9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import type { ElementDefinition } from "../types/remote-dom.js"; | ||
| import type { ElementDefinition, Intent } from "../types/remote-dom.js"; | ||
|
|
||
| export interface ButtonElementArgs { | ||
| label: string; | ||
|
|
@@ -8,6 +8,8 @@ export interface ButtonElementArgs { | |
| isDisabled?: boolean; | ||
| type?: "button" | "submit" | "reset"; | ||
| ariaLabel?: string; | ||
| /** Optional intent to emit when button is pressed */ | ||
| intent?: Intent; | ||
|
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -23,6 +25,7 @@ export function buildButtonElement(args: ButtonElementArgs): ElementDefinition { | |
| isDisabled = false, | ||
| type = "button", | ||
| ariaLabel, | ||
| intent, | ||
| } = args; | ||
|
|
||
| return { | ||
|
|
@@ -37,5 +40,6 @@ export function buildButtonElement(args: ButtonElementArgs): ElementDefinition { | |
| "aria-label": ariaLabel, | ||
| }, | ||
| children: [label], | ||
| events: intent ? { onPress: intent } : undefined, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -288,7 +288,7 @@ function registerTools(server: McpServer) { | |
| { | ||
| title: "Create Product Card", | ||
| description: | ||
| "Creates a product card UI component with name, price, description, image, and stock status using Nimbus design system components.", | ||
| "Creates a product card UI component with name, price, description, image, stock status, and an action button.", | ||
| inputSchema: z.object({ | ||
| productId: z | ||
| .string() | ||
|
|
@@ -310,6 +310,32 @@ function registerTools(server: McpServer) { | |
| .boolean() | ||
| .optional() | ||
| .describe("Whether the product is in stock (default: true)"), | ||
| buttonLabel: z | ||
| .string() | ||
| .describe( | ||
| "Label text for the action button. Choose based on the intent type and user context." | ||
| ), | ||
| buttonIntent: z | ||
| .object({ | ||
| type: z | ||
| .string() | ||
| .describe( | ||
| "Intent type identifier in underscore_case. Choose based on what makes sense for the user's query context." | ||
| ), | ||
| description: z | ||
| .string() | ||
| .describe( | ||
| "Human-readable description of what the user wants to do when clicking this button. Consider the current conversation context and what logical next step." | ||
| ), | ||
| payload: z | ||
| .record(z.any()) | ||
| .describe( | ||
| "Structured data payload for this intent. Include all relevant entity information." | ||
| ), | ||
| }) | ||
| .describe( | ||
| "Intent configuration for the product card's action button. You decide what this button should do based on the user's query context and next logical steps." | ||
| ), | ||
|
Comment on lines
+318
to
+343
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ByronDWall Here, the agent has complete control over the type of the intent, description, and payload. This has a few benefits:
This also has a few drawbacks:
As with most things, we can use the best of both worlds. With this strategy, we can offer a dynamic avenue for agent-steered suggestion. For templates that require a high level of determinism, we can create hardcoded intents with stricter data boundaries. |
||
| }), | ||
| }, | ||
| async (args) => { | ||
|
|
@@ -650,7 +676,7 @@ function registerTools(server: McpServer) { | |
| { | ||
| title: "Create Button", | ||
| description: | ||
| "Creates a button UI component using Nimbus design system. Supports HTML form submission types.", | ||
| "Creates a button UI component using Nimbus design system. Supports HTML form submission types and optional intent emission for interactive workflows.", | ||
| inputSchema: z.object({ | ||
| label: z.string().describe("Button label text"), | ||
| variant: z | ||
|
|
@@ -678,6 +704,28 @@ function registerTools(server: McpServer) { | |
| .describe( | ||
| "Accessible label for the button (overrides visible label for screen readers)" | ||
| ), | ||
| intent: z | ||
| .object({ | ||
| type: z | ||
| .string() | ||
| .describe( | ||
| "Intent type identifier in underscore_case. Choose a name that clearly describes the user's desired action." | ||
| ), | ||
| description: z | ||
| .string() | ||
| .describe( | ||
| "Human-readable description of what the user wants to do when clicking this button. Write as if the user is speaking. Be specific and include relevant context from the current interaction." | ||
| ), | ||
| payload: z | ||
| .record(z.any()) | ||
| .describe( | ||
| "Structured data payload containing relevant information for the agent to act on the intent. Include IDs, names, current state, or any other data the agent might need to fulfill the user's request." | ||
| ), | ||
| }) | ||
| .optional() | ||
| .describe( | ||
| "Optional intent to emit when button is pressed. When provided, clicking the button sends this intent to the agent, allowing for dynamic, context-aware interactions. Use this for buttons that should trigger the agent to take further action." | ||
| ), | ||
| }), | ||
| }, | ||
| async (args) => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,12 @@ export interface ProductCardArgs { | |
| description?: string; | ||
| imageUrl?: string; | ||
| inStock?: boolean; | ||
| buttonLabel: string; | ||
| buttonIntent: { | ||
| type: string; | ||
| description: string; | ||
| payload: Record<string, unknown>; | ||
| }; | ||
| } | ||
|
|
||
| export function createProductCard(args: ProductCardArgs) { | ||
|
|
@@ -28,6 +34,8 @@ export function createProductCard(args: ProductCardArgs) { | |
| description = "", | ||
| imageUrl, | ||
| inStock = true, | ||
| buttonLabel, | ||
| buttonIntent, | ||
| } = args; | ||
|
|
||
| // ✅ Build structured product card using element builders | ||
|
|
@@ -75,12 +83,12 @@ export function createProductCard(args: ProductCardArgs) { | |
| content: description, | ||
| }), | ||
| buildButtonElement({ | ||
| label: "Add to Cart", | ||
| variant: "solid", | ||
| label: buttonLabel, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Along with the agent steering the intent, the agent also chooses the button text |
||
| variant: "outline", | ||
| colorPalette: "primary", | ||
| width: "full", | ||
| isDisabled: !inStock, | ||
| type: "button", | ||
| intent: buttonIntent, | ||
| }), | ||
| ], | ||
| }); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have to show a message to the user. It's just here for DX