Skip to content

Add new agent application template to create agent applications#9597

Open
ranuka-laksika wants to merge 3 commits intowso2:masterfrom
ranuka-laksika:new_agent_application_template
Open

Add new agent application template to create agent applications#9597
ranuka-laksika wants to merge 3 commits intowso2:masterfrom
ranuka-laksika:new_agent_application_template

Conversation

@ranuka-laksika
Copy link

@ranuka-laksika ranuka-laksika commented Feb 13, 2026

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

  • Multi-step wizard: Separated agent creation into two steps
    • Step 1: Agent name and description
    • Step 2: User-serving agent selection
  • OAuth Client ID display: Automatically fetches and displays the OAuth Client ID in the
    credentials modal for user-serving agents
  • UI improvements: Added loading state while fetching client ID from OIDC configuration
  • Model updates: Extended AgentScimSchema with applicationClientId field
  • Application protection: Hide danger zone and delete button for agent applications to prevent
    accidental deletion

Technical Details

  • Agent username format: AGENT/{applicationId}
  • Client ID is fetched asynchronously from the application's OIDC inbound protocol configuration
  • Credentials modal displays:
    • Agent ID
    • Agent Secret
    • OAuth Client ID (for user-serving agents only)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
Add Agent wizard & agent models
features/admin.agents.v1/components/wizards/add-agent-wizard.tsx, features/admin.agents.v1/models/agents.ts
Replaced single-step add-agent form with a two-step wizard (name/description → isUserServingAgent). Added local wizard state and handlers, included IsUserServingAgent in SCIM payload, and added IsUserServingAgent?: boolean and applicationClientId?: string to agent model.
Agent credentials modal & page flow
features/admin.agents.v1/components/edit/agent-secret-show-modal.tsx, features/admin.agents.v1/pages/agents.tsx
Extended modal props with applicationClientId, isUserServingAgent, isFetchingClientId; added UI to show OAuth Client ID for user-serving agents. Pages: fetch application client ID for user-serving agents, track loading state, open credentials modal after creation, and manage fetched client ID lifecycle.
Application templates — config & template file
features/admin.applications.v1/data/application-templates/application-templates-config.ts, features/admin.applications.v1/data/application-templates/templates/agent-application/agent-application.json
Added a new Agent Application template JSON and registered it in the application templates config (controlled by applicationConfig.templates.agent).
Application template IDs & OIDC form
features.admin.applications.v1/models/application.ts, features/admin.applications.v1/components/forms/inbound-oidc-form.tsx
Added AGENT_APPLICATION = "agent-application" to ApplicationTemplateIdTypes and enabled the Client Authentication section in the inbound OIDC form for agent applications.
Extensions templates & public app config
features/admin.extensions.v1/application-templates/templates/agent-application/agent-application.json, features/admin.extensions.v1/configs/application.tsx, features/admin.extensions.v1/configs/models/application.ts
Added agent application extension template resource, exposed templates.agent: true in public applicationConfig, and added agent: boolean flag to ApplicationConfig.templates; updated UI gating to treat agent templates like other supported templates.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Changeset Required ❌ Error The pull request modified 11 files across feature directories but contains no changeset markdown files in the .changeset/ directory. Create a changeset markdown file in .changeset/ directory documenting the changes with affected packages and appropriate version bump types.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a new agent application template to create agent applications, which aligns with the core functionality introduced.
Description check ✅ Passed The PR description covers the purpose, summary of changes, technical details, and implementation notes comprehensively. However, the provided template checklist items are not marked.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟠 Major

Add missing agent-application entry to getAllowedGrantTypes map.

The agent-application template exists and is documented as using OAuth2 client credentials flow, but is missing from the getAllowedGrantTypes configuration. Without this entry, the protocol settings UI will show all grant types as available, rather than restricting to CLIENT_CREDENTIALS_GRANT only.

Add the following entry after the m2m-application block:

         [ "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 consider Owner field placement.

Line 73: values?.isUserServingAgent || false — while functionally correct here, ?? is the idiomatic nullish coalescing operator for defaulting undefined/null to false without 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": "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
"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.

Comment on lines +1 to +18
{
"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
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 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"
fi

Repository: 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 -20

Repository: 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 -10

Repository: 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 -200

Repository: 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
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.88%. Comparing base (c67bea3) to head (134033b).
⚠️ Report is 46 commits behind head on master.

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     
Flag Coverage Δ
@wso2is/core 55.88% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 10 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranuka-laksika ranuka-laksika changed the title Add new agent application template Add new agent application template to create agent applications Feb 13, 2026
@pavinduLakshan
Copy link
Member

Let's add screenshots/screencasts of the UI to better understand the UX.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟠 Major

Type onClose callback properly instead of using any.

The onClose prop should have explicit typing per coding guidelines. Based on usage, it receives either null (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 or unknown with 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 using any.

The handleNext and handleCreate functions use any for the values parameter. 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: Type dispatch properly instead of using any.

Use the proper Dispatch type 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 or unknown with 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.getElementById and dispatchEvent to submit forms is fragile and not idiomatic React. Consider using refs and the form's requestSubmit() 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 memoizing fetchApplicationClientId with useCallback.

The fetchApplicationClientId function uses dispatch from the component scope. Per coding guidelines, callbacks should be stabilized with useCallback to 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 using any type for newAgent state.

The newAgent state should be properly typed instead of using any. Consider using a union type or extending AgentScimSchema to include the isUserServingAgent property 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

📥 Commits

Reviewing files that changed from the base of the PR and between 134033b and 52b4b71.

📒 Files selected for processing (5)
  • features/admin.agents.v1/components/edit/agent-secret-show-modal.tsx
  • features/admin.agents.v1/components/wizards/add-agent-wizard.tsx
  • features/admin.agents.v1/models/agents.ts
  • features/admin.agents.v1/pages/agents.tsx
  • features/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";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 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 -50

Repository: 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 -100

Repository: 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.

Comment on lines +115 to +116
// @ts-ignore - Suppressing deprecation warning for valid async use case
const application: any = await getApplicationDetails(applicationId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
// @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.

Comment on lines +118 to +128
if (!application) {
dispatch(
addAlert({
description: `No application found with ID: ${applicationId}`,
level: AlertLevels.WARNING,
message: "Application not found"
})
);

return null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

Comment on lines +322 to +323
// Open the credentials modal immediately for smooth UX
setIsAgentCredentialWizardOpen(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 52b4b71 and 42ae83e.

📒 Files selected for processing (3)
  • features/admin.applications.v1/components/forms/inbound-oidc-form.tsx
  • features/admin.applications.v1/models/application.ts
  • features/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

Comment on lines +233 to +234
|| application?.templateId === ApplicationTemplateIdTypes.VC_CLIENT_APPLICATION
|| application?.templateId === ApplicationTemplateIdTypes.AGENT_APPLICATION
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants