Skip to content

Project profile history into native Foundation Models sessions - #349

Merged
mattt merged 65 commits into
huggingface:mainfrom
qoli:codex/upstream-profile-native-history
Nov 6, 2026
Merged

mattt merged 65 commits into
huggingface:mainfrom
qoli:codex/upstream-profile-native-history

Conversation

@qoli

@qoli qoli commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

This PR makes native Foundation Models sessions send a profile's projected history, as the framework does.

On main, a profile session's native history comes from the canonical transcript, so historyTransform has no effect on native requests. This PR seeds the native history from the resolved request context and leaves the canonical transcript unchanged. If a transform rewrites the current prompt, the rewritten prompt is sent in place of the current one, so the request holds one copy. Foundation Models 27 does the same with its own profiles: the model sees the rewritten text, and the session's transcript keeps the original. A rewritten prompt reaches the native request through a history transform, because the Foundation Models prompt API can't set a structured segment's ID or source.

The profile constructor stays Compatibility SPI. This PR adds no native delegate or Tool loop, and ordinary sessions keep their evaluation timing. To carry the rewritten prompt, fmRespond and fmStreamResponse now take a closure that returns the session and the prompt together.

Known differences from Foundation Models:

  • If a transform removes the current prompt or ends the history with another entry, the native session still appends the current prompt. Foundation Models sends the transform's output as it is.
  • During a profile session's request, the native path uses one context for every evaluation. Foundation Models evaluates the profile and its history transforms again before the continuation after a tool call. This also happens on main, and this PR does not change it.

qoli added 30 commits October 9, 2026 16:06
…dynamic-profiles

# Conflicts:
#	Sources/AnyLanguageModel/LanguageModelSession.swift
#	Sources/AnyLanguageModel/SessionProperties.swift
#	Sources/AnyLanguageModelMacros/SessionPropertyEntryMacro.swift
#	Tests/AnyLanguageModelTests/APICompatibilityAnyLanguageModelTests.swift
#	Tests/AnyLanguageModelTests/APICompatibilityFoundationModelsTests.swift
#	Tests/AnyLanguageModelTests/SessionPropertyTests.swift
…dynamic-profiles

# Conflicts:
#	Sources/AnyLanguageModel/SessionProperties.swift
#	Tests/AnyLanguageModelTests/SessionPropertyTests.swift
…dynamic-profiles

# Conflicts:
#	Sources/AnyLanguageModel/LanguageModelSession.swift
…ofile-tool-continuations

# Conflicts:
#	Sources/AnyLanguageModel/DynamicProfile.swift
#	Sources/AnyLanguageModel/LanguageModelSession.swift
qoli and others added 29 commits October 19, 2026 09:10
main has the shared profile runtime from huggingface#315 and the work in huggingface#344 to huggingface#348,
so main's version is kept for all files except SystemLanguageModel.swift
and NativeProfileHistoryTests.swift.

The tests now expect what main does when it creates a profile session:
it evaluates the profile once and records an instructions entry.
Foundation Models sends a profile's transformed prompt in place of the current one.
A native request sent both prompts, or the original text if the transform kept the IDs.
During a request, each native evaluation already returns the prepared context,
so the reuse changed nothing there.
The profile is still resolved when the session is made, for the projected history.
The original prompt was converted first, so a transform that replaced a remote image
with text still threw nonFileImageURL. A profile session now converts it only if the
request sends it.

A rewritten prompt went through the tool output converter, which flattened structured
segments to JSON text and dropped their source. A Foundation Models prompt can't set a
segment's ID or source, so a native history transform now sets the rewritten segments.
@mattt
mattt merged commit ba10b11 into huggingface:main Nov 6, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants