-
Notifications
You must be signed in to change notification settings - Fork 6
chore: update dependencies and refactor workflow stages #55
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 all commits
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,7 +1,11 @@ | ||||||||||
| import js from '@eslint/js' | ||||||||||
| import globals from "globals"; | ||||||||||
| import reactHooks from "eslint-plugin-react-hooks"; | ||||||||||
| import reactRefresh from "eslint-plugin-react-refresh"; | ||||||||||
| import tseslint from '@typescript-eslint/eslint-plugin' | ||||||||||
| import tsparser from '@typescript-eslint/parser' | ||||||||||
| import prettierConfig from 'eslint-config-prettier' | ||||||||||
| import { globalIgnores } from "eslint/config"; | ||||||||||
|
||||||||||
| import { globalIgnores } from "eslint/config"; |
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.
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.
style: This globalIgnores call is redundant - dist and node_modules are already in the ignores array above (lines 14-15). Consider removing this line.
Prompt To Fix With AI
This is a comment left during a code review.
Path: eslint.config.js
Line: 53:53
Comment:
**style:** This `globalIgnores` call is redundant - `dist` and `node_modules` are already in the `ignores` array above (lines 14-15). Consider removing this line.
How can I resolve this? If you propose a fix, please make it concise.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.
🧹 Nitpick | 🔵 Trivial
Remove redundant globalIgnores call.
The globalIgnores(["dist", "node_modules"]) duplicates entries already present in the ignores array (lines 13-14: 'node_modules/**' and 'dist/**'). This redundancy adds no value and may cause confusion.
{ ignores },
- globalIgnores(["dist", "node_modules"]),
js.configs.recommended,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| { ignores }, | |
| globalIgnores(["dist", "node_modules"]), | |
| { ignores }, | |
| js.configs.recommended, |
🤖 Prompt for AI Agents
In eslint.config.js around lines 52 to 53, remove the redundant
globalIgnores(["dist", "node_modules"]) call because those patterns are already
present in the ignores array (lines ~13-14 as 'node_modules/**' and 'dist/**');
simply delete the globalIgnores(...) entry so ignores are defined in a single
place to avoid duplication and confusion.
Copilot
AI
Dec 14, 2025
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.
This usage of globalIgnores(["dist", "node_modules"]) is incorrect and will cause a runtime error. The globalIgnores function does not exist in ESLint's API. Additionally, these paths are already included in the ignores array defined earlier (lines 13-14). This line should be removed.
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.
style: Verify that reactRefresh.configs.next exists - the standard config is typically reactRefresh.configs.recommended or a custom flat config object
Prompt To Fix With AI
This is a comment left during a code review.
Path: eslint.config.js
Line: 56:56
Comment:
**style:** Verify that `reactRefresh.configs.next` exists - the standard config is typically `reactRefresh.configs.recommended` or a custom flat config object
How can I resolve this? If you propose a fix, please make it concise.
Copilot
AI
Dec 14, 2025
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.
The configuration reference reactRefresh.configs.next appears to be incorrect. The eslint-plugin-react-refresh package typically exports configs.recommended or configs.vite, not configs.next. This should be verified against the actual plugin documentation and corrected to use a valid configuration export.
| reactRefresh.configs.next, | |
| reactRefresh.configs.recommended, |
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.
issue (bug_risk): Applying globals.browser to all *.ts / *.tsx files may hide issues in Node-only code.
Because this config applies globals.browser to all TS/TSX files, browser globals like window will appear valid even in server-side/Node-only modules, potentially hiding real bugs. Consider limiting globals.browser to known client/React files (e.g., narrower files patterns or a separate override) and using appropriate Node globals for backend code instead.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,6 +1,13 @@ | ||||||
| import { type ClassValue, clsx } from "clsx" | ||||||
| import { twMerge } from "tailwind-merge" | ||||||
| import { v4 as uuid } from "@lukeed/uuid"; | ||||||
|
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. syntax: Missing dependency:
Suggested change
Prompt To Fix With AIThis is a comment left during a code review.
Path: lib/utils.ts
Line: 3:3
Comment:
**syntax:** Missing dependency: `@lukeed/uuid` is imported but not present in `package.json`
```suggestion
import { v4 as uuid } from "uuid";
```
How can I resolve this? If you propose a fix, please make it concise. |
||||||
|
|
||||||
| export function cn(...inputs: ClassValue[]) { | ||||||
| return twMerge(clsx(inputs)) | ||||||
| } | ||||||
| export function newThreadLink( | ||||||
| rootPath: string, | ||||||
| agentId: string, | ||||||
| ): `/${string}/${string}/chat/${string}?new=true` { | ||||||
|
||||||
| ): `/${string}/${string}/chat/${string}?new=true` { | |
| ): string { |
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.
suggestion: Consider normalizing rootPath and agentId to avoid accidental double slashes in the generated URL.
If callers pass rootPath with or without a leading slash, or an agentId that already includes slashes, this helper can generate malformed URLs like //agents//id/chat/.... Normalizing inputs (e.g., trimming leading/trailing slashes) within this function would make it safer and more predictable to use.
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.
🧹 Nitpick | 🔵 Trivial
Add TSDoc documentation and consider input validation.
The function lacks TSDoc documentation. Per coding guidelines, public APIs should include parameter descriptions, return types, and examples. Additionally, consider validating/sanitizing rootPath and agentId to prevent malformed URLs (e.g., if they contain slashes or special characters).
+/**
+ * Generates a new chat thread URL path with a unique identifier.
+ * @param rootPath - The root path segment (e.g., 'app', 'dashboard')
+ * @param agentId - The agent identifier
+ * @returns A URL path in the format `/{rootPath}/{agentId}/chat/{uuid}?new=true`
+ * @example
+ * newThreadLink('app', 'agent-123')
+ * // => '/app/agent-123/chat/550e8400-e29b-41d4-a716-446655440000?new=true'
+ */
export function newThreadLink(
rootPath: string,
agentId: string,
): `/${string}/${string}/chat/${string}?new=true` {
return `/${rootPath}/${agentId}/chat/${uuid()}?new=true`;
}🤖 Prompt for AI Agents
In lib/utils.ts around lines 8–13, add a TSDoc block for newThreadLink
describing parameters (rootPath, agentId), the template-literal return type, and
an example usage; then validate/sanitize inputs by trimming and removing
leading/trailing slashes from rootPath and agentId, ensure they are non-empty
(throw or return a clear error), and URL-encode each segment (e.g., with
encodeURIComponent) before composing the final
`/${rootPath}/${agentId}/chat/${uuid()}?new=true` string so the generated URL is
well-formed and safe.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -119,6 +119,8 @@ | |
| "diff": "^8.0.2", | ||
| "dotenv": "^17.2.3", | ||
| "embla-carousel-react": "^8.6.0", | ||
| "eslint-plugin-react-hooks": "^7.0.1", | ||
| "eslint-plugin-react-refresh": "^0.4.23", | ||
|
Comment on lines
+122
to
+123
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. Move ESLint plugins to ESLint plugins are development-time tools used for linting, not runtime dependencies. They should be in Move these entries from "devDependencies": {
"@mdx-js/loader": "^3.1.1",
...
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.23",
...
}And remove from
🤖 Prompt for AI Agents |
||
| "excalidraw-to-svg": "^3.1.0", | ||
| "fast-glob": "^3.3.3", | ||
| "fast-xml-parser": "^5.3.3", | ||
|
|
@@ -216,4 +218,4 @@ | |
| "body-parser": "^2.2.1", | ||
| "jws": "^4.0.1" | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -269,7 +269,7 @@ const convertPdfToMarkdownStep = createStep({ | |||||||||||||
| data: { | ||||||||||||||
| status: 'in-progress', | ||||||||||||||
| message: 'Converting PDF to markdown `...', | ||||||||||||||
| stage: "documentProcessingAgent", | ||||||||||||||
| stage: "convert-pdf-to-markdown", | ||||||||||||||
|
Comment on lines
271
to
+272
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. Fix typo: stray backtick in message string. The message contains an errant backtick that appears unintentional. status: 'in-progress',
- message: 'Converting PDF to markdown `...',
+ message: 'Converting PDF to markdown...',
stage: "convert-pdf-to-markdown",📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| }, | ||||||||||||||
| id: "convert-pdf-to-markdown", | ||||||||||||||
| }); | ||||||||||||||
|
|
@@ -318,7 +318,7 @@ const convertPdfToMarkdownStep = createStep({ | |||||||||||||
| data: { | ||||||||||||||
| status: "in-progress", | ||||||||||||||
| message: 'Markdown conversion complete (90%)...', | ||||||||||||||
| stage: "documentProcessingAgent", | ||||||||||||||
| stage: "convert-pdf-to-markdown", | ||||||||||||||
| }, | ||||||||||||||
| id: "convert-pdf-to-markdown", | ||||||||||||||
| }); | ||||||||||||||
|
|
@@ -345,7 +345,7 @@ const convertPdfToMarkdownStep = createStep({ | |||||||||||||
| data: { | ||||||||||||||
| status: "done", | ||||||||||||||
| message: "PDF converted to markdown successfully", | ||||||||||||||
| stepId: 'convert-pdf-to-markdown', | ||||||||||||||
| stage: 'convert-pdf-to-markdown', | ||||||||||||||
| }, | ||||||||||||||
| id: "convert-pdf-to-markdown", | ||||||||||||||
| }); | ||||||||||||||
|
|
@@ -360,9 +360,10 @@ const convertPdfToMarkdownStep = createStep({ | |||||||||||||
| logError('convert-pdf-to-markdown', error, { contentType: inputData.contentType }); | ||||||||||||||
|
|
||||||||||||||
| await writer?.custom({ | ||||||||||||||
| type: 'data-workflow-step-error', | ||||||||||||||
| type: 'data-tool-progress', | ||||||||||||||
| data: { | ||||||||||||||
| stepId: 'convert-pdf-to-markdown', | ||||||||||||||
| stage: 'convert-pdf-to-markdown', | ||||||||||||||
| status: "done", | ||||||||||||||
| error: error instanceof Error ? error.message : 'Unknown error', | ||||||||||||||
|
||||||||||||||
| error: error instanceof Error ? error.message : 'Unknown error', | |
| error: error instanceof Error ? error.message : 'Unknown error', | |
| message: `Error in convert-pdf-to-markdown: ${error instanceof Error ? error.message : 'Unknown error'}`, |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -177,29 +177,36 @@ const ingestStep = createStep({ | |
|
|
||
| const result = await mdocumentChunker.execute({ | ||
| documentContent: content, | ||
| documentMetadata: { filePath, source: githubRepo ? 'github' : 'local' }, | ||
| documentMetadata: { filePath, source: (githubRepo) ? 'github' : 'local' }, | ||
| chunkingStrategy: strategy, | ||
| indexName: 'memory_messages_3072', | ||
| generateEmbeddings: true, | ||
| embeddingModel: 'google/gemini-embedding-001', | ||
| embeddingBatchSize: 50, | ||
|
Comment on lines
+184
to
+185
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. 🧹 Nitpick | 🔵 Trivial Consider making embedding configuration parameters configurable. The embedding model and batch size are hardcoded. For flexibility, consider adding these as optional inputs to the workflow schema with sensible defaults. // In scanInputSchema, add optional embedding config:
embeddingModel: z.string().default('google/gemini-embedding-001'),
embeddingBatchSize: z.number().default(50),🤖 Prompt for AI Agents |
||
| chunkSize: 512, | ||
| chunkOverlap: 50, | ||
| chunkSeparator: '\n' | ||
| }, { writer, requestContext }); | ||
|
|
||
| if (result && typeof result === 'object' && 'success' in result && result.success) { | ||
| processedFiles++; | ||
| totalChunks += result.chunkCount; | ||
| } | ||
| else if (result instanceof ZodError) { | ||
| throw new Error(result.message); | ||
| } | ||
| else if (result instanceof Error) { | ||
| throw result; | ||
| } else if (result && typeof result === 'object' && 'error' in result) { | ||
| throw new Error(typeof result.error === 'string' ? result.error : 'Unknown error in chunking'); | ||
| } else { | ||
| throw new Error('Unknown error in chunking'); | ||
| } | ||
| const isSuccessResult = (r: unknown): r is { success: true; chunkCount?: number } => | ||
| typeof r === 'object' && r !== null && 'success' in r && (r as { success: unknown }).success === true; | ||
|
|
||
| const isErrorObject = (r: unknown): r is { error: unknown } => | ||
| typeof r === 'object' && r !== null && 'error' in r; | ||
|
|
||
| if (isSuccessResult(result)) { | ||
| processedFiles++; | ||
| totalChunks += result.chunkCount ?? 0; | ||
| } else if (result instanceof ZodError) { | ||
| throw new Error(result.message); | ||
| } else if (result instanceof Error) { | ||
| throw result; | ||
| } else if (isErrorObject(result)) { | ||
| const err = result.error; | ||
| throw new Error(typeof err === 'string' ? err : 'Unknown error in chunking'); | ||
| } else { | ||
| throw new Error('Unknown error in chunking'); | ||
| } | ||
|
|
||
| } catch (error) { | ||
| const errorObj = error instanceof Error ? error : new Error(String(error)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,9 +72,9 @@ const initializeResearchStep = createStep({ | |
| await writer?.custom({ | ||
| type: 'data-tool-progress', | ||
| data: { | ||
| status: "in-progress", | ||
| message: `Researching topic: ${inputData.topics}...`, | ||
| stage: "researchAgent", | ||
| status: "in-progress", | ||
| message: `Researching topic: ${inputData.topics}...`, | ||
| stage: "researchAgent", | ||
| }, | ||
| id: 'initialize-research', | ||
| }); | ||
|
Comment on lines
72
to
80
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. 🧹 Nitpick | 🔵 Trivial Inconsistent stage naming in This step uses await writer?.custom({
type: 'data-tool-progress',
data: {
status: "in-progress",
message: `Researching topic: ${inputData.topics}...`,
- stage: "researchAgent",
+ stage: "initialize-research",
},
id: 'initialize-research',
});🤖 Prompt for AI Agents |
||
|
|
@@ -84,7 +84,7 @@ const initializeResearchStep = createStep({ | |
| maxSources: inputData.maxSourcesPerTopic, | ||
| })); | ||
|
|
||
|
|
||
| logStepEnd('initialize-research', { topicsCount: topics.length }, Date.now() - startTime); | ||
|
|
||
| return topics; | ||
|
|
@@ -109,7 +109,7 @@ const researchTopicStep = createStep({ | |
| data: { | ||
| status: 'in-progress', | ||
| message: `Researching topic: ${inputData.topic}...`, | ||
| stage: 'workflow', | ||
| stage: 'research-topic-item', | ||
| }, | ||
| id: 'research-topic-item', | ||
| }); | ||
|
|
@@ -128,7 +128,7 @@ const researchTopicStep = createStep({ | |
| data: { | ||
| status: 'in-progress', | ||
| message: `Researching topic: ${inputData.topic}...`, | ||
| stage: 'workflow', | ||
| stage: 'research-topic-item', | ||
| }, | ||
| id: 'research-topic-item', | ||
| }); | ||
|
|
@@ -189,7 +189,7 @@ const researchTopicStep = createStep({ | |
| data: { | ||
| status: 'done', | ||
| message: `Research completed for ${inputData.topic}...`, | ||
| stage: 'workflow', | ||
| stage: 'research-topic-item', | ||
| }, | ||
| id: 'research-topic-item', | ||
| }); | ||
|
|
@@ -211,9 +211,9 @@ const researchTopicStep = createStep({ | |
| await writer?.custom({ | ||
| type: 'data-tool-progress', | ||
| data: { | ||
| status: 'in-progress', | ||
| status: 'done', | ||
| message: `Research error for ${inputData.topic}...`, | ||
| stage: 'researchAgent', | ||
| stage: 'research-topic-item', | ||
| }, | ||
| id: 'research-topic-item', | ||
| }); | ||
|
|
@@ -255,6 +255,7 @@ const synthesizeResearchStep = createStep({ | |
| data: { | ||
| status: 'in-progress', | ||
| message: 'Synthesizing research across topics...', | ||
| stage: 'synthesize-research', | ||
| }, | ||
| id: 'synthesize-research', | ||
| }); | ||
|
|
@@ -269,6 +270,7 @@ const synthesizeResearchStep = createStep({ | |
| data: { | ||
| status: 'in-progress', | ||
| message: 'AI synthesizing findings...', | ||
| stage: 'synthesize-research', | ||
| }, | ||
| id: 'synthesize-research', | ||
| }); | ||
|
|
@@ -352,6 +354,7 @@ Provide: | |
| data: { | ||
| status: 'done', | ||
| message: 'Synthesis complete...', | ||
| stage: 'synthesize-research', | ||
| }, | ||
| id: 'synthesize-research', | ||
| }); | ||
|
|
@@ -376,7 +379,7 @@ Provide: | |
| span.setAttribute('responseTimeMs', Date.now() - startTime); | ||
| span.end(); | ||
|
|
||
|
|
||
| logStepEnd('synthesize-research', { themesCount: synthesis.commonThemes.length }, Date.now() - startTime); | ||
| return result; | ||
| } catch (error) { | ||
|
|
@@ -386,10 +389,11 @@ Provide: | |
| logError('synthesize-research', error); | ||
|
|
||
| await writer?.custom({ | ||
| type: 'data-workflow-step-error', | ||
| type: 'data-tool-progress', | ||
| data: { | ||
| stepId: 'synthesize-research', | ||
| stage: 'synthesize-research', | ||
| error: error instanceof Error ? error.message : 'Unknown error', | ||
| status: 'done', | ||
| }, | ||
|
Comment on lines
391
to
397
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. style: Setting Prompt To Fix With AIThis is a comment left during a code review.
Path: src/mastra/workflows/research-synthesis-workflow.ts
Line: 391:397
Comment:
**style:** Setting `status: 'done'` in error case may be misleading - consider `status: 'error'` to better indicate failure state
How can I resolve this? If you propose a fix, please make it concise. |
||
| id: 'synthesize-research', | ||
| }); | ||
|
|
@@ -421,6 +425,7 @@ const generateResearchReportStep = createStep({ | |
| data: { | ||
| status: 'in-progress', | ||
| message: 'Generating research report...', | ||
| stage: 'generate-research-report', | ||
| }, | ||
| id: 'generate-research-report', | ||
| }); | ||
|
|
@@ -434,6 +439,7 @@ const generateResearchReportStep = createStep({ | |
| data: { | ||
| status: 'in-progress', | ||
| message: 'AI generating comprehensive report...', | ||
| stage: 'generate-research-report', | ||
| }, | ||
| id: 'generate-research-report', | ||
| }); | ||
|
|
@@ -502,7 +508,7 @@ ${inputData.synthesis.gaps?.map(g => `- ${g}`).join('\n') ?? 'No significant gap | |
| data: { | ||
| status: 'done', | ||
| message: 'Report generation complete...', | ||
| stage: 'workflow', | ||
| stage: 'generate-research-report', | ||
| }, | ||
| id: 'generate-research-report', | ||
| }); | ||
|
|
@@ -523,7 +529,7 @@ ${inputData.synthesis.gaps?.map(g => `- ${g}`).join('\n') ?? 'No significant gap | |
| span.setAttribute('responseTimeMs', Date.now() - startTime); | ||
| span.end(); | ||
|
|
||
|
|
||
| logStepEnd('generate-research-report', { reportLength: report.length }, Date.now() - startTime); | ||
| return result; | ||
| } catch (error) { | ||
|
|
@@ -533,11 +539,11 @@ ${inputData.synthesis.gaps?.map(g => `- ${g}`).join('\n') ?? 'No significant gap | |
| logError('generate-research-report', error); | ||
|
|
||
| await writer?.custom({ | ||
| type: 'data-workflow-step-error', | ||
| type: 'data-tool-progress', | ||
| data: { | ||
| stepId: 'generate-research-report', | ||
| stage: 'generate-research-report', | ||
| error: error instanceof Error ? error.message : 'Unknown error', | ||
| stage: 'workflow', | ||
| status: 'done' | ||
| }, | ||
| id: 'generate-research-report', | ||
| }); | ||
|
|
||
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.
style: Verify that
globalIgnoresexport exists ineslint/config- this import path may not be valid for ESLintPrompt To Fix With AI