Skip to content

Add dependency-free TypeScript token providers and client adapters - #519

Merged
robgruen merged 3 commits into
mainfrom
dev/robgruen/typescript-keyless-auth
Nov 4, 2026
Merged

robgruen merged 3 commits into
mainfrom
dev/robgruen/typescript-keyless-auth

Conversation

@robgruen

@robgruen robgruen commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add TypeScript parity for the dependency-free authentication/client-injection approach in #516, in a separate branch/worktree. This PR changes only TypeScript and directly related documentation; it does not expand the Python PR.

  • Add a synchronous/asynchronous TokenProvider option to the OpenAI and Azure HTTP factories. Pass undefined for the API-key argument to opt in; resolve a raw bearer token for each HTTP attempt, including retries.
  • Add createOpenAILanguageModelFromClient with structural ChatCompletionClient and ResponsesClient contracts. Reuse an existing configured client without importing/installing an SDK in TypeChat.
  • Support Chat Completions and explicitly selected Responses clients, including text/image user prompts and per-API image/text-part mapping.
  • Reuse the existing completion/metadata/filtering parser so reported usage, refusal/filtering failures, validation, and repair retain their existing semantics.
  • Add offline regression tests to already-wired model, metadata, and failure test coverage, and document both integration paths.

Compatibility and ownership

  • Existing positional arguments, string-key behavior (including legacy headers), environment routing/defaults, and literal identity values are unchanged. API keys and token providers are mutually exclusive.
  • HTTP models retain proxy dispatch, timeout, response-size, retry, and metadata accounting controls. Empty/non-string tokens and tokens containing whitespace/control/non-ASCII characters fail with a fixed, credential-free error before dispatch. Credential acquisition/caching/renewal remains caller-owned and is not included in the HTTP request timeout.
  • Client adapters expose only complete, preserving the caller's instance, endpoint/API version, authentication, retries/timeouts, and lifecycle. They do not reconfigure/close the client or add a retry/timeout layer. Client exceptions and cancellation propagate unchanged.
  • Unsupported/malformed prompt parts are explicit errors, not dropped content. Images are supported in user messages; system/assistant messages support text only on the new client-adapter path. Legacy fetch request shapes are unchanged.
  • Responses mode is explicit for client adapters; Chat-only clients do not need a responses member. SDK response metadata reflects resolved responses visible to TypeChat, not retries hidden inside the supplied SDK.
  • No dependency manifests, lockfiles, runtime/optional/development dependencies, or test-runner scripts change.

Validation

Using the repository-pinned Node.js 24.22.1:

  • npm run build - passed.
  • tsc -p test - passed.
  • node --test tests\model.test.mjs out\metadata.test.js out\failure.test.js - 182 passed, including legacy behavior, sync/async providers, per-attempt tokens, malformed bearer strings rejected before dispatch, network limits, both client API shapes, images, ownership, errors/cancellation, filtering, metadata, and translator repair.
  • Independent strict structural-type and mocked runtime checks with the genuine OpenAI JS SDK 7.45.1 OpenAI/AzureOpenAI clients - passed. Four mocked calls covered both API shapes, image mapping, rotating Azure bearer tokens, preserved client configuration, and metadata.
  • Whitespace and unchanged dependency-manifest checks passed.

The SDK used for that independent check was installed only in a separate tool directory; repository tests do not require it. The build, unit, and SDK-mock checks above were offline.

Manual live Azure identity validation (2026-11-03)

Tested commit: 91f3b26.

All four live checks passed against a real identity-configured Azure deployment:

Path API Input Result
HTTP token provider Chat Completions Text Passed
Configured AzureOpenAI client Chat Completions Synthetic image and text Passed
HTTP token provider Responses Text Passed
Configured OpenAI client Responses Synthetic image and text Passed

Real Entra access-token acquisition and bearer-only request headers were observed; no Azure OpenAI API-key headers were used. All outputs passed TypeChat schema validation on the first model request, and the image results matched the expected color. There were four actual model requests, with no model-request retries or repairs required.

Not exercised: expiry-driven token renewal. These were manual live smoke tests, not additional CI requirements. Private endpoint, deployment, configuration, and credential details are intentionally omitted.

Review follow-up (2026-11-03)

The malformed-token issue reported on the Python PR was already covered by the TS guard in 91f3b26, including trailing-newline/control/non-ASCII regressions across all HTTP factory paths.

5324d14 also applies the shared blocking-provider concern even though TS had no open review threads:

  • Clarify that providers run on the caller's event loop, use asynchronous I/O for acquisition/renewal, and require application-managed workers for truly blocking legacy providers. Merely wrapping synchronous work in async/a Promise does not offload it.
  • Add pending-credential-Promise regressions for all three HTTP factory paths, confirming event-loop progress and no fetch before credential resolution.
  • Build, test type-check, and 182 focused regressions passed. Provider invocation and runtime validation behavior are unchanged; the live validation above remains pinned to the runtime-equivalent commit actually exercised.

Separate Python follow-ups

These are tracking issues only, not additional Python implementation work in this PR. Related context: #216 and #516. Human review is required; no merge is requested.

Preserve legacy HTTP factories while adding opt-in token providers and configured Chat Completions/Responses clients with multimodal prompts and shared metadata/filtering behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@robgruen robgruen added the Language: TypeScript Pertains to the TypeScript/JavaScript implementation of TypeChat. label Nov 3, 2026
Copilot AI balanced review requested due to automatic review settings November 3, 2026 17:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues remain for the TypeScript authentication and configured-client integration changes.

No open issues 🎉

What changed in this PR

Adds dependency-free authentication and configured-client integration to TypeScript, complementing the separate Python work without changing Python code.

Changes:

  • Adds synchronous/asynchronous bearer-token providers to HTTP factories, resolving tokens for each attempt while preserving existing transport controls.
  • Adds caller-owned Chat Completions and Responses client adapters with text/image prompt mapping and shared completion, metadata, and filtering parsing.
  • Adds offline regression coverage and documents authentication, client ownership, and error behavior.
File Description
typescript/​tests/​model.test.mjs Tests token providers, client adapters, prompt mapping, errors, and compatibility.
typescript/​test/​metadata.test.ts Tests usage accounting, filtering, and multimodal context across repair attempts.
typescript/​src/​model.ts Implements token providers, structural client contracts, adapters, and shared completion parsing.
typescript/​README.md Introduces authentication reuse and links to integration examples.
typescript/​metadata.md Clarifies metadata accounting for caller-owned clients and HTTP token providers.
site/​src/​docs/​typescript/​basic-usage.md Documents integration examples, supported prompts, and control ownership.

Review effort: Balanced

Cover whitespace, trailing newlines, control characters, non-ASCII values, and valid printable-ASCII boundaries without changing legacy API-key handling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 18:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues remain for the TypeScript authentication and client-reuse changes.

No open issues 🎉

Review effort: Balanced

Apply the Python review's shared event-loop guidance to TypeScript without changing provider invocation or the existing malformed-token guard. Add pending-Promise regressions for all HTTP factory paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 20:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues are reported for the TypeScript token-provider authentication and configured-client adapter changes.

No open issues 🎉

Review effort: Balanced

@robgruen
robgruen merged commit cf3a2c8 into main Nov 4, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Language: TypeScript Pertains to the TypeScript/JavaScript implementation of TypeChat.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants