Skip to content

feat: support overridePaths in deployment interfaces #1969 - #1961

Merged
khshanovskyi merged 6 commits into
developmentfrom
feat/interfaces-override-paths
Sep 14, 2026
Merged

khshanovskyi merged 6 commits into
developmentfrom
feat/interfaces-override-paths

Conversation

@khshanovskyi

@khshanovskyi khshanovskyi commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Adds interfaces.<type>.overridePaths so DIAL Core can front services that do not follow the DIAL API path contract (e.g. Switchyard serving /v1/chat/completions): a per-operation path replaces the default "base URL + ingress path" routing, with the exact tokens {id} and {overrideName} substituted. Applies to models, applications and interceptors.

Applicable issues

Description of changes

  • DeploymentInterface gains overridePaths (overridePaths/override_paths), keyed by the new OverridePathKey enum: postAzureOpenaiChatCompletions, postAzureOpenaiEmbeddings, postOpenaiResponses, getOpenaiResponsesById, deleteOpenaiResponsesById, postOpenaiResponsesCancel, postAnthropicMessages, postAnthropicMessagesCountTokens. Unknown key names are tolerated for forward compatibility, mirroring unknown interface types.
  • New PathTemplateUtil substitutes exactly the literal tokens {id} and {overrideName}; any other brace usage (typos like {Id}, unknown placeholders, literal braces) is rejected at config load by a dry-run render, keeping the brace syntax reserved for future tokens.
  • DeploymentEndpointUtil.resolveRequestUri consults the override for the deployments-POST family (chat completions, embeddings, responses create, anthropic messages/count_tokens); a new resolveResponseItemUri covers responses GET/DELETE/cancel by id and replaced the three call sites that concatenated onto resolveResponsesBaseUri (item controller, interceptor hop, background poll). Overrides apply only in the interfaces/base-url flow — legacy endpoint/responsesEndpoint and translator-served interfaces are untouched, and behavior without overridePaths is byte-identical.
  • {id} renders the deployment's name for the deployments-POST family (equal to the path id on direct calls, and still correct on the interceptor callback hop where the raw segment is the pseudo-id interceptor) and the hop's response id for responses item operations; {overrideName} renders the URL-encoded overrideName, falling back to the deployment name.
  • Config validation: misplaced keys, malformed templates, {id} where the operation carries none, and overrides on mode: translator entries are rejected at load for models, applications and interceptors — including the MergedConfigStore partial-update write path, so a write cannot accept an entity the next full rebuild would drop.
  • Tests: unit coverage in PathTemplateUtilTest, DeploymentEndpointUtilTest, ConfigPostProcessorTest; full-stack OverridePathsApiTest proving requests on standard Core paths reach the mock upstream on the overridden paths for chat completions (with {overrideName}), embeddings, anthropic messages/count_tokens, responses create + GET-by-id, an application, and unoverridden cancel/delete keeping default routing.
  • Docs: new "Override paths per interface" section in docs/dynamic-settings/models.md, with pointers from applications.md and interceptors.md.

Checklist

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

🤖 Generated with Claude Code

@ai-dial-actions

This comment has been minimized.

1 similar comment
@ai-dial-actions

This comment has been minimized.

@khshanovskyi
khshanovskyi force-pushed the feat/interfaces-override-paths branch from 5ca9faa to d30ecda Compare September 14, 2026 08:32
Comment thread server/src/main/java/com/epam/aidial/core/server/config/ConfigPostProcessor.java Outdated
@khshanovskyi khshanovskyi changed the title feat: support overridePaths in deployment interfaces feat: support overridePaths in deployment interfaces #1969 Sep 14, 2026
Comment thread config/src/main/java/com/epam/aidial/core/config/OverridePathKey.java Outdated
astsiapanay
astsiapanay previously approved these changes Sep 14, 2026
khshanovskyi and others added 5 commits September 14, 2026 13:42
Adds `interfaces.<type>.overridePaths` so DIAL Core can front services that
do not follow the DIAL API path contract: a per-operation path replaces the
default "base URL + ingress path" routing for models, applications and
interceptors.

- `DeploymentInterface.overridePaths` maps a new `OverridePathKey` constant
  (`postAzureOpenaiChatCompletions`, `postAzureOpenaiEmbeddings`,
  `postOpenaiResponses`, `getOpenaiResponsesById`, `deleteOpenaiResponsesById`,
  `postOpenaiResponsesCancel`, `postAnthropicMessages`,
  `postAnthropicMessagesCountTokens`) to the path applied under the base url.
  A key this Core does not know is ignored, as an unknown interface type is.
- `PathTemplateUtil` substitutes exactly two tokens: `{overrideName}` first
  (url-encoded, so brace-free) and `{id}` last (never rescanned). Braces carry
  no other syntax — anything else is path text forwarded as written. `{id}` is
  the deployment name for the deployments-POST family and the hop's response id
  for Responses item operations.
- `DeploymentEndpointUtil.resolveRequestUri` consults the override per
  operation, and a new `resolveResponseItemUri` serves Responses get/delete/
  cancel, replacing the three sites that concatenated onto
  `resolveResponsesBaseUri` (item controller, interceptor hop, background poll).
  Overrides apply only to interfaces/base-url routing: legacy `endpoint`/
  `responsesEndpoint` and translator-served interfaces are untouched, and
  behaviour without `overridePaths` is unchanged.
- Config validation rejects a key declared under an interface that does not own
  it, an empty path, `{id}` on an operation that carries none, and overrides on
  a `mode: translator` entry — at config load and on every API write surface
  (config-resource writes, custom application writes, admin validate/apply), so
  a write cannot persist an entity the next rebuild would drop.
- Corrects the documented interface types applications serve: the Responses and
  Anthropic Messages APIs work for applications, and nothing dropped them on
  config read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ConfigPostProcessor and ConfigValidationService no longer know about
HttpException: validateOverridePaths only accumulates ValidationWarnings,
and each write surface turns them into its own layer's failure — an
EntityResult/ValidationResult for the admin services, the established
validationWarnings 422 for the config-resource controller (whose body
building is now shared with checkCrossReferences and checkTranslator),
and the service's own HttpException idiom for application writes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Per review. Renames the type and the identifiers named after it
(pathKey -> pathMapping, findRequestPathKey -> findRequestPathMapping,
Operation.key -> Operation.pathMapping); the JSON key names in
overridePaths are unchanged. Also drops a stale line in the
DeploymentInterface javadoc that still promised doubled braces escape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Override-path validation short-circuited before pricing and cross-reference
checks, so a write carrying both kinds of defects reported only the override
paths. Collect all of them into one warnings list on both write paths
(POST /v1/admin/apply and PUT /v1/models/...), keeping override-path errors
fatal even when soft validation is on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rnings list

Interceptor and Application prechecks went through a private String-returning
helper while every other validation in the file collects into a
List<ValidationWarning> and joins it. Use the common shape so a second
validation can be added next to the first one.

Also make override-path defects fatal for Model precheck even under soft
validation, matching ConfigApplyService#applyModel: otherwise precheck reports
the batch as valid and the real-apply phase then refuses the model, after its
siblings have already been written.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@khshanovskyi
khshanovskyi merged commit 6ed0c9a into development Sep 14, 2026
9 checks passed
@khshanovskyi
khshanovskyi deleted the feat/interfaces-override-paths branch September 14, 2026 11:21
@ai-dial-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

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.

Extend interfaces config with overridePaths

4 participants