Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions memory-bank/aiConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,15 @@ JSON Schema:

**Capability maps (single source of truth).** `BUILTIN_CONNECTION_SECTIONS`
(keyed by built-in id) and `CUSTOM_CONNECTION_SECTIONS` (keyed by supported
custom `type`) name which of `aws` / `googleCloud` / `snowflake` / `positaiLogin`
each provider carries. Both are `satisfies Record<…>` so a missing key is a
compile error (exhaustiveness). Only four built-ins carry a section — `bedrock`
(`aws`), `google-vertex` (`googleCloud`), `snowflake-cortex` (`snowflake`),
`positai` (`positaiLogin`); of the custom kinds only `aws` / `google-vertex` /
`snowflake` do. `positaiLogin` attaches to the built-in `positai` key **only** —
no custom variant carries it.
custom `type`) name which of `aws` / `azure` / `googleCloud` / `snowflake` /
`positaiLogin` each provider carries. Both are `satisfies Record<…>` so a
missing key is a compile error (exhaustiveness). Only five built-ins carry a
section — `bedrock` (`aws`), `ms-foundry` (`azure`), `google-vertex`
(`googleCloud`), `snowflake-cortex` (`snowflake`), `positai` (`positaiLogin`);
of the custom kinds only `aws` / `google-vertex` / `snowflake` do.
`positaiLogin` attaches to the built-in `positai` key **only** — no custom
variant carries it. Likewise `azure` attaches to the built-in `ms-foundry`
key only: custom `ms-foundry` providers stay required-API-key.

**Supported custom kinds ⊂ client kinds.** `providers.custom` entries are
restricted to `SUPPORTED_CUSTOM_CLIENT_KIND_VALUES`, a local mirror of
Expand All @@ -126,6 +128,17 @@ overlay. It does **not** touch the auth-method / storage-key / status vocabulary
which stays `oauth` (a genuinely different concept — mapped at the
`getPositaiAuthConfig` seam in `@assistant/node`).

**`azure` (Microsoft Foundry Entra ID).** The built-in `ms-foundry` key carries an
`azure` sub-section (`authMode` `"apikey" | "entra"`, `scope`, `tenantId` — all
optional, all non-secret). `MS_FOUNDRY_DEFAULTS` resolves an absent `authMode`
to `"apikey"` (back-compat) and an absent `scope` to
`MS_FOUNDRY_DEFAULT_SCOPE` (`https://cognitiveservices.azure.com/.default`;
newer Foundry-scoped endpoints may want `https://ai.azure.com/.default`), so the
resolved catalog always carries both. Env overlays: `MS_FOUNDRY_AUTH_MODE` /
`MS_FOUNDRY_ENTRA_SCOPE` / `MS_FOUNDRY_TENANT_ID`. Entra tokens are acquired at
runtime by `@azure/identity` in the bridge — nothing secret is stored, and a
fresh entra configuration writes nothing to the credential store.

**Strict validation vs. permissive working type.** Strictness is a parse-time
property. The inferred `ProvidersMap` built-in blocks and `ResolvedConnection`
stay a permissive **superset** (all sub-sections optional), so reader/writer code
Expand Down Expand Up @@ -206,6 +219,15 @@ distinguishable from ambient-only state. This lets auth-readiness policy stay
conservative without forcing consumers to reconstruct ai-config's precedence
stack.

For the built-in `ms-foundry` provider it additionally records a per-field
`ResolvedConnectionFieldSource` (`user` / `enforced` / `environment` /
`default`) for every UI-managed field — `azure.authMode`, `azure.scope`,
`azure.tenantId`, and `baseUrl` — so a configure form can disable each
individually pinned control without re-deriving precedence from resolved
values. The source is the highest-precedence kept source that sets the field;
`authMode`/`scope` fall back to `"default"` (built-in defaults) when no source
sets them, while `baseUrl`/`tenantId` are absent until some layer sets them.

### Model selection (`resolveModels`)

`resolveModels(modelsBlock, discovered, providerConnection)` runs the per-provider
Expand Down
17 changes: 17 additions & 0 deletions memory-bank/providerGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,23 @@ New providers should support the `customHeaders` field from `ApiKeyCredentials`.

See `src/custom-headers.ts` for the shared filtering/merging utilities.

## Ambient-Cloud-Credential Providers (Vertex, Foundry Entra)

Providers whose auth comes from a cloud CLI / ambient identity (no stored
secret) carry a credential type with **no secret material** and let the cloud
SDK own the token lifecycle:

- `GoogleCloudCredentials` (`google-cloud`) — google-auth-library resolves ADC.
- `AzureEntraCredentials` (`azure-entra`) — `baseUrl` + required `scope` +
optional `tenantId`/`customHeaders`. `src/model-clients/azure-entra-token.ts`
caches `getBearerTokenProvider(new DefaultAzureCredential(...), scope)` per
scope+tenant (the SDK caches tokens per credential instance, so the cache is
required, not optional) and normalizes chain failures into an actionable
"run `az login`" error. The Foundry client factory composes the bearer
injection **around** `createOpenAICompatibleFetch` (which keeps owning
additive `customHeaders` and request/stream normalization) rather than
replacing it.

## Common Pitfalls

- **Don't modify the registry class** -- Use the plugin pattern (`registerModelFetcher` / `registerClientFactory`)
Expand Down
Loading