@ryanfw/prompt-orchestration-pipeline 1.3.2 → 1.3.4

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 (206) hide show
  1. package/docs/http-api.md +80 -4
  2. package/package.json +1 -4
  3. package/src/api/__tests__/index.test.ts +443 -32
  4. package/src/api/index.ts +108 -127
  5. package/src/cli/__tests__/analyze-task.test.ts +40 -7
  6. package/src/cli/__tests__/index.test.ts +337 -17
  7. package/src/cli/__tests__/types.test.ts +0 -18
  8. package/src/cli/__tests__/update-pipeline-json.test.ts +19 -9
  9. package/src/cli/analyze-task.ts +3 -14
  10. package/src/cli/index.ts +73 -61
  11. package/src/cli/types.ts +0 -13
  12. package/src/cli/update-pipeline-json.ts +3 -14
  13. package/src/config/__tests__/paths.test.ts +46 -1
  14. package/src/config/__tests__/pipeline-registry.test.ts +767 -0
  15. package/src/config/__tests__/sse-events.test.ts +470 -0
  16. package/src/config/__tests__/statuses.test.ts +41 -0
  17. package/src/config/paths.ts +11 -2
  18. package/src/config/pipeline-registry.ts +258 -0
  19. package/src/config/sse-events.ts +122 -0
  20. package/src/config/statuses.ts +20 -1
  21. package/src/core/__tests__/agent-step.test.ts +115 -0
  22. package/src/core/__tests__/config.test.ts +545 -105
  23. package/src/core/__tests__/core-boot-resolution.test.ts +181 -0
  24. package/src/core/__tests__/job-concurrency.test.ts +260 -0
  25. package/src/core/__tests__/job-submission.test.ts +396 -0
  26. package/src/core/__tests__/job-view.test.ts +1341 -0
  27. package/src/core/__tests__/json-file.test.ts +111 -0
  28. package/src/core/__tests__/lifecycle-policy.test.ts +81 -7
  29. package/src/core/__tests__/logger.test.ts +22 -0
  30. package/src/core/__tests__/orchestrator-no-deprecated-exports.test.ts +41 -0
  31. package/src/core/__tests__/orchestrator.test.ts +615 -2
  32. package/src/core/__tests__/pipeline-runner.test.ts +946 -9
  33. package/src/core/__tests__/redact.test.ts +153 -0
  34. package/src/core/__tests__/runner-liveness.test.ts +910 -0
  35. package/src/core/__tests__/seed-naming.test.ts +57 -0
  36. package/src/core/__tests__/single-derivation.test.ts +159 -0
  37. package/src/core/__tests__/task-runner.test.ts +594 -3
  38. package/src/core/__tests__/task-telemetry.test.ts +241 -0
  39. package/src/core/__tests__/workspace-root-resolution-guard.test.ts +62 -0
  40. package/src/core/agent-step.ts +4 -1
  41. package/src/core/agent-types.ts +5 -4
  42. package/src/core/config.ts +134 -222
  43. package/src/core/control.ts +3 -0
  44. package/src/core/job-concurrency.ts +56 -20
  45. package/src/core/job-submission.ts +133 -0
  46. package/src/core/job-view.ts +473 -0
  47. package/src/core/json-file.ts +45 -0
  48. package/src/core/lifecycle-policy.ts +23 -8
  49. package/src/core/logger.ts +0 -29
  50. package/src/core/orchestrator.ts +200 -74
  51. package/src/core/pipeline-runner.ts +85 -53
  52. package/src/core/redact.ts +40 -0
  53. package/src/core/runner-liveness.ts +280 -0
  54. package/src/core/seed-naming.ts +9 -0
  55. package/src/core/status-writer.ts +27 -33
  56. package/src/core/task-runner.ts +356 -319
  57. package/src/core/task-telemetry.ts +107 -0
  58. package/src/harness/__tests__/subprocess.test.ts +112 -1
  59. package/src/harness/subprocess.ts +55 -16
  60. package/src/llm/__tests__/index.test.ts +684 -33
  61. package/src/llm/index.ts +310 -67
  62. package/src/providers/__tests__/alibaba.test.ts +67 -6
  63. package/src/providers/__tests__/anthropic.test.ts +35 -14
  64. package/src/providers/__tests__/base.test.ts +62 -0
  65. package/src/providers/__tests__/claude-code.test.ts +99 -14
  66. package/src/providers/__tests__/deepseek.test.ts +16 -6
  67. package/src/providers/__tests__/gemini.test.ts +47 -25
  68. package/src/providers/__tests__/moonshot.test.ts +27 -0
  69. package/src/providers/__tests__/openai.test.ts +262 -74
  70. package/src/providers/__tests__/opencode.test.ts +77 -0
  71. package/src/providers/__tests__/request-timeout-contract.test.ts +226 -0
  72. package/src/providers/__tests__/stream-accumulator.test.ts +52 -0
  73. package/src/providers/__tests__/types.test.ts +85 -0
  74. package/src/providers/__tests__/zero-fill-guard.test.ts +62 -0
  75. package/src/providers/__tests__/zhipu.test.ts +27 -14
  76. package/src/providers/alibaba.ts +20 -39
  77. package/src/providers/anthropic.ts +23 -11
  78. package/src/providers/base.ts +19 -0
  79. package/src/providers/claude-code.ts +27 -18
  80. package/src/providers/deepseek.ts +9 -28
  81. package/src/providers/gemini.ts +20 -58
  82. package/src/providers/moonshot.ts +15 -11
  83. package/src/providers/openai.ts +79 -61
  84. package/src/providers/opencode.ts +16 -33
  85. package/src/providers/stream-accumulator.ts +27 -21
  86. package/src/providers/types.ts +29 -4
  87. package/src/providers/zhipu.ts +15 -44
  88. package/src/task-analysis/__tests__/analyzer.test.ts +0 -0
  89. package/src/task-analysis/__tests__/enrichers-schema-deducer.test.ts +34 -2
  90. package/src/task-analysis/__tests__/no-ast-imports.test.ts +52 -0
  91. package/src/task-analysis/__tests__/repository.test.ts +65 -0
  92. package/src/task-analysis/__tests__/types.test.ts +63 -130
  93. package/src/task-analysis/analyzer.ts +91 -0
  94. package/src/task-analysis/enrichers/schema-deducer.ts +13 -2
  95. package/src/task-analysis/index.ts +2 -36
  96. package/src/task-analysis/repository.ts +45 -0
  97. package/src/task-analysis/types.ts +42 -58
  98. package/src/ui/client/__tests__/api.test.ts +143 -1
  99. package/src/ui/client/__tests__/bootstrap.test.ts +178 -62
  100. package/src/ui/client/__tests__/job-adapter.test.ts +203 -2
  101. package/src/ui/client/__tests__/load-state.test.ts +70 -0
  102. package/src/ui/client/__tests__/types.test.ts +66 -3
  103. package/src/ui/client/__tests__/useJobDetailWithUpdates.test.ts +390 -77
  104. package/src/ui/client/__tests__/useJobList.test.ts +198 -23
  105. package/src/ui/client/__tests__/useJobListWithUpdates.test.ts +218 -7
  106. package/src/ui/client/adapters/__tests__/job-adapter.test.ts +186 -0
  107. package/src/ui/client/adapters/job-adapter.ts +41 -16
  108. package/src/ui/client/api.ts +38 -15
  109. package/src/ui/client/bootstrap.ts +19 -14
  110. package/src/ui/client/hooks/useJobDetailWithUpdates.ts +73 -97
  111. package/src/ui/client/hooks/useJobList.ts +26 -31
  112. package/src/ui/client/hooks/useJobListWithUpdates.ts +42 -76
  113. package/src/ui/client/load-state.ts +20 -0
  114. package/src/ui/client/reducers/__tests__/job-events.test.ts +568 -0
  115. package/src/ui/client/reducers/job-events.ts +137 -0
  116. package/src/ui/client/types.ts +16 -20
  117. package/src/ui/components/DAGGrid.tsx +6 -1
  118. package/src/ui/components/JobDetail.tsx +12 -4
  119. package/src/ui/components/JobTable.tsx +41 -13
  120. package/src/ui/components/StageTimeline.tsx +8 -20
  121. package/src/ui/components/TaskAnalysisDisplay.tsx +48 -6
  122. package/src/ui/components/__tests__/DAGGrid.test.tsx +36 -0
  123. package/src/ui/components/__tests__/JobDetail.test.tsx +112 -0
  124. package/src/ui/components/__tests__/JobTable.test.tsx +137 -1
  125. package/src/ui/components/__tests__/StageTimeline.test.tsx +5 -6
  126. package/src/ui/components/__tests__/TaskAnalysisDisplay.test.tsx +64 -0
  127. package/src/ui/components/types.ts +35 -15
  128. package/src/ui/dist/assets/{index--RH3sAt3.js → index-DN3-zvtP.js} +4324 -263
  129. package/src/ui/dist/assets/index-DN3-zvtP.js.map +1 -0
  130. package/src/ui/dist/assets/style-CtZBnjlR.css +2 -0
  131. package/src/ui/dist/index.html +2 -2
  132. package/src/ui/pages/PipelineDetail.tsx +60 -4
  133. package/src/ui/pages/PromptPipelineDashboard.tsx +59 -7
  134. package/src/ui/pages/__tests__/PromptPipelineDashboard.test.tsx +114 -32
  135. package/src/ui/pages/__tests__/pages.test.tsx +236 -42
  136. package/src/ui/server/__tests__/concurrency-endpoint.test.ts +54 -0
  137. package/src/ui/server/__tests__/config-bridge-node.test.ts +34 -1
  138. package/src/ui/server/__tests__/config-bridge.test.ts +9 -1
  139. package/src/ui/server/__tests__/embedded-assets.test.ts +66 -0
  140. package/src/ui/server/__tests__/file-endpoints.test.ts +183 -5
  141. package/src/ui/server/__tests__/gate-endpoints.test.ts +55 -0
  142. package/src/ui/server/__tests__/index.test.ts +63 -0
  143. package/src/ui/server/__tests__/job-control-endpoints.test.ts +512 -2
  144. package/src/ui/server/__tests__/job-endpoints.test.ts +158 -2
  145. package/src/ui/server/__tests__/read-static-path-guard.test.ts +94 -0
  146. package/src/ui/server/__tests__/router-root-isolation.test.ts +204 -0
  147. package/src/ui/server/__tests__/router-threading.test.ts +148 -0
  148. package/src/ui/server/__tests__/router.test.ts +104 -0
  149. package/src/ui/server/__tests__/sse-broadcast.test.ts +44 -0
  150. package/src/ui/server/__tests__/sse-enhancer.test.ts +70 -0
  151. package/src/ui/server/config-bridge-node.ts +8 -26
  152. package/src/ui/server/config-bridge.ts +3 -4
  153. package/src/ui/server/embedded-assets-imports.d.ts +44 -0
  154. package/src/ui/server/embedded-assets.ts +13 -2
  155. package/src/ui/server/endpoints/__tests__/meta-endpoint.test.ts +1 -0
  156. package/src/ui/server/endpoints/__tests__/pipeline-analysis-endpoint.test.ts +167 -0
  157. package/src/ui/server/endpoints/__tests__/schema-file-endpoint.test.ts +104 -0
  158. package/src/ui/server/endpoints/__tests__/task-analysis-endpoint.test.ts +103 -0
  159. package/src/ui/server/endpoints/__tests__/upload-endpoints.test.ts +162 -96
  160. package/src/ui/server/endpoints/concurrency-endpoint.ts +2 -1
  161. package/src/ui/server/endpoints/create-pipeline-endpoint.ts +14 -29
  162. package/src/ui/server/endpoints/file-endpoints.ts +15 -10
  163. package/src/ui/server/endpoints/gate-endpoints.ts +2 -6
  164. package/src/ui/server/endpoints/job-control-endpoints.ts +129 -141
  165. package/src/ui/server/endpoints/job-endpoints.ts +7 -0
  166. package/src/ui/server/endpoints/meta-endpoint.ts +1 -1
  167. package/src/ui/server/endpoints/pipeline-analysis-endpoint.ts +99 -11
  168. package/src/ui/server/endpoints/schema-file-endpoint.ts +11 -3
  169. package/src/ui/server/endpoints/task-analysis-endpoint.ts +21 -5
  170. package/src/ui/server/endpoints/task-save-endpoint.ts +1 -2
  171. package/src/ui/server/endpoints/upload-endpoints.ts +5 -40
  172. package/src/ui/server/index.ts +19 -14
  173. package/src/ui/server/job-reader.ts +14 -2
  174. package/src/ui/server/router.ts +33 -10
  175. package/src/ui/server/sse-broadcast.ts +14 -3
  176. package/src/ui/server/sse-enhancer.ts +12 -2
  177. package/src/ui/state/__tests__/schema-loader.test.ts +11 -1
  178. package/src/ui/state/__tests__/snapshot.test.ts +120 -14
  179. package/src/ui/state/__tests__/types.test.ts +104 -5
  180. package/src/ui/state/snapshot.ts +2 -2
  181. package/src/ui/state/transformers/__tests__/list-transformer.test.ts +85 -2
  182. package/src/ui/state/transformers/__tests__/status-transformer.test.ts +250 -22
  183. package/src/ui/state/transformers/list-transformer.ts +13 -3
  184. package/src/ui/state/transformers/status-transformer.ts +36 -170
  185. package/src/ui/state/types.ts +15 -48
  186. package/src/utils/__tests__/path-containment.test.ts +160 -0
  187. package/src/{ui/server/utils → utils}/path-containment.ts +21 -0
  188. package/src/task-analysis/__tests__/enrichers-analysis-writer.test.ts +0 -86
  189. package/src/task-analysis/__tests__/enrichers-artifact-resolver.test.ts +0 -124
  190. package/src/task-analysis/__tests__/extractors-artifacts.test.ts +0 -133
  191. package/src/task-analysis/__tests__/extractors-llm-calls.test.ts +0 -46
  192. package/src/task-analysis/__tests__/extractors-stages.test.ts +0 -52
  193. package/src/task-analysis/__tests__/index.test.ts +0 -143
  194. package/src/task-analysis/__tests__/parser.test.ts +0 -41
  195. package/src/task-analysis/__tests__/utils-ast.test.ts +0 -82
  196. package/src/task-analysis/enrichers/analysis-writer.ts +0 -75
  197. package/src/task-analysis/enrichers/artifact-resolver.ts +0 -89
  198. package/src/task-analysis/extractors/artifacts.ts +0 -143
  199. package/src/task-analysis/extractors/llm-calls.ts +0 -117
  200. package/src/task-analysis/extractors/stages.ts +0 -45
  201. package/src/task-analysis/parser.ts +0 -20
  202. package/src/task-analysis/utils/ast.ts +0 -45
  203. package/src/ui/dist/assets/index--RH3sAt3.js.map +0 -1
  204. package/src/ui/dist/assets/style-CSSKuMOe.css +0 -2
  205. package/src/ui/embedded-assets.js +0 -12
  206. package/src/ui/server/__tests__/path-containment.test.ts +0 -54
