121 Commits

  • Python: Add opt-in AG-UI thread snapshot persistence and hydration (#6471)
    * feat(ag-ui): add thread snapshot store primitives
    
    Key decisions:\n- Introduce an AGUIThreadSnapshot model limited to replayable messages, optional Shared State, and optional interrupt state.\n- Define AGUIThreadSnapshotStore as an async protocol keyed by explicit Snapshot Scope and AG-UI Thread id.\n- Add InMemoryAGUIThreadSnapshotStore as memory-only, latest-only, bounded local/demo/test storage; no file-backed store is introduced.\n- Require snapshot_scope_resolver whenever an endpoint is configured with a snapshot store, including pre-wrapped runners, so thread ids are not authorization boundaries.\n\nFiles changed:\n- packages/ag-ui/agent_framework_ag_ui/_snapshots.py\n- packages/ag-ui/agent_framework_ag_ui/__init__.py\n- packages/ag-ui/agent_framework_ag_ui/_agent.py\n- packages/ag-ui/agent_framework_ag_ui/_workflow.py\n- packages/ag-ui/agent_framework_ag_ui/_endpoint.py\n- packages/core/agent_framework/ag_ui/__init__.py\n- packages/core/agent_framework/ag_ui/__init__.pyi\n- packages/ag-ui/tests/ag_ui/test_snapshots.py\n- packages/ag-ui/tests/ag_ui/test_endpoint.py\n- packages/ag-ui/tests/ag_ui/test_public_exports.py\n- packages/ag-ui/AGENTS.md\n\nVerification:\n- uv run pytest packages/ag-ui/tests/ag_ui/test_snapshots.py packages/ag-ui/tests/ag_ui/test_public_exports.py packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_requires_snapshot_scope_resolver_when_store_configured packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_accepts_snapshot_store_with_scope_resolver -q\n- uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_requires_snapshot_scope_resolver_when_store_configured packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_requires_snapshot_scope_resolver_when_wrapped_runner_has_store packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_accepts_snapshot_store_with_scope_resolver -q\n- uv run poe syntax -P ag-ui -C\n- uv run poe pyright -P ag-ui\n- uv run poe syntax -P core -C\n- uv run poe pyright -P core\n- uv run poe typing -P ag-ui\n- uv run poe typing -P core\n- uv run poe test -P ag-ui\n- uv run poe check -P ag-ui\n- git diff --check\n- git diff --cached --check\n\nBlockers / next iteration:\n- No blockers. Next slice can use the store contract to capture and hydrate agent snapshots.\n- uv repeatedly refreshed azure-ai-projects in uv.lock during local runs; reverted the generated lockfile churn because this change does not alter dependencies.\n- The poe-check commit hook was skipped after manual verification because it reformatted unrelated core MCP files outside this task.
    
    * feat(ag-ui): hydrate agent threads from snapshots
    
    Key decisions:
    - Resolve Snapshot Scope per endpoint request and pass it to the AG-UI runner only when snapshot storage is active.
    - Treat empty messages with no resume payload as an agent Hydrate Request when a scoped snapshot store is configured, replaying stored Shared State and message snapshots without invoking the wrapped agent.
    - Save the latest replayable agent message snapshot and Shared State at normal completion under Snapshot Scope plus AG-UI Thread id; no durable or file-backed store is introduced.
    
    Files changed:
    - packages/ag-ui/agent_framework_ag_ui/_agent_run.py
    - packages/ag-ui/agent_framework_ag_ui/_endpoint.py
    - packages/ag-ui/agent_framework_ag_ui/_snapshots.py
    - packages/ag-ui/tests/ag_ui/test_endpoint.py
    
    Verification:
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_stored_thread_snapshot_without_invoking_agent -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_stored_thread_snapshot_without_invoking_agent packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_snapshots_by_scope_and_thread -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_empty_messages packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_stored_thread_snapshot_without_invoking_agent packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_snapshots_by_scope_and_thread -q
    - uv run poe syntax -P ag-ui -C
    - uv run poe pyright -P ag-ui
    - uv run poe typing -P ag-ui
    - uv run poe test -P ag-ui
    - uv run poe check -P ag-ui
    - git diff --check
    - git diff --cached --check
    
    Blockers / next iteration:
    - No blockers. Next slice can reconstruct normal new-user agent turns from stored snapshots.
    - uv repeatedly refreshed azure-ai-projects in uv.lock during local runs; reverted the generated lockfile churn because this change does not alter dependencies.
    - The poe-check commit hook was skipped after manual verification because it refreshed unrelated uv.lock dependency resolution.
    
    * feat(ag-ui): reconstruct agent turns from snapshots
    
    Key decisions:
    - Load scoped thread snapshots for non-hydrate agent requests only when snapshot storage is active and no resume payload is present.
    - Rebuild prior AG-UI history from stored snapshot messages, preserving the incoming new user suffix and treating stored snapshot content as authoritative over conflicting prior client history.
    - Merge stored Shared State with request state overrides before schema defaults and existing state-context injection.
    
    Files changed:
    - packages/ag-ui/agent_framework_ag_ui/_agent_run.py
    - packages/ag-ui/tests/ag_ui/test_endpoint.py
    
    Verification:
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_prepends_stored_snapshot_for_new_user_turn -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_deduplicates_full_history_and_merges_fresh_state -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_endpoint_empty_messages packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_stored_thread_snapshot_without_invoking_agent packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_snapshots_by_scope_and_thread packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_prepends_stored_snapshot_for_new_user_turn packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_deduplicates_full_history_and_merges_fresh_state -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py -q
    - uv run poe syntax -P ag-ui -C
    - uv run poe pyright -P ag-ui
    - uv run poe test -P ag-ui
    - uv run poe check -P ag-ui
    - uv run poe typing -P ag-ui
    - git diff --check
    - git diff --cached --check
    
    Blockers / next iteration:
    - No blockers. Next slice can enable workflow AG-UI Thread Snapshot persistence and hydration.
    - uv repeatedly refreshed azure-ai-projects in uv.lock during local runs; reverted the generated lockfile churn because this change does not alter dependencies.
    - The poe-check commit hook was skipped after manual verification because it refreshes unrelated uv.lock dependency resolution.
    
    * feat(ag-ui): hydrate workflow threads from snapshots
    
    Key decisions:
    - Handle workflow Hydrate Requests before resolving or invoking the wrapped workflow when snapshot storage and Snapshot Scope are active.
    - Capture only replayable workflow protocol data: workflow-emitted state snapshots, workflow-emitted message snapshots, and synthesized messages from text/tool output.
    - Keep workflow snapshot capture inactive without configured persistence, and skip saving snapshots when the workflow stream emits RUN_ERROR.
    
    Files changed:
    - packages/ag-ui/agent_framework_ag_ui/_workflow.py
    - packages/ag-ui/tests/ag_ui/test_endpoint.py
    
    Verification:
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_workflow_endpoint_hydrates_emitted_snapshots_without_invoking_workflow packages/ag-ui/tests/ag_ui/test_endpoint.py::test_workflow_endpoint_hydrates_synthesized_text_and_tool_snapshot -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py -q
    - uv run pytest packages/ag-ui/tests/ag_ui/golden/test_scenario_workflow.py -q
    - uv run poe syntax -P ag-ui -C
    - uv run poe pyright -P ag-ui
    - uv run poe test -P ag-ui
    - uv run poe typing -P ag-ui
    - uv run poe check -P ag-ui
    - git diff --check
    - git diff --cached --check
    
    Blockers / next iteration:
    - No blockers. Next slice can preserve interruption state and protect snapshots on errors across agent and workflow endpoints.
    - uv repeatedly refreshed azure-ai-projects in uv.lock during local runs; reverted the generated lockfile churn because this change does not alter dependencies.
    - The poe-check commit hook was skipped after manual verification because it refreshes unrelated uv.lock dependency resolution.
    
    * feat(ag-ui): preserve interrupted thread snapshots
    
    Key decisions:
    - Capture workflow RUN_FINISHED interrupt metadata in replayable AG-UI Thread Snapshots so Hydrate Requests can restore pending workflow actions without invoking or resuming the workflow.
    - Keep failed agent and workflow runs from replacing the last good snapshot; RUN_ERROR streams leave the previous snapshot available for hydration.
    - Verify interruption hydration through endpoint-level AG-UI streams for both agent and workflow wrappers, including Shared State replay and no wrapped runner invocation.
    
    Files changed:
    - packages/ag-ui/agent_framework_ag_ui/_workflow.py
    - packages/ag-ui/tests/ag_ui/test_endpoint.py
    
    Verification:
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_workflow_endpoint_hydrates_interrupted_thread_without_invoking_workflow -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_hydrates_interrupted_thread_without_invoking_agent packages/ag-ui/tests/ag_ui/test_endpoint.py::test_agent_endpoint_run_error_does_not_overwrite_previous_snapshot packages/ag-ui/tests/ag_ui/test_endpoint.py::test_workflow_endpoint_hydrates_interrupted_thread_without_invoking_workflow packages/ag-ui/tests/ag_ui/test_endpoint.py::test_workflow_endpoint_run_error_does_not_overwrite_previous_snapshot -q
    - uv run pytest packages/ag-ui/tests/ag_ui/test_endpoint.py -q
    - uv run pytest packages/ag-ui/tests/ag_ui/golden/test_scenario_workflow.py -q
    - uv run poe syntax -P ag-ui -C
    - uv run poe pyright -P ag-ui
    - uv run poe test -P ag-ui
    - uv run poe typing -P ag-ui
    - uv run poe check -P ag-ui
    - git diff --check
    - git diff --cached --check
    
    Blockers / next iteration:
    - No blockers. Next slice can document AG-UI Thread Snapshot security and usage.
    - uv repeatedly refreshed azure-ai-projects in uv.lock during local runs; reverted the generated lockfile churn because this change does not alter dependencies.
    - The poe-check commit hook was skipped after manual verification because it refreshes unrelated uv.lock dependency resolution.
    
    * docs(ag-ui): document thread snapshot security
    
    Key decisions:
    - Document AG-UI Thread Snapshot persistence as opt-in and disabled unless a snapshot_store is configured.
    - Place Snapshot Scope guidance next to endpoint authentication guidance, making clear that AG-UI Thread ids identify threads but do not authorize snapshot access.
    - Describe built-in storage as in-memory only, process-local, latest-only, and not durable production storage; durable stores remain app-owned implementations of AGUIThreadSnapshotStore.
    - Call out snapshot confidentiality impact and that no file-backed AG-UI snapshot store is provided.
    
    Files changed:
    - packages/ag-ui/README.md
    
    Verification:
    - uv run python scripts/check_md_code_blocks.py packages/ag-ui/README.md --no-glob
    - git diff --check
    - git diff --cached --check
    - commit hook without SKIP ran changed-package lint/format and AG-UI README markdown-code-lint successfully before stopping because uv.lock was modified
    - uv run poe markdown-code-lint (failed due existing unrelated packages/mistral/README.md missing agent_framework_mistral import resolution; changed AG-UI README blocks passed)
    
    Blockers / next iteration:
    - No blockers. Local issue/PRD planning artifacts remain uncommitted.
    - uv refreshed azure-ai-projects in uv.lock during markdown lint and the commit hook; reverted the generated lockfile churn because this documentation change does not alter dependencies.
    - The poe-check commit hook was skipped after manual verification because it refreshes unrelated uv.lock dependency resolution.
    
    * fix(ag-ui): harden thread snapshot persistence edge cases
    
    - Persist the completed confirm_changes turn with interrupt=None so hydration
      no longer replays a stale pending interrupt after the user responds; resume
      requests prepend stored history so the persisted thread is not truncated.
    - Defer endpoint default_state application to the runners when snapshot
      persistence is active, filling only keys missing from both the stored
      snapshot state and the request state so defaults never reset persisted
      Shared State.
    - Always fold the turn's output into the persisted messages snapshot even when
      the outbound MESSAGES_SNAPSHOT event is suppressed for predictive tools
      without confirmation.
    - Load the stored snapshot on workflow follow-up turns, reconstruct full
      thread history into the run input, and seed the snapshot builder with merged
      state so saving a new turn no longer replaces prior history.
    - Move snapshot message reconstruction helpers to _run_common for reuse by the
      workflow runner; load stored agent snapshots on resume turns for state merge.
    - Add endpoint regression tests for all four scenarios.
    
    * fix(ag-ui): protect snapshot history on resume and harden suffix trust
    
    - Prepend stored thread history when persisting snapshots for resume runs on
      both the agent and workflow paths, so a resumed interrupt no longer
      overwrites the stored thread with just the resume turn's output.
    - Filter the incoming message suffix during thread reconstruction: only user
      turns and tool results answering backend-issued tool calls (stored tool
      calls or pending interrupts) may extend authoritative history. Client-forged
      assistant and tool messages are dropped and logged instead of being
      persisted and replayed.
    - Close the workflow snapshot builder's tool-call group when a tool result or
      text message lands, so synthesized transcripts keep tool results adjacent to
      their tool_calls message and stay valid as provider replay history.
    - Export DEFAULT_MAX_THREAD_SNAPSHOTS from agent_framework_ag_ui and expose
      SnapshotScopeResolver through the core ag_ui facade and stub.
    - Add regression tests for agent and workflow resume history preservation,
      forged suffix rejection, builder tool-call grouping, and the export surface.
    
    * fix(ag-ui): tolerate snapshot save failures and scope workflow cache
    
    - Wrap snapshot_store.save() on both the agent and workflow paths so a
      transient store failure (timeout, connection refused) is logged instead of
      propagating. Previously a failing save converted an already-streamed
      successful run into RUN_ERROR, and on the workflow path emitted RUN_ERROR
      after RUN_FINISHED, violating the single-terminal-event invariant. The
      previous snapshot stays available for hydration.
    - Key the workflow_factory instance cache by (snapshot_scope, thread_id). The
      Snapshot Scope is the authorization boundary, so the same thread id under
      different scopes no longer shares an in-memory workflow instance.
      clear_thread_workflow accepts an optional snapshot_scope and clears all
      scopes for the thread when omitted.
    - Add tests: save-failure tolerance for agent and workflow endpoints,
      scope-isolated workflow cache, async snapshot_scope_resolver support, and
      in-memory store key validation errors.
    
    * fix(ci): ignore all dotnet.microsoft.com links in linkspector
    
    The existing ignore pattern only matched https://dotnet.microsoft.com/download,
    but Microsoft sites insert a locale segment between host and path
    (e.g. /en-us/download/dotnet/10.0), so localized links slip past the pattern
    and get checked. dotnet.microsoft.com bot-blocks CI link checkers with
    intermittent 403s across the whole site, which fails markdown-link-check on
    unrelated pull requests since linkspector scans the entire repository.
    
    Ignore the domain wholesale, matching how platform.openai.com is already
    handled for the same reason. A 403 from bot blocking is indistinguishable
    from a removed page, so the checker cannot produce a meaningful signal for
    this domain either way.
    
    * ag-ui: simplify raw_messages assignment and drop OrderedDict
    
    - Replace list(cast(...)) with a typed annotation for raw_messages
      (_agent_run.py:866) per review suggestion
    - Replace OrderedDict with a plain dict in InMemoryAGUIThreadSnapshotStore
      (_snapshots.py:136); regular dicts are insertion-order-safe since
      Python 3.7, so OrderedDict is unnecessary. Update _evict_oldest to use
      next(iter(...)) for FIFO removal instead of popitem(last=False).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #2458: review comment fixes
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: bump package versions for 1.8.1 release (#6420)
    * Python: bump package versions for 1.8.1 release
    
    * Python: bump agent-framework-foundry-hosting for 1.8.1 release
    
    * Python: bump ag-ui and azurefunctions for 1.8.1 release
    
    * Remove incorrect agent-framework-foundry changelog entry for #6259
    
    * Add [1.8.1] changelog compare link and update [Unreleased] base
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
  • Python: bump package versions for 1.6.0 release (#6017)
    * Python: bump package versions for 1.6.0 release
    
    - Released cohort (agent-framework, core, openai, foundry): 1.5.0 -> 1.6.0
    - Beta packages (21 packages): 1.0.0b260519 -> 1.0.0b260521
    - Alpha packages (azure-contentunderstanding, foundry-hosting, gemini, monty): 1.0.0a260518/19 -> 1.0.0a260521
    - ag-ui stays at 1.0.0rc2, orchestrations at 1.0.0rc1 (dependency bounds updated)
    - Inter-package dependency lower bounds updated (>=1.5.0,<2 -> >=1.6.0,<2)
    - Update CHANGELOG compare links
    - uv.lock refreshed
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: bump RC packages, add shell tool to changelog
    
    - ag-ui: 1.0.0rc2 -> 1.0.0rc3
    - orchestrations: 1.0.0rc1 -> 1.0.0rc2
    - Add shell tool (#5664) to CHANGELOG
    - uv.lock refreshed
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Bump Python package versions for a release (#5964)
    * Bump Python package versions to 1.5.0 for a release
    
    * Promote orchestrations to 1.0.0rc1
    
    * ci(python-setup): merge dynamic exclude into existing workspace exclude
    
    The python-setup action injected exclude = [...] verbatim into
    [tool.uv.workspace], producing a duplicate 'exclude' key when the
    section already had a static exclude. Scope the rewrite to the
    [tool.uv.workspace] section and append the package to the existing
    array when present; idempotent if the package is already excluded.
    
    * Address Copilot review feedback: raise inter-package floors to 1.5.0
    
    - foundry, foundry-local: agent-framework-openai >=1.4.0 -> >=1.5.0
    - azure-contentunderstanding: agent-framework-foundry >=1.4.0 -> >=1.5.0
    - azurefunctions: pin agent-framework-durabletask to >=1.0.0b260519,<2
    
    Keeps lockstep cohort consistent and avoids mixed 1.4.x / 1.5.0 installs.
    
    * Re-include azurefunctions and durabletask in the uv workspace
    
    The pinned durabletask>=1.4.0 floor is enough to make resolution succeed;
    the workspace exclude was over-correction and broke CI samples and pyright
    type-checking (re-exports in agent_framework/azure/__init__.pyi plus
    samples/04-hosting/{azure_functions,durabletask}/ could not resolve their
    imports). Dropping them from agent-framework-core[all] still stands so the
    metapackage does not pull them.
    
    * Restore azurefunctions and durabletask in agent-framework-core[all]
    
    The durabletask floor pin keeps users on the safe 1.4.0, so they are once
    again included in the metapackage. Update CHANGELOG to reflect the pin
    rather than an [all] removal.
    
    * Raise uvicorn ceiling in ag-ui and devui to allow 0.42+
    
    The root override-dependencies pins uvicorn[standard]>=0.34.0 (no upper)
    and the workspace lock resolves to 0.47.0. The package ceiling <0.42.0
    meant the workspace was no longer testing the declared supported range.
    Bump to <1 so the lock fits within the declared bounds.
    
    Also picked up by validate-dependency-bounds: refresh stale orchestrations
    RC pin in devui dev deps.
  • Python: bump package versions for 1.4.0 release (#5872)
    * fixes
    
    * fixes
    
    * Python: bump package versions for 1.4.0 release
    
    Cuts the python-1.4.0 release. MINOR bump on the released cohort
    (agent-framework, agent-framework-core, agent-framework-openai,
    agent-framework-foundry: 1.3.0 -> 1.4.0), driven by breaking changes
    in experimental skills API and new features. All 21 beta packages
    stamp 1.0.0b260514, all 3 alpha packages stamp 1.0.0a260514, and
    ag-ui remains at 1.0.0rc1 (freshly promoted). Date stamp reflects
    2026-05-14 Pacific.
    
    - Released cohort: 1.3.0 -> 1.4.0
    - Beta packages (21): 1.0.0b260507 -> 1.0.0b260514
    - Alpha packages (3): 1.0.0a260507 -> 1.0.0a260514
    - ag-ui: stays at 1.0.0rc1 (dep bound updated only)
    - Inter-package dependency lower bounds updated (>=1.3.0 -> >=1.4.0)
    - Fix chatkit StructuredInputItem exhaustiveness for openai-chatkit 1.6.4
    - Update CHANGELOG compare links
    - uv.lock refreshed
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Bump agent-framework-ag-ui to release candidate stage (#5844)
    * Bump agent-framework-ag-ui to release candidate stage
    
    * Mark agent-framework-ag-ui as rc in PACKAGE_STATUS
  • Python: add ag-ui tool result display channel (#5762)
    * Python: add ag-ui tool result display channel
    
    Key decisions:
    - Add TOOL_RESULT_DISPLAY_KEY and make state_update accept optional state plus a tool_result display payload.
    - Keep text as the LLM-bound tool result while using the display marker only for ToolCallResultEvent.content.
    - Reuse one outer/inner Content additional_properties extraction helper for state and display markers, preserving fallback behavior when display is absent.
    
    Files changed:
    - python/packages/ag-ui/agent_framework_ag_ui/_state.py
    - python/packages/ag-ui/agent_framework_ag_ui/_run_common.py
    - python/packages/ag-ui/tests/ag_ui/test_run_common.py
    - python/packages/ag-ui/tests/ag_ui/golden/test_scenario_deterministic_state.py
    - python/issues/done/01-tool-result-display-channel.md
    
    Blockers/notes:
    - Slice 1 is complete and moved to issues/done.
    - Slice 2 remains for docstring and README documentation.
    
    * Python: document ag-ui tool result display channel
    
    Key decisions:
    - Document state_update as the single helper for LLM text, UI-only tool_result display content, and durable shared state.
    - Keep the display guidance explicit that text remains LLM-bound while tool_result feeds ToolCallResultEvent.content.
    - List both reserved additional_properties markers in the docstring return contract.
    
    Files changed:
    - python/packages/ag-ui/agent_framework_ag_ui/_state.py
    - python/packages/ag-ui/README.md
    - python/issues/done/02-docs-tool-result-display.md
    
    Blockers/notes:
    - Slice 2 is complete and moved to issues/done.
    - Verification passed: uv run poe syntax -P ag-ui --check; uv run poe test -P ag-ui; uv run poe markdown-code-lint; uv run ruff check packages/ag-ui/agent_framework_ag_ui/_state.py.
    - Commit hooks were skipped after poe-check repeatedly rewrote uv.lock ordering; the same checks were run manually and passed.
    
    * Python: update gitignore
  • Python: bump package versions for 1.3.0 release (#5706)
    * Python: bump package versions for 1.3.0 release
    
    MINOR bump on the released cohort (agent-framework, agent-framework-core,
    agent-framework-openai, agent-framework-foundry: 1.2.2 -> 1.3.0). All 22
    beta packages stamp 1.0.0b260507 and all 3 alpha packages stamp
    1.0.0a260507 per the lockstep convention. Date stamp reflects 2026-05-07
    Pacific.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: bump foundry_local openai floor, fix devui orchestrations pin, clarify breaking scope
    
    - foundry_local: bump agent-framework-openai lower bound from >=1.1.0 to >=1.3.0
    - devui: update stale agent-framework-orchestrations dev pin from 1.0.0b260402 to 1.0.0b260507
    - CHANGELOG: clarify [BREAKING] applies to experimental skills API only
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Revert devui orchestrations pin to 1.0.0b260402 to avoid breaking DevUI
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: bump package versions for 1.2.2 release (#5561)
    * Python: bump package versions for 1.2.2 release
    
    PATCH bump (1.2.1 -> 1.2.2) for the released cohort. Five PRs land in this
    window:
    
    - agent-framework-openai: fix file_search citations breaking the assistant-
      message history roundtrip (#5557) — drives the released-tier PATCH
    - agent-framework-orchestrations: [BREAKING] standardize orchestration
      terminal outputs as AgentResponse (#5301)
    - agent-framework-core, agent-framework-declarative: preserve Workflow.run()
      shared state across calls, accept list[Message] in declarative start
      executor, and coerce Enum values when serializing PowerFx symbols (#5531)
    - agent-framework-foundry-hosting: add hosted Durable Workflow support
      (#5531)
    - agent-framework-azure-contentunderstanding: new alpha package — Azure AI
      Content Understanding context provider (#4829)
    - dependencies: workspace package dependency refresh (#5555)
    
    Per lockstep convention, all 21 beta packages stamp 1.0.0b260429 and all 4
    alpha packages (now including the new contentunderstanding) stamp
    1.0.0a260429. Date stamp reflects 2026-04-29 Pacific. Every non-core package
    floor on agent-framework-core is raised to >=1.2.2; the new
    contentunderstanding package's stale >=1.0.0 floor is brought into line.
    
    Two follow-on fixes bundled to keep validate-dependency-bounds-test green
    at lowest-direct resolution:
    - Bump agent-framework-azure-contentunderstanding's azure-ai-content
      understanding lower bound from >=1.0.0 to >=1.0.1 (1.0.0 ships without
      proper typing — pyright reports 65 unknown-type errors)
    - Add pyright ignore comments to core/foundry/__init__.pyi for the new
      alpha package's type-stub imports, since alpha packages are not in
      core's [all] extra and therefore aren't installed at lowest-direct
    
    * Python: add #5552 to 1.2.2 CHANGELOG
    
    Add the streaming-span observability fix to the Fixed section. PR is on
    upstream/main but not yet pulled into origin/main; the code itself will
    land via the PR merge.
    
    * Python: address PR #5561 review feedback on dependency bounds
    
    Two packaging fixes flagged in review:
    
    1. agent-framework-azure-contentunderstanding: add agent-framework-foundry
       as a runtime dependency. The package's README directs users to
       `pip install agent-framework-azure-contentunderstanding --pre` and the
       basic example imports `FoundryChatClient` from `agent_framework.foundry`,
       so the documented install path was failing with ImportError. Pulling
       agent-framework-foundry into deps makes the advertised entry path
       self-contained.
    
    2. agent-framework-foundry: bump agent-framework-openai lower bound from
       >=1.1.0 to >=1.2.2,<2. Foundry imports private modules from
       agent_framework_openai (`_chat_client.py:22`, `_agent.py:34`), so
       resolvers were free to pair foundry==1.2.2 with older OpenAI versions
       that lack this release's coordinated Responses/history fix. Lockstep the
       floor with the released cohort to prevent mismatched installs.
    
    Both changes pass `validate-dependency-bounds-test` lower + upper at
    their respective packages.
  • Python: bump package versions for 1.2.1 release (#5536)
    * Python: bump package versions for 1.2.1 release
    
    PATCH bump (1.2.0 -> 1.2.1) for the released cohort. The release window
    covers two PRs, no new public APIs:
    
    - agent-framework-core: prevent inner_exception from being lost in
      AgentFrameworkException (#5167)
    - samples: add requirements.txt and .env.example to the a2a/ hosting
      sample for pip-based setup (#5510)
    
    Per lockstep convention, all 21 beta packages stamp 1.0.0b260428 and all
    3 alpha packages stamp 1.0.0a260428, regardless of per-package code
    churn. Every non-core package floor on agent-framework-core is raised to
    >=1.2.1 to keep cohort signaling consistent. Date stamp reflects the
    local (Asia) cut date 2026-04-28.
    
    * Python: silence pyright unknown-type warnings in hosted-env detection
    
    `azure.ai.agentserver.core` is probed at runtime via `importlib.util.find_spec`
    and is not a declared dependency. The existing `# pyright: ignore[reportMissingImports]`
    suppresses the missing-import warning, but at `lowest-direct` resolution pyright
    still reports the imported symbol (`AgentConfig`) and its members (`from_env`,
    `is_hosted`) as unknown, breaking `validate-dependency-bounds-test` for
    `packages/core`.
    
    Extend the existing ignore to cover `reportUnknownVariableType` on the import
    and `reportUnknownMemberType` on the call site so the bounds check returns to
    green. Behavior is unchanged.
    
    Latent since #5455 (shipped in 1.2.0).
    
    * Python: raise agent-framework-gemini lower bound to google-genai>=1.65.0
    
    The Gemini chat client references several `google.genai.types` symbols
    (`FileSearch`, `ThinkingLevel`, `SearchTypes`, `McpServer`,
    `StreamableHttpTransport`, plus call-site keyword args `mcp_servers` and
    `search_types`) that are not present at the lower bound of `google-genai>=1.0.0`.
    At `lowest-direct` resolution this caused `validate-dependency-bounds-test` to
    fail for `packages/gemini` with eleven `reportAttributeAccessIssue` /
    `reportUnknownVariableType` errors.
    
    Walking the upstream `google.genai.types` API:
    - `GoogleMaps`, `AuthConfig`: present from 1.40.0
    - `FileSearch`: introduced in 1.49.0
    - `ThinkingLevel`: introduced in 1.55.0
    - `SearchTypes`, `McpServer`, `StreamableHttpTransport`: introduced in 1.65.0
    
    Bump the lower bound to 1.65.0 — the minimum version that exposes every symbol
    the package actually uses. Keep the `<2.0.0` upper cap unchanged. With this
    bump `validate-dependency-bounds-test` passes for both lower and upper
    resolution scenarios across all 27 workspace packages.
    
    Latent since #4847 (Gemini package introduction in 1.1.0); aggravated by
    subsequent feature additions that pulled in newer `types.*` symbols.
    
    * Python: add dependabot bumps to 1.2.1 CHANGELOG
    
    Catalog the 15 dependabot dependency updates that merged on `upstream/main`
    between python-1.2.0 and the 1.2.1 cut window under a new Changed section:
    
    - Workspace dev/runtime deps: `rich`, `prek`, `python-multipart`, `pyasn1`,
      `pytest` (ag-ui, devui, lab), `uv` (lab)
    - Frontend deps: `vite` (devui, chatkit), `postcss` (devui, chatkit, handoff),
      `picomatch` (devui, handoff)
    
    CHANGELOG-only — no source or pyproject.toml changes. PRs themselves merged
    upstream independently of this release branch and will be brought in via the
    PR merge.
  • Python: Bump pytest from 9.0.2 to 9.0.3 in /python/packages/lab (#5470)
    * Bump pytest from 9.0.2 to 9.0.3 in /python/packages/lab
    
    Bumps [pytest](https://github.com/pytest-dev/pytest) from 9.0.2 to 9.0.3.
    - [Release notes](https://github.com/pytest-dev/pytest/releases)
    - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
    - [Commits](https://github.com/pytest-dev/pytest/compare/9.0.2...9.0.3)
    
    ---
    updated-dependencies:
    - dependency-name: pytest
      dependency-version: 9.0.3
      dependency-type: direct:development
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    * Update pytest from 9.0.2 to 9.0.3 across all workspace packages
    
    Fix dependency conflict: agent-framework workspace packages were pinning
    pytest==9.0.2 while agent-framework-lab required pytest==9.0.3, causing
    uv dependency resolution to fail. Updated all pyproject.toml files and
    regenerated uv.lock to use pytest==9.0.3 consistently.
    
    Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/d274f7c5-b5ed-4b18-8eab-4db3cfd9d1bf
    
    Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com>
    
    ---------
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: moonbox3 <35585003+moonbox3@users.noreply.github.com>
  • Python: Bump Python package versions for 1.2.0 release (#5468)
    * Bump Python package versions for 1.2.0 release
    
    Released tier bumps 1.1.1 -> 1.2.0 (core, openai, foundry, root) to
    reflect additive public APIs landed since 1.1.0: functional workflow API
    (#4238) and FunctionTool SKIP_PARSING sentinel (#5424). All beta packages
    stamped 1.0.0b260424, alpha packages 1.0.0a260424. All 26 non-core
    agent-framework-core floors raised to >=1.2.0,<2. CHANGELOG consolidates
    the never-tagged 1.1.1 entries with the post-merge additions into [1.2.0].
    
    * Update CHANGELOG footer links for 1.2.0
    
    Advance [Unreleased] comparison base from python-1.1.0 to python-1.2.0
    and add a [1.2.0] reference link comparing python-1.1.0...python-1.2.0
    so the heading links resolve correctly.
    
    * Fix CHANGELOG: restore [1.1.1] section and add proper [1.2.0]
    
    Previous commit incorrectly renamed the [1.1.1] header to [1.2.0], which
    wiped the historical 1.1.1 entries and wrongly attributed them to 1.2.0.
    This restores [1.1.1] to its origin/main content and adds a new [1.2.0]
    section above containing only the commits in python-1.1.1..HEAD:
    
    - #4238 functional workflow API
    - #5142 GitHub Copilot OpenTelemetry
    - #2403 A2A bridge support
    - #5070 oauth_consent_request events in Foundry clients
    - #5447 FoundryAgent hosted agent sessions
    - #5459 hosting server dependency upgrade + types
    - #5389 AG-UI reasoning/multimodal parsing fix
    - #5440 stop [TOOLBOXES] warning spam
    - #5455 user agent prefix fix
    
    Also corrects the [1.2.0] compare base to python-1.1.1 (not 1.1.0) and
    adds the missing [1.1.1] reference link.
  • Python: Fix AG-UI reasoning role and multimodal media parsing to follow specification (#5389)
    * Fix AG-UI reasoning role and multimodal media value field parsing
    
    Fix two spec compliance issues in the AG-UI integration:
    
    1. ReasoningMessageStartEvent now uses role='reasoning' instead of
       role='assistant', matching the AG-UI specification for reasoning
       messages.
    
    2. _parse_multimodal_media_part now reads the 'value' field from source
       dicts (with fallback to 'data' for backward compatibility), matching
       the current AG-UI InputContentSource specification.
    
    Bump ag-ui-protocol dependency from ==0.1.13 to >=0.1.16,<0.2 to pick
    up the SDK fix that accepts role='reasoning' in ReasoningMessageStartEvent.
    
    Fix pre-existing pyright reportMissingImports errors for orjson in sample
    files, and fix import ordering in foundry-hosted-agents sample.
    
    Fixes #5340
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Fix AG-UI reasoning role and multimodal media parsing to follow specification
    
    Fixes #5340
    
    * Remove unintended .maf-runtime-ready marker file
    
    Address PR review feedback: the .maf-runtime-ready file is not referenced anywhere in the repo and was left over from automation.
    
    Fixes #5340
    
    * Python: Fix duplicate AG-UI multimodal 'value' parsing in snapshot path
    
    The snapshot normalization path used a second copy of the multimodal source
    parsing logic that still read the deprecated 'data' field. When clients sent
    base64 media with source={"type": "base64", "value": ...}, the snapshot event
    emitted by the server dropped the payload, causing AG-UI-compatible clients
    to crash on ingest.
    
    Extract the shared source-field extraction into _extract_multimodal_source_fields
    so both _parse_multimodal_media_part and the snapshot _legacy_binary_part stay
    in sync with the AG-UI spec. Add snapshot-path regression tests covering
    value-only, value-preferred-over-data, and the legacy data-field fallback.
    
    Addresses review feedback on #5389 from @Rickyneer.
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Bump Python package versions for a release. (#5432)
    * Bump Python version for a release.
    
    * Revert lockstep bumps on unchanged connectors
    
    Per PR review: only connectors that changed (or whose published metadata
    changed) should get new versions. Keeps released tier at 1.1.1, a2a/ag-ui
    at 1.0.0b260422, foundry-hosting at 1.0.0a260422; reverts the 19 unchanged
    betas and 2 unchanged alphas to 1.0.0b260421/1.0.0a260421. Reverts all 26
    non-core agent-framework-core floors to >=1.1.0,<2 since no connector
    actually depends on a 1.1.1 API or bug fix.
    
    * Restore lockstep prerelease bumps and raise core floors to >=1.1.1
    
    Reverses the lean-revert: all beta packages stamped 1.0.0b260423 and alpha
    packages stamped 1.0.0a260423 (Asia date, matching release cut time). All
    26 non-core packages raise agent-framework-core lower bound from >=1.1.0,<2
    to >=1.1.1,<2 to signal the validated cohort for this release. CHANGELOG
    date updated to 2026-04-23.
  • Python: Pass client thread_id as session_id when constructing AgentSession in AG-UI (#5384)
    * Pass thread_id as session_id when constructing AgentSession in AG-UI
    
    run_agent_stream() was constructing AgentSession without passing the
    client's thread_id as session_id, causing every request to receive a
    random UUID. This broke session continuity for HistoryProvider
    implementations that rely on session_id matching the client's thread_id.
    
    Pass session_id=thread_id in both the service-session and non-service
    code paths so the session identity is consistent with the AG-UI client.
    
    Fixes #5357
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add test for service_session with no thread_id edge case (#5357)
    
    When use_service_session=True but no thread_id/threadId is in the payload,
    verify session_id is a generated UUID and service_session_id is None.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Bump versions for a release. Update CHANGELOG (#5385)
    * Bump versions for a release. Update CHANGELOG
    
    * Bump devui
  • Python: Expose forwardedProps to agents and tools via session metadata (#5264)
    * Expose forwarded_props to agents and tools via session metadata (#5239)
    
    Include forwarded_props from AG-UI request input_data in session.metadata
    (agent runner) and function_invocation_kwargs (workflow runner) so that
    agents, tools, and workflow executors can access request-level metadata
    such as invocation source flags from CopilotKit.
    
    - Add forwarded_props to base_metadata in _agent_run.py when present
    - Add 'forwarded_props' to AG_UI_INTERNAL_METADATA_KEYS to filter it
      from LLM-bound client metadata
    - Extract forwarded_props in _workflow_run.py and pass via
      function_invocation_kwargs to workflow.run()
    - Accept both snake_case and camelCase keys (forwarded_props/forwardedProps)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix(ag-ui): pass stream=True as literal to satisfy pyright overload resolution (#5239)
    
    The previous fix passed stream=True via **kwargs dict, which prevented
    pyright from resolving the Workflow.run() overload to the streaming
    variant. Pass stream=True as an explicit keyword argument so pyright
    can correctly infer the ResponseStream return type.
    
    Also remove unused pytest import in test file.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: address PR review feedback for forwarded_props (#5239)
    
    - Use key-presence checks instead of truthiness for forwarded_props so
      empty dict {} is forwarded correctly
    - Gate function_invocation_kwargs on workflow.run() signature inspection
      to avoid TypeError for workflows without **kwargs
    - Change _build_safe_metadata to drop (with warning) keys whose
      serialized values exceed 512 chars instead of truncating into invalid
      JSON
    - Rewrite metadata tests to exercise _build_safe_metadata directly with
      JSON-decodability and truncation assertions
    - Add workflow tests for empty dict forwarded_props, stream=True
      assertion, and signature-gated kwarg dropping
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * test: add stream=True assertions to CapturingWorkflow tests (#5239)
    
    Guard against accidental removal of the explicit stream=True kwarg
    in all forwarded_props CapturingWorkflow test cases.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #5239: Python: Expose forwardedProps to agents and tools via session metadata
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: AG-UI deterministic state updates from tool results (#5201)
    * AG-UI deterministic state updates from tool results
    
    * fix(ag-ui): address PR #5201 review comments
    
    1. Add missing AGUIEventConverter, AGUIHttpService, __version__ to
       _IMPORTS in core ag_ui lazy-export list to match the .pyi stub.
    
    2. Coalesce predictive and deterministic state snapshots into a single
       StateSnapshotEvent when both mechanisms are active on the same tool
       result, reducing redundant snapshot traffic.
    
    3. Update state_update() docstring to clarify that a predictive snapshot
       may be emitted before the deterministic one when predict_state_config
       is active.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Bump Python version to 1.0.1 for a release (#5196)
    * Bump Python version to 1.1.0 for a release
    
    * Fix changelog
    
    * 1.0.1 instead of 1.1.0
    
    * Update CHANGELOG.md
    
    * update version and changelog
    
    * Bump lower bounds
  • Python: Stop emitting duplicate reasoning content from OpenAI response.reasoning_text.done and response.reasoning_summary_text.done events (#5162)
    * Fix reasoning text done events duplicating streamed delta content (#5157)
    
    The OpenAI Responses API sends both reasoning_text.delta (incremental
    chunks) and reasoning_text.done (full accumulated text) events. The
    chat client was emitting Content for both, causing ag-ui to append the
    full done text onto already-accumulated delta text, producing
    duplicated reasoning output.
    
    Stop emitting Content for reasoning_text.done and
    reasoning_summary_text.done events, matching how output_text.done is
    already handled (not emitted). The deltas contain all the content;
    the done event is redundant.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix(openai): emit reasoning done content as fallback when no deltas observed (#5157)
    
    Address PR review feedback:
    - Track item_ids that received reasoning deltas via seen_reasoning_delta_item_ids set
    - Emit content from done events only when no deltas were received for the
      item_id, preventing silent content loss on stream resumption
    - Add comment documenting code_interpreter done event asymmetry
    - Replace redundant ag-ui test with deduplication-focused test
    - Add integration test for delta+done sequence in OpenAI chat client tests
    - Add fallback path tests for done events without preceding deltas
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #5157: Python: [Bug]: "type": "response.reasoning_text.delta" and "response.reasoning_text.done" both get exposed as "text_reasoning"
    
    * Fix AG-UI reasoning streaming to use proper Start/End pattern (#5157)
    
    _emit_text_reasoning now follows the same streaming pattern as _emit_text:
    - Emits ReasoningStartEvent/ReasoningMessageStartEvent only on the first
      delta for a given message_id
    - Emits only ReasoningMessageContentEvent for subsequent deltas
    - Defers ReasoningMessageEndEvent/ReasoningEndEvent until
      _close_reasoning_block is called (on content type switch or end-of-run)
    
    This produces the correct protocol pattern:
      ReasoningStartEvent
        ReasoningMessageStartEvent
        ReasoningMessageContentEvent(delta1)
        ReasoningMessageContentEvent(delta2)
        ReasoningMessageEndEvent
      ReasoningEndEvent
    
    Instead of wrapping every delta in a full Start→End sequence.
    
    Backward compatibility is preserved: calling _emit_text_reasoning without
    a flow argument still produces the full sequence per call.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix import ordering lint error in AG-UI test file (#5157)
    
    Move inline import of TextMessageContentEvent to the top-level import
    block and ensure alphabetical ordering to satisfy ruff I001 rule.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix mypy error: rename loop variable to avoid type conflict with WorkflowEvent
    
    The 'event' variable was already typed as WorkflowEvent[Any] from the
    async for loop at line 590. Reusing it in the _close_reasoning_block
    loop (which returns list[BaseEvent]) caused an incompatible assignment
    error. Renamed to 'reasoning_evt' to avoid the conflict.
    
    Fixes #5162
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #5157: review comment fixes
    
    * narrow test result reporting to explicit pytest JUnit XML
    
    * Fix test args
    
    * Fix pytest-results-action in merge workflow and remove committed test artifacts
    
    Apply the same JUnit XML fix from python-tests.yml to python-merge-tests.yml:
    add --junitxml=pytest.xml to all test commands and narrow the results action
    path from ./python/**.xml to ./python/pytest.xml. Also remove accidentally
    committed pytest.xml and python-coverage.xml and add them to .gitignore.
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] update to v1.0.0 (#5062)
    * updates to final deprecated pieces and versions
    
    * fix mypy
    
    * fix readme links
  • Python: [BREAKING] Standardize model selection on model (#4999)
    * Refactor Anthropic model option and provider clients
    
    Rename the Anthropic client model option from model_id to model, add provider-specific Anthropic wrappers for Foundry, Bedrock, and Vertex, and expose them through the Anthropic, Foundry, Amazon, and Google namespaces. Update core option handling, docs, samples, and tests accordingly.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix Anthropic skills sample typing
    
    Cast the Anthropic beta client to Any in the skills sample so the pre-commit sample pyright check no longer fails on beta skills and files endpoints that are not exposed by the current SDK stubs.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * undo sample mypy
    
    * Retry CI after transient external failures
    
    Retrigger PR validation after an unrelated Copilot review workflow SAML failure and a transient external tau2 git fetch failure in the Windows Python test setup.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback on model option merging
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address Anthropic compatibility review feedback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * moved all to `model`
    
    * fixes for azure ai search
    
    * Python: standardize remaining sample env var names
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: fix foundry-local pyright compatibility
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated env vars in cicd
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] Remove deprecated Python OpenAI/Azure AI surfaces (#4990)
    * [BREAKING] Remove deprecated Python OpenAI/Azure AI surfaces
    
    Also clean up follow-on docs, environment guidance, package metadata, and lab test stability.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix deleted semantic-kernel sample links
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review feedback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * improve foundry language
    
    * Fix A2A Foundry sample regression
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Update Python Packages for rc6 (#4979)
    * python package update
    
    * small fix
  • Python: Include reasoning messages in MESSAGES_SNAPSHOT events (#4844)
    * Include reasoning messages in MESSAGES_SNAPSHOT (#4843)
    
    FlowState now tracks reasoning messages emitted during a run.
    _emit_text_reasoning() persists reasoning (including encrypted_value)
    into flow.reasoning_messages, and _build_messages_snapshot() appends
    them to the final MESSAGES_SNAPSHOT event.
    
    Changes:
    - Add reasoning_messages field to FlowState
    - Update _emit_text_reasoning() to accept optional flow parameter
    - Include reasoning_messages in _build_messages_snapshot()
    - Add 'reasoning' to ALLOWED_AGUI_ROLES so normalize_agui_role()
      preserves the role through snapshot round-trips
    - Skip reasoning messages in agui_messages_to_agent_framework() since
      they are UI-only state and should not be forwarded to LLM providers
    - Add regression tests for snapshot emission, encrypted value
      preservation, and multi-turn round-trip with reasoning
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Include reasoning messages in MESSAGES_SNAPSHOT events
    
    Fixes #4843
    
    * Fix PR review feedback for reasoning persistence (#4843)
    
    - Accumulate reasoning text per message_id (append deltas) instead of
      storing only the current chunk, matching flow.accumulated_text pattern
    - Use camelCase encryptedValue in snapshot JSON to match AG-UI protocol
      conventions (toolCallId, encryptedValue)
    - Normalize snake_case encrypted_value to encryptedValue in
      agui_messages_to_snapshot_format for input compatibility
    - Update normalize_agui_role docstring to include reasoning role
    - Add tests for incremental reasoning accumulation and key normalization
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #4843: Python: agent-framework-ag-ui: include reasoning messages in MESSAGES_SNAPSHOT
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Bump Python version to 1.0.0rc5 and 1.0.0b260319 for a release. (#4807)
    * Bump Python version to 1.0.0rc5 and 1.0.0b260319 for a release.
    
    * update missed pkg versions
    
    * Update changelog
  • Python: [BREAKING] Refactor middleware layering and split Anthropic raw client (#4746)
    * [BREAKING] Refactor middleware layering and raw clients
    
    Reorder chat client layers so function invocation wraps chat middleware, and chat middleware stays outside telemetry while still running for each inner model call. Add middleware pipeline caching, refresh docs and samples, and split Anthropic into raw and public clients to match the standard layering model.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Tighten typing ignores in ancillary modules
    
    Add targeted typing ignores in workflow visualization and lab modules so pyright stays clean alongside the middleware refactor work.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix categorize_middleware to unpack tuple/Sequence and use relative MRO assertions
    
    - Broaden isinstance check in categorize_middleware from list to Sequence
      so tuples and other Sequence types are properly unpacked instead of
      being appended as a single item.
    - Replace fragile hardcoded MRO index assertions in anthropic test with
      relative ordering via mro.index().
    - Add regression tests for categorize_middleware with tuple, list, and
      None inputs.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix middleware string decomposition, add middleware param to FunctionInvocationLayer, and add tests (#4710)
    
    - Guard categorize_middleware Sequence check against str/bytes to prevent
      character-by-character decomposition of accidentally passed strings
    - Add explicit middleware parameter to FunctionInvocationLayer.get_response
      and merge it into client_kwargs before categorization, fixing the
      inconsistency where only OpenAIChatClient supported this parameter
    - Add assertions that RawAnthropicClient does not inherit convenience layers
    - Add chat middleware cache test with non-empty base middleware
    - Add tests for single unwrapped middleware item and string input
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Apply pre-commit auto-fixes
    
    * Address review feedback for #4710: review comment fixes
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Co-authored-by: Copilot <copilot@github.com>
  • Python: Emit TOOL_CALL_RESULT events when resuming after tool approval (#4758)
    * Emit TOOL_CALL_RESULT events on approval resume (#4589)
    
    When a tool call is approved via the interrupt/resume flow,
    _resolve_approval_responses executes the tool and injects the result
    into the messages array, but no TOOL_CALL_RESULT SSE event was yielded
    to the client.
    
    Changes:
    - _resolve_approval_responses now returns the list of resolved
      function_result Content objects instead of None
    - run_agent_stream yields ToolCallResultEvent for each resolved
      approval result after RunStartedEvent is emitted
    - Add ToolCallResultEvent to ag_ui.core imports in _agent_run.py
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * fix(ag-ui): address PR review feedback for #4589
    
    1. _resolve_approval_responses now returns only approved results (not
       rejections) so TOOL_CALL_RESULT events are emitted only for executed
       tools. Rejection results are still written into message history.
    
    2. Emit resolved TOOL_CALL_RESULT events in the no-updates fallback
       RUN_STARTED path so approval results are never lost.
    
    3. Rewrite tests to use real FunctionTool with func and
       approval_mode='always_require' via StubAgent default_options,
       verifying actual tool execution output in TOOL_CALL_RESULT content.
       Added test for rejection not emitting TOOL_CALL_RESULT.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix #4589: clean up approval resolution and add missing tests
    
    - Extract duplicated TOOL_CALL_RESULT emission block into
      _make_approval_tool_result_events helper to prevent drift
    - Remove dead rejection_results construction in _resolve_approval_responses;
      _replace_approval_contents_with_results already handles rejections inline
    - Pass only approved_results (not all_results) to clarify the contract
    - Add mixed approve/reject test validating the core splitting logic
    - Add zero-updates test covering the no-updates fallback emission path
    - Add direct unit test for _resolve_approval_responses return value
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Fix import sorting lint error in test_approval_result_event.py
    
    Add blank line between first-party and third-party import groups
    to satisfy ruff I001 rule.
    
    Fixes #4589
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Emit AG-UI events for MCP tool calls, results, and text reasoning (#4760)
    * Python: Emit AG-UI events for MCP tool calls, results, and text reasoning
    
    Fixes #4213 — `_emit_content()` in the AG-UI layer only handled `text`,
    `function_call`, `function_result`, `function_approval_request`, `usage`,
    and `oauth_consent_request` content types. Foundry MCP content types
    (`mcp_server_tool_call`, `mcp_server_tool_result`) and `text_reasoning`
    fell through unhandled, producing no SSE events for AG-UI consumers.
    
    Added three new handler functions wired into `_emit_content()`:
    
    - `_emit_mcp_tool_call`: emits TOOL_CALL_START + TOOL_CALL_ARGS and
      tracks in FlowState for MESSAGES_SNAPSHOT inclusion
    - `_emit_mcp_tool_result`: emits TOOL_CALL_END + TOOL_CALL_RESULT with
      full FlowState cleanup mirroring `_emit_tool_result`
    - `_emit_text_reasoning`: emits the protocol-defined reasoning event
      sequence (ReasoningStart → MessageStart → MessageContent → MessageEnd
      → ReasoningEnd) with ReasoningEncryptedValueEvent for protected_data
    
    * Add HTTP round-trip tests for MCP tool and reasoning SSE events
    
    Exercises the full POST → SSE bytes → parse → validate pipeline for
    mcp_server_tool_call, mcp_server_tool_result, text_reasoning, and
    ReasoningEncryptedValueEvent content through FastAPI TestClient.
    
    * Fix _emit_mcp_tool_result missing predictive_handler support (#4213)
    
    - Add predictive_handler parameter to _emit_mcp_tool_result and mirror
      the apply_pending_updates + StateSnapshotEvent block from _emit_tool_result
    - Forward predictive_handler from _emit_content to _emit_mcp_tool_result
    - Add assertion for stored arguments in MCP tool call test
    - Add test for predictive handler state snapshot after MCP tool result
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Refactor MCP tool emit functions and add missing tests (#4213)
    
    - Extract _emit_tool_result_common shared helper to eliminate duplication
      between _emit_tool_result and _emit_mcp_tool_result
    - Remove server_name prefix from tool_call_name in _emit_mcp_tool_call;
      display_name now equals tool_name directly
    - Add test for tool_name fallback to 'mcp_tool' when tool_name is None
    - Add test for output=None fallback to empty string in _emit_mcp_tool_result
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback for #4213: review comment fixes
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Simplify Python Poe tasks and unify package selectors (#4722)
    * updated automation tasks and commands, with alias for the time being
    
    * Restore aggregate test exclusions
    
    Preserve the legacy all-tests scope for test --all by excluding lab and devui from the default aggregate sweep, while still allowing explicit package selection. Also ignore hidden/generated test directories such as .mypy_cache during aggregate discovery.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated versions in pre-commit
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix RUN_FINISHED.interrupt to accumulate all interrupts when multiple tools need approval (#4717)
    * Fix flow.interrupts overwrite when multiple tools need approval (#4590)
    
    Change flow.interrupts assignment to append so that all interrupt entries
    accumulate when multiple tools require approval in a single turn.
    
    Both _run_common.py and _agent_run.py used assignment (=) which caused
    each new interrupt to overwrite the previous one. Switching to append()
    ensures RUN_FINISHED.interrupt contains all pending approvals.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add test for streaming path with multiple confirm_changes interrupts (#4590)
    
    Add integration test exercising run_agent_stream with multiple predictive
    tool calls requiring confirmation. Verifies that flow.interrupts.append()
    correctly accumulates all interrupt entries and they appear in the
    RUN_FINISHED event.
    
    Also confirms FlowState already declares interrupts field with
    default_factory=list, addressing the AttributeError concern from review.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix _deduplicate_messages catch-all branch dropping valid repeated messages (#4716)
    * Fix _deduplicate_messages catch-all branch dropping valid repeated messages (#4682)
    
    Remove the catch-all dedup branch that used (role, hash(content_str)) as a
    dedup key. This incorrectly treated any two messages with the same role and
    identical content as duplicates, dropping valid repeated messages (e.g., a
    user saying 'yes' to confirm two separate things).
    
    The tool-specific dedup branches (tool results by call_id, assistant tool
    calls by call_id tuple) remain unchanged as they correctly identify true
    protocol-level duplicates.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review: consecutive-duplicate detection for non-tool messages (#4682)
    
    - Replace blanket dedup removal with consecutive-duplicate detection:
      only skip a message if the immediately preceding message has the same
      role and content, preserving protection against upstream replays while
      allowing identical messages at different conversation points.
    - Strengthen test assertions to verify message identity and order, not
      just list length.
    - Add tests for consecutive duplicate skipping, non-consecutive
      preservation, and messages with contents=None.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Apply pre-commit auto-fixes
    
    * Use message_id for deduplication instead of content hashing
    
    Deduplicate general messages by message_id when available, replacing
    the consecutive-duplicate content check. Two messages with the same id
    are definitively the same message (upstream replay), while identical
    content with distinct ids (e.g. repeated "yes" confirmations) is
    preserved. Messages without a message_id are always kept.
    
    * Fix message_id dedup: truthy check, content-hash fallback, log safety
    
    - Use truthy check (`if msg.message_id`) instead of `is not None` so
      empty-string IDs fall through to content-hash dedup rather than
      collapsing unrelated messages.
    - Add content-hash fallback for messages without message_id, preventing
      false negatives from integrations that don't set IDs.
    - Remove raw message_id from log format string (addresses log-injection
      surface with control characters).
    - Add tests for empty-string message_id edge cases.
    - Update existing tests to reflect content-hash dedup behavior.
    
    Fixes #4682
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <copilot@github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: chore(python): improve dependency range automation (#4343)
    * chore(python): improve dependency range automation
    
    - tighten dependency bounds and coding standards guidance\n- add dependency range validation workflow, reporting, and issue automation\n- update related tests and dependency pins for compatibility
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated text and pyarrow
    
    * new lock
    
    * fixed workflow
    
    * updated deps
    
    * fix tiktoken
    
    * chore(python): refine dependency validation workflows
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * docs(python): add high-level dependency validation comments
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * WIP
    
    * added additional comments and excludes
    
    * added dev dependency handling and workflow and updates to package ranges
    
    * added readme and simplified commands
    
    * fix markers
    
    * chore(python): address dependency review feedback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Tighten dependency bounds, remove stale overrides, restore Python 3.10 support
    
    - Apply dependency bound policy across all packages: stable >=1.0 deps use
      >=floor,<next_major; pre-1.0/prerelease deps use validated hard-bounded ranges
    - Remove stale root tool.uv.override-dependencies (uvicorn, websockets, grpcio)
    - Lower github_copilot requires-python to >=3.10 with github-copilot-sdk gated
      behind python_version >= 3.11 marker; import raises ImportError on 3.10
    - Skip github_copilot pyright/mypy/test tasks on Python <3.11
    - Use version-conditional pyrightconfig for samples on Python 3.10
    - Add compatibility fix in core responses client for older openai typed dicts
    - Normalize uv.lock prerelease mode and refresh dev dependencies
    - Update CODING_STANDARD.md, DEV_SETUP.md, and package management skill docs
    
    Closes #902
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * small tweaks
    
    * add note in workflow
    
    * fix workflows and several versions
    
    * fix duplicate
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • [BREAKING] Python: clean up kwargs across agents, chat clients, tools, and sessions (#4581)
    * Python: clean up kwargs across agents, chat clients, tools, and sessions (#3642)
    
    Audit and refactor public **kwargs usage across core agents, chat clients,
    tools, sessions, and provider packages per the migration strategy codified
    in CODING_STANDARD.md.
    
    Key changes:
    - Add explicit runtime buckets: function_invocation_kwargs and client_kwargs
      on RawAgent.run() and chat client get_response() layers.
    - Refactor FunctionTool to prefer explicit ctx: FunctionInvocationContext
      injection; legacy **kwargs tools still work via _forward_runtime_kwargs.
    - Refactor Agent.as_tool() to use direct JSON schema, always-streaming
      wrapper, approval_mode parameter, and UserInputRequiredException
      propagation (integrates PR #4568 behavior).
    - Remove implicit session bleeding into FunctionInvocationContext; tools
      that need a session must receive it via function_invocation_kwargs.
    - Lower chat-client layers after FunctionInvocationLayer accept only
      compatibility **kwargs (client_kwargs flattened, function_invocation_kwargs
      ignored).
    - Add layered docstring composition from Raw... implementations via
      _docstrings.py helper.
    - Clean up provider constructors to use explicit additional_properties.
    - Deprecation warnings on legacy direct kwargs paths.
    - Update samples, tests, and typing across all 23 packages.
    
    Resolves #3642
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * clarified docstring
    
    * feedback fixes
    
    * Add unit tests for _docstrings.py build/apply helpers
    
    Tests cover: no docstring source, no extra kwargs, appending to existing
    Keyword Args section, inserting after Args, inserting in plain docstrings,
    multiline descriptions, ordering, and apply_layered_docstring.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add test for propagate_session TypeError on non-AgentSession values
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add tests for multi-content and empty UserInputRequiredException propagation
    
    Cover the branching logic in _try_execute_function_calls for:
    - Multiple user_input_request items in a single exception (extra_user_input_contents path)
    - Empty contents list (fallback function_result path)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add tests for DurableAIAgent.get_session forwarding service_session_id
    
    Verifies get_session correctly forwards service_session_id and session_id
    to the executor's get_new_session, replacing the removed kwargs test.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Simplify ag-ui test stub to read session from client_kwargs only
    
    Remove dual-mode detection (client_kwargs vs raw kwargs fallback) from
    the test mock. Session is now read exclusively from client_kwargs,
    matching the settled public calling convention.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated create and get sessions in durable
    
    * fixed docstrings
    
    * fix test
    
    * updated session handling
    
    * updated from main
    
    * updated tests
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Unify tool results as Content items with rich content support (#4331)
    * feat(python): allow @tool functions to return rich content (images, audio)
    
    Add support for tool functions to return Content objects that the model can perceive natively. Closes #4272
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Anthropic logging + mypy fix
    
    * Address PR review: fix MCP ordering, fold helper into from_function_result, fix Chat client
    
    - Preserve original content order in MCP tool results instead of text-first
    - Move _build_function_result logic into Content.from_function_result()
    - Chat Completions: inject user message for rich items (API only supports string tool content)
    - Update tests for ordering and new from_function_result behavior
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Use native Responses API multi-part output, warn+omit for Chat client
    
    - Responses client: put rich items directly in function_call_output's
      output field as list (native API support) instead of user message injection
    - Chat client: warn and omit rich items (API doesn't support multi-part
      tool results), matching Ollama/Bedrock pattern
    - Unify test image: use sample_image.jpg across all integration tests
    - Add Azure OpenAI Responses integration test
    - Assert model describes house image to verify perception
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix lint: remove print statement, wrap long line
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address review feedback: bug fixes, single-pass MCP, unit tests
    
    - Add isinstance guard in from_function_result for non-Content lists
    - Fix Anthropic empty tool_content fallback to string result
    - Fix Content(type='text', text=None) edge case in parse_result
    - Rewrite MCP _parse_tool_result_from_mcp as single-pass (no index counters)
    - Add Anthropic unit tests: data image, uri image, unsupported media, all-unsupported
    - Add OpenAI Chat unit test: rich items warning and omission
    - Add OpenAI Responses unit tests: function_result with/without items
    - Add test_types tests: only-rich-items list, non-Content list fallback
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix pyright errors: add type ignore comments for Any list iteration
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix mypy/pyright: ensure ToolExecutionException receives str
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix lint: remove duplicate test_prepare_options_excludes_conversation_id
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * refactor: unify all tool results into Content items
    
    * addressed copilot comments
    
    * pyright fix
    
    * small fix
    
    * comments
    
    * fix: address Copilot review - warnings, blob safety, dedup
    
    - Add warning logs when rich content is dropped in Claude agent and
      MCP server handlers (matching Chat/Bedrock/Ollama pattern)
    - Defensive blob URI construction: wrap plain base64 in data: prefix
    - Simplify Chat client _prepare_content_for_openai to use content.result
    - Simplify Responses client text-only path, remove redundant nesting
    - Add test for plain base64 blob without data: prefix
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix token double-counting in compaction and address review comments
    
    - Exclude items from _serialize_content() to prevent double-counting
      tokens when items mirrors result in function_result content
    - Add rich content warning in GitHub Copilot agent tool handler
    - Replace raw Content debug log with concise item count/type summary
    - Update stale test comments about FunctionTool.invoke return type
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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: 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 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: 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 / .NET Samples - Restructure and Improve Samples (Feature Branc… (#4092)
    * Python: .NET Samples - Restructure and Improve Samples (Feature Branch) (#4091)
    
    * Moved by agent (#4094)
    
    * Fix readme links
    
    * .NET Samples - Create `04-hosting` learning path step (#4098)
    
    * Agent move
    
    * Agent reorderd
    
    * Remove A2A section from README 
    
    Removed A2A section from the Getting Started README.
    
    * Agent fixed links
    
    * Fix broken sample links in durable-agents README (#4101)
    
    * Initial plan
    
    * Fix broken internal links in documentation
    
    Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
    
    * Revert template link changes; keep only durable-agents README fix
    
    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>
    
    * .NET Samples - Create `03-workflows` learning path step (#4102)
    
    * Fix solution project path
    
    * Python: Fix broken markdown links to repo resources (outside /docs) (#4105)
    
    * Initial plan
    
    * Fix broken markdown links to repo resources
    
    Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
    
    * Update README to rename .NET Workflows Samples section
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
    
    * .NET Samples - Create `02-agents` learning path step (#4107)
    
    * .NET: Fix broken relative link in GroupChatToolApproval README (#4108)
    
    * Initial plan
    
    * Fix broken link in GroupChatToolApproval README
    
    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>
    
    * Update labeler configuration for workflow samples
    
    * .NET - Reorder Agents samples to start from Step01 instead of Step04 (#4110)
    
    * Fix solution
    
    * Resolve new sample paths
    
    * Move new AgentSkills and AgentWithMemory_Step04 samples
    
    * Fix link
    
    * Fix readme path
    
    * fix: update stale dotnet/samples/Durable path reference in AGENTS.md
    
    Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
    
    * Moved new sample
    
    * Update solution
    
    * Resolve merge (new sample)
    
    * Sync to new sample - FoundryAgents_Step21_BingCustomSearch
    
    * Updated README
    
    * .NET Samples - Configuration Naming Update (#4149)
    
    * .NET: Restore AzureFunctions index parity with ConsoleApps under DurableAgents samples (#4221)
    
    * Clean-up `05_host_your_agent`
    
    * Config setting consistency
    
    * Refine samples
    
    * AGENTS.md
    
    * Move new samples
    
    * Re-order samples
    
    * Move new project and fixup solution
    
    * Fixup model config
    
    * Fix up new UT project
    
    ---------
    
    Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
  • Update Python package versions to rc2 (#4258)
    - Bump core and azure-ai to 1.0.0rc2
    - Bump preview packages to 1.0.0b260225
    - Update dependencies to >=1.0.0rc2
    - Add CHANGELOG entries for changes since rc1
    - Update uv.lock
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Phase 2: Embedding clients for Ollama, Bedrock, and Azure AI Inference (#4207)
    * Phase 2: Embedding clients for Ollama, Bedrock, and Azure AI Inference
    
    Add embedding client implementations to existing provider packages:
    
    - OllamaEmbeddingClient: Text embeddings via Ollama's embed API
    - BedrockEmbeddingClient: Text embeddings via Amazon Titan on Bedrock
    - AzureAIInferenceEmbeddingClient: Text and image embeddings via Azure AI
      Inference, supporting Content | str input with separate model IDs for
      text (AZURE_AI_INFERENCE_EMBEDDING_MODEL_ID) and image
      (AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL_ID) endpoints
    
    Additional changes:
    - Rename EmbeddingCoT -> EmbeddingT, EmbeddingOptionsCoT -> EmbeddingOptionsT
    - Add otel_provider_name passthrough to all embedding clients
    - Register integration pytest marker in all packages
    - Add lazy-loading namespace exports for Ollama and Bedrock embeddings
    - Add image embedding sample using Cohere-embed-v3-english
    - Add azure-ai-inference dependency to azure-ai package
    
    Part of #1188
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix mypy duplicate name and ruff lint issues
    
    - Rename second 'vector' variable to 'img_vector' in image embedding loop
    - Combine nested with statements in tests
    - Remove unused result assignments in tests
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updates from feedback
    
    * Fix CI failures in embedding usage handling
    
    - Fix Azure AI embedding mypy issues by normalizing vectors to list[float],
      safely accumulating optional usage token fields, and filtering None entries
      before constructing GeneratedEmbeddings
    - Avoid Bandit false positive by initializing usage details as an empty dict
    - Update OpenAI embedding tests to assert canonical usage keys
      (input_token_count/total_token_count)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix doubled tool_call arguments in MESSAGES_SNAPSHOT when streaming (#4200)
    * fix: prevent doubled tool_call arguments in MESSAGES_SNAPSHOT
    
    When streaming with client-side tools, some providers send a full-
    arguments replay after the streaming deltas complete. The `_emit_tool_call`
    function unconditionally appends every arguments delta to the internal
    `flow.tool_calls_by_id` tracking dictionary via `+=`. When the replay
    contains the exact same complete arguments string that was already
    accumulated from prior deltas, the arguments get doubled (e.g.,
    `{"todoText":"buy groceries"}{"todoText":"buy groceries"}`).
    
    This causes `MESSAGES_SNAPSHOT` events to contain invalid doubled JSON in
    `tool_calls[].function.arguments`, breaking any client or middleware that
    relies on snapshots for state reconstruction.
    
    The fix adds a guard (mirroring the existing duplicate guard in
    `_emit_text`) that detects when the incoming delta exactly equals the
    already-accumulated arguments string, indicating a full-arguments replay
    rather than an incremental delta. In this case the append is skipped,
    preventing the doubling.
    
    The `ToolCallArgsEvent` deltas are still emitted correctly for real-time
    streaming — only the internal snapshot accumulator is guarded.
    
    Fixes #4194
    
    * fix: move duplicate check before event emission + add test
    
    Address Copilot review feedback:
    1. Move duplicate full-arguments replay detection BEFORE emitting
       ToolCallArgsEvent, for consistency with _emit_text() which returns
       early without emitting any events on replay detection.
    2. Add test_emit_tool_call_skips_duplicate_full_arguments_replay() to
       verify the duplicate detection behavior for tool call arguments,
       matching the existing test pattern for text content.