@shipfox/client-workflows 15.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.
Files changed (225) hide show
  1. package/.storybook/preview.css +4 -0
  2. package/.turbo/turbo-build.log +1 -1
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +41 -0
  5. package/dist/components/identifier/identifier.js +2 -2
  6. package/dist/components/identifier/identifier.js.map +1 -1
  7. package/dist/components/job-detail/agent-config-failure-callout.d.ts.map +1 -1
  8. package/dist/components/job-detail/agent-config-failure-callout.js +1 -1
  9. package/dist/components/job-detail/agent-config-failure-callout.js.map +1 -1
  10. package/dist/components/job-detail/job-context-panel.d.ts +6 -0
  11. package/dist/components/job-detail/job-context-panel.d.ts.map +1 -0
  12. package/dist/components/job-detail/job-context-panel.js +224 -0
  13. package/dist/components/job-detail/job-context-panel.js.map +1 -0
  14. package/dist/components/job-detail/job-detail-header.d.ts +10 -1
  15. package/dist/components/job-detail/job-detail-header.d.ts.map +1 -1
  16. package/dist/components/job-detail/job-detail-header.js +58 -39
  17. package/dist/components/job-detail/job-detail-header.js.map +1 -1
  18. package/dist/components/job-detail/job-detail-view.d.ts +1 -1
  19. package/dist/components/job-detail/job-detail-view.d.ts.map +1 -1
  20. package/dist/components/job-detail/job-detail-view.js +92 -41
  21. package/dist/components/job-detail/job-detail-view.js.map +1 -1
  22. package/dist/components/job-detail/job-empty-states.d.ts.map +1 -1
  23. package/dist/components/job-detail/job-empty-states.js +19 -10
  24. package/dist/components/job-detail/job-empty-states.js.map +1 -1
  25. package/dist/components/job-detail/job-execution-switcher.js +4 -4
  26. package/dist/components/job-detail/job-execution-switcher.js.map +1 -1
  27. package/dist/components/job-detail/json-code.d.ts +14 -0
  28. package/dist/components/job-detail/json-code.d.ts.map +1 -0
  29. package/dist/components/job-detail/json-code.js +93 -0
  30. package/dist/components/job-detail/json-code.js.map +1 -0
  31. package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -1
  32. package/dist/components/job-detail/step-attempt-log-panel.js +9 -6
  33. package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -1
  34. package/dist/components/job-detail/step-troubleshooting.d.ts +18 -0
  35. package/dist/components/job-detail/step-troubleshooting.d.ts.map +1 -0
  36. package/dist/components/job-detail/step-troubleshooting.js +493 -0
  37. package/dist/components/job-detail/step-troubleshooting.js.map +1 -0
  38. package/dist/components/job-graph/job-graph-content.d.ts.map +1 -1
  39. package/dist/components/job-graph/job-graph-content.js +5 -4
  40. package/dist/components/job-graph/job-graph-content.js.map +1 -1
  41. package/dist/components/job-graph/job-node.js +3 -3
  42. package/dist/components/job-graph/job-node.js.map +1 -1
  43. package/dist/components/step-list/index.d.ts +1 -0
  44. package/dist/components/step-list/index.d.ts.map +1 -1
  45. package/dist/components/step-list/index.js.map +1 -1
  46. package/dist/components/step-list/step-list-model.d.ts.map +1 -1
  47. package/dist/components/step-list/step-list-model.js +5 -0
  48. package/dist/components/step-list/step-list-model.js.map +1 -1
  49. package/dist/components/step-list/step-list.d.ts +5 -1
  50. package/dist/components/step-list/step-list.d.ts.map +1 -1
  51. package/dist/components/step-list/step-list.js +117 -82
  52. package/dist/components/step-list/step-list.js.map +1 -1
  53. package/dist/components/workflow-run-duration-label.js +1 -1
  54. package/dist/components/workflow-run-duration-label.js.map +1 -1
  55. package/dist/components/workflow-run-list/job-status-strip.js +6 -6
  56. package/dist/components/workflow-run-list/job-status-strip.js.map +1 -1
  57. package/dist/components/workflow-run-list/workflow-run-filter-menu.js +1 -1
  58. package/dist/components/workflow-run-list/workflow-run-filter-menu.js.map +1 -1
  59. package/dist/components/workflow-run-list/workflow-run-filters.js +4 -4
  60. package/dist/components/workflow-run-list/workflow-run-filters.js.map +1 -1
  61. package/dist/components/workflow-run-list/workflow-run-list-states.js +6 -6
  62. package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -1
  63. package/dist/components/workflow-run-list/workflow-run-list-view.js +1 -1
  64. package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -1
  65. package/dist/components/workflow-run-list/workflow-run-row.js +7 -7
  66. package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
  67. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +1 -1
  68. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -1
  69. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +0 -1
  70. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
  71. package/dist/components/workflow-run-summary/workflow-run-summary.js +9 -13
  72. package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
  73. package/dist/components/workflow-run-tabs/index.d.ts +3 -0
  74. package/dist/components/workflow-run-tabs/index.d.ts.map +1 -1
  75. package/dist/components/workflow-run-tabs/index.js +3 -0
  76. package/dist/components/workflow-run-tabs/index.js.map +1 -1
  77. package/dist/components/workflow-run-tabs/run-annotation-count-chip.d.ts +16 -0
  78. package/dist/components/workflow-run-tabs/run-annotation-count-chip.d.ts.map +1 -0
  79. package/dist/components/workflow-run-tabs/run-annotation-count-chip.js +50 -0
  80. package/dist/components/workflow-run-tabs/run-annotation-count-chip.js.map +1 -0
  81. package/dist/components/workflow-run-tabs/run-annotation-item.d.ts +20 -0
  82. package/dist/components/workflow-run-tabs/run-annotation-item.d.ts.map +1 -0
  83. package/dist/components/workflow-run-tabs/run-annotation-item.js +102 -0
  84. package/dist/components/workflow-run-tabs/run-annotation-item.js.map +1 -0
  85. package/dist/components/workflow-run-tabs/run-annotation-list.d.ts +39 -0
  86. package/dist/components/workflow-run-tabs/run-annotation-list.d.ts.map +1 -0
  87. package/dist/components/workflow-run-tabs/run-annotation-list.js +211 -0
  88. package/dist/components/workflow-run-tabs/run-annotation-list.js.map +1 -0
  89. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts +1 -1
  90. package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts.map +1 -1
  91. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js +90 -25
  92. package/dist/components/workflow-run-tabs/run-annotation-summary-line.js.map +1 -1
  93. package/dist/components/workflow-run-tabs/severity-visuals.d.ts +20 -0
  94. package/dist/components/workflow-run-tabs/severity-visuals.d.ts.map +1 -0
  95. package/dist/components/workflow-run-tabs/severity-visuals.js +31 -0
  96. package/dist/components/workflow-run-tabs/severity-visuals.js.map +1 -0
  97. package/dist/components/workflow-run-view/run-workspace-nav.d.ts +1 -1
  98. package/dist/components/workflow-run-view/run-workspace-nav.d.ts.map +1 -1
  99. package/dist/components/workflow-run-view/run-workspace-nav.js +16 -10
  100. package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -1
  101. package/dist/components/workflow-run-view/workflow-run-states.js +6 -6
  102. package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -1
  103. package/dist/components/workflow-run-view/workflow-run-view.d.ts +1 -3
  104. package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
  105. package/dist/components/workflow-run-view/workflow-run-view.js +217 -59
  106. package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
  107. package/dist/core/entities/job-execution.d.ts +7 -0
  108. package/dist/core/entities/job-execution.d.ts.map +1 -1
  109. package/dist/core/entities/job-execution.js.map +1 -1
  110. package/dist/core/entities/job.d.ts +9 -0
  111. package/dist/core/entities/job.d.ts.map +1 -1
  112. package/dist/core/entities/job.js.map +1 -1
  113. package/dist/core/entities/step-attempt.d.ts +29 -0
  114. package/dist/core/entities/step-attempt.d.ts.map +1 -1
  115. package/dist/core/entities/step-attempt.js.map +1 -1
  116. package/dist/core/entities/step.d.ts +3 -1
  117. package/dist/core/entities/step.d.ts.map +1 -1
  118. package/dist/core/entities/step.js.map +1 -1
  119. package/dist/core/run-annotation.d.ts +79 -0
  120. package/dist/core/run-annotation.d.ts.map +1 -0
  121. package/dist/core/run-annotation.js +125 -0
  122. package/dist/core/run-annotation.js.map +1 -0
  123. package/dist/core/workflow-run.d.ts +1 -1
  124. package/dist/core/workflow-run.d.ts.map +1 -1
  125. package/dist/core/workflow-run.js.map +1 -1
  126. package/dist/hooks/api/annotations.d.ts +63 -0
  127. package/dist/hooks/api/annotations.d.ts.map +1 -0
  128. package/dist/hooks/api/annotations.js +145 -0
  129. package/dist/hooks/api/annotations.js.map +1 -0
  130. package/dist/hooks/api/run-annotation-mapper.d.ts +10 -0
  131. package/dist/hooks/api/run-annotation-mapper.d.ts.map +1 -0
  132. package/dist/hooks/api/run-annotation-mapper.js +22 -0
  133. package/dist/hooks/api/run-annotation-mapper.js.map +1 -0
  134. package/dist/hooks/api/run-annotations.d.ts +25 -0
  135. package/dist/hooks/api/run-annotations.d.ts.map +1 -0
  136. package/dist/hooks/api/run-annotations.js +78 -0
  137. package/dist/hooks/api/run-annotations.js.map +1 -0
  138. package/dist/hooks/api/step-attempt-detail.d.ts +14 -0
  139. package/dist/hooks/api/step-attempt-detail.d.ts.map +1 -0
  140. package/dist/hooks/api/step-attempt-detail.js +43 -0
  141. package/dist/hooks/api/step-attempt-detail.js.map +1 -0
  142. package/dist/hooks/api/workflow-run-mapper.d.ts +9 -2
  143. package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
  144. package/dist/hooks/api/workflow-run-mapper.js +47 -0
  145. package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
  146. package/dist/pages/project-workflows-page.js +19 -19
  147. package/dist/pages/project-workflows-page.js.map +1 -1
  148. package/dist/pages/workflow-run-list-page.js +1 -1
  149. package/dist/pages/workflow-run-list-page.js.map +1 -1
  150. package/dist/routes/inputs.d.ts +7 -2
  151. package/dist/routes/inputs.d.ts.map +1 -1
  152. package/dist/routes/inputs.js +5 -6
  153. package/dist/routes/inputs.js.map +1 -1
  154. package/dist/tsconfig.test.tsbuildinfo +1 -1
  155. package/package.json +10 -9
  156. package/src/components/identifier/identifier.tsx +2 -2
  157. package/src/components/job-detail/agent-config-failure-callout.tsx +5 -1
  158. package/src/components/job-detail/job-context-panel.test.tsx +72 -0
  159. package/src/components/job-detail/job-context-panel.tsx +237 -0
  160. package/src/components/job-detail/job-detail-header.test.tsx +3 -0
  161. package/src/components/job-detail/job-detail-header.tsx +65 -34
  162. package/src/components/job-detail/job-detail-view.stories.tsx +555 -48
  163. package/src/components/job-detail/job-detail-view.tsx +101 -42
  164. package/src/components/job-detail/job-empty-states.tsx +23 -10
  165. package/src/components/job-detail/job-execution-switcher.tsx +5 -5
  166. package/src/components/job-detail/json-code.tsx +120 -0
  167. package/src/components/job-detail/step-attempt-log-panel.test.tsx +1 -0
  168. package/src/components/job-detail/step-attempt-log-panel.tsx +17 -6
  169. package/src/components/job-detail/step-troubleshooting.stories.tsx +120 -0
  170. package/src/components/job-detail/step-troubleshooting.test.tsx +337 -0
  171. package/src/components/job-detail/step-troubleshooting.tsx +537 -0
  172. package/src/components/job-graph/job-graph-content.tsx +4 -3
  173. package/src/components/job-graph/job-node.tsx +3 -3
  174. package/src/components/step-list/index.ts +1 -0
  175. package/src/components/step-list/step-list-model.ts +5 -0
  176. package/src/components/step-list/step-list.test.tsx +75 -2
  177. package/src/components/step-list/step-list.tsx +73 -20
  178. package/src/components/workflow-run-duration-label.tsx +1 -1
  179. package/src/components/workflow-run-list/job-status-strip.tsx +6 -6
  180. package/src/components/workflow-run-list/workflow-run-filter-menu.tsx +1 -1
  181. package/src/components/workflow-run-list/workflow-run-filters.tsx +4 -4
  182. package/src/components/workflow-run-list/workflow-run-list-states.tsx +6 -6
  183. package/src/components/workflow-run-list/workflow-run-list-view.tsx +1 -1
  184. package/src/components/workflow-run-list/workflow-run-row.tsx +7 -7
  185. package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +1 -1
  186. package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +1 -1
  187. package/src/components/workflow-run-summary/workflow-run-summary.tsx +12 -12
  188. package/src/components/workflow-run-tabs/index.ts +7 -0
  189. package/src/components/workflow-run-tabs/run-annotation-count-chip.tsx +63 -0
  190. package/src/components/workflow-run-tabs/run-annotation-item.tsx +123 -0
  191. package/src/components/workflow-run-tabs/run-annotation-list.tsx +273 -0
  192. package/src/components/workflow-run-tabs/run-annotation-summary-line.test.tsx +77 -3
  193. package/src/components/workflow-run-tabs/run-annotation-summary-line.tsx +95 -20
  194. package/src/components/workflow-run-tabs/run-annotations.stories.tsx +293 -0
  195. package/src/components/workflow-run-tabs/severity-visuals.ts +37 -0
  196. package/src/components/workflow-run-view/run-workspace-nav.test.tsx +44 -0
  197. package/src/components/workflow-run-view/run-workspace-nav.tsx +22 -9
  198. package/src/components/workflow-run-view/workflow-run-states.tsx +6 -6
  199. package/src/components/workflow-run-view/workflow-run-view.test.tsx +246 -20
  200. package/src/components/workflow-run-view/workflow-run-view.tsx +255 -37
  201. package/src/core/entities/job-execution.ts +7 -0
  202. package/src/core/entities/job.ts +9 -0
  203. package/src/core/entities/step-attempt.ts +33 -0
  204. package/src/core/entities/step.ts +3 -1
  205. package/src/core/run-annotation.test.ts +315 -0
  206. package/src/core/run-annotation.ts +244 -0
  207. package/src/core/workflow-run.ts +4 -0
  208. package/src/hooks/api/annotations.test.ts +84 -0
  209. package/src/hooks/api/annotations.ts +240 -0
  210. package/src/hooks/api/run-annotation-mapper.ts +30 -0
  211. package/src/hooks/api/run-annotations.ts +137 -0
  212. package/src/hooks/api/step-attempt-detail.ts +67 -0
  213. package/src/hooks/api/workflow-run-mapper.ts +46 -0
  214. package/src/hooks/api/workflow-runs.test.tsx +61 -1
  215. package/src/pages/project-workflows-page.tsx +19 -19
  216. package/src/pages/workflow-job-detail-page.test.tsx +118 -1
  217. package/src/pages/workflow-run-list-page.tsx +1 -1
  218. package/src/routes/inputs.ts +7 -2
  219. package/test/fixtures/workflow-run.ts +7 -0
  220. package/tsconfig.build.tsbuildinfo +1 -1
  221. package/dist/core/workflow-run-tabs.d.ts +0 -9
  222. package/dist/core/workflow-run-tabs.d.ts.map +0 -1
  223. package/dist/core/workflow-run-tabs.js +0 -3
  224. package/dist/core/workflow-run-tabs.js.map +0 -1
  225. package/src/core/workflow-run-tabs.ts +0 -8
