Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions application/single_app/agent_delegation_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,19 +153,20 @@
log_event("[AGENT_DELEGATION] Client cleanup failed.", extra={"error_type": type(exc).__name__})


def _build_local_agent(target, settings):
def _build_local_agent(target, settings, *, construction_profile="agent-core"):

Check warning on line 156 in application/single_app/agent_delegation_runtime.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
from semantic_kernel import Kernel
from semantic_kernel_loader import load_agent_core_plugins, load_single_agent_for_kernel

frame = current_agent_execution()
capture_kwargs = {"invocation_capture": frame.invocation_capture} if frame.invocation_capture is not None else {}
kernel = Kernel()
load_agent_core_plugins(kernel, settings, **capture_kwargs)
load_agent_core_plugins(kernel, settings, construction_profile=construction_profile, **capture_kwargs)

Check warning on line 163 in application/single_app/agent_delegation_runtime.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
kernel, agents = load_single_agent_for_kernel(
kernel, deepcopy(target), settings, SimpleNamespace(),
mode_label="group" if target.get("is_group") else "global" if target.get("is_global") else "per-user",
group_scope_id=target.get("group_id"),
execution_user_id=frame.identity.user_id,
construction_profile=construction_profile,
**capture_kwargs,
)
agent = (agents or {}).get(target.get("name"))
Expand Down Expand Up @@ -576,10 +577,7 @@
invocation_retry_state = None
retry_override = self._stream_retry_override
selected = self.agent
descriptor = _continuation.get() or {
"mode": "chat", "checkpoint_id": self.credential_checkpoint_id,
"agent_reference": deepcopy(self.reference),
}
descriptor = _continuation.get()
try:
with agent_execution(frame) as frame:
frame.budget.raise_authentication_requirement(frame.identity)
Expand All @@ -606,6 +604,12 @@
kernel, selected = _build_local_agent(canonical, invocation_settings)
if retry_override:
invocation_retry_state = retry_override[1](selected, retry_override[0])
if descriptor is None:
descriptor = {
"mode": "chat", "checkpoint_id": self.credential_checkpoint_id,

Check warning on line 609 in application/single_app/agent_delegation_runtime.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"agent_reference": deepcopy(self.reference),

Check warning on line 610 in application/single_app/agent_delegation_runtime.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
"construction_profile": getattr(selected, "construction_profile", "agent-core"),

Check warning on line 611 in application/single_app/agent_delegation_runtime.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Check warning on line 611 in application/single_app/agent_delegation_runtime.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Moderate - Changed line contains obfuscation, dynamic loading, or hidden payload marker. Recommendation%3A Confirm the changed code is not hiding behavior, decoding payloads, or bypassing normal review.
}
if streaming:
with agent_execution(frame), credential_continuation(descriptor):
# Stream wrappers such as the M365 continuation journal set
Expand Down
5 changes: 4 additions & 1 deletion application/single_app/agent_logging_chat_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from functions_model_budget_runtime import prepare_model_execution_settings
import datetime
import re
from typing import Literal


class LoggingChatCompletionAgent(ChatCompletionAgent):
Expand All @@ -27,8 +28,9 @@
azure_endpoint: str | None = Field(default=None)
api_version: str | None = Field(default=None)
model_token_budget: ModelTokenBudget | None = Field(default=None, exclude=True)
construction_profile: Literal["agent-core", "per-user", "global"] = Field(default="agent-core", exclude=True)

Check warning on line 31 in application/single_app/agent_logging_chat_completion.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

def __init__(self, *args, display_name=None, default_agent=False, deployment_name=None, azure_endpoint=None, api_version=None, model_token_budget=None, **kwargs):
def __init__(self, *args, display_name=None, default_agent=False, deployment_name=None, azure_endpoint=None, api_version=None, model_token_budget=None, construction_profile="agent-core", **kwargs):

Check warning on line 33 in application/single_app/agent_logging_chat_completion.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Check warning on line 33 in application/single_app/agent_logging_chat_completion.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
# Remove these from kwargs so the base class doesn't see them
kwargs.pop('display_name', None)
kwargs.pop('default_agent', None)
Expand All @@ -42,6 +44,7 @@
self.azure_endpoint = azure_endpoint
self.api_version = api_version
self.model_token_budget = model_token_budget
self.construction_profile = construction_profile
# tool_invocations is now properly declared as a Pydantic field

def _merge_arguments(self, override_args):
Expand Down
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.261.344"
VERSION = "0.261.346"
IS_DEVELOPMENT = is_development_env_enabled()

