Skip to content

Commit 2cb017e

Browse files
committed
feat(FR-2590): display currentRevision modelDefinition in EndpointDetailPage service info (#6746)
Resolves #6744 (FR-2590) ## Summary - Added `modelDeployment: node(id: $deploymentId)` GraphQL query to `EndpointDetailPageQuery` to fetch `currentRevision.modelDefinition` - Added `$skipModelDefinition: Boolean!` variable gated on `baiClient.supports('model-card-v2')` (26.4.0+) - Displays model definition fields in the Service Info `Descriptions` component for each model in the `models` array: - Model Name - Model Path - Start Command (rendered via `SourceCodeView`) - Port - Health Check path, initial delay, max retries - When `currentRevision` is null or `models` is empty, no items are added - Added `'use memo'` directive to `EndpointDetailPage` component **Checklist:** - [ ] Documentation - [x] Minimum required manager version (26.4.0 — gated via `model-card-v2` feature flag) - [ ] Specific setting for review - [ ] Minimum requirements to check during review - [ ] Test case(s) to demonstrate the difference of before/after
1 parent 80d9660 commit 2cb017e

30 files changed

Lines changed: 1085 additions & 174 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Model Definition GraphQL Improvements Findings
2+
3+
## Decisions
4+
| Date | Decision | Rationale | Issue |
5+
|------|----------|-----------|-------|
6+
7+
## Discoveries
8+
9+
## Issues Encountered
10+
| Date | Problem | Root Cause | Resolution | Issue |
11+
|------|---------|-----------|------------|-------|
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Model Definition GraphQL Improvements Progress
2+
3+
## Last Session: 2026-04-16 12:00
4+
5+
### 1. Current Phase
6+
Planning complete. Ready for Wave 1 implementation.
7+
8+
### 2. Next Action
9+
Run /batch-implement .specs/FR-2588-model-definition-graphql/dev-plan.md to start Wave 1.
10+
11+
### 3. Current Goal
12+
Begin implementation of model definition GraphQL improvements.
13+
14+
### 4. Lessons Learned
15+
(none yet)
16+
17+
### 5. Completed Work
18+
- Spec created: .specs/FR-2588-model-definition-graphql/spec.md
19+
- Dev plan created: .specs/FR-2588-model-definition-graphql/dev-plan.md
20+
- 2 issues created with GitHub cross-links (FR-2590 #6744, FR-2591 #6745)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Model Definition GraphQL Improvements Tasks
2+
3+
> Last synced: 2026-04-16 12:00
4+
> Source: Jira / GitHub Issues
5+
6+
## Progress: 0/2 complete
7+
8+
### Wave 1 (parallel)
9+
- [ ] FR-2590 (#6744): Display currentRevision.modelDefinition in EndpointDetailPage Service Info -- created
10+
- [ ] FR-2591 (#6745): Replace vfolder YAML parsing with GraphQL query and add overwrite confirmation in edit mode -- created
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Model Definition GraphQL Improvements Dev Plan
2+
3+
## Spec Reference
4+
`.specs/FR-2588-model-definition-graphql/spec.md`
5+
6+
## Epic: FR-2588
7+
8+
## Sub-tasks (Implementation Order)
9+
10+
### 1. Display currentRevision.modelDefinition in EndpointDetailPage Service Info - FR-2590
11+
- **GitHub Issue**: #6744
12+
- **Changed files**: `react/src/pages/EndpointDetailPage.tsx`, `resources/i18n/en.json`, `resources/i18n/ko.json`
13+
- **Dependencies**: None
14+
- **Review complexity**: Medium
15+
- **Branch**: `feat/FR-2590-endpoint-model-definition-display`
16+
- **Stack base**: `04-16-feat_add_model_definition_graphql_improvement_spec`
17+
- **Description**:
18+
- Add `deployment(id: $deploymentId) { currentRevision { modelDefinition { models { name, modelPath, service { startCommand, port, healthCheck { path, initialDelay, maxRetries } } } } } }` to `EndpointDetailPageQuery`
19+
- The query already has `$deploymentId: ID!` variable and `toGlobalId('ModelDeployment', serviceId)` — just need to add the `deployment` field
20+
- Add Descriptions items after existing items for: Model Name, Model Path, Start Command, Port, Health Check Path, Initial Delay, Max Retries
21+
- Guard with null checks: `currentRevision` may be null, `models` may be empty
22+
- Reuse existing i18n keys from `modelService.*` namespace (HealthCheck, InitialDelay, MaxRetries, Port) and `modelStore.*` (ModelName, ModelPath, StartCommand)
23+
- May need new i18n key for section header like "Model Definition" (already exists: `modelService.ModelDefinition`)
24+
25+
### 2. Replace vfolder YAML parsing with GraphQL query and add overwrite confirmation in edit mode - FR-2591
26+
- **GitHub Issue**: #6745
27+
- **Changed files**: `react/src/components/ServiceLauncherPageContent.tsx`
28+
- **Dependencies**: None
29+
- **Review complexity**: High
30+
- **Branch**: `feat/FR-2591-graphql-edit-and-overwrite-confirm`
31+
- **Stack base**: `04-16-feat_add_model_definition_graphql_improvement_spec`
32+
- **Description**:
33+
- **Feature 2 — GraphQL data load**: Replace `loadModelDefinitionForEdit` (lines 1339-1371) which does vfolder download + YAML parse with a GraphQL query using `deployment(id:) { currentRevision { modelDefinition { models { ... } } } }`. Use `fetchQuery` from relay-runtime since this is an imperative load triggered from useEffect, not a declarative render-time query. Map `models[0].service` fields to form: `startCommand`, `port` -> `commandPort`, `healthCheck.path` -> `commandHealthCheck`, `healthCheck.initialDelay` -> `commandInitialDelay`, `healthCheck.maxRetries` -> `commandMaxRetries`. Keep vfolder parsing as fallback when `modelDefinition` is null.
34+
- **Feature 3 — Overwrite confirmation**: In the `handleOk` edit mode flow (around line 966), add `modal.confirm` before uploading model-definition.yaml, matching the same pattern used in create mode (lines 642-657). Wrap upload in a `new Promise<boolean>` resolved by `onOk`/`onCancel`. If cancelled, abort via `throw new DOMException('User cancelled overwrite', 'AbortError')`.
35+
36+
## PR Stack Strategy
37+
- Stack 1: Sub-task 1 (FR-2590) — EndpointDetailPage changes
38+
- Stack 2: Sub-task 2 (FR-2591) — ServiceLauncherPageContent changes
39+
- Both stacks branch from `04-16-feat_add_model_definition_graphql_improvement_spec`
40+
- Stacks are fully independent and can be reviewed/merged in parallel
41+
42+
## Dependency Graph
43+
```
44+
FR-2590 (EndpointDetailPage display) [independent]
45+
FR-2591 (GraphQL edit + overwrite modal) [independent]
46+
47+
Both can run in parallel — Wave 1 contains both tasks.
48+
```
49+
50+
## Waves for batch-implement
51+
- **Wave 1**: FR-2590, FR-2591 (parallel)
52+
53+
## Risks and Notes
54+
- `currentRevision` field is marked "Added in UNRELEASED" in the schema — need `@since` directive or feature flag if backend version gating is required
55+
- `startCommand` is `JSON!` type in GraphQL schema (not String) — need to handle serialization when displaying and when mapping to form field
56+
- FR-2591 is High complexity due to replacing an imperative async flow with GraphQL and adding modal confirmation logic in the same mutation handler

.specs/FR-2588-model-definition-graphql/metadata.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44
"slug": "model-definition-graphql",
55
"specTaskKey": "FR-2589",
66
"stories": [],
7+
"tasks": [
8+
{
9+
"key": "FR-2590",
10+
"title": "Display currentRevision.modelDefinition in EndpointDetailPage Service Info",
11+
"githubIssue": 6744,
12+
"specSection": "Requirement 1"
13+
},
14+
{
15+
"key": "FR-2591",
16+
"title": "Replace vfolder YAML parsing with GraphQL query and add overwrite confirmation in edit mode",
17+
"githubIssue": 6745,
18+
"specSection": "Requirements 2 and 3"
19+
}
20+
],
721
"sourceIssues": ["FR-2581"],
822
"createdAt": "2026-04-16T00:00:00+09:00"
923
}

packages/backend.ai-ui/src/components/fragments/BAIRouteNodes.tsx

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ const routeHealthStatusSemanticMap: Record<string, SemanticColor> = {
6363
NOT_CHECKED: 'default',
6464
};
6565

66-
const trafficStatusSemanticMap: Record<string, SemanticColor> = {
67-
ACTIVE: 'success',
68-
};
69-
7066
export interface BAIRouteNodesProps extends Omit<
7167
BAITableProps<RouteNodeInList>,
7268
'dataSource' | 'onChangeOrder' | 'columns'
@@ -198,24 +194,25 @@ const BAIRouteNodes = ({
198194
) : null,
199195
}
200196
: undefined,
201-
{
202-
title: t('comp:BAIRouteNodes.TrafficStatus'),
203-
dataIndex: 'trafficStatus',
204-
key: 'trafficStatus',
205-
render: (trafficStatus) =>
206-
trafficStatus && trafficStatus !== '%future added value' ? (
207-
<BAITag
208-
color={
209-
semanticColorMap[
210-
trafficStatusSemanticMap[trafficStatus] ?? 'default'
211-
]
212-
}
213-
style={{ marginRight: 0 }}
214-
>
215-
{trafficStatus}
216-
</BAITag>
217-
) : null,
218-
},
197+
// TODO(needs-backend): Unhide when backend interaction for traffic status is supported (FR-2591)
198+
// {
199+
// title: t('comp:BAIRouteNodes.TrafficStatus'),
200+
// dataIndex: 'trafficStatus',
201+
// key: 'trafficStatus',
202+
// render: (trafficStatus) =>
203+
// trafficStatus && trafficStatus !== '%future added value' ? (
204+
// <BAITag
205+
// color={
206+
// semanticColorMap[
207+
// trafficStatusSemanticMap[trafficStatus] ?? 'default'
208+
// ]
209+
// }
210+
// style={{ marginRight: 0 }}
211+
// >
212+
// {trafficStatus}
213+
// </BAITag>
214+
// ) : null,
215+
// },
219216
// TODO(needs-backend): Uncomment when the backend supports traffic ratio for routes
220217
// {
221218
// title: t('comp:BAIRouteNodes.TrafficRatio'),

0 commit comments

Comments
 (0)