-
Notifications
You must be signed in to change notification settings - Fork 7
Add per-user Chat Profiles (MCP tool allowlist + prompt override) for the browser AI Assistant #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
IzBrain67
wants to merge
6
commits into
main
Choose a base branch
from
feat/chat-profiles
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
8d09cd0
Add per-user Chat Profiles for the browser AI Assistant
IzBrain67 c93df5b
Harden Chat Profiles validation and the create-profile default
c568096
Record PR #94 Chat Profiles audit close-out
f0c5cff
Drop the audit progress log from PR #94
IzBrain67 1f0e319
Make Chat Profiles admin-managed shared presets with an enforced default
IzBrain67 ae30153
Address Copilot review on Chat Profiles
IzBrain67 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Chat Profiles (browser chat) | ||
|
|
||
| Chat Profiles let each user control which MCP tools the browser **AI Assistant** | ||
| may use, and optionally override its system prompt. Profiles are stored per user | ||
| on the backend and switched from the chat header. | ||
|
|
||
| ## Concepts | ||
|
|
||
| | Term | Meaning | | ||
| |---|---| | ||
| | **Default** (no profile) | Unchanged behaviour: every MCP tool is offered and `DEFAULT_SYSTEM_PROMPT` is used. | | ||
| | `allowed_tools` | Explicit allowlist of MCP tool names. Only these tools are offered to OpenAI **and** allowed to execute. | | ||
| | `allowed_tools = []` | Tools disabled: the backend skips MCP discovery entirely and appends `TOOLS_DISABLED_NOTE` to the system prompt. | | ||
| | `system_prompt` | Optional override. Precedence: profile prompt > `Conversation.system_prompt` > `DEFAULT_SYSTEM_PROMPT`. | | ||
|
|
||
| Because the allowlist is explicit, **new MCP tools start unchecked in existing | ||
| profiles**. They appear under "Other" in the editor until they are categorised | ||
| in `chatToolCategories.ts`. | ||
|
|
||
| When a profile restricts (but does not disable) tools, the backend appends | ||
| `TOOLS_RESTRICTED_NOTE` listing the enabled tools, because the default prompt | ||
| refers to tools by name. | ||
|
|
||
| ## Using it | ||
|
|
||
| 1. **Settings → Chat Profiles** (`/settings/chat-profiles`): create a profile — | ||
| name, optional system prompt, and the tool picker (grouped by category, with | ||
| per-category and per-tool checkboxes plus *Select all* / *Select none*). | ||
| 2. In the chat header, pick the profile from the dropdown next to the | ||
| conversation selector. The selection is remembered per user in this browser | ||
| (`localStorage` key `chatProfileId:<user key>`, where the key is the Keycloak | ||
| `sub`, falling back to `preferred_username` / email when the access token | ||
| carries no `sub` — the same order the backend maps users by) and sent as | ||
| `profile_id` with every message, so it can be switched mid-conversation. | ||
| 3. The **Generate report** button is disabled when the selected profile lacks | ||
| `get_workflow_facts` or `save_report`. | ||
|
|
||
| ## API | ||
|
|
||
| | Method | Endpoint | Notes | | ||
| |---|---|---| | ||
| | GET / POST | `/api/chat/profiles/` | List / create the caller's profiles. Body: `{name, allowed_tools: string[], system_prompt}` | | ||
| | GET / PUT / DELETE | `/api/chat/profiles/<uuid>/` | Owner-scoped (404 otherwise). PUT is partial. DELETE returns 204 | | ||
| | POST | `/api/chat/stream/` | Accepts optional `profile_id`; an unknown or foreign id returns 404 before any conversation is created | | ||
| | GET | `/api/chat/mcp-tools/` | Tool catalog used by the editor (shared with the notebook agent; shape unchanged) | | ||
|
|
||
| ## Code map | ||
|
|
||
| Backend (`gui/workflow_backend/django-project/app/chat/`): | ||
| `models.py` (`ChatProfile`, migration `0002_chatprofile`), | ||
| `serializers.py` (`ChatProfileSerializer`, `SendMessageSerializer.profile_id`), | ||
| `views.py` (`ChatProfileListCreateView`, `ChatProfileDetailView`, `ChatStreamView`), | ||
| `services/mcp_client.py` (`mcp_tools_to_openai_functions(..., allowed=)`), | ||
| `services/chat_orchestrator.py` (`orchestrate_chat(..., profile=)`). | ||
|
|
||
| Frontend (`gui/workflow_frontend/src/`): | ||
| `api/chatProfileApi.ts`, `stores/chatProfileStore.ts`, | ||
| `views/home/components/ChatProfileSelector.tsx`, `ChatProfileManager.tsx`, | ||
| `ChatProfileModal.tsx`, `chatToolCategories.ts`; wired in `chatbotView.tsx`, | ||
| `components/tabs/TabManager.tsx` and `shared/header/header.tsx`. | ||
|
|
||
| Tests: `gui/workflow_backend/django-project/tests/test_chat_profiles.py`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
gui/workflow_backend/django-project/app/chat/migrations/0002_chatprofile.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # Generated by Django 5.2 on 2026-09-05 08:57 | ||
|
|
||
| import django.db.models.deletion | ||
| import uuid | ||
| from django.conf import settings | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('chat', '0001_initial'), | ||
| migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.CreateModel( | ||
| name='ChatProfile', | ||
| fields=[ | ||
| ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), | ||
| ('name', models.CharField(max_length=100)), | ||
| ('allowed_tools', models.JSONField(blank=True, default=list)), | ||
| ('system_prompt', models.TextField(blank=True, default='')), | ||
| ('created_at', models.DateTimeField(auto_now_add=True)), | ||
| ('updated_at', models.DateTimeField(auto_now=True)), | ||
| ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chat_profiles', to=settings.AUTH_USER_MODEL)), | ||
| ], | ||
| options={ | ||
| 'db_table': 'chat_profiles', | ||
| 'ordering': ['name'], | ||
| 'constraints': [models.UniqueConstraint(fields=('user', 'name'), name='chat_profile_unique_user_name')], | ||
| }, | ||
| ), | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.