Skip to content

feat: AI Selector Widget#1505

Open
olexii4 wants to merge 30 commits intomainfrom
AI_widget
Open

feat: AI Selector Widget#1505
olexii4 wants to merge 30 commits intomainfrom
AI_widget

Conversation

@olexii4
Copy link
Copy Markdown
Contributor

@olexii4 olexii4 commented Mar 30, 2026

What does this PR do?

Adds an AI Selector widget to the Create Workspace page and integrates AI tool management across the dashboard, allowing users to pick an AI tool (e.g. Gemini CLI, Claude Code, OpenCode), save their API key, and have the tool automatically injected into workspaces.

Type Definitions

Two separate types model the AI feature:

  • AiProviderDefinition — provider metadata (id, name, publisher, description, icon, docs URL). Icons and descriptions live on the provider, not on individual tools.
  • AiToolDefinition — injection details (providerId as FK to provider, tag, binary, pattern, injectorImage, envVarName). The providerId follows vendor/product convention (e.g. anthropic/claude, google/gemini).

Create Workspace — AI Provider Selector

  • Accordion-based UI ("Use a Default AI Provider" / "Choose an AI Provider") rendered on the Create Workspace page between Editor Selector and Import form.
  • Link to "Manage API keys in User Preferences" for quick navigation.

User Preferences — AI Providers Keys

  • New "AI Providers Keys" tab in User Preferences with a table listing configured API keys per tool.
  • Add/Edit modal with provider dropdown and masked API key input;
  • Delete confirmation modal.

Workspace Details — Overview Tab

  • AiToolFormGroup section displaying the currently injected AI tool (or "None").
  • Edit mode opens a radio-button modal listing all available tools with descriptions from the provider definition.
  • Info modal explaining the injection mechanism and listing available tools with provider descriptions.

Workspaces List — AI Provider Column

  • New "AI Provider" column in the Workspaces List table.

AI Tool Injection into DevWorkspace

  • addAiToolToWorkspace() creates an init container from the tool's injectorImage, a shared injected-tools volume, and DevWorkspace lifecycle commands:
    • preStart: apply command runs the injector init container.
    • postStart: exec command symlinks the binary into PATH and optionally runs setupCommand.
  • Two injection patterns: init (single binary copy) and bundle (full runtime directory with symlink).

Screenshot/screencast of this PR

Знімок екрана 2026-04-06 о 06 19 52 Знімок екрана 2026-04-06 о 06 21 04 Знімок екрана 2026-04-06 о 06 21 32 Знімок екрана 2026-04-06 о 06 22 08 Знімок екрана 2026-04-06 о 06 22 30 Знімок екрана 2026-04-06 о 06 22 59

What issues does this PR fix or reference?

fixes eclipse-che/che#23796

Is it tested? How?

Setting up the AI Tool Registry

The dashboard reads AI tool definitions from a Kubernetes ConfigMap at runtime. To enable the AI widgets you need to create this ConfigMap:

# Clone the AI tool images repository
git clone https://github.com/olexii4/che-ai-tool-images.git
cd che-ai-tool-images

# Set your Che namespace
NS="${CHE_NAMESPACE:-eclipse-che}"

# Create the AI tool registry ConfigMap
oc create configmap ai-tool-registry \
  --from-file=registry.json=registry.json \
  -n "$NS" \
  --dry-run=client -o yaml | \
  oc label --local -f - \
    app.kubernetes.io/component=ai-tool-registry \
    app.kubernetes.io/part-of=che.eclipse.org \
    -o yaml | \
  oc apply -f -

When no ConfigMap is found, the dashboard returns an empty registry and all AI-related UI elements are hidden automatically. To remove all AI tools:

oc delete configmap ai-tool-registry -n "${CHE_NAMESPACE:-eclipse-che}"

