Automatic Sync: Merge changes from stable/mi to main#2355
Automatic Sync: Merge changes from stable/mi to main#2355choreo-cicd wants to merge 123 commits into
Conversation
Replace VALID_FILE_EXTENSIONS / VALID_SPECIAL_FILE_NAMES with BLOCKED_BINARY_EXTENSIONS so the agent can read/write any text file (including extensionless ones like Dockerfile, Makefile, .gitignore) while still blocking archives, executables, office docs, images, etc. Shell sandbox now enforces the same deny-list on mutation paths. The @-mention picker keeps its own short UX allow-list, decoupled from the security gate. Also enable XML validation for .dbs data services.
Trim filePath in getReadFileKind() to keep classification consistent with validateReadableFilePath(), and update shell sandbox error message to accurately describe all mutation types (write/edit/delete/rename).
Loads a root-level AGENTS.md (CLAUDE.md / Cursor convention) as a tracked context block. Re-injected only on content drift via the existing session-context hash system, so it does not waste tokens every turn. Files over 30 KB are truncated before being shipped to the model. The block carries an explicit truncation banner so the agent knows context is missing (and can file_read the tail on demand), and a persistent in-chat warning segment tells the user. Truncation warnings fire only when the block is actually being injected, so an unchanged large file does not re-warn each turn.
- agent.ts: make `saveAgentsMdWarning` failure non-fatal. The live event still fires so the user sees the warning this turn; only the JSONL replay across reconnects is sacrificed on persistence failure. - prompt.ts: neutralize embedded `<system-reminder>` / `<user_query>` tags in user-authored AGENTS.md so they can't break out of the surrounding envelope. Replaces the angle brackets with U+27E8 / U+27E9. - prompt.ts: fix the `SessionContextBlockHashes.agentsMd` doc comment to describe what the code actually hashes (surfaced bytes + truncation metadata) instead of the old "full untruncated raw bytes" claim. - AIChatFooter.tsx: splice the warning before the optimistic streaming placeholder. Appending at the end displaced the placeholder, causing subsequent content_block / thinking_* events to land in the warning bubble instead of the assistant message. - eventToMessageConverter.ts: drop `(event as any)` cast now that `warningMessage` is a typed field on AgentEvent / ChatHistoryEvent.
Fix trivy detected vulnerabilities
Support the startOnLoad attribute for tasks in MI 4.1.0
Instruct agent-mode to flip pom.xml <packaging> to jar and declare synapse-core when creating a class mediator, otherwise the CApp ships without the compiled jar and deployment silently fails. Fixes wso2/product-integrator#1631
file_write and file_edit now append a <system-reminder> to the tool result whenever the touched file is a class mediator java source (src/main/java/**/*.java), telling the agent to verify root pom.xml packaging is "jar" and synapse-core is declared. The prompt-level guideline alone can be missed; a per-tool reminder makes it harder to skip. Related to wso2/product-integrator#1631
Read the project root pom.xml and skip the class mediator reminder when <packaging>jar</packaging> is already set, so the agent is not prompted to fix something that is already correct. When packaging is something else (typically the default "pom"), the reminder reports the current value to make the required change unambiguous.
Prepare for the MI 4.0.2 release
…ging Fix copilot-created class mediators not packed in CApp
- Clarify file_read offset/limit are line-based in AGENTS.md guidance - Use Math.ceil for KB rounding and improve truncation warning copy - Add aria-hidden to decorative warning icon - Dedup context_warning on panel reconnect/event replay
Mirror the POSIX shell sandbox check so the agent cannot mutate foo.jar, foo.dll, etc. via PowerShell on Windows.
Switch agent file tools to a binary deny-list
Fix trivy detected vulnerabilities
Sync latest changes from release/mi-4.0.2
Merge "micro-integrator-4.0.2" into "stable/mi"
Fix issues in the MI Extension
Improve MI build and run process
Add improvements to MCP Server feature.
Fix issues in the MI Extension
Show lengthy connection type labels on hover
…nager.ts Co-authored-by: Chinthaka Jayatilake <37581983+ChinthakaJ98@users.noreply.github.com>
Prepare for MI extension v4.1.0 release
…i into feature/mi-mcp-server
Improve Fill With AI experience with MCP Server
Fix E2E tests
Merge "micro-integrator-4.1.0" into "stable/mi"
📝 WalkthroughWalkthroughThis PR updates dependency overrides and package manifests, adds AGENTS.md/context-warning handling for agent mode, and introduces MCP server RPC, project explorer, and visualizer flows across the MI extension. ChangesDependency sync
Agent-mode and debugger flow
MCP server feature
Sequence Diagram(s)sequenceDiagram
participant MCPServerWizard
participant MiDiagramRpcManager
participant ProjectExplorer
participant MainPanel
MCPServerWizard->>MiDiagramRpcManager: create local entry and inbound endpoint
ProjectExplorer->>MiDiagramRpcManager: open/show/delete MCP server
MainPanel->>MCPServerWizard: render MCPServerForm and MCPServerFromAPIsForm views
Estimated code review effort🎯 5 (Critical) | ⏱️ ~90+ minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
|
|
|
There was a problem hiding this comment.
Actionable comments posted: 1
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
workspaces/mi/mi-extension/src/ai-features/agent-mode/tools/file_tools.ts (1)
134-151:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReject special files before the
"text"fallback.This fallback now treats any non-blocked path as text, while the read path explicitly allows absolute paths outside the workspace. That means extensionless special files like
/proc/self/environ,/proc/cpuinfo, or/dev/randomcan pass validation and then getreadFileSync'd later, which is both a host-data leak and a potential hang.Suggested fix
function validateReadableFilePath(projectPath: string, filePath: string): ValidationResult { const securityValidation = validateFilePathSecurity(projectPath, filePath, { allowOutsideProject: true }); if (!securityValidation.valid) { return securityValidation; } + + const fullPath = resolveFullPath(projectPath, filePath); + if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isFile()) { + return { + valid: false, + error: `Cannot read '${filePath}'. Only regular files are supported.` + }; + } if (getReadFileKind(filePath) === 'unsupported') { return { valid: false, error: `Cannot read binary file '${filePath}'. The extension is on the blocked-binary list (archives, executables, native libraries, office docs, fonts, audio/video, etc.). Use shell tools for binary inspection if needed.`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/ai-features/agent-mode/tools/file_tools.ts` around lines 134 - 151, getReadFileKind currently falls back to 'text' for any non-blocked path; update getReadFileKind to detect and reject OS special files (e.g., paths starting with '/proc/', '/dev/', '/sys/' and other well-known pseudo-filesystems or device nodes) before the text fallback so they return 'unsupported' instead of 'text'. In practice, add a check near the top of getReadFileKind (before the hasBlockedBinaryExtension check) that normalizes/trimmed the path and returns 'unsupported' for absolute special-system paths and obvious device files; keep the existing READ_PDF_EXTENSION and READ_IMAGE_EXTENSIONS logic and still call hasBlockedBinaryExtension for other cases. Ensure you reference getReadFileKind and hasBlockedBinaryExtension when making the change.workspaces/mi/mi-extension/src/rpc-managers/mi-diagram/rpc-manager.ts (1)
455-464:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlso clear the API-level fallback default here.
This only removes
content[key].defaultRequest. If the last shared payload is deleted, the old top-levelcontent.defaultRequestsurvives, and Line 544 still falls back to it. That can resurrect a deleted default payload name for APIs.Suggested fix
if (cleanShared.length > 0) { content.requests = cleanShared; if (content.defaultRequest) { delete content.defaultRequest; } } else { content.requests = []; + if (content.defaultRequest) { + delete content.defaultRequest; + } }Also applies to: 480-482
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/rpc-managers/mi-diagram/rpc-manager.ts` around lines 455 - 464, When handling type === "API" in rpc-manager.ts, the code only deletes content[key].defaultRequest but leaves the top-level content.defaultRequest intact when shared requests are cleared; update the block that sets content.requests (and the similar block around the other occurrence referenced) so that when cleanShared.length === 0 you also delete content.defaultRequest (or set it to undefined) to ensure the API-level fallback default is removed; target the branch inside the function that uses the variables content, cleanShared and type === "API" (and the analogous branch at the other occurrence) to apply the change.workspaces/mi/mi-visualizer/src/views/AIPanel/component/AIChatMessage.tsx (1)
281-301:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winExclude context warnings from answer-content detection.
hasAnswerContentdoesn’t treatsegment.isContextWarningas a system segment, so warning-only synthetic messages can incorrectly show the feedback bar.Suggested fix
const isSystemSegment = Boolean( segment.isToolCall || segment.isTodoList || segment.isBashOutput || segment.isCompactSummary || + segment.isContextWarning || segment.isFileChanges || segment.isPlan || segment.isThinking );Also applies to: 381-390
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/AIPanel/component/AIChatMessage.tsx` around lines 281 - 301, The hasAnswerContent detection currently treats system-like segments via the isSystemSegment boolean but omits segment.isContextWarning, so synthetic messages that only contain context warnings still count as answer content; update the isSystemSegment expression inside the parsedSegments.some callback in AIChatMessage.tsx (the hasAnswerContent computation) to include segment.isContextWarning alongside segment.isToolCall, segment.isTodoList, segment.isBashOutput, segment.isCompactSummary, segment.isFileChanges, segment.isPlan, and segment.isThinking, and apply the same change to the other analogous hasAnswerContent block later in the file so context warnings are excluded from answer-content detection.
🟠 Major comments (20)
workspaces/mi/mi-extension/src/project-explorer/activate.ts-486-490 (1)
486-490:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPass a string path into
refreshViewsAfterDelete().This block still accepts both
Uriand string inputs, but the helper expects a string path. WhenfileUriis aUri, the delete succeeds and the follow-up refresh call throws, so the user gets a false “Failed to delete …” error after the artifact was already removed.Suggested fix
if (item.contextValue === 'api') { deleteSwagger(fileUri); deleteApiMetadata(fileUri); } - refreshViewsAfterDelete(fileUri); + refreshViewsAfterDelete(fileUri.fsPath ?? fileUri); } catch (error) { window.showErrorMessage(`Failed to delete ${item.label}: ${error}`); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/project-explorer/activate.ts` around lines 486 - 490, The call to refreshViewsAfterDelete currently passes fileUri which can be a Uri and causes a runtime error; update the call site (around deleteSwagger and deleteApiMetadata in activate.ts) to pass a string path instead by resolving fileUri to a string (e.g. use fileUri.fsPath when fileUri is a Uri, otherwise use the value as-is) so refreshViewsAfterDelete always receives a string path.workspaces/mi/mi-extension/src/project-explorer/activate.ts-680-689 (1)
680-689:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDon't require an inbound endpoint to delete every MCP server.
MCPServerTreeItemmarksinboundEndpointas optional, and the delete logic below already handles it conditionally. This guard currently blocks deletion for valid MCP servers that only have a local entry.Suggested fix
- if (!localEntryPath || !inboundEndpointPath) { - window.showErrorMessage('Could not determine MCP server paths'); + if (!localEntryPath) { + window.showErrorMessage('Could not determine the MCP server local entry path'); return; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/project-explorer/activate.ts` around lines 680 - 689, The guard in the 'mcpServer' case is incorrectly requiring inboundEndpointPath even though MCPServerTreeItem.inboundEndpoint is optional; update the check to only require localEntryPath (i.e. verify mcpItem.info?.localEntry?.path exists) and remove the inboundEndpointPath requirement so deletion can proceed when only a local entry is present; adjust the window.showErrorMessage text accordingly and keep the rest of the delete logic (which already handles inboundEndpointPath conditionally) unchanged.workspaces/mi/mi-extension/src/rpc-managers/ai-features/rpc-manager.ts-950-956 (1)
950-956:⚠️ Potential issue | 🟠 Major | ⚡ Quick winValidate the model payload before returning it over RPC.
A syntactically valid JSON response is not enough here. If the model returns non-string
name/descriptionfields or a non-objectinputSchema, this method will still forward that malformed payload across the RPC boundary and into the MCP tool flow. Add a runtime shape check and fail closed when it does not match the expected contract.🧪 Suggested validation
const cleaned = text.trim().replace(/^```json\s*/i, '').replace(/```\s*$/, ''); const parsed = JSON.parse(cleaned); + const validInputSchema = + parsed?.inputSchema && + typeof parsed.inputSchema === 'object' && + !Array.isArray(parsed.inputSchema); + + if ( + typeof parsed?.name !== 'string' || + typeof parsed?.description !== 'string' || + !validInputSchema + ) { + throw new Error('Model returned an invalid MCP tool suggestion payload'); + } + return { - name: parsed.name || '', - description: parsed.description || '', - inputSchema: JSON.stringify(parsed.inputSchema || {}), + name: parsed.name, + description: parsed.description, + inputSchema: JSON.stringify(parsed.inputSchema), };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/rpc-managers/ai-features/rpc-manager.ts` around lines 950 - 956, The current code trims and JSON.parses the model output (variables cleaned/parsed) but does not validate types, so non-string name/description or non-object inputSchema can be forwarded; add runtime shape checks after parsing (verify typeof parsed.name === 'string', typeof parsed.description === 'string', and parsed.inputSchema is a plain object and not an array), throw an Error to fail closed if validation fails, and only then return the object using parsed.name, parsed.description and JSON.stringify(parsed.inputSchema) instead of defaulting to empty values.workspaces/mi/mi-extension/src/rpc-managers/ai-features/rpc-manager.ts-906-948 (1)
906-948:⚠️ Potential issue | 🟠 Major | ⚡ Quick winConstrain MCP context reads to workspace XML files.
apiXmlPathandsequenceXmlPathcome straight from the RPC payload, are read from disk, and are then sent to Anthropic. That turns this endpoint into a local-file disclosure primitive if a webview request is ever tampered with. Resolve the path, reject anything outsidethis.projectUri, and enforce an.xmlextension before reading.🔒 Suggested guard
+ const path = require('path') as typeof import('path'); const fs = require('fs') as typeof import('fs'); const MAX_XML_CHARS = 3000; + + const readWorkspaceXml = (filePath: string): string => { + const resolvedPath = fs.realpathSync(filePath); + const relativePath = path.relative(this.projectUri, resolvedPath); + if ( + !relativePath || + relativePath.startsWith('..') || + path.isAbsolute(relativePath) || + path.extname(resolvedPath).toLowerCase() !== '.xml' + ) { + throw new Error('Only workspace XML files can be used as MCP context'); + } + + let xml = fs.readFileSync(resolvedPath, 'utf8'); + if (xml.length > MAX_XML_CHARS) { + xml = `${xml.slice(0, MAX_XML_CHARS)}\n... (truncated)`; + } + return xml; + }; if (apiXmlPath) { try { - let xml = fs.readFileSync(apiXmlPath, 'utf8'); - if (xml.length > MAX_XML_CHARS) xml = xml.slice(0, MAX_XML_CHARS) + '\n... (truncated)'; + const xml = readWorkspaceXml(apiXmlPath); contextLines.push(`\nAPI resource XML (Synapse configuration):\n${xml}`); } catch { /* file unreadable — skip */ } } if (sequenceXmlPath) { try { - let xml = fs.readFileSync(sequenceXmlPath, 'utf8'); - if (xml.length > MAX_XML_CHARS) xml = xml.slice(0, MAX_XML_CHARS) + '\n... (truncated)'; + const xml = readWorkspaceXml(sequenceXmlPath); contextLines.push(`\nSequence implementation XML (Synapse configuration):\n${xml}`); } catch { /* file unreadable — skip */ } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/rpc-managers/ai-features/rpc-manager.ts` around lines 906 - 948, The code reads apiXmlPath and sequenceXmlPath directly from the RPC payload and can disclose arbitrary local files; update the read logic around apiXmlPath and sequenceXmlPath to: resolve the incoming path with path.resolve, ensure the resolved path has a .xml extension, verify it is inside this.projectUri (e.g. by computing path.relative(this.projectUri, resolved) and rejecting if it starts with '..' or is absolute outside the project), and only then read and truncate into contextLines (respecting MAX_XML_CHARS); leave existing variable names (apiXmlPath, sequenceXmlPath, MAX_XML_CHARS, contextLines) and error handling in place so callers like getAnthropicClient/generateText are unchanged.workspaces/mi/mi-extension/src/rpc-managers/mi-diagram/rpc-manager.ts-815-827 (1)
815-827:⚠️ Potential issue | 🟠 Major | ⚡ Quick winKeep the published swagger name consistent with the file you now write.
This block always saves the definition as
${fileName}.yaml, but the generated publish path and the artifact.xml entry still come fromgetSwaggerName(swaggerDefPath). For.json/.ymlinputs, the API can end up referencing a.json/.ymlresource that was never written.Suggested fix
- const getSwaggerName = (swaggerDefPath: string) => { - const ext = path.extname(swaggerDefPath); - return `${name}${apiVersion !== "" ? `_v${apiVersion}` : ''}${ext === ".yml" ? ".yaml" : ext }`; - }; + const getSwaggerName = (swaggerDefPath: string) => { + const ext = path.extname(swaggerDefPath).toLowerCase(); + const normalizedExt = + ext === ".json" || ext === ".yml" || ext === ".yaml" ? ".yaml" : ext; + return `${name}${apiVersion !== "" ? `_v${apiVersion}` : ''}${normalizedExt}`; + };Also applies to: 830-833
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/rpc-managers/mi-diagram/rpc-manager.ts` around lines 815 - 827, The code writes converted JSON/YML inputs to a fixed `${fileName}.yaml` (swaggerRegPath) but later uses getSwaggerName(swaggerDefPath) for the published name, causing mismatches; update the logic so the published swagger name always matches what you write: compute a single swaggerFileName (e.g., use getSwaggerName(swaggerDefPath) then if ext is ".json" or ".yml" replace its extension with ".yaml" or alternatively set swaggerFileName = fileName + ".yaml" and use that value everywhere), use that swaggerFileName when building swaggerRegPath and when generating the publish path / artifact.xml entry, and keep parse/stringify/copyFileSync behavior unchanged (refer to variables swaggerDefPath, fileName, swaggerRegPath and function getSwaggerName).workspaces/mi/mi-extension/src/rpc-managers/mi-diagram/rpc-manager.ts-6817-6843 (1)
6817-6843:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPreserve existing inbound endpoint flags when applying MCP edits.
getInboundEndpoint()gives you the currenttraceandstatisticsvalues, but this rewrite drops both fromattributes. Updating only port/CORS will silently clear those persisted settings on the inbound endpoint.Suggested fix
const attributes: Record<string, string | number | boolean> = { name: current.name, type: current.type, sequence: current.sequence ?? '', onError: current.errorSequence ?? '', suspend: current.suspend, + trace: current.trace, + statistics: current.statistics, ...(endpointClass && { class: endpointClass }), };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/rpc-managers/mi-diagram/rpc-manager.ts` around lines 6817 - 6843, The current rewrite of the inbound endpoint drops persisted flags (trace and statistics); when building attributes for getInboundEndpointXmlWrapper you must copy trace and statistics from the existing inbound endpoint returned by getInboundEndpoint() into the attributes object (e.g., include ...(current.trace !== undefined && { trace: current.trace }) and ...(current.statistics !== undefined && { statistics: current.statistics })), keeping the existing endpointClass handling and other fields, then generate the xml with getInboundEndpointXmlWrapper and call replaceFullContentToFile as before.workspaces/mi/mi-extension/src/util/fileOperations.ts-613-624 (1)
613-624:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
deleteApiMetadatacan surface unhandled promise rejections on deletion failures.Line 613 defines this as
async, but Line 622 usesfs.unlinkSync. If unlink throws, the function returns a rejected promise, and current caller usage is fire-and-forget. This can leak unhandled rejections in the extension host. Make this function synchronous (or catch internally) to keep failure handling deterministic.Suggested fix
-export async function deleteApiMetadata(apiPath: string) { +export function deleteApiMetadata(apiPath: string): void { + try { const projectRoot = workspace.getWorkspaceFolder(Uri.file(apiPath))?.uri.fsPath; if (!projectRoot) { return; @@ const metadataFilePath = path.join(projectRoot, 'src', 'main', 'wso2mi', 'resources', 'metadata', metadataFileName); if (fs.existsSync(metadataFilePath)) { fs.unlinkSync(metadataFilePath); } + } catch (error) { + console.error(`Failed to delete API metadata for ${apiPath}:`, error); + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/util/fileOperations.ts` around lines 613 - 624, The async function deleteApiMetadata can throw an unhandled rejection when fs.unlinkSync fails; make failure deterministic by either removing the async keyword and keeping synchronous behavior, or catch errors inside the function. Locate deleteApiMetadata and wrap the metadata deletion (the fs.existsSync / fs.unlinkSync block) in a try-catch that logs/handles the error, or convert to fs.unlink with a callback/promisified API and handle the error before returning; ensure callers no longer receive an unhandled rejected promise.workspaces/mi/mi-visualizer/src/views/Forms/InboundEPform/index.tsx-176-177 (1)
176-177:⚠️ Potential issue | 🟠 Major | ⚡ Quick winThe store-connector download flow assumes the connector is already installed locally.
selectStoreConnectordereferences.idbefore checking whether a local connector exists, so clicking a store-only connector throws instead of showing the download prompt.handleAcceptDownloadrepeats the same assumption before the download runs, so the follow-up schema load still uses stale local state. Branch on a missing local entry first, callrequiresDownload(connector)in that case, and afteracceptDownload(...)refresh local inbound connectors before resolving the newid.Suggested fix
const selectStoreConnector = async (connector: any) => { - const connectorId = localConnectors.find((c: any) => c.name === connector.connectorName).id; - const response = await rpcClient.getMiDiagramRpcClient().getInboundEPUischema({ connectorName: connectorId }); + const localEntry = localConnectors.find((c: any) => c.name === connector.connectorName); + if (!localEntry) { + requiresDownload(connector); + return; + } + + const response = await rpcClient.getMiDiagramRpcClient().getInboundEPUischema({ connectorName: localEntry.id }); if (response?.uiSchema) { setConnectorSchema(response?.uiSchema); } else { requiresDownload(connector); } } const handleAcceptDownload = () => { - const connectorId = localConnectors.find((c: any) => c.name === inboundOnconfirmation.connectorName).id; acceptDownload(async () => { - const schema = await rpcClient.getMiDiagramRpcClient().getInboundEPUischema({ connectorName: connectorId }); + const refreshed = await rpcClient.getMiDiagramRpcClient().getLocalInboundConnectors(); + const localEntry = refreshed["inbound-connector-data"]?.find( + (c: any) => c.name === inboundOnconfirmation.connectorName + ); + if (!localEntry) { + throw new Error(`Inbound connector "${inboundOnconfirmation.connectorName}" was not installed`); + } + + setLocalConnectors( + refreshed["inbound-connector-data"]?.filter( + (connector: any) => !HIDDEN_INBOUND_CONNECTORS.test(connector.name) + ) + ); + + const schema = await rpcClient.getMiDiagramRpcClient().getInboundEPUischema({ + connectorName: localEntry.id + }); setConnectorSchema(schema?.uiSchema); }); };Also applies to: 226-231
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/InboundEPform/index.tsx` around lines 176 - 177, selectStoreConnector and handleAcceptDownload currently dereference local connector .id before verifying existence, causing exceptions for store-only connectors; change both to first check whether localConnectors.find(...) returns a value and if not call requiresDownload(connector) and prompt download, and after acceptDownload(...) refresh the local inbound connectors list (e.g., re-fetch into localConnectors) before using its .id; then pass the refreshed id into rpcClient.getMiDiagramRpcClient().getInboundEPUischema({ connectorName: connectorId }) so the schema load uses the newly installed connector. Ensure the same guard/fetch refresh is applied to the other block around the lines referenced (the follow-up schema load at ~226-231).workspaces/mi/mi-visualizer/src/Hooks.tsx-54-56 (1)
54-56:⚠️ Potential issue | 🟠 MajorMove the download-progress listener registration out of render and into
useEffect.
workspaces/mi/mi-visualizer/src/Hooks.tsxregistersrpcClient.onDownloadProgress(...)directly in the hook body (Lines 54-56), so it runs on every render. SinceRpcClient.onDownloadProgressjust forwards tomessenger.onNotification(...)and doesn’t surface an unsubscribe/disposer, this should be registered once inuseEffectand cleaned up on unmount (using the messenger’s unsubscribe/disposer API if available).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/Hooks.tsx` around lines 54 - 56, The download-progress listener is being registered on every render because rpcClient.onDownloadProgress((data: DownloadProgressData) => setDownloadProgress(data)) is called in the hook body; move this registration into a useEffect so it runs once and is cleaned up on unmount. Wrap the rpcClient.onDownloadProgress call inside useEffect with an empty dependency array (or include rpcClient if it can change), capture the returned unsubscribe/disposer from the messenger or rpc client (if available) and call it in the effect cleanup, and keep the handler using setDownloadProgress to update state.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/ToolsList.tsx-81-93 (1)
81-93:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHandle RPC failures from schema conversion to avoid unhandled rejections.
convertMcpJsonSchemais awaited withouttry/catchin both validation and save paths. A transport/backend failure can break the dialog flow and leave stale state.💡 Suggested fix
const validateSchema = async (value: string): Promise<boolean> => { if (!value.trim()) { setSchemaError(null); return true; } - const { schema } = await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: value }); - if (schema === null) { - setSchemaError(INVALID_MCP_SCHEMA_MESSAGE); - return false; - } - setSchemaError(null); - return true; + try { + const { schema } = await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: value }); + if (schema === null) { + setSchemaError(INVALID_MCP_SCHEMA_MESSAGE); + return false; + } + setSchemaError(null); + return true; + } catch { + setSchemaError('Schema validation failed. Please try again.'); + return false; + } }; const saveEdit = async () => { if (!editingTool) return; if (schemaError) return; - - const normalizedSchema = editToolInputSchema.trim() - ? (await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: editToolInputSchema })).schema - : null; + let normalizedSchema: string | null = null; + try { + normalizedSchema = editToolInputSchema.trim() + ? (await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: editToolInputSchema })).schema + : null; + } catch { + setSchemaError('Schema validation failed. Please try again.'); + return; + }Also applies to: 95-101
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/ToolsList.tsx` around lines 81 - 93, The validateSchema function (and the similar save/submit path that calls rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema) must guard against transport/backend failures: wrap the await rpc call in a try/catch, on error call setSchemaError with a clear RPC-failure message (or error.message) and return false, and optionally log the error to avoid leaving stale state or unhandled rejections; ensure both validateSchema and the save handler use the same try/catch pattern around convertMcpJsonSchema to consistently clear or set schema errors and return false on failure.workspaces/mi/mi-visualizer/src/views/Forms/TaskForm.tsx-267-270 (1)
267-270:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse a minimum-version gate for
startOnLoad, not exact-match only.At Line 269,
=== 0enables support only for runtime4.1.0and disables it for newer versions (e.g.,4.4.0), which breaks the intended feature gating.💡 Suggested fix
- setIsStartOnLoadSupported(compareVersions(runtimeVersion, RUNTIME_VERSION_410) === 0); + setIsStartOnLoadSupported(compareVersions(runtimeVersion, RUNTIME_VERSION_410) >= 0);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/TaskForm.tsx` around lines 267 - 270, The gating currently uses compareVersions(runtimeVersion, RUNTIME_VERSION_410) === 0 which only allows an exact match to RUNTIME_VERSION_410; change the check to allow runtimeVersion >= RUNTIME_VERSION_410 (e.g., compareVersions(...) >= 0) so setIsStartOnLoadSupported is enabled for 4.1.0 and any newer compatible runtimes; update the code around getProjectDetails()/runtimeVersion and RUNTIME_VERSION_410 to use the >=0 comparison.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/ToolsList.tsx-99-106 (1)
99-106:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAllow users to clear
inputSchemainstead of restoring the previous value.At Line 105,
inputSchema: normalizedSchema || t.inputSchemarestores the old schema when the edit field is intentionally cleared, so schema removal is impossible.💡 Suggested fix
- const normalizedSchema = editToolInputSchema.trim() - ? (await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: editToolInputSchema })).schema - : null; + const hasSchemaInput = editToolInputSchema.trim().length > 0; + const normalizedSchema = hasSchemaInput + ? (await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: editToolInputSchema })).schema + : null; const updatedTools = tools.map(t => { if (t.id !== editingTool.id) return t; - return { ...t, name: editToolName.trim() || t.name, description: editToolDescription, inputSchema: normalizedSchema || t.inputSchema }; + return { + ...t, + name: editToolName.trim() || t.name, + description: editToolDescription, + inputSchema: hasSchemaInput ? normalizedSchema : null + }; });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/ToolsList.tsx` around lines 99 - 106, The current update merges tools using inputSchema: normalizedSchema || t.inputSchema which prevents clearing the schema because a falsy normalizedSchema falls back to the previous value; change that logic so inputSchema is explicitly set based on the edit input: if editToolInputSchema.trim() is non-empty use normalizedSchema, otherwise set inputSchema to null (thus allowing removal). Update the tools.map update (the updatedTools block that checks t.id === editingTool.id) to use this conditional so edits that clear editToolInputSchema remove the stored schema instead of restoring t.inputSchema.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/AddSequenceToolDialog.tsx-200-213 (1)
200-213:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDon't downgrade a failed schema conversion to
EMPTY_MCP_SCHEMA.If
convertMcpJsonSchema()returnsnullhere, the submit path still falls back toEMPTY_MCP_SCHEMA, so the tool is created without the schema the user entered. Surface the validation error and abort submission for that item instead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/AddSequenceToolDialog.tsx` around lines 200 - 213, In AddSequenceToolDialog where you build `selected` (the Promise.all mapping), stop falling back to `EMPTY_MCP_SCHEMA` when `convertMcpJsonSchema()` returns null/invalid: if `converted` is null/undefined treat that as a validation failure for that `sequenceId` (or `customName`) and abort the submission path instead of assigning `EMPTY_MCP_SCHEMA`; implement this by checking the `converted` value after the RPC call and either throw a descriptive error (to reject the Promise and prevent submit) or add the error to the component’s validation state so the submit is blocked and the user sees the conversion error — do not silently replace with `EMPTY_MCP_SCHEMA`. Ensure you reference `convertMcpJsonSchema`, the `selected` mapping logic, and `EMPTY_MCP_SCHEMA` when making the change.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/AddSequenceToolDialog.tsx-110-121 (1)
110-121:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAsync schema validation races in both MCP tool dialogs.
Both dialogs call
convertMcpJsonSchema()directly fromonChange, so late responses can overwrite validation state for newer text. Debounce these requests or tag them and ignore stale completions in both places.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/AddSequenceToolDialog.tsx` around lines 110 - 121, The validateSchema function currently calls rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema() directly from onChange, causing race conditions where late responses can overwrite newer validation state; modify validateSchema (and the equivalent validator in the other MCP tool dialog) to either debounce calls or attach a per-call token/sequence id: capture a unique request id before calling convertMcpJsonSchema(), and when the Promise resolves only apply setError/clearErrors if the id matches the latest stored token for that input (or use a short debounce window around onChange to avoid firing every keystroke). Ensure you update the logic around validateSchema and any onChange handlers that call convertMcpJsonSchema() so stale responses are ignored.workspaces/mi/mi-visualizer/src/views/Forms/InboundEPform/ImportInboundConnector.tsx-43-47 (1)
43-47:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHandle both popup and non-popup completion paths, and invoke provided callbacks.
onImportSuccessandhandlePopupCloseare part of the component contract but never used; success/cancel currently only close whenisPopupis true. This makes non-popup usage a no-op on close/finish and can break parent flow expectations.Suggested fix
export function ImportInboundConnectorForm(props: ImportInboundConnectorFormProps) { @@ if (response.success) { - rpcClient.getMiVisualizerRpcClient().openView({ - type: POPUP_EVENT_TYPE.CLOSE_VIEW, - location: { view: null, recentIdentifier: "success" }, - isPopup: true - }); + props.onImportSuccess?.(); + if (props.isPopup) { + rpcClient.getMiVisualizerRpcClient().openView({ + type: POPUP_EVENT_TYPE.CLOSE_VIEW, + location: { view: null, recentIdentifier: "success" }, + isPopup: true + }); + } else { + props.handlePopupClose?.(); + } @@ const handleCancel = () => { if (props.isPopup) { rpcClient.getMiVisualizerRpcClient().openView({ type: POPUP_EVENT_TYPE.CLOSE_VIEW, location: { view: null, recentIdentifier: "cancel" }, isPopup: true }); + } else { + props.handlePopupClose?.(); } }Also applies to: 66-71, 83-91
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/InboundEPform/ImportInboundConnector.tsx` around lines 43 - 47, The ImportInboundConnector component currently only closes popup flows; update its success and cancel/close handlers so they call the provided callbacks: always call onImportSuccess() from the import/finish success handler (regardless of isPopup) and, when closing/canceling, call handlePopupClose() if provided (do this regardless of isPopup so non-popup parents get notified). Locate the success/finish handler and the cancel/close handler inside the ImportInboundConnector component (referencing ImportInboundConnectorFormProps, onImportSuccess, handlePopupClose, and isPopup) and add the appropriate calls and null-checks for the callbacks.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/AddAPIToolDialog.tsx-325-334 (1)
325-334:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReject invalid schema conversion during submit instead of silently replacing it with empty schema.
If
convertMcpJsonSchemareturnsschema: null, the current code still submits usingEMPTY_MCP_SCHEMAviaconverted || EMPTY_MCP_SCHEMA. That accepts invalid user input as a valid empty schema.Suggested fix
- let converted: string | null = null; + let converted: string | null = null; if (raw) { const { schema } = await rpcClient.getMiDiagramRpcClient().convertMcpJsonSchema({ input: raw }); - converted = schema; + if (schema === null) { + setError(`items.${opId}.inputSchema` as const, { message: INVALID_MCP_SCHEMA_MESSAGE }); + throw new Error(`Invalid schema for operation ${opId}`); + } + converted = schema; } return { @@ - inputSchema: converted || EMPTY_MCP_SCHEMA, + inputSchema: converted ?? EMPTY_MCP_SCHEMA, }; }]; }).map(fn => fn()));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/AddAPIToolDialog.tsx` around lines 325 - 334, The submit path currently treats a null conversion result as valid by falling back to EMPTY_MCP_SCHEMA; change it so that after calling getMiDiagramRpcClient().convertMcpJsonSchema({ input: raw }) you explicitly check whether schema is null/invalid and abort/raise a validation error instead of using EMPTY_MCP_SCHEMA (e.g., return/throw a user-facing error or set form error state), referencing convertMcpJsonSchema and the surrounding submit logic in AddAPIToolDialog so the form refuses to submit when converted === null and prompts the user to fix the input.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/index.tsx-63-67 (1)
63-67:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce valid TCP port bounds in schema.
Line [63-67] currently accepts any integer, so invalid values (e.g.,
0,70000) can pass client validation and be written intoinbound.mcp.port/inbound.http.portat Line [197-198], producing unusable config.Suggested fix
port: yup.number() .typeError('Port must be a number') .required('Port is required') - .integer('Port must be an integer'), + .integer('Port must be an integer') + .min(1, 'Port must be between 1 and 65535') + .max(65535, 'Port must be between 1 and 65535'),Also applies to: 197-198
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/index.tsx` around lines 63 - 67, The port schema currently allows any integer; update the Yup validation for port in MCPServerForm (the port field in index.tsx) to enforce TCP bounds by adding .min(1, 'Port must be between 1 and 65535') and .max(65535, 'Port must be between 1 and 65535') to the existing yup.number() chain so invalid values like 0 or 70000 are rejected before they can be written to inbound.mcp.port / inbound.http.port.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/index.tsx-179-209 (1)
179-209:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftAvoid partial writes when the second artifact creation fails.
If
createLocalEntrysucceeds butcreateInboundEndpointfails, the project is left in a partial state (orphaned local entry) with no rollback path. This creates cross-artifact inconsistency.Also applies to: 219-221
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/index.tsx` around lines 179 - 209, The current flow calls createLocalEntry then createInboundEndpoint, leaving an orphaned local entry if createInboundEndpoint fails; wrap the two calls so they are atomic: after successfully calling createLocalEntry (rpcClient.getMiDiagramRpcClient().createLocalEntry) perform createInboundEndpoint inside a try/catch and on any error call the corresponding cleanup RPC to remove the created entry (e.g., rpcClient.getMiDiagramRpcClient().deleteLocalEntry or equivalent) to rollback, then rethrow or propagate the original error; alternatively reverse the order (createInboundEndpoint then createLocalEntry) if safe, but ensure you add compensating cleanup in both success/failure paths (same for the other occurrences around lines 219-221).workspaces/mi/mi-extension/src/util/mcp-server-utils.ts-89-104 (1)
89-104:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGuard
$refdereferencing against recursive cycles.
derefSchemahas unbounded recursion. A cyclic reference graph can cause stack overflow and terminate this flow.Suggested fix
-function derefSchema(spec: any, schema: any): any { +function derefSchema(spec: any, schema: any, seen = new Set<any>()): any { if (!schema || typeof schema !== "object") return schema; + if (seen.has(schema)) return schema; + seen.add(schema); if (schema.$ref) { const resolved = resolveRef(spec, schema.$ref); - return resolved ? derefSchema(spec, resolved) : schema; + return resolved ? derefSchema(spec, resolved, seen) : schema; } if (schema.allOf) { return schema.allOf.reduce((acc: any, s: any) => { - const resolved = derefSchema(spec, s); + const resolved = derefSchema(spec, s, seen); return { ...acc, properties: { ...acc.properties, ...resolved?.properties }, required: [...(acc.required || []), ...(resolved?.required || [])], }; }, { type: "object", properties: {} }); } return schema; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/util/mcp-server-utils.ts` around lines 89 - 104, The derefSchema function can recurse infinitely on cyclic $ref graphs; modify derefSchema to accept or create a visited set (e.g., Set<string>) of resolved reference keys and check this set before calling resolveRef/derefSchema again: when encountering a schema.$ref, compute a unique ref id (schema.$ref or resolved pointer), if it's already in visited return the original schema (or a safe placeholder) to break the cycle, otherwise add it to visited, resolve via resolveRef and recurse, and remove from visited on return; apply the same visited-guard when processing schema.allOf entries so derefSchema and resolveRef use the visited set to avoid stack overflows.workspaces/mi/mi-extension/src/util/mcp-server-utils.ts-122-130 (1)
122-130:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInclude path-level parameters when building API tool input schemas.
extractInputSchemacurrently reads onlyoperation.parameters, so shared params declared at the path-item level are silently dropped. This can generate incomplete MCP tool schemas and break valid calls downstream.Suggested fix
- if (Array.isArray(operation.parameters)) { - for (const param of operation.parameters) { + const mergedParameters = [ + ...(Array.isArray(pathItem.parameters) ? pathItem.parameters : []), + ...(Array.isArray(operation.parameters) ? operation.parameters : []), + ]; + for (const param of mergedParameters) { if ((param.in === "path" || param.in === "query") && param.name && param.schema) { const paramSchema = derefSchema(spec, param.schema); properties[param.name] = { ...paramSchema, ...(param.description ? { description: param.description } : {}) }; if (param.required) required.push(param.name); } - } - } + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/util/mcp-server-utils.ts` around lines 122 - 130, extractInputSchema only iterates operation.parameters, so path-level parameters are omitted; update the logic to merge path-item parameters with operation.parameters (e.g., start from [...(pathItem?.parameters||[]), ...(operation.parameters||[])]) before the Array.isArray check, deduplicate by parameter name+in with operation-level entries taking precedence, and then call derefSchema for each param and populate properties and required as the current loop does (referencing operation.parameters, pathItem.parameters, derefSchema, properties, required).
🟡 Minor comments (7)
workspaces/mi/mi-extension/src/ai-features/agent-mode/attachment-utils.ts-96-108 (1)
96-108:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlign image validation with the new raw-base64 fallback path.
toImageContentPart(...)accepts raw base64 fallback, butvalidateAttachments(...)still rejects anything that is not a data URI. This makes the fallback path unreachable for validated inputs.Suggested fix
if (images && images.length > 0) { for (const image of images) { - if (!isValidImageDataUri(image.imageBase64)) { + const isDataUri = isValidImageDataUri(image.imageBase64); + const isRawBase64 = isValidBase64(image.imageBase64); + if (!isDataUri && !isRawBase64) { warnings.push(`Invalid image format: ${image.imageName}`); } } }Also applies to: 199-203
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/ai-features/agent-mode/attachment-utils.ts` around lines 96 - 108, The image converter toImageContentPart supports both data-URI and raw base64, but validateAttachments still rejects non-data-URI images, making the raw-base64 path unreachable; update validateAttachments (and the other validation block that mirrors it around validateAttachments usage) to accept either a data URI matching /^data:[^;]+;base64,[\s\S]+$/ or a raw base64 string (e.g., /^[A-Za-z0-9+/=]+$/ possibly with whitespace) when attachment.type === "image", and ensure the validation error messages reflect both allowed formats so toImageContentPart can be reached for valid raw-base64 inputs.workspaces/mi/mi-extension/src/debugger/debugHelper.ts-439-443 (1)
439-443:⚠️ Potential issue | 🟡 MinorSuppress “build failed” toast on user-initiated stop
disconnectRequest()callsabortBuildAndRun(), which SIGKILLsactiveBuildProcess. The build process still hits the generic non-zero path that unconditionally shows${path.basename(project)} build failedin thebuildProcess.on('close')handler (and similarly rejects withBuild process failed), so user cancellation can surface as a build failure UI. Add a cancellation/abort guard (e.g., flag checked by theclose/exithandlers) so aborted builds are treated as cancellation rather than failure.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/src/debugger/debugHelper.ts` around lines 439 - 443, The build cancellation currently still triggers the generic failure path because abortBuildAndRun() kills activeBuildProcess but does not signal the close/exit handlers; add a cancellation guard: introduce a module-scoped boolean like buildAborted (or similar) that disconnectRequest()/abortBuildAndRun() sets to true before treeKill, have the buildProcess.on('close') and on('exit') handlers check this flag and treat it as a user-cancel (skip showing `${path.basename(project)} build failed` toast and avoid rejecting with `Build process failed`), and reset the flag after handling so subsequent builds behave normally; reference abortBuildAndRun, activeBuildProcess, buildProcess.on('close')/on('exit'), and disconnectRequest to implement this.workspaces/mi/mi-extension/CHANGELOG.md-33-33 (1)
33-33:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winHyphenate the compound adjective in this release note.
Line 33 reads better as “Copilot-created class mediators…”.
✏️ Suggested edit
-Fixed: Copilot created class mediators are not getting packed in the CApp ([`#1631`](https://github.com/wso2/product-integrator/issues/1631)) +Fixed: Copilot-created class mediators are not getting packed in the CApp ([`#1631`](https://github.com/wso2/product-integrator/issues/1631))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-extension/CHANGELOG.md` at line 33, Update the release note string "Fixed: Copilot created class mediators are not getting packed in the CApp" to hyphenate the compound adjective so it reads "Fixed: Copilot-created class mediators are not getting packed in the CApp" (i.e., change "Copilot created" to "Copilot-created").Source: Linters/SAST tools
workspaces/mi/mi-visualizer/src/views/Forms/TaskForm.tsx-113-115 (1)
113-115:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winReset
isStartOnLoadUpdatedwhen loading/resetting form state.
isStartOnLoadUpdatedis set totrueon toggle but never reset during task/path reload flows, so the Save button can stay enabled without current-session edits.💡 Suggested fix
} else { paramConfigs.paramValues = []; setParams(paramConfigs); reset(newTask); setIsNewTask(true); setIsCustomPropsUpdated(false); + setIsStartOnLoadUpdated(false); }Also applies to: 575-575
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/TaskForm.tsx` around lines 113 - 115, When the form is loaded or reset, the flag isStartOnLoadUpdated must be cleared so the Save button reflects current-session edits; update the form initialization/reset logic (where startOnLoad, isStartOnLoadSupported are set — e.g., the task/path load handler or the useEffect that initializes form state) to call setIsStartOnLoadUpdated(false) alongside setting startOnLoad and setIsStartOnLoadSupported so the "updated" flag is reset whenever a task or path is reloaded.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/MCPServerToolsForm.tsx-95-98 (1)
95-98:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd port range validation.
The port validation only checks that it's a number and an integer, but doesn't enforce the valid TCP port range (1-65535). Invalid ports like 0, -1, or 70000 would pass validation but fail at runtime.
🛡️ Proposed fix to add port range validation
port: yup.number() .typeError('Port must be a number') .required('Port is required') - .integer('Port must be an integer'), + .integer('Port must be an integer') + .min(1, 'Port must be between 1 and 65535') + .max(65535, 'Port must be between 1 and 65535'),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/MCPServerToolsForm.tsx` around lines 95 - 98, The port schema currently only enforces type and integer; update the 'port' validation (the yup.number() chain in MCPServerToolsForm.tsx) to enforce the TCP port range by adding .min(1, 'Port must be between 1 and 65535') and .max(65535, 'Port must be between 1 and 65535') (or an equivalent .test(...) with the same message) so values like 0, negative numbers, or >65535 are rejected at validation time.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/MCPServerToolsForm.tsx-213-260 (1)
213-260:⚠️ Potential issue | 🟡 MinorFix
useEffectdependency array to include edit mode data
Inworkspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/MCPServerToolsForm.tsx(lines 213-260), thisuseEffectreferencesisEditModeandeditData(editData.localEntryPath,editData.inboundEndpointPath,editData.tools), but the dependency array is only[rpcClient, props.path]. Add the relevantisEditMode/editDatadependencies (or the specificeditDatafields used) so the effect reruns when the editing context changes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/MCPServerToolsForm.tsx` around lines 213 - 260, The useEffect that defines loadData references isEditMode and editData (including editData.localEntryPath, editData.inboundEndpointPath, and editData.tools) but only lists [rpcClient, props.path] in its dependency array, so it won't re-run when the editing context changes; update the dependency array of the useEffect to include isEditMode and the relevant editData fields (or editData as a whole) so loadData re-executes when those change — i.e., ensure the effect dependencies include isEditMode and editData (or editData.localEntryPath, editData.inboundEndpointPath, editData.tools) while keeping rpcClient and props.path to correctly refresh setTools, setResolvedInboundPath, setValue/setOriginalPort, setCorsSettings/setOriginalCorsSettings, and setUsedPorts.workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/index.tsx-124-142 (1)
124-142:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPort discovery failure currently leads to a dead-end form state.
On discovery failure, Line [226] keeps the form busy via
!!portDiscoveryError, and there is no in-view retry action in the main form branch. Users can get blocked from progressing unless they close/reopen.Also applies to: 226-227, 312-312
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@workspaces/mi/mi-visualizer/src/views/Forms/MCPServerForm/index.tsx` around lines 124 - 142, The port discovery error leaves the form blocked because the UI treats portDiscoveryError as a busy gate; change loadUsedPorts (used in the useEffect) so that on catch it still clears loading and sets usedPorts to an empty Set (setUsedPorts(new Set())) and preserves portDiscoveryError for display, and add an in-form retry action that calls loadUsedPorts (expose loadUsedPorts or wrap it in a stable callback) so the main form branch no longer disables progress based on !!portDiscoveryError but instead shows an inline error + Retry button that re-invokes loadUsedPorts and clears portDiscoveryError on retry (use setPortDiscoveryError(null) at retry start).
| "jsonix": "3.0.0", | ||
| "lodash": "4.17.23", | ||
| "axios": "1.15.2", | ||
| "axios": "1.16.0", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if axios 1.16.0 exists on npm
echo "=== Checking axios 1.16.0 availability ==="
npm view axios@1.16.0 version 2>/dev/null || echo "Version not found"
# Check for security advisories
echo "=== Checking security advisories ==="
gh api graphql -f query='
{
securityVulnerabilities(first: 10, ecosystem: NPM, package: "axios") {
nodes {
advisory {
summary
severity
publishedAt
}
vulnerableVersionRange
firstPatchedVersion {
identifier
}
}
}
}'Repository: wso2/vscode-extensions
Length of output: 341
Fix axios version: “1.16.0” appears missing and security check can’t run
workspaces/api-designer/api-designer-extension/package.json(line 126) setsaxiosto"1.16.0", butnpm view axios@1.16.0returns “Version not found” (would likely break installs).- The GitHub
securityVulnerabilitiesGraphQL query fails withRequires authentication (HTTP 401); use an unauthenticated advisory source (e.g., OSV/npm audit) for the security scan.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@workspaces/api-designer/api-designer-extension/package.json` at line 126, The
package.json entry for the axios dependency currently pins "axios": "1.16.0"
which is a non-existent version—update the "axios" dependency value to a valid
published version (query via npm view or use a known stable 1.x version) in the
package.json "axios" field so installs won't fail, and replace the GitHub
GraphQL "securityVulnerabilities" check (which fails with HTTP 401) with an
unauthenticated advisory source such as OSV or npm audit for the security scan
invocation so the vulnerability scan runs without GitHub auth.
This PR syncs changes from stable/mi to the main branch.
Automated PR created by GitHub Actions.
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores
axios,webpack-dev-server,hono, andtmp.