@shipfox/client-workflows 16.0.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +20 -0
- package/dist/components/identifier/identifier.js +2 -2
- package/dist/components/identifier/identifier.js.map +1 -1
- package/dist/components/job-detail/agent-config-failure-callout.d.ts.map +1 -1
- package/dist/components/job-detail/agent-config-failure-callout.js +1 -1
- package/dist/components/job-detail/agent-config-failure-callout.js.map +1 -1
- package/dist/components/job-detail/job-context-panel.d.ts +6 -0
- package/dist/components/job-detail/job-context-panel.d.ts.map +1 -0
- package/dist/components/job-detail/job-context-panel.js +224 -0
- package/dist/components/job-detail/job-context-panel.js.map +1 -0
- package/dist/components/job-detail/job-detail-header.d.ts +3 -1
- package/dist/components/job-detail/job-detail-header.d.ts.map +1 -1
- package/dist/components/job-detail/job-detail-header.js +54 -48
- package/dist/components/job-detail/job-detail-header.js.map +1 -1
- package/dist/components/job-detail/job-detail-view.d.ts +1 -1
- package/dist/components/job-detail/job-detail-view.d.ts.map +1 -1
- package/dist/components/job-detail/job-detail-view.js +80 -44
- package/dist/components/job-detail/job-detail-view.js.map +1 -1
- package/dist/components/job-detail/job-empty-states.d.ts.map +1 -1
- package/dist/components/job-detail/job-empty-states.js +19 -10
- package/dist/components/job-detail/job-empty-states.js.map +1 -1
- package/dist/components/job-detail/job-execution-switcher.js +4 -4
- package/dist/components/job-detail/job-execution-switcher.js.map +1 -1
- package/dist/components/job-detail/json-code.d.ts +14 -0
- package/dist/components/job-detail/json-code.d.ts.map +1 -0
- package/dist/components/job-detail/json-code.js +93 -0
- package/dist/components/job-detail/json-code.js.map +1 -0
- package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -1
- package/dist/components/job-detail/step-attempt-log-panel.js +9 -6
- package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -1
- package/dist/components/job-detail/step-troubleshooting.d.ts +18 -0
- package/dist/components/job-detail/step-troubleshooting.d.ts.map +1 -0
- package/dist/components/job-detail/step-troubleshooting.js +493 -0
- package/dist/components/job-detail/step-troubleshooting.js.map +1 -0
- package/dist/components/job-graph/job-graph-content.d.ts.map +1 -1
- package/dist/components/job-graph/job-graph-content.js +5 -4
- package/dist/components/job-graph/job-graph-content.js.map +1 -1
- package/dist/components/job-graph/job-node.js +3 -3
- package/dist/components/job-graph/job-node.js.map +1 -1
- package/dist/components/step-list/index.d.ts +1 -0
- package/dist/components/step-list/index.d.ts.map +1 -1
- package/dist/components/step-list/index.js.map +1 -1
- package/dist/components/step-list/step-list-model.d.ts.map +1 -1
- package/dist/components/step-list/step-list-model.js +5 -0
- package/dist/components/step-list/step-list-model.js.map +1 -1
- package/dist/components/step-list/step-list.d.ts +5 -1
- package/dist/components/step-list/step-list.d.ts.map +1 -1
- package/dist/components/step-list/step-list.js +117 -82
- package/dist/components/step-list/step-list.js.map +1 -1
- package/dist/components/workflow-run-duration-label.js +1 -1
- package/dist/components/workflow-run-duration-label.js.map +1 -1
- package/dist/components/workflow-run-list/job-status-strip.js +6 -6
- package/dist/components/workflow-run-list/job-status-strip.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-filter-menu.js +1 -1
- package/dist/components/workflow-run-list/workflow-run-filter-menu.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-filters.js +4 -4
- package/dist/components/workflow-run-list/workflow-run-filters.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-states.js +6 -6
- package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.js +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.js +7 -7
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +1 -1
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +0 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.js +8 -13
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
- package/dist/components/workflow-run-tabs/index.d.ts +1 -1
- package/dist/components/workflow-run-tabs/index.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/index.js.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-count-chip.js +2 -2
- package/dist/components/workflow-run-tabs/run-annotation-count-chip.js.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-list.d.ts +9 -2
- package/dist/components/workflow-run-tabs/run-annotation-list.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-list.js +28 -19
- package/dist/components/workflow-run-tabs/run-annotation-list.js.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.js +5 -5
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.js.map +1 -1
- package/dist/components/workflow-run-view/run-workspace-nav.js +7 -7
- package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-states.js +6 -6
- package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.js +72 -12
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
- package/dist/core/entities/job-execution.d.ts +7 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -1
- package/dist/core/entities/job-execution.js.map +1 -1
- package/dist/core/entities/job.d.ts +9 -0
- package/dist/core/entities/job.d.ts.map +1 -1
- package/dist/core/entities/job.js.map +1 -1
- package/dist/core/entities/step-attempt.d.ts +29 -0
- package/dist/core/entities/step-attempt.d.ts.map +1 -1
- package/dist/core/entities/step-attempt.js.map +1 -1
- package/dist/core/entities/step.d.ts +3 -1
- package/dist/core/entities/step.d.ts.map +1 -1
- package/dist/core/entities/step.js.map +1 -1
- package/dist/core/run-annotation.d.ts +6 -0
- package/dist/core/run-annotation.d.ts.map +1 -1
- package/dist/core/run-annotation.js.map +1 -1
- package/dist/core/workflow-run.d.ts +1 -1
- package/dist/core/workflow-run.d.ts.map +1 -1
- package/dist/core/workflow-run.js.map +1 -1
- package/dist/hooks/api/annotations.d.ts +63 -0
- package/dist/hooks/api/annotations.d.ts.map +1 -0
- package/dist/hooks/api/annotations.js +145 -0
- package/dist/hooks/api/annotations.js.map +1 -0
- package/dist/hooks/api/step-attempt-detail.d.ts +14 -0
- package/dist/hooks/api/step-attempt-detail.d.ts.map +1 -0
- package/dist/hooks/api/step-attempt-detail.js +43 -0
- package/dist/hooks/api/step-attempt-detail.js.map +1 -0
- package/dist/hooks/api/workflow-run-mapper.d.ts +9 -2
- package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
- package/dist/hooks/api/workflow-run-mapper.js +47 -0
- package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
- package/dist/pages/project-workflows-page.js +19 -19
- package/dist/pages/project-workflows-page.js.map +1 -1
- package/dist/pages/workflow-run-list-page.js +1 -1
- package/dist/pages/workflow-run-list-page.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/components/identifier/identifier.tsx +2 -2
- package/src/components/job-detail/agent-config-failure-callout.tsx +5 -1
- package/src/components/job-detail/job-context-panel.test.tsx +72 -0
- package/src/components/job-detail/job-context-panel.tsx +237 -0
- package/src/components/job-detail/job-detail-header.tsx +52 -46
- package/src/components/job-detail/job-detail-view.stories.tsx +555 -53
- package/src/components/job-detail/job-detail-view.tsx +87 -45
- package/src/components/job-detail/job-empty-states.tsx +23 -10
- package/src/components/job-detail/job-execution-switcher.tsx +5 -5
- package/src/components/job-detail/json-code.tsx +120 -0
- package/src/components/job-detail/step-attempt-log-panel.test.tsx +1 -0
- package/src/components/job-detail/step-attempt-log-panel.tsx +17 -6
- package/src/components/job-detail/step-troubleshooting.stories.tsx +120 -0
- package/src/components/job-detail/step-troubleshooting.test.tsx +337 -0
- package/src/components/job-detail/step-troubleshooting.tsx +537 -0
- package/src/components/job-graph/job-graph-content.tsx +4 -3
- package/src/components/job-graph/job-node.tsx +3 -3
- package/src/components/step-list/index.ts +1 -0
- package/src/components/step-list/step-list-model.ts +5 -0
- package/src/components/step-list/step-list.test.tsx +75 -2
- package/src/components/step-list/step-list.tsx +73 -20
- package/src/components/workflow-run-duration-label.tsx +1 -1
- package/src/components/workflow-run-list/job-status-strip.tsx +6 -6
- package/src/components/workflow-run-list/workflow-run-filter-menu.tsx +1 -1
- package/src/components/workflow-run-list/workflow-run-filters.tsx +4 -4
- package/src/components/workflow-run-list/workflow-run-list-states.tsx +6 -6
- package/src/components/workflow-run-list/workflow-run-list-view.tsx +1 -1
- package/src/components/workflow-run-list/workflow-run-row.tsx +7 -7
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +1 -1
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +1 -1
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +11 -11
- package/src/components/workflow-run-tabs/index.ts +5 -1
- package/src/components/workflow-run-tabs/run-annotation-count-chip.tsx +2 -2
- package/src/components/workflow-run-tabs/run-annotation-list.tsx +25 -10
- package/src/components/workflow-run-tabs/run-annotation-summary-line.tsx +5 -5
- package/src/components/workflow-run-view/run-workspace-nav.tsx +7 -7
- package/src/components/workflow-run-view/workflow-run-states.tsx +6 -6
- package/src/components/workflow-run-view/workflow-run-view.tsx +114 -14
- package/src/core/entities/job-execution.ts +7 -0
- package/src/core/entities/job.ts +9 -0
- package/src/core/entities/step-attempt.ts +33 -0
- package/src/core/entities/step.ts +3 -1
- package/src/core/run-annotation.ts +6 -0
- package/src/core/workflow-run.ts +4 -0
- package/src/hooks/api/annotations.test.ts +84 -0
- package/src/hooks/api/annotations.ts +240 -0
- package/src/hooks/api/step-attempt-detail.ts +67 -0
- package/src/hooks/api/workflow-run-mapper.ts +46 -0
- package/src/hooks/api/workflow-runs.test.tsx +61 -1
- package/src/pages/project-workflows-page.tsx +19 -19
- package/src/pages/workflow-job-detail-page.test.tsx +52 -1
- package/src/pages/workflow-run-list-page.tsx +1 -1
- package/test/fixtures/workflow-run.ts +7 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '@shipfox/react-ui/button';
|
|
3
|
+
import { Callout, CalloutContent, CalloutDescription, CalloutTitle } from '@shipfox/react-ui/callout';
|
|
4
|
+
import { Sheet, SheetBody, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@shipfox/react-ui/sheet';
|
|
5
|
+
import { Skeleton } from '@shipfox/react-ui/skeleton';
|
|
6
|
+
import { Code, Text } from '@shipfox/react-ui/typography';
|
|
7
|
+
import { cn } from '@shipfox/react-ui/utils';
|
|
8
|
+
import { Link } from '@tanstack/react-router';
|
|
9
|
+
import { useStepAttemptDetailQuery } from '#hooks/api/step-attempt-detail.js';
|
|
10
|
+
import { workflowRunSearchParams } from '#routes/inputs.js';
|
|
11
|
+
import { humanizeStatus } from '../step-list/step-list-model.js';
|
|
12
|
+
import { AgentConfigFailureCallout } from './agent-config-failure-callout.js';
|
|
13
|
+
import { toSelectedAttemptError } from './job-empty-states.js';
|
|
14
|
+
import { JsonCode, JsonCodeTabs } from './json-code.js';
|
|
15
|
+
export function StepInspectorSheet({ entry, open, onOpenChange, workspaceSlug, projectSlug, workflowRunId, runAttempt, jobId, annotationCount }) {
|
|
16
|
+
const error = selectedStepError(entry.step, entry.error);
|
|
17
|
+
const inspectorQuery = useStepAttemptDetailQuery(entry.step.id, entry.attempt, {
|
|
18
|
+
enabled: open
|
|
19
|
+
});
|
|
20
|
+
return /*#__PURE__*/ _jsx(Sheet, {
|
|
21
|
+
open: open,
|
|
22
|
+
onOpenChange: onOpenChange,
|
|
23
|
+
children: /*#__PURE__*/ _jsxs(SheetContent, {
|
|
24
|
+
side: "right",
|
|
25
|
+
className: "w-full sm:max-w-[560px]",
|
|
26
|
+
children: [
|
|
27
|
+
/*#__PURE__*/ _jsxs(SheetHeader, {
|
|
28
|
+
children: [
|
|
29
|
+
/*#__PURE__*/ _jsx(SheetTitle, {
|
|
30
|
+
children: entry.step.label
|
|
31
|
+
}),
|
|
32
|
+
/*#__PURE__*/ _jsxs(SheetDescription, {
|
|
33
|
+
children: [
|
|
34
|
+
"Attempt #",
|
|
35
|
+
entry.attempt,
|
|
36
|
+
" · ",
|
|
37
|
+
humanizeStatus(entry.statusVisual.kind)
|
|
38
|
+
]
|
|
39
|
+
})
|
|
40
|
+
]
|
|
41
|
+
}),
|
|
42
|
+
/*#__PURE__*/ _jsx(SheetBody, {
|
|
43
|
+
className: "gap-section",
|
|
44
|
+
children: /*#__PURE__*/ _jsx(StepInspector, {
|
|
45
|
+
step: entry.step,
|
|
46
|
+
attempt: entry,
|
|
47
|
+
error: error,
|
|
48
|
+
showFailure: entry.statusVisual.kind === 'failed' || entry.error !== null,
|
|
49
|
+
query: inspectorQuery,
|
|
50
|
+
workspaceSlug: workspaceSlug,
|
|
51
|
+
projectSlug: projectSlug,
|
|
52
|
+
workflowRunId: workflowRunId,
|
|
53
|
+
runAttempt: runAttempt,
|
|
54
|
+
jobId: jobId,
|
|
55
|
+
annotationCount: annotationCount
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
]
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function StepFailureCallout({ step, attempt, error, workspaceSlug, projectSlug, workflowRunId, runAttempt }) {
|
|
63
|
+
const reason = error?.reason ?? step.statusReason ?? 'unknown';
|
|
64
|
+
const title = failureTitle(reason);
|
|
65
|
+
const sourceLink = sourceLinkForFailure(reason) && step.sourceLocation;
|
|
66
|
+
if (step.type === 'agent' && reason === 'agent_config_invalid') {
|
|
67
|
+
return /*#__PURE__*/ _jsx(AgentConfigFailureCallout, {
|
|
68
|
+
workspaceSlug: workspaceSlug,
|
|
69
|
+
config: step.agentConfig,
|
|
70
|
+
error: error
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return /*#__PURE__*/ _jsx(Callout, {
|
|
74
|
+
role: "alert",
|
|
75
|
+
type: "error",
|
|
76
|
+
variant: "secondary",
|
|
77
|
+
className: "rounded-8 border border-tag-error-border p-panel-compact shadow-none",
|
|
78
|
+
children: /*#__PURE__*/ _jsxs(CalloutContent, {
|
|
79
|
+
children: [
|
|
80
|
+
/*#__PURE__*/ _jsx(CalloutTitle, {
|
|
81
|
+
children: title
|
|
82
|
+
}),
|
|
83
|
+
/*#__PURE__*/ _jsx(CalloutDescription, {
|
|
84
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
85
|
+
className: "flex min-w-0 flex-wrap items-center gap-x-inline gap-y-tight",
|
|
86
|
+
children: [
|
|
87
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
88
|
+
className: "flex min-w-0 flex-col gap-tight",
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ _jsx("span", {
|
|
91
|
+
children: failureDescription(reason)
|
|
92
|
+
}),
|
|
93
|
+
error?.message ? /*#__PURE__*/ _jsx("span", {
|
|
94
|
+
className: "text-foreground-neutral-muted",
|
|
95
|
+
children: error.message
|
|
96
|
+
}) : null
|
|
97
|
+
]
|
|
98
|
+
}),
|
|
99
|
+
/*#__PURE__*/ _jsx(Code, {
|
|
100
|
+
as: "span",
|
|
101
|
+
variant: "label",
|
|
102
|
+
className: "text-tag-error-text",
|
|
103
|
+
children: reason
|
|
104
|
+
}),
|
|
105
|
+
sourceLink ? /*#__PURE__*/ _jsx(Link, {
|
|
106
|
+
to: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId",
|
|
107
|
+
params: {
|
|
108
|
+
workspaceSlug,
|
|
109
|
+
projectSlug,
|
|
110
|
+
workflowRunId
|
|
111
|
+
},
|
|
112
|
+
search: workflowRunSearchParams({
|
|
113
|
+
tab: 'source'
|
|
114
|
+
}, {
|
|
115
|
+
stepId: step.id,
|
|
116
|
+
stepAttemptId: attempt.id,
|
|
117
|
+
runAttempt
|
|
118
|
+
}),
|
|
119
|
+
className: "font-medium text-foreground-highlight-interactive underline-offset-2 hover:underline",
|
|
120
|
+
children: "View in source"
|
|
121
|
+
}) : null
|
|
122
|
+
]
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
]
|
|
126
|
+
})
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function StepInspector({ step, attempt, error, showFailure, query, workspaceSlug, projectSlug, workflowRunId, runAttempt, jobId, annotationCount }) {
|
|
130
|
+
const detail = query.data;
|
|
131
|
+
const trace = detail?.evaluationTrace ?? null;
|
|
132
|
+
const resolvedConfig = detail?.config ?? null;
|
|
133
|
+
const hasInputs = detail !== undefined && (countConfigValues(detail.authoredConfig) > 0 || countConfigValues(resolvedConfig) > 0);
|
|
134
|
+
const hasOutputs = attempt.outputs !== null || attempt.output !== null || attempt.response !== null;
|
|
135
|
+
const hasTrace = trace !== null && trace.length > 0;
|
|
136
|
+
const hasAnnotations = annotationCount !== undefined && annotationCount > 0;
|
|
137
|
+
const detailCount = Number(hasInputs) + Number(hasOutputs) + Number(hasTrace);
|
|
138
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
139
|
+
className: "flex min-w-0 flex-col gap-section",
|
|
140
|
+
children: [
|
|
141
|
+
showFailure ? /*#__PURE__*/ _jsx(StepFailureCallout, {
|
|
142
|
+
step: step,
|
|
143
|
+
attempt: attempt,
|
|
144
|
+
error: error,
|
|
145
|
+
workspaceSlug: workspaceSlug,
|
|
146
|
+
projectSlug: projectSlug,
|
|
147
|
+
workflowRunId: workflowRunId,
|
|
148
|
+
runAttempt: runAttempt
|
|
149
|
+
}) : null,
|
|
150
|
+
query.isPending ? /*#__PURE__*/ _jsx(InspectorLoading, {}) : null,
|
|
151
|
+
query.isError ? /*#__PURE__*/ _jsx(Callout, {
|
|
152
|
+
role: "alert",
|
|
153
|
+
type: "warning",
|
|
154
|
+
variant: "secondary",
|
|
155
|
+
className: "rounded-8 border border-tag-warning-border p-panel-compact shadow-none",
|
|
156
|
+
children: /*#__PURE__*/ _jsxs(CalloutContent, {
|
|
157
|
+
children: [
|
|
158
|
+
/*#__PURE__*/ _jsx(CalloutTitle, {
|
|
159
|
+
children: "Details unavailable"
|
|
160
|
+
}),
|
|
161
|
+
/*#__PURE__*/ _jsxs(CalloutDescription, {
|
|
162
|
+
className: "flex items-center justify-between gap-inline",
|
|
163
|
+
children: [
|
|
164
|
+
/*#__PURE__*/ _jsx("span", {
|
|
165
|
+
children: "We could not load the resolved configuration for this attempt."
|
|
166
|
+
}),
|
|
167
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
168
|
+
type: "button",
|
|
169
|
+
size: "2xs",
|
|
170
|
+
variant: "secondary",
|
|
171
|
+
onClick: ()=>void query.refetch(),
|
|
172
|
+
children: "Retry"
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
})
|
|
176
|
+
]
|
|
177
|
+
})
|
|
178
|
+
}) : null,
|
|
179
|
+
detail ? /*#__PURE__*/ _jsxs("div", {
|
|
180
|
+
className: "flex min-w-0 flex-col gap-group",
|
|
181
|
+
children: [
|
|
182
|
+
hasInputs ? /*#__PURE__*/ _jsx(InspectorSection, {
|
|
183
|
+
title: "Inputs",
|
|
184
|
+
children: /*#__PURE__*/ _jsx(ConfigCode, {
|
|
185
|
+
authoredConfig: detail.authoredConfig,
|
|
186
|
+
resolvedConfig: resolvedConfig
|
|
187
|
+
})
|
|
188
|
+
}) : null,
|
|
189
|
+
hasOutputs ? /*#__PURE__*/ _jsxs(InspectorSection, {
|
|
190
|
+
title: "Outputs",
|
|
191
|
+
children: [
|
|
192
|
+
attempt.outputs !== null || attempt.output !== null ? /*#__PURE__*/ _jsx(JsonCode, {
|
|
193
|
+
value: attempt.outputs ?? attempt.output ?? {},
|
|
194
|
+
emptyMessage: "No outputs declared; the `outputs:` mapping is empty."
|
|
195
|
+
}) : null,
|
|
196
|
+
attempt.response !== null ? /*#__PURE__*/ _jsxs("div", {
|
|
197
|
+
className: "flex min-w-0 flex-col gap-tight",
|
|
198
|
+
children: [
|
|
199
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
200
|
+
size: "xs",
|
|
201
|
+
className: "text-foreground-neutral-muted",
|
|
202
|
+
children: "Response"
|
|
203
|
+
}),
|
|
204
|
+
/*#__PURE__*/ _jsx("pre", {
|
|
205
|
+
className: "max-h-160 min-w-0 overflow-auto rounded-6 border border-border-neutral-base bg-background-neutral-subtle p-tight font-code text-xs leading-18 text-foreground-neutral-muted scrollbar",
|
|
206
|
+
children: attempt.response
|
|
207
|
+
})
|
|
208
|
+
]
|
|
209
|
+
}) : null
|
|
210
|
+
]
|
|
211
|
+
}) : null,
|
|
212
|
+
hasTrace ? /*#__PURE__*/ _jsx(InspectorSection, {
|
|
213
|
+
title: "Evaluation",
|
|
214
|
+
children: /*#__PURE__*/ _jsx(EvaluationTrace, {
|
|
215
|
+
trace: trace ?? []
|
|
216
|
+
})
|
|
217
|
+
}) : null,
|
|
218
|
+
detailCount === 0 && !showFailure && !hasAnnotations ? /*#__PURE__*/ _jsx(EmptyInspector, {}) : null
|
|
219
|
+
]
|
|
220
|
+
}) : null,
|
|
221
|
+
hasAnnotations ? /*#__PURE__*/ _jsxs(Link, {
|
|
222
|
+
to: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId",
|
|
223
|
+
params: {
|
|
224
|
+
workspaceSlug,
|
|
225
|
+
projectSlug,
|
|
226
|
+
workflowRunId
|
|
227
|
+
},
|
|
228
|
+
search: workflowRunSearchParams({
|
|
229
|
+
tab: 'annotations'
|
|
230
|
+
}, {
|
|
231
|
+
jobId,
|
|
232
|
+
runAttempt
|
|
233
|
+
}),
|
|
234
|
+
className: "inline-flex w-fit rounded-4 text-xs text-foreground-highlight-interactive underline-offset-2 hover:underline focus-visible:shadow-button-neutral-focus",
|
|
235
|
+
children: [
|
|
236
|
+
"View ",
|
|
237
|
+
annotationCount,
|
|
238
|
+
" annotation",
|
|
239
|
+
annotationCount === 1 ? '' : 's'
|
|
240
|
+
]
|
|
241
|
+
}) : null,
|
|
242
|
+
!query.isPending && !query.isError && !detail && !showFailure && !hasAnnotations ? /*#__PURE__*/ _jsx(EmptyInspector, {}) : null
|
|
243
|
+
]
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function InspectorSection({ title, children }) {
|
|
247
|
+
return /*#__PURE__*/ _jsxs("section", {
|
|
248
|
+
className: "flex min-w-0 flex-col gap-inline",
|
|
249
|
+
"aria-label": title,
|
|
250
|
+
children: [
|
|
251
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
252
|
+
size: "xs",
|
|
253
|
+
bold: true,
|
|
254
|
+
className: "text-foreground-neutral-base",
|
|
255
|
+
children: title
|
|
256
|
+
}),
|
|
257
|
+
children
|
|
258
|
+
]
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function ConfigCode({ authoredConfig, resolvedConfig }) {
|
|
262
|
+
const entries = [
|
|
263
|
+
...authoredConfig ? [
|
|
264
|
+
{
|
|
265
|
+
filename: 'authored.json',
|
|
266
|
+
label: 'Authored configuration',
|
|
267
|
+
value: authoredConfig
|
|
268
|
+
}
|
|
269
|
+
] : [],
|
|
270
|
+
...resolvedConfig ? [
|
|
271
|
+
{
|
|
272
|
+
filename: 'resolved.json',
|
|
273
|
+
label: 'Resolved configuration',
|
|
274
|
+
value: resolvedConfig
|
|
275
|
+
}
|
|
276
|
+
] : []
|
|
277
|
+
];
|
|
278
|
+
if (entries.length === 0) return null;
|
|
279
|
+
return /*#__PURE__*/ _jsx(JsonCodeTabs, {
|
|
280
|
+
entries: entries
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
export function EvaluationTrace({ trace }) {
|
|
284
|
+
const keyCounts = new Map();
|
|
285
|
+
return /*#__PURE__*/ _jsx("dl", {
|
|
286
|
+
className: "flex min-w-0 flex-col divide-y divide-border-neutral-base rounded-6 border border-border-neutral-base",
|
|
287
|
+
children: trace.map((entry)=>{
|
|
288
|
+
if ('dropped' in entry) {
|
|
289
|
+
const keyBase = `limit-${entry.dropped}`;
|
|
290
|
+
const occurrence = keyCounts.get(keyBase) ?? 0;
|
|
291
|
+
keyCounts.set(keyBase, occurrence + 1);
|
|
292
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
293
|
+
className: "px-row py-row text-xs text-foreground-neutral-muted",
|
|
294
|
+
children: [
|
|
295
|
+
entry.dropped,
|
|
296
|
+
" more evaluation",
|
|
297
|
+
entry.dropped === 1 ? '' : 's',
|
|
298
|
+
" not recorded"
|
|
299
|
+
]
|
|
300
|
+
}, `${keyBase}-${occurrence}`);
|
|
301
|
+
}
|
|
302
|
+
const empty = entry.value === undefined || entry.value === '';
|
|
303
|
+
const keyBase = `evaluation-${entry.field}-${entry.expression}-${entry.evaluatedAt}-${entry.fillTarget}`;
|
|
304
|
+
const occurrence = keyCounts.get(keyBase) ?? 0;
|
|
305
|
+
keyCounts.set(keyBase, occurrence + 1);
|
|
306
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
307
|
+
className: cn('grid min-w-0 grid-cols-1 gap-inline px-row py-row min-[768px]:grid-cols-[160px_minmax(0,1fr)]', entry.degraded && 'border-l border-tag-error-icon'),
|
|
308
|
+
children: [
|
|
309
|
+
/*#__PURE__*/ _jsxs("dt", {
|
|
310
|
+
className: "flex min-w-0 flex-col gap-tight font-code text-xs text-foreground-neutral-muted",
|
|
311
|
+
title: entry.field,
|
|
312
|
+
children: [
|
|
313
|
+
/*#__PURE__*/ _jsx("span", {
|
|
314
|
+
className: "block truncate",
|
|
315
|
+
children: entry.field
|
|
316
|
+
}),
|
|
317
|
+
/*#__PURE__*/ _jsx("span", {
|
|
318
|
+
className: "block break-all text-foreground-neutral-subtle",
|
|
319
|
+
children: entry.expression
|
|
320
|
+
})
|
|
321
|
+
]
|
|
322
|
+
}),
|
|
323
|
+
/*#__PURE__*/ _jsxs("dd", {
|
|
324
|
+
className: "flex min-w-0 flex-col gap-tight text-xs text-foreground-neutral-base",
|
|
325
|
+
children: [
|
|
326
|
+
entry.degraded ? /*#__PURE__*/ _jsx("span", {
|
|
327
|
+
className: "sr-only",
|
|
328
|
+
children: "Degraded evaluation"
|
|
329
|
+
}) : null,
|
|
330
|
+
/*#__PURE__*/ _jsx("div", {
|
|
331
|
+
className: "break-words font-code",
|
|
332
|
+
children: empty ? /*#__PURE__*/ _jsx("span", {
|
|
333
|
+
className: "text-tag-error-text",
|
|
334
|
+
children: "(empty)"
|
|
335
|
+
}) : entry.value
|
|
336
|
+
}),
|
|
337
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
338
|
+
className: "flex min-w-0 flex-wrap gap-x-inline gap-y-tight text-foreground-neutral-muted",
|
|
339
|
+
children: [
|
|
340
|
+
entry.degraded ? /*#__PURE__*/ _jsx("span", {
|
|
341
|
+
className: "text-tag-error-text",
|
|
342
|
+
children: "degraded"
|
|
343
|
+
}) : null,
|
|
344
|
+
entry.truncated || entry.exprTruncated ? /*#__PURE__*/ _jsx("span", {
|
|
345
|
+
children: "truncated"
|
|
346
|
+
}) : null
|
|
347
|
+
]
|
|
348
|
+
})
|
|
349
|
+
]
|
|
350
|
+
})
|
|
351
|
+
]
|
|
352
|
+
}, `${keyBase}-${occurrence}`);
|
|
353
|
+
})
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
function InspectorLoading() {
|
|
357
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
358
|
+
role: "status",
|
|
359
|
+
"aria-label": "Loading troubleshooting details",
|
|
360
|
+
className: "flex flex-col gap-inline",
|
|
361
|
+
children: [
|
|
362
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
363
|
+
className: "h-16 w-120"
|
|
364
|
+
}),
|
|
365
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
366
|
+
className: "h-120 w-full"
|
|
367
|
+
})
|
|
368
|
+
]
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function EmptyInspector() {
|
|
372
|
+
return /*#__PURE__*/ _jsx(Text, {
|
|
373
|
+
size: "xs",
|
|
374
|
+
className: "text-foreground-neutral-muted",
|
|
375
|
+
children: "No additional troubleshooting details were recorded."
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
function selectedStepError(step, attemptError) {
|
|
379
|
+
return toSelectedAttemptError(step, attemptError) ?? step.error;
|
|
380
|
+
}
|
|
381
|
+
function failureTitle(reason) {
|
|
382
|
+
switch(reason){
|
|
383
|
+
case 'checkout_failed':
|
|
384
|
+
return 'Checkout failed';
|
|
385
|
+
case 'checkout_auth_failed':
|
|
386
|
+
return 'Checkout authentication failed';
|
|
387
|
+
case 'checkout_unavailable':
|
|
388
|
+
return 'Checkout service unavailable';
|
|
389
|
+
case 'checkout_path_invalid':
|
|
390
|
+
return 'Checkout path is invalid';
|
|
391
|
+
case 'checkout_destination_occupied':
|
|
392
|
+
return 'Checkout destination is already occupied';
|
|
393
|
+
case 'git_unavailable':
|
|
394
|
+
return 'Git was unavailable';
|
|
395
|
+
case 'workspace_prep_failed':
|
|
396
|
+
return 'Workspace preparation failed';
|
|
397
|
+
case 'setup_aborted':
|
|
398
|
+
return 'Step setup was aborted';
|
|
399
|
+
case 'config_unresolvable':
|
|
400
|
+
return 'Step configuration could not be resolved';
|
|
401
|
+
case 'output_invalid':
|
|
402
|
+
return 'Step output was invalid';
|
|
403
|
+
case 'agent_config_invalid':
|
|
404
|
+
return 'Agent configuration is invalid';
|
|
405
|
+
case 'agent_invocation_failed':
|
|
406
|
+
return 'Agent invocation failed';
|
|
407
|
+
case 'agent_harness_unavailable':
|
|
408
|
+
return 'Agent harness was unavailable';
|
|
409
|
+
case 'runner_lost':
|
|
410
|
+
return 'Runner stopped responding';
|
|
411
|
+
case 'timed_out':
|
|
412
|
+
return 'Step timed out';
|
|
413
|
+
case 'step_failed':
|
|
414
|
+
return 'A step failed';
|
|
415
|
+
case 'dependency_not_completed':
|
|
416
|
+
return 'A dependency did not complete';
|
|
417
|
+
case 'condition_false':
|
|
418
|
+
return 'The job condition was false';
|
|
419
|
+
case 'default_gate_rejected':
|
|
420
|
+
return 'The default gate rejected this job';
|
|
421
|
+
case 'condition_rejected':
|
|
422
|
+
return 'The job condition rejected this job';
|
|
423
|
+
case 'condition_errored':
|
|
424
|
+
return 'The job condition could not be evaluated';
|
|
425
|
+
case 'user_cancelled':
|
|
426
|
+
return 'The job was cancelled by a user';
|
|
427
|
+
case 'run_cancelled':
|
|
428
|
+
return 'The run was cancelled';
|
|
429
|
+
case 'unknown':
|
|
430
|
+
return 'The failure reason was not recorded';
|
|
431
|
+
default:
|
|
432
|
+
return 'Step failed';
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function failureDescription(reason) {
|
|
436
|
+
switch(reason){
|
|
437
|
+
case 'checkout_auth_failed':
|
|
438
|
+
return 'Checkout credentials were rejected. Verify repository access before re-running.';
|
|
439
|
+
case 'checkout_unavailable':
|
|
440
|
+
return 'The checkout service was unavailable. Retry after the service recovers.';
|
|
441
|
+
case 'git_unavailable':
|
|
442
|
+
return 'The runner could not start Git. Check the runner image before re-running.';
|
|
443
|
+
case 'workspace_prep_failed':
|
|
444
|
+
return 'The runner could not prepare its workspace. Review the runner setup details.';
|
|
445
|
+
case 'config_unresolvable':
|
|
446
|
+
return 'The resolved configuration contains a value that could not be evaluated.';
|
|
447
|
+
case 'output_invalid':
|
|
448
|
+
return 'The step returned output that did not match the declared contract.';
|
|
449
|
+
case 'agent_config_invalid':
|
|
450
|
+
return 'The agent configuration is not valid for this step.';
|
|
451
|
+
case 'agent_invocation_failed':
|
|
452
|
+
return 'The agent invocation failed after configuration was accepted.';
|
|
453
|
+
case 'agent_harness_unavailable':
|
|
454
|
+
return 'The runner could not start the agent harness.';
|
|
455
|
+
case 'runner_lost':
|
|
456
|
+
return 'The runner stopped responding before the step completed.';
|
|
457
|
+
case 'timed_out':
|
|
458
|
+
return 'The step exceeded its configured time limit.';
|
|
459
|
+
case 'dependency_not_completed':
|
|
460
|
+
return 'A required job did not complete, so this job could not start.';
|
|
461
|
+
case 'condition_false':
|
|
462
|
+
case 'condition_rejected':
|
|
463
|
+
return 'The job condition did not allow this job to run.';
|
|
464
|
+
case 'condition_errored':
|
|
465
|
+
return 'The job condition could not be evaluated.';
|
|
466
|
+
case 'default_gate_rejected':
|
|
467
|
+
return 'A required job did not succeed, so this job was not allowed to run.';
|
|
468
|
+
case 'step_failed':
|
|
469
|
+
return 'A step failed before this job could complete.';
|
|
470
|
+
case 'user_cancelled':
|
|
471
|
+
case 'run_cancelled':
|
|
472
|
+
return 'The run was cancelled before this work completed.';
|
|
473
|
+
case 'unknown':
|
|
474
|
+
return 'No machine-readable failure reason was recorded.';
|
|
475
|
+
default:
|
|
476
|
+
return `${humanize(reason)}. Review the details below and re-run after resolving the cause.`;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function sourceLinkForFailure(reason) {
|
|
480
|
+
return reason === 'config_unresolvable' || reason === 'agent_config_invalid' || reason === 'output_invalid' || reason === 'default_gate_rejected' || reason === 'condition_rejected' || reason === 'condition_errored';
|
|
481
|
+
}
|
|
482
|
+
function humanize(value) {
|
|
483
|
+
return value.replaceAll('_', ' ').replace(/\b\w/g, (letter)=>letter.toUpperCase());
|
|
484
|
+
}
|
|
485
|
+
function countConfigValues(value) {
|
|
486
|
+
if (Array.isArray(value)) return value.reduce((total, item)=>total + countConfigValues(item), 0);
|
|
487
|
+
if (value !== null && typeof value === 'object') {
|
|
488
|
+
return Object.values(value).reduce((total, item)=>total + countConfigValues(item), 0);
|
|
489
|
+
}
|
|
490
|
+
return value === undefined ? 0 : 1;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
//# sourceMappingURL=step-troubleshooting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/job-detail/step-troubleshooting.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {Callout, CalloutContent, CalloutDescription, CalloutTitle} from '@shipfox/react-ui/callout';\nimport {\n Sheet,\n SheetBody,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from '@shipfox/react-ui/sheet';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport type {ReactNode} from 'react';\nimport type {\n EvaluationTraceEntry,\n JobStatusReason,\n Step,\n StepAttempt,\n StepError,\n} from '#core/workflow-run.js';\nimport {useStepAttemptDetailQuery} from '#hooks/api/step-attempt-detail.js';\nimport {workflowRunSearchParams} from '#routes/inputs.js';\nimport {humanizeStatus, type StepListEntryModel} from '../step-list/step-list-model.js';\nimport {AgentConfigFailureCallout} from './agent-config-failure-callout.js';\nimport {toSelectedAttemptError} from './job-empty-states.js';\nimport {JsonCode, type JsonCodeEntry, JsonCodeTabs} from './json-code.js';\n\nexport interface StepInspectorSheetProps {\n entry: StepListEntryModel;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n workspaceSlug: string;\n projectSlug: string;\n workflowRunId: string;\n runAttempt: number;\n jobId: string;\n annotationCount?: number | undefined;\n}\n\nexport function StepInspectorSheet({\n entry,\n open,\n onOpenChange,\n workspaceSlug,\n projectSlug,\n workflowRunId,\n runAttempt,\n jobId,\n annotationCount,\n}: StepInspectorSheetProps) {\n const error = selectedStepError(entry.step, entry.error);\n const inspectorQuery = useStepAttemptDetailQuery(entry.step.id, entry.attempt, {\n enabled: open,\n });\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent side=\"right\" className=\"w-full sm:max-w-[560px]\">\n <SheetHeader>\n <SheetTitle>{entry.step.label}</SheetTitle>\n <SheetDescription>\n Attempt #{entry.attempt} · {humanizeStatus(entry.statusVisual.kind)}\n </SheetDescription>\n </SheetHeader>\n <SheetBody className=\"gap-section\">\n <StepInspector\n step={entry.step}\n attempt={entry}\n error={error}\n showFailure={entry.statusVisual.kind === 'failed' || entry.error !== null}\n query={inspectorQuery}\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n workflowRunId={workflowRunId}\n runAttempt={runAttempt}\n jobId={jobId}\n annotationCount={annotationCount}\n />\n </SheetBody>\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction StepFailureCallout({\n step,\n attempt,\n error,\n workspaceSlug,\n projectSlug,\n workflowRunId,\n runAttempt,\n}: {\n step: Step;\n attempt: StepAttempt;\n error: StepError | null;\n workspaceSlug: string;\n projectSlug: string;\n workflowRunId: string;\n runAttempt: number;\n}) {\n const reason = error?.reason ?? step.statusReason ?? 'unknown';\n const title = failureTitle(reason);\n const sourceLink = sourceLinkForFailure(reason) && step.sourceLocation;\n\n if (step.type === 'agent' && reason === 'agent_config_invalid') {\n return (\n <AgentConfigFailureCallout\n workspaceSlug={workspaceSlug}\n config={step.agentConfig}\n error={error}\n />\n );\n }\n\n return (\n <Callout\n role=\"alert\"\n type=\"error\"\n variant=\"secondary\"\n className=\"rounded-8 border border-tag-error-border p-panel-compact shadow-none\"\n >\n <CalloutContent>\n <CalloutTitle>{title}</CalloutTitle>\n <CalloutDescription>\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-inline gap-y-tight\">\n <div className=\"flex min-w-0 flex-col gap-tight\">\n <span>{failureDescription(reason)}</span>\n {error?.message ? (\n <span className=\"text-foreground-neutral-muted\">{error.message}</span>\n ) : null}\n </div>\n <Code as=\"span\" variant=\"label\" className=\"text-tag-error-text\">\n {reason}\n </Code>\n {sourceLink ? (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId}}\n search={\n workflowRunSearchParams(\n {tab: 'source'},\n {stepId: step.id, stepAttemptId: attempt.id, runAttempt},\n ) as never\n }\n className=\"font-medium text-foreground-highlight-interactive underline-offset-2 hover:underline\"\n >\n View in source\n </Link>\n ) : null}\n </div>\n </CalloutDescription>\n </CalloutContent>\n </Callout>\n );\n}\n\nfunction StepInspector({\n step,\n attempt,\n error,\n showFailure,\n query,\n workspaceSlug,\n projectSlug,\n workflowRunId,\n runAttempt,\n jobId,\n annotationCount,\n}: {\n step: Step;\n attempt: StepAttempt;\n error: StepError | null;\n showFailure: boolean;\n query: ReturnType<typeof useStepAttemptDetailQuery>;\n workspaceSlug: string;\n projectSlug: string;\n workflowRunId: string;\n runAttempt: number;\n jobId: string;\n annotationCount: number | undefined;\n}) {\n const detail = query.data;\n const trace = detail?.evaluationTrace ?? null;\n const resolvedConfig = detail?.config ?? null;\n const hasInputs =\n detail !== undefined &&\n (countConfigValues(detail.authoredConfig) > 0 || countConfigValues(resolvedConfig) > 0);\n const hasOutputs =\n attempt.outputs !== null || attempt.output !== null || attempt.response !== null;\n const hasTrace = trace !== null && trace.length > 0;\n const hasAnnotations = annotationCount !== undefined && annotationCount > 0;\n const detailCount = Number(hasInputs) + Number(hasOutputs) + Number(hasTrace);\n\n return (\n <div className=\"flex min-w-0 flex-col gap-section\">\n {showFailure ? (\n <StepFailureCallout\n step={step}\n attempt={attempt}\n error={error}\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n workflowRunId={workflowRunId}\n runAttempt={runAttempt}\n />\n ) : null}\n {query.isPending ? <InspectorLoading /> : null}\n {query.isError ? (\n <Callout\n role=\"alert\"\n type=\"warning\"\n variant=\"secondary\"\n className=\"rounded-8 border border-tag-warning-border p-panel-compact shadow-none\"\n >\n <CalloutContent>\n <CalloutTitle>Details unavailable</CalloutTitle>\n <CalloutDescription className=\"flex items-center justify-between gap-inline\">\n <span>We could not load the resolved configuration for this attempt.</span>\n <Button\n type=\"button\"\n size=\"2xs\"\n variant=\"secondary\"\n onClick={() => void query.refetch()}\n >\n Retry\n </Button>\n </CalloutDescription>\n </CalloutContent>\n </Callout>\n ) : null}\n {detail ? (\n <div className=\"flex min-w-0 flex-col gap-group\">\n {hasInputs ? (\n <InspectorSection title=\"Inputs\">\n <ConfigCode authoredConfig={detail.authoredConfig} resolvedConfig={resolvedConfig} />\n </InspectorSection>\n ) : null}\n {hasOutputs ? (\n <InspectorSection title=\"Outputs\">\n {attempt.outputs !== null || attempt.output !== null ? (\n <JsonCode\n value={attempt.outputs ?? attempt.output ?? {}}\n emptyMessage=\"No outputs declared; the `outputs:` mapping is empty.\"\n />\n ) : null}\n {attempt.response !== null ? (\n <div className=\"flex min-w-0 flex-col gap-tight\">\n <Text size=\"xs\" className=\"text-foreground-neutral-muted\">\n Response\n </Text>\n <pre className=\"max-h-160 min-w-0 overflow-auto rounded-6 border border-border-neutral-base bg-background-neutral-subtle p-tight font-code text-xs leading-18 text-foreground-neutral-muted scrollbar\">\n {attempt.response}\n </pre>\n </div>\n ) : null}\n </InspectorSection>\n ) : null}\n {hasTrace ? (\n <InspectorSection title=\"Evaluation\">\n <EvaluationTrace trace={trace ?? []} />\n </InspectorSection>\n ) : null}\n {detailCount === 0 && !showFailure && !hasAnnotations ? <EmptyInspector /> : null}\n </div>\n ) : null}\n {hasAnnotations ? (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId}}\n search={workflowRunSearchParams({tab: 'annotations'}, {jobId, runAttempt}) as never}\n className=\"inline-flex w-fit rounded-4 text-xs text-foreground-highlight-interactive underline-offset-2 hover:underline focus-visible:shadow-button-neutral-focus\"\n >\n View {annotationCount} annotation{annotationCount === 1 ? '' : 's'}\n </Link>\n ) : null}\n {!query.isPending && !query.isError && !detail && !showFailure && !hasAnnotations ? (\n <EmptyInspector />\n ) : null}\n </div>\n );\n}\n\nfunction InspectorSection({title, children}: {title: string; children: ReactNode}) {\n return (\n <section className=\"flex min-w-0 flex-col gap-inline\" aria-label={title}>\n <Text size=\"xs\" bold className=\"text-foreground-neutral-base\">\n {title}\n </Text>\n {children}\n </section>\n );\n}\n\nfunction ConfigCode({\n authoredConfig,\n resolvedConfig,\n}: {\n authoredConfig: Record<string, unknown> | null;\n resolvedConfig: Record<string, unknown> | null;\n}) {\n const entries: JsonCodeEntry[] = [\n ...(authoredConfig\n ? [\n {\n filename: 'authored.json',\n label: 'Authored configuration',\n value: authoredConfig,\n },\n ]\n : []),\n ...(resolvedConfig\n ? [\n {\n filename: 'resolved.json',\n label: 'Resolved configuration',\n value: resolvedConfig,\n },\n ]\n : []),\n ];\n\n if (entries.length === 0) return null;\n return <JsonCodeTabs entries={entries} />;\n}\n\nexport function EvaluationTrace({trace}: {trace: readonly EvaluationTraceEntry[]}) {\n const keyCounts = new Map<string, number>();\n\n return (\n <dl className=\"flex min-w-0 flex-col divide-y divide-border-neutral-base rounded-6 border border-border-neutral-base\">\n {trace.map((entry) => {\n if ('dropped' in entry) {\n const keyBase = `limit-${entry.dropped}`;\n const occurrence = keyCounts.get(keyBase) ?? 0;\n keyCounts.set(keyBase, occurrence + 1);\n return (\n <div\n key={`${keyBase}-${occurrence}`}\n className=\"px-row py-row text-xs text-foreground-neutral-muted\"\n >\n {entry.dropped} more evaluation{entry.dropped === 1 ? '' : 's'} not recorded\n </div>\n );\n }\n\n const empty = entry.value === undefined || entry.value === '';\n const keyBase = `evaluation-${entry.field}-${entry.expression}-${entry.evaluatedAt}-${entry.fillTarget}`;\n const occurrence = keyCounts.get(keyBase) ?? 0;\n keyCounts.set(keyBase, occurrence + 1);\n return (\n <div\n key={`${keyBase}-${occurrence}`}\n className={cn(\n 'grid min-w-0 grid-cols-1 gap-inline px-row py-row min-[768px]:grid-cols-[160px_minmax(0,1fr)]',\n entry.degraded && 'border-l border-tag-error-icon',\n )}\n >\n <dt\n className=\"flex min-w-0 flex-col gap-tight font-code text-xs text-foreground-neutral-muted\"\n title={entry.field}\n >\n <span className=\"block truncate\">{entry.field}</span>\n <span className=\"block break-all text-foreground-neutral-subtle\">\n {entry.expression}\n </span>\n </dt>\n <dd className=\"flex min-w-0 flex-col gap-tight text-xs text-foreground-neutral-base\">\n {entry.degraded ? <span className=\"sr-only\">Degraded evaluation</span> : null}\n <div className=\"break-words font-code\">\n {empty ? <span className=\"text-tag-error-text\">(empty)</span> : entry.value}\n </div>\n <div className=\"flex min-w-0 flex-wrap gap-x-inline gap-y-tight text-foreground-neutral-muted\">\n {entry.degraded ? <span className=\"text-tag-error-text\">degraded</span> : null}\n {entry.truncated || entry.exprTruncated ? <span>truncated</span> : null}\n </div>\n </dd>\n </div>\n );\n })}\n </dl>\n );\n}\n\nfunction InspectorLoading() {\n return (\n <div\n role=\"status\"\n aria-label=\"Loading troubleshooting details\"\n className=\"flex flex-col gap-inline\"\n >\n <Skeleton className=\"h-16 w-120\" />\n <Skeleton className=\"h-120 w-full\" />\n </div>\n );\n}\n\nfunction EmptyInspector() {\n return (\n <Text size=\"xs\" className=\"text-foreground-neutral-muted\">\n No additional troubleshooting details were recorded.\n </Text>\n );\n}\n\nfunction selectedStepError(\n step: Step,\n attemptError: Record<string, unknown> | null,\n): StepError | null {\n return toSelectedAttemptError(step, attemptError) ?? step.error;\n}\n\nfunction failureTitle(reason: string | JobStatusReason): string {\n switch (reason) {\n case 'checkout_failed':\n return 'Checkout failed';\n case 'checkout_auth_failed':\n return 'Checkout authentication failed';\n case 'checkout_unavailable':\n return 'Checkout service unavailable';\n case 'checkout_path_invalid':\n return 'Checkout path is invalid';\n case 'checkout_destination_occupied':\n return 'Checkout destination is already occupied';\n case 'git_unavailable':\n return 'Git was unavailable';\n case 'workspace_prep_failed':\n return 'Workspace preparation failed';\n case 'setup_aborted':\n return 'Step setup was aborted';\n case 'config_unresolvable':\n return 'Step configuration could not be resolved';\n case 'output_invalid':\n return 'Step output was invalid';\n case 'agent_config_invalid':\n return 'Agent configuration is invalid';\n case 'agent_invocation_failed':\n return 'Agent invocation failed';\n case 'agent_harness_unavailable':\n return 'Agent harness was unavailable';\n case 'runner_lost':\n return 'Runner stopped responding';\n case 'timed_out':\n return 'Step timed out';\n case 'step_failed':\n return 'A step failed';\n case 'dependency_not_completed':\n return 'A dependency did not complete';\n case 'condition_false':\n return 'The job condition was false';\n case 'default_gate_rejected':\n return 'The default gate rejected this job';\n case 'condition_rejected':\n return 'The job condition rejected this job';\n case 'condition_errored':\n return 'The job condition could not be evaluated';\n case 'user_cancelled':\n return 'The job was cancelled by a user';\n case 'run_cancelled':\n return 'The run was cancelled';\n case 'unknown':\n return 'The failure reason was not recorded';\n default:\n return 'Step failed';\n }\n}\n\nfunction failureDescription(reason: string | JobStatusReason): string {\n switch (reason) {\n case 'checkout_auth_failed':\n return 'Checkout credentials were rejected. Verify repository access before re-running.';\n case 'checkout_unavailable':\n return 'The checkout service was unavailable. Retry after the service recovers.';\n case 'git_unavailable':\n return 'The runner could not start Git. Check the runner image before re-running.';\n case 'workspace_prep_failed':\n return 'The runner could not prepare its workspace. Review the runner setup details.';\n case 'config_unresolvable':\n return 'The resolved configuration contains a value that could not be evaluated.';\n case 'output_invalid':\n return 'The step returned output that did not match the declared contract.';\n case 'agent_config_invalid':\n return 'The agent configuration is not valid for this step.';\n case 'agent_invocation_failed':\n return 'The agent invocation failed after configuration was accepted.';\n case 'agent_harness_unavailable':\n return 'The runner could not start the agent harness.';\n case 'runner_lost':\n return 'The runner stopped responding before the step completed.';\n case 'timed_out':\n return 'The step exceeded its configured time limit.';\n case 'dependency_not_completed':\n return 'A required job did not complete, so this job could not start.';\n case 'condition_false':\n case 'condition_rejected':\n return 'The job condition did not allow this job to run.';\n case 'condition_errored':\n return 'The job condition could not be evaluated.';\n case 'default_gate_rejected':\n return 'A required job did not succeed, so this job was not allowed to run.';\n case 'step_failed':\n return 'A step failed before this job could complete.';\n case 'user_cancelled':\n case 'run_cancelled':\n return 'The run was cancelled before this work completed.';\n case 'unknown':\n return 'No machine-readable failure reason was recorded.';\n default:\n return `${humanize(reason)}. Review the details below and re-run after resolving the cause.`;\n }\n}\n\nfunction sourceLinkForFailure(reason: string | JobStatusReason): boolean {\n return (\n reason === 'config_unresolvable' ||\n reason === 'agent_config_invalid' ||\n reason === 'output_invalid' ||\n reason === 'default_gate_rejected' ||\n reason === 'condition_rejected' ||\n reason === 'condition_errored'\n );\n}\n\nfunction humanize(value: string): string {\n return value.replaceAll('_', ' ').replace(/\\b\\w/g, (letter) => letter.toUpperCase());\n}\n\nfunction countConfigValues(value: unknown): number {\n if (Array.isArray(value))\n return value.reduce((total, item) => total + countConfigValues(item), 0);\n if (value !== null && typeof value === 'object') {\n return Object.values(value).reduce((total, item) => total + countConfigValues(item), 0);\n }\n return value === undefined ? 0 : 1;\n}\n"],"names":["Button","Callout","CalloutContent","CalloutDescription","CalloutTitle","Sheet","SheetBody","SheetContent","SheetDescription","SheetHeader","SheetTitle","Skeleton","Code","Text","cn","Link","useStepAttemptDetailQuery","workflowRunSearchParams","humanizeStatus","AgentConfigFailureCallout","toSelectedAttemptError","JsonCode","JsonCodeTabs","StepInspectorSheet","entry","open","onOpenChange","workspaceSlug","projectSlug","workflowRunId","runAttempt","jobId","annotationCount","error","selectedStepError","step","inspectorQuery","id","attempt","enabled","side","className","label","statusVisual","kind","StepInspector","showFailure","query","StepFailureCallout","reason","statusReason","title","failureTitle","sourceLink","sourceLinkForFailure","sourceLocation","type","config","agentConfig","role","variant","div","span","failureDescription","message","as","to","params","search","tab","stepId","stepAttemptId","detail","data","trace","evaluationTrace","resolvedConfig","hasInputs","undefined","countConfigValues","authoredConfig","hasOutputs","outputs","output","response","hasTrace","length","hasAnnotations","detailCount","Number","isPending","InspectorLoading","isError","size","onClick","refetch","InspectorSection","ConfigCode","value","emptyMessage","pre","EvaluationTrace","EmptyInspector","children","section","aria-label","bold","entries","filename","keyCounts","Map","dl","map","keyBase","dropped","occurrence","get","set","empty","field","expression","evaluatedAt","fillTarget","degraded","dt","dd","truncated","exprTruncated","attemptError","humanize","replaceAll","replace","letter","toUpperCase","Array","isArray","reduce","total","item","Object","values"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-graph-content.d.ts","sourceRoot":"","sources":["../../../src/components/job-graph/job-graph-content.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAC,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAG3E,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"job-graph-content.d.ts","sourceRoot":"","sources":["../../../src/components/job-graph/job-graph-content.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAC,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAG3E,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,YAAY,CAAC;AAUxD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,OAAO,EACP,aAAa,EACb,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,IAAI,CACX,iBAAiB,EACjB,qBAAqB,GAAG,cAAc,GAAG,iBAAiB,GAAG,eAAe,CAC7E,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;CACpF,+BAyFA"}
|
|
@@ -8,7 +8,7 @@ import { JobNode, TriggerNode } from './job-node.js';
|
|
|
8
8
|
const NODE_WIDTH = 208;
|
|
9
9
|
const NODE_HEIGHT = 48;
|
|
10
10
|
const COLUMN_GAP = 64;
|
|
11
|
-
const ROW_GAP = 20;
|
|
11
|
+
/** Fixed graph spacing shared by the DOM rows and the edge geometry below. */ const ROW_GAP = 20;
|
|
12
12
|
const TRIGGER_WIDTH = 36;
|
|
13
13
|
const PADDING = 16;
|
|
14
14
|
export function JobGraphContent({ model, trigger, selectedJobId, onSelectJob }) {
|
|
@@ -16,7 +16,7 @@ export function JobGraphContent({ model, trigger, selectedJobId, onSelectJob })
|
|
|
16
16
|
const [hoveredJobId, setHoveredJobId] = useState();
|
|
17
17
|
if (model.nodes.length === 0) {
|
|
18
18
|
return /*#__PURE__*/ _jsx(EmptyState, {
|
|
19
|
-
className: "min-h-160
|
|
19
|
+
className: "min-h-160 p-panel",
|
|
20
20
|
icon: "componentLine",
|
|
21
21
|
title: "No jobs yet",
|
|
22
22
|
description: "This run has not materialized jobs.",
|
|
@@ -77,10 +77,11 @@ export function JobGraphContent({ model, trigger, selectedJobId, onSelectJob })
|
|
|
77
77
|
})
|
|
78
78
|
}),
|
|
79
79
|
model.columns.map((column, columnIndex)=>/*#__PURE__*/ _jsx("div", {
|
|
80
|
-
className: "absolute flex flex-col
|
|
80
|
+
className: "absolute flex flex-col",
|
|
81
81
|
style: {
|
|
82
82
|
left: jobLeft(columnIndex),
|
|
83
|
-
top: PADDING
|
|
83
|
+
top: PADDING,
|
|
84
|
+
rowGap: ROW_GAP
|
|
84
85
|
},
|
|
85
86
|
children: column.map((node)=>/*#__PURE__*/ _jsx(JobNode, {
|
|
86
87
|
node: node,
|