Manual testing steps

  1. Deploy Eclipse Che with the dashboard image from this PR.
  2. Create Workspace page: verify the AI Provider Selector accordion renders below the Editor Selector. Expand "Choose an AI Provider" — cards should show provider icons, names, and descriptions sorted alphabetically, navigable with arrow keys. Selecting a card and creating a workspace should inject the tool's init container, shared volume, and lifecycle commands into the DevWorkspace spec.
  3. Default provider message: if the admin configures defaultAiProvider in the CheCluster CR, the "Use a Default AI Provider" panel should display the resolved provider name (e.g. "The default AI provider "Gemini" configured by your administrator will be used.").
  4. User Preferences → AI Providers Keys tab: add an API key for a tool — verify the secret is created in the user namespace with correct labels (che.eclipse.org/ai-provider-id, controller.devfile.io/mount-to-devworkspace, controller.devfile.io/watch-secret) and annotation (controller.devfile.io/mount-as: env). Update and delete the key. Verify the "Key configured" badge updates on the Create Workspace gallery cards.
  5. Workspaces List: verify the "AI Provider" column shows the injected tool icon and name for workspaces that have an AI tool, and "-" for those without.
  6. Workspace Details → Overview tab: verify the AI Tool section shows the current tool or "None". Click the info icon — verify the modal shows tools with provider descriptions. Click edit, select a different tool, save — verify the DevWorkspace spec is updated. When no tools are configured, verify the empty-state message is shown.
  7. Workspace runtime: start a workspace with an injected tool (e.g. Gemini CLI). Open a terminal in the editor container and verify the tool binary is available in PATH (e.g. which gemini). Verify the API key env var is set (e.g. echo $GEMINI_API_KEY).
  8. Empty registry: delete the ai-tool-registry ConfigMap and verify that the AI Provider Selector on the Create Workspace page, the AI Provider(s) column in the Workspaces List, and the AI Providers Keys tab in User Preferences are all hidden.
  9. AI tool injection (Gemini CLI): on the Create Workspace page, select "Gemini CLI" as the AI Provider. Create a new workspace from any sample (e.g. Go). Wait for the workspace to start and the IDE to load. Open a terminal in the IDE and run gemini — verify the Gemini CLI starts (or prints its help/version output), confirming the AI tool binary was injected into PATH.
  10. AI tool injection (Claude Code): repeat step 9 but select "Claude Code" as the AI Provider. In the terminal, run claude — verify the Claude Code CLI is available.
  11. Multiple AI tools: on the Create Workspace page, expand "Choose an AI Provider" and select multiple providers (e.g. both Gemini CLI and Claude Code). Create a workspace, open a terminal, and verify both gemini and claude commands are available. Check the Workspaces List — the "AI Provider(s)" column should show icons for both tools.

Release Notes

Docs PR

eclipse-che/che-docs#3062

@che-bot
Copy link
Copy Markdown
Contributor

che-bot commented Mar 30, 2026

Click here to review and test in web IDE: Contribute

Comment thread packages/dashboard-backend/src/routes/api/aiConfig.ts Fixed
@olexii4 olexii4 force-pushed the AI_widget branch 3 times, most recently from 147736e to dd23665 Compare March 30, 2026 01:15
Comment thread packages/dashboard-backend/src/routes/api/aiConfig.ts Fixed
@olexii4 olexii4 force-pushed the AI_widget branch 7 times, most recently from 7a2dae5 to c0f7621 Compare March 30, 2026 05:03
@olexii4 olexii4 force-pushed the AI_widget branch 8 times, most recently from cb23caf to e756cf0 Compare April 1, 2026 02:13
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1505 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1505", name: che-dashboard}]}}]"

@olexii4 olexii4 force-pushed the AI_widget branch 3 times, most recently from 73b403a to 183e6c5 Compare April 1, 2026 03:02
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1505 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1505", name: che-dashboard}]}}]"

1 similar comment
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1505 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1505", name: che-dashboard}]}}]"

olexii4 added 27 commits May 7, 2026 14:12
Rework AiProviderKeysList table to follow WorkspacesList patterns:
- Use variant="compact" string, screenReaderText for select columns
- Add CSS classes for column width constraints and cell overflow
- Move inline styles to CSS module (envVarCell, actionsCell, noKeyLabel)
- Inline row rendering to simplify component

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Use CSS class with hover state for the question-circle icon in the
Add/Edit API Key form, matching the Temporary Storage switch pattern.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Fix icon margins, tooltip styling, toolbar alignment, label help
positioning, and reorder AI Provider Keys as the last preferences tab.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Replace hardcoded AI provider/tool defaults with a ConfigMap-based
registry read via GET /api/ai-registry. Remove AI fields from
server-config API. Hide all AI UI elements (provider selector, table
column, preferences tab, detail form) when the registry is empty.
Add tag-agnostic image comparison and admin-manageable component
cleanup before workspace start.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
…al render

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
The setupCommand (e.g. creating ~/.gemini config dir) was joined with
&& to the critical symlink/PATH commands. When $HOME is read-only
(e.g. Go toolset container), the setup failure prevented the symlink
from being created, leaving the AI tool binary missing from PATH.

Wrap setupCommand in a best-effort block so symlink and PATH setup
always execute regardless of setup failures.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
…and test cleanup

- Guard fetchAiProviderKeyStatus to skip when no AI providers/tools exist
- Implement updateOutdatedAiTools() to auto-update stale AI tool injectors
  before workspace start (tag priority: next > latest > semver)
- Fix bulk delete of AI provider keys (modal now accepts array of providers)
- Replace personal image references with dummy names in tests
- Add unit tests for updateOutdatedAiTools and prepareDevfile AI injection

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
…cleanup commands