@@ -0,0 +1,125 @@
1
+ /**
2
+ * The severities the run surfaces rank and filter by. The `default` style carries no severity:
3
+ * it counts toward the total and sorts last, but no severity filter selects it.
4
+ */ export const RUN_ANNOTATION_SEVERITIES = [
5
+ 'error',
6
+ 'warning',
7
+ 'info',
8
+ 'success'
9
+ ];
10
+ const SEVERITY_RANK = {
11
+ error: 0,
12
+ warning: 1,
13
+ info: 2,
14
+ success: 3,
15
+ default: 4
16
+ };
17
+ const SEVERITY_SET = new Set(RUN_ANNOTATION_SEVERITIES);
18
+ export function annotationSeverity(style) {
19
+ return SEVERITY_SET.has(style) ? style : null;
20
+ }
21
+ export function summarizeRunAnnotations(annotations, { truncated = false } = {}) {
22
+ const summary = {
23
+ total: annotations.length,
24
+ error: 0,
25
+ warning: 0,
26
+ info: 0,
27
+ success: 0,
28
+ truncated
29
+ };
30
+ for (const annotation of annotations){
31
+ const severity = annotationSeverity(annotation.style);
32
+ if (severity) summary[severity] += 1;
33
+ }
34
+ return summary;
35
+ }
36
+ /**
37
+ * Ranks annotations for display.
38
+ *
39
+ * Severity leads: emission order is a log affordance, not a summary affordance. `sequence` is
40
+ * only stable within one job execution, so the tie-break walks down job position and execution
41
+ * sequence before using it, and ends on the id so the order never depends on input order.
42
+ */ export function buildRunAnnotationList({ annotations, jobs, severity, jobId }) {
43
+ const index = indexJobs(jobs);
44
+ const entries = [];
45
+ for (const annotation of annotations){
46
+ if (jobId && annotation.jobId !== jobId) continue;
47
+ const annotationSeverityValue = annotationSeverity(annotation.style);
48
+ if (severity && annotationSeverityValue !== severity) continue;
49
+ entries.push(toEntry(annotation, index));
50
+ }
51
+ return entries.sort((left, right)=>compareEntries(left, right, index));
52
+ }
53
+ /** Counts annotations owned by one job, for the job page's bounded reference chip. */ export function summarizeJobAnnotations(annotations, jobId, options = {}) {
54
+ return summarizeRunAnnotations(annotations.filter((annotation)=>annotation.jobId === jobId), options);
55
+ }
56
+ /** The loudest severity present, which tints a count chip. */ export function highestRunAnnotationSeverity(summary) {
57
+ return RUN_ANNOTATION_SEVERITIES.find((severity)=>summary[severity] > 0) ?? null;
58
+ }
59
+ function indexJobs(jobs) {
60
+ const index = new Map();
61
+ for (const job of jobs){
62
+ const executions = new Map();
63
+ for (const execution of job.jobExecutions){
64
+ const steps = new Map();
65
+ for (const step of execution.steps){
66
+ const attemptIds = new Map();
67
+ for (const attempt of step.attempts)attemptIds.set(attempt.attempt, attempt.id);
68
+ steps.set(step.id, {
69
+ label: step.name || step.key || step.id,
70
+ attemptIds
71
+ });
72
+ }
73
+ executions.set(execution.id, {
74
+ sequence: execution.sequence,
75
+ steps
76
+ });
77
+ }
78
+ index.set(job.id, {
79
+ position: job.position,
80
+ name: job.displayName,
81
+ executionCount: job.jobExecutions.length,
82
+ executions
83
+ });
84
+ }
85
+ return index;
86
+ }
87
+ function toEntry(annotation, index) {
88
+ const job = index.get(annotation.jobId);
89
+ const execution = job?.executions.get(annotation.jobExecutionId);
90
+ const step = execution?.steps.get(annotation.originStepId);
91
+ const stepAttemptId = step?.attemptIds.get(annotation.originStepAttempt);
92
+ return {
93
+ annotation,
94
+ jobName: job?.name ?? null,
95
+ executionLabel: execution && job && job.executionCount > 1 ? `execution #${execution.sequence}` : null,
96
+ stepLabel: step?.label ?? null,
97
+ attemptLabel: `attempt ${annotation.originStepAttempt}`,
98
+ origin: stepAttemptId ? {
99
+ jobId: annotation.jobId,
100
+ jobExecutionId: annotation.jobExecutionId,
101
+ stepId: annotation.originStepId,
102
+ stepAttemptId
103
+ } : null
104
+ };
105
+ }
106
+ function compareEntries(left, right, index) {
107
+ const bySeverity = SEVERITY_RANK[left.annotation.style] - SEVERITY_RANK[right.annotation.style];
108
+ if (bySeverity !== 0) return bySeverity;
109
+ const byJob = jobPosition(left, index) - jobPosition(right, index);
110
+ if (byJob !== 0) return byJob;
111
+ const byExecution = executionSequence(left, index) - executionSequence(right, index);
112
+ if (byExecution !== 0) return byExecution;
113
+ const bySequence = left.annotation.sequence - right.annotation.sequence;
114
+ if (bySequence !== 0) return bySequence;
115
+ return left.annotation.id.localeCompare(right.annotation.id);
116
+ }
117
+ /** An unmatched job sorts last rather than first, so known provenance leads the list. */ function jobPosition(entry, index) {
118
+ return index.get(entry.annotation.jobId)?.position ?? Number.MAX_SAFE_INTEGER;
119
+ }
120
+ function executionSequence(entry, index) {
121
+ const job = index.get(entry.annotation.jobId);
122
+ return job?.executions.get(entry.annotation.jobExecutionId)?.sequence ?? Number.MAX_SAFE_INTEGER;
123
+ }
124
+
125
+ //# sourceMappingURL=run-annotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/run-annotation.ts"],"sourcesContent":["import type {Job} from './workflow-run.js';\n\nexport type RunAnnotationStyle = 'default' | 'info' | 'success' | 'warning' | 'error';\n\n/**\n * The severities the run surfaces rank and filter by. The `default` style carries no severity:\n * it counts toward the total and sorts last, but no severity filter selects it.\n */\nexport const RUN_ANNOTATION_SEVERITIES = ['error', 'warning', 'info', 'success'] as const;\n\nexport type RunAnnotationSeverity = (typeof RUN_ANNOTATION_SEVERITIES)[number];\n\nconst SEVERITY_RANK: Record<RunAnnotationStyle, number> = {\n error: 0,\n warning: 1,\n info: 2,\n success: 3,\n default: 4,\n};\n\nconst SEVERITY_SET = new Set<string>(RUN_ANNOTATION_SEVERITIES);\n\nexport interface RunAnnotation {\n id: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n context: string;\n style: RunAnnotationStyle;\n sequence: number;\n}\n\nexport interface RunAnnotationRecord extends RunAnnotation {\n body: string;\n}\n\n/** Counts shown by the run rail and the severity summary line. */\nexport interface RunAnnotationSummary {\n total: number;\n error: number;\n warning: number;\n info: number;\n success: number;\n /** True when the read hit its page budget, so every count is a lower bound. */\n truncated: boolean;\n /** Optional per-step counts used by the step inspector without loading annotation bodies. */\n stepCounts?: readonly {\n stepId: string;\n attempt: number;\n total: number;\n }[];\n}\n\n/** Everything the annotations list needs to route back to the step that emitted an annotation. */\nexport interface RunAnnotationOrigin {\n jobId: string;\n jobExecutionId: string;\n stepId: string;\n stepAttemptId: string;\n}\n\nexport interface RunAnnotationEntry {\n annotation: RunAnnotationRecord;\n jobName: string | null;\n /** Only set when the job ran more than once, so a single-execution job stays uncluttered. */\n executionLabel: string | null;\n stepLabel: string | null;\n attemptLabel: string;\n /** `null` when the run attempt no longer contains the emitting step, so no link is offered. */\n origin: RunAnnotationOrigin | null;\n}\n\nexport function annotationSeverity(style: RunAnnotationStyle): RunAnnotationSeverity | null {\n return SEVERITY_SET.has(style) ? (style as RunAnnotationSeverity) : null;\n}\n\nexport function summarizeRunAnnotations(\n annotations: readonly RunAnnotation[],\n {truncated = false}: {truncated?: boolean | undefined} = {},\n): RunAnnotationSummary {\n const summary: RunAnnotationSummary = {\n total: annotations.length,\n error: 0,\n warning: 0,\n info: 0,\n success: 0,\n truncated,\n };\n\n for (const annotation of annotations) {\n const severity = annotationSeverity(annotation.style);\n if (severity) summary[severity] += 1;\n }\n\n return summary;\n}\n\nexport interface BuildRunAnnotationListInput {\n annotations: readonly RunAnnotationRecord[];\n jobs: readonly Job[];\n severity?: RunAnnotationSeverity | undefined;\n jobId?: string | undefined;\n}\n\n/**\n * Ranks annotations for display.\n *\n * Severity leads: emission order is a log affordance, not a summary affordance. `sequence` is\n * only stable within one job execution, so the tie-break walks down job position and execution\n * sequence before using it, and ends on the id so the order never depends on input order.\n */\nexport function buildRunAnnotationList({\n annotations,\n jobs,\n severity,\n jobId,\n}: BuildRunAnnotationListInput): RunAnnotationEntry[] {\n const index = indexJobs(jobs);\n const entries: RunAnnotationEntry[] = [];\n\n for (const annotation of annotations) {\n if (jobId && annotation.jobId !== jobId) continue;\n const annotationSeverityValue = annotationSeverity(annotation.style);\n if (severity && annotationSeverityValue !== severity) continue;\n entries.push(toEntry(annotation, index));\n }\n\n return entries.sort((left, right) => compareEntries(left, right, index));\n}\n\n/** Counts annotations owned by one job, for the job page's bounded reference chip. */\nexport function summarizeJobAnnotations(\n annotations: readonly RunAnnotation[],\n jobId: string,\n options: {truncated?: boolean | undefined} = {},\n): RunAnnotationSummary {\n return summarizeRunAnnotations(\n annotations.filter((annotation) => annotation.jobId === jobId),\n options,\n );\n}\n\n/** The loudest severity present, which tints a count chip. */\nexport function highestRunAnnotationSeverity(\n summary: RunAnnotationSummary,\n): RunAnnotationSeverity | null {\n return RUN_ANNOTATION_SEVERITIES.find((severity) => summary[severity] > 0) ?? null;\n}\n\ninterface JobIndexEntry {\n position: number;\n name: string;\n executionCount: number;\n executions: Map<string, JobExecutionIndexEntry>;\n}\n\ninterface JobExecutionIndexEntry {\n sequence: number;\n steps: Map<string, {label: string; attemptIds: Map<number, string>}>;\n}\n\nfunction indexJobs(jobs: readonly Job[]): Map<string, JobIndexEntry> {\n const index = new Map<string, JobIndexEntry>();\n\n for (const job of jobs) {\n const executions = new Map<string, JobExecutionIndexEntry>();\n for (const execution of job.jobExecutions) {\n const steps = new Map<string, {label: string; attemptIds: Map<number, string>}>();\n for (const step of execution.steps) {\n const attemptIds = new Map<number, string>();\n for (const attempt of step.attempts) attemptIds.set(attempt.attempt, attempt.id);\n steps.set(step.id, {label: step.name || step.key || step.id, attemptIds});\n }\n executions.set(execution.id, {sequence: execution.sequence, steps});\n }\n\n index.set(job.id, {\n position: job.position,\n name: job.displayName,\n executionCount: job.jobExecutions.length,\n executions,\n });\n }\n\n return index;\n}\n\nfunction toEntry(\n annotation: RunAnnotationRecord,\n index: Map<string, JobIndexEntry>,\n): RunAnnotationEntry {\n const job = index.get(annotation.jobId);\n const execution = job?.executions.get(annotation.jobExecutionId);\n const step = execution?.steps.get(annotation.originStepId);\n const stepAttemptId = step?.attemptIds.get(annotation.originStepAttempt);\n\n return {\n annotation,\n jobName: job?.name ?? null,\n executionLabel:\n execution && job && job.executionCount > 1 ? `execution #${execution.sequence}` : null,\n stepLabel: step?.label ?? null,\n attemptLabel: `attempt ${annotation.originStepAttempt}`,\n origin: stepAttemptId\n ? {\n jobId: annotation.jobId,\n jobExecutionId: annotation.jobExecutionId,\n stepId: annotation.originStepId,\n stepAttemptId,\n }\n : null,\n };\n}\n\nfunction compareEntries(\n left: RunAnnotationEntry,\n right: RunAnnotationEntry,\n index: Map<string, JobIndexEntry>,\n): number {\n const bySeverity = SEVERITY_RANK[left.annotation.style] - SEVERITY_RANK[right.annotation.style];\n if (bySeverity !== 0) return bySeverity;\n\n const byJob = jobPosition(left, index) - jobPosition(right, index);\n if (byJob !== 0) return byJob;\n\n const byExecution = executionSequence(left, index) - executionSequence(right, index);\n if (byExecution !== 0) return byExecution;\n\n const bySequence = left.annotation.sequence - right.annotation.sequence;\n if (bySequence !== 0) return bySequence;\n\n return left.annotation.id.localeCompare(right.annotation.id);\n}\n\n/** An unmatched job sorts last rather than first, so known provenance leads the list. */\nfunction jobPosition(entry: RunAnnotationEntry, index: Map<string, JobIndexEntry>): number {\n return index.get(entry.annotation.jobId)?.position ?? Number.MAX_SAFE_INTEGER;\n}\n\nfunction executionSequence(entry: RunAnnotationEntry, index: Map<string, JobIndexEntry>): number {\n const job = index.get(entry.annotation.jobId);\n return job?.executions.get(entry.annotation.jobExecutionId)?.sequence ?? Number.MAX_SAFE_INTEGER;\n}\n"],"names":["RUN_ANNOTATION_SEVERITIES","SEVERITY_RANK","error","warning","info","success","default","SEVERITY_SET","Set","annotationSeverity","style","has","summarizeRunAnnotations","annotations","truncated","summary","total","length","annotation","severity","buildRunAnnotationList","jobs","jobId","index","indexJobs","entries","annotationSeverityValue","push","toEntry","sort","left","right","compareEntries","summarizeJobAnnotations","options","filter","highestRunAnnotationSeverity","find","Map","job","executions","execution","jobExecutions","steps","step","attemptIds","attempt","attempts","set","id","label","name","key","sequence","position","displayName","executionCount","get","jobExecutionId","originStepId","stepAttemptId","originStepAttempt","jobName","executionLabel","stepLabel","attemptLabel","origin","stepId","bySeverity","byJob","jobPosition","byExecution","executionSequence","bySequence","localeCompare","entry","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
@@ -4,7 +4,7 @@ export type { JobExecutionDisplayDuration, JobExecutionDisplayStatus, JobExecuti
4
4
  export { deriveJobExecutionDisplayStatus, elapsedTimeFromTimestamps, isTerminalJobExecutionStatus, JobExecution, } from './entities/job-execution.js';
5
5
  export type { AgentConfigIssue, AgentStepConfig, Step, StepError, StepErrorCategory, StepErrorReason, StepSourceLocation, } from './entities/step.js';
6
6
  export { AGENT_CONFIG_ISSUES, compareStepAttempts, resolveStepAttempt, STEP_ERROR_REASONS, } from './entities/step.js';
7
- export type { StepAttemptDisplayDuration, StepGateResult, } from './entities/step-attempt.js';
7
+ export type { EvaluationTraceEntry, EvaluationTraceLimitEntry, EvaluationTraceValueEntry, StepAttemptDetail, StepAttemptDisplayDuration, StepGateResult, } from './entities/step-attempt.js';
8
8
  export { StepAttempt } from './entities/step-attempt.js';
9
9
  export type { ManualWorkflowLaunch, WorkflowDisplayStatus, WorkflowRun, WorkflowRunDetail, WorkflowRunDisplay, WorkflowRunDisplayDuration, WorkflowRunJobStatusCount, WorkflowRunJobSummary, WorkflowRunJobs, WorkflowRunListItem, WorkflowRunListPage, WorkflowRunProgress, WorkflowRunRecord, WorkflowRunRerunMode, WorkflowRunStatus, WorkflowRunTriggerReference, WorkflowSourceSnapshot, WorkflowStatus, } from './entities/workflow-run.js';
10
10
  export { deriveWorkflowRunDisplay, isWorkflowRunTerminal, isWorkflowStatus, TERMINAL_WORKFLOW_RUN_STATUSES, WORKFLOW_DISPLAY_STATUSES, WORKFLOW_RUN_STATUSES, workflowRunActor, workflowRunBlockingJob, workflowRunBranchLabel, workflowRunCommitLabel, workflowRunDetailDisplay, workflowRunFirstStartedAt, workflowRunListItemDisplay, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel, } from './entities/workflow-run.js';
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../src/core/workflow-run.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,GAAG,EACH,mBAAmB,EACnB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,2BAA2B,EAC3B,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,GACb,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,0BAA0B,EAC1B,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,8BAA8B,EAC9B,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAC,iCAAiC,EAAC,MAAM,oCAAoC,CAAC;AAC1F,OAAO,EAAC,kBAAkB,EAAE,yBAAyB,EAAC,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../src/core/workflow-run.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,GAAG,EACH,mBAAmB,EACnB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,2BAA2B,EAC3B,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,GACb,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,EACzB,iBAAiB,EACjB,0BAA0B,EAC1B,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,8BAA8B,EAC9B,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAC,iCAAiC,EAAC,MAAM,oCAAoC,CAAC;AAC1F,OAAO,EAAC,kBAAkB,EAAE,yBAAyB,EAAC,MAAM,oCAAoC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/workflow-run.ts"],"sourcesContent":["export type {\n JobDisplayDuration,\n JobDisplayStatus,\n JobListening,\n JobMode,\n JobStatus,\n JobStatusReason,\n ListenerStatus,\n ResolutionReason,\n} from './entities/job.js';\nexport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n isTerminalJobStatus,\n Job,\n resolveJobExecution,\n TERMINAL_WORKFLOW_JOB_STATUSES,\n WORKFLOW_JOB_STATUSES,\n} from './entities/job.js';\nexport type {\n JobExecutionDisplayDuration,\n JobExecutionDisplayStatus,\n JobExecutionStatus,\n JobExecutionTime,\n WorkflowExecutionEvent,\n} from './entities/job-execution.js';\nexport {\n deriveJobExecutionDisplayStatus,\n elapsedTimeFromTimestamps,\n isTerminalJobExecutionStatus,\n JobExecution,\n} from './entities/job-execution.js';\nexport type {\n AgentConfigIssue,\n AgentStepConfig,\n Step,\n StepError,\n StepErrorCategory,\n StepErrorReason,\n StepSourceLocation,\n} from './entities/step.js';\nexport {\n AGENT_CONFIG_ISSUES,\n compareStepAttempts,\n resolveStepAttempt,\n STEP_ERROR_REASONS,\n} from './entities/step.js';\nexport type {\n StepAttemptDisplayDuration,\n StepGateResult,\n} from './entities/step-attempt.js';\nexport {StepAttempt} from './entities/step-attempt.js';\nexport type {\n ManualWorkflowLaunch,\n WorkflowDisplayStatus,\n WorkflowRun,\n WorkflowRunDetail,\n WorkflowRunDisplay,\n WorkflowRunDisplayDuration,\n WorkflowRunJobStatusCount,\n WorkflowRunJobSummary,\n WorkflowRunJobs,\n WorkflowRunListItem,\n WorkflowRunListPage,\n WorkflowRunProgress,\n WorkflowRunRecord,\n WorkflowRunRerunMode,\n WorkflowRunStatus,\n WorkflowRunTriggerReference,\n WorkflowSourceSnapshot,\n WorkflowStatus,\n} from './entities/workflow-run.js';\nexport {\n deriveWorkflowRunDisplay,\n isWorkflowRunTerminal,\n isWorkflowStatus,\n TERMINAL_WORKFLOW_RUN_STATUSES,\n WORKFLOW_DISPLAY_STATUSES,\n WORKFLOW_RUN_STATUSES,\n workflowRunActor,\n workflowRunBlockingJob,\n workflowRunBranchLabel,\n workflowRunCommitLabel,\n workflowRunDetailDisplay,\n workflowRunFirstStartedAt,\n workflowRunListItemDisplay,\n workflowRunTriggerDisplayLabel,\n workflowRunTriggerLabel,\n} from './entities/workflow-run.js';\nexport type {WorkflowRunAttemptDisplayDuration} from './entities/workflow-run-attempt.js';\nexport {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './entities/workflow-run-attempt.js';\n"],"names":["defaultJobExecution","deriveJobDisplayStatus","isTerminalJobStatus","Job","resolveJobExecution","TERMINAL_WORKFLOW_JOB_STATUSES","WORKFLOW_JOB_STATUSES","deriveJobExecutionDisplayStatus","elapsedTimeFromTimestamps","isTerminalJobExecutionStatus","JobExecution","AGENT_CONFIG_ISSUES","compareStepAttempts","resolveStepAttempt","STEP_ERROR_REASONS","StepAttempt","deriveWorkflowRunDisplay","isWorkflowRunTerminal","isWorkflowStatus","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_DISPLAY_STATUSES","WORKFLOW_RUN_STATUSES","workflowRunActor","workflowRunBlockingJob","workflowRunBranchLabel","workflowRunCommitLabel","workflowRunDetailDisplay","workflowRunFirstStartedAt","workflowRunListItemDisplay","workflowRunTriggerDisplayLabel","workflowRunTriggerLabel","WorkflowRunAttempt","WorkflowRunAttemptSummary"],"mappings":"AAUA,SACEA,mBAAmB,EACnBC,sBAAsB,EACtBC,mBAAmB,EACnBC,GAAG,EACHC,mBAAmB,EACnBC,8BAA8B,EAC9BC,qBAAqB,QAChB,oBAAoB;AAQ3B,SACEC,+BAA+B,EAC/BC,yBAAyB,EACzBC,4BAA4B,EAC5BC,YAAY,QACP,8BAA8B;AAUrC,SACEC,mBAAmB,EACnBC,mBAAmB,EACnBC,kBAAkB,EAClBC,kBAAkB,QACb,qBAAqB;AAK5B,SAAQC,WAAW,QAAO,6BAA6B;AAqBvD,SACEC,wBAAwB,EACxBC,qBAAqB,EACrBC,gBAAgB,EAChBC,8BAA8B,EAC9BC,yBAAyB,EACzBC,qBAAqB,EACrBC,gBAAgB,EAChBC,sBAAsB,EACtBC,sBAAsB,EACtBC,sBAAsB,EACtBC,wBAAwB,EACxBC,yBAAyB,EACzBC,0BAA0B,EAC1BC,8BAA8B,EAC9BC,uBAAuB,QAClB,6BAA6B;AAEpC,SAAQC,kBAAkB,EAAEC,yBAAyB,QAAO,qCAAqC"}
1
+ {"version":3,"sources":["../../src/core/workflow-run.ts"],"sourcesContent":["export type {\n JobDisplayDuration,\n JobDisplayStatus,\n JobListening,\n JobMode,\n JobStatus,\n JobStatusReason,\n ListenerStatus,\n ResolutionReason,\n} from './entities/job.js';\nexport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n isTerminalJobStatus,\n Job,\n resolveJobExecution,\n TERMINAL_WORKFLOW_JOB_STATUSES,\n WORKFLOW_JOB_STATUSES,\n} from './entities/job.js';\nexport type {\n JobExecutionDisplayDuration,\n JobExecutionDisplayStatus,\n JobExecutionStatus,\n JobExecutionTime,\n WorkflowExecutionEvent,\n} from './entities/job-execution.js';\nexport {\n deriveJobExecutionDisplayStatus,\n elapsedTimeFromTimestamps,\n isTerminalJobExecutionStatus,\n JobExecution,\n} from './entities/job-execution.js';\nexport type {\n AgentConfigIssue,\n AgentStepConfig,\n Step,\n StepError,\n StepErrorCategory,\n StepErrorReason,\n StepSourceLocation,\n} from './entities/step.js';\nexport {\n AGENT_CONFIG_ISSUES,\n compareStepAttempts,\n resolveStepAttempt,\n STEP_ERROR_REASONS,\n} from './entities/step.js';\nexport type {\n EvaluationTraceEntry,\n EvaluationTraceLimitEntry,\n EvaluationTraceValueEntry,\n StepAttemptDetail,\n StepAttemptDisplayDuration,\n StepGateResult,\n} from './entities/step-attempt.js';\nexport {StepAttempt} from './entities/step-attempt.js';\nexport type {\n ManualWorkflowLaunch,\n WorkflowDisplayStatus,\n WorkflowRun,\n WorkflowRunDetail,\n WorkflowRunDisplay,\n WorkflowRunDisplayDuration,\n WorkflowRunJobStatusCount,\n WorkflowRunJobSummary,\n WorkflowRunJobs,\n WorkflowRunListItem,\n WorkflowRunListPage,\n WorkflowRunProgress,\n WorkflowRunRecord,\n WorkflowRunRerunMode,\n WorkflowRunStatus,\n WorkflowRunTriggerReference,\n WorkflowSourceSnapshot,\n WorkflowStatus,\n} from './entities/workflow-run.js';\nexport {\n deriveWorkflowRunDisplay,\n isWorkflowRunTerminal,\n isWorkflowStatus,\n TERMINAL_WORKFLOW_RUN_STATUSES,\n WORKFLOW_DISPLAY_STATUSES,\n WORKFLOW_RUN_STATUSES,\n workflowRunActor,\n workflowRunBlockingJob,\n workflowRunBranchLabel,\n workflowRunCommitLabel,\n workflowRunDetailDisplay,\n workflowRunFirstStartedAt,\n workflowRunListItemDisplay,\n workflowRunTriggerDisplayLabel,\n workflowRunTriggerLabel,\n} from './entities/workflow-run.js';\nexport type {WorkflowRunAttemptDisplayDuration} from './entities/workflow-run-attempt.js';\nexport {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './entities/workflow-run-attempt.js';\n"],"names":["defaultJobExecution","deriveJobDisplayStatus","isTerminalJobStatus","Job","resolveJobExecution","TERMINAL_WORKFLOW_JOB_STATUSES","WORKFLOW_JOB_STATUSES","deriveJobExecutionDisplayStatus","elapsedTimeFromTimestamps","isTerminalJobExecutionStatus","JobExecution","AGENT_CONFIG_ISSUES","compareStepAttempts","resolveStepAttempt","STEP_ERROR_REASONS","StepAttempt","deriveWorkflowRunDisplay","isWorkflowRunTerminal","isWorkflowStatus","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_DISPLAY_STATUSES","WORKFLOW_RUN_STATUSES","workflowRunActor","workflowRunBlockingJob","workflowRunBranchLabel","workflowRunCommitLabel","workflowRunDetailDisplay","workflowRunFirstStartedAt","workflowRunListItemDisplay","workflowRunTriggerDisplayLabel","workflowRunTriggerLabel","WorkflowRunAttempt","WorkflowRunAttemptSummary"],"mappings":"AAUA,SACEA,mBAAmB,EACnBC,sBAAsB,EACtBC,mBAAmB,EACnBC,GAAG,EACHC,mBAAmB,EACnBC,8BAA8B,EAC9BC,qBAAqB,QAChB,oBAAoB;AAQ3B,SACEC,+BAA+B,EAC/BC,yBAAyB,EACzBC,4BAA4B,EAC5BC,YAAY,QACP,8BAA8B;AAUrC,SACEC,mBAAmB,EACnBC,mBAAmB,EACnBC,kBAAkB,EAClBC,kBAAkB,QACb,qBAAqB;AAS5B,SAAQC,WAAW,QAAO,6BAA6B;AAqBvD,SACEC,wBAAwB,EACxBC,qBAAqB,EACrBC,gBAAgB,EAChBC,8BAA8B,EAC9BC,yBAAyB,EACzBC,qBAAqB,EACrBC,gBAAgB,EAChBC,sBAAsB,EACtBC,sBAAsB,EACtBC,sBAAsB,EACtBC,wBAAwB,EACxBC,yBAAyB,EACzBC,0BAA0B,EAC1BC,8BAA8B,EAC9BC,uBAAuB,QAClB,6BAA6B;AAEpC,SAAQC,kBAAkB,EAAEC,yBAAyB,QAAO,qCAAqC"}
@@ -0,0 +1,63 @@
1
+ import { type AnnotationStyleDto } from '@shipfox/annotations-dto';
2
+ import type { RunAnnotationSummary } from '#core/run-annotation.js';
3
+ export interface WorkflowRunAnnotation {
4
+ id: string;
5
+ jobId: string;
6
+ jobExecutionId: string;
7
+ originStepId: string;
8
+ originStepAttempt: number;
9
+ context: string;
10
+ style: AnnotationStyleDto;
11
+ sequence: number;
12
+ body: string;
13
+ }
14
+ export interface WorkflowRunAnnotationsPage {
15
+ annotations: WorkflowRunAnnotation[];
16
+ hasMore: boolean;
17
+ nextCursor: string | null;
18
+ }
19
+ export declare const workflowRunAnnotationsQueryKeys: {
20
+ all: readonly ['workflow-run-annotations'];
21
+ list: (workflowRunId: string, attempt: number, jobExecutionId?: string) => readonly ["workflow-run-annotations", "list", string, number, string | null];
22
+ summary: (workflowRunId: string, attempt: number, jobExecutionId?: string) => readonly ["workflow-run-annotations", "summary", string, number, string | null];
23
+ };
24
+ export declare function workflowRunAnnotationsQueryOptions(workflowRunId: string | undefined, attempt: number | undefined, jobExecutionId?: string | undefined, options?: {
25
+ enabled?: boolean | undefined;
26
+ polling?: boolean | undefined;
27
+ }): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseInfiniteQueryOptions<WorkflowRunAnnotationsPage, Error, import("@tanstack/react-query").InfiniteData<WorkflowRunAnnotationsPage, unknown>, readonly ["workflow-run-annotations", "list"] | readonly ["workflow-run-annotations", "list", string, number, string | null], string | null>, "queryFn"> & {
28
+ queryFn?: import("@tanstack/react-query").QueryFunction<WorkflowRunAnnotationsPage, readonly ["workflow-run-annotations", "list"] | readonly ["workflow-run-annotations", "list", string, number, string | null], string | null>;
29
+ } & {
30
+ queryKey: (readonly ["workflow-run-annotations", "list"] & {
31
+ [dataTagSymbol]: import("@tanstack/react-query").InfiniteData<WorkflowRunAnnotationsPage, unknown>;
32
+ [dataTagErrorSymbol]: Error;
33
+ }) | (readonly ["workflow-run-annotations", "list", string, number, string | null] & {
34
+ [dataTagSymbol]: import("@tanstack/react-query").InfiniteData<WorkflowRunAnnotationsPage, unknown>;
35
+ [dataTagErrorSymbol]: Error;
36
+ });
37
+ };
38
+ export declare function useWorkflowRunAnnotationsQuery(workflowRunId: string | undefined, attempt: number | undefined, jobExecutionId?: string | undefined, options?: {
39
+ enabled?: boolean | undefined;
40
+ polling?: boolean | undefined;
41
+ }): import("@tanstack/react-query").UseInfiniteQueryResult<import("@tanstack/react-query").InfiniteData<WorkflowRunAnnotationsPage, unknown>, Error>;
42
+ export declare function workflowRunAnnotationSummaryQueryOptions(workflowRunId: string | undefined, attempt: number | undefined, jobExecutionId?: string | undefined, options?: {
43
+ enabled?: boolean | undefined;
44
+ polling?: boolean | undefined;
45
+ }): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<RunAnnotationSummary, Error, RunAnnotationSummary, readonly ["workflow-run-annotations", "summary"] | readonly ["workflow-run-annotations", "summary", string, number, string | null]>, "queryFn"> & {
46
+ queryFn?: import("@tanstack/react-query").QueryFunction<RunAnnotationSummary, readonly ["workflow-run-annotations", "summary"] | readonly ["workflow-run-annotations", "summary", string, number, string | null], never>;
47
+ } & {
48
+ queryKey: (readonly ["workflow-run-annotations", "summary"] & {
49
+ [dataTagSymbol]: RunAnnotationSummary;
50
+ [dataTagErrorSymbol]: Error;
51
+ }) | (readonly ["workflow-run-annotations", "summary", string, number, string | null] & {
52
+ [dataTagSymbol]: RunAnnotationSummary;
53
+ [dataTagErrorSymbol]: Error;
54
+ });
55
+ };
56
+ export declare function useWorkflowRunAnnotationSummaryQuery(workflowRunId: string | undefined, attempt: number | undefined, jobExecutionId?: string | undefined, options?: {
57
+ enabled?: boolean | undefined;
58
+ polling?: boolean | undefined;
59
+ }): import("@tanstack/react-query").UseQueryResult<NoInfer<RunAnnotationSummary>, Error>;
60
+ export declare function flattenWorkflowRunAnnotations(data: {
61
+ pages: readonly WorkflowRunAnnotationsPage[];
62
+ } | undefined): WorkflowRunAnnotation[];
63
+ //# sourceMappingURL=annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/annotations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAKlE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,+BAA+B;IAC1C,GAAG,YAAG,0BAA0B;IAChC,IAAI,kBAAkB,MAAM,WAAW,MAAM,mBAAmB,MAAM;IAQtE,OAAO,kBAAkB,MAAM,WAAW,MAAM,mBAAmB,MAAM;CAQ1E,CAAC;AAiFF,wBAAgB,kCAAkC,CAChD,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,CAAC,EAAE;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAC;;;;;;;;;;EA6BzE;AAED,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,CAAC,EAAE;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAC,oJAKzE;AAED,wBAAgB,wCAAwC,CACtD,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,CAAC,EAAE;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAC;;;;;;;;;;EAoBzE;AAED,wBAAgB,oCAAoC,CAClD,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,CAAC,EAAE;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAC,wFAKzE;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE;IAAC,KAAK,EAAE,SAAS,0BAA0B,EAAE,CAAA;CAAC,GAAG,SAAS,GAC/D,qBAAqB,EAAE,CAEzB"}
@@ -0,0 +1,145 @@
1
+ import { annotationSummaryResponseSchema, readAnnotationsResponseSchema } from '@shipfox/annotations-dto';
2
+ import { checkedApiRequest } from '@shipfox/client-api';
3
+ import { infiniteQueryOptions, queryOptions, useInfiniteQuery, useQuery } from '@tanstack/react-query';
4
+ const ANNOTATIONS_PAGE_SIZE = 100;
5
+ const ANNOTATIONS_REFRESH_INTERVAL_MS = 5_000;
6
+ export const workflowRunAnnotationsQueryKeys = {
7
+ all: [
8
+ 'workflow-run-annotations'
9
+ ],
10
+ list: (workflowRunId, attempt, jobExecutionId)=>[
11
+ ...workflowRunAnnotationsQueryKeys.all,
12
+ 'list',
13
+ workflowRunId,
14
+ attempt,
15
+ jobExecutionId ?? null
16
+ ],
17
+ summary: (workflowRunId, attempt, jobExecutionId)=>[
18
+ ...workflowRunAnnotationsQueryKeys.all,
19
+ 'summary',
20
+ workflowRunId,
21
+ attempt,
22
+ jobExecutionId ?? null
23
+ ]
24
+ };
25
+ function annotationParams({ workflowRunId, attempt, jobExecutionId, cursor }) {
26
+ const params = new URLSearchParams({
27
+ workflow_run_id: workflowRunId,
28
+ attempt: String(attempt),
29
+ limit: String(ANNOTATIONS_PAGE_SIZE)
30
+ });
31
+ if (jobExecutionId) params.set('job_execution_id', jobExecutionId);
32
+ if (cursor) params.set('cursor', cursor);
33
+ return params;
34
+ }
35
+ async function getWorkflowRunAnnotationsPage({ workflowRunId, attempt, jobExecutionId, cursor, signal }) {
36
+ const response = await checkedApiRequest(readAnnotationsResponseSchema, `/annotations?${annotationParams({
37
+ workflowRunId,
38
+ attempt,
39
+ jobExecutionId,
40
+ cursor
41
+ }).toString()}`, {
42
+ signal
43
+ });
44
+ return {
45
+ annotations: response.annotations.map(toWorkflowRunAnnotation),
46
+ hasMore: response.has_more,
47
+ nextCursor: response.next_cursor
48
+ };
49
+ }
50
+ async function getWorkflowRunAnnotationSummary({ workflowRunId, attempt, jobExecutionId, signal }) {
51
+ const params = annotationParams({
52
+ workflowRunId,
53
+ attempt,
54
+ jobExecutionId
55
+ });
56
+ params.delete('limit');
57
+ const response = await checkedApiRequest(annotationSummaryResponseSchema, `/annotations/summary?${params.toString()}`, {
58
+ signal
59
+ });
60
+ return {
61
+ total: response.total,
62
+ error: response.error,
63
+ warning: response.warning,
64
+ info: response.info,
65
+ success: response.success,
66
+ truncated: false,
67
+ stepCounts: response.step_counts.map((step)=>({
68
+ stepId: step.origin_step_id,
69
+ attempt: step.origin_step_attempt,
70
+ total: step.total
71
+ }))
72
+ };
73
+ }
74
+ export function workflowRunAnnotationsQueryOptions(workflowRunId, attempt, jobExecutionId, options) {
75
+ const enabled = Boolean(workflowRunId) && attempt !== undefined && (options?.enabled ?? true);
76
+ const polling = options?.polling ?? true;
77
+ return infiniteQueryOptions({
78
+ queryKey: workflowRunId && attempt !== undefined ? workflowRunAnnotationsQueryKeys.list(workflowRunId, attempt, jobExecutionId) : [
79
+ ...workflowRunAnnotationsQueryKeys.all,
80
+ 'list'
81
+ ],
82
+ enabled,
83
+ initialPageParam: null,
84
+ queryFn: ({ pageParam, signal })=>getWorkflowRunAnnotationsPage({
85
+ workflowRunId: workflowRunId ?? '',
86
+ attempt: attempt ?? 0,
87
+ ...jobExecutionId ? {
88
+ jobExecutionId
89
+ } : {},
90
+ cursor: pageParam,
91
+ signal
92
+ }),
93
+ getNextPageParam: (lastPage)=>lastPage.nextCursor,
94
+ staleTime: 2_000,
95
+ refetchInterval: enabled && polling ? (query)=>{
96
+ const pages = query.state.data?.pages;
97
+ return pages && pages.length > 1 ? false : ANNOTATIONS_REFRESH_INTERVAL_MS;
98
+ } : false
99
+ });
100
+ }
101
+ export function useWorkflowRunAnnotationsQuery(workflowRunId, attempt, jobExecutionId, options) {
102
+ return useInfiniteQuery(workflowRunAnnotationsQueryOptions(workflowRunId, attempt, jobExecutionId, options));
103
+ }
104
+ export function workflowRunAnnotationSummaryQueryOptions(workflowRunId, attempt, jobExecutionId, options) {
105
+ const enabled = Boolean(workflowRunId) && attempt !== undefined && (options?.enabled ?? true);
106
+ const polling = options?.polling ?? true;
107
+ return queryOptions({
108
+ queryKey: workflowRunId && attempt !== undefined ? workflowRunAnnotationsQueryKeys.summary(workflowRunId, attempt, jobExecutionId) : [
109
+ ...workflowRunAnnotationsQueryKeys.all,
110
+ 'summary'
111
+ ],
112
+ enabled,
113
+ queryFn: ({ signal })=>getWorkflowRunAnnotationSummary({
114
+ workflowRunId: workflowRunId ?? '',
115
+ attempt: attempt ?? 0,
116
+ ...jobExecutionId ? {
117
+ jobExecutionId
118
+ } : {},
119
+ signal
120
+ }),
121
+ staleTime: 2_000,
122
+ refetchInterval: enabled && polling ? ANNOTATIONS_REFRESH_INTERVAL_MS : false
123
+ });
124
+ }
125
+ export function useWorkflowRunAnnotationSummaryQuery(workflowRunId, attempt, jobExecutionId, options) {
126
+ return useQuery(workflowRunAnnotationSummaryQueryOptions(workflowRunId, attempt, jobExecutionId, options));
127
+ }
128
+ export function flattenWorkflowRunAnnotations(data) {
129
+ return data?.pages.flatMap((page)=>page.annotations) ?? [];
130
+ }
131
+ function toWorkflowRunAnnotation(annotation) {
132
+ return {
133
+ id: annotation.id,
134
+ jobId: annotation.job_id,
135
+ jobExecutionId: annotation.job_execution_id,
136
+ originStepId: annotation.origin_step_id,
137
+ originStepAttempt: annotation.origin_step_attempt,
138
+ context: annotation.context,
139
+ style: annotation.style,
140
+ sequence: annotation.sequence,
141
+ body: annotation.body
142
+ };
143
+ }
144
+
145
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/hooks/api/annotations.ts"],"sourcesContent":["import {\n type AnnotationStyleDto,\n annotationSummaryResponseSchema,\n readAnnotationsResponseSchema,\n} from '@shipfox/annotations-dto';\nimport {checkedApiRequest} from '@shipfox/client-api';\nimport {\n infiniteQueryOptions,\n queryOptions,\n useInfiniteQuery,\n useQuery,\n} from '@tanstack/react-query';\nimport type {RunAnnotationSummary} from '#core/run-annotation.js';\n\nconst ANNOTATIONS_PAGE_SIZE = 100;\nconst ANNOTATIONS_REFRESH_INTERVAL_MS = 5_000;\n\nexport interface WorkflowRunAnnotation {\n id: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n context: string;\n style: AnnotationStyleDto;\n sequence: number;\n body: string;\n}\n\nexport interface WorkflowRunAnnotationsPage {\n annotations: WorkflowRunAnnotation[];\n hasMore: boolean;\n nextCursor: string | null;\n}\n\nexport const workflowRunAnnotationsQueryKeys = {\n all: ['workflow-run-annotations'] as const,\n list: (workflowRunId: string, attempt: number, jobExecutionId?: string) =>\n [\n ...workflowRunAnnotationsQueryKeys.all,\n 'list',\n workflowRunId,\n attempt,\n jobExecutionId ?? null,\n ] as const,\n summary: (workflowRunId: string, attempt: number, jobExecutionId?: string) =>\n [\n ...workflowRunAnnotationsQueryKeys.all,\n 'summary',\n workflowRunId,\n attempt,\n jobExecutionId ?? null,\n ] as const,\n};\n\nfunction annotationParams({\n workflowRunId,\n attempt,\n jobExecutionId,\n cursor,\n}: {\n workflowRunId: string;\n attempt: number;\n jobExecutionId?: string | undefined;\n cursor?: string | null | undefined;\n}): URLSearchParams {\n const params = new URLSearchParams({\n workflow_run_id: workflowRunId,\n attempt: String(attempt),\n limit: String(ANNOTATIONS_PAGE_SIZE),\n });\n if (jobExecutionId) params.set('job_execution_id', jobExecutionId);\n if (cursor) params.set('cursor', cursor);\n return params;\n}\n\nasync function getWorkflowRunAnnotationsPage({\n workflowRunId,\n attempt,\n jobExecutionId,\n cursor,\n signal,\n}: {\n workflowRunId: string;\n attempt: number;\n jobExecutionId?: string | undefined;\n cursor?: string | null | undefined;\n signal?: AbortSignal;\n}): Promise<WorkflowRunAnnotationsPage> {\n const response = await checkedApiRequest(\n readAnnotationsResponseSchema,\n `/annotations?${annotationParams({workflowRunId, attempt, jobExecutionId, cursor}).toString()}`,\n {signal},\n );\n return {\n annotations: response.annotations.map(toWorkflowRunAnnotation),\n hasMore: response.has_more,\n nextCursor: response.next_cursor,\n };\n}\n\nasync function getWorkflowRunAnnotationSummary({\n workflowRunId,\n attempt,\n jobExecutionId,\n signal,\n}: {\n workflowRunId: string;\n attempt: number;\n jobExecutionId?: string | undefined;\n signal?: AbortSignal;\n}): Promise<RunAnnotationSummary> {\n const params = annotationParams({workflowRunId, attempt, jobExecutionId});\n params.delete('limit');\n const response = await checkedApiRequest(\n annotationSummaryResponseSchema,\n `/annotations/summary?${params.toString()}`,\n {signal},\n );\n return {\n total: response.total,\n error: response.error,\n warning: response.warning,\n info: response.info,\n success: response.success,\n truncated: false,\n stepCounts: response.step_counts.map((step) => ({\n stepId: step.origin_step_id,\n attempt: step.origin_step_attempt,\n total: step.total,\n })),\n };\n}\n\nexport function workflowRunAnnotationsQueryOptions(\n workflowRunId: string | undefined,\n attempt: number | undefined,\n jobExecutionId?: string | undefined,\n options?: {enabled?: boolean | undefined; polling?: boolean | undefined},\n) {\n const enabled = Boolean(workflowRunId) && attempt !== undefined && (options?.enabled ?? true);\n const polling = options?.polling ?? true;\n return infiniteQueryOptions({\n queryKey:\n workflowRunId && attempt !== undefined\n ? workflowRunAnnotationsQueryKeys.list(workflowRunId, attempt, jobExecutionId)\n : ([...workflowRunAnnotationsQueryKeys.all, 'list'] as const),\n enabled,\n initialPageParam: null as string | null,\n queryFn: ({pageParam, signal}) =>\n getWorkflowRunAnnotationsPage({\n workflowRunId: workflowRunId ?? '',\n attempt: attempt ?? 0,\n ...(jobExecutionId ? {jobExecutionId} : {}),\n cursor: pageParam,\n signal,\n }),\n getNextPageParam: (lastPage) => lastPage.nextCursor,\n staleTime: 2_000,\n refetchInterval:\n enabled && polling\n ? (query) => {\n const pages = query.state.data?.pages;\n return pages && pages.length > 1 ? false : ANNOTATIONS_REFRESH_INTERVAL_MS;\n }\n : false,\n });\n}\n\nexport function useWorkflowRunAnnotationsQuery(\n workflowRunId: string | undefined,\n attempt: number | undefined,\n jobExecutionId?: string | undefined,\n options?: {enabled?: boolean | undefined; polling?: boolean | undefined},\n) {\n return useInfiniteQuery(\n workflowRunAnnotationsQueryOptions(workflowRunId, attempt, jobExecutionId, options),\n );\n}\n\nexport function workflowRunAnnotationSummaryQueryOptions(\n workflowRunId: string | undefined,\n attempt: number | undefined,\n jobExecutionId?: string | undefined,\n options?: {enabled?: boolean | undefined; polling?: boolean | undefined},\n) {\n const enabled = Boolean(workflowRunId) && attempt !== undefined && (options?.enabled ?? true);\n const polling = options?.polling ?? true;\n return queryOptions({\n queryKey:\n workflowRunId && attempt !== undefined\n ? workflowRunAnnotationsQueryKeys.summary(workflowRunId, attempt, jobExecutionId)\n : ([...workflowRunAnnotationsQueryKeys.all, 'summary'] as const),\n enabled,\n queryFn: ({signal}) =>\n getWorkflowRunAnnotationSummary({\n workflowRunId: workflowRunId ?? '',\n attempt: attempt ?? 0,\n ...(jobExecutionId ? {jobExecutionId} : {}),\n signal,\n }),\n staleTime: 2_000,\n refetchInterval: enabled && polling ? ANNOTATIONS_REFRESH_INTERVAL_MS : false,\n });\n}\n\nexport function useWorkflowRunAnnotationSummaryQuery(\n workflowRunId: string | undefined,\n attempt: number | undefined,\n jobExecutionId?: string | undefined,\n options?: {enabled?: boolean | undefined; polling?: boolean | undefined},\n) {\n return useQuery(\n workflowRunAnnotationSummaryQueryOptions(workflowRunId, attempt, jobExecutionId, options),\n );\n}\n\nexport function flattenWorkflowRunAnnotations(\n data: {pages: readonly WorkflowRunAnnotationsPage[]} | undefined,\n): WorkflowRunAnnotation[] {\n return data?.pages.flatMap((page) => page.annotations) ?? [];\n}\n\nfunction toWorkflowRunAnnotation(\n annotation: Awaited<\n ReturnType<typeof readAnnotationsResponseSchema.parse>\n >['annotations'][number],\n): WorkflowRunAnnotation {\n return {\n id: annotation.id,\n jobId: annotation.job_id,\n jobExecutionId: annotation.job_execution_id,\n originStepId: annotation.origin_step_id,\n originStepAttempt: annotation.origin_step_attempt,\n context: annotation.context,\n style: annotation.style,\n sequence: annotation.sequence,\n body: annotation.body,\n };\n}\n"],"names":["annotationSummaryResponseSchema","readAnnotationsResponseSchema","checkedApiRequest","infiniteQueryOptions","queryOptions","useInfiniteQuery","useQuery","ANNOTATIONS_PAGE_SIZE","ANNOTATIONS_REFRESH_INTERVAL_MS","workflowRunAnnotationsQueryKeys","all","list","workflowRunId","attempt","jobExecutionId","summary","annotationParams","cursor","params","URLSearchParams","workflow_run_id","String","limit","set","getWorkflowRunAnnotationsPage","signal","response","toString","annotations","map","toWorkflowRunAnnotation","hasMore","has_more","nextCursor","next_cursor","getWorkflowRunAnnotationSummary","delete","total","error","warning","info","success","truncated","stepCounts","step_counts","step","stepId","origin_step_id","origin_step_attempt","workflowRunAnnotationsQueryOptions","options","enabled","Boolean","undefined","polling","queryKey","initialPageParam","queryFn","pageParam","getNextPageParam","lastPage","staleTime","refetchInterval","query","pages","state","data","length","useWorkflowRunAnnotationsQuery","workflowRunAnnotationSummaryQueryOptions","useWorkflowRunAnnotationSummaryQuery","flattenWorkflowRunAnnotations","flatMap","page","annotation","id","jobId","job_id","job_execution_id","originStepId","originStepAttempt","context","style","sequence","body"],"mappings":"AAAA,SAEEA,+BAA+B,EAC/BC,6BAA6B,QACxB,2BAA2B;AAClC,SAAQC,iBAAiB,QAAO,sBAAsB;AACtD,SACEC,oBAAoB,EACpBC,YAAY,EACZC,gBAAgB,EAChBC,QAAQ,QACH,wBAAwB;AAG/B,MAAMC,wBAAwB;AAC9B,MAAMC,kCAAkC;AAoBxC,OAAO,MAAMC,kCAAkC;IAC7CC,KAAK;QAAC;KAA2B;IACjCC,MAAM,CAACC,eAAuBC,SAAiBC,iBAC7C;eACKL,gCAAgCC,GAAG;YACtC;YACAE;YACAC;YACAC,kBAAkB;SACnB;IACHC,SAAS,CAACH,eAAuBC,SAAiBC,iBAChD;eACKL,gCAAgCC,GAAG;YACtC;YACAE;YACAC;YACAC,kBAAkB;SACnB;AACL,EAAE;AAEF,SAASE,iBAAiB,EACxBJ,aAAa,EACbC,OAAO,EACPC,cAAc,EACdG,MAAM,EAMP;IACC,MAAMC,SAAS,IAAIC,gBAAgB;QACjCC,iBAAiBR;QACjBC,SAASQ,OAAOR;QAChBS,OAAOD,OAAOd;IAChB;IACA,IAAIO,gBAAgBI,OAAOK,GAAG,CAAC,oBAAoBT;IACnD,IAAIG,QAAQC,OAAOK,GAAG,CAAC,UAAUN;IACjC,OAAOC;AACT;AAEA,eAAeM,8BAA8B,EAC3CZ,aAAa,EACbC,OAAO,EACPC,cAAc,EACdG,MAAM,EACNQ,MAAM,EAOP;IACC,MAAMC,WAAW,MAAMxB,kBACrBD,+BACA,CAAC,aAAa,EAAEe,iBAAiB;QAACJ;QAAeC;QAASC;QAAgBG;IAAM,GAAGU,QAAQ,IAAI,EAC/F;QAACF;IAAM;IAET,OAAO;QACLG,aAAaF,SAASE,WAAW,CAACC,GAAG,CAACC;QACtCC,SAASL,SAASM,QAAQ;QAC1BC,YAAYP,SAASQ,WAAW;IAClC;AACF;AAEA,eAAeC,gCAAgC,EAC7CvB,aAAa,EACbC,OAAO,EACPC,cAAc,EACdW,MAAM,EAMP;IACC,MAAMP,SAASF,iBAAiB;QAACJ;QAAeC;QAASC;IAAc;IACvEI,OAAOkB,MAAM,CAAC;IACd,MAAMV,WAAW,MAAMxB,kBACrBF,iCACA,CAAC,qBAAqB,EAAEkB,OAAOS,QAAQ,IAAI,EAC3C;QAACF;IAAM;IAET,OAAO;QACLY,OAAOX,SAASW,KAAK;QACrBC,OAAOZ,SAASY,KAAK;QACrBC,SAASb,SAASa,OAAO;QACzBC,MAAMd,SAASc,IAAI;QACnBC,SAASf,SAASe,OAAO;QACzBC,WAAW;QACXC,YAAYjB,SAASkB,WAAW,CAACf,GAAG,CAAC,CAACgB,OAAU,CAAA;gBAC9CC,QAAQD,KAAKE,cAAc;gBAC3BlC,SAASgC,KAAKG,mBAAmB;gBACjCX,OAAOQ,KAAKR,KAAK;YACnB,CAAA;IACF;AACF;AAEA,OAAO,SAASY,mCACdrC,aAAiC,EACjCC,OAA2B,EAC3BC,cAAmC,EACnCoC,OAAwE;IAExE,MAAMC,UAAUC,QAAQxC,kBAAkBC,YAAYwC,aAAcH,CAAAA,SAASC,WAAW,IAAG;IAC3F,MAAMG,UAAUJ,SAASI,WAAW;IACpC,OAAOnD,qBAAqB;QAC1BoD,UACE3C,iBAAiBC,YAAYwC,YACzB5C,gCAAgCE,IAAI,CAACC,eAAeC,SAASC,kBAC5D;eAAIL,gCAAgCC,GAAG;YAAE;SAAO;QACvDyC;QACAK,kBAAkB;QAClBC,SAAS,CAAC,EAACC,SAAS,EAAEjC,MAAM,EAAC,GAC3BD,8BAA8B;gBAC5BZ,eAAeA,iBAAiB;gBAChCC,SAASA,WAAW;gBACpB,GAAIC,iBAAiB;oBAACA;gBAAc,IAAI,CAAC,CAAC;gBAC1CG,QAAQyC;gBACRjC;YACF;QACFkC,kBAAkB,CAACC,WAAaA,SAAS3B,UAAU;QACnD4B,WAAW;QACXC,iBACEX,WAAWG,UACP,CAACS;YACC,MAAMC,QAAQD,MAAME,KAAK,CAACC,IAAI,EAAEF;YAChC,OAAOA,SAASA,MAAMG,MAAM,GAAG,IAAI,QAAQ3D;QAC7C,IACA;IACR;AACF;AAEA,OAAO,SAAS4D,+BACdxD,aAAiC,EACjCC,OAA2B,EAC3BC,cAAmC,EACnCoC,OAAwE;IAExE,OAAO7C,iBACL4C,mCAAmCrC,eAAeC,SAASC,gBAAgBoC;AAE/E;AAEA,OAAO,SAASmB,yCACdzD,aAAiC,EACjCC,OAA2B,EAC3BC,cAAmC,EACnCoC,OAAwE;IAExE,MAAMC,UAAUC,QAAQxC,kBAAkBC,YAAYwC,aAAcH,CAAAA,SAASC,WAAW,IAAG;IAC3F,MAAMG,UAAUJ,SAASI,WAAW;IACpC,OAAOlD,aAAa;QAClBmD,UACE3C,iBAAiBC,YAAYwC,YACzB5C,gCAAgCM,OAAO,CAACH,eAAeC,SAASC,kBAC/D;eAAIL,gCAAgCC,GAAG;YAAE;SAAU;QAC1DyC;QACAM,SAAS,CAAC,EAAChC,MAAM,EAAC,GAChBU,gCAAgC;gBAC9BvB,eAAeA,iBAAiB;gBAChCC,SAASA,WAAW;gBACpB,GAAIC,iBAAiB;oBAACA;gBAAc,IAAI,CAAC,CAAC;gBAC1CW;YACF;QACFoC,WAAW;QACXC,iBAAiBX,WAAWG,UAAU9C,kCAAkC;IAC1E;AACF;AAEA,OAAO,SAAS8D,qCACd1D,aAAiC,EACjCC,OAA2B,EAC3BC,cAAmC,EACnCoC,OAAwE;IAExE,OAAO5C,SACL+D,yCAAyCzD,eAAeC,SAASC,gBAAgBoC;AAErF;AAEA,OAAO,SAASqB,8BACdL,IAAgE;IAEhE,OAAOA,MAAMF,MAAMQ,QAAQ,CAACC,OAASA,KAAK7C,WAAW,KAAK,EAAE;AAC9D;AAEA,SAASE,wBACP4C,UAEwB;IAExB,OAAO;QACLC,IAAID,WAAWC,EAAE;QACjBC,OAAOF,WAAWG,MAAM;QACxB/D,gBAAgB4D,WAAWI,gBAAgB;QAC3CC,cAAcL,WAAW3B,cAAc;QACvCiC,mBAAmBN,WAAW1B,mBAAmB;QACjDiC,SAASP,WAAWO,OAAO;QAC3BC,OAAOR,WAAWQ,KAAK;QACvBC,UAAUT,WAAWS,QAAQ;QAC7BC,MAAMV,WAAWU,IAAI;IACvB;AACF"}
@@ -0,0 +1,10 @@
1
+ import type { AnnotationDto, ReadAnnotationsResponseDto } from '@shipfox/annotations-dto';
2
+ import type { RunAnnotationRecord } from '#core/run-annotation.js';
3
+ export interface RunAnnotationPage {
4
+ annotations: RunAnnotationRecord[];
5
+ hasMore: boolean;
6
+ nextCursor: string | null;
7
+ }
8
+ export declare function toRunAnnotation(dto: AnnotationDto): RunAnnotationRecord;
9
+ export declare function toRunAnnotationPage(response: ReadAnnotationsResponseDto): RunAnnotationPage;
10
+ //# sourceMappingURL=run-annotation-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-annotation-mapper.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/run-annotation-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,0BAA0B,EAAC,MAAM,0BAA0B,CAAC;AACxF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,yBAAyB,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,mBAAmB,CAYvE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,0BAA0B,GAAG,iBAAiB,CAM3F"}
@@ -0,0 +1,22 @@
1
+ export function toRunAnnotation(dto) {
2
+ return {
3
+ id: dto.id,
4
+ jobId: dto.job_id,
5
+ jobExecutionId: dto.job_execution_id,
6
+ originStepId: dto.origin_step_id,
7
+ originStepAttempt: dto.origin_step_attempt,
8
+ context: dto.context,
9
+ style: dto.style,
10
+ sequence: dto.sequence,
11
+ body: dto.body
12
+ };
13
+ }
14
+ export function toRunAnnotationPage(response) {
15
+ return {
16
+ annotations: response.annotations.map(toRunAnnotation),
17
+ hasMore: response.has_more,
18
+ nextCursor: response.next_cursor
19
+ };
20
+ }
21
+
22
+ //# sourceMappingURL=run-annotation-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/hooks/api/run-annotation-mapper.ts"],"sourcesContent":["import type {AnnotationDto, ReadAnnotationsResponseDto} from '@shipfox/annotations-dto';\nimport type {RunAnnotationRecord} from '#core/run-annotation.js';\n\nexport interface RunAnnotationPage {\n annotations: RunAnnotationRecord[];\n hasMore: boolean;\n nextCursor: string | null;\n}\n\nexport function toRunAnnotation(dto: AnnotationDto): RunAnnotationRecord {\n return {\n id: dto.id,\n jobId: dto.job_id,\n jobExecutionId: dto.job_execution_id,\n originStepId: dto.origin_step_id,\n originStepAttempt: dto.origin_step_attempt,\n context: dto.context,\n style: dto.style,\n sequence: dto.sequence,\n body: dto.body,\n };\n}\n\nexport function toRunAnnotationPage(response: ReadAnnotationsResponseDto): RunAnnotationPage {\n return {\n annotations: response.annotations.map(toRunAnnotation),\n hasMore: response.has_more,\n nextCursor: response.next_cursor,\n };\n}\n"],"names":["toRunAnnotation","dto","id","jobId","job_id","jobExecutionId","job_execution_id","originStepId","origin_step_id","originStepAttempt","origin_step_attempt","context","style","sequence","body","toRunAnnotationPage","response","annotations","map","hasMore","has_more","nextCursor","next_cursor"],"mappings":"AASA,OAAO,SAASA,gBAAgBC,GAAkB;IAChD,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVC,OAAOF,IAAIG,MAAM;QACjBC,gBAAgBJ,IAAIK,gBAAgB;QACpCC,cAAcN,IAAIO,cAAc;QAChCC,mBAAmBR,IAAIS,mBAAmB;QAC1CC,SAASV,IAAIU,OAAO;QACpBC,OAAOX,IAAIW,KAAK;QAChBC,UAAUZ,IAAIY,QAAQ;QACtBC,MAAMb,IAAIa,IAAI;IAChB;AACF;AAEA,OAAO,SAASC,oBAAoBC,QAAoC;IACtE,OAAO;QACLC,aAAaD,SAASC,WAAW,CAACC,GAAG,CAAClB;QACtCmB,SAASH,SAASI,QAAQ;QAC1BC,YAAYL,SAASM,WAAW;IAClC;AACF"}
@@ -0,0 +1,25 @@
1
+ import { type InfiniteData, type UseInfiniteQueryOptions, useInfiniteQuery } from '@tanstack/react-query';
2
+ import { type RunAnnotationRecord, type RunAnnotationSummary } from '#core/run-annotation.js';
3
+ import { type RunAnnotationPage } from './run-annotation-mapper.js';
4
+ export declare const runAnnotationsQueryKeys: {
5
+ all: readonly ['run-annotations'];
6
+ list: (workflowRunId: string, runAttempt?: number | undefined) => readonly ["run-annotations", "list", string, number | null];
7
+ };
8
+ type RunAnnotationsQueryKey = ReturnType<typeof runAnnotationsQueryKeys.list> | readonly ['run-annotations', 'list'];
9
+ type RunAnnotationsQueryOptions = UseInfiniteQueryOptions<RunAnnotationPage, Error, InfiniteData<RunAnnotationPage, string | undefined>, RunAnnotationsQueryKey, string | undefined>;
10
+ export interface RunAnnotationsQueryInput {
11
+ workflowRunId: string | undefined;
12
+ runAttempt: number | undefined;
13
+ /** Poll while the run attempt is non-terminal, then settle. */
14
+ live?: boolean | undefined;
15
+ }
16
+ export declare function runAnnotationsQueryOptions({ workflowRunId, runAttempt, live, }: RunAnnotationsQueryInput): RunAnnotationsQueryOptions;
17
+ export interface RunAnnotationsQueryResult {
18
+ query: ReturnType<typeof useInfiniteQuery<RunAnnotationPage, Error, InfiniteData<RunAnnotationPage, string | undefined>, RunAnnotationsQueryKey, string | undefined>>;
19
+ /** `undefined` until the first page resolves, so counts never render a speculative zero. */
20
+ annotations: RunAnnotationRecord[] | undefined;
21
+ summary: RunAnnotationSummary | undefined;
22
+ }
23
+ export declare function useRunAnnotationsQuery(input: RunAnnotationsQueryInput): RunAnnotationsQueryResult;
24
+ export {};
25
+ //# sourceMappingURL=run-annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-annotations.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/run-annotations.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,uBAAuB,EAC5B,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAE1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAC,KAAK,iBAAiB,EAAsB,MAAM,4BAA4B,CAAC;AAKvF,eAAO,MAAM,uBAAuB;IAClC,GAAG,YAAG,iBAAiB;IACvB,IAAI,kBAAkB,MAAM,eAAe,MAAM,GAAG,SAAS;CAE9D,CAAC;AAEF,KAAK,sBAAsB,GACvB,UAAU,CAAC,OAAO,uBAAuB,CAAC,IAAI,CAAC,GAC/C,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;AAEzC,KAAK,0BAA0B,GAAG,uBAAuB,CACvD,iBAAiB,EACjB,KAAK,EACL,YAAY,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC,EACnD,sBAAsB,EACtB,MAAM,GAAG,SAAS,CACnB,CAAC;AA2BF,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC5B;AAED,wBAAgB,0BAA0B,CAAC,EACzC,aAAa,EACb,UAAU,EACV,IAAY,GACb,EAAE,wBAAwB,GAAG,0BAA0B,CA6BvD;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,UAAU,CACf,OAAO,gBAAgB,CACrB,iBAAiB,EACjB,KAAK,EACL,YAAY,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC,EACnD,sBAAsB,EACtB,MAAM,GAAG,SAAS,CACnB,CACF,CAAC;IACF,4FAA4F;IAC5F,WAAW,EAAE,mBAAmB,EAAE,GAAG,SAAS,CAAC;IAC/C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,wBAAwB,GAAG,yBAAyB,CAiBjG"}
@@ -0,0 +1,78 @@
1
+ import { READ_ANNOTATIONS_MAX_LIMIT, readAnnotationsResponseSchema } from '@shipfox/annotations-dto';
2
+ import { checkedApiRequest } from '@shipfox/client-api';
3
+ import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/react-query';
4
+ import { useMemo } from 'react';
5
+ import { summarizeRunAnnotations } from '#core/run-annotation.js';
6
+ import { toRunAnnotationPage } from './run-annotation-mapper.js';
7
+ /** Matches the run detail poll, so annotations and run state never disagree by more than a tick. */ const ACTIVE_POLL_MS = 4_000;
8
+ export const runAnnotationsQueryKeys = {
9
+ all: [
10
+ 'run-annotations'
11
+ ],
12
+ list: (workflowRunId, runAttempt)=>[
13
+ ...runAnnotationsQueryKeys.all,
14
+ 'list',
15
+ workflowRunId,
16
+ runAttempt ?? null
17
+ ]
18
+ };
19
+ async function listRunAnnotations({ workflowRunId, runAttempt, cursor, signal }) {
20
+ const params = new URLSearchParams({
21
+ workflow_run_id: workflowRunId,
22
+ attempt: String(runAttempt),
23
+ limit: String(READ_ANNOTATIONS_MAX_LIMIT)
24
+ });
25
+ if (cursor) params.set('cursor', cursor);
26
+ return toRunAnnotationPage(await checkedApiRequest(readAnnotationsResponseSchema, `/annotations?${params.toString()}`, {
27
+ signal
28
+ }));
29
+ }
30
+ export function runAnnotationsQueryOptions({ workflowRunId, runAttempt, live = false }) {
31
+ const enabled = Boolean(workflowRunId) && runAttempt !== undefined;
32
+ // Polling stops once the reader has paged past the first page: the cursor bounding page 2 was
33
+ // computed from page 1's last row, so a refetch that shifts that boundary can drop a range of
34
+ // annotations into a between-pages gap.
35
+ return infiniteQueryOptions({
36
+ queryKey: workflowRunId ? runAnnotationsQueryKeys.list(workflowRunId, runAttempt) : [
37
+ ...runAnnotationsQueryKeys.all,
38
+ 'list'
39
+ ],
40
+ enabled,
41
+ initialPageParam: undefined,
42
+ queryFn: ({ pageParam, signal })=>listRunAnnotations({
43
+ workflowRunId: workflowRunId ?? '',
44
+ runAttempt: runAttempt ?? 1,
45
+ cursor: pageParam,
46
+ signal
47
+ }),
48
+ getNextPageParam: (lastPage)=>lastPage.nextCursor ?? undefined,
49
+ staleTime: 2_000,
50
+ refetchOnWindowFocus: true,
51
+ refetchInterval: (query)=>{
52
+ if (!live) return false;
53
+ const pages = query.state.data?.pages;
54
+ return pages && pages.length > 1 ? false : ACTIVE_POLL_MS;
55
+ },
56
+ refetchIntervalInBackground: false
57
+ });
58
+ }
59
+ export function useRunAnnotationsQuery(input) {
60
+ const query = useInfiniteQuery(runAnnotationsQueryOptions(input));
61
+ const pages = query.data?.pages;
62
+ const annotations = useMemo(()=>pages ? pages.flatMap((page)=>page.annotations) : undefined, [
63
+ pages
64
+ ]);
65
+ const summary = useMemo(()=>annotations ? summarizeRunAnnotations(annotations, {
66
+ truncated: pages?.at(-1)?.hasMore ?? false
67
+ }) : undefined, [
68
+ annotations,
69
+ pages
70
+ ]);
71
+ return {
72
+ query,
73
+ annotations,
74
+ summary
75
+ };
76
+ }
77
+
78
+ //# sourceMappingURL=run-annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/hooks/api/run-annotations.ts"],"sourcesContent":["import {READ_ANNOTATIONS_MAX_LIMIT, readAnnotationsResponseSchema} from '@shipfox/annotations-dto';\nimport {checkedApiRequest} from '@shipfox/client-api';\nimport {\n type InfiniteData,\n infiniteQueryOptions,\n type UseInfiniteQueryOptions,\n useInfiniteQuery,\n} from '@tanstack/react-query';\nimport {useMemo} from 'react';\nimport {\n type RunAnnotationRecord,\n type RunAnnotationSummary,\n summarizeRunAnnotations,\n} from '#core/run-annotation.js';\nimport {type RunAnnotationPage, toRunAnnotationPage} from './run-annotation-mapper.js';\n\n/** Matches the run detail poll, so annotations and run state never disagree by more than a tick. */\nconst ACTIVE_POLL_MS = 4_000;\n\nexport const runAnnotationsQueryKeys = {\n all: ['run-annotations'] as const,\n list: (workflowRunId: string, runAttempt?: number | undefined) =>\n [...runAnnotationsQueryKeys.all, 'list', workflowRunId, runAttempt ?? null] as const,\n};\n\ntype RunAnnotationsQueryKey =\n | ReturnType<typeof runAnnotationsQueryKeys.list>\n | readonly ['run-annotations', 'list'];\n\ntype RunAnnotationsQueryOptions = UseInfiniteQueryOptions<\n RunAnnotationPage,\n Error,\n InfiniteData<RunAnnotationPage, string | undefined>,\n RunAnnotationsQueryKey,\n string | undefined\n>;\n\nasync function listRunAnnotations({\n workflowRunId,\n runAttempt,\n cursor,\n signal,\n}: {\n workflowRunId: string;\n runAttempt: number;\n cursor?: string | undefined;\n signal?: AbortSignal;\n}): Promise<RunAnnotationPage> {\n const params = new URLSearchParams({\n workflow_run_id: workflowRunId,\n attempt: String(runAttempt),\n limit: String(READ_ANNOTATIONS_MAX_LIMIT),\n });\n if (cursor) params.set('cursor', cursor);\n\n return toRunAnnotationPage(\n await checkedApiRequest(readAnnotationsResponseSchema, `/annotations?${params.toString()}`, {\n signal,\n }),\n );\n}\n\nexport interface RunAnnotationsQueryInput {\n workflowRunId: string | undefined;\n runAttempt: number | undefined;\n /** Poll while the run attempt is non-terminal, then settle. */\n live?: boolean | undefined;\n}\n\nexport function runAnnotationsQueryOptions({\n workflowRunId,\n runAttempt,\n live = false,\n}: RunAnnotationsQueryInput): RunAnnotationsQueryOptions {\n const enabled = Boolean(workflowRunId) && runAttempt !== undefined;\n\n // Polling stops once the reader has paged past the first page: the cursor bounding page 2 was\n // computed from page 1's last row, so a refetch that shifts that boundary can drop a range of\n // annotations into a between-pages gap.\n return infiniteQueryOptions({\n queryKey: workflowRunId\n ? runAnnotationsQueryKeys.list(workflowRunId, runAttempt)\n : ([...runAnnotationsQueryKeys.all, 'list'] as const),\n enabled,\n initialPageParam: undefined as string | undefined,\n queryFn: ({pageParam, signal}) =>\n listRunAnnotations({\n workflowRunId: workflowRunId ?? '',\n runAttempt: runAttempt ?? 1,\n cursor: pageParam,\n signal,\n }),\n getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,\n staleTime: 2_000,\n refetchOnWindowFocus: true,\n refetchInterval: (query) => {\n if (!live) return false;\n const pages = query.state.data?.pages;\n return pages && pages.length > 1 ? false : ACTIVE_POLL_MS;\n },\n refetchIntervalInBackground: false,\n });\n}\n\nexport interface RunAnnotationsQueryResult {\n query: ReturnType<\n typeof useInfiniteQuery<\n RunAnnotationPage,\n Error,\n InfiniteData<RunAnnotationPage, string | undefined>,\n RunAnnotationsQueryKey,\n string | undefined\n >\n >;\n /** `undefined` until the first page resolves, so counts never render a speculative zero. */\n annotations: RunAnnotationRecord[] | undefined;\n summary: RunAnnotationSummary | undefined;\n}\n\nexport function useRunAnnotationsQuery(input: RunAnnotationsQueryInput): RunAnnotationsQueryResult {\n const query = useInfiniteQuery(runAnnotationsQueryOptions(input));\n const pages = query.data?.pages;\n\n const annotations = useMemo(\n () => (pages ? pages.flatMap((page) => page.annotations) : undefined),\n [pages],\n );\n const summary = useMemo(\n () =>\n annotations\n ? summarizeRunAnnotations(annotations, {truncated: pages?.at(-1)?.hasMore ?? false})\n : undefined,\n [annotations, pages],\n );\n\n return {query, annotations, summary};\n}\n"],"names":["READ_ANNOTATIONS_MAX_LIMIT","readAnnotationsResponseSchema","checkedApiRequest","infiniteQueryOptions","useInfiniteQuery","useMemo","summarizeRunAnnotations","toRunAnnotationPage","ACTIVE_POLL_MS","runAnnotationsQueryKeys","all","list","workflowRunId","runAttempt","listRunAnnotations","cursor","signal","params","URLSearchParams","workflow_run_id","attempt","String","limit","set","toString","runAnnotationsQueryOptions","live","enabled","Boolean","undefined","queryKey","initialPageParam","queryFn","pageParam","getNextPageParam","lastPage","nextCursor","staleTime","refetchOnWindowFocus","refetchInterval","query","pages","state","data","length","refetchIntervalInBackground","useRunAnnotationsQuery","input","annotations","flatMap","page","summary","truncated","at","hasMore"],"mappings":"AAAA,SAAQA,0BAA0B,EAAEC,6BAA6B,QAAO,2BAA2B;AACnG,SAAQC,iBAAiB,QAAO,sBAAsB;AACtD,SAEEC,oBAAoB,EAEpBC,gBAAgB,QACX,wBAAwB;AAC/B,SAAQC,OAAO,QAAO,QAAQ;AAC9B,SAGEC,uBAAuB,QAClB,0BAA0B;AACjC,SAAgCC,mBAAmB,QAAO,6BAA6B;AAEvF,kGAAkG,GAClG,MAAMC,iBAAiB;AAEvB,OAAO,MAAMC,0BAA0B;IACrCC,KAAK;QAAC;KAAkB;IACxBC,MAAM,CAACC,eAAuBC,aAC5B;eAAIJ,wBAAwBC,GAAG;YAAE;YAAQE;YAAeC,cAAc;SAAK;AAC/E,EAAE;AAcF,eAAeC,mBAAmB,EAChCF,aAAa,EACbC,UAAU,EACVE,MAAM,EACNC,MAAM,EAMP;IACC,MAAMC,SAAS,IAAIC,gBAAgB;QACjCC,iBAAiBP;QACjBQ,SAASC,OAAOR;QAChBS,OAAOD,OAAOrB;IAChB;IACA,IAAIe,QAAQE,OAAOM,GAAG,CAAC,UAAUR;IAEjC,OAAOR,oBACL,MAAML,kBAAkBD,+BAA+B,CAAC,aAAa,EAAEgB,OAAOO,QAAQ,IAAI,EAAE;QAC1FR;IACF;AAEJ;AASA,OAAO,SAASS,2BAA2B,EACzCb,aAAa,EACbC,UAAU,EACVa,OAAO,KAAK,EACa;IACzB,MAAMC,UAAUC,QAAQhB,kBAAkBC,eAAegB;IAEzD,8FAA8F;IAC9F,8FAA8F;IAC9F,wCAAwC;IACxC,OAAO1B,qBAAqB;QAC1B2B,UAAUlB,gBACNH,wBAAwBE,IAAI,CAACC,eAAeC,cAC3C;eAAIJ,wBAAwBC,GAAG;YAAE;SAAO;QAC7CiB;QACAI,kBAAkBF;QAClBG,SAAS,CAAC,EAACC,SAAS,EAAEjB,MAAM,EAAC,GAC3BF,mBAAmB;gBACjBF,eAAeA,iBAAiB;gBAChCC,YAAYA,cAAc;gBAC1BE,QAAQkB;gBACRjB;YACF;QACFkB,kBAAkB,CAACC,WAAaA,SAASC,UAAU,IAAIP;QACvDQ,WAAW;QACXC,sBAAsB;QACtBC,iBAAiB,CAACC;YAChB,IAAI,CAACd,MAAM,OAAO;YAClB,MAAMe,QAAQD,MAAME,KAAK,CAACC,IAAI,EAAEF;YAChC,OAAOA,SAASA,MAAMG,MAAM,GAAG,IAAI,QAAQpC;QAC7C;QACAqC,6BAA6B;IAC/B;AACF;AAiBA,OAAO,SAASC,uBAAuBC,KAA+B;IACpE,MAAMP,QAAQpC,iBAAiBqB,2BAA2BsB;IAC1D,MAAMN,QAAQD,MAAMG,IAAI,EAAEF;IAE1B,MAAMO,cAAc3C,QAClB,IAAOoC,QAAQA,MAAMQ,OAAO,CAAC,CAACC,OAASA,KAAKF,WAAW,IAAInB,WAC3D;QAACY;KAAM;IAET,MAAMU,UAAU9C,QACd,IACE2C,cACI1C,wBAAwB0C,aAAa;YAACI,WAAWX,OAAOY,GAAG,CAAC,IAAIC,WAAW;QAAK,KAChFzB,WACN;QAACmB;QAAaP;KAAM;IAGtB,OAAO;QAACD;QAAOQ;QAAaG;IAAO;AACrC"}