-
Notifications
You must be signed in to change notification settings - Fork 15
feat(appkit): reference agent-app, dev-playground chat UI, docs, and template #306
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
Merged
Merged
Changes from all commits
Commits
Show all changes
56 commits
Select commit
Hold shift + click to select a range
0213e14
feat(appkit): reference agent-app, dev-playground chat UI, docs, and …
MarioCadenas 0adf359
fix(appkit): align chat clients + template with renamed 'agents' plugin
MarioCadenas 3ab0ce6
docs(agents): folder layout on disk, migrate samples, sync API refs
MarioCadenas 88c051f
docs(appkit): regenerate typedoc API reference for folder-agents loader
MarioCadenas f1097f9
feat(dev-playground): port Smart Dashboard as /smart-dashboard route;…
MarioCadenas 12b49b6
feat(dev-playground): stage 2-4 of smart-dashboard demo
MarioCadenas e4f40c2
feat(appkit): sub-agent approval gate + save view to volume + saved v…
MarioCadenas f682e1d
fix(playground): treat missing saved-views dir as empty list, not 500
MarioCadenas b85688d
fix(appkit): forward all sub-agent events except metadata
MarioCadenas 8924883
fix(playground): use html2canvas-pro to support oklch() colors
MarioCadenas eeb5060
fix(playground): unwrap DownloadResponse when serving saved-view PNGs
MarioCadenas 6f21dbc
fix(playground): apply saved view directly from metadata on thumbnail…
MarioCadenas b3422df
docs(appkit): regenerate typedoc for tool annotations
MarioCadenas bb3796b
feat(playground): revamp smart dashboard with denser charts and actio…
MarioCadenas acade71
feat(playground): hamburger nav with shared catalog and redesigned home
MarioCadenas 9daf107
feat(playground): tiered approval card — writes vs updates vs destruc…
MarioCadenas 42d658e
fix(playground): pin agent-feed card tints to sRGB hex
MarioCadenas ce326d3
fix(playground): gate Tailwind dark: variant on the theme class
MarioCadenas a934113
fix(playground): stop streaming chat bubbles from pulsing
MarioCadenas c819b40
chore(playground): migrate dev-playground server to onPluginsReady
MarioCadenas 929b0e6
feat(template): scaffold a working starter agent
MarioCadenas 1c86186
fix(playground, template): import agents from @databricks/appkit/beta
MarioCadenas 6800f3a
docs: beta agents banner, template stability, and unified typedoc entry
MarioCadenas 62a687f
chore: remove plans scratch docs from agents stack branch
MarioCadenas 7b3d48b
chore(appkit): regenerate typedoc and sync lockfile after rebase
MarioCadenas 60ba6f1
chore(appkit): regenerate typedoc after rebase onto v5
MarioCadenas 19e572f
chore(playground): migrate dev-playground to tools(plugins) function …
MarioCadenas 62599fc
chore(appkit): regenerate typedoc after tools(plugins) migration
MarioCadenas caf04c8
chore(appkit): regenerate typedoc after dropping RegisteredPlugins
MarioCadenas cbd35ab
fix(agents): unhide manifest so plugin exports from @databricks/appki…
MarioCadenas 00e5702
chore(appkit): regenerate typedoc after runAgent docstring update
MarioCadenas fed3cc8
feat(appkit): unified tools list in markdown agent frontmatter
MarioCadenas b933498
chore: package-lock
MarioCadenas 63f8cce
fix(appkit): tool() name optional, execute returns unknown, docs accu…
MarioCadenas d82c518
fix(appkit): mcp client hardening + reload() race
MarioCadenas c557334
feat(appkit-ui): useAgentChat React hook wrapping connectSSE
MarioCadenas 17117dc
fix(template): read agents list from clientConfig, drop /api/agents/i…
MarioCadenas b67371a
refactor(playground): migrate useAgentStream to wrap useAgentChat
MarioCadenas 7bb3d1d
revert(changelog): drop manual edits, release-it owns CHANGELOG.md
MarioCadenas c6c670e
refactor(appkit): unify tool callbacks, migrate to effect enum, valid…
MarioCadenas 0f489ba
refactor(appkit): mcp connectAll partial failures + tool description …
MarioCadenas 64ffad3
chore: fix CI integration env + reviewer template/docs polish
MarioCadenas 82b895f
feat(template): bring back the markdown-agent demo as `planner`
MarioCadenas 7537a94
feat(template): collapse template chat to one agent backed by a sub-a…
MarioCadenas 18043af
refactor(playground): drop featured demo card from landing page
MarioCadenas 514b940
fix(playground): split SavedViewsPanel header to avoid nested button
MarioCadenas fd4dd96
fix(appkit): preserve Vertex thought_signature on tool_call round-trips
MarioCadenas c4fc7ed
fix(template): bump zod to match AppKit, guard future drift
MarioCadenas aa58ff4
chore: package-lock
MarioCadenas 90751bb
refactor(appkit): drop unused snake_case thought_signature handling
MarioCadenas 91c9166
docs(appkit): tighten agents plugin resource description for CLI
MarioCadenas 2448455
chore(appkit): address PR #306 agentic review findings
MarioCadenas d97fbf2
fix(appkit): raise default express.json body limit to 1mb
MarioCadenas 526ad84
chore(template): sync agents plugin description from manifest
MarioCadenas e1481c3
chore: fixup
MarioCadenas abe81d4
chore: fixup
MarioCadenas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
apps/dev-playground/client/src/features/smart-dashboard/components/action-toast.tsx
|
pkosiec marked this conversation as resolved.
pkosiec marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import { CheckCircle2Icon } from "lucide-react"; | ||
| import { useEffect, useState } from "react"; | ||
|
|
||
| interface ActionToastProps { | ||
| /** | ||
| * Latest dispatcher-surfaced action summary. Each new value bumps a | ||
| * render key so the toast re-animates even if the same message arrives | ||
| * twice (e.g. two identical filter calls in a row). | ||
| */ | ||
| message: string | null; | ||
| durationMs?: number; | ||
| } | ||
|
|
||
| /** | ||
| * Non-intrusive bottom-left toast that confirms every agent-driven UI | ||
| * action. Silent success was the worst failure mode before: an action | ||
| * silently not-applied looked identical to one that worked but didn't | ||
| * show its effect. | ||
| */ | ||
| export function ActionToast({ message, durationMs = 2800 }: ActionToastProps) { | ||
| const [visible, setVisible] = useState<{ key: number; text: string } | null>( | ||
| null, | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
| if (!message) return; | ||
| const key = Date.now(); | ||
| setVisible({ key, text: message }); | ||
| const t = setTimeout(() => { | ||
| setVisible((v) => (v?.key === key ? null : v)); | ||
| }, durationMs); | ||
| return () => { | ||
| clearTimeout(t); | ||
| }; | ||
| }, [message, durationMs]); | ||
|
|
||
| if (!visible) return null; | ||
|
|
||
| return ( | ||
| <div | ||
| key={visible.key} | ||
| className="fixed bottom-20 left-4 z-30 rounded-full bg-card border border-border shadow-lg px-3 py-1.5 flex items-center gap-2 animate-in fade-in slide-in-from-bottom-2 duration-200" | ||
| > | ||
| <CheckCircle2Icon className="h-3.5 w-3.5 text-green-500 shrink-0" /> | ||
| <span className="text-xs text-foreground">{visible.text}</span> | ||
| </div> | ||
| ); | ||
| } |
191 changes: 191 additions & 0 deletions
191
apps/dev-playground/client/src/features/smart-dashboard/components/actionable-card.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,191 @@ | ||
| import { | ||
| AlertTriangleIcon, | ||
| ArrowRightIcon, | ||
| CalendarIcon, | ||
| CrosshairIcon, | ||
| DollarSignIcon, | ||
| HighlighterIcon, | ||
| LightbulbIcon, | ||
| MapPinIcon, | ||
| MessageSquareIcon, | ||
| } from "lucide-react"; | ||
| import type { FeedAction } from "../lib/feed-actions"; | ||
|
|
||
| type Variant = "insight" | "anomaly"; | ||
| type Severity = "low" | "medium" | "high"; | ||
|
|
||
| interface ActionableCardProps { | ||
| variant: Variant; | ||
| severity?: Severity; | ||
| title: string; | ||
| description: string; | ||
| actions: FeedAction[]; | ||
| /** Fired for non-ask actions. Route applies them to dashboard state. */ | ||
| onAction: (action: FeedAction) => void; | ||
| /** Fired for `ask` actions. Route forwards the prompt to the chat drawer. */ | ||
| onAsk: (prompt: string) => void; | ||
| } | ||
|
|
||
| // Backgrounds are written as arbitrary 8-digit hex (e.g. `bg-[#eff6ff80]`) | ||
| // instead of Tailwind's `/N` alpha shorthand. Rationale: `bg-blue-50/50` | ||
| // compiles in Tailwind v4 to a pair — an sRGB hex fallback and a | ||
| // `@supports (color-mix)` override that re-mixes in oklab over the oklch | ||
| // palette token. Browsers that support `color-mix` (recent Chrome/Arc) take | ||
| // the oklab path; older embedded Chromiums (e.g. Cursor's built-in browser | ||
| // at the time of writing) fall through to the sRGB hex. Because oklab and | ||
| // sRGB interpolation produce visibly different tints — especially against | ||
| // the dark `--card` token — the same card ends up looking different in each | ||
| // browser. Pinning the colour to a literal hex (no `/N`, no @supports | ||
| // override) keeps all browsers on the same sRGB path and therefore the same | ||
| // visual result. | ||
| const INSIGHT_STYLES = { | ||
| border: "border-blue-200 dark:border-blue-900", | ||
| bg: "bg-[#eff6ff80] dark:bg-[#1624564d]", | ||
| icon: "text-blue-500", | ||
| }; | ||
|
|
||
| const ANOMALY_STYLES: Record< | ||
| Severity, | ||
| { border: string; bg: string; icon: string; badge: string } | ||
| > = { | ||
| low: { | ||
| border: "border-yellow-200 dark:border-yellow-900", | ||
| bg: "bg-[#fefce880] dark:bg-[#4320044d]", | ||
| icon: "text-yellow-500", | ||
| badge: | ||
| "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/50 dark:text-yellow-400", | ||
| }, | ||
| medium: { | ||
| border: "border-orange-200 dark:border-orange-900", | ||
| bg: "bg-[#fff7ed80] dark:bg-[#4413064d]", | ||
| icon: "text-orange-500", | ||
| badge: | ||
| "bg-orange-100 text-orange-700 dark:bg-orange-900/50 dark:text-orange-400", | ||
| }, | ||
| high: { | ||
| border: "border-red-200 dark:border-red-900", | ||
| bg: "bg-[#fef2f280] dark:bg-[#4608094d]", | ||
| icon: "text-red-500", | ||
| badge: "bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-400", | ||
| }, | ||
| }; | ||
|
|
||
| function iconForAction(kind: FeedAction["kind"]): React.ReactNode { | ||
| const cls = "h-3 w-3"; | ||
| switch (kind) { | ||
| case "filter_date": | ||
| return <CalendarIcon className={cls} />; | ||
| case "filter_zip": | ||
| return <MapPinIcon className={cls} />; | ||
| case "filter_fare": | ||
| return <DollarSignIcon className={cls} />; | ||
| case "highlight_period": | ||
| return <HighlighterIcon className={cls} />; | ||
| case "highlight_zone": | ||
| return <MapPinIcon className={cls} />; | ||
| case "focus_chart": | ||
| return <CrosshairIcon className={cls} />; | ||
| case "ask": | ||
| return <MessageSquareIcon className={cls} />; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Action chip for a single feed suggestion. The chip's visual weight depends | ||
| * on its kind: structural mutations (filter/highlight/focus) use the primary | ||
| * tint, `ask` uses a neutral outline so the user can tell "this opens the | ||
| * chat" from "this changes the dashboard" without reading the label. | ||
| */ | ||
| function ActionChip({ | ||
| action, | ||
| onAction, | ||
| onAsk, | ||
| }: { | ||
| action: FeedAction; | ||
| onAction: (a: FeedAction) => void; | ||
| onAsk: (prompt: string) => void; | ||
| }) { | ||
| const isAsk = action.kind === "ask"; | ||
| const isHighlight = | ||
| action.kind === "highlight_period" || action.kind === "highlight_zone"; | ||
|
|
||
| return ( | ||
| <button | ||
| type="button" | ||
| onClick={() => { | ||
| if (isAsk) onAsk(action.prompt); | ||
| else onAction(action); | ||
| }} | ||
| className={`inline-flex items-center gap-1 text-[11px] font-medium px-2 py-1 rounded-md transition-colors ${ | ||
| isAsk | ||
| ? "border border-border bg-background text-foreground/80 hover:bg-muted hover:text-foreground" | ||
| : isHighlight | ||
| ? "bg-amber-100 text-amber-800 hover:bg-amber-200 dark:bg-amber-900/40 dark:text-amber-200 dark:hover:bg-amber-900/60" | ||
| : "bg-primary/10 text-primary hover:bg-primary/20" | ||
| }`} | ||
| > | ||
| {iconForAction(action.kind)} | ||
| <span>{action.label}</span> | ||
| {isAsk && <ArrowRightIcon className="h-3 w-3 opacity-70" />} | ||
| </button> | ||
| ); | ||
| } | ||
|
|
||
| export function ActionableCard({ | ||
| variant, | ||
| severity, | ||
| title, | ||
| description, | ||
| actions, | ||
| onAction, | ||
| onAsk, | ||
| }: ActionableCardProps) { | ||
| const isAnomaly = variant === "anomaly"; | ||
| const styles = isAnomaly | ||
| ? ANOMALY_STYLES[severity ?? "low"] | ||
| : { ...INSIGHT_STYLES, badge: "" }; | ||
|
|
||
| return ( | ||
| <div className={`rounded-lg border ${styles.border} ${styles.bg} p-3`}> | ||
| <div className="flex items-start gap-2 mb-2"> | ||
| {isAnomaly ? ( | ||
| <AlertTriangleIcon | ||
| className={`h-4 w-4 ${styles.icon} mt-0.5 shrink-0`} | ||
| /> | ||
| ) : ( | ||
| <LightbulbIcon className={`h-4 w-4 ${styles.icon} mt-0.5 shrink-0`} /> | ||
| )} | ||
| <div className="min-w-0 flex-1"> | ||
| <div className="flex items-start gap-2"> | ||
| <p className="text-sm font-medium text-foreground leading-tight flex-1"> | ||
| {title} | ||
| </p> | ||
| {isAnomaly && severity && ( | ||
| <span | ||
| className={`text-[10px] font-medium px-1.5 py-0.5 rounded shrink-0 ${styles.badge}`} | ||
| > | ||
| {severity} | ||
| </span> | ||
| )} | ||
| </div> | ||
| <p className="text-xs text-muted-foreground mt-1 leading-relaxed"> | ||
| {description} | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| {actions.length > 0 && ( | ||
| <div className="flex flex-wrap gap-1.5 pl-6"> | ||
| {actions.map((action, i) => ( | ||
| <ActionChip | ||
| key={`${action.kind}-${i}-${action.label}`} | ||
| action={action} | ||
| onAction={onAction} | ||
| onAsk={onAsk} | ||
| /> | ||
| ))} | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.