@@ -1,29 +1,31 @@
1
1
  import { useEffect, useRef, useState } from "react";
2
2
 
3
- import { adaptJobSummary } from "../adapters/job-adapter";
3
+ import { parseSseEvent, type SseEvent } from "../../../config/sse-events.ts";
4
4
  import { useJobList } from "./useJobList";
5
+ import { applyJobEvent } from "../reducers/job-events.ts";
5
6
  import type {
6
7
  ConnectionStatus,
7
8
  NormalizedJobSummary,
8
- SseJobEvent,
9
9
  UseJobListWithUpdatesResult,
10
10
  } from "../types";
11
11
 
12
- const REFETCH_EVENTS = new Set(["seed:uploaded", "state:change", "state:summary"]);
12
+ export { applyJobEvent };
13
+
14
+ const REFETCH_EVENTS = new Set<SseEvent["type"]>(["seed:uploaded", "state:change", "state:summary"]);
13
15
  const RECONNECT_DELAY_MS = 2_000;
14
16
  const REFETCH_DEBOUNCE_MS = 300;
15
17
 
16
- function sortNormalizedJobs(jobs: NormalizedJobSummary[]): NormalizedJobSummary[] {
17
- const priority: Record<string, number> = {
18
- running: 4,
19
- waiting: 4,
20
- failed: 3,
21
- pending: 2,
22
- complete: 1,
23
- };
18
+ const STATUS_PRIORITY: Record<string, number> = {
19
+ running: 4,
20
+ waiting: 4,
21
+ failed: 3,
22
+ pending: 2,
23
+ complete: 1,
24
+ };
24
25
 
26
+ function sortNormalizedJobs(jobs: NormalizedJobSummary[]): NormalizedJobSummary[] {
25
27
  return jobs.slice().sort((left, right) => {
26
- const statusOrder = (priority[right.status] ?? 0) - (priority[left.status] ?? 0);
28
+ const statusOrder = (STATUS_PRIORITY[right.status] ?? 0) - (STATUS_PRIORITY[left.status] ?? 0);
27
29
  if (statusOrder !== 0) return statusOrder;
28
30
  const leftCreated = left.createdAt ?? "";
29
31
  const rightCreated = right.createdAt ?? "";
@@ -33,67 +35,37 @@ function sortNormalizedJobs(jobs: NormalizedJobSummary[]): NormalizedJobSummary[
33
35
  });
34
36
  }
35
37
 
36
- function completedCountFromTasks(job: NormalizedJobSummary): number {
37
- return Object.values(job.tasks).filter((task) => task.state === "done" || task.state === "skipped").length;
38
+ export function shouldRefetchForListEvent(type: SseEvent["type"]): boolean {
39
+ return REFETCH_EVENTS.has(type);
38
40
  }
39
41
 
40
- function comparableJob(job: NormalizedJobSummary): Record<string, unknown> {
41
- const comparable: Record<string, unknown> = { ...job };
42
- for (const [key, value] of Object.entries(comparable)) {
43
- if (value === undefined) delete comparable[key];
42
+ export type ListMessageAction =
43
+ | { kind: "refetch" }
44
+ | { kind: "apply"; event: SseEvent };
45
+
46
+ export function handleListSseMessage(
47
+ type: string,
48
+ rawData: string,
49
+ ): ListMessageAction {
50
+ let parsedData: unknown;
51
+ try {
52
+ parsedData = JSON.parse(rawData);
53
+ } catch (error) {
54
+ console.warn("useJobListWithUpdates: failed to parse SSE payload", error);
55
+ return { kind: "refetch" };
44
56
  }
45
- if (comparable["completedCount"] === completedCountFromTasks(job)) {
46
- delete comparable["completedCount"];
47
- }
48
- return comparable;
49
- }
50
57
 
51
- function jobsEqual(left: NormalizedJobSummary[], right: NormalizedJobSummary[]): boolean {
52
- return JSON.stringify(left.map(comparableJob)) === JSON.stringify(right.map(comparableJob));
53
- }
54
-
55
- function mergeJob(current: NormalizedJobSummary, incoming: NormalizedJobSummary): NormalizedJobSummary {
56
- return {
57
- ...current,
58
- ...incoming,
59
- id: incoming.id || current.id,
60
- jobId: incoming.jobId || current.jobId,
61
- name: incoming.name || current.name,
62
- createdAt: incoming.createdAt ?? current.createdAt,
63
- updatedAt: incoming.updatedAt ?? current.updatedAt,
64
- pipeline: incoming.pipeline ?? current.pipeline,
65
- pipelineLabel: incoming.pipelineLabel ?? current.pipelineLabel,
66
- current: incoming.current ?? current.current,
67
- currentStage: incoming.currentStage ?? current.currentStage,
68
- };
69
- }
70
-
71
- export function applyJobEvent(
72
- jobs: NormalizedJobSummary[],
73
- event: SseJobEvent,
74
- ): NormalizedJobSummary[] {
75
- const incoming = adaptJobSummary(event.data);
76
- const key = incoming.jobId;
77
-
78
- if (event.type === "job:removed") {
79
- const next = jobs.filter((job) => job.jobId !== key);
80
- return jobsEqual(next, jobs) ? jobs : sortNormalizedJobs(next);
58
+ const event = parseSseEvent(type, parsedData);
59
+ if (event === null) {
60
+ console.warn(`useJobListWithUpdates: dropping invalid SSE event of type "${type}"`);
61
+ return { kind: "refetch" };
81
62
  }
82
63
 
83
- if (event.type === "job:created" || event.type === "job:updated") {
84
- const existingIndex = jobs.findIndex((job) => job.jobId === key);
85
- const next = existingIndex === -1
86
- ? [...jobs, incoming]
87
- : jobs.map((job, index) => index === existingIndex ? mergeJob(job, incoming) : job);
88
- const sorted = sortNormalizedJobs(next);
89
- return jobsEqual(sorted, jobs) ? jobs : sorted;
64
+ if (shouldRefetchForListEvent(event.type)) {
65
+ return { kind: "refetch" };
90
66
  }
91
67
 
92
- return jobs;
93
- }
94
-
95
- export function shouldRefetchForListEvent(type: string): boolean {
96
- return REFETCH_EVENTS.has(type);
68
+ return { kind: "apply", event };
97
69
  }
98
70
 
99
71
  export function useJobListWithUpdates(): UseJobListWithUpdatesResult {
@@ -102,7 +74,7 @@ export function useJobListWithUpdates(): UseJobListWithUpdatesResult {
102
74
  const [connectionStatus, setConnectionStatus] = useState<ConnectionStatus>("disconnected");
103
75
  const hydratedRef = useRef(false);
104
76
  const dataRef = useRef<NormalizedJobSummary[] | null>(null);
105
- const queueRef = useRef<SseJobEvent[]>([]);
77
+ const queueRef = useRef<SseEvent[]>([]);
106
78
  const eventSourceRef = useRef<EventSource | null>(null);
107
79
  const reconnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
108
80
  const refetchTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -155,27 +127,21 @@ export function useJobListWithUpdates(): UseJobListWithUpdatesResult {
155
127
  };
156
128
 
157
129
  const onMessage = (event: MessageEvent<string>) => {
158
- let payload: SseJobEvent | null = null;
159
- try {
160
- payload = { type: event.type as SseJobEvent["type"], data: JSON.parse(event.data) as Record<string, unknown> };
161
- } catch (error) {
162
- console.warn("Failed to parse job list SSE payload", error);
163
- return;
164
- }
130
+ const result = handleListSseMessage(event.type, event.data);
165
131
 
166
- if (shouldRefetchForListEvent(payload.type)) {
132
+ if (result.kind === "refetch") {
167
133
  scheduleRefetch();
168
134
  return;
169
135
  }
170
136
 
171
137
  if (!hydratedRef.current || refetchingRef.current) {
172
- queueRef.current.push(payload);
138
+ queueRef.current.push(result.event);
173
139
  return;
174
140
  }
175
141
 
176
142
  setData((current) => {
177
143
  if (current === null) return current;
178
- const next = applyJobEvent(current, payload);
144
+ const next = applyJobEvent(current, result.event);
179
145
  dataRef.current = next;
180
146
  return next;
181
147
  });
@@ -0,0 +1,20 @@
1
+ import type { ApiError } from "./types";
2
+
3
+ export interface LoadState<T> {
4
+ data: T | null;
5
+ error: ApiError | null;
6
+ }
7
+
8
+ export type LoadResult<T> =
9
+ | { ok: true; data: T }
10
+ | { ok: false; error: ApiError };
11
+
12
+ export function nextLoadState<T>(
13
+ prev: LoadState<T>,
14
+ result: LoadResult<T>,
15
+ ): LoadState<T> {
16
+ if (result.ok) {
17
+ return { data: result.data, error: null };
18
+ }
19
+ return { data: prev.data, error: result.error };
20
+ }