From 7aea53543c55462930e6cfe520b87d018a5c4c50 Mon Sep 17 00:00:00 2001 From: ssdeanx Date: Thu, 15 Jan 2026 11:11:50 -0500 Subject: [PATCH] feat: update README and improve ESLint configuration - Updated the Chat UI-Backend Architecture section in README.md to reflect new message rendering logic. - Enhanced the ESLint configuration by refining ignored files and updating TypeScript ESLint plugin usage. - Changed AccordionTriggerProps and AccordionContentProps from interface to type for consistency in ui/accordion.tsx. - Updated TabsListProps from interface to type for consistency in ui/tabs.tsx. --- README.md | 293 +++++++++++++++++++++++++++++++++-------------- eslint.config.js | 93 ++++++++------- ui/accordion.tsx | 4 +- ui/tabs.tsx | 2 +- 4 files changed, 254 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index 4178e4f..46b0790 100644 --- a/README.md +++ b/README.md @@ -143,105 +143,222 @@ graph TB style UI stroke:#58a6ff ``` -## 🔍 **Workflow Architecture** +## 🔍 **Chat UI-Backend Architecture** ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#58a6ff', 'primaryTextColor': '#c9d1d9', 'primaryBorderColor': '#30363d', 'lineColor': '#58a6ff', 'sectionBkgColor': '#161b22', 'altSectionBkgColor': '#0d1117', 'sectionTextColor': '#c9d1d9', 'gridColor': '#30363d', 'tertiaryColor': '#161b22' }}}%% sequenceDiagram - participant User - participant Workflow - participant Writer - participant Agent/Tool - participant Logger - - User->>Workflow: Execute workflow step - Workflow->>Logger: logStepStart() - - Workflow->>Writer: custom({ type: "data-tool-progress" }) - Note over Writer: status: "in-progress"
message: "Starting..."
stage: "step-id" - Writer-->>User: Stream progress update - - Workflow->>Agent/Tool: Execute operation - Agent/Tool->>Writer: custom({ type: "data-tool-progress" }) - Note over Writer: Tool emits progress
with same format - Writer-->>User: Stream tool progress - - Agent/Tool-->>Workflow: Return result - - Workflow->>Writer: custom({ type: "data-tool-progress" }) - Note over Writer: status: "done"
message: "Completed..."
stage: "step-id" - Writer-->>User: Stream completion - - Workflow->>Logger: logStepEnd() - Workflow-->>User: Return final output - - alt Error occurs - Agent/Tool->>Writer: custom({ type: "data-tool-progress" }) - Note over Writer: status: "error"
message: error details - Writer-->>User: Stream error - Workflow->>Logger: logError() + participant UI as ChatUI + participant Msg as MessageItem + participant TG as TypeGuards + participant ADS as AgentDataSection + participant WDS as WorkflowDataSection + participant NDS as NetworkDataSection + participant AT as AgentTool + + UI->>Msg: render(message) + Msg->>Msg: compute dataParts via useMemo + + loop for each part in dataParts + Msg->>TG: isAgentDataPart(part) + alt part is AgentDataPart + Msg->>ADS: render part + ADS-->>Msg: Agent execution collapsible + else not AgentDataPart + Msg->>TG: isWorkflowDataPart(part) + alt part is WorkflowDataPart + Msg->>WDS: render part + WDS-->>Msg: Workflow execution collapsible + else not WorkflowDataPart + Msg->>TG: isNetworkDataPart(part) + alt part is NetworkDataPart + Msg->>NDS: render part + NDS-->>Msg: Network execution collapsible + else other data-tool-* part + alt part.type startsWith data-tool- + Msg->>AT: render custom tool UI + AT-->>Msg: Tool-specific panel + else generic data-* part + Msg-->>Msg: render generic Collapsible with JSON + end + end + end + end end + + Msg-->>UI: message body with nested sections ``` ## 📊 **System Flowchart** ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#58a6ff', 'primaryTextColor': '#c9d1d9', 'primaryBorderColor': '#30363d', 'lineColor': '#58a6ff', 'sectionBkgColor': '#161b22', 'altSectionBkgColor': '#0d1117', 'sectionTextColor': '#c9d1d9', 'gridColor': '#30363d', 'tertiaryColor': '#161b22' }}}%% -flowchart TD - A[app/chat] -->|components| B[chat-header.tsx] - A -->|components| C[chat-messages.tsx] - A -->|components| D[chat-input.tsx] - A -->|config| E[agents.ts] - A -->|providers| F[chat-context.tsx] - - G[app/networks] -->|components| H[network-header.tsx] - G -->|components| I[network-messages.tsx] - G -->|config| J[networks.ts] - G -->|providers| K[network-context.tsx] - - L[app/workflows] -->|components| M[workflow-canvas.tsx] - L -->|components| N[workflow-header.tsx] - L -->|config| O[workflows.ts] - L -->|providers| P[workflow-context.tsx] - - Q[app/dashboard] -->|components| R[dashboard.tsx] - Q -->|components| S[agent-list.tsx] - Q -->|providers| T[dashboard-context.tsx] - - U[lib] -->|hooks| V[use-mastra.ts] - U -->|hooks| W[use-dashboard-queries.ts] - U -->|utils| X[utils.ts] - U -->|client| Y[mastra-client.ts] - - Z[src/types] -->|api| AA[mastra-api.ts] - - AB[src/mastra/index.ts] -->|imports| AC[agents/*] - AB -->|imports| AD[tools/*] - AB -->|imports| AE[workflows/*] - AB -->|imports| AF[networks/*] - AB -->|imports| AG[config/*] - - style A stroke:#64b5f6 - style B stroke:#64b5f6 - style C stroke:#64b5f6 - style D stroke:#64b5f6 - style E stroke:#64b5f6 - style F stroke:#64b5f6 - style G stroke:#64b5f6 - style H stroke:#64b5f6 - style I stroke:#64b5f6 - style J stroke:#64b5f6 - style K stroke:#64b5f6 - style L stroke:#64b5f6 - style M stroke:#64b5f6 - style N stroke:#64b5f6 - style O stroke:#64b5f6 - style P stroke:#64b5f6 - style L stroke:#64b5f6 - style Q stroke:#64b5f6 - style U stroke:#64b5f6 - style Z stroke:#64b5f6 - style AB stroke:#64b5f6 +classDiagram + direction LR + + class UIMessage { + +string id + +parts MastraDataPart[] + } + + class MastraDataPart { + +string type + +string id + +unknown data + } + + class AgentDataPart { + +string type + +string id + +AgentExecutionData data + } + + class WorkflowDataPart { + +string type + +string id + +WorkflowExecutionData data + } + + class NetworkDataPart { + +string type + +string id + +NetworkExecutionData data + } + + class AgentExecutionData { + +string text + +unknown usage + +toolResults unknown[] + } + + class WorkflowExecutionData { + +string name + +string status + +WorkflowStepMap steps + +WorkflowOutput output + } + + class NetworkExecutionData { + +string name + +string status + +NetworkStep[] steps + +NetworkUsage usage + +unknown output + } + + class WorkflowStepMap { + <> + +string key + +WorkflowStep value + } + + class WorkflowStep { + +string status + +unknown input + +unknown output + +unknown suspendPayload + } + + class NetworkStep { + +string name + +string status + +unknown input + +unknown output + } + + class NetworkUsage { + +number inputTokens + +number outputTokens + +number totalTokens + } + + class MessageItem { + +UIMessage message + -MastraDataPart[] dataParts + +render() + } + + class AgentDataSection { + +AgentDataPart part + +render() + } + + class WorkflowDataSection { + +WorkflowDataPart part + +render() + } + + class NetworkDataSection { + +NetworkDataPart part + +render() + } + + class AgentTool { + +string id + +string type + +unknown data + +render() + } + + class TypeGuards { + +bool hasStringType(unknown part) + +bool isAgentDataPart(unknown part) + +bool isWorkflowDataPart(unknown part) + +bool isNetworkDataPart(unknown part) + } + + class KeyHelpers { + +string getToolCallId(unknown tool, number fallbackIndex) + } + + UIMessage "1" o-- "*" MastraDataPart + MastraDataPart <|-- AgentDataPart + MastraDataPart <|-- WorkflowDataPart + MastraDataPart <|-- NetworkDataPart + + MessageItem ..> MastraDataPart : filters dataParts + MessageItem ..> AgentDataPart : uses when isAgentDataPart + MessageItem ..> WorkflowDataPart : uses when isWorkflowDataPart + MessageItem ..> NetworkDataPart : uses when isNetworkDataPart + + MessageItem --> AgentDataSection : renders nested agent + MessageItem --> WorkflowDataSection : renders nested workflow + MessageItem --> NetworkDataSection : renders nested network + MessageItem --> AgentTool : renders other data-tool-* parts + + MessageItem ..> TypeGuards + MessageItem ..> KeyHelpers + + AgentDataSection --> AgentExecutionData + WorkflowDataSection --> WorkflowExecutionData + NetworkDataSection --> NetworkExecutionData + + WorkflowExecutionData o-- WorkflowStepMap + WorkflowStepMap o-- WorkflowStep + NetworkExecutionData o-- NetworkStep + NetworkExecutionData o-- NetworkUsage + + + style UIMessage stroke:#64b5f6 + style MastraDataPart stroke:#64b5f6 + style AgentDataPart stroke:#64b5f6 + style WorkflowDataPart stroke:#64b5f6 + style NetworkDataPart stroke:#64b5f6 + style AgentExecutionData stroke:#64b5f6 + style WorkflowExecutionData stroke:#64b5f6 + style NetworkExecutionData stroke:#64b5f6 + style MessageItem stroke:#64b5f6 + style TypeGuards stroke:#64b5f6 + style KeyHelpers stroke:#64b5f6 + style AgentDataSection stroke:#64b5f6 + style WorkflowDataSection stroke:#64b5f6 + style NetworkDataSection stroke:#64b5f6 + style AgentTool stroke:#64b5f6 + style NetworkUsage stroke:#64b5f6 + style NetworkStep stroke:#64b5f6 + style WorkflowStep stroke:#64b5f6 + style WorkflowStepMap stroke:#64b5f6 + style uses when stroke:#64b5f6 ``` ## 🔄 **RAG Pipeline (Production-Grade)** diff --git a/eslint.config.js b/eslint.config.js index da10133..0697ab1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,6 +1,4 @@ import js from '@eslint/js' -import tseslint from '@typescript-eslint/eslint-plugin' -import tsparser from '@typescript-eslint/parser' import prettierConfig from 'eslint-config-prettier' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' @@ -8,54 +6,55 @@ import { globalIgnores } from 'eslint/config' import globals from 'globals' import typescriptEslint from 'typescript-eslint' -const ignores = [ - 'eslint.config.js', - 'eslint.config.cjs', - 'node_modules/**', - 'dist/**', - '.next/**', - 'public/**', - 'coverage/**', - 'build/**', - 'out/**', - 'logs/**', - '.vscode/**', - '.mastra/**', - '.kilocode/**', - '.github/**', - '*.log', - 'memory-bank/**', - 'memories/**', - 'docs/**', - 'components/ui/**', - 'node_modules/@crawlee/http/internals/http-crawler.d.ts', - 'node_modules/@mdx-js/loader/index.d.cts', - 'docker/**', - '.spec/**', - '.specstory/**', - '.kiro/**', - '.codacy/**', - 'LICENSE', - 'CHANGELOG.md', - 'README.md', - 'CONTRIBUTING.md', - 'vitest.config.ts', - 'globalSetup.ts', - 'testSetup.ts', - 'vite.config.ts', - 'scripts/**', - '.gemini/**', - '.github/prompts/**/*.md', - '.github/chatmodes/*.md', -] - const tsTypeCheckedRecommended = typescriptEslint.plugin.configs['flat/recommended-type-checked'].map((cfg) => cfg.files ? cfg : { ...cfg, files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'] } ) export default [ - { ignores }, - globalIgnores(['dist', 'node_modules']), + globalIgnores([ + 'dist/**', + '**/node_modules/', + '**/tests/**', + '**/types/**', + '**/*.test.ts', + '**/*.test.tsx', + '**/*.spec.ts', + '**/*.spec.tsx', + '.next/**', + 'public/**', + 'coverage/**', + 'build/**', + 'out/**', + 'logs/**', + '.vscode/**', + '.mastra/**', + '.kilocode/**', + '.github/**', + '*.log', + 'memory-bank/**', + 'memories/**', + 'docs/**', + 'components/ui/**', + 'node_modules/@crawlee/http/internals/http-crawler.d.ts', + 'node_modules/@mdx-js/loader/index.d.cts', + 'docker/**', + '.spec/**', + '.specstory/**', + '.kiro/**', + '.codacy/**', + 'LICENSE', + 'CHANGELOG.md', + 'README.md', + 'CONTRIBUTING.md', + 'vitest.config.ts', + 'globalSetup.ts', + 'testSetup.ts', + 'vite.config.ts', + 'scripts/**', + '.gemini/**', + '.github/prompts/**/*.md', + '.github/chatmodes/*.md', + ]), js.configs.recommended, reactHooks.configs.flat.recommended, reactRefresh.configs.next, @@ -65,10 +64,10 @@ export default [ { files: ['**/*.ts', '**/*.tsx'], plugins: { - '@typescript-eslint': tseslint, + '@typescript-eslint': typescriptEslint.plugin, }, languageOptions: { - parser: tsparser, + parser: typescriptEslint.parser, globals: { ...globals.browser, ...globals.node }, parserOptions: { ecmaVersion: 2022, diff --git a/ui/accordion.tsx b/ui/accordion.tsx index 4305eff..9172f77 100644 --- a/ui/accordion.tsx +++ b/ui/accordion.tsx @@ -130,7 +130,7 @@ export function AccordionItem({ ) } -export interface AccordionTriggerProps extends React.ButtonHTMLAttributes {} +export type AccordionTriggerProps = React.ButtonHTMLAttributes export function AccordionTrigger({ className, @@ -162,7 +162,7 @@ export function AccordionTrigger({ ) } -export interface AccordionContentProps extends React.HTMLAttributes {} +export type AccordionContentProps = React.HTMLAttributes export function AccordionContent({ className, diff --git a/ui/tabs.tsx b/ui/tabs.tsx index 172c860..4146668 100644 --- a/ui/tabs.tsx +++ b/ui/tabs.tsx @@ -57,7 +57,7 @@ export function Tabs({ ) } -export interface TabsListProps extends React.HTMLAttributes {} +export type TabsListProps = React.HTMLAttributes export function TabsList({ className, children, ...props }: TabsListProps) { return (