Skip to content

Add opt-in completion metadata and harden prompt delimiters - #336

Open
robgruen wants to merge 5 commits into
mainfrom
dev/robgruen/jailbreak_fix
Open

robgruen wants to merge 5 commits into
mainfrom
dev/robgruen/jailbreak_fix

Conversation

@robgruen

@robgruen robgruen commented Aug 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Merge the latest main (d0b9597), including Retain rejected output and repair failure context #338's rejected-output and repair-failure context.
  • Preserve ILanguageModel.CompleteAsync and all existing provider methods as Task<string>. Add opt-in ILanguageModelWithMetadata.CompleteWithMetadataAsync plus an extension method that supports existing text-only models.
  • Keep existing TranslateAsync calls routed through the original protected GetResponseAsync hook. The additive TranslateToResultAsync API uses a separate metadata-aware hook and retains both completion metadata and failure context.
  • Preserve transport exception identity and cancellation. Only exhausted validation/repair failures become failed results; metadata describes the final completion rather than total repair usage.
  • Fix Azure endpoint switching, preserve v1 routes and query strings, and concatenate all Responses API text parts. Handle malformed brace ordering as invalid model output rather than a parser exception.
  • JSON-encode request and repair-error data to harden prompt delimiters; this is not a guarantee against prompt injection.

Compatibility

Existing model implementations, Task<string> callers, and translator subclasses continue to work without recompilation. REST and Microsoft.Extensions.AI expose the optional metadata capability. Semantic Kernel and other text-only models work through the extension-method fallback with unavailable metadata left null. No shared "last completion" state is introduced.

The original throwing translation API remains supported. Subclasses opting into the result-returning API can override GetResponseWithMetadataAsync.

Validation

  • All 265 unit tests pass locally, including 112 focused compatibility, provider, failure-context, prompt, and endpoint tests.
  • A binary-compatibility test compiles a consumer against a metadata-free reference contract, then loads it against the current library. It exercises an old model implementation, an old translator override, and an old concrete-model caller.
  • Changed libraries and tests build in Release with warnings treated as errors, except the explicitly reported local NU1900 warning for an unreachable NuGet audit feed.
  • Full-solution restore is blocked locally by a NuGet TLS failure for integration-test dependencies. The complete solution build and unit-test matrix both passed in GitHub Actions: https://github.com/microsoft/typechat.net/actions/runs/38806801329.

@robgruen
robgruen requested a lite review from Copilot August 28, 2026 22:58
@robgruen
robgruen requested a review from a team as a code owner August 28, 2026 22:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Lite
Findings: 1 High severity · 1 Medium severity

New issues introduced by this change (2)
Severity Finding
High severity src/​typechat/​LanguageModel.cs — When OpenAIConfig.UseResponsesApi is explicitly set to false, non-Azure configuration should ensure…
Medium severity src/​typechat/​HttpEx.cs — GetJsonResponseWithRawAsync reuses a single StringContent across retries, but…
What changed in this PR

This PR upgrades TypeChat’s language-model abstraction to return a richer LanguageModelResponse (text + normalized completion metadata), adds normalized token/finish-reason types, updates prompts to JSON-encode user/error sections to reduce prompt-injection risk, and expands unit tests to cover the new behaviors (including OpenAI “Responses API” routing).

Changes:

  • Changed ILanguageModel.CompleteAsync (and implementations) to return LanguageModelResponse, carrying CompletionInfo (model, finish reason, token usage, raw JSON).
  • Added non-throwing JsonTranslator.TranslateToResultAsync APIs returning Result<T> with attached completion metadata on success.
  • Added HTTP helper to capture raw JSON responses and updated prompt templates to JSON-string encode untrusted request/error text.
File Description
tests/​TypeChat.UnitTests/​TestLanguageModel.cs Adds coverage for CompletionInfo parsing and /responses endpoint routing.
tests/​TypeChat.UnitTests/​TestJsonTranslatorPrompts.cs Verifies prompt sections JSON-encode untrusted request/error text.
tests/​TypeChat.TestLib/​Models.cs Updates mock language model to new LanguageModelResponse return type.
tests/​TypeChat.IntegrationTests/​TestEndToEnd.cs Adjusts assertion to handle LanguageModelResponse (string conversion).
src/​typechat/​TokenUsage.cs Introduces normalized token usage model.
src/​typechat/​Result.cs Adds optional CompletionInfo to successful results.
src/​typechat/​OpenAIConfig.cs Adds UseResponsesApi selector for endpoint variant selection.
src/​typechat/​LanguageModelResponse.cs New response wrapper with implicit conversion to/from string.
src/​typechat/​LanguageModel.cs Adds Responses API support, endpoint inference/rewrites, and completion metadata extraction.
src/​typechat/​JsonTranslatorPrompts.cs Switches prompt embedding to JSON-string encoding for safety/consistency.
src/​typechat/​JsonTranslator.cs Adds non-throwing translation APIs and propagates completion info + repair attempts.
src/​typechat/​ILanguageModel.cs Interface updated to return LanguageModelResponse.
src/​typechat/​HttpEx.cs Adds GetJsonResponseWithRawAsync to return parsed + raw response JSON.
src/​typechat/​CompletionInfo.cs New normalized completion metadata container (model/usage/finish/raw/repairs).
src/​typechat/​CompletionFinishReason.cs New normalized finish reason enum.
src/​typechat.sk/​TextCompletionModel.cs Updates SK adapter to return LanguageModelResponse.
src/​typechat.sk/​ChatLanguageModel.cs Updates SK adapter to return LanguageModelResponse.
src/​typechat.meai/​ChatLanguageModel.cs Updates MEAI adapter to return LanguageModelResponse with normalized metadata.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/typechat/LanguageModel.cs Outdated
Comment thread src/typechat/HttpEx.cs Outdated
robgruen and others added 3 commits August 28, 2026 16:04
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Preserve the original completion API and translator hooks while adding optional metadata and validation-result APIs. Retain failure context from main, fix endpoint and output handling, and test consumers compiled against the original contracts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@robgruen robgruen changed the title Add token stats and raw completion info; prevent jailbreaking Add opt-in completion metadata and harden prompt delimiters Oct 15, 2026

This branch has not been deployed

No deployments
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