Skip to content

Feature/aifoundryagents#812

Open
Bionic711 wants to merge 47 commits intoDevelopmentfrom
feature/aifoundryagents
Open

Feature/aifoundryagents#812
Bionic711 wants to merge 47 commits intoDevelopmentfrom
feature/aifoundryagents

Conversation

@Bionic711
Copy link
Copy Markdown
Collaborator

Adds multiendpoint support for all 3 scopes (models, as well as classic and new foundry agent support)
Fixes for a multitude of stuff
Updates core plugins to 1st class by adding plugin logger
Enhances thoughts and streaming
Improves MS graph plugin capabilities

@Bionic711 Bionic711 requested a review from paullizer March 27, 2026 15:22
@Bionic711 Bionic711 added the enhancement New feature or request label Mar 27, 2026
Copilot AI review requested due to automatic review settings March 27, 2026 15:22
@github-project-automation github-project-automation bot moved this to Pending Evaluation in Simple Chat Roadmap Mar 27, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Copy link
Copy Markdown
Contributor

@paullizer paullizer left a comment

Choose a reason for hiding this comment

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

please review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

user/group model fetch and test endpoints bypass the custom-endpoint feature gates

44-50: resolve_request_endpoint_payload() merges raw request payload even when no persisted endpoint_id exists.
208-286: both handle_fetch_model_list() and handle_test_model_connection() consume that resolved payload.
823-836: /api/user/models/fetch and /api/user/models/test-model only require login/user auth.
839-866: /api/group/models/fetch and /api/group/models/test-model only require group workspaces, not allow_group_custom_endpoints.

Why this matters:

These routes will accept a caller-supplied endpoint/auth payload when endpoint_id is omitted.
That means the backend can still be used to probe arbitrary AOAI/Foundry endpoints even when custom endpoints are disabled.
For the user routes this is available to any authenticated user. For the group routes it is available even if group custom endpoints are disabled.
Impact:

Feature gating is not actually enforced on the backend.
The server becomes a credentialed network proxy for endpoint discovery and test calls outside the intended admin/workspace flows.

Suggested review comment:

Require the same enabled_required(...) guards as the save/list routes, and reject raw payloads for non-admin scopes unless they reference a persisted endpoint the caller is authorized to use.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

stream reattach cannot work for the first message in a brand-new conversation

application/single_app/route_backend_chats.py
application/single_app/static/js/chat/chat-streaming.js

5324-5325: stream session is started from the incoming conversation_id before the backend creates a new one.
5669-5670: the streaming path generates a new UUID later if the request started without a conversation id.
7143-7166: status/reattach endpoints only look up sessions by the final conversation id.
286-302 in chat-streaming.js: the client reattach flow requires a real conversation id.

Why this matters:

When a user starts streaming in a new conversation, there is no incoming conversation_id, so no live session is registered.
If the page reconnects during that first response, the reattach/status endpoints have nothing to find under the eventual conversation id.

Impact:

Reattach works for existing conversations but not for the first streamed reply of a new conversation, which is exactly when the connection is most fragile.

Suggested review comment:

Start/register the stream session after the conversation id is finalized, or allow the session key to be rebound once the UUID is created.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

delete please

return jsonify({"success": True})


@app.route('/api/group/model-endpoints', methods=['GET'])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

proup model endpoint reads trust activeGroupOid without verifying current membership

application/single_app/route_backend_models.py
application/single_app/functions_group.py

660-675 in route_backend_models.py: /api/group/model-endpoints GET only calls require_active_group(user_id).
132-149 in functions_group.py: require_active_group() only reads the stored active group id, while assert_group_role() is the function that actually enforces membership.

Why this matters:

The read endpoint returns sanitized group model endpoints based only on the caller's stored activeGroupOid.
Unlike the write/test/list-foundry paths, it never verifies that the caller is still a member of that group.

Impact:

A stale or tampered activeGroupOid can expose group endpoint metadata to a user who no longer belongs to the group.
This is inconsistent with the stricter authorization already used by the adjacent POST/test routes.

Suggested review comment:

Apply the same assert_group_role(..., allowed_roles=("Owner", "Admin", "DocumentManager", "User")) check on the GET route before returning group endpoint metadata.

)
return None

def resolve_multi_endpoint_agent_config():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

group agents resolve model endpoints from the current active group, not from the agent's own group

application/single_app/semantic_kernel_loader.py
application/single_app/functions_group_agents.py
application/single_app/route_backend_agents.py

359-368 and 417-428 in semantic_kernel_loader.py: when is_group_agent is true, endpoint lookup uses require_active_group(get_current_user_id()).
66-71 in functions_group_agents.py: group agents are persisted with their own group_id.
60-73 and 90-99 in route_backend_agents.py: selected-agent payload matching also preserves group_id for group agents.

Why this matters:

The selected group agent already carries its own group identity, but model endpoint resolution ignores that and re-derives the group from the user's current active group.
If the user changes active group after selecting an agent, or opens a conversation tied to a different group context, the loader can resolve the wrong endpoint set.

Impact:

Group agents can fail to load their configured endpoint/model.
Worse, a group agent may resolve against another active group's endpoints if endpoint ids collide or if the intended endpoint is missing in the current group.

Suggested review comment:

Resolve group-scoped model endpoints using the agent's persisted group_id (or the conversation's group id), not the mutable active-group setting.

per_user_enabled = settings.get('per_user_semantic_kernel', False)
allow_user_custom_agent_endpoints = settings.get('allow_user_custom_agent_endpoints', False)
allow_group_custom_agent_endpoints = settings.get('allow_group_custom_agent_endpoints', False)
allow_user_custom_endpoints = settings.get('allow_user_custom_endpoints', False) or settings.get('allow_user_custom_agent_endpoints', False)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

loader feature-flag typo makes group custom endpoint behavior depend on the user custom-agent flag

application/single_app/semantic_kernel_loader.py

164-165 in semantic_kernel_loader.py:
allow_user_custom_endpoints = settings.get('allow_user_custom_endpoints', False) or settings.get('allow_user_custom_agent_endpoints', False)
allow_group_custom_endpoints = settings.get('allow_group_custom_endpoints', False) or settings.get('allow_user_custom_agent_endpoints', False)

Why this matters:

The second line appears to reference allow_user_custom_agent_endpoints instead of the group equivalent.
That means enabling user custom-agent endpoints can inadvertently enable group custom-endpoint resolution logic inside the loader.

Impact:

Group-agent routing behavior becomes dependent on the wrong admin toggle.
This creates inconsistent runtime behavior between UI settings and backend agent resolution.

Suggested review comment:

Replace the second fallback with the intended group-scoped flag so group endpoint resolution only activates under group endpoint settings.

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

Labels

enhancement New feature or request

Projects

Status: Pending Evaluation

Development

Successfully merging this pull request may close these issues.

4 participants