Fix UI types to match actual backend API
Validated against live OpenAPI spec at /api/v1/api-docs. Fixes: - duration → durationMs (all models) - Remove processorCount (not in ExecutionSummary) - Remove ProcessorNode.index and .uri (not in backend) - ProcessorSnapshot is Record<string,string>, not structured object - Add missing fields: endTime, diagramContentHash, exchangeId, etc. - Save openapi.json from live server Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1071
ui/src/api/openapi.json
Normal file
1071
ui/src/api/openapi.json
Normal file
File diff suppressed because it is too large
Load Diff
41
ui/src/api/schema.d.ts
vendored
41
ui/src/api/schema.d.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Hand-written OpenAPI types matching the cameleer3 server REST API.
|
* Types matching the cameleer3 server REST API (validated against live OpenAPI spec).
|
||||||
* Will be replaced by openapi-typescript codegen once backend is running.
|
* Generated from: GET /api/v1/api-docs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface paths {
|
export interface paths {
|
||||||
@@ -88,7 +88,7 @@ export interface paths {
|
|||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
'application/json': ExchangeSnapshot;
|
'application/json': ProcessorSnapshot;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
404: { content: { 'application/json': { message: string } } };
|
404: { content: { 'application/json': { message: string } } };
|
||||||
@@ -137,45 +137,46 @@ export interface ExecutionSummary {
|
|||||||
executionId: string;
|
executionId: string;
|
||||||
routeId: string;
|
routeId: string;
|
||||||
agentId: string;
|
agentId: string;
|
||||||
status: 'COMPLETED' | 'FAILED' | 'RUNNING';
|
status: string;
|
||||||
startTime: string;
|
startTime: string;
|
||||||
duration: number;
|
endTime: string | null;
|
||||||
processorCount: number;
|
durationMs: number;
|
||||||
correlationId: string | null;
|
correlationId: string | null;
|
||||||
errorMessage: string | null;
|
errorMessage: string | null;
|
||||||
|
diagramContentHash: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExecutionDetail {
|
export interface ExecutionDetail {
|
||||||
executionId: string;
|
executionId: string;
|
||||||
routeId: string;
|
routeId: string;
|
||||||
agentId: string;
|
agentId: string;
|
||||||
status: 'COMPLETED' | 'FAILED' | 'RUNNING';
|
status: string;
|
||||||
startTime: string;
|
startTime: string;
|
||||||
duration: number;
|
endTime: string | null;
|
||||||
|
durationMs: number;
|
||||||
correlationId: string | null;
|
correlationId: string | null;
|
||||||
|
exchangeId: string | null;
|
||||||
errorMessage: string | null;
|
errorMessage: string | null;
|
||||||
|
errorStackTrace: string | null;
|
||||||
|
diagramContentHash: string | null;
|
||||||
processors: ProcessorNode[];
|
processors: ProcessorNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProcessorNode {
|
export interface ProcessorNode {
|
||||||
index: number;
|
|
||||||
processorId: string;
|
processorId: string;
|
||||||
processorType: string;
|
processorType: string;
|
||||||
uri: string | null;
|
status: string;
|
||||||
status: 'COMPLETED' | 'FAILED' | 'RUNNING';
|
startTime: string;
|
||||||
duration: number;
|
endTime: string | null;
|
||||||
|
durationMs: number;
|
||||||
|
diagramNodeId: string | null;
|
||||||
errorMessage: string | null;
|
errorMessage: string | null;
|
||||||
|
errorStackTrace: string | null;
|
||||||
children: ProcessorNode[];
|
children: ProcessorNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExchangeSnapshot {
|
/** Processor snapshot is a flat key-value map (Map<String, String> in Java) */
|
||||||
exchangeId: string;
|
export type ProcessorSnapshot = Record<string, string>;
|
||||||
correlationId: string | null;
|
|
||||||
bodyType: string | null;
|
|
||||||
body: string | null;
|
|
||||||
headers: Record<string, string> | null;
|
|
||||||
properties: Record<string, string> | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AgentInstance {
|
export interface AgentInstance {
|
||||||
agentId: string;
|
agentId: string;
|
||||||
|
|||||||
@@ -7,14 +7,16 @@ interface ExchangeDetailProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ExchangeDetail({ execution }: ExchangeDetailProps) {
|
export function ExchangeDetail({ execution }: ExchangeDetailProps) {
|
||||||
// Fetch the first processor's snapshot (index 0) for body preview
|
// Fetch the first processor's snapshot (index 0) — returns Record<string, string>
|
||||||
const { data: snapshot } = useProcessorSnapshot(execution.executionId, 0);
|
const { data: snapshot } = useProcessorSnapshot(execution.executionId, 0);
|
||||||
|
|
||||||
|
const body = snapshot?.['body'];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.sidebar}>
|
<div className={styles.sidebar}>
|
||||||
<h4 className={styles.title}>Exchange Details</h4>
|
<h4 className={styles.title}>Exchange Details</h4>
|
||||||
<dl className={styles.kv}>
|
<dl className={styles.kv}>
|
||||||
<dt className={styles.kvKey}>Exchange ID</dt>
|
<dt className={styles.kvKey}>Execution ID</dt>
|
||||||
<dd className={styles.kvValue}>{execution.executionId}</dd>
|
<dd className={styles.kvValue}>{execution.executionId}</dd>
|
||||||
<dt className={styles.kvKey}>Correlation</dt>
|
<dt className={styles.kvKey}>Correlation</dt>
|
||||||
<dd className={styles.kvValue}>{execution.correlationId ?? '-'}</dd>
|
<dd className={styles.kvValue}>{execution.correlationId ?? '-'}</dd>
|
||||||
@@ -25,15 +27,13 @@ export function ExchangeDetail({ execution }: ExchangeDetailProps) {
|
|||||||
<dt className={styles.kvKey}>Timestamp</dt>
|
<dt className={styles.kvKey}>Timestamp</dt>
|
||||||
<dd className={styles.kvValue}>{new Date(execution.startTime).toISOString()}</dd>
|
<dd className={styles.kvValue}>{new Date(execution.startTime).toISOString()}</dd>
|
||||||
<dt className={styles.kvKey}>Duration</dt>
|
<dt className={styles.kvKey}>Duration</dt>
|
||||||
<dd className={styles.kvValue}>{execution.duration}ms</dd>
|
<dd className={styles.kvValue}>{execution.durationMs}ms</dd>
|
||||||
<dt className={styles.kvKey}>Processors</dt>
|
|
||||||
<dd className={styles.kvValue}>{execution.processorCount}</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
{snapshot?.body && (
|
{body && (
|
||||||
<div className={styles.bodyPreview}>
|
<div className={styles.bodyPreview}>
|
||||||
<span className={styles.bodyLabel}>Input Body</span>
|
<span className={styles.bodyLabel}>Input Body</span>
|
||||||
{snapshot.body}
|
{body}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function ExecutionExplorer() {
|
|||||||
// Derive stats from current search results
|
// Derive stats from current search results
|
||||||
const failedCount = results.filter((r) => r.status === 'FAILED').length;
|
const failedCount = results.filter((r) => r.status === 'FAILED').length;
|
||||||
const avgDuration = results.length > 0
|
const avgDuration = results.length > 0
|
||||||
? Math.round(results.reduce((sum, r) => sum + r.duration, 0) / results.length)
|
? Math.round(results.reduce((sum, r) => sum + r.durationMs, 0) / results.length)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const showFrom = total > 0 ? offset + 1 : 0;
|
const showFrom = total > 0 ? offset + 1 : 0;
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ export function ProcessorTree({ executionId }: { executionId: string }) {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.tree}>
|
<div className={styles.tree}>
|
||||||
<h4 className={styles.title}>Processor Execution Tree</h4>
|
<h4 className={styles.title}>Processor Execution Tree</h4>
|
||||||
{data.processors.map((proc) => (
|
{data.processors.map((proc, i) => (
|
||||||
<ProcessorNodeView key={proc.index} node={proc} />
|
<ProcessorNodeView key={proc.processorId ?? i} node={proc} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -52,16 +52,15 @@ function ProcessorNodeView({ node }: { node: ProcessorNodeType }) {
|
|||||||
<div className={`${styles.procIcon} ${icon.className}`}>{icon.label}</div>
|
<div className={`${styles.procIcon} ${icon.className}`}>{icon.label}</div>
|
||||||
<div className={styles.procInfo}>
|
<div className={styles.procInfo}>
|
||||||
<div className={styles.procType}>{node.processorType}</div>
|
<div className={styles.procType}>{node.processorType}</div>
|
||||||
{node.uri && <div className={styles.procUri}>{node.uri}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.procTiming}>
|
<div className={styles.procTiming}>
|
||||||
<span className={styles.procDuration}>{node.duration}ms</span>
|
<span className={styles.procDuration}>{node.durationMs}ms</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{node.children.length > 0 && (
|
{node.children.length > 0 && (
|
||||||
<div className={styles.nested}>
|
<div className={styles.nested}>
|
||||||
{node.children.map((child) => (
|
{node.children.map((child, i) => (
|
||||||
<ProcessorNodeView key={child.index} node={child} />
|
<ProcessorNodeView key={child.processorId ?? i} node={child} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ export function ResultsTable({ results, loading }: ResultsTableProps) {
|
|||||||
<th className={styles.th}>Route</th>
|
<th className={styles.th}>Route</th>
|
||||||
<th className={styles.th}>Correlation ID</th>
|
<th className={styles.th}>Correlation ID</th>
|
||||||
<th className={styles.th}>Duration</th>
|
<th className={styles.th}>Duration</th>
|
||||||
<th className={styles.th}>Processors</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -101,13 +100,12 @@ function ResultRow({
|
|||||||
{exec.correlationId ?? '-'}
|
{exec.correlationId ?? '-'}
|
||||||
</td>
|
</td>
|
||||||
<td className={styles.td}>
|
<td className={styles.td}>
|
||||||
<DurationBar duration={exec.duration} />
|
<DurationBar duration={exec.durationMs} />
|
||||||
</td>
|
</td>
|
||||||
<td className={`${styles.td} mono text-muted`}>{exec.processorCount}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{isExpanded && (
|
{isExpanded && (
|
||||||
<tr className={styles.detailRowVisible}>
|
<tr className={styles.detailRowVisible}>
|
||||||
<td className={styles.detailCell} colSpan={8}>
|
<td className={styles.detailCell} colSpan={7}>
|
||||||
<div className={styles.detailContent}>
|
<div className={styles.detailContent}>
|
||||||
<ProcessorTree executionId={exec.executionId} />
|
<ProcessorTree executionId={exec.executionId} />
|
||||||
<ExchangeDetail execution={exec} />
|
<ExchangeDetail execution={exec} />
|
||||||
|
|||||||
Reference in New Issue
Block a user