diff --git a/frontend/src/api/admin/ops.ts b/frontend/src/api/admin/ops.ts
index 64f6a6d0..0541bb59 100644
--- a/frontend/src/api/admin/ops.ts
+++ b/frontend/src/api/admin/ops.ts
@@ -969,6 +969,10 @@ export interface OpsErrorLog {
client_ip?: string | null
request_path?: string
stream?: boolean
+
+ // Model mapping context for ops error observability
+ requested_model?: string
+ upstream_model?: string
}
export interface OpsErrorDetail extends OpsErrorLog {
diff --git a/frontend/src/views/admin/ops/components/OpsErrorDetailModal.vue b/frontend/src/views/admin/ops/components/OpsErrorDetailModal.vue
index a7edff96..0817f239 100644
--- a/frontend/src/views/admin/ops/components/OpsErrorDetailModal.vue
+++ b/frontend/src/views/admin/ops/components/OpsErrorDetailModal.vue
@@ -59,7 +59,14 @@
{{ t('admin.ops.errorDetail.model') }}
- {{ detail.model || '—' }}
+
+ {{ detail.requested_model }}
+ →
+ {{ detail.upstream_model }}
+
+
+ {{ displayModel(detail) || '—' }}
+
@@ -213,6 +220,22 @@ function isUpstreamError(d: OpsErrorDetail | null): boolean {
return phase === 'upstream' && owner === 'provider'
}
+function hasModelMapping(d: OpsErrorDetail | null): boolean {
+ if (!d) return false
+ const requested = String(d.requested_model || '').trim()
+ const upstream = String(d.upstream_model || '').trim()
+ return !!requested && !!upstream && requested !== upstream
+}
+
+function displayModel(d: OpsErrorDetail | null): string {
+ if (!d) return ''
+ const upstream = String(d.upstream_model || '').trim()
+ if (upstream) return upstream
+ const requested = String(d.requested_model || '').trim()
+ if (requested) return requested
+ return String(d.model || '').trim()
+}
+
const correlatedUpstream = ref([])
const correlatedUpstreamLoading = ref(false)
diff --git a/frontend/src/views/admin/ops/components/OpsErrorLogTable.vue b/frontend/src/views/admin/ops/components/OpsErrorLogTable.vue
index 28868552..58846db6 100644
--- a/frontend/src/views/admin/ops/components/OpsErrorLogTable.vue
+++ b/frontend/src/views/admin/ops/components/OpsErrorLogTable.vue
@@ -83,11 +83,22 @@
-
-
- {{ log.model }}
-
- -
+
+
+
+
+ {{ log.requested_model }}
+ →
+ {{ log.upstream_model }}
+
+
+
+
+
+ {{ displayModel(log) }}
+
+ -
+
|
@@ -193,6 +204,28 @@ function isUpstreamRow(log: OpsErrorLog): boolean {
return phase === 'upstream' && owner === 'provider'
}
+function hasModelMapping(log: OpsErrorLog): boolean {
+ const requested = String(log.requested_model || '').trim()
+ const upstream = String(log.upstream_model || '').trim()
+ return !!requested && !!upstream && requested !== upstream
+}
+
+function modelMappingTooltip(log: OpsErrorLog): string {
+ const requested = String(log.requested_model || '').trim()
+ const upstream = String(log.upstream_model || '').trim()
+ if (!requested && !upstream) return ''
+ if (requested && upstream) return `${requested} → ${upstream}`
+ return upstream || requested
+}
+
+function displayModel(log: OpsErrorLog): string {
+ const upstream = String(log.upstream_model || '').trim()
+ if (upstream) return upstream
+ const requested = String(log.requested_model || '').trim()
+ if (requested) return requested
+ return String(log.model || '').trim()
+}
+
function getTypeBadge(log: OpsErrorLog): { label: string; className: string } {
const phase = String(log.phase || '').toLowerCase()
const owner = String(log.error_owner || '').toLowerCase()
@@ -263,4 +296,4 @@ function formatSmartMessage(msg: string): string {
return msg.length > 200 ? msg.substring(0, 200) + '...' : msg
}
-
\ No newline at end of file
+