Init containers now clean their own files before copying, handling
image updates naturally. removeAiToolFromWorkspace no longer adds
postStart cleanup commands. sanitizeStaleAiTools now also removes
orphaned tool commands (install/symlink/run/cleanup) whose injector
component no longer exists in the spec.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
…Line

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
The frontend no longer base64-encodes the API key via btoa() before
posting it to the backend. The backend is responsible for encoding
when creating the Kubernetes Secret.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Kubernetes Secret `data` expects base64-encoded values, but the API
key now arrives as plain text after removing frontend btoa() encoding.
Switch to `stringData` so Kubernetes handles base64 encoding
automatically.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
The onSelect callback was called inside the setState() updater
function and read this.state.expandedId instead of prevState.
Move the side effect to the setState callback to ensure it
runs after state is committed and reads the correct values.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
When removing an AI tool, a cleanup postStart command is added to
remove stale binaries from the shared PVC on the next workspace start.
sanitizeStaleAiTools now preserves cleanup commands (they must run at
least once) while still removing orphaned install/symlink/run commands.

Also adds missing ai-registry mock in workspaceCreationTimeCheck to
fix CI failure.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Wrap cleanup commands in `nohup sh -c '...' &` so they never block
or freeze workspace startup. Each tool's cleanup runs independently
and in parallel. If removal fails the command retries on next start.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Since cleanup postStart commands run in the background, by the next
workspace start they have already executed. sanitizeStaleAiTools now
removes orphaned cleanup-* commands automatically, so they do not
accumulate in the spec even if the tool is never re-added.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
- Restrict toolId schema to K8s-label-safe characters (remove : and @)
- Sanitize all non-label-safe chars in toSanitizedProviderId
- Fix stuck isLoading when tools array is empty in refreshKeyStatus
- Combine sanitize + update AI tools into a single PATCH on start
- Batch double setState in AiSelector.handleToggle
- Use providerId comparison instead of reference equality in List
- Add onError fallback to provider icon <img> tags
- Avoid redundant getProvider() calls in Gallery render

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Replace all occurrences of the specific AI agent name in code
comments with a generic "AI Assistant" identifier.

Assisted-by: AI Assistant
Signed-off-by: Oleksii Orel <[email protected]>
When sanitizeStaleAiTools removes the injected-tools volume (because
no recognized injectors remain), also remove the injected-tools volume
mount and PATH env override from editor containers. Without this, the
DevWorkspace operator rejects the spec with "unable to find volume
mount injected-tools in devfile volume components".

Assisted-by: AI Assistant
Signed-off-by: Oleksii Orel <[email protected]>
Cleanup commands added by removeAiToolFromWorkspace were removed by
sanitizeStaleAiTools before they could execute on cold start. Add a
pending-cleanup annotation so the cleanup command survives one start
cycle, executes during postStart, then gets removed on the next start.

Also add a comment explaining why $(PATH) substitution cannot be used
in the editor container env.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
JSON.parse can return primitives or arrays, not just objects. Add a
runtime type guard before casting to Record<string, unknown> to prevent
potential property access on non-object values.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
Add tests for AiConfig selectors, fetchAiRegistry API client,
AiSelectorDocsLink component, and AiSelectorErrorBoundary component
to bring global function coverage back above the 85% threshold.

Assisted-by: Claude Opus 4.6
Signed-off-by: Oleksii Orel <[email protected]>
The PATCH in startWorkspace only sent /spec/template, so annotation
changes from sanitizeStaleAiTools were lost. This caused cleanup
commands to never be removed and stale tool binaries to persist on
the shared volume across restarts.

Also adds tests for AddEditModal and DeleteModal to restore function
coverage above the 85% threshold.

Assisted-by: Claude Sonnet 4.5
Signed-off-by: Oleksii Orel <[email protected]>
Assisted-by: Claude Sonnet 4.5
Signed-off-by: Oleksii Orel <[email protected]>
Assisted-by: Claude Sonnet 4.5
Signed-off-by: Oleksii Orel <[email protected]>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1505 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1505", name: che-dashboard}]}}]"

Copy link
Copy Markdown
Member

@ibuziuk ibuziuk left a comment

Choose a reason for hiding this comment

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

@olexii4 let's add the Tech preview label to the widget, similar to what we have on devfile samples:
Image

@dmytro-ndp
Copy link
Copy Markdown
Contributor

I have a few questions:

  1. there are also codex CLI and Copilot CLI available in the Market. Should we support them as well?
  2. do you need AI CLI owner agreements to place their tile in the User Dashboard?
  3. will there be team wide API keys supported which covers several accounts?

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.

[UD] Add AI coding tool selection and API key management for DevWorkspaces

7 participants