@ryanfw/prompt-orchestration-pipeline 0.17.1 → 0.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -635
- package/docs/pop-task-guide.md +64 -13
- package/package.json +1 -1
- package/src/components/DAGGrid.jsx +3 -0
- package/src/components/ui/RestartJobModal.jsx +21 -17
- package/src/providers/moonshot.js +56 -0
- package/src/ui/client/api.js +3 -0
- package/src/ui/dist/assets/{index-xx8otyG0.js → index-BidlfsSr.js} +47 -38
- package/src/ui/dist/assets/{index-xx8otyG0.js.map → index-BidlfsSr.js.map} +1 -1
- package/src/ui/dist/assets/style-CdV-vuS0.css +180 -0
- package/src/ui/dist/index.html +2 -2
- package/src/ui/endpoints/job-control-endpoints.js +10 -8
- package/src/ui/server.js +5 -13
- package/src/ui/dist/assets/style-CVd3RRU2.css +0 -180
package/docs/pop-task-guide.md
CHANGED
|
@@ -253,16 +253,67 @@ Each stage receives:
|
|
|
253
253
|
preProcessing, // Output from preProcessing
|
|
254
254
|
promptTemplating, // Output from promptTemplating
|
|
255
255
|
// ... other stage outputs
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
##
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
256
|
+
},
|
|
257
|
+
output, // Previous non-validation stage output
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Detailed Stage Reference
|
|
264
|
+
|
|
265
|
+
This reference describes the intent and responsibility of each standard phase. All phases execute sequentially.
|
|
266
|
+
|
|
267
|
+
### 1. Ingestion
|
|
268
|
+
**Purpose**: Load and extract raw input data from the seed.
|
|
269
|
+
**Responsibility**: Read input parameters, extract required fields, and pass data forward.
|
|
270
|
+
|
|
271
|
+
### 2. PreProcessing
|
|
272
|
+
**Purpose**: Normalize and prepare input data.
|
|
273
|
+
**Responsibility**: Clean input formats, deduplicate arrays, set defaults, and sanitize data.
|
|
274
|
+
|
|
275
|
+
### 3. PromptTemplating
|
|
276
|
+
**Purpose**: Build structured prompts for the LLM.
|
|
277
|
+
**Responsibility**: Create system and user prompts, including output format specifications.
|
|
278
|
+
|
|
279
|
+
### 4. Inference
|
|
280
|
+
**Purpose**: Execute the LLM call.
|
|
281
|
+
**Responsibility**: Call the LLM API, handle raw responses, and write initial output artifacts.
|
|
282
|
+
|
|
283
|
+
### 5. Parsing
|
|
284
|
+
**Purpose**: Transform raw output into typed structure.
|
|
285
|
+
**Responsibility**: specific parsing logic if not handled during inference (e.g. complex regex extraction).
|
|
286
|
+
|
|
287
|
+
### 6. ValidateStructure
|
|
288
|
+
**Purpose**: Validate response against JSON schema.
|
|
289
|
+
**Responsibility**: programmatic validation using Ajv or similar. Sets `needsRefinement: true` if invalid.
|
|
290
|
+
|
|
291
|
+
### 7. ValidateQuality
|
|
292
|
+
**Purpose**: LLM-based content quality assessment.
|
|
293
|
+
**Responsibility**: Check for factual consistency, completeness, and specific requirements. Sets `needsRefinement: true` if issues found.
|
|
294
|
+
|
|
295
|
+
### 8. Critique
|
|
296
|
+
**Purpose**: Generate improvement instructions.
|
|
297
|
+
**Responsibility**: If validation failed, analyze errors and generate actionable feedback.
|
|
298
|
+
|
|
299
|
+
### 9. Refine
|
|
300
|
+
**Purpose**: Re-run the core task with improvements.
|
|
301
|
+
**Responsibility**: If `needsRefinement` is true, call LLM again with original prompt + critique.
|
|
302
|
+
|
|
303
|
+
### 10. FinalValidation
|
|
304
|
+
**Purpose**: Safety gate for refined output.
|
|
305
|
+
**Responsibility**: Re-validate structure to ensure refinement didn't break the JSON schema.
|
|
306
|
+
|
|
307
|
+
### 11. Integration
|
|
308
|
+
**Purpose**: Persist and organize final results.
|
|
309
|
+
**Responsibility**: Save final artifacts to databases, files, or trigger downstream workflows.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Summary
|
|
314
|
+
|
|
315
|
+
1. Export only valid stage names: `ingestion`, `preProcessing`, `promptTemplating`, `inference`, `parsing`, `validateStructure`, `validateQuality`, `critique`, `refine`, `finalValidation`, `integration`
|
|
316
|
+
2. Return `{ output, flags }` from every stage
|
|
317
|
+
3. Custom helper functions are valid JavaScript but will not be called by the pipeline—only use them if called from within a valid stage
|
|
318
|
+
4. Most simple tasks need only: `ingestion` → `promptTemplating` → `inference`
|
|
319
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryanfw/prompt-orchestration-pipeline",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.3",
|
|
4
4
|
"description": "A Prompt-orchestration pipeline (POP) is a framework for building, running, and experimenting with complex chains of LLM tasks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/ui/server.js",
|
|
@@ -588,6 +588,9 @@ function DAGGrid({
|
|
|
588
588
|
if (options?.singleTask) {
|
|
589
589
|
restartOptions.singleTask = options.singleTask;
|
|
590
590
|
}
|
|
591
|
+
if (options?.continueAfter) {
|
|
592
|
+
restartOptions.continueAfter = options.continueAfter;
|
|
593
|
+
}
|
|
591
594
|
|
|
592
595
|
await restartJob(jobId, restartOptions);
|
|
593
596
|
|
|
@@ -81,6 +81,15 @@ export function RestartJobModal({
|
|
|
81
81
|
tabIndex={-1}
|
|
82
82
|
onKeyDown={handleKeyDown}
|
|
83
83
|
>
|
|
84
|
+
{/* Close button */}
|
|
85
|
+
<button
|
|
86
|
+
onClick={onClose}
|
|
87
|
+
disabled={isSubmitting}
|
|
88
|
+
className="absolute top-4 right-4 text-gray-500 hover:text-gray-700 text-xl font-light"
|
|
89
|
+
aria-label="Close"
|
|
90
|
+
>
|
|
91
|
+
×
|
|
92
|
+
</button>
|
|
84
93
|
<div className="p-6">
|
|
85
94
|
{/* Header */}
|
|
86
95
|
<Heading
|
|
@@ -107,10 +116,6 @@ export function RestartJobModal({
|
|
|
107
116
|
<Text as="p" className="text-sm text-gray-600 mb-3">
|
|
108
117
|
<strong>Triggered from task:</strong> {taskId}
|
|
109
118
|
</Text>
|
|
110
|
-
<Text as="p" className="text-sm text-blue-600 mb-3">
|
|
111
|
-
<strong>Just this task:</strong> Only the selected task will
|
|
112
|
-
be reset and re-run. Other tasks remain unchanged.
|
|
113
|
-
</Text>
|
|
114
119
|
</>
|
|
115
120
|
)}
|
|
116
121
|
|
|
@@ -120,31 +125,30 @@ export function RestartJobModal({
|
|
|
120
125
|
</Box>
|
|
121
126
|
|
|
122
127
|
{/* Actions */}
|
|
123
|
-
<Flex gap="
|
|
124
|
-
<Button
|
|
125
|
-
variant="outline"
|
|
126
|
-
onClick={onClose}
|
|
127
|
-
disabled={isSubmitting}
|
|
128
|
-
className="min-w-[80px]"
|
|
129
|
-
>
|
|
130
|
-
Cancel
|
|
131
|
-
</Button>
|
|
132
|
-
|
|
128
|
+
<Flex direction="column" gap="2" justify="end" align="end">
|
|
133
129
|
{taskId ? (
|
|
134
130
|
<>
|
|
135
131
|
<Button
|
|
136
132
|
variant="outline"
|
|
137
133
|
onClick={() => onConfirm({ singleTask: false })}
|
|
138
134
|
disabled={isSubmitting}
|
|
139
|
-
className="
|
|
135
|
+
className="w-full sm:w-auto"
|
|
140
136
|
>
|
|
141
137
|
{isSubmitting ? "Restarting..." : "Restart entire pipeline"}
|
|
142
138
|
</Button>
|
|
139
|
+
<Button
|
|
140
|
+
variant="outline"
|
|
141
|
+
onClick={() => onConfirm({ singleTask: true, continueAfter: true })}
|
|
142
|
+
disabled={isSubmitting}
|
|
143
|
+
className="w-full sm:w-auto"
|
|
144
|
+
>
|
|
145
|
+
{isSubmitting ? "Running..." : "Re-run task and continue pipeline"}
|
|
146
|
+
</Button>
|
|
143
147
|
<Button
|
|
144
148
|
variant="default"
|
|
145
149
|
onClick={() => onConfirm({ singleTask: true })}
|
|
146
150
|
disabled={isSubmitting}
|
|
147
|
-
className="
|
|
151
|
+
className="w-full sm:w-auto"
|
|
148
152
|
>
|
|
149
153
|
{isSubmitting ? "Running..." : "Re-run this task"}
|
|
150
154
|
</Button>
|
|
@@ -154,7 +158,7 @@ export function RestartJobModal({
|
|
|
154
158
|
variant="destructive"
|
|
155
159
|
onClick={() => onConfirm({ singleTask: false })}
|
|
156
160
|
disabled={isSubmitting}
|
|
157
|
-
className="
|
|
161
|
+
className="w-full sm:w-auto"
|
|
158
162
|
>
|
|
159
163
|
{isSubmitting ? "Restarting..." : "Restart"}
|
|
160
164
|
</Button>
|
|
@@ -7,10 +7,49 @@ import {
|
|
|
7
7
|
ProviderJsonParseError,
|
|
8
8
|
createProviderError,
|
|
9
9
|
} from "./base.js";
|
|
10
|
+
import { deepseekChat } from "./deepseek.js";
|
|
10
11
|
import { createLogger } from "../core/logger.js";
|
|
11
12
|
|
|
12
13
|
const logger = createLogger("Moonshot");
|
|
13
14
|
|
|
15
|
+
function isContentFilterError(error) {
|
|
16
|
+
return (
|
|
17
|
+
error.status === 400 &&
|
|
18
|
+
/high risk|rejected/i.test(error.message)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function fallbackToDeepSeek({
|
|
23
|
+
messages,
|
|
24
|
+
temperature,
|
|
25
|
+
maxTokens,
|
|
26
|
+
responseFormat,
|
|
27
|
+
topP,
|
|
28
|
+
frequencyPenalty,
|
|
29
|
+
presencePenalty,
|
|
30
|
+
stop,
|
|
31
|
+
stream,
|
|
32
|
+
thinking,
|
|
33
|
+
}) {
|
|
34
|
+
const fallbackModel = thinking === "enabled" ? "deepseek-reasoner" : "deepseek-chat";
|
|
35
|
+
logger.warn("Moonshot content filter triggered, falling back to DeepSeek", {
|
|
36
|
+
fallbackModel,
|
|
37
|
+
thinking,
|
|
38
|
+
});
|
|
39
|
+
return deepseekChat({
|
|
40
|
+
messages,
|
|
41
|
+
model: fallbackModel,
|
|
42
|
+
temperature,
|
|
43
|
+
maxTokens,
|
|
44
|
+
responseFormat,
|
|
45
|
+
topP,
|
|
46
|
+
frequencyPenalty,
|
|
47
|
+
presencePenalty,
|
|
48
|
+
stop,
|
|
49
|
+
stream,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
14
53
|
export async function moonshotChat({
|
|
15
54
|
messages,
|
|
16
55
|
model = "moonshot-v1-128k",
|
|
@@ -22,6 +61,7 @@ export async function moonshotChat({
|
|
|
22
61
|
presencePenalty,
|
|
23
62
|
stop,
|
|
24
63
|
stream = false,
|
|
64
|
+
thinking = "enabled",
|
|
25
65
|
maxRetries = 3,
|
|
26
66
|
}) {
|
|
27
67
|
const isJsonMode =
|
|
@@ -162,6 +202,22 @@ export async function moonshotChat({
|
|
|
162
202
|
errorStatus: error.status,
|
|
163
203
|
});
|
|
164
204
|
|
|
205
|
+
// Check for content filter error and attempt DeepSeek fallback
|
|
206
|
+
if (isContentFilterError(error) && process.env.DEEPSEEK_API_KEY) {
|
|
207
|
+
return fallbackToDeepSeek({
|
|
208
|
+
messages,
|
|
209
|
+
temperature,
|
|
210
|
+
maxTokens,
|
|
211
|
+
responseFormat,
|
|
212
|
+
topP,
|
|
213
|
+
frequencyPenalty,
|
|
214
|
+
presencePenalty,
|
|
215
|
+
stop,
|
|
216
|
+
stream,
|
|
217
|
+
thinking,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
165
221
|
if (error.status === 401) throw error;
|
|
166
222
|
|
|
167
223
|
if (isRetryableError(error) && attempt < maxRetries) {
|
package/src/ui/client/api.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @param {Object} opts - Options object
|
|
10
10
|
* @param {string} [opts.fromTask] - Task ID to restart from (inclusive)
|
|
11
11
|
* @param {boolean} [opts.singleTask] - Whether to run only the target task and then stop
|
|
12
|
+
* @param {boolean} [opts.continueAfter] - Whether to continue pipeline after the single task completes
|
|
12
13
|
* @param {Object} [opts.options] - Additional options for the restart
|
|
13
14
|
* @param {boolean} [opts.options.clearTokenUsage=true] - Whether to clear token usage
|
|
14
15
|
* @returns {Promise<Object>} Parsed JSON response from the server
|
|
@@ -25,11 +26,13 @@ export async function restartJob(jobId, opts = {}) {
|
|
|
25
26
|
fromTask: opts.fromTask,
|
|
26
27
|
options,
|
|
27
28
|
...(opts.singleTask !== undefined && { singleTask: opts.singleTask }),
|
|
29
|
+
...(opts.continueAfter !== undefined && { continueAfter: opts.continueAfter }),
|
|
28
30
|
}
|
|
29
31
|
: {
|
|
30
32
|
mode: "clean-slate",
|
|
31
33
|
options,
|
|
32
34
|
...(opts.singleTask !== undefined && { singleTask: opts.singleTask }),
|
|
35
|
+
...(opts.continueAfter !== undefined && { continueAfter: opts.continueAfter }),
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
try {
|
|
@@ -24794,7 +24794,7 @@ function RestartJobModal({
|
|
|
24794
24794
|
"aria-hidden": "true"
|
|
24795
24795
|
}
|
|
24796
24796
|
),
|
|
24797
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
24797
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
24798
24798
|
"div",
|
|
24799
24799
|
{
|
|
24800
24800
|
ref: modalRef,
|
|
@@ -24806,61 +24806,65 @@ function RestartJobModal({
|
|
|
24806
24806
|
style: { minWidth: "320px", maxWidth: "560px" },
|
|
24807
24807
|
tabIndex: -1,
|
|
24808
24808
|
onKeyDown: handleKeyDown,
|
|
24809
|
-
children:
|
|
24809
|
+
children: [
|
|
24810
24810
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24811
|
-
|
|
24811
|
+
"button",
|
|
24812
24812
|
{
|
|
24813
|
-
|
|
24814
|
-
|
|
24815
|
-
|
|
24816
|
-
|
|
24817
|
-
children:
|
|
24813
|
+
onClick: onClose,
|
|
24814
|
+
disabled: isSubmitting,
|
|
24815
|
+
className: "absolute top-4 right-4 text-gray-500 hover:text-gray-700 text-xl font-light",
|
|
24816
|
+
"aria-label": "Close",
|
|
24817
|
+
children: "×"
|
|
24818
24818
|
}
|
|
24819
24819
|
),
|
|
24820
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
24821
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$d, { as: "p", className: "text-gray-700 mb-4", children: taskId ? `This will restart the job from the "${taskId}" task. Tasks before ${taskId} will remain completed, while ${taskId} and all subsequent tasks will be reset to pending. Files and artifacts are preserved. A new background run will start automatically. This cannot be undone.` : "This will clear the job's progress and active stage and reset all tasks to pending. Files and artifacts are preserved. A new background run will start automatically. This cannot be undone." }),
|
|
24822
|
-
taskId && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
24823
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$d, { as: "p", className: "text-sm text-gray-600 mb-3", children: [
|
|
24824
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Triggered from task:" }),
|
|
24825
|
-
" ",
|
|
24826
|
-
taskId
|
|
24827
|
-
] }),
|
|
24828
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$d, { as: "p", className: "text-sm text-blue-600 mb-3", children: [
|
|
24829
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Just this task:" }),
|
|
24830
|
-
" Only the selected task will be reset and re-run. Other tasks remain unchanged."
|
|
24831
|
-
] })
|
|
24832
|
-
] }),
|
|
24833
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$d, { as: "p", className: "text-sm text-gray-500 italic", children: "Note: Job must be in current lifecycle and not running." })
|
|
24834
|
-
] }),
|
|
24835
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$6, { gap: "3", justify: "end", children: [
|
|
24820
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6", children: [
|
|
24836
24821
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24837
|
-
|
|
24822
|
+
r$a,
|
|
24838
24823
|
{
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
className: "
|
|
24843
|
-
children: "
|
|
24824
|
+
id: "restart-modal-title",
|
|
24825
|
+
as: "h2",
|
|
24826
|
+
size: "5",
|
|
24827
|
+
className: "mb-4 text-gray-900",
|
|
24828
|
+
children: taskId ? `Restart from ${taskId}` : "Restart job (reset progress)"
|
|
24844
24829
|
}
|
|
24845
24830
|
),
|
|
24846
|
-
|
|
24831
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$9, { id: "restart-modal-description", className: "mb-6", children: [
|
|
24832
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$d, { as: "p", className: "text-gray-700 mb-4", children: taskId ? `This will restart the job from the "${taskId}" task. Tasks before ${taskId} will remain completed, while ${taskId} and all subsequent tasks will be reset to pending. Files and artifacts are preserved. A new background run will start automatically. This cannot be undone.` : "This will clear the job's progress and active stage and reset all tasks to pending. Files and artifacts are preserved. A new background run will start automatically. This cannot be undone." }),
|
|
24833
|
+
taskId && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$d, { as: "p", className: "text-sm text-gray-600 mb-3", children: [
|
|
24834
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Triggered from task:" }),
|
|
24835
|
+
" ",
|
|
24836
|
+
taskId
|
|
24837
|
+
] }) }),
|
|
24838
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$d, { as: "p", className: "text-sm text-gray-500 italic", children: "Note: Job must be in current lifecycle and not running." })
|
|
24839
|
+
] }),
|
|
24840
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$6, { direction: "column", gap: "2", justify: "end", align: "end", children: taskId ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
24847
24841
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24848
24842
|
Button,
|
|
24849
24843
|
{
|
|
24850
24844
|
variant: "outline",
|
|
24851
24845
|
onClick: () => onConfirm({ singleTask: false }),
|
|
24852
24846
|
disabled: isSubmitting,
|
|
24853
|
-
className: "
|
|
24847
|
+
className: "w-full sm:w-auto",
|
|
24854
24848
|
children: isSubmitting ? "Restarting..." : "Restart entire pipeline"
|
|
24855
24849
|
}
|
|
24856
24850
|
),
|
|
24851
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24852
|
+
Button,
|
|
24853
|
+
{
|
|
24854
|
+
variant: "outline",
|
|
24855
|
+
onClick: () => onConfirm({ singleTask: true, continueAfter: true }),
|
|
24856
|
+
disabled: isSubmitting,
|
|
24857
|
+
className: "w-full sm:w-auto",
|
|
24858
|
+
children: isSubmitting ? "Running..." : "Re-run task and continue pipeline"
|
|
24859
|
+
}
|
|
24860
|
+
),
|
|
24857
24861
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24858
24862
|
Button,
|
|
24859
24863
|
{
|
|
24860
24864
|
variant: "default",
|
|
24861
24865
|
onClick: () => onConfirm({ singleTask: true }),
|
|
24862
24866
|
disabled: isSubmitting,
|
|
24863
|
-
className: "
|
|
24867
|
+
className: "w-full sm:w-auto",
|
|
24864
24868
|
children: isSubmitting ? "Running..." : "Re-run this task"
|
|
24865
24869
|
}
|
|
24866
24870
|
)
|
|
@@ -24870,12 +24874,12 @@ function RestartJobModal({
|
|
|
24870
24874
|
variant: "destructive",
|
|
24871
24875
|
onClick: () => onConfirm({ singleTask: false }),
|
|
24872
24876
|
disabled: isSubmitting,
|
|
24873
|
-
className: "
|
|
24877
|
+
className: "w-full sm:w-auto",
|
|
24874
24878
|
children: isSubmitting ? "Restarting..." : "Restart"
|
|
24875
24879
|
}
|
|
24876
|
-
)
|
|
24880
|
+
) })
|
|
24877
24881
|
] })
|
|
24878
|
-
]
|
|
24882
|
+
]
|
|
24879
24883
|
}
|
|
24880
24884
|
)
|
|
24881
24885
|
]
|
|
@@ -24890,11 +24894,13 @@ async function restartJob(jobId, opts = {}) {
|
|
|
24890
24894
|
const requestBody = opts.fromTask ? {
|
|
24891
24895
|
fromTask: opts.fromTask,
|
|
24892
24896
|
options,
|
|
24893
|
-
...opts.singleTask !== void 0 && { singleTask: opts.singleTask }
|
|
24897
|
+
...opts.singleTask !== void 0 && { singleTask: opts.singleTask },
|
|
24898
|
+
...opts.continueAfter !== void 0 && { continueAfter: opts.continueAfter }
|
|
24894
24899
|
} : {
|
|
24895
24900
|
mode: "clean-slate",
|
|
24896
24901
|
options,
|
|
24897
|
-
...opts.singleTask !== void 0 && { singleTask: opts.singleTask }
|
|
24902
|
+
...opts.singleTask !== void 0 && { singleTask: opts.singleTask },
|
|
24903
|
+
...opts.continueAfter !== void 0 && { continueAfter: opts.continueAfter }
|
|
24898
24904
|
};
|
|
24899
24905
|
try {
|
|
24900
24906
|
const response = await fetch(
|
|
@@ -25641,6 +25647,9 @@ function DAGGrid({
|
|
|
25641
25647
|
if (options?.singleTask) {
|
|
25642
25648
|
restartOptions.singleTask = options.singleTask;
|
|
25643
25649
|
}
|
|
25650
|
+
if (options?.continueAfter) {
|
|
25651
|
+
restartOptions.continueAfter = options.continueAfter;
|
|
25652
|
+
}
|
|
25644
25653
|
await restartJob(jobId, restartOptions);
|
|
25645
25654
|
const successMessage = options?.singleTask ? `Re-running task ${restartTaskId} in isolation. The job will remain in current after completion.` : restartTaskId ? `Restart requested from ${restartTaskId}. The job will start from that task in the background.` : "Restart requested. The job will reset to pending and start in the background.";
|
|
25646
25655
|
setAlertMessage(successMessage);
|