# Opt-out for deployments where App Service Easy Auth is active but the platform
Expand Down
52 changes: 41 additions & 11 deletions application/single_app/route_backend_action_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@
from swagger_wrapper import swagger_route, get_auth_security


CONTINUATION_FAILURE_CODES = frozenset({
"credential_execution_changed", "credential_checkpoint_changed", "credential_request_changed",

Check warning on line 24 in application/single_app/route_backend_action_credentials.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"credential_continuation_unavailable", "credential_request_closed", "credentials_unavailable",
"action_credentials_required", "trusted_origin_required",
})


def _log_continuation_failure(error, item, stage):
code = error.code if isinstance(error, ActionCredentialError) else None
log_event("[PLUGINS] Credential continuation stopped.", level=logging.WARNING, extra={
**workflow_log_context(conversation_id=item["conversation_id"], turn_id=item["id"]),
"stage": stage, "error_type": type(error).__name__,
"failure_code": code if code in CONTINUATION_FAILURE_CODES else "credentials_unavailable",
})


def _csrf_token():
if not session.get("action_credentials_csrf_token"):
session["action_credentials_csrf_token"] = secrets.token_urlsafe(32)
Expand Down Expand Up @@ -145,16 +161,27 @@
import asyncio

descriptor = {**item["continuation"], "resume": True}
checkpoint = state.read(user_id, descriptor["checkpoint_id"], record_type="credential_checkpoint")
if checkpoint["conversation_id"] != item["conversation_id"] or "root" not in checkpoint["value"]:
raise ActionCredentialError("credential_checkpoint_changed")
identity = capture_execution_identity(user_id, item["conversation_id"])
settings = get_settings()
target = resolve_delegation_agent(descriptor["agent_reference"], user_id=user_id, settings=settings)
frame = AgentExecutionFrame(identity, target, DelegationBudget())
# Reconstruct a new invocation-local kernel under the current actor's bridge.
with identity.bridge(target), agent_execution(frame):
kernel, agent = _build_local_agent(target, settings)
stage = "credential_checkpoint_validation"
try:
checkpoint = state.read(user_id, descriptor["checkpoint_id"], record_type="credential_checkpoint")
if checkpoint["conversation_id"] != item["conversation_id"] or "root" not in checkpoint["value"]:
raise ActionCredentialError("credential_checkpoint_changed")
stage = "credential_reconstruction"
identity = capture_execution_identity(user_id, item["conversation_id"])
settings = get_settings()
target = resolve_delegation_agent(descriptor["agent_reference"], user_id=user_id, settings=settings)
frame = AgentExecutionFrame(identity, target, DelegationBudget())
# Reconstruct a new invocation-local kernel under the current actor's bridge.
with identity.bridge(target), agent_execution(frame):
profile = descriptor.get("construction_profile")
# Existing requests retain their historical agent-core path; no backfill/replay.
kernel, agent = (
_build_local_agent(target, settings) if profile is None
else _build_local_agent(target, settings, construction_profile=profile)
)
except Exception as error:
_log_continuation_failure(error, item, stage)
raise

async def execute():
with identity.bridge(target), agent_execution(frame), credential_continuation(descriptor):
Expand All @@ -165,8 +192,10 @@

@stream_with_context
def frames():
stage = "credential_tool_resume"
try:
result = asyncio.run(execute())
stage = "credential_response_persistence"
authorize_conversation(user_id, item["conversation_id"])
message = {
"id": uuid.uuid4().hex, "conversation_id": item["conversation_id"], "user_id": user_id,
Expand All @@ -175,6 +204,7 @@
"metadata": {"action_credential_continuation": True},
}
saved = _persist_screened_assistant(message, user_id, settings=settings)
stage = "credential_continuation_finalization"
_finish_request(user_id, item["id"], item["continuation_claim"], "completed")
yield serialize_sse({"content": saved["content"]})
yield serialize_sse({
Expand All @@ -186,7 +216,7 @@
yield serialize_sse(error.event)
except Exception as error:
_finish_request(user_id, item["id"], item["continuation_claim"], "failed")
log_event("[PLUGINS] Credential continuation stopped.", extra={"error_type": type(error).__name__})
_log_continuation_failure(error, item, stage)
yield serialize_sse({"error": "Saved work could not be continued. Refresh this conversation."})

return Response(frames(), mimetype="text/event-stream", headers={"Cache-Control": "no-store"})
Expand Down
Loading
Loading