Add new agent application template to create agent applications#9597
Add new agent application template to create agent applications#9597ranuka-laksika wants to merge 3 commits intowso2:masterfrom
Conversation
📝 WalkthroughWalkthroughAdds Agent Application support, a new two-step Add Agent wizard capturing IsUserServingAgent, updates agent models with IsUserServingAgent and applicationClientId, fetches/displays OAuth client ID for user-serving agents, and registers an Agent Application template and related UI config flags. Changes
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 warning)
✅ Passed checks (2 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
features/admin.extensions.v1/configs/application.tsx (1)
429-511:⚠️ Potential issue | 🟠 MajorAdd missing
agent-applicationentry togetAllowedGrantTypesmap.The
agent-applicationtemplate exists and is documented as using OAuth2 client credentials flow, but is missing from thegetAllowedGrantTypesconfiguration. Without this entry, the protocol settings UI will show all grant types as available, rather than restricting toCLIENT_CREDENTIALS_GRANTonly.Add the following entry after the
m2m-applicationblock:[ "m2m-application" ]: [ ApplicationManagementConstants.CLIENT_CREDENTIALS_GRANT ], + [ "agent-application" ]: [ + ApplicationManagementConstants.CLIENT_CREDENTIALS_GRANT + ],
🤖 Fix all issues with AI agents
In
`@features/admin.applications.v1/data/application-templates/templates/agent-application/agent-application.json`:
- Line 7: The template's authenticationProtocol is empty which can break
protocol-specific UI; update the JSON field "authenticationProtocol" in the
agent application template to "oidc" so it matches the extensions copy and the
OAuth2 client credentials intent, ensuring the ExtensionsManager merge or
application-templates-config.ts import won't leave a blank protocol and OIDC
forms render correctly.
In
`@features/admin.extensions.v1/application-templates/templates/agent-application/agent-application.json`:
- Around line 1-18: The two agent-application template JSONs diverge on fields
"authenticationProtocol", "grant_type", and presence of "subTemplates" which
causes confusing overrides when lodash merge() in
application-templates-config.ts combines templates; fix by either making the
extension template explicitly mirror the base (add "subTemplates": [], remove or
set "authenticationProtocol" and "grant_type" to the same values as base) or add
clear comments in both JSONs documenting that the extension intentionally
overrides "authenticationProtocol" to "oidc" and sets an empty "grant_type"
while omitting "subTemplates"; update the extension file accordingly and ensure
the intended behavior is described near the template metadata so reviewers
understand the deliberate differences.
🧹 Nitpick comments (1)
features/admin.agents.v1/components/wizards/add-agent-wizard.tsx (1)
68-75: Prefer??over||for boolean default, and considerOwnerfield placement.Line 73:
values?.isUserServingAgent || false— while functionally correct here,??is the idiomatic nullish coalescing operator for defaultingundefined/nulltofalsewithout accidentally coercing other falsy values.Suggested fix
- IsUserServingAgent: values?.isUserServingAgent || false + IsUserServingAgent: values?.isUserServingAgent ?? false
| "name": "Agent Application", | ||
| "description": "Application auto-created for AI agents using OAuth2 client credentials.", | ||
| "image": "m2m", | ||
| "authenticationProtocol": "", |
There was a problem hiding this comment.
Empty authenticationProtocol may cause protocol resolution issues.
This file sets "authenticationProtocol": "" while the extensions copy sets "oidc". This template is imported directly by application-templates-config.ts as the base resource. If the ExtensionsManager merge doesn't override this field, the empty value could prevent correct protocol-specific UI (e.g., OIDC form rendering) from loading. Consider setting this to "oidc" to match the extensions version and the OAuth2 client credentials intent.
Suggested fix
- "authenticationProtocol": "",
+ "authenticationProtocol": "oidc",📝 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.
| "authenticationProtocol": "", | |
| "authenticationProtocol": "oidc", |
🤖 Prompt for AI Agents
In
`@features/admin.applications.v1/data/application-templates/templates/agent-application/agent-application.json`
at line 7, The template's authenticationProtocol is empty which can break
protocol-specific UI; update the JSON field "authenticationProtocol" in the
agent application template to "oidc" so it matches the extensions copy and the
OAuth2 client credentials intent, ensuring the ExtensionsManager merge or
application-templates-config.ts import won't leave a blank protocol and OIDC
forms render correctly.
| { | ||
| "id": "agent-application", | ||
| "templateId": "agent-application", | ||
| "name": "Agent Application", | ||
| "description": "Application auto-created for AI agents using OAuth2 client credentials.", | ||
| "image": "m2m", | ||
| "authenticationProtocol": "oidc", | ||
| "category": "DEFAULT", | ||
| "displayOrder": -1, | ||
| "self": "", | ||
| "subTemplatesSectionTitle": "", | ||
| "templateGroup": "", | ||
| "grant_type":"", | ||
| "types": [ | ||
| "oauth2" | ||
| ], | ||
| "application": null | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all agent-application.json files in the repository
echo "=== Searching for all agent-application.json files ==="
fd "agent-application.json" --type f
echo ""
echo "=== Comparing contents ==="
# Read both files if they exist
FILE1="features/admin.extensions.v1/application-templates/templates/agent-application/agent-application.json"
FILE2="features/admin.applications.v1/data/application-templates/templates/agent-application/agent-application.json"
if [ -f "$FILE1" ]; then
echo "File 1: $FILE1"
cat "$FILE1" | jq . 2>/dev/null || cat "$FILE1"
else
echo "File 1 NOT FOUND: $FILE1"
fi
echo ""
if [ -f "$FILE2" ]; then
echo "File 2: $FILE2"
cat "$FILE2" | jq . 2>/dev/null || cat "$FILE2"
else
echo "File 2 NOT FOUND: $FILE2"
fiRepository: wso2/identity-apps
Length of output: 1457
🏁 Script executed:
#!/bin/bash
# Search for ExtensionsManager implementation
echo "=== Finding ExtensionsManager ==="
fd -t f "ExtensionsManager" --extension ts --extension tsx --extension js
echo ""
echo "=== Searching for ExtensionsManager in source ==="
rg "ExtensionsManager" --type ts --type tsx -A 5 -B 2 | head -100
echo ""
echo "=== Searching for merge or template resolution logic ==="
rg "agent-application" --type json | head -20
echo ""
echo "=== Searching for template merge logic ==="
rg "merge.*template\|template.*merge" -i --type ts --type tsx | head -20Repository: wso2/identity-apps
Length of output: 883
🏁 Script executed:
#!/bin/bash
# Search for template loading/merging logic more broadly
echo "=== Searching for template file imports ==="
rg "agent-application\.json" -A 3 -B 3
echo ""
echo "=== Searching for template loading functions ==="
rg "loadTemplate\|getTemplate\|mergeTemplate" -i --type ts | head -30
echo ""
echo "=== Searching for extension handling ==="
rg "extension.*template\|template.*extension" -i --type ts | head -20
echo ""
echo "=== Checking for any merge/deep merge utilities ==="
rg "Object\.assign\|spread.*operator\|\.\.\." -i --type ts --type js | grep -i "template\|config" | head -10
echo ""
echo "=== Looking for application template schema/interface ==="
fd "application.*template" -t f --extension ts | grep -E "(interface|type|model|schema)" | head -10Repository: wso2/identity-apps
Length of output: 1607
🏁 Script executed:
#!/bin/bash
# Read the application-templates-config.ts file
FILE="features/admin.applications.v1/data/application-templates/application-templates-config.ts"
echo "=== Reading $FILE ==="
wc -l "$FILE"
echo ""
cat -n "$FILE" | head -200Repository: wso2/identity-apps
Length of output: 9788
🏁 Script executed:
#!/bin/bash
# Search for any comments explaining why extensions differs from base
echo "=== Checking extensions template directory for README or comments ==="
ls -la features/admin.extensions.v1/application-templates/templates/agent-application/
echo ""
echo "=== Checking base template directory ==="
ls -la features/admin.applications.v1/data/application-templates/templates/agent-application/
echo ""
echo "=== Searching for any documentation or comments about template merging ==="
rg "template.*merge\|merge.*template\|extension.*override" -i --type ts | head -10
echo ""
echo "=== Checking git history for why these fields differ ==="
git log --oneline -n 20 -- "features/admin.extensions.v1/application-templates/templates/agent-application/agent-application.json" 2>/dev/null || echo "Git history not available"Repository: wso2/identity-apps
Length of output: 716
Align or document the intentional differences between the two agent-application.json template files.
This file sets "authenticationProtocol": "oidc" and "grant_type": "", and omits "subTemplates", while the base copy at features/admin.applications.v1/data/application-templates/templates/agent-application/agent-application.json sets "authenticationProtocol": "", omits "grant_type", and includes "subTemplates": [].
These templates are merged via lodash merge() in application-templates-config.ts (line 180), with the extensions version overriding the base. While the merge order is deterministic, the undocumented field differences create maintenance confusion. Either synchronize both files to have consistent field coverage or add comments clarifying which differences are intentional overrides.
🤖 Prompt for AI Agents
In
`@features/admin.extensions.v1/application-templates/templates/agent-application/agent-application.json`
around lines 1 - 18, The two agent-application template JSONs diverge on fields
"authenticationProtocol", "grant_type", and presence of "subTemplates" which
causes confusing overrides when lodash merge() in
application-templates-config.ts combines templates; fix by either making the
extension template explicitly mirror the base (add "subTemplates": [], remove or
set "authenticationProtocol" and "grant_type" to the same values as base) or add
clear comments in both JSONs documenting that the extension intentionally
overrides "authenticationProtocol" to "oidc" and sets an empty "grant_type"
while omitting "subTemplates"; update the extension file accordingly and ensure
the intended behavior is described near the template metadata so reviewers
understand the deliberate differences.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #9597 +/- ##
=======================================
Coverage 55.88% 55.88%
=======================================
Files 42 42
Lines 1020 1020
Branches 247 231 -16
=======================================
Hits 570 570
- Misses 416 450 +34
+ Partials 34 0 -34
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Let's add screenshots/screencasts of the UI to better understand the UX. |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
features/admin.agents.v1/components/wizards/add-agent-wizard.tsx (1)
33-33: 🛠️ Refactor suggestion | 🟠 MajorType
onClosecallback properly instead of usingany.The
onCloseprop should have explicit typing per coding guidelines. Based on usage, it receives eithernull(on cancel) or the augmented agent response.♻️ Proposed fix
+import { AgentScimSchema } from "../../models/agents"; + +interface CreatedAgentResponseInterface extends AgentScimSchema { + isUserServingAgent: boolean; +} + interface AddAgentWizardProps extends IdentifiableComponentInterface { isOpen: boolean; - onClose: any; + onClose: (agent: CreatedAgentResponseInterface | null) => void; }As per coding guidelines: "Never use
any; use proper types orunknownwith type guards."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` at line 33, Replace the loose any typing for the onClose prop with a proper callback signature: update the props interface used by the AddAgentWizard component (e.g., AddAgentWizardProps or the component props inline) so onClose is typed as a function that accepts either the augmented agent response type (AugmentedAgentResponse) or null and returns void — e.g., onClose: (agent: AugmentedAgentResponse | null) => void — and adjust any call sites to match this signature.
🧹 Nitpick comments (6)
features/admin.agents.v1/components/wizards/add-agent-wizard.tsx (4)
56-66: Type handler parameters explicitly instead of usingany.The
handleNextandhandleCreatefunctions useanyfor thevaluesparameter. Define an interface for form values.♻️ Proposed fix
+interface StepOneFormValuesInterface { + name?: string; + description?: string; +} + +interface StepTwoFormValuesInterface { + isUserServingAgent?: boolean; +} + - const handleNext = (values: any) => { + const handleNext = (values: StepOneFormValuesInterface) => { if (!values?.name) { // ... } }; - const handleCreate = (values: any) => { + const handleCreate = (values: StepTwoFormValuesInterface) => { // ... };As per coding guidelines: "Always use explicit type annotations everywhere—do not rely on type inference. Never use
any."Also applies to: 72-106
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` around lines 56 - 66, The handlers handleNext and handleCreate currently accept values: any; define a specific interface (e.g., AddAgentFormValues with fields name: string and description?: string and any other expected fields) and replace the any usages with that type for both handleNext and handleCreate (and any other handlers in the same block), update related state setters (setStepOneValues) typing to use the same interface or a narrowed subset, and ensure any calls or usages match the new type so TypeScript enforces correct shape instead of using any.
41-41: Typedispatchproperly instead of usingany.Use the proper
Dispatchtype from Redux.♻️ Proposed fix
+import { Dispatch } from "redux"; + export default function AddAgentWizard({ isOpen, onClose, [ "data-componentid" ]: componentId }: AddAgentWizardProps) { - const dispatch: any = useDispatch(); + const dispatch: Dispatch = useDispatch();As per coding guidelines: "Never use
any; use proper types orunknownwith type guards."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` at line 41, Replace the untyped "const dispatch: any = useDispatch();" by typing dispatch properly: either use your app-specific AppDispatch type (e.g., export type AppDispatch = typeof store.dispatch and then call useDispatch<AppDispatch>()) or import Redux's Dispatch and narrow it to the expected action types; update the useDispatch invocation (useDispatch<AppDispatch>() or useDispatch<Dispatch<MyActionType>>()) and remove the "any" so dispatch is strongly typed; search for useDispatch and the store export to locate where to add/export AppDispatch and apply it in add-agent-wizard's dispatch declaration.
167-171: Consider using form refs instead of DOM manipulation for submission.Using
document.getElementByIdanddispatchEventto submit forms is fragile and not idiomatic React. Consider using refs and the form'srequestSubmit()method, or restructuring to have the submit button inside the form.♻️ Alternative approach using refs
+import React, { useState, useRef } from "react"; + export default function AddAgentWizard({ // ... }: AddAgentWizardProps) { + const stepOneFormRef = useRef<HTMLFormElement>(null); + const stepTwoFormRef = useRef<HTMLFormElement>(null); // ... - <form id="addAgentStepOneForm" onSubmit={ handleSubmit }> + <form ref={ stepOneFormRef } onSubmit={ handleSubmit }> // ... <Button primary={ true } onClick={ () => { - document - .getElementById("addAgentStepOneForm") - .dispatchEvent(new Event("submit", { bubbles: true, cancelable: true })); + stepOneFormRef.current?.requestSubmit(); } }Also applies to: 213-217
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` around lines 167 - 171, The onClick handler currently uses document.getElementById("addAgentStepOneForm").dispatchEvent(...) which is fragile; replace this DOM manipulation with a React ref for the form (e.g., const formRef = useRef<HTMLFormElement|null>(null)) and call formRef.current?.requestSubmit() from the onClick, or move the submit button inside the form so the native submit occurs; update both occurrences that reference "addAgentStepOneForm" (and the similar handler later in the file) to use the ref-based approach and ensure the form element has ref={formRef}.
96-102: Use i18n translation keys instead of hardcoded error messages.Error messages should use the translation system for localization support.
♻️ Proposed fix
+import { useTranslation } from "react-i18next"; + export default function AddAgentWizard({ // ... }: AddAgentWizardProps) { + const { t } = useTranslation(); // ... .catch((_err: unknown) => { dispatch( addAlert({ - description: "Creating agent failed", + description: t("agents:new.alerts.error.description"), level: AlertLevels.ERROR, - message: "Something went wrong" + message: t("agents:new.alerts.error.message") }) ); })As per coding guidelines: "Use translation keys in the format
<namespace>:<key.path>"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` around lines 96 - 102, Replace the hardcoded alert strings with i18n translation keys and translated values: use the component's i18n hook (e.g., useTranslation or t) to produce the message/description passed to dispatch(addAlert(...)) instead of literal text, and switch the keys to the required format like "admin.agents:addAgent.failedMessage" and "admin.agents:addAgent.failedDescription"; update imports to include the i18n hook if missing and call t(...) for both description and message while leaving AlertLevels.ERROR unchanged.features/admin.agents.v1/pages/agents.tsx (2)
99-159: Consider memoizingfetchApplicationClientIdwithuseCallback.The
fetchApplicationClientIdfunction usesdispatchfrom the component scope. Per coding guidelines, callbacks should be stabilized withuseCallbackto prevent unnecessary re-renders and ensure referential stability.♻️ Proposed refactor
- const fetchApplicationClientId = async (agentUsername: string): Promise<string | null> => { + const fetchApplicationClientId = useCallback(async (agentUsername: string): Promise<string | null> => { try { // ... function body } finally { setIsFetchingClientId(false); } - }; + }, [ dispatch ]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/pages/agents.tsx` around lines 99 - 159, The fetchApplicationClientId function should be memoized with React's useCallback to stabilize the reference because it closes over component scope values like dispatch and setIsFetchingClientId; wrap the existing async function in useCallback and supply a dependency array containing dispatch, setIsFetchingClientId, getApplicationDetails, getInboundProtocolConfig and any other external values used so the callback updates only when those change; ensure you import useCallback and replace the inline declaration of fetchApplicationClientId with the useCallback-wrapped version throughout the component.
48-48: Avoid usinganytype fornewAgentstate.The
newAgentstate should be properly typed instead of usingany. Consider using a union type or extendingAgentScimSchemato include theisUserServingAgentproperty that the wizard attaches.♻️ Proposed fix
+import { AgentScimSchema } from "../models/agents"; + +interface CreatedAgentInterface extends AgentScimSchema { + isUserServingAgent?: boolean; +} + export default function Agents ({ "data-componentid": componentId }: AgentPageProps) { - const [ newAgent, setNewAgent ] = useState<any>(null); + const [ newAgent, setNewAgent ] = useState<CreatedAgentInterface | null>(null);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@features/admin.agents.v1/pages/agents.tsx` at line 48, Replace the useState any for newAgent with a precise type: define a local type or interface (e.g., AgentWithServingFlag) that extends AgentScimSchema and adds isUserServingAgent?: boolean, then change the state declaration from const [newAgent, setNewAgent] = useState<any>(null) to useState<AgentWithServingFlag | null>(null). Update any places that read/write newAgent (wizard handlers that set isUserServingAgent) to satisfy the new type so TypeScript enforces correct shape while keeping null as the initial state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx`:
- Line 23: The import currently pulls FinalForm, FinalFormField,
FormRenderProps, TextFieldAdapter, and CheckboxFieldAdapter from the package's
internal path "@wso2is/form/src"; change the import to use the package's public
entry "@wso2is/form" so the components use the official public exports and avoid
production build issues—update the import statement that references FinalForm,
FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter
accordingly.
In `@features/admin.agents.v1/pages/agents.tsx`:
- Around line 322-323: The comment says the credentials modal should open
immediately but the JSX keeps it closed until fetch finishes; update the modal's
isOpen prop to depend only on isAgentCredentialWizardOpen (e.g.,
isOpen={isAgentCredentialWizardOpen}) so calling
setIsAgentCredentialWizardOpen(true) opens it right away, and rely on the
existing isFetchingClientId prop passed into the modal component to render a
loading state while the clientId is being fetched; adjust any conditional logic
around modal rendering to remove the && !isFetchingClientId guard and keep
fetch-state-driven UI inside the modal (references:
setIsAgentCredentialWizardOpen, isAgentCredentialWizardOpen, isFetchingClientId,
and the modal component's isFetchingClientId prop).
- Around line 115-116: Replace the inline TypeScript suppression: locate the
call to getApplicationDetails(applicationId) where the file uses "// `@ts-ignore`
- Suppressing deprecation warning for valid async use case" and change the
directive to "// `@ts-expect-error`" so the suppression fails if it becomes
unnecessary; keep the existing explanatory comment text and ensure the same
placement immediately above the const application: any = await
getApplicationDetails(applicationId) statement.
- Around line 118-128: The null-check branch for application is unreachable
because getApplicationDetails throws on HTTP errors; remove the dead if
(!application) { ... return null; } block from the component (references:
application, applicationId, dispatch, addAlert) OR replace it by catching
AxiosError around the getApplicationDetails call (in the same async routine that
calls getApplicationDetails) and, if err.response?.status === 404, dispatch the
addAlert with the same message; otherwise rethrow or handle other errors in the
existing catch. Ensure you update only the code that handles the
getApplicationDetails result and its error handling, not other logic.
---
Outside diff comments:
In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx`:
- Line 33: Replace the loose any typing for the onClose prop with a proper
callback signature: update the props interface used by the AddAgentWizard
component (e.g., AddAgentWizardProps or the component props inline) so onClose
is typed as a function that accepts either the augmented agent response type
(AugmentedAgentResponse) or null and returns void — e.g., onClose: (agent:
AugmentedAgentResponse | null) => void — and adjust any call sites to match this
signature.
---
Nitpick comments:
In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx`:
- Around line 56-66: The handlers handleNext and handleCreate currently accept
values: any; define a specific interface (e.g., AddAgentFormValues with fields
name: string and description?: string and any other expected fields) and replace
the any usages with that type for both handleNext and handleCreate (and any
other handlers in the same block), update related state setters
(setStepOneValues) typing to use the same interface or a narrowed subset, and
ensure any calls or usages match the new type so TypeScript enforces correct
shape instead of using any.
- Line 41: Replace the untyped "const dispatch: any = useDispatch();" by typing
dispatch properly: either use your app-specific AppDispatch type (e.g., export
type AppDispatch = typeof store.dispatch and then call
useDispatch<AppDispatch>()) or import Redux's Dispatch and narrow it to the
expected action types; update the useDispatch invocation
(useDispatch<AppDispatch>() or useDispatch<Dispatch<MyActionType>>()) and remove
the "any" so dispatch is strongly typed; search for useDispatch and the store
export to locate where to add/export AppDispatch and apply it in
add-agent-wizard's dispatch declaration.
- Around line 167-171: The onClick handler currently uses
document.getElementById("addAgentStepOneForm").dispatchEvent(...) which is
fragile; replace this DOM manipulation with a React ref for the form (e.g.,
const formRef = useRef<HTMLFormElement|null>(null)) and call
formRef.current?.requestSubmit() from the onClick, or move the submit button
inside the form so the native submit occurs; update both occurrences that
reference "addAgentStepOneForm" (and the similar handler later in the file) to
use the ref-based approach and ensure the form element has ref={formRef}.
- Around line 96-102: Replace the hardcoded alert strings with i18n translation
keys and translated values: use the component's i18n hook (e.g., useTranslation
or t) to produce the message/description passed to dispatch(addAlert(...))
instead of literal text, and switch the keys to the required format like
"admin.agents:addAgent.failedMessage" and
"admin.agents:addAgent.failedDescription"; update imports to include the i18n
hook if missing and call t(...) for both description and message while leaving
AlertLevels.ERROR unchanged.
In `@features/admin.agents.v1/pages/agents.tsx`:
- Around line 99-159: The fetchApplicationClientId function should be memoized
with React's useCallback to stabilize the reference because it closes over
component scope values like dispatch and setIsFetchingClientId; wrap the
existing async function in useCallback and supply a dependency array containing
dispatch, setIsFetchingClientId, getApplicationDetails, getInboundProtocolConfig
and any other external values used so the callback updates only when those
change; ensure you import useCallback and replace the inline declaration of
fetchApplicationClientId with the useCallback-wrapped version throughout the
component.
- Line 48: Replace the useState any for newAgent with a precise type: define a
local type or interface (e.g., AgentWithServingFlag) that extends
AgentScimSchema and adds isUserServingAgent?: boolean, then change the state
declaration from const [newAgent, setNewAgent] = useState<any>(null) to
useState<AgentWithServingFlag | null>(null). Update any places that read/write
newAgent (wizard handlers that set isUserServingAgent) to satisfy the new type
so TypeScript enforces correct shape while keeping null as the initial state.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 47904066-4e40-4ba6-a57e-5c7f0f4fdc8f
📒 Files selected for processing (5)
features/admin.agents.v1/components/edit/agent-secret-show-modal.tsxfeatures/admin.agents.v1/components/wizards/add-agent-wizard.tsxfeatures/admin.agents.v1/models/agents.tsfeatures/admin.agents.v1/pages/agents.tsxfeatures/admin.extensions.v1/configs/application.tsx
| import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models"; | ||
| import { addAlert } from "@wso2is/core/store"; | ||
| import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter } from "@wso2is/form/src"; | ||
| import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter } from "@wso2is/form/src"; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if importing from `@wso2is/form/src` is a pattern used elsewhere
rg "from ['\"]@wso2is/form" --type ts --type tsx -A 0 | head -50Repository: wso2/identity-apps
Length of output: 89
🏁 Script executed:
#!/bin/bash
# Search for `@wso2is/form` imports without file type restrictions
rg "@wso2is/form" --glob "*.ts" --glob "*.tsx" -A 0 | head -100Repository: wso2/identity-apps
Length of output: 13171
🏁 Script executed:
#!/bin/bash
# Check the exact file mentioned in the review comment
head -30 features/admin.agents.v1/components/wizards/add-agent-wizard.tsx | grep -n "import"Repository: wso2/identity-apps
Length of output: 752
Change import path from @wso2is/form/src to @wso2is/form.
Importing from /src bypasses the package's public exports and can cause issues in production builds. Use the public entry point instead.
- import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter } from "@wso2is/form/src";
+ import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter } from "@wso2is/form";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` at line 23,
The import currently pulls FinalForm, FinalFormField, FormRenderProps,
TextFieldAdapter, and CheckboxFieldAdapter from the package's internal path
"@wso2is/form/src"; change the import to use the package's public entry
"@wso2is/form" so the components use the official public exports and avoid
production build issues—update the import statement that references FinalForm,
FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter
accordingly.
| // @ts-ignore - Suppressing deprecation warning for valid async use case | ||
| const application: any = await getApplicationDetails(applicationId); |
There was a problem hiding this comment.
Replace @ts-ignore with @ts-expect-error.
ESLint flags @ts-ignore as it silently suppresses errors. Use @ts-expect-error instead, which will error if the suppression becomes unnecessary.
🔧 Proposed fix
- // `@ts-ignore` - Suppressing deprecation warning for valid async use case
+ // `@ts-expect-error` - Suppressing deprecation warning for valid async use case
const application: any = await getApplicationDetails(applicationId);📝 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.
| // @ts-ignore - Suppressing deprecation warning for valid async use case | |
| const application: any = await getApplicationDetails(applicationId); | |
| // `@ts-expect-error` - Suppressing deprecation warning for valid async use case | |
| const application: any = await getApplicationDetails(applicationId); |
🧰 Tools
🪛 ESLint
[error] 115-115: Do not use "@ts-ignore" because it alters compilation errors.
(@typescript-eslint/ban-ts-comment)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@features/admin.agents.v1/pages/agents.tsx` around lines 115 - 116, Replace
the inline TypeScript suppression: locate the call to
getApplicationDetails(applicationId) where the file uses "// `@ts-ignore` -
Suppressing deprecation warning for valid async use case" and change the
directive to "// `@ts-expect-error`" so the suppression fails if it becomes
unnecessary; keep the existing explanatory comment text and ensure the same
placement immediately above the const application: any = await
getApplicationDetails(applicationId) statement.
| if (!application) { | ||
| dispatch( | ||
| addAlert({ | ||
| description: `No application found with ID: ${applicationId}`, | ||
| level: AlertLevels.WARNING, | ||
| message: "Application not found" | ||
| }) | ||
| ); | ||
|
|
||
| return null; | ||
| } |
There was a problem hiding this comment.
Null check for application is unreachable.
Based on getApplicationDetails implementation (context snippet 2), HTTP errors including 404s are caught and re-thrown as rejected promises, so the function will throw before returning null. This if (!application) block will never execute—the error will be caught in the catch block instead.
Consider removing this dead code or, if you want to handle 404s specially, catch AxiosError and check the status code.
♻️ Proposed refactor to handle 404 explicitly
try {
setIsFetchingClientId(true);
const applicationId: string = agentUsername.replace(/^AGENT\//i, "");
- // `@ts-expect-error` - Suppressing deprecation warning for valid async use case
- const application: any = await getApplicationDetails(applicationId);
-
- if (!application) {
- dispatch(
- addAlert({
- description: `No application found with ID: ${applicationId}`,
- level: AlertLevels.WARNING,
- message: "Application not found"
- })
- );
-
- return null;
- }
+ let application: any;
+ try {
+ // `@ts-expect-error` - Suppressing deprecation warning for valid async use case
+ application = await getApplicationDetails(applicationId);
+ } catch (appError: unknown) {
+ const axiosError = appError as AxiosError;
+ if (axiosError?.response?.status === 404) {
+ dispatch(
+ addAlert({
+ description: `No application found with ID: ${applicationId}`,
+ level: AlertLevels.WARNING,
+ message: "Application not found"
+ })
+ );
+ return null;
+ }
+ throw appError;
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@features/admin.agents.v1/pages/agents.tsx` around lines 118 - 128, The
null-check branch for application is unreachable because getApplicationDetails
throws on HTTP errors; remove the dead if (!application) { ... return null; }
block from the component (references: application, applicationId, dispatch,
addAlert) OR replace it by catching AxiosError around the getApplicationDetails
call (in the same async routine that calls getApplicationDetails) and, if
err.response?.status === 404, dispatch the addAlert with the same message;
otherwise rethrow or handle other errors in the existing catch. Ensure you
update only the code that handles the getApplicationDetails result and its error
handling, not other logic.
| // Open the credentials modal immediately for smooth UX | ||
| setIsAgentCredentialWizardOpen(true); |
There was a problem hiding this comment.
UX contradiction: Modal waits for fetch despite "immediate open" comment.
The comment on lines 322-323 says "Open the credentials modal immediately for smooth UX", but line 350 has isOpen={ isAgentCredentialWizardOpen && !isFetchingClientId }, which keeps the modal closed until the fetch completes.
This contradicts the intended UX. The modal should open immediately and show a loading state (which the modal already supports via isFetchingClientId prop). Consider:
🔧 Proposed fix to open modal immediately
<AgentSecretShowModal
title={ t("agents:new.title") }
agentId={ newAgent?.id }
agentSecret={ newAgent?.password }
applicationClientId={ fetchedApplicationClientId }
isUserServingAgent={ newAgent?.isUserServingAgent }
- isOpen={ isAgentCredentialWizardOpen && !isFetchingClientId }
+ isFetchingClientId={ isFetchingClientId }
+ isOpen={ isAgentCredentialWizardOpen }
onClose={ () => {Also applies to: 350-350
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@features/admin.agents.v1/pages/agents.tsx` around lines 322 - 323, The
comment says the credentials modal should open immediately but the JSX keeps it
closed until fetch finishes; update the modal's isOpen prop to depend only on
isAgentCredentialWizardOpen (e.g., isOpen={isAgentCredentialWizardOpen}) so
calling setIsAgentCredentialWizardOpen(true) opens it right away, and rely on
the existing isFetchingClientId prop passed into the modal component to render a
loading state while the clientId is being fetched; adjust any conditional logic
around modal rendering to remove the && !isFetchingClientId guard and keep
fetch-state-driven UI inside the modal (references:
setIsAgentCredentialWizardOpen, isAgentCredentialWizardOpen, isFetchingClientId,
and the modal component's isFetchingClientId prop).
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@features/admin.extensions.v1/configs/application.tsx`:
- Around line 233-234: The code references
ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION which does not exist; fix by
either adding VC_CLIENT_APPLICATION to the ApplicationTemplateIdTypes enum
definition in features/admin.applications.v1/models/application.ts (ensure the
enum export includes the new VC_CLIENT_APPLICATION member) or remove the
conditional that checks application?.templateId ===
ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION in
features/admin.extensions.v1/configs/application.tsx so only existing enum
members are used; update any related usages or tests to reflect the chosen
change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: bd1c34e8-1dad-43cf-97f0-67170adaa3c2
📒 Files selected for processing (3)
features/admin.applications.v1/components/forms/inbound-oidc-form.tsxfeatures/admin.applications.v1/models/application.tsfeatures/admin.extensions.v1/configs/application.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- features/admin.applications.v1/components/forms/inbound-oidc-form.tsx
| || application?.templateId === ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION | ||
| || application?.templateId === ApplicationTemplateIdTypes.AGENT_APPLICATION |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for VC_CLIENT_APPLICATION in the application.ts file
echo "=== Searching for VC_CLIENT_APPLICATION ==="
rg -n "VC_CLIENT_APPLICATION" --type ts --type tsx
echo ""
echo "=== Checking the ApplicationTemplateIdTypes enum ==="
# Look for the enum definition to see all members
rg -A 30 "export enum ApplicationTemplateIdTypes" features/admin.applications.v1/models/Repository: wso2/identity-apps
Length of output: 2804
VC_CLIENT_APPLICATION is not defined in ApplicationTemplateIdTypes enum.
Line 233 references ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION, but this value does not exist in the ApplicationTemplateIdTypes enum defined in features/admin.applications.v1/models/application.ts. This will cause a TypeScript compilation error. The enum contains: SPA, OIDC_WEB_APPLICATION, SAML_WEB_APPLICATION, MOBILE_APPLICATION, M2M_APPLICATION, AGENT_APPLICATION, CUSTOM_APPLICATION, MCP_CLIENT_APPLICATION, DIGITAL_WALLET_APPLICATION, REACT_APPLICATION, NEXT_JS_APPLICATION, ANGULAR_APPLICATION, and EXPRESSJS_APPLICATION.
Either add VC_CLIENT_APPLICATION to the enum or remove this reference.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@features/admin.extensions.v1/configs/application.tsx` around lines 233 - 234,
The code references ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION which does
not exist; fix by either adding VC_CLIENT_APPLICATION to the
ApplicationTemplateIdTypes enum definition in
features/admin.applications.v1/models/application.ts (ensure the enum export
includes the new VC_CLIENT_APPLICATION member) or remove the conditional that
checks application?.templateId ===
ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION in
features/admin.extensions.v1/configs/application.tsx so only existing enum
members are used; update any related usages or tests to reflect the chosen
change.
Add Agent Application Template and User-Serving Agent Support
Summary
This PR enhances the agent creation flow to display the OAuth Client ID for user-serving agents,
improving the developer experience by providing all necessary credentials in one place.
Changes
credentials modal for user-serving agents
AgentScimSchemawithapplicationClientIdfieldaccidental deletion
Technical Details
AGENT/{applicationId}