Commit Graph

793 Commits

  • Python: Fix state snapshot to use deepcopy so nested mutations are detected in durable workflow activities (#4518)
    * Use deepcopy for state snapshot to detect nested mutations (#4500)
    
    Replace dict() shallow copy with copy.deepcopy() when snapshotting
    workflow state before activity execution. The shallow copy shared
    references to nested objects (dicts, lists), so in-place mutations by
    executors were reflected in both the snapshot and live state, producing
    an empty diff and preventing state updates from propagating to
    downstream activities.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Fix state snapshot to use deepcopy so nested mutations are detected in durable workflow activities
    
    Fixes #4500
    
    * Address PR review: remove report, extract testable helpers (#4500)
    
    - Delete REPRODUCTION_REPORT.md (debugging artifact with local paths
      and raw LLM output)
    - Extract _create_state_snapshot() and _compute_state_updates() as
      module-level helpers in _app.py so tests exercise the production
      code path
    - Update TestStateSnapshotDiff to import and use production helpers
      instead of reimplementing snapshot/diff logic locally
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Add regression tests proving shallow copy bug and deep copy isolation (#4500)
    
    Add two additional tests to TestStateSnapshotDiff:
    - test_shallow_copy_would_miss_nested_mutations: reproduces the original
      bug by demonstrating that dict() (shallow copy) misses nested mutations
    - test_create_state_snapshot_isolates_nested_objects: verifies the
      production _create_state_snapshot helper creates a true deep copy
    
    These tests ensure a regression back to shallow copy would be caught.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add integration test exercising full activity code path (#4500)
    
    Address PR review comment: add test_executor_activity_detects_nested_state_mutations
    that captures the actual executor_activity function from _setup_executor_activity
    and verifies it detects in-place nested mutations. This test would fail if
    _app.py line 314 regressed from _create_state_snapshot() back to dict().
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #4518: review comment fixes
    
    * Address PR review feedback for state snapshot diff
    
    - Inline _compute_state_updates logic at call site to reuse precomputed
      original_keys/current_keys sets, avoiding redundant set allocations
    - Fix test docstring to describe behavioral regression instead of
      hard-coding a specific line number
    - Use SOURCE_ORCHESTRATOR constant in integration test instead of
      literal string
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * fix: remove unused _compute_state_updates from _app.py (#4518)
    
    The function was inlined per review comment, making the module-level
    helper unused and triggering a pyright reportUnusedFunction error.
    Move the helper into the test file where it is still needed for unit
    testing the diffing logic.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Bump rollup from 4.47.1 to 4.59.0 in /python/packages/devui/frontend (#4338)
    Bumps [rollup](https://github.com/rollup/rollup) from 4.47.1 to 4.59.0.
    - [Release notes](https://github.com/rollup/rollup/releases)
    - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rollup/rollup/compare/v4.47.1...v4.59.0)
    
    ---
    updated-dependencies:
    - dependency-name: rollup
      dependency-version: 4.59.0
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Bump minimatch from 3.1.2 to 3.1.5 in /python/packages/devui/frontend (#4337)
    Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5.
    - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
    - [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)
    
    ---
    updated-dependencies:
    - dependency-name: minimatch
      dependency-version: 3.1.5
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Fix CWE-863: Validate function approval responses in DevUI executor (#4598)
    The DevUI /v1/responses endpoint accepts function_approval_response content
    without verifying that the request_id corresponds to a real pending approval
    request issued by the server. This allows forged approval responses to
    execute arbitrary tools with attacker-controlled arguments, bypassing
    approval_mode='always_require'.
    
    Changes:
    - Track outgoing approval requests in a server-side registry
      (_pending_approvals) keyed by request_id
    - Validate incoming approval responses against this registry; reject
      any response whose request_id was not issued by the server
    - Use server-stored function_call data (tool name, arguments, call_id)
      instead of client-supplied data when constructing the approval response
    - Consume request_ids on use (pop from registry) to prevent replay attacks
    
    Tests:
    - 8 new tests covering forged rejection, server-data enforcement,
      anti-replay, multiple independent approvals, and edge cases
    
    Co-authored-by: REDMOND\tusharmudi <tusharmudi@microsoft.com>
  • Python: Validate approval responses against server-side pending request registry (#4548)
    * Validate approval responses against server-side pending request registry
    
    * improvements
    
    * pin GHCP sdk version to non-breaking for now
    
    * Pin CHCP sdk to LKG.
    
    * really fix GHCP sdk pkg version
    
    * Fix HITL approval validation security gaps and memory leak
    
    - Validate rejected approval responses against pending_approvals registry,
      not just approved ones. Fabricated rejections without a prior request are
      now stripped from messages before reaching the LLM.
    - Bound _pending_approvals with OrderedDict + LRU eviction (max 10k) to
      prevent unbounded memory growth from abandoned approval requests.
    - Skip registration when function_call.name is None/empty; log warning
      when content.id or function_call is missing at registration time.
    - Document pending_approvals parameter in run_agent_stream docstring.
    - Add test for fabricated rejection attack scenario.
    - Assert pending approval entry is preserved after function name mismatch.
    - Pre-populate pending_approvals in rejection test for correct validation.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix function_approval_response extraction in AG-UI workflow path (#4550)
    * Extract function_approval_response from workflow messages (#4546)
    
    _extract_responses_from_messages now handles function_approval_response
    content in addition to function_result content. Previously, approval
    responses sent via the messages field were silently dropped because the
    function only checked for content.type == "function_result".
    
    The approval response is keyed by content.id and includes the approved
    status, id, and serialized function_call — consistent with how
    _coerce_content identifies approval response payloads.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Fix #4546: Update docstring and add integration tests for message-based approvals
    
    - Update _extract_responses_from_messages docstring to reflect that it
      now handles function_approval_response content in addition to
      function_result content.
    - Add integration tests for run_workflow_stream across two turns with
      approval responses provided via messages (function_approvals) rather
      than resume.interrupts, covering both approved and denied scenarios.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review feedback for #4546
    
    - Use safer 'not .get("interrupt")' assertion instead of 'not in'
      to handle Pydantic v2 model_dump() including keys with None values
    - Add unit test for mixed function_result and function_approval_response
      in the same message to TestExtractResponsesFromMessages
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix missing status input for OpenAI responses API (#4626)
    * Fix missing status input for OpenAI responses API
    
    * Fix mypy
    
    * Address comments
    
    * Remove raw_rep restore
    
    * Do not set status if it's None
  • Python: Implement annotation-based context compaction (#4469)
    * Implement annotation-based context compaction
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Handle missing compaction attributes in BaseChatClient
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix CI typing and bandit issues
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Optimize incremental compaction annotation pass
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * refinement
    
    * Python: add ToolResultCompactionStrategy and CompactionProvider
    
    Add ToolResultCompactionStrategy that collapses older tool-call groups
    into short summary messages (e.g. [Tool calls: get_weather]) while
    keeping the most recent groups verbatim. This mirrors the .NET
    ToolResultCompactionStrategy from PR #4533.
    
    Add CompactionProvider as a context-provider that auto-applies compaction
    before each agent turn and stores compacted history in session state
    after each turn.
    
    Includes tests and samples for both features.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * refinement and alignment with dotnet PR
    
    * updated tool result compaction
    
    * updated tool result compaction
    
    * Python: add ToolResultCompactionStrategy, CompactionProvider, and skip_excluded
    
    - ToolResultCompactionStrategy collapses older tool-call groups into
      [Tool results: func_name: result] summaries with bidirectional tracing
      (same pattern as SummarizationStrategy).
    - CompactionProvider as BaseContextProvider with separate before_strategy
      and after_strategy parameters. before_strategy compacts loaded context;
      after_strategy compacts stored history via history_source_id.
    - InMemoryHistoryProvider gains skip_excluded flag to filter out messages
      marked as excluded by compaction strategies.
    - Tests, samples, and exports updated.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fixed checks
    
    * fix mypy
    
    * Fix: ensure summary messages from both strategies get full compaction annotations
    
    SummarizationStrategy was not calling annotate_message_groups after
    inserting its summary message, so the summary lacked core group
    annotations (id, kind, index, has_reasoning, _excluded). Added the
    missing call. ToolResultCompactionStrategy already had it.
    
    Added tests verifying both strategies produce fully annotated summaries.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated propagation
    
    * fix mypy
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Support skill scripts execution (#4558)
    * support skill scripts execution
    
    * fix mixed line endings
    
    * address comments and fix syntax issues
    
    * use few try/except instead of one
    
    * change samples
    
    * validate either script path or script resource is set not both
    
    * fix: separate LLM args from runtime kwargs in skill script execution
    
    * address pr review comments
    
    * address PR review comments
    
    * Update python/packages/core/agent_framework/_skills.py
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Update python/packages/core/agent_framework/_skills.py
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Update python/packages/core/agent_framework/_skills.py
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * 1. Fixing the caching bug where parameters_schema would re-inspect on every call when the result was None
       2. Updating the arguments tool description to be more generic (not CLI-specific)
    
    * fix failing tests
    
    * address pr review comments
    
    * address pr review comments
    
    * allow resource function returning any instead of sting
    
    * address PR review comments
    
    ---------
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
  • Python: Fix broken link in purview README (504 on Microsoft 365 Dev Program URL) (#4610)
    * Initial plan
    
    * Fix broken link in purview README: replace 504-returning dev-program URL with stable learn.microsoft.com URL
    
    Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
  • Python: Fix executor_completed event with non-copyable raw_representation in mixed workflows (#4493)
    * Python: Fix `executor_completed` event with non-copyable raw_representation in mixed workflows
    
    Fixes #4455
    
    * fix(#4455): use class-level sets for deepcopy field exclusion
    
    - SerializationMixin.__deepcopy__: check type(self).DEFAULT_EXCLUDE
      instead of hardcoding 'raw_representation'
    - Content.__deepcopy__: add _SHALLOW_COPY_FIELDS class variable and
      check against it instead of hardcoding
    - Fix tautological assertion in test (was always True)
    - Add second excluded field to test to verify DEFAULT_EXCLUDE is
      respected generically
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Decouple __deepcopy__ from DEFAULT_EXCLUDE in SerializationMixin (#4455)
    
    Introduce _SHALLOW_COPY_FIELDS class variable in SerializationMixin to
    separate deep-copy semantics from serialization semantics. Previously,
    __deepcopy__ used DEFAULT_EXCLUDE to decide which fields to shallow-copy,
    conflating 'not serialized' with 'not safe to deep-copy'. A field added
    to DEFAULT_EXCLUDE purely for serialization (e.g. additional_properties)
    would be silently shared between original and copy.
    
    - Add _SHALLOW_COPY_FIELDS (default {'raw_representation'}) to
      SerializationMixin, matching the pattern already used by Content
    - Update __deepcopy__ to read from _SHALLOW_COPY_FIELDS instead of
      DEFAULT_EXCLUDE
    - Add test verifying DEFAULT_EXCLUDE fields are deep-copied unless
      also in _SHALLOW_COPY_FIELDS
    - Add test for Content._SHALLOW_COPY_FIELDS identity preservation
    - Add test for ChatResponse deep-copying additional_properties
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add test for _SHALLOW_COPY_FIELDS and DEFAULT_EXCLUDE independence
    
    Add test_deepcopy_shallow_copy_fields_override_default_exclude to verify
    that a field in both DEFAULT_EXCLUDE and _SHALLOW_COPY_FIELDS is
    shallow-copied (controlled by _SHALLOW_COPY_FIELDS), while a field in
    DEFAULT_EXCLUDE only is still deep-copied. This addresses review comment
    #11 ensuring the two class variables control independent concerns.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Remove unnecessary local variable in __deepcopy__
    
    Inline cls._SHALLOW_COPY_FIELDS directly in the loop check instead of
    assigning to a local variable first, per review feedback.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Prevent pickle deserialization of untrusted HITL HTTP input (#4566)
    * fix: prevent pickle deserialization of untrusted HITL input
    
    Add strip_pickle_markers() to sanitize HTTP input before it reaches
    pickle.loads() via the checkpoint decoding path. Applied as a 3-layer
    defence-in-depth:
    
    1. _app.py: sanitize req.get_json() at the HTTP boundary
    2. _workflow.py: sanitize in _deserialize_hitl_response() before decode
    3. _serialization.py: sanitize in reconstruct_to_type() as final guard
    
    Any dict containing __pickled__ or __type__ markers from untrusted
    sources is replaced with None, blocking arbitrary code execution via
    crafted payloads to POST /workflow/respond/{instanceId}/{requestId}.
    
    Includes 12 new unit tests covering the sanitizer and end-to-end
    attack prevention.
    
    * refactor: address review concerns for pickle fix
    
    1. Remove deserialize_value() fallback in _deserialize_hitl_response
       untrusted HITL data now returns as-is when no type hint is available,
       never flowing into pickle.loads().
    
    2. Move strip_pickle_markers() out of reconstruct_to_type()  the function
       is general-purpose again; untrusted-data callers are responsible for
       sanitizing first (documented with NOTE comment).
    
    3. Define _PICKLE_MARKER/_TYPE_MARKER as local constants with import-time
       assertions against core's values  decouples from private names while
       failing loudly if core ever changes them.
    
    4. Update tests to reflect new responsibility boundaries.
    
    * fix: simplify warning message and fix ruff RUF001 lint
    
    * fix: suppress pyright reportPrivateUsage on core marker imports
    
    * Lower marker-strip log from warning to debug to avoid log flooding
    
    * Replace assert with RuntimeError for marker sync checks (ruff S101)
    
    * Fix pyright and ruff CI errors in security fix
    
    - Use cast() for dict/list comprehensions in strip_pickle_markers (pyright)
    - type: ignore for narrowed dict return in _workflow.py (pyright)
    - Simplify marker imports: use core constants directly, remove local copies
    - Remove duplicate pyright ignore comment
    
    * Remove duplicate end-to-end test in TestStripPickleMarkers
    
    * Suppress mypy redundant-cast on list cast needed by pyright
  • Python: Fix store=False not overriding client default (#4569)
    * Fix store=False not overriding client default
    
    * Address comments
    
    * Fix unit tests
    
    * Fix integration tests
    
    * Fix tests
  • Auto-finalize ResponseStream on iteration completion (#4478)
    * Add multi-turn streaming sample and rename multi-turn samples
    
    - Rename 03_multi_turn.py to 03a_multi_turn.py
    - Add 03b_multi_turn_streaming.py showing streaming with session history
    - The new sample demonstrates calling get_final_response() after
      iterating the stream to persist conversation history
    - Update READMEs to reflect the new file names
    
    Closes #4447
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Auto-finalize ResponseStream on iteration completion
    
    When a ResponseStream is fully consumed via async iteration,
    automatically trigger finalization (finalizer + result hooks).
    This ensures session history is persisted in streaming multi-turn
    conversations without requiring an explicit get_final_response() call.
    
    - Add auto-finalize call in __anext__ on StopAsyncIteration
    - Guard inner stream finalization to prevent double-execution
    - Re-check _finalized after iteration in get_final_response()
    - Add tests for auto-finalization and streaming session history
    - Revert sample file renames from previous commit
    
    Closes #4447
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * README fix
    
    * Fix SIM102 lint: combine nested if statements
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Exclude conversation_id from chat completions API options (#4517)
    * Python: Exclude conversation_id from chat completions options (#4315)
    
    When a session with service_session_id is passed to an agent using the
    Chat Completions client, conversation_id leaked through _prepare_options()
    into AsyncCompletions.create(), causing an 'unexpected keyword argument'
    error. The Responses client already excluded conversation_id but the Chat
    Completions client did not.
    
    Added conversation_id to the exclusion set in _prepare_options().
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Remove reproduction report artifact
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix conversation-id propagation when chat_options is a dict (#4340)
    * Fix #4305: Handle dict chat_options in _update_conversation_id
    
    _update_conversation_id assumed chat_options had attribute access, but
    ChatOptions is a TypedDict (dict). When a dict was passed, setting
    .conversation_id raised AttributeError. Now checks isinstance(dict) and
    uses key access for dicts, falling back to attribute access for objects.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR feedback: use Mapping ABC and add missing tests (#4305)
    
    - Use collections.abc.Mapping instead of dict for isinstance check in
      _update_conversation_id, making it more robust for non-dict mapping types.
    - Add test for object-style chat_options with optional options dict parameter.
    - Add test verifying existing conversation_id gets overwritten (idempotent).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Remove unnecessary Mapping check in _update_conversation_id (#4305)
    
    chat_options is always a dict, so the isinstance(chat_opts, Mapping)
    check and the else branch for attribute-style access are dead code.
    Simplify to direct dict key assignment and remove object-style tests.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [Breaking] Upgrade to azure-ai-projects 2.0+ (#4536)
    * Prepare azure-ai-projects 2.0 GA compatibility
    
    Add allow_preview support for internal AIProjectClient creation, keep backward compatibility for renamed SDK model classes, and align Azure AI/core paths and tests for GA validation workflows.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * upgrade to ai-project==2.0.0
    
    * Python: remove azure-ai-projects keyword-guard paths
    
    Assume azure-ai-projects 2.0+ in Azure AI client/provider/responses code paths by removing _supports_keyword_argument gating and related fallback branching.
    
    Also fix pyright typing in FoundryMemoryProvider memory store calls by using ResponseInputItemParam-typed items.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * check fixes
    
    * Python: remove unsupported foundry_features option
    
    Drop foundry_features from Azure AI client and provider surfaces because azure-ai-projects 2.0.0 does not expose that create_version parameter.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: add allow_preview to Foundry memory provider
    
    Propagate allow_preview when FoundryMemoryProvider constructs an AIProjectClient and update tests accordingly.
    
    Also finish wiring allow_preview through AzureAIClient-facing surfaces and related docs.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * aligning docstrings
    
    * udpated lock
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • [BREAKING] Python: Update github-copilot-sdk integration to use ToolInvocation/ToolResult types (#4551)
    * Update github_copilot package for github-copilot-sdk>=0.1.32 (#4549)
    
    - Update requires-python from >=3.10 to >=3.11
    - Remove Python 3.10 classifier
    - Update mypy python_version to 3.11
    - Update dependency to github-copilot-sdk>=0.1.32
    - Fix ToolResult API: use snake_case kwargs (text_result_for_llm,
      result_type) instead of camelCase (textResultForLlm, resultType)
    - Update test assertions to use attribute access on ToolResult
    - Add ToolResult type assertions to tool handler tests
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix tests to use ToolInvocation dataclass instead of plain dict (#4549)
    
    Update test_github_copilot_agent.py to pass ToolInvocation objects to tool
    handlers instead of plain dicts, matching the github-copilot-sdk>=0.1.32 API
    where ToolInvocation is a dataclass with an .arguments attribute.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add regression tests for ToolInvocation contract (#4549)
    
    Add tests to lock in the new ToolInvocation-based calling convention:
    - test_tool_handler_rejects_raw_dict_invocation: verifies passing a raw
      dict (old calling convention) raises TypeError/AttributeError
    - test_tool_handler_with_empty_arguments: verifies ToolInvocation with
      empty arguments works correctly for no-arg tools
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Revert requires-python to >=3.10 to avoid breaking CI (#4549)
    
    The repo CI runs with Python 3.10 (uv sync --all-packages) and all other
    packages require >=3.10. Raising this package to >=3.11 would break the
    shared install flow. The SDK dependency version constraint (>=0.1.32) will
    enforce any Python version requirement from the SDK itself.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix min Python version for github_copilot package to >=3.11
    
    github-copilot-sdk>=0.1.32 requires Python>=3.11, which conflicts
    with the package's declared >=3.10 minimum, breaking uv sync.
    
    * Bump py version for GH workflows to 3.11, exclude GHCP sdk from 3.10 items
    
    * Fix uv command
    
    * Fixes
    
    * Update samples
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Improve ag-ui tests and coverage (#4442)
    * Improve ag-ui tests and coverage
    
    * fix tests paths
    
    * Fixes
    
    * Improve AG-UI test robustness and correctness
    
    - Map toolName → tool_call_name in SSE helpers for TOOL_CALL_START events
    - Fail loudly on malformed SSE JSON in parse_sse_response() instead of silently dropping
    - Detect duplicate TOOL_CALL_START/TOOL_CALL_END in assert_tool_calls_balanced()
    - Remove fragile source line reference from test docstring
    - Add found guard in test_client_tool_sets_additional_properties to prevent vacuous pass
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix RedisContextProvider for redisvl 0.14.0 by using AggregateHybridQuery (#3954)
    * Initial plan
    
    * Fix: Replace alpha with linear_alpha in HybridQuery for redisvl 0.14.0 compatibility
    
    Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
    
    * Address code review: Improve test readability and add explanatory comment
    
    Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
    
    * Add CHANGELOG entry for redisvl 0.14.0 compatibility fix
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * Use AggregateHybridQuery instead of HybridQuery for backward compatibility
    
    Replace HybridQuery with AggregateHybridQuery to preserve existing functionality that works with older Redis versions. The new HybridQuery in redisvl 0.14.0 requires Redis 8.4.0+ and uses a different API, while AggregateHybridQuery maintains compatibility with the original implementation.
    
    Co-authored-by: TaoChenOSU <12570346+TaoChenOSU@users.noreply.github.com>
    
    * Fix test to use linear_alpha parameter matching _redis_search implementation
    
    The test was passing alpha as a keyword argument to _redis_search(), but the
    method uses linear_alpha to match the redisvl 0.14.0 AggregateHybridQuery API.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix pyright error: use alpha parameter matching AggregateHybridQuery API
    
    AggregateHybridQuery expects 'alpha', not 'linear_alpha'. Updated the
    _redis_search method parameter and the test accordingly.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    Co-authored-by: TaoChenOSU <12570346+TaoChenOSU@users.noreply.github.com>
    Co-authored-by: Ben Thomas <ben.thomas@microsoft.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Propagated MCP isError flag through function middleware pipeline (#4511)
    * Propagated MCP isError flag through function middleware pipeline
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Small update
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix CI
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix as_agent() not defaulting name/description from client properties (#4484)
    * Fix as_agent() not defaulting name/description from client properties
    
    AzureAIClient.as_agent() and AzureAIAgentClient.as_agent() now fall back
    to self.agent_name and self.agent_description when name/description are
    not explicitly passed. This ensures Agent.name is populated for
    telemetry spans without requiring callers to repeat the name.
    
    Fixes #4471
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: use is None checks instead of truthiness
    
    Switch from name or self.agent_name to explicit is None checks so
    that callers can intentionally pass empty strings without them being
    replaced by client defaults. Added edge-case tests for empty strings.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Update docstrings to document name/description defaulting behavior
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Forward runtime kwargs to skill resource functions (#4417)
    * support code skills
    
    * address pr review comments
    
    * address package and syntax checks
    
    * address pr review comments
    
    * address pr review comment
    
    * address failed check
    
    * rename agentskill and agetnskillprovider
    
    * move agent skills related assets to _skills.py
    
    * address pr review comments
    
    * address review comments
    
    * support kwargs
    
    * address pr review feedback
  • Python: Fix Python pyright package scoping and typing remediation (#4426)
    * Fix Python pyright package scoping and typing remediation
    
    Implements issue #4407 by removing the root pyright include, adding package-level pyright includes, and resolving pyright/mypy typing issues across Python packages. Also cleans unnecessary casts and applies line-level, rule-specific ignores where external libraries are too dynamic.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Reduce pyright cost in handoff cloning
    
    Simplify cloned_options construction in HandoffAgentExecutor to avoid expensive TypedDict narrowing/inference in _handoff.py, which was causing pyright to spend a long time in orchestrations.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix types
    
    * Fix lint and type-check regressions
    
    Resolve current Python package check failures across lint, pyright, and mypy after recent code changes, including purview/declarative pyright issues and multiple ruff simplification findings.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fixed hooks
    
    * Stabilize package tests and test tasks
    
    Resolve cross-package non-integration test failures, simplify streaming type flow, harden locale/culture handling, and standardize package test poe tasks to exclude integration tests where applicable.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * lots of small fixes
    
    * Fix current Python test regressions
    
    Address current failing unit tests in azure-ai, bedrock, and azure-cosmos while keeping Bedrock parsing logic inline (no new static helper methods).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * small fixes
    
    * small fixes
    
    * removed pydantic from json
    
    * final updates
    
    * fix core
    
    * fix tests
    
    * fix obser
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Add propagate_session to as_tool() for session sharing in agent-as-tool scenarios (#4439)
    * Python: Add propagate_session parameter to as_tool() for session sharing
    
    Add opt-in session propagation in agent-as-tool scenarios. When
    propagate_session=True, the parent agent's AgentSession is forwarded
    to the sub-agent's run() call, allowing both agents to share session
    state (history, metadata, session_id).
    
    - Add propagate_session parameter to BaseAgent.as_tool() (default False)
    - Include session in additional_function_arguments so it flows to tools
    - Add 3 tests for propagation on/off and shared state verification
    - Add sample showing session propagation with observability middleware
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Clarify propagate_session docstring per review feedback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] Support code-defined agent skills (#4387)
    * support code skills
    
    * address pr review comments
    
    * address package and syntax checks
    
    * address pr review comments
    
    * address pr review comment
    
    * address failed check
    
    * rename agentskill and agetnskillprovider
    
    * move agent skills related assets to _skills.py
    
    * address pr review comments
    
    * address review comments
  • Python: feat(claude): add plugins, setting_sources, thinking, and effort options to ClaudeAgentOptions (#4425)
    * feat(claude): add plugins, setting_sources, thinking, and effort options
    
    Add four Claude Agent SDK options to ClaudeAgentOptions that are clean
    passthroughs with no abstraction conflicts:
    
    - plugins: load Claude Code plugins programmatically via SdkPluginConfig
    - setting_sources: control which .claude settings files are loaded
    - thinking: modern extended thinking config (adaptive/enabled/disabled)
    - effort: control thinking depth (low/medium/high/max)
    
    * feat(claude): remove max_thinking_tokens, add plugins/setting_sources/thinking/effort
    
    Remove the deprecated max_thinking_tokens field from ClaudeAgentOptions
    in favor of the new thinking field (ThinkingConfig).
    
    Add four Claude Agent SDK options as clean passthroughs:
    - plugins: load Claude Code plugins via SdkPluginConfig
    - setting_sources: control which .claude settings files are loaded
    - thinking: extended thinking config (adaptive/enabled/disabled)
    - effort: thinking depth control (low/medium/high/max)
  • Python: Fix PowerFx eval crash on non-English system locales by setting CurrentUICulture to en-US (#4408)
    * Fix #4321: Set CurrentUICulture to en-US in PowerFx eval()
    
    On non-English systems, CultureInfo.CurrentUICulture causes PowerFx to
    emit localized error messages. The existing ValueError guard only matches
    English strings ("isn't recognized", "Name isn't valid"), so undefined
    variable errors crash instead of returning None gracefully.
    
    Fix: save and restore CurrentUICulture alongside CurrentCulture before
    calling engine.eval(), ensuring error messages are always in English.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Reuse single CultureInfo instance to avoid redundant allocations
    
    Cache CultureInfo("en-US") in a local variable instead of instantiating
    it twice per eval() call, as suggested in PR review.
    
    Fixes #4321
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add assertion for CurrentUICulture restoration after eval
    
    Assert that the production code's finally-block correctly restores
    CurrentUICulture to it-IT after eval returns, covering future
    regressions where the culture could leak.
    
    The CultureInfo caching suggestion (comment #2) was already
    implemented in the production code.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix MCP tools duplicated on second turn when runtime tools are present (#4432)
    * Fix MCP tools duplicated on second turn when runtime tools are present
    
    When AG-UI's collect_server_tools pre-expands MCP functions on turn 2
    (after the MCP server is connected), _prepare_run_context unconditionally
    appends them again from self.mcp_tools, duplicating every MCP tool.
    
    Skip MCP functions whose names already exist in the final tool list,
    following the same name-based dedup pattern used in _merge_options.
    
    Fixes #4381
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * mypy fix
    
    * Remove issue-specific references from test docstring
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Upgraded azure-ai-projects to 2.0.0b4 (#4438)
    * Upgraded azure-ai-projects to 2.0.0b4
    
    * Fixed tests
  • Python: Fix: Parse oauth_consent_request events in Azure AI client (#4197)
    * Fix: Parse oauth_consent_request events in Azure AI client (#3950)
    
    When Azure AI Agent Service returns an oauth_consent_request output item
    for OAuth-protected MCP tools, the base OpenAI responses parser drops it
    (hits case _ default branch). This causes agent runs to complete silently
    with zero content.
    
    Changes:
    - Add oauth_consent_request ContentType and Content.from_oauth_consent_request()
      factory with consent_link field and user_input_request=True
    - Override _parse_response_from_openai and _parse_chunk_from_openai in
      RawAzureAIClient to intercept Azure-specific oauth_consent_request items
    - Add _emit_oauth_consent helper in AG-UI to emit CustomEvent for frontends
    - Add tests proving base parser drops the event and Azure AI override catches it
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * addressed comment
    
    * addressed comments
    
    * addressed comments
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Add file_ids and data_sources support to get_code_interpreter_tool() (#4201)
    * Python: Add file_ids and data_sources support to AzureAIAgentClient.get_code_interpreter_tool()
    
    Update the factory method to accept file_ids and data_sources keyword
    arguments, matching the underlying azure.ai.agents SDK CodeInterpreterTool
    constructor. This enables users to attach uploaded files for code
    interpreter analysis.
    
    Fixes #4050
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * addressed comments
    
    * addressed comments
    
    * Add per-message file attachment support for AzureAIAgentClient
    
    Add hosted_file handling in _prepare_messages() to convert
    Content.from_hosted_file() into MessageAttachment on ThreadMessageOptions.
    This enables per-message file scoping for code interpreter, matching the
    underlying Azure AI Agents SDK MessageAttachment pattern.
    
    - Add hosted_file case in _prepare_messages() match statement
    - Import MessageAttachment from azure.ai.agents.models
    - Add sample for per-message CSV file attachment with code interpreter
    - Add employees.csv test data file
    - Add 3 unit tests for hosted_file attachment conversion
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review: validation, fix assertions, remove MessageAttachment
    
    - Add empty string validation in resolve_file_ids()
    - Add test for Content with file_id=None
    - Add test for empty string file_ids
    - Revert MessageAttachment/hosted_file handling from _prepare_messages()
      (moved to separate issue #4352 for proper design)
    - Remove per-message file upload sample and employees.csv
    - Keep data_sources assertion as-is (dict keyed by asset_identifier)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix workflow tests pyright warnings (#4362)
    * Fix workflow tests pyright warnings
    
    * Update uv.lock
    
    * Fix pyright
    
    * Comments
    
    * Update root pyproject pyright setting
    
    * Update core pyproject pyright setting
    
    * Update core pyproject pyright setting
  • Python: Add OpenTelemetry instrumentation to ClaudeAgent (#4278) (#4326)
    * Python: Add OpenTelemetry instrumentation to ClaudeAgent (#4278)
    
    Add inline telemetry to ClaudeAgent.run() so that enable_instrumentation()
    emits invoke_agent spans and metrics. Covers both streaming and
    non-streaming paths using the same observability helpers as
    AgentTelemetryLayer. Adds 5 unit tests for telemetry behavior.
    
    Co-Authored-By: amitmukh <amimukherjee@microsoft.com>
    
    * Address PR review feedback for ClaudeAgent telemetry
    
    - Add justification comment for private observability API imports
    - Pass system_instructions to capture_messages for system prompt capture
    - Use monkeypatch instead of try/finally for test global state isolation
    
    Co-Authored-By: amitmukh <amitmukh@users.noreply.github.com>
    Co-Authored-By: Claude <noreply@anthropic.com>
    
    * Adopt AgentTelemetryLayer instead of inline telemetry
    
    Restructure ClaudeAgent to inherit from AgentTelemetryLayer via a
    _ClaudeAgentRunImpl mixin, eliminating duplicated telemetry code and
    private API imports.
    
    MRO: ClaudeAgent → AgentTelemetryLayer → _ClaudeAgentRunImpl → BaseAgent
    
    - Remove inline _run_with_telemetry / _run_with_telemetry_stream methods
    - Remove private observability helper imports (_capture_messages, etc.)
    - Add default_options property mapping system_prompt → instructions
    - Net -105 lines by reusing core telemetry layer
    
    Co-Authored-By: amitmukh <amitmukh@users.noreply.github.com>
    Co-Authored-By: Claude <noreply@anthropic.com>
    
    * Fix mypy: align _ClaudeAgentRunImpl.run() signature with AgentTelemetryLayer.run()
    
    Remove explicit `options` parameter from mixin's run() signature and
    extract it from **kwargs to match AgentTelemetryLayer's signature.
    Also align overload return types (ResponseStream, Awaitable) to match.
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    
    * Introduce RawClaudeAgent following framework's RawAgent/Agent pattern
    
    Replace private _ClaudeAgentRunImpl mixin with public RawClaudeAgent
    class that contains all core logic (init, run, lifecycle, tools).
    ClaudeAgent becomes a thin wrapper that adds AgentTelemetryLayer.
    
    - RawClaudeAgent(BaseAgent): full implementation without telemetry
    - ClaudeAgent(AgentTelemetryLayer, RawClaudeAgent): adds OTel tracing
    - Export RawClaudeAgent from package __init__.py
    
    Users who want to skip telemetry or provide their own can use
    RawClaudeAgent directly.
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    
    * Address review nits: trim RawClaudeAgent docstring, fix import paths
    
    - Simplify RawClaudeAgent docstring to a single basic example (not the
      primary entry point for most users)
    - Use agent_framework.anthropic import path in docstrings instead of
      direct agent_framework_claude path
    - Add RawClaudeAgent to agent_framework.anthropic lazy re-exports
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Amit Mukherjee <amimukherjee@microsoft.com>
    Co-authored-by: amitmukh <amitmukh@users.noreply.github.com>
    Co-authored-by: Claude <noreply@anthropic.com>
    Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
  • Python: Fix StandardMagenticManager to propagate session to manager agent (#4409)
    * Fix #4371: Propagate session to manager agent in StandardMagenticManager
    
    StandardMagenticManager._complete() was calling self._agent.run(messages)
    without passing a session. This caused context providers (e.g.
    RedisHistoryProvider) configured on the manager agent to silently fail,
    as each call created a new ephemeral session with a different session_id.
    
    Changes:
    - Create an AgentSession in StandardMagenticManager.__init__()
    - Pass session=self._session in _complete() calls to agent.run()
    - Persist/restore the session in checkpoint save/restore methods
    - Add regression tests for session propagation and checkpoint round-trip
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add type: ignore[reportPrivateUsage] to private attribute assertions in tests
    
    Address PR review feedback: add # type: ignore[reportPrivateUsage] comments
    to _session attribute accesses in the new regression tests, matching the
    existing convention used elsewhere in test_magentic.py (e.g., lines 401-406).
    
    The @pytest.mark.asyncio decorator is not needed because pyproject.toml
    sets asyncio_mode = "auto".
    
    Fixes #4371
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: use getattr for private _session access in tests (#4371)
    
    Replace direct mgr._session access with getattr(mgr, "_session") to avoid
    reportPrivateUsage type-checking warnings without needing type: ignore comments.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Address PR review: fix session restore guard and improve test robustness (#4371)
    
    - Use 'is not None' instead of truthiness check for session_payload restore
    - Use getattr() for private _session attribute access in tests
    - Add backward-compatibility test for on_checkpoint_restore with empty state
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Make non-async tests plain def to avoid pytest-asyncio dependency (#4409)
    
    Tests that never await anything don't need to be async. Using plain def
    ensures they always run regardless of pytest-asyncio configuration.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Added Shell tool (#4339)
    * Added shell tool
    
    * Fixed CI error
    
    * Add ShellTool support for OpenAI and Anthropic providers
    
    - Add shell_tool_call, shell_tool_result, and shell_command_output content types
    - Add ShellTool class and shell_tool decorator to core
    - Add get_hosted_shell_tool() to OpenAI Responses client
    - Handle shell_call and shell_call_output parsing in OpenAI (sync and streaming)
    - Map ShellTool to Anthropic bash tool API format
    - Parse bash_code_execution_tool_result as shell_tool_result in Anthropic
    - Add unit tests for all new functionality
    - Add sample scripts for hosted and local shell execution
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Addressed comments
    
    * Reverted ruff change
    
    * Fixed tests
    
    * Addressed comments
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix IndexError when reasoning models produce reasoning-only messages in Magentic-One workflow (#4413)
    * Fix IndexError when reasoning models return no text content (#4384)
    
    In _prepare_message_for_openai(), the text_reasoning case unconditionally
    accessed all_messages[-1] to attach reasoning_details. When a reasoning
    model (e.g. gpt-5-mini) returns reasoning_details without text content,
    all_messages is empty, causing an IndexError.
    
    Guard the access by initializing all_messages with the current args dict
    when it is empty, so reasoning_details can be safely attached.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: buffer reasoning details for valid message payloads (#4384)
    
    - Buffer pending reasoning details and attach to the next message with
      content/tool_calls, avoiding standalone reasoning-only messages.
    - When reasoning is the only content, emit a message with empty content
      to satisfy Chat Completions schema requirements.
    - Strengthen test assertions to verify text+reasoning co-location and
      that all messages with reasoning_details also have content or tool_calls.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix text_reasoning handling: always buffer and tighten tests (#4384)
    
    - Always buffer reasoning into pending_reasoning instead of conditionally
      attaching to the previous message via fragile all_messages emptiness check
    - Attach buffered reasoning to last message at end-of-loop when no subsequent
      content consumed it
    - Assert exact content values (content == '' not in ('', None))
    - Assert exact list lengths (== 1 not >= 1) for stronger regression guards
    - Add test for reasoning before FunctionCallContent
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Add Azure Cosmos history provider package (#4271)
    * Created cosmos history provider
    
    * add marker
    
    * Python: address Cosmos PR feedback
    
    - address provider/test/sample review feedback and cleanup typing
    - add cosmos integration test coverage and skip gating
    - add dedicated cosmos emulator jobs to python merge/integration workflows
    - switch cosmos workflow execution to package poe integration-tests task
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: handle empty Cosmos session id
    
    - replace default partition fallback for empty session_id
    - log warning and generate GUID when session_id is empty
    - update unit tests to validate GUID fallback behavior
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix sample
    
    * fix cross partition query
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Add regression tests for Entry JoinExecutor Workflow.Inputs initialization (#4335)
    * Python: Add regression tests for #3948 - Entry JoinExecutor initializes Workflow.Inputs
    
    Add tests verifying that when workflow.run() is called with a dict or string
    input, the Entry node (JoinExecutor with kind: 'Entry') correctly initializes
    Workflow.Inputs via _ensure_state_initialized so that:
    - Expressions like =inputs.age resolve to the correct value
    - Conditions like =Local.age < 13 evaluate based on actual input (not blank/0)
    - String inputs populate both inputs.input and System.LastMessage.Text
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Fix D420 and RUF070 lint errors across packages
    
    * Revert _workflow.py yield-inside-context-manager changes
    
    Moving yield inside `with _framework_event_origin()` blocks in the
    async generator causes ContextVar token reset failures on Python 3.12
    Windows. The token stays un-reset while the generator is suspended,
    and async generator finalization in a different contextvars.Context
    triggers ValueError, corrupting OpenTelemetry span state and causing
    test_span_creation_and_attributes to see leaked spans.
    
    Keep yields outside the context manager blocks to ensure tokens are
    reset immediately before the generator suspends.
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: fix(python): Handle thread.message.completed event in Assistants API streaming (#4333)
    * fix: handle thread.message.completed event in Assistants API streaming
    
    Previously, `thread.message.completed` events fell through to the
    catch-all `else` branch and yielded empty `ChatResponseUpdate` objects,
    silently discarding fully-resolved annotation data (file citations,
    file paths, and their character-offset regions).
    
    This commit adds a dedicated handler for `thread.message.completed`
    that:
    - Walks the completed ThreadMessage.content array
    - Extracts text blocks with their fully-resolved annotations
    - Maps FileCitationAnnotation and FilePathAnnotation to the
      framework's Annotation type with proper TextSpanRegion data
    - Yields a ChatResponseUpdate containing the complete text and
      annotations
    
    Fixes #4322
    
    * test: add tests for thread.message.completed annotation handling
    
    Tests cover:
    - File citation annotation extraction
    - File path annotation extraction
    - Multiple annotations on a single text block
    - Text-only messages (no annotations)
    - Non-text blocks are skipped
    - Mixed content blocks (text + image)
    - Conversation ID propagation
    
    * fix: address Copilot review - add quote field and log unrecognized annotations
    
    - Include `quote` from `annotation.file_citation.quote` in
      `additional_properties` for FileCitationAnnotation, preserving the
      exact cited text snippet from the source file
    - Add `else` clause to log unrecognized annotation types at debug level,
      consistent with the pattern in `_responses_client.py`
    - Add `import logging` and module-level logger
    
    * test: add coverage for quote field and unrecognized annotation logging
    
    - test_message_completed_with_file_citation_quote: verifies quote is
      included in additional_properties
    - test_message_completed_with_file_citation_no_quote: verifies quote
      is omitted when None
    - test_message_completed_unrecognized_annotation_logged: verifies
      unknown annotation types are logged at debug level and skipped
    
    * fix: address reviewer nits — logger name convention + annotation type string
    
    Per @giles17's review:
    - Use logging.getLogger('agent_framework.openai') to match module convention
    - Simplify debug message to use annotation.type instead of type().__name__
    
    * refactor: move message.completed tests into consolidated test file
    
    Per @giles17's review: moved all tests from test_assistants_message_completed.py
    into test_openai_assistants_client.py and deleted the standalone file.
    
    * fix: resolve mypy no-redef and ruff RET504 lint errors
    
    - Remove duplicate type annotation for 'ann' variable (no-redef)
    - Return directly from fixture instead of unnecessary assignment (RET504)
    
    * fix: rename annotation variable in completed block to fix mypy type conflict
    
    The 'annotation' loop variable in thread.message.completed has type
    FileCitationAnnotation | FilePathAnnotation, which conflicts with the
    delta block's 'annotation' of type FileCitationDeltaAnnotation |
    FilePathDeltaAnnotation. Renamed to 'completed_annotation' to avoid
    mypy 'Incompatible types in assignment' error.
    
    * fix: remove quote field from FileCitationAnnotation handling
    
    ---------
    
    Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
  • Python: Fix walrus operator precedence for model_id kwarg in AzureOpenAIResponsesClient (#4310)
    * Fix walrus operator precedence for model_id in AzureOpenAIResponsesClient (#4299)
    
    Add parentheses around the walrus assignment so model_id receives the
    actual string value instead of the boolean result of
    `kwargs.pop(...) and not deployment_name`.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: replace walrus with explicit None check, add edge-case tests (#4299)
    
    - Replace walrus operator with explicit assignment and 'is not None'
      check to avoid boolean-coercion pitfalls (empty string now correctly
      surfaces as ValueError instead of silently falling back)
    - Add test: deployment_name takes precedence over model_id kwarg
    - Add test: model_id='' raises ValueError
    - Add test: model_id=None falls back to env var
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add explicit validation for empty model_id in AzureOpenAIResponsesClient
    
    Reject empty or whitespace-only model_id with ValueError instead of
    silently passing an empty deployment name downstream. This ensures the
    test_init_model_id_kwarg_empty_string test correctly validates behavior
    defined in production code rather than relying on downstream validation.
    
    Addresses PR review feedback for #4299.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Simplify model_id handling using walrus operator
    
    Addresses review comment on PR #4310.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Restore explicit model_id validation to fix test failures (#4299)
    
    The walrus operator refactor silently dropped the empty-string validation,
    causing test_init_model_id_kwarg_empty_string to fail. Restore the explicit
    None check and ValueError raise for empty model_id.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Revert "Restore explicit model_id validation to fix test failures (#4299)"
    
    This reverts commit 1d2965fff6.
    
    * Revert to walrus operator fix per review feedback
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: .NET: Fix .NET conversation memory in DevUI (#3484) (#4294)
    * Fix .NET conversation memory in DevUI (#3484)
    
    * formatting fixes
    
    * fix memory regression in python devui , fix for #4123
    
    * Fix for #3983: Added _get_event_type() helper that safely accesses event type on both objects (.type) and dicts (.get("type")). Replaced all 4 bare event.type accesses in _executor.py (lines 267, 477, 499, 523).
    
    Root cause: PR #3690 changed event.__class__.__name__ == "RequestInfoEvent" (safe) to event.type == "request_info" (crashes on dicts), but _execute_workflow still yields raw dicts on error paths.
    
    Test: test_workflow_error_yields_dict_event_without_crash — mocks a workflow that raises, verifies execute_entity consumes the dict error events without crashing.
    
    * format fixes
    
    * lint fixes
  • Python: Fix executor handler type resolution when using from __future__ import annotations (#4317)
    * Python: Fix Executor handler type checking with __future__ annotations (#3898)
    
    Use typing.get_type_hints() in _validate_handler_signature to resolve
    string annotations from `from __future__ import annotations`. This
    mirrors the fix applied to FunctionExecutor in #2308.
    
    When __future__ annotations are enabled, type annotations are stored as
    strings. The handler decorator was passing these strings directly to
    validate_workflow_context_annotation, which uses typing.get_origin and
    returns None for strings, causing a ValueError.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review feedback for #3898: improve error handling and test coverage
    
    - Wrap typing.get_type_hints() in try/except to provide a descriptive
      ValueError mentioning the handler name when annotations cannot be resolved
    - Strengthen bare context test to assert output_types and workflow_output_types
    - Add test for @handler(input=..., output=...) with future annotations
      covering the skip_message_annotation branch
    - Add test for union-type context annotations with future annotations
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Narrow exception catch and add test for unresolvable annotations (#3898)
    
    - Narrow except clause from bare Exception to (NameError, AttributeError,
      TypeError) to avoid masking unexpected errors.
    - Add test_handler_unresolvable_annotation_raises to verify that a handler
      with a forward-reference to a non-existent type raises ValueError with
      the expected message.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix #3898: fall back to raw annotations when get_type_hints fails
    
    When typing.get_type_hints(func) raises NameError (unresolvable forward
    ref), AttributeError, RecursionError, or any other exception, fall back
    to the raw parameter annotations instead of raising a ValueError.
    This matches the suggestion from @moonbox3 on PR #4317.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix test to match new fallback behavior when get_type_hints fails (#3898)
    
    The code now falls back to raw string annotations instead of raising
    'Failed to resolve type annotations'. A ValueError is still raised when
    the raw string ctx annotation is not a valid WorkflowContext type, so
    update the test to match on ValueError without checking the message.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pyupgrade: remove unnecessary string annotation quote
    
    * Add noqa for intentionally undefined name in annotation test
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Tuning auto sample validation workflow (#4218)
    * Tuning validate-01-get-started
    
    * Add gh token
    
    * Add model
    
    * enable debug log
    
    * bump up timeout for testing purposes
    
    * Test cli is working
    
    * Fix end quote
    
    * Run gh auth
    
    * Run gh auth trail 2
    
    * Run gh auth trail 3
    
    * Test token
    
    * Add zcure login
    
    * Add zcure login 2
    
    * Add zcure login 3
    
    * Add zcure login 4
    
    * Extract common actions
    
    * Extract common actions 2
    
    * Correct env vars
    
    * Print outputs to action console
    
    * Disable end-to-end samples
    
    * Fix ruff errors
    
    * Fix ruff errors 2
    
    * Revert workflow changes to fix tests
    
    * Revert workflow changes to fix tests 2
    
    * Revert workflow changes to fix tests 3
    
    * Revert workflow changes to fix tests 4
  • Python: Fix agent option merge to support dict-defined tools (#4314)
    * Fix _merge_options dropping dict-defined tools (#4303)
    
    _merge_options used getattr(tool, 'name', None) to de-duplicate tools,
    which returns None for dict-style tool definitions. This caused all
    override dict tools to be treated as duplicates of each other and of any
    base dict tools, silently dropping them.
    
    Add _get_tool_name() helper that extracts the name from both object-style
    tools (via .name attribute) and dict-style tools (via tool['function']['name']).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: fix None dedup bug and add comprehensive tests (#4303)
    
    - Exclude None from existing_names set so nameless/malformed tools are
      not silently deduplicated against each other
    - Add test for cross-type dedup (dict tool + object tool with same name)
    - Add test verifying nameless tools are preserved (not falsely deduped)
    - Add unit tests for _get_tool_name edge cases: missing function key,
      non-dict function value, missing name, no name attribute, non-dict
      inputs, and valid dict/object tools
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix single-tool input handling in OpenAIResponsesClient._prepare_tools_for_openai (#4312)
    * Fix OpenAIResponsesClient mishandling single-tool inputs (#4304)
    
    Use normalize_tools() in _prepare_tools_for_openai to wrap single tools
    (FunctionTool or dict) in a list before iteration, consistent with the
    chat client implementation.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review feedback for #4304
    
    - Use precise type annotation matching normalize_tools/OpenAIChatClient signature
      instead of collapsed Sequence[Any] | Any | None
    - Move emptiness guard after normalize_tools() call so single falsy tool
      objects are not silently swallowed
    - Import ToolTypes for the type annotation
    - Expand test_prepare_tools_for_openai_single_function_tool assertions to
      verify parameters, strict, and parameter schema fields
    - Add test_prepare_tools_for_openai_none to verify None input returns []
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix WorkflowAgent not persisting response messages to session history (#1694) (#4319)
    WorkflowAgent._run_impl() and _run_stream_impl() did not set
    session_context._response before calling _run_after_providers().
    This caused InMemoryHistoryProvider.after_run() to see context.response
    as None, so response messages were never stored in the session.
    
    On subsequent runs, the workflow only received prior user inputs without
    assistant responses, breaking multi-turn conversations.
    
    Fix: Set session_context._response to the workflow result before running
    after_run providers, matching the behavior of the regular Agent class.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>