@ryanfw/prompt-orchestration-pipeline 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/package.json +1 -2
- package/src/api/validators/json.js +39 -0
- package/src/components/DAGGrid.jsx +392 -303
- package/src/components/JobCard.jsx +14 -12
- package/src/components/JobDetail.jsx +54 -51
- package/src/components/JobTable.jsx +72 -23
- package/src/components/Layout.jsx +145 -42
- package/src/components/LiveText.jsx +47 -0
- package/src/components/PageSubheader.jsx +75 -0
- package/src/components/TaskDetailSidebar.jsx +216 -0
- package/src/components/TimerText.jsx +82 -0
- package/src/components/UploadSeed.jsx +0 -70
- package/src/components/ui/Logo.jsx +16 -0
- package/src/components/ui/RestartJobModal.jsx +140 -0
- package/src/components/ui/toast.jsx +138 -0
- package/src/config/models.js +322 -0
- package/src/config/statuses.js +119 -0
- package/src/core/config.js +4 -34
- package/src/core/file-io.js +13 -28
- package/src/core/module-loader.js +54 -40
- package/src/core/pipeline-runner.js +65 -26
- package/src/core/status-writer.js +213 -58
- package/src/core/symlink-bridge.js +57 -0
- package/src/core/symlink-utils.js +94 -0
- package/src/core/task-runner.js +321 -437
- package/src/llm/index.js +258 -86
- package/src/pages/Code.jsx +351 -0
- package/src/pages/PipelineDetail.jsx +124 -15
- package/src/pages/PromptPipelineDashboard.jsx +20 -88
- package/src/providers/anthropic.js +83 -69
- package/src/providers/base.js +52 -0
- package/src/providers/deepseek.js +20 -21
- package/src/providers/gemini.js +226 -0
- package/src/providers/openai.js +36 -106
- package/src/providers/zhipu.js +136 -0
- package/src/ui/client/adapters/job-adapter.js +42 -28
- package/src/ui/client/api.js +134 -0
- package/src/ui/client/hooks/useJobDetailWithUpdates.js +65 -179
- package/src/ui/client/index.css +15 -0
- package/src/ui/client/index.html +2 -1
- package/src/ui/client/main.jsx +19 -14
- package/src/ui/client/time-store.js +161 -0
- package/src/ui/config-bridge.js +15 -24
- package/src/ui/config-bridge.node.js +15 -24
- package/src/ui/dist/assets/{index-CxcrauYR.js → index-DqkbzXZ1.js} +2132 -1086
- package/src/ui/dist/assets/style-DBF9NQGk.css +62 -0
- package/src/ui/dist/index.html +4 -3
- package/src/ui/job-reader.js +0 -108
- package/src/ui/public/favicon.svg +12 -0
- package/src/ui/server.js +252 -0
- package/src/ui/sse-enhancer.js +0 -1
- package/src/ui/transformers/list-transformer.js +32 -12
- package/src/ui/transformers/status-transformer.js +29 -42
- package/src/utils/dag.js +8 -4
- package/src/utils/duration.js +13 -19
- package/src/utils/formatters.js +27 -0
- package/src/utils/geometry-equality.js +83 -0
- package/src/utils/pipelines.js +5 -1
- package/src/utils/time-utils.js +40 -0
- package/src/utils/token-cost-calculator.js +294 -0
- package/src/utils/ui.jsx +18 -20
- package/src/components/ui/select.jsx +0 -27
- package/src/lib/utils.js +0 -6
- package/src/ui/client/hooks/useTicker.js +0 -26
- package/src/ui/config-bridge.browser.js +0 -149
- package/src/ui/dist/assets/style-D6K_oQ12.css +0 -62
|
@@ -520,11 +520,11 @@ function requireReact_production() {
|
|
|
520
520
|
react_production.useState = function(initialState) {
|
|
521
521
|
return ReactSharedInternals.H.useState(initialState);
|
|
522
522
|
};
|
|
523
|
-
react_production.useSyncExternalStore = function(
|
|
523
|
+
react_production.useSyncExternalStore = function(subscribe2, getSnapshot2, getServerSnapshot2) {
|
|
524
524
|
return ReactSharedInternals.H.useSyncExternalStore(
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
525
|
+
subscribe2,
|
|
526
|
+
getSnapshot2,
|
|
527
|
+
getServerSnapshot2
|
|
528
528
|
);
|
|
529
529
|
};
|
|
530
530
|
react_production.useTransition = function() {
|
|
@@ -3180,15 +3180,15 @@ function requireReactDomClient_production() {
|
|
|
3180
3180
|
return value;
|
|
3181
3181
|
}
|
|
3182
3182
|
var AbortControllerLocal = "undefined" !== typeof AbortController ? AbortController : function() {
|
|
3183
|
-
var
|
|
3183
|
+
var listeners2 = [], signal = this.signal = {
|
|
3184
3184
|
aborted: false,
|
|
3185
3185
|
addEventListener: function(type, listener) {
|
|
3186
|
-
|
|
3186
|
+
listeners2.push(listener);
|
|
3187
3187
|
}
|
|
3188
3188
|
};
|
|
3189
3189
|
this.abort = function() {
|
|
3190
3190
|
signal.aborted = true;
|
|
3191
|
-
|
|
3191
|
+
listeners2.forEach(function(listener) {
|
|
3192
3192
|
return listener();
|
|
3193
3193
|
});
|
|
3194
3194
|
};
|
|
@@ -3234,33 +3234,33 @@ function requireReactDomClient_production() {
|
|
|
3234
3234
|
function pingEngtangledActionScope() {
|
|
3235
3235
|
if (0 === --currentEntangledPendingCount && null !== currentEntangledListeners) {
|
|
3236
3236
|
null !== currentEntangledActionThenable && (currentEntangledActionThenable.status = "fulfilled");
|
|
3237
|
-
var
|
|
3237
|
+
var listeners2 = currentEntangledListeners;
|
|
3238
3238
|
currentEntangledListeners = null;
|
|
3239
3239
|
currentEntangledLane = 0;
|
|
3240
3240
|
currentEntangledActionThenable = null;
|
|
3241
|
-
for (var i2 = 0; i2 <
|
|
3241
|
+
for (var i2 = 0; i2 < listeners2.length; i2++) (0, listeners2[i2])();
|
|
3242
3242
|
}
|
|
3243
3243
|
}
|
|
3244
3244
|
function chainThenableValue(thenable, result) {
|
|
3245
|
-
var
|
|
3245
|
+
var listeners2 = [], thenableWithOverride = {
|
|
3246
3246
|
status: "pending",
|
|
3247
3247
|
value: null,
|
|
3248
3248
|
reason: null,
|
|
3249
3249
|
then: function(resolve) {
|
|
3250
|
-
|
|
3250
|
+
listeners2.push(resolve);
|
|
3251
3251
|
}
|
|
3252
3252
|
};
|
|
3253
3253
|
thenable.then(
|
|
3254
3254
|
function() {
|
|
3255
3255
|
thenableWithOverride.status = "fulfilled";
|
|
3256
3256
|
thenableWithOverride.value = result;
|
|
3257
|
-
for (var i2 = 0; i2 <
|
|
3257
|
+
for (var i2 = 0; i2 < listeners2.length; i2++) (0, listeners2[i2])(result);
|
|
3258
3258
|
},
|
|
3259
3259
|
function(error) {
|
|
3260
3260
|
thenableWithOverride.status = "rejected";
|
|
3261
3261
|
thenableWithOverride.reason = error;
|
|
3262
|
-
for (error = 0; error <
|
|
3263
|
-
(0,
|
|
3262
|
+
for (error = 0; error < listeners2.length; error++)
|
|
3263
|
+
(0, listeners2[error])(void 0);
|
|
3264
3264
|
}
|
|
3265
3265
|
);
|
|
3266
3266
|
return thenableWithOverride;
|
|
@@ -4327,22 +4327,22 @@ function requireReactDomClient_production() {
|
|
|
4327
4327
|
}
|
|
4328
4328
|
return [newState, dispatch];
|
|
4329
4329
|
}
|
|
4330
|
-
function updateSyncExternalStore(
|
|
4330
|
+
function updateSyncExternalStore(subscribe2, getSnapshot2, getServerSnapshot2) {
|
|
4331
4331
|
var fiber = currentlyRenderingFiber, hook = updateWorkInProgressHook(), isHydrating$jscomp$0 = isHydrating;
|
|
4332
4332
|
if (isHydrating$jscomp$0) {
|
|
4333
|
-
if (void 0 ===
|
|
4334
|
-
|
|
4335
|
-
} else
|
|
4333
|
+
if (void 0 === getServerSnapshot2) throw Error(formatProdErrorMessage(407));
|
|
4334
|
+
getServerSnapshot2 = getServerSnapshot2();
|
|
4335
|
+
} else getServerSnapshot2 = getSnapshot2();
|
|
4336
4336
|
var snapshotChanged = !objectIs(
|
|
4337
4337
|
(currentHook || hook).memoizedState,
|
|
4338
|
-
|
|
4338
|
+
getServerSnapshot2
|
|
4339
4339
|
);
|
|
4340
|
-
snapshotChanged && (hook.memoizedState =
|
|
4340
|
+
snapshotChanged && (hook.memoizedState = getServerSnapshot2, didReceiveUpdate = true);
|
|
4341
4341
|
hook = hook.queue;
|
|
4342
|
-
updateEffect(subscribeToStore.bind(null, fiber, hook,
|
|
4343
|
-
|
|
4342
|
+
updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe2), [
|
|
4343
|
+
subscribe2
|
|
4344
4344
|
]);
|
|
4345
|
-
if (hook.getSnapshot !==
|
|
4345
|
+
if (hook.getSnapshot !== getSnapshot2 || snapshotChanged || null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1) {
|
|
4346
4346
|
fiber.flags |= 2048;
|
|
4347
4347
|
pushSimpleEffect(
|
|
4348
4348
|
9,
|
|
@@ -4351,29 +4351,29 @@ function requireReactDomClient_production() {
|
|
|
4351
4351
|
null,
|
|
4352
4352
|
fiber,
|
|
4353
4353
|
hook,
|
|
4354
|
-
|
|
4355
|
-
|
|
4354
|
+
getServerSnapshot2,
|
|
4355
|
+
getSnapshot2
|
|
4356
4356
|
),
|
|
4357
4357
|
null
|
|
4358
4358
|
);
|
|
4359
4359
|
if (null === workInProgressRoot) throw Error(formatProdErrorMessage(349));
|
|
4360
|
-
isHydrating$jscomp$0 || 0 !== (renderLanes & 127) || pushStoreConsistencyCheck(fiber,
|
|
4360
|
+
isHydrating$jscomp$0 || 0 !== (renderLanes & 127) || pushStoreConsistencyCheck(fiber, getSnapshot2, getServerSnapshot2);
|
|
4361
4361
|
}
|
|
4362
|
-
return
|
|
4362
|
+
return getServerSnapshot2;
|
|
4363
4363
|
}
|
|
4364
|
-
function pushStoreConsistencyCheck(fiber,
|
|
4364
|
+
function pushStoreConsistencyCheck(fiber, getSnapshot2, renderedSnapshot) {
|
|
4365
4365
|
fiber.flags |= 16384;
|
|
4366
|
-
fiber = { getSnapshot, value: renderedSnapshot };
|
|
4367
|
-
|
|
4368
|
-
null ===
|
|
4366
|
+
fiber = { getSnapshot: getSnapshot2, value: renderedSnapshot };
|
|
4367
|
+
getSnapshot2 = currentlyRenderingFiber.updateQueue;
|
|
4368
|
+
null === getSnapshot2 ? (getSnapshot2 = createFunctionComponentUpdateQueue(), currentlyRenderingFiber.updateQueue = getSnapshot2, getSnapshot2.stores = [fiber]) : (renderedSnapshot = getSnapshot2.stores, null === renderedSnapshot ? getSnapshot2.stores = [fiber] : renderedSnapshot.push(fiber));
|
|
4369
4369
|
}
|
|
4370
|
-
function updateStoreInstance(fiber, inst, nextSnapshot,
|
|
4370
|
+
function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot2) {
|
|
4371
4371
|
inst.value = nextSnapshot;
|
|
4372
|
-
inst.getSnapshot =
|
|
4372
|
+
inst.getSnapshot = getSnapshot2;
|
|
4373
4373
|
checkIfSnapshotChanged(inst) && forceStoreRerender(fiber);
|
|
4374
4374
|
}
|
|
4375
|
-
function subscribeToStore(fiber, inst,
|
|
4376
|
-
return
|
|
4375
|
+
function subscribeToStore(fiber, inst, subscribe2) {
|
|
4376
|
+
return subscribe2(function() {
|
|
4377
4377
|
checkIfSnapshotChanged(inst) && forceStoreRerender(fiber);
|
|
4378
4378
|
});
|
|
4379
4379
|
}
|
|
@@ -5092,23 +5092,23 @@ function requireReactDomClient_production() {
|
|
|
5092
5092
|
mountWorkInProgressHook().memoizedState = stateHook;
|
|
5093
5093
|
return [false, stateHook];
|
|
5094
5094
|
},
|
|
5095
|
-
useSyncExternalStore: function(
|
|
5095
|
+
useSyncExternalStore: function(subscribe2, getSnapshot2, getServerSnapshot2) {
|
|
5096
5096
|
var fiber = currentlyRenderingFiber, hook = mountWorkInProgressHook();
|
|
5097
5097
|
if (isHydrating) {
|
|
5098
|
-
if (void 0 ===
|
|
5098
|
+
if (void 0 === getServerSnapshot2)
|
|
5099
5099
|
throw Error(formatProdErrorMessage(407));
|
|
5100
|
-
|
|
5100
|
+
getServerSnapshot2 = getServerSnapshot2();
|
|
5101
5101
|
} else {
|
|
5102
|
-
|
|
5102
|
+
getServerSnapshot2 = getSnapshot2();
|
|
5103
5103
|
if (null === workInProgressRoot)
|
|
5104
5104
|
throw Error(formatProdErrorMessage(349));
|
|
5105
|
-
0 !== (workInProgressRootRenderLanes & 127) || pushStoreConsistencyCheck(fiber,
|
|
5105
|
+
0 !== (workInProgressRootRenderLanes & 127) || pushStoreConsistencyCheck(fiber, getSnapshot2, getServerSnapshot2);
|
|
5106
5106
|
}
|
|
5107
|
-
hook.memoizedState =
|
|
5108
|
-
var inst = { value:
|
|
5107
|
+
hook.memoizedState = getServerSnapshot2;
|
|
5108
|
+
var inst = { value: getServerSnapshot2, getSnapshot: getSnapshot2 };
|
|
5109
5109
|
hook.queue = inst;
|
|
5110
|
-
mountEffect(subscribeToStore.bind(null, fiber, inst,
|
|
5111
|
-
|
|
5110
|
+
mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe2), [
|
|
5111
|
+
subscribe2
|
|
5112
5112
|
]);
|
|
5113
5113
|
fiber.flags |= 2048;
|
|
5114
5114
|
pushSimpleEffect(
|
|
@@ -5118,12 +5118,12 @@ function requireReactDomClient_production() {
|
|
|
5118
5118
|
null,
|
|
5119
5119
|
fiber,
|
|
5120
5120
|
inst,
|
|
5121
|
-
|
|
5122
|
-
|
|
5121
|
+
getServerSnapshot2,
|
|
5122
|
+
getSnapshot2
|
|
5123
5123
|
),
|
|
5124
5124
|
null
|
|
5125
5125
|
);
|
|
5126
|
-
return
|
|
5126
|
+
return getServerSnapshot2;
|
|
5127
5127
|
},
|
|
5128
5128
|
useId: function() {
|
|
5129
5129
|
var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix;
|
|
@@ -8813,10 +8813,10 @@ function requireReactDomClient_production() {
|
|
|
8813
8813
|
var tag = node.tag;
|
|
8814
8814
|
if ((0 === tag || 11 === tag || 15 === tag) && node.flags & 16384 && (tag = node.updateQueue, null !== tag && (tag = tag.stores, null !== tag)))
|
|
8815
8815
|
for (var i2 = 0; i2 < tag.length; i2++) {
|
|
8816
|
-
var check = tag[i2],
|
|
8816
|
+
var check = tag[i2], getSnapshot2 = check.getSnapshot;
|
|
8817
8817
|
check = check.value;
|
|
8818
8818
|
try {
|
|
8819
|
-
if (!objectIs(
|
|
8819
|
+
if (!objectIs(getSnapshot2(), check)) return false;
|
|
8820
8820
|
} catch (error) {
|
|
8821
8821
|
return false;
|
|
8822
8822
|
}
|
|
@@ -10201,15 +10201,15 @@ function requireReactDomClient_production() {
|
|
|
10201
10201
|
};
|
|
10202
10202
|
}
|
|
10203
10203
|
function accumulateTwoPhaseListeners(targetFiber, reactName) {
|
|
10204
|
-
for (var captureName = reactName + "Capture",
|
|
10204
|
+
for (var captureName = reactName + "Capture", listeners2 = []; null !== targetFiber; ) {
|
|
10205
10205
|
var _instance2 = targetFiber, stateNode = _instance2.stateNode;
|
|
10206
10206
|
_instance2 = _instance2.tag;
|
|
10207
|
-
5 !== _instance2 && 26 !== _instance2 && 27 !== _instance2 || null === stateNode || (_instance2 = getListener(targetFiber, captureName), null != _instance2 &&
|
|
10207
|
+
5 !== _instance2 && 26 !== _instance2 && 27 !== _instance2 || null === stateNode || (_instance2 = getListener(targetFiber, captureName), null != _instance2 && listeners2.unshift(
|
|
10208
10208
|
createDispatchListener(targetFiber, _instance2, stateNode)
|
|
10209
|
-
), _instance2 = getListener(targetFiber, reactName), null != _instance2 &&
|
|
10209
|
+
), _instance2 = getListener(targetFiber, reactName), null != _instance2 && listeners2.push(
|
|
10210
10210
|
createDispatchListener(targetFiber, _instance2, stateNode)
|
|
10211
10211
|
));
|
|
10212
|
-
if (3 === targetFiber.tag) return
|
|
10212
|
+
if (3 === targetFiber.tag) return listeners2;
|
|
10213
10213
|
targetFiber = targetFiber.return;
|
|
10214
10214
|
}
|
|
10215
10215
|
return [];
|
|
@@ -10222,18 +10222,18 @@ function requireReactDomClient_production() {
|
|
|
10222
10222
|
return inst ? inst : null;
|
|
10223
10223
|
}
|
|
10224
10224
|
function accumulateEnterLeaveListenersForEvent(dispatchQueue, event, target, common, inCapturePhase) {
|
|
10225
|
-
for (var registrationName = event._reactName,
|
|
10225
|
+
for (var registrationName = event._reactName, listeners2 = []; null !== target && target !== common; ) {
|
|
10226
10226
|
var _instance3 = target, alternate = _instance3.alternate, stateNode = _instance3.stateNode;
|
|
10227
10227
|
_instance3 = _instance3.tag;
|
|
10228
10228
|
if (null !== alternate && alternate === common) break;
|
|
10229
|
-
5 !== _instance3 && 26 !== _instance3 && 27 !== _instance3 || null === stateNode || (alternate = stateNode, inCapturePhase ? (stateNode = getListener(target, registrationName), null != stateNode &&
|
|
10229
|
+
5 !== _instance3 && 26 !== _instance3 && 27 !== _instance3 || null === stateNode || (alternate = stateNode, inCapturePhase ? (stateNode = getListener(target, registrationName), null != stateNode && listeners2.unshift(
|
|
10230
10230
|
createDispatchListener(target, stateNode, alternate)
|
|
10231
|
-
)) : inCapturePhase || (stateNode = getListener(target, registrationName), null != stateNode &&
|
|
10231
|
+
)) : inCapturePhase || (stateNode = getListener(target, registrationName), null != stateNode && listeners2.push(
|
|
10232
10232
|
createDispatchListener(target, stateNode, alternate)
|
|
10233
10233
|
)));
|
|
10234
10234
|
target = target.return;
|
|
10235
10235
|
}
|
|
10236
|
-
0 !==
|
|
10236
|
+
0 !== listeners2.length && dispatchQueue.push({ event, listeners: listeners2 });
|
|
10237
10237
|
}
|
|
10238
10238
|
var NORMALIZE_NEWLINES_REGEX = /\r\n?/g, NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
|
|
10239
10239
|
function normalizeMarkupForTextOrAttribute(markup) {
|
|
@@ -12550,7 +12550,7 @@ function requireClient() {
|
|
|
12550
12550
|
return client.exports;
|
|
12551
12551
|
}
|
|
12552
12552
|
var clientExports = requireClient();
|
|
12553
|
-
const ReactDOM = /* @__PURE__ */ getDefaultExportFromCjs(clientExports);
|
|
12553
|
+
const ReactDOM$1 = /* @__PURE__ */ getDefaultExportFromCjs(clientExports);
|
|
12554
12554
|
/**
|
|
12555
12555
|
* react-router v7.9.4
|
|
12556
12556
|
*
|
|
@@ -14637,6 +14637,7 @@ function useViewTransitionState(to, { relative } = {}) {
|
|
|
14637
14637
|
return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
|
|
14638
14638
|
}
|
|
14639
14639
|
var reactDomExports = requireReactDom();
|
|
14640
|
+
const ReactDOM = /* @__PURE__ */ getDefaultExportFromCjs(reactDomExports);
|
|
14640
14641
|
function setRef(ref, value) {
|
|
14641
14642
|
if (typeof ref === "function") {
|
|
14642
14643
|
return ref(value);
|
|
@@ -15332,11 +15333,11 @@ function usePointerDownOutside(onPointerDownOutside, ownerDocument = globalThis?
|
|
|
15332
15333
|
}
|
|
15333
15334
|
isPointerInsideReactTreeRef.current = false;
|
|
15334
15335
|
};
|
|
15335
|
-
const
|
|
15336
|
+
const timerId2 = window.setTimeout(() => {
|
|
15336
15337
|
ownerDocument.addEventListener("pointerdown", handlePointerDown);
|
|
15337
15338
|
}, 0);
|
|
15338
15339
|
return () => {
|
|
15339
|
-
window.clearTimeout(
|
|
15340
|
+
window.clearTimeout(timerId2);
|
|
15340
15341
|
ownerDocument.removeEventListener("pointerdown", handlePointerDown);
|
|
15341
15342
|
ownerDocument.removeEventListener("click", handleClickRef.current);
|
|
15342
15343
|
};
|
|
@@ -15380,6 +15381,15 @@ function handleAndDispatchCustomEvent(name, handler, detail, { discrete }) {
|
|
|
15380
15381
|
target.dispatchEvent(event);
|
|
15381
15382
|
}
|
|
15382
15383
|
}
|
|
15384
|
+
var PORTAL_NAME$1 = "Portal";
|
|
15385
|
+
var Portal$1 = reactExports.forwardRef((props, forwardedRef) => {
|
|
15386
|
+
const { container: containerProp, ...portalProps } = props;
|
|
15387
|
+
const [mounted, setMounted] = reactExports.useState(false);
|
|
15388
|
+
useLayoutEffect2(() => setMounted(true), []);
|
|
15389
|
+
const container = containerProp || mounted && globalThis?.document?.body;
|
|
15390
|
+
return container ? ReactDOM.createPortal(/* @__PURE__ */ jsxRuntimeExports.jsx(Primitive.div, { ...portalProps, ref: forwardedRef }), container) : null;
|
|
15391
|
+
});
|
|
15392
|
+
Portal$1.displayName = PORTAL_NAME$1;
|
|
15383
15393
|
function useSize(element) {
|
|
15384
15394
|
const [size2, setSize] = reactExports.useState(void 0);
|
|
15385
15395
|
useLayoutEffect2(() => {
|
|
@@ -16007,7 +16017,7 @@ async function convertValueToCoords(state, options) {
|
|
|
16007
16017
|
y: crossAxis * crossAxisMulti
|
|
16008
16018
|
};
|
|
16009
16019
|
}
|
|
16010
|
-
const offset$
|
|
16020
|
+
const offset$3 = function(options) {
|
|
16011
16021
|
if (options === void 0) {
|
|
16012
16022
|
options = 0;
|
|
16013
16023
|
}
|
|
@@ -16990,7 +17000,7 @@ function autoUpdate(reference, floating, update, options) {
|
|
|
16990
17000
|
}
|
|
16991
17001
|
};
|
|
16992
17002
|
}
|
|
16993
|
-
const offset$
|
|
17003
|
+
const offset$2 = offset$3;
|
|
16994
17004
|
const shift$1 = shift$2;
|
|
16995
17005
|
const flip$1 = flip$2;
|
|
16996
17006
|
const size$1 = size$2;
|
|
@@ -17263,8 +17273,8 @@ const arrow$1 = (options) => {
|
|
|
17263
17273
|
}
|
|
17264
17274
|
};
|
|
17265
17275
|
};
|
|
17266
|
-
const offset = (options, deps) => ({
|
|
17267
|
-
...offset$
|
|
17276
|
+
const offset$1 = (options, deps) => ({
|
|
17277
|
+
...offset$2(options),
|
|
17268
17278
|
options: [options, deps]
|
|
17269
17279
|
});
|
|
17270
17280
|
const shift = (options, deps) => ({
|
|
@@ -17388,7 +17398,7 @@ var PopperContent = reactExports.forwardRef(
|
|
|
17388
17398
|
reference: context.anchor
|
|
17389
17399
|
},
|
|
17390
17400
|
middleware: [
|
|
17391
|
-
offset({ mainAxis: sideOffset + arrowHeight, alignmentAxis: alignOffset }),
|
|
17401
|
+
offset$1({ mainAxis: sideOffset + arrowHeight, alignmentAxis: alignOffset }),
|
|
17392
17402
|
avoidCollisions && shift({
|
|
17393
17403
|
mainAxis: true,
|
|
17394
17404
|
crossAxis: false,
|
|
@@ -18867,6 +18877,12 @@ var PORTAL_NAME = "TooltipPortal";
|
|
|
18867
18877
|
var [PortalProvider, usePortalContext] = createTooltipContext(PORTAL_NAME, {
|
|
18868
18878
|
forceMount: void 0
|
|
18869
18879
|
});
|
|
18880
|
+
var TooltipPortal = (props) => {
|
|
18881
|
+
const { __scopeTooltip, forceMount, children, container } = props;
|
|
18882
|
+
const context = useTooltipContext(PORTAL_NAME, __scopeTooltip);
|
|
18883
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(PortalProvider, { scope: __scopeTooltip, forceMount, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { asChild: true, container, children }) }) });
|
|
18884
|
+
};
|
|
18885
|
+
TooltipPortal.displayName = PORTAL_NAME;
|
|
18870
18886
|
var CONTENT_NAME = "TooltipContent";
|
|
18871
18887
|
var TooltipContent = reactExports.forwardRef(
|
|
18872
18888
|
(props, forwardedRef) => {
|
|
@@ -19135,7 +19151,9 @@ function getHullPresorted(points) {
|
|
|
19135
19151
|
var Provider = TooltipProvider;
|
|
19136
19152
|
var Root3 = Tooltip;
|
|
19137
19153
|
var Trigger = TooltipTrigger;
|
|
19154
|
+
var Portal = TooltipPortal;
|
|
19138
19155
|
var Content2 = TooltipContent;
|
|
19156
|
+
var Arrow2 = TooltipArrow;
|
|
19139
19157
|
var classnames = { exports: {} };
|
|
19140
19158
|
/*!
|
|
19141
19159
|
Copyright (c) 2018 Jed Watson.
|
|
@@ -19201,23 +19219,23 @@ function requireClassnames() {
|
|
|
19201
19219
|
}
|
|
19202
19220
|
var classnamesExports = requireClassnames();
|
|
19203
19221
|
const y = /* @__PURE__ */ getDefaultExportFromCjs(classnamesExports);
|
|
19204
|
-
const o$
|
|
19222
|
+
const o$7 = { asChild: { type: "boolean" } };
|
|
19205
19223
|
const t$7 = { width: { type: "string", className: "rt-r-w", customProperties: ["--width"], responsive: true }, minWidth: { type: "string", className: "rt-r-min-w", customProperties: ["--min-width"], responsive: true }, maxWidth: { type: "string", className: "rt-r-max-w", customProperties: ["--max-width"], responsive: true } };
|
|
19206
|
-
const e$
|
|
19207
|
-
const o$
|
|
19208
|
-
const o$
|
|
19209
|
-
const e$
|
|
19210
|
-
const e$
|
|
19211
|
-
const e$
|
|
19212
|
-
const e$
|
|
19213
|
-
const e$
|
|
19214
|
-
const m$6 = ["h1", "h2", "h3", "h4", "h5", "h6"], a$9 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], n$7 = { as: { type: "enum", values: m$6, default: "h1" }, ...o$
|
|
19215
|
-
const e$
|
|
19216
|
-
function e$
|
|
19224
|
+
const e$f = { height: { type: "string", className: "rt-r-h", customProperties: ["--height"], responsive: true }, minHeight: { type: "string", className: "rt-r-min-h", customProperties: ["--min-height"], responsive: true }, maxHeight: { type: "string", className: "rt-r-max-h", customProperties: ["--max-height"], responsive: true } };
|
|
19225
|
+
const o$6 = ["gray", "gold", "bronze", "brown", "yellow", "amber", "orange", "tomato", "red", "ruby", "crimson", "pink", "plum", "purple", "violet", "iris", "indigo", "blue", "cyan", "teal", "jade", "green", "grass", "lime", "mint", "sky"], r$c = { color: { type: "enum", values: o$6, default: void 0 } }, s$5 = { color: { type: "enum", values: o$6, default: "" } };
|
|
19226
|
+
const o$5 = { highContrast: { type: "boolean", className: "rt-high-contrast", default: void 0 } };
|
|
19227
|
+
const e$e = ["normal", "start", "end", "both"], r$b = { trim: { type: "enum", className: "rt-r-lt", values: e$e, responsive: true } };
|
|
19228
|
+
const e$d = ["left", "center", "right"], t$6 = { align: { type: "enum", className: "rt-r-ta", values: e$d, responsive: true } };
|
|
19229
|
+
const e$c = ["wrap", "nowrap", "pretty", "balance"], r$a = { wrap: { type: "enum", className: "rt-r-tw", values: e$c, responsive: true } };
|
|
19230
|
+
const e$b = { truncate: { type: "boolean", className: "rt-truncate" } };
|
|
19231
|
+
const e$a = ["light", "regular", "medium", "bold"], t$5 = { weight: { type: "enum", className: "rt-r-weight", values: e$a, responsive: true } };
|
|
19232
|
+
const m$6 = ["h1", "h2", "h3", "h4", "h5", "h6"], a$9 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], n$7 = { as: { type: "enum", values: m$6, default: "h1" }, ...o$7, size: { type: "enum", className: "rt-r-size", values: a$9, default: "6", responsive: true }, ...t$5, ...t$6, ...r$b, ...e$b, ...r$a, ...r$c, ...o$5 };
|
|
19233
|
+
const e$9 = ["initial", "xs", "sm", "md", "lg", "xl"];
|
|
19234
|
+
function e$8(n2, r2) {
|
|
19217
19235
|
return Object.prototype.hasOwnProperty.call(n2, r2);
|
|
19218
19236
|
}
|
|
19219
|
-
function i$
|
|
19220
|
-
return typeof e2 == "object" && Object.keys(e2).some((s2) => e$
|
|
19237
|
+
function i$4(e2) {
|
|
19238
|
+
return typeof e2 == "object" && Object.keys(e2).some((s2) => e$9.includes(s2));
|
|
19221
19239
|
}
|
|
19222
19240
|
function R$2({ className: r2, customProperties: n2, ...t2 }) {
|
|
19223
19241
|
const p2 = g({ allowArbitraryValues: true, className: r2, ...t2 }), e2 = m$5({ customProperties: n2, ...t2 });
|
|
@@ -19227,10 +19245,10 @@ function g({ allowArbitraryValues: r2, value: n2, className: t2, propValues: p2,
|
|
|
19227
19245
|
const s2 = [];
|
|
19228
19246
|
if (n2) {
|
|
19229
19247
|
if (typeof n2 == "string" && p2.includes(n2)) return l$3(t2, n2, e2);
|
|
19230
|
-
if (i$
|
|
19248
|
+
if (i$4(n2)) {
|
|
19231
19249
|
const i2 = n2;
|
|
19232
19250
|
for (const o2 in i2) {
|
|
19233
|
-
if (!e$
|
|
19251
|
+
if (!e$8(i2, o2) || !e$9.includes(o2)) continue;
|
|
19234
19252
|
const u2 = i2[o2];
|
|
19235
19253
|
if (u2 !== void 0) {
|
|
19236
19254
|
if (p2.includes(u2)) {
|
|
@@ -19254,10 +19272,10 @@ function l$3(r2, n2, t2) {
|
|
|
19254
19272
|
function m$5({ customProperties: r2, value: n2, propValues: t2, parseValue: p2 = (e2) => e2 }) {
|
|
19255
19273
|
let e2 = {};
|
|
19256
19274
|
if (!(!n2 || typeof n2 == "string" && t2.includes(n2))) {
|
|
19257
|
-
if (typeof n2 == "string" && (e2 = Object.fromEntries(r2.map((s2) => [s2, n2]))), i$
|
|
19275
|
+
if (typeof n2 == "string" && (e2 = Object.fromEntries(r2.map((s2) => [s2, n2]))), i$4(n2)) {
|
|
19258
19276
|
const s2 = n2;
|
|
19259
19277
|
for (const i2 in s2) {
|
|
19260
|
-
if (!e$
|
|
19278
|
+
if (!e$8(s2, i2) || !e$9.includes(i2)) continue;
|
|
19261
19279
|
const o2 = s2[i2];
|
|
19262
19280
|
if (!t2.includes(o2)) for (const u2 of r2) e2 = { [i2 === "initial" ? u2 : `${u2}-${i2}`]: o2, ...e2 };
|
|
19263
19281
|
}
|
|
@@ -19283,11 +19301,11 @@ function v(r2, ...m2) {
|
|
|
19283
19301
|
for (const n2 in f2) {
|
|
19284
19302
|
let s2 = a2[n2];
|
|
19285
19303
|
const e2 = f2[n2];
|
|
19286
|
-
if (e2.default !== void 0 && s2 === void 0 && (s2 = e2.default), e2.type === "enum" && ![e2.default, ...e2.values].includes(s2) && !i$
|
|
19304
|
+
if (e2.default !== void 0 && s2 === void 0 && (s2 = e2.default), e2.type === "enum" && ![e2.default, ...e2.values].includes(s2) && !i$4(s2) && (s2 = e2.default), a2[n2] = s2, "className" in e2 && e2.className) {
|
|
19287
19305
|
delete a2[n2];
|
|
19288
19306
|
const u2 = "responsive" in e2;
|
|
19289
|
-
if (!s2 || i$
|
|
19290
|
-
if (i$
|
|
19307
|
+
if (!s2 || i$4(s2) && !u2) continue;
|
|
19308
|
+
if (i$4(s2) && (e2.default !== void 0 && s2.initial === void 0 && (s2.initial = e2.default), e2.type === "enum" && ([e2.default, ...e2.values].includes(s2.initial) || (s2.initial = e2.default))), e2.type === "enum") {
|
|
19291
19309
|
const i2 = g({ allowArbitraryValues: false, value: s2, className: e2.className, propValues: e2.values, parseValue: e2.parseValue });
|
|
19292
19310
|
t2 = y(t2, i2);
|
|
19293
19311
|
continue;
|
|
@@ -19305,18 +19323,18 @@ function v(r2, ...m2) {
|
|
|
19305
19323
|
}
|
|
19306
19324
|
return a2.className = y(t2, r2.className), a2.style = l$2(l2, r2.style), a2;
|
|
19307
19325
|
}
|
|
19308
|
-
const e$
|
|
19309
|
-
const r$
|
|
19310
|
-
const { children: e2, className: s2, asChild: a2, as: n2 = "h1", color: i2, ...m2 } = v(p2, n$7, r$
|
|
19326
|
+
const e$7 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9"], r$9 = { m: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-m", customProperties: ["--m"] }, mx: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-mx", customProperties: ["--ml", "--mr"] }, my: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-my", customProperties: ["--mt", "--mb"] }, mt: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-mt", customProperties: ["--mt"] }, mr: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-mr", customProperties: ["--mr"] }, mb: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-mb", customProperties: ["--mb"] }, ml: { type: "enum | string", values: e$7, responsive: true, className: "rt-r-ml", customProperties: ["--ml"] } };
|
|
19327
|
+
const r$8 = reactExports.forwardRef((p2, t2) => {
|
|
19328
|
+
const { children: e2, className: s2, asChild: a2, as: n2 = "h1", color: i2, ...m2 } = v(p2, n$7, r$9);
|
|
19311
19329
|
return reactExports.createElement(Slot, { "data-accent-color": i2, ...m2, ref: t2, className: y("rt-Heading", s2) }, a2 ? e2 : reactExports.createElement(n2, null, e2));
|
|
19312
19330
|
});
|
|
19313
|
-
r$
|
|
19314
|
-
const m$4 = ["span", "div", "label", "p"], a$8 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], n$6 = { as: { type: "enum", values: m$4, default: "span" }, ...o$
|
|
19315
|
-
const p$
|
|
19316
|
-
const { children: e2, className: s2, asChild: m2, as: a2 = "span", color: n2, ...P2 } = v(t2, n$6, r$
|
|
19331
|
+
r$8.displayName = "Heading";
|
|
19332
|
+
const m$4 = ["span", "div", "label", "p"], a$8 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], n$6 = { as: { type: "enum", values: m$4, default: "span" }, ...o$7, size: { type: "enum", className: "rt-r-size", values: a$8, responsive: true }, ...t$5, ...t$6, ...r$b, ...e$b, ...r$a, ...r$c, ...o$5 };
|
|
19333
|
+
const p$b = reactExports.forwardRef((t2, r2) => {
|
|
19334
|
+
const { children: e2, className: s2, asChild: m2, as: a2 = "span", color: n2, ...P2 } = v(t2, n$6, r$9);
|
|
19317
19335
|
return reactExports.createElement(Slot, { "data-accent-color": n2, ...P2, ref: r2, className: y("rt-Text", s2) }, m2 ? e2 : reactExports.createElement(a2, null, e2));
|
|
19318
19336
|
});
|
|
19319
|
-
p$
|
|
19337
|
+
p$b.displayName = "Text";
|
|
19320
19338
|
function a$7(e2) {
|
|
19321
19339
|
switch (e2) {
|
|
19322
19340
|
case "tomato":
|
|
@@ -19353,7 +19371,7 @@ function a$7(e2) {
|
|
|
19353
19371
|
return "gray";
|
|
19354
19372
|
}
|
|
19355
19373
|
}
|
|
19356
|
-
const e$
|
|
19374
|
+
const e$6 = ["none", "small", "medium", "large", "full"], r$7 = { radius: { type: "enum", values: e$6, default: void 0 } };
|
|
19357
19375
|
const s$4 = { hasBackground: { default: true }, appearance: { default: "inherit" }, accentColor: { default: "indigo" }, grayColor: { default: "auto" }, panelBackground: { default: "translucent" }, radius: { default: "medium" }, scaling: { default: "100%" } };
|
|
19358
19376
|
const d$3 = () => {
|
|
19359
19377
|
}, P$2 = reactExports.createContext(void 0);
|
|
@@ -19385,42 +19403,42 @@ function d$2(i2, e2) {
|
|
|
19385
19403
|
const t2 = reactExports.Children.only(c2);
|
|
19386
19404
|
return reactExports.cloneElement(t2, { children: typeof e2 == "function" ? e2(t2.props.children) : e2 });
|
|
19387
19405
|
}
|
|
19388
|
-
const e$
|
|
19389
|
-
const s$3 = ["div", "span"], o$
|
|
19390
|
-
const e$
|
|
19391
|
-
const r$
|
|
19392
|
-
const p$
|
|
19393
|
-
const { className: t2, asChild: e2, as: m2 = "div", ...a2 } = v(r2, p$
|
|
19394
|
-
return reactExports.createElement(e2 ? e$
|
|
19406
|
+
const e$5 = Slot;
|
|
19407
|
+
const s$3 = ["div", "span"], o$4 = ["none", "inline", "inline-block", "block", "contents"], p$a = { as: { type: "enum", values: s$3, default: "div" }, ...o$7, display: { type: "enum", className: "rt-r-display", values: o$4, responsive: true } };
|
|
19408
|
+
const e$4 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], p$9 = { p: { type: "enum | string", className: "rt-r-p", customProperties: ["--p"], values: e$4, responsive: true }, px: { type: "enum | string", className: "rt-r-px", customProperties: ["--pl", "--pr"], values: e$4, responsive: true }, py: { type: "enum | string", className: "rt-r-py", customProperties: ["--pt", "--pb"], values: e$4, responsive: true }, pt: { type: "enum | string", className: "rt-r-pt", customProperties: ["--pt"], values: e$4, responsive: true }, pr: { type: "enum | string", className: "rt-r-pr", customProperties: ["--pr"], values: e$4, responsive: true }, pb: { type: "enum | string", className: "rt-r-pb", customProperties: ["--pb"], values: e$4, responsive: true }, pl: { type: "enum | string", className: "rt-r-pl", customProperties: ["--pl"], values: e$4, responsive: true } };
|
|
19409
|
+
const r$6 = ["visible", "hidden", "clip", "scroll", "auto"], i$3 = ["static", "relative", "absolute", "fixed", "sticky"], e$3 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9"], p$8 = ["0", "1"], n$5 = ["0", "1"], u$3 = { ...p$9, ...t$7, ...e$f, position: { type: "enum", className: "rt-r-position", values: i$3, responsive: true }, inset: { type: "enum | string", className: "rt-r-inset", customProperties: ["--inset"], values: e$3, responsive: true }, top: { type: "enum | string", className: "rt-r-top", customProperties: ["--top"], values: e$3, responsive: true }, right: { type: "enum | string", className: "rt-r-right", customProperties: ["--right"], values: e$3, responsive: true }, bottom: { type: "enum | string", className: "rt-r-bottom", customProperties: ["--bottom"], values: e$3, responsive: true }, left: { type: "enum | string", className: "rt-r-left", customProperties: ["--left"], values: e$3, responsive: true }, overflow: { type: "enum", className: "rt-r-overflow", values: r$6, responsive: true }, overflowX: { type: "enum", className: "rt-r-ox", values: r$6, responsive: true }, overflowY: { type: "enum", className: "rt-r-oy", values: r$6, responsive: true }, flexBasis: { type: "string", className: "rt-r-fb", customProperties: ["--flex-basis"], responsive: true }, flexShrink: { type: "enum | string", className: "rt-r-fs", customProperties: ["--flex-shrink"], values: p$8, responsive: true }, flexGrow: { type: "enum | string", className: "rt-r-fg", customProperties: ["--flex-grow"], values: n$5, responsive: true }, gridArea: { type: "string", className: "rt-r-ga", customProperties: ["--grid-area"], responsive: true }, gridColumn: { type: "string", className: "rt-r-gc", customProperties: ["--grid-column"], responsive: true }, gridColumnStart: { type: "string", className: "rt-r-gcs", customProperties: ["--grid-column-start"], responsive: true }, gridColumnEnd: { type: "string", className: "rt-r-gce", customProperties: ["--grid-column-end"], responsive: true }, gridRow: { type: "string", className: "rt-r-gr", customProperties: ["--grid-row"], responsive: true }, gridRowStart: { type: "string", className: "rt-r-grs", customProperties: ["--grid-row-start"], responsive: true }, gridRowEnd: { type: "string", className: "rt-r-gre", customProperties: ["--grid-row-end"], responsive: true } };
|
|
19410
|
+
const p$7 = reactExports.forwardRef((r2, s2) => {
|
|
19411
|
+
const { className: t2, asChild: e2, as: m2 = "div", ...a2 } = v(r2, p$a, u$3, r$9);
|
|
19412
|
+
return reactExports.createElement(e2 ? e$5 : m2, { ...a2, ref: s2, className: y("rt-Box", t2) });
|
|
19395
19413
|
});
|
|
19396
|
-
p$
|
|
19397
|
-
const t$4 = ["1", "2", "3", "4"], a$6 = ["classic", "solid", "soft", "surface", "outline", "ghost"], i$
|
|
19398
|
-
const e$
|
|
19399
|
-
const t$3 = ["div", "span"], p$
|
|
19400
|
-
function f$
|
|
19414
|
+
p$7.displayName = "Box";
|
|
19415
|
+
const t$4 = ["1", "2", "3", "4"], a$6 = ["classic", "solid", "soft", "surface", "outline", "ghost"], i$2 = { ...o$7, size: { type: "enum", className: "rt-r-size", values: t$4, default: "2", responsive: true }, variant: { type: "enum", className: "rt-variant", values: a$6, default: "solid" }, ...s$5, ...o$5, ...r$7, loading: { type: "boolean", className: "rt-loading", default: false } };
|
|
19416
|
+
const e$2 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], p$6 = { gap: { type: "enum | string", className: "rt-r-gap", customProperties: ["--gap"], values: e$2, responsive: true }, gapX: { type: "enum | string", className: "rt-r-cg", customProperties: ["--column-gap"], values: e$2, responsive: true }, gapY: { type: "enum | string", className: "rt-r-rg", customProperties: ["--row-gap"], values: e$2, responsive: true } };
|
|
19417
|
+
const t$3 = ["div", "span"], p$5 = ["none", "inline-flex", "flex"], a$5 = ["row", "column", "row-reverse", "column-reverse"], o$3 = ["start", "center", "end", "baseline", "stretch"], n$4 = ["start", "center", "end", "between"], l$1 = ["nowrap", "wrap", "wrap-reverse"], u$2 = { as: { type: "enum", values: t$3, default: "div" }, ...o$7, display: { type: "enum", className: "rt-r-display", values: p$5, responsive: true }, direction: { type: "enum", className: "rt-r-fd", values: a$5, responsive: true }, align: { type: "enum", className: "rt-r-ai", values: o$3, responsive: true }, justify: { type: "enum", className: "rt-r-jc", values: n$4, parseValue: f$5, responsive: true }, wrap: { type: "enum", className: "rt-r-fw", values: l$1, responsive: true }, ...p$6 };
|
|
19418
|
+
function f$5(e2) {
|
|
19401
19419
|
return e2 === "between" ? "space-between" : e2;
|
|
19402
19420
|
}
|
|
19403
|
-
const p$
|
|
19404
|
-
const { className: s2, asChild: t2, as: m2 = "div", ...l2 } = v(r2, u$2, u$3, r$
|
|
19405
|
-
return reactExports.createElement(t2 ? e$
|
|
19421
|
+
const p$4 = reactExports.forwardRef((r2, e2) => {
|
|
19422
|
+
const { className: s2, asChild: t2, as: m2 = "div", ...l2 } = v(r2, u$2, u$3, r$9);
|
|
19423
|
+
return reactExports.createElement(t2 ? e$5 : m2, { ...l2, ref: e2, className: y("rt-Flex", s2) });
|
|
19406
19424
|
});
|
|
19407
|
-
p$
|
|
19408
|
-
const e$
|
|
19425
|
+
p$4.displayName = "Flex";
|
|
19426
|
+
const e$1 = ["1", "2", "3"], s$2 = { size: { type: "enum", className: "rt-r-size", values: e$1, default: "2", responsive: true }, loading: { type: "boolean", default: true } };
|
|
19409
19427
|
const s$1 = reactExports.forwardRef((i2, o2) => {
|
|
19410
|
-
const { className: a2, children: e2, loading: t2, ...m2 } = v(i2, s$2, r$
|
|
19428
|
+
const { className: a2, children: e2, loading: t2, ...m2 } = v(i2, s$2, r$9);
|
|
19411
19429
|
if (!t2) return e2;
|
|
19412
19430
|
const r2 = reactExports.createElement("span", { ...m2, ref: o2, className: y("rt-Spinner", a2) }, reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }), reactExports.createElement("span", { className: "rt-SpinnerLeaf" }));
|
|
19413
|
-
return e2 === void 0 ? r2 : reactExports.createElement(p$
|
|
19431
|
+
return e2 === void 0 ? r2 : reactExports.createElement(p$4, { asChild: true, position: "relative", align: "center", justify: "center" }, reactExports.createElement("span", null, reactExports.createElement("span", { "aria-hidden": true, style: { display: "contents", visibility: "hidden" }, inert: void 0 }, e2), reactExports.createElement(p$4, { asChild: true, align: "center", justify: "center", position: "absolute", inset: "0" }, reactExports.createElement("span", null, r2))));
|
|
19414
19432
|
});
|
|
19415
19433
|
s$1.displayName = "Spinner";
|
|
19416
19434
|
const d$1 = Root$3;
|
|
19417
19435
|
function s(e2, t2) {
|
|
19418
19436
|
if (e2 !== void 0) return typeof e2 == "string" ? t2(e2) : Object.fromEntries(Object.entries(e2).map(([n2, o2]) => [n2, t2(o2)]));
|
|
19419
19437
|
}
|
|
19420
|
-
function p$
|
|
19438
|
+
function p$3(e2) {
|
|
19421
19439
|
return e2 === "3" ? "3" : "2";
|
|
19422
19440
|
}
|
|
19423
|
-
function r$
|
|
19441
|
+
function r$5(e2) {
|
|
19424
19442
|
switch (e2) {
|
|
19425
19443
|
case "1":
|
|
19426
19444
|
return "1";
|
|
@@ -19432,15 +19450,15 @@ function r$6(e2) {
|
|
|
19432
19450
|
}
|
|
19433
19451
|
}
|
|
19434
19452
|
const n$3 = reactExports.forwardRef((t2, p2) => {
|
|
19435
|
-
const { size: i2 = i$
|
|
19436
|
-
return reactExports.createElement(f2, { "data-disabled": s$22 || void 0, "data-accent-color": d2, "data-radius": l2, ...u2, ref: p2, className: y("rt-reset", "rt-BaseButton", a2), disabled: s$22 }, t2.loading ? reactExports.createElement(reactExports.Fragment, null, reactExports.createElement("span", { style: { display: "contents", visibility: "hidden" }, "aria-hidden": true }, e2), reactExports.createElement(d$1, null, e2), reactExports.createElement(p$
|
|
19453
|
+
const { size: i2 = i$2.size.default } = t2, { className: a2, children: e2, asChild: m2, color: d2, radius: l2, disabled: s$22 = t2.loading, ...u2 } = v(t2, i$2, r$9), f2 = m2 ? Slot : "button";
|
|
19454
|
+
return reactExports.createElement(f2, { "data-disabled": s$22 || void 0, "data-accent-color": d2, "data-radius": l2, ...u2, ref: p2, className: y("rt-reset", "rt-BaseButton", a2), disabled: s$22 }, t2.loading ? reactExports.createElement(reactExports.Fragment, null, reactExports.createElement("span", { style: { display: "contents", visibility: "hidden" }, "aria-hidden": true }, e2), reactExports.createElement(d$1, null, e2), reactExports.createElement(p$4, { asChild: true, align: "center", justify: "center", position: "absolute", inset: "0" }, reactExports.createElement("span", null, reactExports.createElement(s$1, { size: s(i2, r$5) })))) : e2);
|
|
19437
19455
|
});
|
|
19438
19456
|
n$3.displayName = "BaseButton";
|
|
19439
|
-
const o$
|
|
19440
|
-
o$
|
|
19441
|
-
const t$2 = ["1", "2", "3"], r$
|
|
19457
|
+
const o$2 = reactExports.forwardRef(({ className: e2, ...n2 }, r2) => reactExports.createElement(n$3, { ...n2, ref: r2, className: y("rt-Button", e2) }));
|
|
19458
|
+
o$2.displayName = "Button";
|
|
19459
|
+
const t$2 = ["1", "2", "3"], r$4 = ["soft", "surface", "outline"], a$4 = { ...o$7, size: { type: "enum", className: "rt-r-size", values: t$2, default: "2", responsive: true }, variant: { type: "enum", className: "rt-variant", values: r$4, default: "soft" }, ...s$5, ...o$5 };
|
|
19442
19460
|
const a$3 = reactExports.createContext({}), n$2 = reactExports.forwardRef((t2, l2) => {
|
|
19443
|
-
const { size: e2 = a$4.size.default } = t2, { asChild: r2, children: C, className: i2, color: c2, ...f2 } = v(t2, a$4, r$
|
|
19461
|
+
const { size: e2 = a$4.size.default } = t2, { asChild: r2, children: C, className: i2, color: c2, ...f2 } = v(t2, a$4, r$9), P2 = r2 ? Slot : "div";
|
|
19444
19462
|
return reactExports.createElement(P2, { "data-accent-color": c2, ...f2, className: y("rt-CalloutRoot", i2), ref: l2 }, reactExports.createElement(a$3.Provider, { value: reactExports.useMemo(() => ({ size: e2 }), [e2]) }, C));
|
|
19445
19463
|
});
|
|
19446
19464
|
n$2.displayName = "Callout.Root";
|
|
@@ -19448,21 +19466,21 @@ const m$3 = reactExports.forwardRef(({ className: t2, ...l2 }, e2) => reactExpor
|
|
|
19448
19466
|
m$3.displayName = "Callout.Icon";
|
|
19449
19467
|
const u$1 = reactExports.forwardRef(({ className: t2, ...l2 }, e2) => {
|
|
19450
19468
|
const { size: r2 } = reactExports.useContext(a$3);
|
|
19451
|
-
return reactExports.createElement(p$
|
|
19469
|
+
return reactExports.createElement(p$b, { as: "p", size: s(r2, p$3), ...l2, asChild: false, ref: e2, className: y("rt-CalloutText", t2) });
|
|
19452
19470
|
});
|
|
19453
19471
|
u$1.displayName = "Callout.Text";
|
|
19454
|
-
const
|
|
19455
|
-
const
|
|
19456
|
-
const { asChild:
|
|
19457
|
-
return reactExports.createElement(
|
|
19472
|
+
const a$2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], i$1 = ["solid", "soft", "outline", "ghost"], f$4 = { ...o$7, size: { type: "enum", className: "rt-r-size", values: a$2, responsive: true }, variant: { type: "enum", className: "rt-variant", values: i$1, default: "soft" }, ...t$5, ...s$5, ...o$5, ...e$b, ...r$a };
|
|
19473
|
+
const p$2 = reactExports.forwardRef((o2, t2) => {
|
|
19474
|
+
const { asChild: s2, className: m2, color: e2, ...d2 } = v(o2, f$4, r$9), n2 = o2.variant === "ghost" ? e2 || void 0 : e2, a2 = s2 ? Slot : "code";
|
|
19475
|
+
return reactExports.createElement(a2, { "data-accent-color": n2, ...d2, ref: t2, className: y("rt-reset", "rt-Code", m2) });
|
|
19458
19476
|
});
|
|
19459
|
-
|
|
19460
|
-
const r$3 = ["1", "2", "3"], t$1 = { ...o$
|
|
19477
|
+
p$2.displayName = "Code";
|
|
19478
|
+
const r$3 = ["1", "2", "3"], t$1 = { ...o$7, size: { values: r$3, default: "1" }, ...r$7, scrollbars: { default: "both" } };
|
|
19461
19479
|
function a$1(r2) {
|
|
19462
19480
|
const { m: t2, mx: m2, my: o2, mt: p2, mr: n2, mb: s2, ml: e2, ...i2 } = r2;
|
|
19463
19481
|
return { m: t2, mx: m2, my: o2, mt: p2, mr: n2, mb: s2, ml: e2, rest: i2 };
|
|
19464
19482
|
}
|
|
19465
|
-
const r$2 = r$
|
|
19483
|
+
const r$2 = r$9.m.values;
|
|
19466
19484
|
function S(s2) {
|
|
19467
19485
|
const [e2, t2] = R$2({ className: "rt-r-m", customProperties: ["--margin"], propValues: r$2, value: s2.m }), [a2, o2] = R$2({ className: "rt-r-mx", customProperties: ["--margin-left", "--margin-right"], propValues: r$2, value: s2.mx }), [l2, i2] = R$2({ className: "rt-r-my", customProperties: ["--margin-top", "--margin-bottom"], propValues: r$2, value: s2.my }), [p2, u2] = R$2({ className: "rt-r-mt", customProperties: ["--margin-top"], propValues: r$2, value: s2.mt }), [n2, c2] = R$2({ className: "rt-r-mr", customProperties: ["--margin-right"], propValues: r$2, value: s2.mr }), [g2, P2] = R$2({ className: "rt-r-mb", customProperties: ["--margin-bottom"], propValues: r$2, value: s2.mb }), [N2, C] = R$2({ className: "rt-r-ml", customProperties: ["--margin-left"], propValues: r$2, value: s2.ml });
|
|
19468
19486
|
return [y(e2, a2, l2, p2, n2, g2, N2), l$2(t2, o2, i2, u2, c2, P2, C)];
|
|
@@ -19472,23 +19490,23 @@ const c$1 = reactExports.forwardRef((n2, S$1) => {
|
|
|
19472
19490
|
return reactExports.createElement(Root, { type: t2, scrollHideDelay: N2, className: y("rt-ScrollAreaRoot", u2, y$1), style: l$2(A2, v2), asChild: a2 }, d$2({ asChild: a2, children: d2 }, (g$1) => reactExports.createElement(reactExports.Fragment, null, reactExports.createElement(Viewport, { ...b2, ref: S$1, className: "rt-ScrollAreaViewport" }, g$1), reactExports.createElement("div", { className: "rt-ScrollAreaViewportFocusRing" }), l2 !== "vertical" ? reactExports.createElement(Scrollbar, { "data-radius": p2, orientation: "horizontal", className: y("rt-ScrollAreaScrollbar", g({ className: "rt-r-size", value: i2, propValues: t$1.size.values })) }, reactExports.createElement(Thumb, { className: "rt-ScrollAreaThumb" })) : null, l2 !== "horizontal" ? reactExports.createElement(Scrollbar, { "data-radius": p2, orientation: "vertical", className: y("rt-ScrollAreaScrollbar", g({ className: "rt-r-size", value: i2, propValues: t$1.size.values })) }, reactExports.createElement(Thumb, { className: "rt-ScrollAreaThumb" })) : null, l2 === "both" ? reactExports.createElement(Corner, { className: "rt-ScrollAreaCorner" }) : null)));
|
|
19473
19491
|
});
|
|
19474
19492
|
c$1.displayName = "ScrollArea";
|
|
19475
|
-
const n$1 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], f$3 = ["auto", "always", "hover", "none"], m$2 = { ...o$
|
|
19493
|
+
const n$1 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"], f$3 = ["auto", "always", "hover", "none"], m$2 = { ...o$7, size: { type: "enum", className: "rt-r-size", values: n$1, responsive: true }, ...t$5, ...r$b, ...e$b, ...r$a, underline: { type: "enum", className: "rt-underline", values: f$3, default: "auto" }, ...s$5, ...o$5 };
|
|
19476
19494
|
const e = reactExports.forwardRef((p2, t2) => {
|
|
19477
19495
|
const { children: r2, className: s2, color: n2, asChild: i2, ...m2 } = v(p2, m$2);
|
|
19478
|
-
return reactExports.createElement(p$
|
|
19496
|
+
return reactExports.createElement(p$b, { ...m2, "data-accent-color": n2, ref: t2, asChild: true, className: y("rt-reset", "rt-Link", s2) }, i2 ? r2 : reactExports.createElement("a", null, r2));
|
|
19479
19497
|
});
|
|
19480
19498
|
e.displayName = "Link";
|
|
19481
|
-
const r$1 = ["1", "2"], t = ["nowrap", "wrap", "wrap-reverse"], o$1 = ["start", "center", "end"], p$1 = { size: { type: "enum", className: "rt-r-size", values: r$1, default: "2", responsive: true }, wrap: { type: "enum", className: "rt-r-fw", values: t, responsive: true }, justify: { type: "enum", className: "rt-r-jc", values: o$1, responsive: true }, ...r$
|
|
19499
|
+
const r$1 = ["1", "2"], t = ["nowrap", "wrap", "wrap-reverse"], o$1 = ["start", "center", "end"], p$1 = { size: { type: "enum", className: "rt-r-size", values: r$1, default: "2", responsive: true }, wrap: { type: "enum", className: "rt-r-fw", values: t, responsive: true }, justify: { type: "enum", className: "rt-r-jc", values: o$1, responsive: true }, ...r$c, ...o$5 };
|
|
19482
19500
|
const r = ["1", "2", "3"], a = ["surface", "ghost"], o = ["auto", "fixed"], n = { size: { type: "enum", className: "rt-r-size", values: r, default: "2", responsive: true }, variant: { type: "enum", className: "rt-variant", values: a, default: "ghost" }, layout: { type: "enum", className: "rt-r-tl", values: o, responsive: true } }, i = ["start", "center", "end", "baseline"], u = { align: { type: "enum", className: "rt-r-va", values: i, parseValue: l, responsive: true } };
|
|
19483
19501
|
function l(e2) {
|
|
19484
19502
|
return { baseline: "baseline", start: "top", center: "middle", end: "bottom" }[e2];
|
|
19485
19503
|
}
|
|
19486
|
-
const p = ["start", "center", "end"], f$2 = { justify: { type: "enum", className: "rt-r-ta", values: p, parseValue: c, responsive: true }, ...t$7, ...p$
|
|
19504
|
+
const p = ["start", "center", "end"], f$2 = { justify: { type: "enum", className: "rt-r-ta", values: p, parseValue: c, responsive: true }, ...t$7, ...p$9 };
|
|
19487
19505
|
function c(e2) {
|
|
19488
19506
|
return { start: "left", center: "center", end: "right" }[e2];
|
|
19489
19507
|
}
|
|
19490
19508
|
const m$1 = reactExports.forwardRef((o2, l2) => {
|
|
19491
|
-
const { layout: a2, ...r2 } = n, { className: C, children: c2, layout: y$1, ...i2 } = v(o2, r2, r$
|
|
19509
|
+
const { layout: a2, ...r2 } = n, { className: C, children: c2, layout: y$1, ...i2 } = v(o2, r2, r$9), w = g({ value: y$1, className: n.layout.className, propValues: n.layout.values });
|
|
19492
19510
|
return reactExports.createElement("div", { ref: l2, className: y("rt-TableRoot", C), ...i2 }, reactExports.createElement(c$1, null, reactExports.createElement("table", { className: y("rt-TableRootTable", w) }, c2)));
|
|
19493
19511
|
});
|
|
19494
19512
|
m$1.displayName = "Table.Root";
|
|
@@ -19517,12 +19535,12 @@ const R = reactExports.forwardRef((o2, l2) => {
|
|
|
19517
19535
|
});
|
|
19518
19536
|
R.displayName = "Table.RowHeaderCell";
|
|
19519
19537
|
const m = reactExports.forwardRef((t2, o2) => {
|
|
19520
|
-
const { className: r2, ...e2 } = v(t2, r$
|
|
19538
|
+
const { className: r2, ...e2 } = v(t2, r$9);
|
|
19521
19539
|
return reactExports.createElement(Root2, { ...e2, ref: o2, className: y("rt-TabsRoot", r2) });
|
|
19522
19540
|
});
|
|
19523
19541
|
m.displayName = "Tabs.Root";
|
|
19524
19542
|
const b = reactExports.forwardRef((t2, o2) => {
|
|
19525
|
-
const { className: r2, color: e2, ...n2 } = v(t2, p$1, r$
|
|
19543
|
+
const { className: r2, color: e2, ...n2 } = v(t2, p$1, r$9);
|
|
19526
19544
|
return reactExports.createElement(List, { "data-accent-color": e2, ...n2, asChild: false, ref: o2, className: y("rt-BaseTabList", "rt-TabsList", r2) });
|
|
19527
19545
|
});
|
|
19528
19546
|
b.displayName = "Tabs.List";
|
|
@@ -19532,7 +19550,7 @@ const P = reactExports.forwardRef((t2, o2) => {
|
|
|
19532
19550
|
});
|
|
19533
19551
|
P.displayName = "Tabs.Trigger";
|
|
19534
19552
|
const f = reactExports.forwardRef((t2, o2) => {
|
|
19535
|
-
const { className: r2, ...e2 } = v(t2, r$
|
|
19553
|
+
const { className: r2, ...e2 } = v(t2, r$9);
|
|
19536
19554
|
return reactExports.createElement(Content, { ...e2, ref: o2, className: y("rt-TabsContent", r2) });
|
|
19537
19555
|
});
|
|
19538
19556
|
f.displayName = "Tabs.Content";
|
|
@@ -19610,8 +19628,9 @@ function derivePipelineMetadata(source = {}) {
|
|
|
19610
19628
|
const pipelineLabel = source?.pipelineLabel ?? (typeof pipelineSlugFromSource === "string" ? humanizePipelineSlug(pipelineSlugFromSource) : null);
|
|
19611
19629
|
const pipelineObject = pipelineValue && typeof pipelineValue === "object" && !Array.isArray(pipelineValue) ? pipelineValue : null;
|
|
19612
19630
|
const pipeline = pipelineObject ?? (typeof pipelineSlugFromSource === "string" ? pipelineSlugFromSource : null);
|
|
19631
|
+
const stringPipeline = typeof pipelineValue === "string" ? pipelineValue : null;
|
|
19613
19632
|
return {
|
|
19614
|
-
pipeline,
|
|
19633
|
+
pipeline: pipeline || stringPipeline,
|
|
19615
19634
|
pipelineSlug: typeof pipelineSlugFromSource === "string" ? pipelineSlugFromSource : null,
|
|
19616
19635
|
pipelineLabel: pipelineLabel || null
|
|
19617
19636
|
};
|
|
@@ -19909,13 +19928,70 @@ function useJobListWithUpdates() {
|
|
|
19909
19928
|
connectionStatus
|
|
19910
19929
|
};
|
|
19911
19930
|
}
|
|
19912
|
-
const
|
|
19913
|
-
|
|
19931
|
+
const TaskState = Object.freeze({
|
|
19932
|
+
PENDING: "pending",
|
|
19933
|
+
RUNNING: "running",
|
|
19934
|
+
DONE: "done",
|
|
19935
|
+
FAILED: "failed"
|
|
19936
|
+
});
|
|
19937
|
+
const JobStatus = Object.freeze({
|
|
19938
|
+
PENDING: "pending",
|
|
19939
|
+
RUNNING: "running",
|
|
19940
|
+
FAILED: "failed",
|
|
19941
|
+
COMPLETE: "complete"
|
|
19942
|
+
});
|
|
19943
|
+
const JobLocation = Object.freeze({
|
|
19944
|
+
PENDING: "pending",
|
|
19945
|
+
CURRENT: "current",
|
|
19946
|
+
COMPLETE: "complete",
|
|
19947
|
+
REJECTED: "rejected"
|
|
19948
|
+
});
|
|
19949
|
+
new Set(Object.values(TaskState));
|
|
19950
|
+
new Set(Object.values(JobStatus));
|
|
19951
|
+
new Set(Object.values(JobLocation));
|
|
19952
|
+
function normalizeTaskState(state) {
|
|
19953
|
+
if (typeof state !== "string") {
|
|
19954
|
+
return TaskState.PENDING;
|
|
19955
|
+
}
|
|
19956
|
+
const normalized = state.toLowerCase().trim();
|
|
19957
|
+
switch (normalized) {
|
|
19958
|
+
case "error":
|
|
19959
|
+
return TaskState.FAILED;
|
|
19960
|
+
case "succeeded":
|
|
19961
|
+
return TaskState.DONE;
|
|
19962
|
+
case TaskState.PENDING:
|
|
19963
|
+
case TaskState.RUNNING:
|
|
19964
|
+
case TaskState.DONE:
|
|
19965
|
+
case TaskState.FAILED:
|
|
19966
|
+
return normalized;
|
|
19967
|
+
default:
|
|
19968
|
+
return TaskState.PENDING;
|
|
19969
|
+
}
|
|
19970
|
+
}
|
|
19971
|
+
function deriveJobStatusFromTasks(tasks) {
|
|
19972
|
+
if (!Array.isArray(tasks) || tasks.length === 0) {
|
|
19973
|
+
return JobStatus.PENDING;
|
|
19974
|
+
}
|
|
19975
|
+
const normalizedStates = tasks.map((task) => normalizeTaskState(task.state));
|
|
19976
|
+
if (normalizedStates.some((state) => state === TaskState.FAILED)) {
|
|
19977
|
+
return JobStatus.FAILED;
|
|
19978
|
+
}
|
|
19979
|
+
if (normalizedStates.some((state) => state === TaskState.RUNNING)) {
|
|
19980
|
+
return JobStatus.RUNNING;
|
|
19981
|
+
}
|
|
19982
|
+
if (normalizedStates.every((state) => state === TaskState.DONE)) {
|
|
19983
|
+
return JobStatus.COMPLETE;
|
|
19984
|
+
}
|
|
19985
|
+
return JobStatus.PENDING;
|
|
19986
|
+
}
|
|
19987
|
+
function normalizeTaskStateWithWarning(raw) {
|
|
19914
19988
|
if (!raw || typeof raw !== "string")
|
|
19915
19989
|
return { state: "pending", warning: "missing_state" };
|
|
19916
|
-
const
|
|
19917
|
-
if (
|
|
19918
|
-
|
|
19990
|
+
const normalizedState = normalizeTaskState(raw);
|
|
19991
|
+
if (raw !== normalizedState) {
|
|
19992
|
+
return { state: normalizedState, warning: `unknown_state:${raw}` };
|
|
19993
|
+
}
|
|
19994
|
+
return { state: normalizedState };
|
|
19919
19995
|
}
|
|
19920
19996
|
function normalizeTasks(rawTasks) {
|
|
19921
19997
|
if (!rawTasks) return { tasks: {}, warnings: [] };
|
|
@@ -19923,7 +19999,7 @@ function normalizeTasks(rawTasks) {
|
|
|
19923
19999
|
if (typeof rawTasks === "object" && !Array.isArray(rawTasks)) {
|
|
19924
20000
|
const tasks = {};
|
|
19925
20001
|
Object.entries(rawTasks).forEach(([name, t2]) => {
|
|
19926
|
-
const ns =
|
|
20002
|
+
const ns = normalizeTaskStateWithWarning(t2 && t2.state);
|
|
19927
20003
|
if (ns.warning) warnings.push(`${name}:${ns.warning}`);
|
|
19928
20004
|
const taskObj = {
|
|
19929
20005
|
name,
|
|
@@ -19945,7 +20021,9 @@ function normalizeTasks(rawTasks) {
|
|
|
19945
20021
|
logs: [],
|
|
19946
20022
|
tmp: []
|
|
19947
20023
|
},
|
|
19948
|
-
artifacts: Array.isArray(t2 && t2.artifacts) ? t2.artifacts.slice() : void 0
|
|
20024
|
+
artifacts: Array.isArray(t2 && t2.artifacts) ? t2.artifacts.slice() : void 0,
|
|
20025
|
+
// Preserve tokenUsage if present
|
|
20026
|
+
...t2 && t2.tokenUsage ? { tokenUsage: t2.tokenUsage } : {}
|
|
19949
20027
|
};
|
|
19950
20028
|
tasks[name] = taskObj;
|
|
19951
20029
|
});
|
|
@@ -19955,7 +20033,7 @@ function normalizeTasks(rawTasks) {
|
|
|
19955
20033
|
const tasks = {};
|
|
19956
20034
|
rawTasks.forEach((t2, idx) => {
|
|
19957
20035
|
const name = t2 && t2.name ? String(t2.name) : `task-${idx}`;
|
|
19958
|
-
const ns =
|
|
20036
|
+
const ns = normalizeTaskStateWithWarning(t2 && t2.state);
|
|
19959
20037
|
if (ns.warning) warnings.push(`${name}:${ns.warning}`);
|
|
19960
20038
|
tasks[name] = {
|
|
19961
20039
|
name,
|
|
@@ -19967,21 +20045,15 @@ function normalizeTasks(rawTasks) {
|
|
|
19967
20045
|
// Preserve stage metadata for DAG visualization
|
|
19968
20046
|
...typeof t2?.currentStage === "string" && t2.currentStage.length > 0 ? { currentStage: t2.currentStage } : {},
|
|
19969
20047
|
...typeof t2?.failedStage === "string" && t2.failedStage.length > 0 ? { failedStage: t2.failedStage } : {},
|
|
19970
|
-
artifacts: Array.isArray(t2 && t2.artifacts) ? t2.artifacts.slice() : void 0
|
|
20048
|
+
artifacts: Array.isArray(t2 && t2.artifacts) ? t2.artifacts.slice() : void 0,
|
|
20049
|
+
// Preserve tokenUsage if present
|
|
20050
|
+
...t2 && t2.tokenUsage ? { tokenUsage: t2.tokenUsage } : {}
|
|
19971
20051
|
};
|
|
19972
20052
|
});
|
|
19973
20053
|
return { tasks, warnings };
|
|
19974
20054
|
}
|
|
19975
20055
|
return { tasks: {}, warnings: ["invalid_tasks_shape"] };
|
|
19976
20056
|
}
|
|
19977
|
-
function deriveStatusFromTasks(tasks) {
|
|
19978
|
-
const taskList = Object.values(tasks);
|
|
19979
|
-
if (!Array.isArray(taskList) || taskList.length === 0) return "pending";
|
|
19980
|
-
if (taskList.some((t2) => t2.state === "failed")) return "failed";
|
|
19981
|
-
if (taskList.some((t2) => t2.state === "running")) return "running";
|
|
19982
|
-
if (taskList.every((t2) => t2.state === "done")) return "complete";
|
|
19983
|
-
return "pending";
|
|
19984
|
-
}
|
|
19985
20057
|
function computeJobSummaryStats(tasks) {
|
|
19986
20058
|
const taskList = Object.values(tasks);
|
|
19987
20059
|
const taskCount = taskList.length;
|
|
@@ -19989,14 +20061,14 @@ function computeJobSummaryStats(tasks) {
|
|
|
19989
20061
|
(acc, t2) => acc + (t2.state === "done" ? 1 : 0),
|
|
19990
20062
|
0
|
|
19991
20063
|
);
|
|
19992
|
-
const status =
|
|
20064
|
+
const status = deriveJobStatusFromTasks(Object.values(tasks));
|
|
19993
20065
|
const progress = taskCount > 0 ? Math.round(doneCount / taskCount * 100) : 0;
|
|
19994
20066
|
return { status, progress, doneCount, taskCount };
|
|
19995
20067
|
}
|
|
19996
20068
|
function adaptJobSummary(apiJob) {
|
|
19997
20069
|
const id = apiJob.jobId;
|
|
19998
20070
|
const name = apiJob.title || "";
|
|
19999
|
-
const rawTasks = apiJob.
|
|
20071
|
+
const rawTasks = apiJob.tasks;
|
|
20000
20072
|
const location = apiJob.location;
|
|
20001
20073
|
const current = apiJob.current;
|
|
20002
20074
|
const currentStage = apiJob.currentStage;
|
|
@@ -20022,13 +20094,25 @@ function adaptJobSummary(apiJob) {
|
|
|
20022
20094
|
const { pipeline, pipelineLabel } = derivePipelineMetadata(apiJob);
|
|
20023
20095
|
if (pipeline != null) job.pipeline = pipeline;
|
|
20024
20096
|
if (pipelineLabel != null) job.pipelineLabel = pipelineLabel;
|
|
20097
|
+
if (apiJob.costsSummary) {
|
|
20098
|
+
job.costsSummary = {
|
|
20099
|
+
totalTokens: apiJob.costsSummary.totalTokens || 0,
|
|
20100
|
+
totalInputTokens: apiJob.costsSummary.totalInputTokens || 0,
|
|
20101
|
+
totalOutputTokens: apiJob.costsSummary.totalOutputTokens || 0,
|
|
20102
|
+
totalCost: apiJob.costsSummary.totalCost || 0,
|
|
20103
|
+
totalInputCost: apiJob.costsSummary.totalInputCost || 0,
|
|
20104
|
+
totalOutputCost: apiJob.costsSummary.totalOutputCost || 0
|
|
20105
|
+
};
|
|
20106
|
+
job.totalCost = job.costsSummary.totalCost;
|
|
20107
|
+
job.totalTokens = job.costsSummary.totalTokens;
|
|
20108
|
+
}
|
|
20025
20109
|
if (warnings.length > 0) job.__warnings = warnings;
|
|
20026
20110
|
return job;
|
|
20027
20111
|
}
|
|
20028
20112
|
function adaptJobDetail(apiDetail) {
|
|
20029
20113
|
const id = apiDetail.jobId;
|
|
20030
20114
|
const name = apiDetail.title || "";
|
|
20031
|
-
const rawTasks = apiDetail.
|
|
20115
|
+
const rawTasks = apiDetail.tasks;
|
|
20032
20116
|
const location = apiDetail.location;
|
|
20033
20117
|
const current = apiDetail.current;
|
|
20034
20118
|
const currentStage = apiDetail.currentStage;
|
|
@@ -20054,104 +20138,12 @@ function adaptJobDetail(apiDetail) {
|
|
|
20054
20138
|
const { pipeline, pipelineLabel } = derivePipelineMetadata(apiDetail);
|
|
20055
20139
|
if (pipeline != null) detail.pipeline = pipeline;
|
|
20056
20140
|
if (pipelineLabel != null) detail.pipelineLabel = pipelineLabel;
|
|
20141
|
+
if (apiDetail.costs) {
|
|
20142
|
+
detail.costs = apiDetail.costs;
|
|
20143
|
+
}
|
|
20057
20144
|
if (warnings.length > 0) detail.__warnings = warnings;
|
|
20058
20145
|
return detail;
|
|
20059
20146
|
}
|
|
20060
|
-
function normalizeState(state) {
|
|
20061
|
-
switch (state) {
|
|
20062
|
-
case "done":
|
|
20063
|
-
return "completed";
|
|
20064
|
-
case "failed":
|
|
20065
|
-
case "error":
|
|
20066
|
-
return "error";
|
|
20067
|
-
case "pending":
|
|
20068
|
-
case "running":
|
|
20069
|
-
case "current":
|
|
20070
|
-
case "completed":
|
|
20071
|
-
case "rejected":
|
|
20072
|
-
return state;
|
|
20073
|
-
default:
|
|
20074
|
-
return state;
|
|
20075
|
-
}
|
|
20076
|
-
}
|
|
20077
|
-
function taskDisplayDurationMs(task, now = Date.now()) {
|
|
20078
|
-
const { state, startedAt, endedAt, executionTime, executionTimeMs } = task;
|
|
20079
|
-
const normalizedState = normalizeState(state);
|
|
20080
|
-
switch (normalizedState) {
|
|
20081
|
-
case "pending":
|
|
20082
|
-
return 0;
|
|
20083
|
-
case "running":
|
|
20084
|
-
case "current":
|
|
20085
|
-
if (!startedAt) {
|
|
20086
|
-
return 0;
|
|
20087
|
-
}
|
|
20088
|
-
const startTime = Date.parse(startedAt);
|
|
20089
|
-
return Math.max(0, now - startTime);
|
|
20090
|
-
case "completed":
|
|
20091
|
-
const execTime = executionTimeMs != null ? executionTimeMs : executionTime;
|
|
20092
|
-
if (typeof execTime === "number" && execTime >= 0) {
|
|
20093
|
-
return execTime;
|
|
20094
|
-
}
|
|
20095
|
-
if (!startedAt) {
|
|
20096
|
-
return 0;
|
|
20097
|
-
}
|
|
20098
|
-
const completedStartTime = Date.parse(startedAt);
|
|
20099
|
-
const endTime = endedAt ? Date.parse(endedAt) : now;
|
|
20100
|
-
return Math.max(0, endTime - completedStartTime);
|
|
20101
|
-
case "rejected":
|
|
20102
|
-
return 0;
|
|
20103
|
-
default:
|
|
20104
|
-
return 0;
|
|
20105
|
-
}
|
|
20106
|
-
}
|
|
20107
|
-
function jobCumulativeDurationMs(job, now = Date.now()) {
|
|
20108
|
-
const { tasks } = job;
|
|
20109
|
-
if (!tasks) {
|
|
20110
|
-
return 0;
|
|
20111
|
-
}
|
|
20112
|
-
let taskList;
|
|
20113
|
-
if (Array.isArray(tasks)) {
|
|
20114
|
-
taskList = tasks;
|
|
20115
|
-
} else if (typeof tasks === "object") {
|
|
20116
|
-
taskList = Object.values(tasks);
|
|
20117
|
-
} else {
|
|
20118
|
-
return 0;
|
|
20119
|
-
}
|
|
20120
|
-
return taskList.reduce((total, task) => {
|
|
20121
|
-
return total + taskDisplayDurationMs(task, now);
|
|
20122
|
-
}, 0);
|
|
20123
|
-
}
|
|
20124
|
-
function fmtDuration(ms) {
|
|
20125
|
-
if (ms <= 0) return "0s";
|
|
20126
|
-
const seconds = Math.floor(ms / 1e3);
|
|
20127
|
-
const minutes = Math.floor(seconds / 60);
|
|
20128
|
-
const hours = Math.floor(minutes / 60);
|
|
20129
|
-
if (hours > 0) {
|
|
20130
|
-
const remainingMinutes = minutes % 60;
|
|
20131
|
-
const remainingSeconds = seconds % 60;
|
|
20132
|
-
if (remainingSeconds > 0) {
|
|
20133
|
-
return `${hours}h ${remainingMinutes}m ${remainingSeconds}s`;
|
|
20134
|
-
} else {
|
|
20135
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
20136
|
-
}
|
|
20137
|
-
} else if (minutes > 0) {
|
|
20138
|
-
return `${minutes}m ${seconds % 60}s`;
|
|
20139
|
-
} else {
|
|
20140
|
-
return `${seconds}s`;
|
|
20141
|
-
}
|
|
20142
|
-
}
|
|
20143
|
-
function useTicker(intervalMs = 1e3) {
|
|
20144
|
-
const [now, setNow] = reactExports.useState(() => Date.now());
|
|
20145
|
-
reactExports.useEffect(() => {
|
|
20146
|
-
const intervalId = setInterval(() => {
|
|
20147
|
-
setNow(Date.now());
|
|
20148
|
-
}, intervalMs);
|
|
20149
|
-
return () => {
|
|
20150
|
-
clearInterval(intervalId);
|
|
20151
|
-
};
|
|
20152
|
-
}, [intervalMs]);
|
|
20153
|
-
return now;
|
|
20154
|
-
}
|
|
20155
20147
|
/**
|
|
20156
20148
|
* @license lucide-react v0.544.0 - ISC
|
|
20157
20149
|
*
|
|
@@ -20257,19 +20249,20 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
20257
20249
|
* This source code is licensed under the ISC license.
|
|
20258
20250
|
* See the LICENSE file in the root directory of this source tree.
|
|
20259
20251
|
*/
|
|
20260
|
-
const __iconNode$3 = [
|
|
20261
|
-
|
|
20262
|
-
["path", { d: "M19 12H5", key: "x3x0zl" }]
|
|
20263
|
-
];
|
|
20264
|
-
const ArrowLeft = createLucideIcon("arrow-left", __iconNode$3);
|
|
20252
|
+
const __iconNode$3 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
|
|
20253
|
+
const ChevronRight = createLucideIcon("chevron-right", __iconNode$3);
|
|
20265
20254
|
/**
|
|
20266
20255
|
* @license lucide-react v0.544.0 - ISC
|
|
20267
20256
|
*
|
|
20268
20257
|
* This source code is licensed under the ISC license.
|
|
20269
20258
|
* See the LICENSE file in the root directory of this source tree.
|
|
20270
20259
|
*/
|
|
20271
|
-
const __iconNode$2 = [
|
|
20272
|
-
|
|
20260
|
+
const __iconNode$2 = [
|
|
20261
|
+
["path", { d: "m18 16 4-4-4-4", key: "1inbqp" }],
|
|
20262
|
+
["path", { d: "m6 8-4 4 4 4", key: "15zrgr" }],
|
|
20263
|
+
["path", { d: "m14.5 4-5 16", key: "e7oirm" }]
|
|
20264
|
+
];
|
|
20265
|
+
const CodeXml = createLucideIcon("code-xml", __iconNode$2);
|
|
20273
20266
|
/**
|
|
20274
20267
|
* @license lucide-react v0.544.0 - ISC
|
|
20275
20268
|
*
|
|
@@ -20277,16 +20270,12 @@ const ChevronRight = createLucideIcon("chevron-right", __iconNode$2);
|
|
|
20277
20270
|
* See the LICENSE file in the root directory of this source tree.
|
|
20278
20271
|
*/
|
|
20279
20272
|
const __iconNode$1 = [
|
|
20280
|
-
["path", { d: "
|
|
20281
|
-
[
|
|
20282
|
-
|
|
20283
|
-
|
|
20284
|
-
d: "M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
|
|
20285
|
-
key: "r6nss1"
|
|
20286
|
-
}
|
|
20287
|
-
]
|
|
20273
|
+
["path", { d: "M10 2h4", key: "n1abiw" }],
|
|
20274
|
+
["path", { d: "M12 14v-4", key: "1evpnu" }],
|
|
20275
|
+
["path", { d: "M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6", key: "1ts96g" }],
|
|
20276
|
+
["path", { d: "M9 17H4v5", key: "8t5av" }]
|
|
20288
20277
|
];
|
|
20289
|
-
const
|
|
20278
|
+
const TimerReset = createLucideIcon("timer-reset", __iconNode$1);
|
|
20290
20279
|
/**
|
|
20291
20280
|
* @license lucide-react v0.544.0 - ISC
|
|
20292
20281
|
*
|
|
@@ -20294,12 +20283,83 @@ const House = createLucideIcon("house", __iconNode$1);
|
|
|
20294
20283
|
* See the LICENSE file in the root directory of this source tree.
|
|
20295
20284
|
*/
|
|
20296
20285
|
const __iconNode = [
|
|
20297
|
-
["path", { d: "
|
|
20298
|
-
["path", { d: "
|
|
20299
|
-
["path", { d: "
|
|
20300
|
-
["path", { d: "M9 17H4v5", key: "8t5av" }]
|
|
20286
|
+
["path", { d: "M12 3v12", key: "1x0j5s" }],
|
|
20287
|
+
["path", { d: "m17 8-5-5-5 5", key: "7q97r8" }],
|
|
20288
|
+
["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }]
|
|
20301
20289
|
];
|
|
20302
|
-
const
|
|
20290
|
+
const Upload = createLucideIcon("upload", __iconNode);
|
|
20291
|
+
function normalizeState(state) {
|
|
20292
|
+
const canonicalState = normalizeTaskState(state);
|
|
20293
|
+
if (canonicalState === TaskState.DONE) {
|
|
20294
|
+
return "completed";
|
|
20295
|
+
}
|
|
20296
|
+
return canonicalState;
|
|
20297
|
+
}
|
|
20298
|
+
function taskDisplayDurationMs(task, now = Date.now()) {
|
|
20299
|
+
const { state, startedAt, endedAt, executionTime, executionTimeMs } = task;
|
|
20300
|
+
const normalizedState = normalizeState(state);
|
|
20301
|
+
switch (normalizedState) {
|
|
20302
|
+
case TaskState.PENDING:
|
|
20303
|
+
return 0;
|
|
20304
|
+
case TaskState.RUNNING:
|
|
20305
|
+
if (!startedAt) {
|
|
20306
|
+
return 0;
|
|
20307
|
+
}
|
|
20308
|
+
const startTime = Date.parse(startedAt);
|
|
20309
|
+
return Math.max(0, now - startTime);
|
|
20310
|
+
case "completed":
|
|
20311
|
+
const execTime = executionTimeMs != null ? executionTimeMs : executionTime;
|
|
20312
|
+
if (typeof execTime === "number" && execTime >= 0) {
|
|
20313
|
+
return execTime;
|
|
20314
|
+
}
|
|
20315
|
+
if (!startedAt) {
|
|
20316
|
+
return 0;
|
|
20317
|
+
}
|
|
20318
|
+
const completedStartTime = Date.parse(startedAt);
|
|
20319
|
+
const endTime = endedAt ? Date.parse(endedAt) : now;
|
|
20320
|
+
return Math.max(0, endTime - completedStartTime);
|
|
20321
|
+
case TaskState.FAILED:
|
|
20322
|
+
return 0;
|
|
20323
|
+
default:
|
|
20324
|
+
return 0;
|
|
20325
|
+
}
|
|
20326
|
+
}
|
|
20327
|
+
function jobCumulativeDurationMs(job, now = Date.now()) {
|
|
20328
|
+
const { tasks } = job;
|
|
20329
|
+
if (!tasks) {
|
|
20330
|
+
return 0;
|
|
20331
|
+
}
|
|
20332
|
+
let taskList;
|
|
20333
|
+
if (Array.isArray(tasks)) {
|
|
20334
|
+
taskList = tasks;
|
|
20335
|
+
} else if (typeof tasks === "object") {
|
|
20336
|
+
taskList = Object.values(tasks);
|
|
20337
|
+
} else {
|
|
20338
|
+
return 0;
|
|
20339
|
+
}
|
|
20340
|
+
return taskList.reduce((total, task) => {
|
|
20341
|
+
return total + taskDisplayDurationMs(task, now);
|
|
20342
|
+
}, 0);
|
|
20343
|
+
}
|
|
20344
|
+
function fmtDuration(ms) {
|
|
20345
|
+
if (ms <= 0) return "0s";
|
|
20346
|
+
const seconds = Math.floor(ms / 1e3);
|
|
20347
|
+
const minutes = Math.floor(seconds / 60);
|
|
20348
|
+
const hours = Math.floor(minutes / 60);
|
|
20349
|
+
if (hours > 0) {
|
|
20350
|
+
const remainingMinutes = minutes % 60;
|
|
20351
|
+
const remainingSeconds = seconds % 60;
|
|
20352
|
+
if (remainingSeconds > 0) {
|
|
20353
|
+
return `${hours}h ${remainingMinutes}m ${remainingSeconds}s`;
|
|
20354
|
+
} else {
|
|
20355
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
20356
|
+
}
|
|
20357
|
+
} else if (minutes > 0) {
|
|
20358
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
20359
|
+
} else {
|
|
20360
|
+
return `${seconds}s`;
|
|
20361
|
+
}
|
|
20362
|
+
}
|
|
20303
20363
|
const countCompleted = (job) => {
|
|
20304
20364
|
const list = Array.isArray(job?.tasks) ? job.tasks : Object.values(job?.tasks || {});
|
|
20305
20365
|
return list.filter((t2) => t2?.state === "done" || t2?.state === "completed").length;
|
|
@@ -20321,42 +20381,209 @@ function Badge({ children, intent = "gray", className = "", ...props }) {
|
|
|
20321
20381
|
}
|
|
20322
20382
|
const statusBadge = (status) => {
|
|
20323
20383
|
switch (status) {
|
|
20324
|
-
case
|
|
20325
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, {
|
|
20326
|
-
case
|
|
20327
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, {
|
|
20328
|
-
case
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "default", "aria-label": "Pending", children: "Pending" });
|
|
20384
|
+
case TaskState.RUNNING:
|
|
20385
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { intent: "blue", "aria-label": "Running", children: "Running" });
|
|
20386
|
+
case TaskState.FAILED:
|
|
20387
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { intent: "red", "aria-label": "Failed", children: "Failed" });
|
|
20388
|
+
case TaskState.DONE:
|
|
20389
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { intent: "green", "aria-label": "Completed", children: "Completed" });
|
|
20390
|
+
case TaskState.PENDING:
|
|
20391
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { intent: "gray", "aria-label": "Pending", children: "Pending" });
|
|
20333
20392
|
default:
|
|
20334
20393
|
return null;
|
|
20335
20394
|
}
|
|
20336
20395
|
};
|
|
20337
20396
|
const progressClasses = (status) => {
|
|
20338
20397
|
switch (status) {
|
|
20339
|
-
case
|
|
20398
|
+
case TaskState.RUNNING:
|
|
20340
20399
|
return "bg-info/20 [&>div]:bg-info";
|
|
20341
|
-
case
|
|
20400
|
+
case TaskState.FAILED:
|
|
20342
20401
|
return "bg-destructive/20 [&>div]:bg-destructive";
|
|
20343
|
-
case
|
|
20402
|
+
case TaskState.DONE:
|
|
20344
20403
|
return "bg-success/20 [&>div]:bg-success";
|
|
20345
20404
|
default:
|
|
20346
20405
|
return "bg-muted [&>div]:bg-muted-foreground";
|
|
20347
20406
|
}
|
|
20348
20407
|
};
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20408
|
+
const offset = Date.now() - performance.now();
|
|
20409
|
+
let currentNow = Math.floor(performance.now() + offset);
|
|
20410
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
20411
|
+
const cadenceHints = /* @__PURE__ */ new Map();
|
|
20412
|
+
let timerId = null;
|
|
20413
|
+
let activeIntervalMs = 1e3;
|
|
20414
|
+
let isBackground = false;
|
|
20415
|
+
function subscribe(listener) {
|
|
20416
|
+
listeners.add(listener);
|
|
20417
|
+
if (listeners.size === 1) {
|
|
20418
|
+
startTimer();
|
|
20419
|
+
}
|
|
20420
|
+
return () => {
|
|
20421
|
+
listeners.delete(listener);
|
|
20422
|
+
if (listeners.size === 0) {
|
|
20423
|
+
stopTimer();
|
|
20424
|
+
}
|
|
20425
|
+
};
|
|
20426
|
+
}
|
|
20427
|
+
function getSnapshot() {
|
|
20428
|
+
return currentNow;
|
|
20429
|
+
}
|
|
20430
|
+
function getServerSnapshot() {
|
|
20431
|
+
return Date.now();
|
|
20432
|
+
}
|
|
20433
|
+
function addCadenceHint(id, ms) {
|
|
20434
|
+
cadenceHints.set(id, ms);
|
|
20435
|
+
recalculateInterval();
|
|
20436
|
+
}
|
|
20437
|
+
function removeCadenceHint(id) {
|
|
20438
|
+
cadenceHints.delete(id);
|
|
20439
|
+
recalculateInterval();
|
|
20440
|
+
}
|
|
20441
|
+
function recalculateInterval() {
|
|
20442
|
+
const minCadence = Math.min(...cadenceHints.values(), 1e3);
|
|
20443
|
+
const newIntervalMs = isBackground ? Math.max(minCadence, 6e4) : minCadence;
|
|
20444
|
+
if (newIntervalMs !== activeIntervalMs) {
|
|
20445
|
+
activeIntervalMs = newIntervalMs;
|
|
20446
|
+
if (listeners.size > 0) {
|
|
20447
|
+
stopTimer();
|
|
20448
|
+
startTimer();
|
|
20449
|
+
}
|
|
20450
|
+
}
|
|
20451
|
+
}
|
|
20452
|
+
function startTimer() {
|
|
20453
|
+
if (timerId !== null) return;
|
|
20454
|
+
const tick = () => {
|
|
20455
|
+
currentNow = Math.floor(performance.now() + offset);
|
|
20456
|
+
listeners.forEach((listener) => {
|
|
20457
|
+
try {
|
|
20458
|
+
listener();
|
|
20459
|
+
} catch (error) {
|
|
20460
|
+
console.error("Error in time store listener:", error);
|
|
20461
|
+
}
|
|
20462
|
+
});
|
|
20463
|
+
};
|
|
20464
|
+
if (activeIntervalMs >= 6e4) {
|
|
20465
|
+
const now = Date.now();
|
|
20466
|
+
const nextMinuteBoundary = Math.ceil(now / 6e4) * 6e4;
|
|
20467
|
+
const initialDelay = nextMinuteBoundary - now;
|
|
20468
|
+
timerId = setTimeout(() => {
|
|
20469
|
+
tick();
|
|
20470
|
+
timerId = setInterval(tick, 6e4);
|
|
20471
|
+
}, initialDelay);
|
|
20472
|
+
} else {
|
|
20473
|
+
timerId = setInterval(tick, activeIntervalMs);
|
|
20474
|
+
}
|
|
20475
|
+
}
|
|
20476
|
+
function stopTimer() {
|
|
20477
|
+
if (timerId !== null) {
|
|
20478
|
+
clearTimeout(timerId);
|
|
20479
|
+
clearInterval(timerId);
|
|
20480
|
+
timerId = null;
|
|
20481
|
+
}
|
|
20482
|
+
}
|
|
20483
|
+
function handleVisibilityChange() {
|
|
20484
|
+
const wasBackground = isBackground;
|
|
20485
|
+
isBackground = document.visibilityState === "hidden";
|
|
20486
|
+
if (wasBackground !== isBackground) {
|
|
20487
|
+
recalculateInterval();
|
|
20488
|
+
}
|
|
20489
|
+
}
|
|
20490
|
+
if (typeof document !== "undefined") {
|
|
20491
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
20492
|
+
}
|
|
20493
|
+
function TimerText({
|
|
20494
|
+
startMs,
|
|
20495
|
+
endMs = null,
|
|
20496
|
+
granularity = "second",
|
|
20497
|
+
format = fmtDuration,
|
|
20498
|
+
className
|
|
20355
20499
|
}) {
|
|
20500
|
+
const id = reactExports.useId();
|
|
20501
|
+
const now = reactExports.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
20502
|
+
const [displayText, setDisplayText] = reactExports.useState(() => {
|
|
20503
|
+
if (!startMs) return "—";
|
|
20504
|
+
const initialEnd = endMs ?? Date.now();
|
|
20505
|
+
const elapsed = Math.max(0, initialEnd - startMs);
|
|
20506
|
+
return format(elapsed);
|
|
20507
|
+
});
|
|
20508
|
+
reactExports.useEffect(() => {
|
|
20509
|
+
if (!startMs) return;
|
|
20510
|
+
const cadenceMs = granularity === "second" ? 1e3 : 6e4;
|
|
20511
|
+
addCadenceHint(id, cadenceMs);
|
|
20512
|
+
return () => {
|
|
20513
|
+
removeCadenceHint(id);
|
|
20514
|
+
};
|
|
20515
|
+
}, [id, granularity, startMs]);
|
|
20516
|
+
reactExports.useEffect(() => {
|
|
20517
|
+
if (!startMs) return;
|
|
20518
|
+
if (endMs !== null) return;
|
|
20519
|
+
const elapsed = Math.max(0, now - startMs);
|
|
20520
|
+
setDisplayText(format(elapsed));
|
|
20521
|
+
}, [now, startMs, endMs, format]);
|
|
20522
|
+
reactExports.useEffect(() => {
|
|
20523
|
+
if (!startMs || endMs === null) return;
|
|
20524
|
+
const elapsed = Math.max(0, endMs - startMs);
|
|
20525
|
+
setDisplayText(format(elapsed));
|
|
20526
|
+
}, [startMs, endMs, format]);
|
|
20527
|
+
if (!startMs) {
|
|
20528
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className, children: "—" });
|
|
20529
|
+
}
|
|
20530
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className, children: displayText });
|
|
20531
|
+
}
|
|
20532
|
+
function LiveText({ compute, cadenceMs = 1e4, className }) {
|
|
20533
|
+
const id = reactExports.useId();
|
|
20534
|
+
const now = reactExports.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
20535
|
+
const [displayText, setDisplayText] = reactExports.useState(() => {
|
|
20536
|
+
return compute(Date.now());
|
|
20537
|
+
});
|
|
20538
|
+
reactExports.useEffect(() => {
|
|
20539
|
+
addCadenceHint(id, cadenceMs);
|
|
20540
|
+
return () => {
|
|
20541
|
+
removeCadenceHint(id);
|
|
20542
|
+
};
|
|
20543
|
+
}, [id, cadenceMs]);
|
|
20544
|
+
reactExports.useEffect(() => {
|
|
20545
|
+
setDisplayText(compute(now));
|
|
20546
|
+
}, [now, compute]);
|
|
20547
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className, children: displayText });
|
|
20548
|
+
}
|
|
20549
|
+
function toMilliseconds(timestamp) {
|
|
20550
|
+
if (timestamp === null || timestamp === void 0) {
|
|
20551
|
+
return null;
|
|
20552
|
+
}
|
|
20553
|
+
if (typeof timestamp === "number") {
|
|
20554
|
+
return isNaN(timestamp) ? null : timestamp;
|
|
20555
|
+
}
|
|
20556
|
+
if (typeof timestamp === "string") {
|
|
20557
|
+
const parsed = Date.parse(timestamp);
|
|
20558
|
+
return isNaN(parsed) ? null : parsed;
|
|
20559
|
+
}
|
|
20560
|
+
return null;
|
|
20561
|
+
}
|
|
20562
|
+
function taskToTimerProps(task) {
|
|
20563
|
+
return {
|
|
20564
|
+
startMs: toMilliseconds(task?.startedAt),
|
|
20565
|
+
endMs: toMilliseconds(task?.endedAt)
|
|
20566
|
+
};
|
|
20567
|
+
}
|
|
20568
|
+
function formatCurrency4$1(x) {
|
|
20569
|
+
if (typeof x !== "number" || x === 0) return "$0.0000";
|
|
20570
|
+
const formatted = x.toFixed(4);
|
|
20571
|
+
return `$${formatted.replace(/\.?0+$/, "")}`;
|
|
20572
|
+
}
|
|
20573
|
+
function formatTokensCompact$1(n2) {
|
|
20574
|
+
if (typeof n2 !== "number" || n2 === 0) return "0 tok";
|
|
20575
|
+
if (n2 >= 1e6) {
|
|
20576
|
+
return `${(n2 / 1e6).toFixed(1).replace(/\.0$/, "")}M tok`;
|
|
20577
|
+
} else if (n2 >= 1e3) {
|
|
20578
|
+
return `${(n2 / 1e3).toFixed(1).replace(/\.0$/, "")}k tok`;
|
|
20579
|
+
}
|
|
20580
|
+
return `${n2} tok`;
|
|
20581
|
+
}
|
|
20582
|
+
function JobTable({ jobs, pipeline, onOpenJob }) {
|
|
20356
20583
|
if (jobs.length === 0) {
|
|
20357
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20584
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { className: "p-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", className: "text-slate-600", children: "No jobs to show here yet." }) });
|
|
20358
20585
|
}
|
|
20359
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20586
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(m$1, { radius: "none", children: [
|
|
20360
20587
|
/* @__PURE__ */ jsxRuntimeExports.jsx(d, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(P$1, { children: [
|
|
20361
20588
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Job Name" }),
|
|
20362
20589
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Pipeline" }),
|
|
@@ -20364,11 +20591,12 @@ function JobTable({
|
|
|
20364
20591
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Current Task" }),
|
|
20365
20592
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Progress" }),
|
|
20366
20593
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Tasks" }),
|
|
20594
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Cost" }),
|
|
20367
20595
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Duration" }),
|
|
20368
20596
|
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { className: "w-12" })
|
|
20369
20597
|
] }) }),
|
|
20370
20598
|
/* @__PURE__ */ jsxRuntimeExports.jsx(b$1, { children: jobs.map((job) => {
|
|
20371
|
-
const jobTitle = job.
|
|
20599
|
+
const jobTitle = job.name;
|
|
20372
20600
|
const taskById = Array.isArray(job.tasks) ? Object.fromEntries(
|
|
20373
20601
|
(job.tasks || []).map((t2) => {
|
|
20374
20602
|
if (typeof t2 === "string") return [t2, { id: t2, name: t2 }];
|
|
@@ -20376,13 +20604,14 @@ function JobTable({
|
|
|
20376
20604
|
})
|
|
20377
20605
|
) : job.tasks || {};
|
|
20378
20606
|
const currentTask = job.current ? taskById[job.current] : void 0;
|
|
20379
|
-
const currentElapsedMs = currentTask ? taskDisplayDurationMs(currentTask, now) : 0;
|
|
20380
20607
|
const totalCompleted = countCompleted(job);
|
|
20381
20608
|
const totalTasks = pipeline?.tasks?.length ?? (Array.isArray(job.tasks) ? job.tasks.length : Object.keys(job.tasks || {}).length);
|
|
20382
20609
|
const progress = Number.isFinite(job.progress) ? Math.round(job.progress) : 0;
|
|
20383
|
-
const duration = overallElapsed(job);
|
|
20384
20610
|
const currentTaskName = currentTask ? currentTask.name ?? currentTask.id ?? job.current : void 0;
|
|
20385
20611
|
const currentTaskConfig = job.current && (currentTask?.config || pipeline?.taskConfig?.[job.current]) || {};
|
|
20612
|
+
const costsSummary = job.costsSummary || {};
|
|
20613
|
+
const totalCost = job.totalCost || costsSummary.totalCost || 0;
|
|
20614
|
+
const totalTokens = job.totalTokens || costsSummary.totalTokens || 0;
|
|
20386
20615
|
const hasValidId = Boolean(job.id);
|
|
20387
20616
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20388
20617
|
P$1,
|
|
@@ -20394,24 +20623,38 @@ function JobTable({
|
|
|
20394
20623
|
"aria-label": hasValidId ? `Open ${jobTitle}` : `${jobTitle} - No valid job ID, cannot open details`,
|
|
20395
20624
|
title: hasValidId ? void 0 : "This job cannot be opened because it lacks a valid ID",
|
|
20396
20625
|
children: [
|
|
20397
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20398
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20399
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20626
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { direction: "column", gap: "1", children: [
|
|
20627
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", weight: "medium", className: "text-slate-900", children: jobTitle }),
|
|
20628
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "1", className: "text-slate-500", children: job.id })
|
|
20400
20629
|
] }) }),
|
|
20401
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20402
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20403
|
-
job.pipelineLabel && job.pipeline && /* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20630
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { direction: "column", gap: "1", children: [
|
|
20631
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", className: "text-slate-900", children: job.pipelineLabel || job.pipeline || "—" }),
|
|
20632
|
+
job.pipelineLabel && job.pipeline && /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "1", className: "text-slate-500", children: job.pipeline })
|
|
20404
20633
|
] }) }),
|
|
20405
20634
|
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: statusBadge(job.status) }),
|
|
20406
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20407
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20408
|
-
currentTask && /* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
20635
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { direction: "column", gap: "1", children: [
|
|
20636
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", className: "text-slate-700", children: currentTaskName ? currentTaskName : job.status === "done" ? "—" : job.current ?? "—" }),
|
|
20637
|
+
currentTask && /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "1", className: "text-slate-500", children: [
|
|
20409
20638
|
currentTaskConfig?.model || currentTask?.model,
|
|
20410
20639
|
currentTaskConfig?.temperature != null || currentTask?.temperature != null ? `temp ${currentTaskConfig?.temperature ?? currentTask?.temperature}` : null,
|
|
20411
|
-
|
|
20412
|
-
|
|
20640
|
+
(() => {
|
|
20641
|
+
const { startMs, endMs } = taskToTimerProps(currentTask);
|
|
20642
|
+
return startMs ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20643
|
+
TimerText,
|
|
20644
|
+
{
|
|
20645
|
+
startMs,
|
|
20646
|
+
endMs,
|
|
20647
|
+
granularity: "second",
|
|
20648
|
+
className: "text-slate-500"
|
|
20649
|
+
}
|
|
20650
|
+
) : null;
|
|
20651
|
+
})()
|
|
20652
|
+
].filter(Boolean).map((item, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(React.Fragment, { children: [
|
|
20653
|
+
typeof item === "string" ? item : item,
|
|
20654
|
+
index2 < 2 && " · "
|
|
20655
|
+
] }, index2)) })
|
|
20413
20656
|
] }) }),
|
|
20414
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20657
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { direction: "column", gap: "2", className: "w-32", children: [
|
|
20415
20658
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20416
20659
|
Progress,
|
|
20417
20660
|
{
|
|
@@ -20420,22 +20663,33 @@ function JobTable({
|
|
|
20420
20663
|
"aria-label": `Progress ${progress}%`
|
|
20421
20664
|
}
|
|
20422
20665
|
),
|
|
20423
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20666
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { size: "1", className: "text-slate-500", children: [
|
|
20424
20667
|
progress,
|
|
20425
20668
|
"%"
|
|
20426
20669
|
] })
|
|
20427
20670
|
] }) }),
|
|
20428
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20671
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { size: "2", className: "text-slate-700", children: [
|
|
20429
20672
|
totalCompleted,
|
|
20430
20673
|
" of ",
|
|
20431
20674
|
totalTasks
|
|
20432
20675
|
] }) }),
|
|
20433
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20676
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { direction: "column", gap: "1", children: [
|
|
20677
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", className: "text-slate-700", children: totalCost > 0 ? formatCurrency4$1(totalCost) : "—" }),
|
|
20678
|
+
totalTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "1", className: "text-slate-500", children: formatTokensCompact$1(totalTokens) })
|
|
20679
|
+
] }) }),
|
|
20680
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { align: "center", gap: "1", children: [
|
|
20434
20681
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TimerReset, { className: "h-3 w-3 text-slate-500" }),
|
|
20435
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20682
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20683
|
+
LiveText,
|
|
20684
|
+
{
|
|
20685
|
+
cadenceMs: 1e4,
|
|
20686
|
+
compute: (now) => fmtDuration(jobCumulativeDurationMs(job, now)),
|
|
20687
|
+
className: "text-slate-700"
|
|
20688
|
+
}
|
|
20689
|
+
)
|
|
20436
20690
|
] }) }),
|
|
20437
20691
|
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20438
|
-
o$
|
|
20692
|
+
o$2,
|
|
20439
20693
|
{
|
|
20440
20694
|
variant: "ghost",
|
|
20441
20695
|
size: "1",
|
|
@@ -20462,7 +20716,7 @@ function Button({
|
|
|
20462
20716
|
const color = variant === "destructive" ? "red" : void 0;
|
|
20463
20717
|
const combinedClassName = `transition-colors duration-200 ${className}`;
|
|
20464
20718
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20465
|
-
o$
|
|
20719
|
+
o$2,
|
|
20466
20720
|
{
|
|
20467
20721
|
variant: radixVariant,
|
|
20468
20722
|
size: radixSize,
|
|
@@ -20472,34 +20726,93 @@ function Button({
|
|
|
20472
20726
|
}
|
|
20473
20727
|
);
|
|
20474
20728
|
}
|
|
20475
|
-
const
|
|
20476
|
-
|
|
20477
|
-
|
|
20478
|
-
|
|
20479
|
-
|
|
20480
|
-
|
|
20481
|
-
|
|
20729
|
+
const Logo = () => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20730
|
+
"svg",
|
|
20731
|
+
{
|
|
20732
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
20733
|
+
width: "100%",
|
|
20734
|
+
height: "100%",
|
|
20735
|
+
viewBox: "0 0 1200 1200",
|
|
20736
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20737
|
+
"path",
|
|
20738
|
+
{
|
|
20739
|
+
fill: "#009966",
|
|
20740
|
+
d: "M406.13 988.31c-17.297 75.047-84.562 131.11-164.86 131.11-93.375 0-169.18-75.797-169.18-169.18s75.797-169.18 169.18-169.18 169.18 75.797 169.18 169.18v1.266h447.74v-167.9H671.63c-14.859 0-29.062-5.906-39.562-16.406s-16.406-24.703-16.406-39.562v-37.312h-317.16c-10.312 0-18.656-8.344-18.656-18.656V355.78h-147.94c-14.859 0-29.062-5.906-39.562-16.406s-16.406-24.75-16.406-39.562v-111.94c0-14.859 5.906-29.109 16.406-39.562 10.5-10.5 24.75-16.406 39.562-16.406h391.78c14.859 0 29.062 5.906 39.562 16.406s16.406 24.75 16.406 39.562v37.312h202.4c9.281-84.609 81.094-150.52 168.14-150.52 93.375 0 169.18 75.797 169.18 169.18s-75.797 169.18-169.18 169.18c-87.047 0-158.86-65.906-168.14-150.52h-202.4v37.312c0 14.859-5.906 29.062-16.406 39.562s-24.75 16.406-39.562 16.406h-206.53v297.24h298.5v-37.312c0-14.859 5.906-29.062 16.406-39.562s24.703-16.406 39.562-16.406h392.63c14.859 0 29.062 5.906 39.562 16.406s16.406 24.703 16.406 39.562v111.94c0 14.859-5.906 29.062-16.406 39.562s-24.75 16.406-39.562 16.406h-168.74v186.56c0 10.312-8.344 18.656-18.656 18.656h-466.4c-1.5 0-2.906-.187-4.312-.516zM225.19 262.45h18.656c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656H225.19c-10.312 0-18.656 8.344-18.656 18.656s8.344 18.656 18.656 18.656zm186.56 0h18.656c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656H411.75c-10.312 0-18.656 8.344-18.656 18.656s8.344 18.656 18.656 18.656zm-93.281 0h18.656c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656h-18.656c-10.312 0-18.656 8.344-18.656 18.656s8.344 18.656 18.656 18.656zm616.18 0h85.5c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656h-85.5l29.062-22.594c8.109-6.328 9.609-18.047 3.281-26.156s-18.047-9.609-26.156-3.281l-71.953 55.969a18.61 18.61 0 0 0 0 29.438l71.953 55.969c8.109 6.328 19.875 4.875 26.156-3.281 6.328-8.109 4.875-19.875-3.281-26.203l-29.062-22.594zm-779.95 696.66l50.391 50.391c7.266 7.313 19.078 7.313 26.391 0l100.73-100.73c7.266-7.266 7.266-19.078 0-26.391-7.266-7.266-19.078-7.266-26.391 0l-87.562 87.562-37.172-37.172c-7.266-7.266-19.078-7.266-26.391 0-7.266 7.266-7.266 19.078 0 26.391zm797.21-268.78h18.656c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656h-18.656c-10.312 0-18.656 8.344-18.656 18.656s8.344 18.656 18.656 18.656zm-186.56 0h18.656c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656h-18.656c-10.312 0-18.656 8.344-18.656 18.656s8.344 18.656 18.656 18.656zm93.281 0h18.656c10.312 0 18.656-8.344 18.656-18.656s-8.344-18.656-18.656-18.656H858.63c-10.312 0-18.656 8.344-18.656 18.656s8.344 18.656 18.656 18.656z",
|
|
20741
|
+
fillRule: "evenodd"
|
|
20742
|
+
}
|
|
20743
|
+
)
|
|
20482
20744
|
}
|
|
20483
|
-
|
|
20484
|
-
|
|
20485
|
-
|
|
20486
|
-
|
|
20487
|
-
|
|
20488
|
-
|
|
20489
|
-
|
|
20490
|
-
|
|
20491
|
-
|
|
20492
|
-
|
|
20493
|
-
|
|
20494
|
-
|
|
20495
|
-
|
|
20496
|
-
|
|
20497
|
-
|
|
20498
|
-
|
|
20499
|
-
|
|
20500
|
-
|
|
20501
|
-
|
|
20502
|
-
|
|
20745
|
+
);
|
|
20746
|
+
function PageSubheader({
|
|
20747
|
+
breadcrumbs = [],
|
|
20748
|
+
children,
|
|
20749
|
+
maxWidth = "max-w-7xl"
|
|
20750
|
+
}) {
|
|
20751
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20752
|
+
p$7,
|
|
20753
|
+
{
|
|
20754
|
+
role: "region",
|
|
20755
|
+
"aria-label": "Page header",
|
|
20756
|
+
className: "border-b border-gray-300 bg-gray-1/60 backdrop-blur supports-[backdrop-filter]:bg-gray-1/40 mb-4",
|
|
20757
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20758
|
+
p$4,
|
|
20759
|
+
{
|
|
20760
|
+
align: "center",
|
|
20761
|
+
justify: "between",
|
|
20762
|
+
className: `mx-auto w-full ${maxWidth} px-1.5 py-3`,
|
|
20763
|
+
gap: "4",
|
|
20764
|
+
wrap: "wrap",
|
|
20765
|
+
children: [
|
|
20766
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", gap: "3", className: "min-w-0 flex-1", children: breadcrumbs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("nav", { "aria-label": "Breadcrumb", className: "shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("ol", { className: "flex items-center gap-2 text-sm text-gray-11", children: breadcrumbs.map((crumb, index2) => {
|
|
20767
|
+
const isLast = index2 === breadcrumbs.length - 1;
|
|
20768
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(React.Fragment, { children: [
|
|
20769
|
+
index2 > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20770
|
+
ChevronRight,
|
|
20771
|
+
{
|
|
20772
|
+
className: "h-4 w-4 text-gray-9",
|
|
20773
|
+
"aria-hidden": "true"
|
|
20774
|
+
}
|
|
20775
|
+
),
|
|
20776
|
+
crumb.href ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20777
|
+
Link,
|
|
20778
|
+
{
|
|
20779
|
+
to: crumb.href,
|
|
20780
|
+
className: "hover:text-gray-12 transition-colors underline-offset-4 hover:underline",
|
|
20781
|
+
children: crumb.label
|
|
20782
|
+
}
|
|
20783
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20784
|
+
p$b,
|
|
20785
|
+
{
|
|
20786
|
+
as: "span",
|
|
20787
|
+
"aria-current": isLast ? "page" : void 0,
|
|
20788
|
+
className: isLast ? "text-gray-12 font-medium" : "",
|
|
20789
|
+
children: crumb.label
|
|
20790
|
+
}
|
|
20791
|
+
)
|
|
20792
|
+
] }, index2);
|
|
20793
|
+
}) }) }) }),
|
|
20794
|
+
children && /* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", gap: "3", className: "shrink-0", children })
|
|
20795
|
+
]
|
|
20796
|
+
}
|
|
20797
|
+
)
|
|
20798
|
+
}
|
|
20799
|
+
);
|
|
20800
|
+
}
|
|
20801
|
+
const normalizeUploadError = (err) => {
|
|
20802
|
+
if (!err) return "Upload failed";
|
|
20803
|
+
if (typeof err === "string") return err;
|
|
20804
|
+
if (err instanceof Error) return err.message;
|
|
20805
|
+
if (typeof err === "object") {
|
|
20806
|
+
if ("message" in err && err.message) return String(err.message);
|
|
20807
|
+
if ("error" in err && err.error) return String(err.error);
|
|
20808
|
+
}
|
|
20809
|
+
return "Upload failed";
|
|
20810
|
+
};
|
|
20811
|
+
function UploadSeed({ onUploadSuccess }) {
|
|
20812
|
+
const fileInputRef = React.useRef(null);
|
|
20813
|
+
const [error, setError] = reactExports.useState(null);
|
|
20814
|
+
const handleFileChange = async (event) => {
|
|
20815
|
+
const files = event.target.files;
|
|
20503
20816
|
if (!files || files.length === 0) return;
|
|
20504
20817
|
const file = files[0];
|
|
20505
20818
|
try {
|
|
@@ -20558,7 +20871,7 @@ function UploadSeed({ onUploadSuccess }) {
|
|
|
20558
20871
|
};
|
|
20559
20872
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "upload-seed", className: "space-y-3", children: [
|
|
20560
20873
|
error && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20561
|
-
p$
|
|
20874
|
+
p$7,
|
|
20562
20875
|
{
|
|
20563
20876
|
role: "alert",
|
|
20564
20877
|
"data-testid": "upload-error",
|
|
@@ -20631,80 +20944,62 @@ function UploadSeed({ onUploadSuccess }) {
|
|
|
20631
20944
|
onChange: handleFileChange,
|
|
20632
20945
|
"data-testid": "file-input"
|
|
20633
20946
|
}
|
|
20634
|
-
)
|
|
20635
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-gray-200 rounded-lg overflow-hidden", children: [
|
|
20636
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20637
|
-
"button",
|
|
20638
|
-
{
|
|
20639
|
-
type: "button",
|
|
20640
|
-
onClick: () => setShowSample(!showSample),
|
|
20641
|
-
className: "w-full px-4 py-3 text-left bg-gray-50 hover:bg-gray-100 transition-colors flex items-center justify-between",
|
|
20642
|
-
"aria-expanded": showSample,
|
|
20643
|
-
"data-testid": "sample-toggle",
|
|
20644
|
-
children: [
|
|
20645
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-700", children: "Need help? View sample seed file structure" }),
|
|
20646
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20647
|
-
"svg",
|
|
20648
|
-
{
|
|
20649
|
-
className: `w-4 h-4 text-gray-500 transition-transform ${showSample ? "rotate-180" : ""}`,
|
|
20650
|
-
fill: "none",
|
|
20651
|
-
viewBox: "0 0 24 24",
|
|
20652
|
-
stroke: "currentColor",
|
|
20653
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20654
|
-
"path",
|
|
20655
|
-
{
|
|
20656
|
-
strokeLinecap: "round",
|
|
20657
|
-
strokeLinejoin: "round",
|
|
20658
|
-
strokeWidth: 2,
|
|
20659
|
-
d: "M19 9l-7 7-7-7"
|
|
20660
|
-
}
|
|
20661
|
-
)
|
|
20662
|
-
}
|
|
20663
|
-
)
|
|
20664
|
-
]
|
|
20665
|
-
}
|
|
20666
|
-
),
|
|
20667
|
-
showSample && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-white border-t border-gray-200", children: [
|
|
20668
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
20669
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-600", children: "Use this structure as a reference for your seed file:" }),
|
|
20670
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20671
|
-
"button",
|
|
20672
|
-
{
|
|
20673
|
-
type: "button",
|
|
20674
|
-
onClick: () => navigator.clipboard.writeText(
|
|
20675
|
-
JSON.stringify(sampleSeed, null, 2)
|
|
20676
|
-
),
|
|
20677
|
-
className: "text-xs bg-blue-100 text-blue-700 px-2 py-1 rounded hover:bg-blue-200 transition-colors",
|
|
20678
|
-
"data-testid": "copy-sample",
|
|
20679
|
-
children: "Copy"
|
|
20680
|
-
}
|
|
20681
|
-
)
|
|
20682
|
-
] }),
|
|
20683
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs bg-gray-50 p-3 rounded overflow-auto max-h-60", children: JSON.stringify(sampleSeed, null, 2) })
|
|
20684
|
-
] })
|
|
20685
|
-
] })
|
|
20947
|
+
)
|
|
20686
20948
|
] });
|
|
20687
20949
|
}
|
|
20688
20950
|
function Layout({
|
|
20689
20951
|
children,
|
|
20690
20952
|
title,
|
|
20953
|
+
pageTitle,
|
|
20954
|
+
breadcrumbs,
|
|
20691
20955
|
actions,
|
|
20692
|
-
showBackButton = false,
|
|
20693
20956
|
backTo = "/",
|
|
20694
20957
|
maxWidth = "max-w-7xl"
|
|
20695
20958
|
}) {
|
|
20696
20959
|
const navigate = useNavigate();
|
|
20697
20960
|
const location = useLocation();
|
|
20961
|
+
const [isUploadOpen, setIsUploadOpen] = reactExports.useState(false);
|
|
20962
|
+
const [seedUploadSuccess, setSeedUploadSuccess] = reactExports.useState(null);
|
|
20963
|
+
const [seedUploadTimer, setSeedUploadTimer] = reactExports.useState(null);
|
|
20964
|
+
const uploadPanelRef = reactExports.useRef(null);
|
|
20698
20965
|
const isActivePath = (path) => {
|
|
20699
|
-
if (location.pathname
|
|
20966
|
+
if (location.pathname.startsWith(path)) return true;
|
|
20700
20967
|
return false;
|
|
20701
20968
|
};
|
|
20702
|
-
const
|
|
20703
|
-
|
|
20969
|
+
const toggleUploadPanel = () => {
|
|
20970
|
+
setIsUploadOpen(!isUploadOpen);
|
|
20971
|
+
};
|
|
20972
|
+
const handleSeedUploadSuccess = ({ jobName }) => {
|
|
20973
|
+
if (seedUploadTimer) {
|
|
20974
|
+
clearTimeout(seedUploadTimer);
|
|
20975
|
+
}
|
|
20976
|
+
setSeedUploadSuccess(jobName);
|
|
20977
|
+
const timer = setTimeout(() => {
|
|
20978
|
+
setSeedUploadSuccess(null);
|
|
20979
|
+
setSeedUploadTimer(null);
|
|
20980
|
+
}, 5e3);
|
|
20981
|
+
setSeedUploadTimer(timer);
|
|
20704
20982
|
};
|
|
20705
|
-
|
|
20983
|
+
reactExports.useEffect(() => {
|
|
20984
|
+
return () => {
|
|
20985
|
+
if (seedUploadTimer) {
|
|
20986
|
+
clearTimeout(seedUploadTimer);
|
|
20987
|
+
}
|
|
20988
|
+
};
|
|
20989
|
+
}, [seedUploadTimer]);
|
|
20990
|
+
reactExports.useEffect(() => {
|
|
20991
|
+
if (isUploadOpen && uploadPanelRef.current) {
|
|
20992
|
+
const uploadArea = uploadPanelRef.current.querySelector(
|
|
20993
|
+
'[data-testid="upload-area"]'
|
|
20994
|
+
);
|
|
20995
|
+
if (uploadArea) {
|
|
20996
|
+
uploadArea.focus();
|
|
20997
|
+
}
|
|
20998
|
+
}
|
|
20999
|
+
}, [isUploadOpen]);
|
|
21000
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Provider, { delayDuration: 200, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { className: "min-h-screen bg-gray-1", children: [
|
|
20706
21001
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20707
|
-
p$
|
|
21002
|
+
p$7,
|
|
20708
21003
|
{
|
|
20709
21004
|
as: "a",
|
|
20710
21005
|
href: "#main-content",
|
|
@@ -20713,40 +21008,55 @@ function Layout({
|
|
|
20713
21008
|
}
|
|
20714
21009
|
),
|
|
20715
21010
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20716
|
-
p$
|
|
21011
|
+
p$7,
|
|
20717
21012
|
{
|
|
20718
21013
|
role: "banner",
|
|
20719
21014
|
className: "sticky top-0 z-20 border-b border-gray-300 bg-gray-1/80 backdrop-blur supports-[backdrop-filter]:bg-gray-1/60",
|
|
20720
21015
|
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20721
|
-
p$
|
|
21016
|
+
p$4,
|
|
20722
21017
|
{
|
|
20723
21018
|
align: "center",
|
|
20724
21019
|
justify: "between",
|
|
20725
21020
|
className: `mx-auto w-full ${maxWidth} px-4 sm:px-6 lg:px-8 py-4`,
|
|
20726
21021
|
gap: "4",
|
|
20727
21022
|
children: [
|
|
20728
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20729
|
-
|
|
20730
|
-
|
|
20731
|
-
|
|
20732
|
-
|
|
20733
|
-
|
|
20734
|
-
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
21023
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { align: "center", className: "min-w-0 flex-1", children: [
|
|
21024
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21025
|
+
p$7,
|
|
21026
|
+
{
|
|
21027
|
+
asChild: true,
|
|
21028
|
+
className: "shrink-0",
|
|
21029
|
+
style: { width: "80px", height: "60px" },
|
|
21030
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21031
|
+
Link,
|
|
21032
|
+
{
|
|
21033
|
+
to: "/",
|
|
21034
|
+
"aria-label": "Go to homepage",
|
|
21035
|
+
className: "rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500",
|
|
21036
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Logo, {})
|
|
21037
|
+
}
|
|
21038
|
+
)
|
|
21039
|
+
}
|
|
21040
|
+
),
|
|
20743
21041
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20744
|
-
|
|
21042
|
+
p$7,
|
|
20745
21043
|
{
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
children:
|
|
21044
|
+
asChild: true,
|
|
21045
|
+
className: "shrink-0 cursor-pointer hover:bg-gray-3 rounded p-1 -m-1 transition-colors",
|
|
21046
|
+
onClick: () => navigate("/"),
|
|
21047
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21048
|
+
r$8,
|
|
21049
|
+
{
|
|
21050
|
+
size: "6",
|
|
21051
|
+
weight: "medium",
|
|
21052
|
+
className: "text-gray-12 truncate",
|
|
21053
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
21054
|
+
"Prompt",
|
|
21055
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
21056
|
+
"Pipeline"
|
|
21057
|
+
] })
|
|
21058
|
+
}
|
|
21059
|
+
)
|
|
20750
21060
|
}
|
|
20751
21061
|
)
|
|
20752
21062
|
] }),
|
|
@@ -20756,21 +21066,66 @@ function Layout({
|
|
|
20756
21066
|
role: "navigation",
|
|
20757
21067
|
"aria-label": "Main navigation",
|
|
20758
21068
|
className: "hidden md:flex",
|
|
20759
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$
|
|
21069
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", gap: "6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20760
21070
|
e,
|
|
20761
21071
|
{
|
|
20762
|
-
href: "/",
|
|
20763
|
-
className: `text-sm font-medium transition-colors hover:text-blue-600 ${isActivePath() ? "text-blue-600" : "text-gray-11 hover:text-gray-12"}`,
|
|
20764
|
-
"aria-current": isActivePath() ? "page" : void 0,
|
|
20765
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
20766
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20767
|
-
"
|
|
21072
|
+
href: "/code",
|
|
21073
|
+
className: `text-sm font-medium transition-colors hover:text-blue-600 ${isActivePath("/code") ? "text-blue-600" : "text-gray-11 hover:text-gray-12"}`,
|
|
21074
|
+
"aria-current": isActivePath("/code") ? "page" : void 0,
|
|
21075
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { align: "center", gap: "2", children: [
|
|
21076
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { className: "h-4 w-4" }),
|
|
21077
|
+
"Help"
|
|
20768
21078
|
] })
|
|
20769
21079
|
}
|
|
20770
21080
|
) })
|
|
20771
21081
|
}
|
|
20772
21082
|
),
|
|
20773
|
-
|
|
21083
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { align: "center", gap: "3", className: "shrink-0", children: [
|
|
21084
|
+
actions,
|
|
21085
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Root3, { delayDuration: 200, children: [
|
|
21086
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21087
|
+
Button,
|
|
21088
|
+
{
|
|
21089
|
+
size: "sm",
|
|
21090
|
+
variant: "default",
|
|
21091
|
+
onClick: toggleUploadPanel,
|
|
21092
|
+
"aria-controls": "layout-upload-panel",
|
|
21093
|
+
"aria-expanded": isUploadOpen,
|
|
21094
|
+
children: [
|
|
21095
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "h-4 w-4" }),
|
|
21096
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", className: "ml-2", children: "Upload Seed" })
|
|
21097
|
+
]
|
|
21098
|
+
}
|
|
21099
|
+
) }),
|
|
21100
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Content2, { side: "bottom", sideOffset: 5, children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", children: "Upload seed file" }) })
|
|
21101
|
+
] })
|
|
21102
|
+
] })
|
|
21103
|
+
]
|
|
21104
|
+
}
|
|
21105
|
+
)
|
|
21106
|
+
}
|
|
21107
|
+
),
|
|
21108
|
+
isUploadOpen && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21109
|
+
p$7,
|
|
21110
|
+
{
|
|
21111
|
+
id: "layout-upload-panel",
|
|
21112
|
+
ref: uploadPanelRef,
|
|
21113
|
+
role: "region",
|
|
21114
|
+
"aria-label": "Upload seed file",
|
|
21115
|
+
className: "bg-blue-50",
|
|
21116
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21117
|
+
p$4,
|
|
21118
|
+
{
|
|
21119
|
+
direction: "column",
|
|
21120
|
+
gap: "3",
|
|
21121
|
+
className: `mx-auto w-full ${maxWidth} px-4 sm:px-6 lg:px-8 py-4`,
|
|
21122
|
+
children: [
|
|
21123
|
+
seedUploadSuccess && /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { className: "rounded-md bg-green-50 p-3 border border-green-200", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { size: "2", className: "text-green-800", children: [
|
|
21124
|
+
"Job ",
|
|
21125
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: seedUploadSuccess }),
|
|
21126
|
+
" created successfully"
|
|
21127
|
+
] }) }),
|
|
21128
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(UploadSeed, { onUploadSuccess: handleSeedUploadSuccess })
|
|
20774
21129
|
]
|
|
20775
21130
|
}
|
|
20776
21131
|
)
|
|
@@ -20781,7 +21136,7 @@ function Layout({
|
|
|
20781
21136
|
{
|
|
20782
21137
|
id: "main-content",
|
|
20783
21138
|
role: "main",
|
|
20784
|
-
className: `mx-auto w-full ${maxWidth} px-4 sm:px-6 lg:px-8
|
|
21139
|
+
className: `mx-auto w-full ${maxWidth} px-4 sm:px-6 lg:px-8`,
|
|
20785
21140
|
children
|
|
20786
21141
|
}
|
|
20787
21142
|
)
|
|
@@ -20799,36 +21154,32 @@ function PromptPipelineDashboard({ isConnected }) {
|
|
|
20799
21154
|
return src.map(adaptJobSummary);
|
|
20800
21155
|
}, [apiJobs, error]);
|
|
20801
21156
|
const [activeTab, setActiveTab] = reactExports.useState("current");
|
|
20802
|
-
const [seedUploadSuccess, setSeedUploadSuccess] = reactExports.useState(null);
|
|
20803
|
-
const [seedUploadTimer, setSeedUploadTimer] = reactExports.useState(null);
|
|
20804
|
-
const now = useTicker(1e4);
|
|
20805
21157
|
const errorCount = reactExports.useMemo(
|
|
20806
|
-
() => jobs.filter((j) => j.status ===
|
|
21158
|
+
() => jobs.filter((j) => j.status === TaskState.FAILED).length,
|
|
20807
21159
|
[jobs]
|
|
20808
21160
|
);
|
|
20809
21161
|
const currentCount = reactExports.useMemo(
|
|
20810
|
-
() => jobs.filter((j) => j.status ===
|
|
21162
|
+
() => jobs.filter((j) => j.status === TaskState.RUNNING).length,
|
|
20811
21163
|
[jobs]
|
|
20812
21164
|
);
|
|
20813
21165
|
const completedCount = reactExports.useMemo(
|
|
20814
|
-
() => jobs.filter((j) => j.status ===
|
|
21166
|
+
() => jobs.filter((j) => j.status === JobStatus.COMPLETE).length,
|
|
20815
21167
|
[jobs]
|
|
20816
21168
|
);
|
|
20817
21169
|
const filteredJobs = reactExports.useMemo(() => {
|
|
20818
21170
|
switch (activeTab) {
|
|
20819
21171
|
case "current":
|
|
20820
|
-
return jobs.filter((j) => j.status ===
|
|
21172
|
+
return jobs.filter((j) => j.status === TaskState.RUNNING);
|
|
20821
21173
|
case "errors":
|
|
20822
|
-
return jobs.filter((j) => j.status ===
|
|
21174
|
+
return jobs.filter((j) => j.status === TaskState.FAILED);
|
|
20823
21175
|
case "complete":
|
|
20824
|
-
return jobs.filter((j) => j.status ===
|
|
21176
|
+
return jobs.filter((j) => j.status === JobStatus.COMPLETE);
|
|
20825
21177
|
default:
|
|
20826
21178
|
return [];
|
|
20827
21179
|
}
|
|
20828
21180
|
}, [jobs, activeTab]);
|
|
20829
|
-
const overallElapsed = (job) => jobCumulativeDurationMs(job, now);
|
|
20830
21181
|
const runningJobs = reactExports.useMemo(
|
|
20831
|
-
() => jobs.filter((j) => j.status ===
|
|
21182
|
+
() => jobs.filter((j) => j.status === TaskState.RUNNING),
|
|
20832
21183
|
[jobs]
|
|
20833
21184
|
);
|
|
20834
21185
|
const aggregateProgress = reactExports.useMemo(() => {
|
|
@@ -20843,94 +21194,76 @@ function PromptPipelineDashboard({ isConnected }) {
|
|
|
20843
21194
|
console.warn(`Cannot open job "${job.name}" - no valid job ID available`);
|
|
20844
21195
|
}
|
|
20845
21196
|
};
|
|
20846
|
-
const
|
|
20847
|
-
|
|
20848
|
-
clearTimeout(seedUploadTimer);
|
|
20849
|
-
}
|
|
20850
|
-
setSeedUploadSuccess(jobName);
|
|
20851
|
-
const timer = setTimeout(() => {
|
|
20852
|
-
setSeedUploadSuccess(null);
|
|
20853
|
-
setSeedUploadTimer(null);
|
|
20854
|
-
}, 5e3);
|
|
20855
|
-
setSeedUploadTimer(timer);
|
|
20856
|
-
};
|
|
20857
|
-
reactExports.useEffect(() => {
|
|
20858
|
-
return () => {
|
|
20859
|
-
if (seedUploadTimer) {
|
|
20860
|
-
clearTimeout(seedUploadTimer);
|
|
20861
|
-
}
|
|
20862
|
-
};
|
|
20863
|
-
}, [seedUploadTimer]);
|
|
20864
|
-
const headerActions = runningJobs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(p$3, { align: "center", gap: "2", className: "text-gray-11", children: [
|
|
20865
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(p$a, { size: "1", weight: "medium", children: "Overall Progress" }),
|
|
21197
|
+
const headerActions = runningJobs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { align: "center", gap: "2", className: "text-gray-11", children: [
|
|
21198
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "1", weight: "medium", children: "Overall Progress" }),
|
|
20866
21199
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Progress, { value: aggregateProgress, className: "w-20" }),
|
|
20867
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$
|
|
21200
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { size: "1", className: "text-gray-9", children: [
|
|
20868
21201
|
aggregateProgress,
|
|
20869
21202
|
"%"
|
|
20870
21203
|
] })
|
|
20871
21204
|
] });
|
|
20872
21205
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Layout, { title: "Prompt Pipeline", actions: headerActions, children: [
|
|
20873
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
|
|
20877
|
-
|
|
20878
|
-
|
|
20879
|
-
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
|
|
20883
|
-
|
|
20884
|
-
|
|
20885
|
-
|
|
20886
|
-
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
|
|
20893
|
-
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
|
|
20897
|
-
|
|
20898
|
-
")
|
|
20899
|
-
|
|
20900
|
-
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
|
|
20904
|
-
jobs: filteredJobs,
|
|
20905
|
-
pipeline: null,
|
|
20906
|
-
onOpenJob: openJob,
|
|
20907
|
-
overallElapsed,
|
|
20908
|
-
now
|
|
20909
|
-
}
|
|
20910
|
-
) }),
|
|
20911
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(f, { value: "errors", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20912
|
-
JobTable,
|
|
20913
|
-
{
|
|
20914
|
-
jobs: filteredJobs,
|
|
20915
|
-
pipeline: null,
|
|
20916
|
-
onOpenJob: openJob,
|
|
20917
|
-
overallElapsed,
|
|
20918
|
-
now
|
|
20919
|
-
}
|
|
20920
|
-
) }),
|
|
20921
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(f, { value: "complete", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20922
|
-
JobTable,
|
|
20923
|
-
{
|
|
20924
|
-
jobs: filteredJobs,
|
|
20925
|
-
pipeline: null,
|
|
20926
|
-
onOpenJob: openJob,
|
|
20927
|
-
overallElapsed,
|
|
20928
|
-
now
|
|
20929
|
-
}
|
|
20930
|
-
) })
|
|
20931
|
-
] })
|
|
21206
|
+
error && /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { className: "mb-4 rounded-md bg-yellow-50 p-3 border border-yellow-200", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", className: "text-yellow-800", children: "Unable to load jobs from the server" }) }),
|
|
21207
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21208
|
+
m,
|
|
21209
|
+
{
|
|
21210
|
+
value: activeTab,
|
|
21211
|
+
onValueChange: setActiveTab,
|
|
21212
|
+
className: "mt-4",
|
|
21213
|
+
children: [
|
|
21214
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(b, { "aria-label": "Job filters", children: [
|
|
21215
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(P, { value: "current", children: [
|
|
21216
|
+
"Current (",
|
|
21217
|
+
currentCount,
|
|
21218
|
+
")"
|
|
21219
|
+
] }),
|
|
21220
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(P, { value: "errors", children: [
|
|
21221
|
+
"Errors (",
|
|
21222
|
+
errorCount,
|
|
21223
|
+
")"
|
|
21224
|
+
] }),
|
|
21225
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(P, { value: "complete", children: [
|
|
21226
|
+
"Completed (",
|
|
21227
|
+
completedCount,
|
|
21228
|
+
")"
|
|
21229
|
+
] })
|
|
21230
|
+
] }),
|
|
21231
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f, { value: "current", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JobTable, { jobs: filteredJobs, pipeline: null, onOpenJob: openJob }) }),
|
|
21232
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f, { value: "errors", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JobTable, { jobs: filteredJobs, pipeline: null, onOpenJob: openJob }) }),
|
|
21233
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f, { value: "complete", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JobTable, { jobs: filteredJobs, pipeline: null, onOpenJob: openJob }) })
|
|
21234
|
+
]
|
|
21235
|
+
}
|
|
21236
|
+
)
|
|
20932
21237
|
] });
|
|
20933
21238
|
}
|
|
21239
|
+
function areGeometriesEqual(prev, next, epsilon = 0.5) {
|
|
21240
|
+
if (prev === next) return true;
|
|
21241
|
+
if (!prev || !next) return false;
|
|
21242
|
+
if (prev.itemsLength !== next.itemsLength) return false;
|
|
21243
|
+
if (prev.effectiveCols !== next.effectiveCols) return false;
|
|
21244
|
+
if (!areOverlayBoxesEqual(prev.overlayBox, next.overlayBox, epsilon)) {
|
|
21245
|
+
return false;
|
|
21246
|
+
}
|
|
21247
|
+
const prevBoxes = prev.boxes;
|
|
21248
|
+
const nextBoxes = next.boxes;
|
|
21249
|
+
if (prevBoxes.length !== nextBoxes.length) return false;
|
|
21250
|
+
for (let i2 = 0; i2 < prevBoxes.length; i2++) {
|
|
21251
|
+
if (!areBoxesEqual(prevBoxes[i2], nextBoxes[i2], epsilon)) {
|
|
21252
|
+
return false;
|
|
21253
|
+
}
|
|
21254
|
+
}
|
|
21255
|
+
return true;
|
|
21256
|
+
}
|
|
21257
|
+
function areOverlayBoxesEqual(a2, b2, epsilon) {
|
|
21258
|
+
return areNumbersClose(a2.left, b2.left, epsilon) && areNumbersClose(a2.top, b2.top, epsilon) && areNumbersClose(a2.width, b2.width, epsilon) && areNumbersClose(a2.height, b2.height, epsilon) && areNumbersClose(a2.right, b2.right, epsilon) && areNumbersClose(a2.bottom, b2.bottom, epsilon);
|
|
21259
|
+
}
|
|
21260
|
+
function areBoxesEqual(a2, b2, epsilon) {
|
|
21261
|
+
if (!a2 || !b2) return a2 === b2;
|
|
21262
|
+
return areNumbersClose(a2.left, b2.left, epsilon) && areNumbersClose(a2.top, b2.top, epsilon) && areNumbersClose(a2.width, b2.width, epsilon) && areNumbersClose(a2.height, b2.height, epsilon) && areNumbersClose(a2.right, b2.right, epsilon) && areNumbersClose(a2.bottom, b2.bottom, epsilon) && areNumbersClose(a2.headerMidY, b2.headerMidY, epsilon);
|
|
21263
|
+
}
|
|
21264
|
+
function areNumbersClose(a2, b2, epsilon) {
|
|
21265
|
+
return Math.abs(a2 - b2) <= epsilon;
|
|
21266
|
+
}
|
|
20934
21267
|
function TaskFilePane({
|
|
20935
21268
|
isOpen,
|
|
20936
21269
|
jobId,
|
|
@@ -21366,82 +21699,428 @@ function TaskFilePane({
|
|
|
21366
21699
|
] })
|
|
21367
21700
|
] });
|
|
21368
21701
|
}
|
|
21369
|
-
|
|
21370
|
-
|
|
21371
|
-
|
|
21372
|
-
|
|
21373
|
-
|
|
21374
|
-
|
|
21375
|
-
|
|
21376
|
-
|
|
21377
|
-
|
|
21378
|
-
|
|
21379
|
-
|
|
21380
|
-
|
|
21381
|
-
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21385
|
-
|
|
21386
|
-
|
|
21387
|
-
|
|
21388
|
-
|
|
21389
|
-
|
|
21390
|
-
|
|
21391
|
-
|
|
21392
|
-
|
|
21393
|
-
|
|
21394
|
-
|
|
21395
|
-
|
|
21396
|
-
if (otherKeys.length > 0) {
|
|
21397
|
-
console.warn(
|
|
21398
|
-
`[task-files] Ignoring unsupported task.files keys: ${otherKeys.join(", ")}`
|
|
21399
|
-
);
|
|
21400
|
-
}
|
|
21401
|
-
}
|
|
21402
|
-
function normalizeTaskFiles(candidate) {
|
|
21403
|
-
const safeCandidate = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : {};
|
|
21404
|
-
const unsupportedKeys = Object.keys(safeCandidate).filter(
|
|
21405
|
-
(key) => !CATEGORY_KEYS.includes(key)
|
|
21406
|
-
);
|
|
21407
|
-
reportUnsupportedKeys(unsupportedKeys);
|
|
21408
|
-
return {
|
|
21409
|
-
artifacts: coerceStringArray(safeCandidate.artifacts),
|
|
21410
|
-
logs: coerceStringArray(safeCandidate.logs),
|
|
21411
|
-
tmp: coerceStringArray(safeCandidate.tmp)
|
|
21412
|
-
};
|
|
21413
|
-
}
|
|
21414
|
-
function ensureTaskFiles(task) {
|
|
21415
|
-
const normalized = normalizeTaskFiles(task?.files);
|
|
21416
|
-
if (task && typeof task === "object") {
|
|
21417
|
-
task.files = normalized;
|
|
21418
|
-
}
|
|
21419
|
-
return normalized;
|
|
21420
|
-
}
|
|
21421
|
-
function matchesTaskIdentifier(task, taskId) {
|
|
21422
|
-
if (!task || typeof task !== "object" || taskId == null) return false;
|
|
21423
|
-
const target = String(taskId);
|
|
21424
|
-
if (task.id != null && String(task.id) === target) return true;
|
|
21425
|
-
if (task.name != null && String(task.name) === target) return true;
|
|
21426
|
-
return false;
|
|
21427
|
-
}
|
|
21428
|
-
function findTaskCandidate(tasks, taskId) {
|
|
21429
|
-
if (!tasks || taskId == null) return null;
|
|
21430
|
-
if (Array.isArray(tasks)) {
|
|
21431
|
-
if (typeof taskId === "number" && tasks[taskId]) {
|
|
21432
|
-
const indexedTask = tasks[taskId];
|
|
21433
|
-
if (indexedTask && typeof indexedTask === "object") {
|
|
21434
|
-
return indexedTask;
|
|
21435
|
-
}
|
|
21702
|
+
function TaskDetailSidebar({
|
|
21703
|
+
open,
|
|
21704
|
+
title,
|
|
21705
|
+
status,
|
|
21706
|
+
jobId,
|
|
21707
|
+
taskId,
|
|
21708
|
+
taskBody,
|
|
21709
|
+
filesByTypeForItem = () => ({ artifacts: [], logs: [], tmp: [] }),
|
|
21710
|
+
task,
|
|
21711
|
+
onClose,
|
|
21712
|
+
taskIndex
|
|
21713
|
+
// Add taskIndex for ID compatibility
|
|
21714
|
+
}) {
|
|
21715
|
+
const [filePaneType, setFilePaneType] = reactExports.useState("artifacts");
|
|
21716
|
+
const [filePaneOpen, setFilePaneOpen] = reactExports.useState(false);
|
|
21717
|
+
const [filePaneFilename, setFilePaneFilename] = reactExports.useState(null);
|
|
21718
|
+
const closeButtonRef = reactExports.useRef(null);
|
|
21719
|
+
const getHeaderClasses2 = (status2) => {
|
|
21720
|
+
switch (status2) {
|
|
21721
|
+
case TaskState.DONE:
|
|
21722
|
+
return "bg-green-50 border-green-200 text-green-700";
|
|
21723
|
+
case TaskState.RUNNING:
|
|
21724
|
+
return "bg-amber-50 border-amber-200 text-amber-700";
|
|
21725
|
+
case TaskState.FAILED:
|
|
21726
|
+
return "bg-pink-50 border-pink-200 text-pink-700";
|
|
21727
|
+
default:
|
|
21728
|
+
return "bg-gray-100 border-gray-200 text-gray-700";
|
|
21436
21729
|
}
|
|
21437
|
-
|
|
21438
|
-
|
|
21439
|
-
|
|
21440
|
-
|
|
21441
|
-
if (direct && typeof direct === "object") {
|
|
21442
|
-
return direct;
|
|
21730
|
+
};
|
|
21731
|
+
reactExports.useEffect(() => {
|
|
21732
|
+
if (open && closeButtonRef.current) {
|
|
21733
|
+
closeButtonRef.current.focus();
|
|
21443
21734
|
}
|
|
21444
|
-
|
|
21735
|
+
}, [open]);
|
|
21736
|
+
reactExports.useEffect(() => {
|
|
21737
|
+
if (open) {
|
|
21738
|
+
setFilePaneType("artifacts");
|
|
21739
|
+
setFilePaneOpen(false);
|
|
21740
|
+
setFilePaneFilename(null);
|
|
21741
|
+
}
|
|
21742
|
+
}, [open]);
|
|
21743
|
+
reactExports.useEffect(() => {
|
|
21744
|
+
setFilePaneFilename(null);
|
|
21745
|
+
setFilePaneOpen(false);
|
|
21746
|
+
}, [filePaneType]);
|
|
21747
|
+
const handleFileClick = (filename) => {
|
|
21748
|
+
setFilePaneFilename(filename);
|
|
21749
|
+
setFilePaneOpen(true);
|
|
21750
|
+
};
|
|
21751
|
+
const handleFilePaneClose = () => {
|
|
21752
|
+
setFilePaneOpen(false);
|
|
21753
|
+
setFilePaneFilename(null);
|
|
21754
|
+
};
|
|
21755
|
+
if (!open) {
|
|
21756
|
+
return null;
|
|
21757
|
+
}
|
|
21758
|
+
const filesForStep = filesByTypeForItem(task);
|
|
21759
|
+
const filesForTab = filesForStep[filePaneType] ?? [];
|
|
21760
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21761
|
+
"aside",
|
|
21762
|
+
{
|
|
21763
|
+
role: "dialog",
|
|
21764
|
+
"aria-modal": "true",
|
|
21765
|
+
"aria-labelledby": `slide-over-title-${taskIndex}`,
|
|
21766
|
+
"aria-hidden": false,
|
|
21767
|
+
className: `fixed inset-y-0 right-0 z-[2000] w-full max-w-4xl bg-white border-l border-gray-200 transform transition-transform duration-300 ease-out translate-x-0`,
|
|
21768
|
+
children: [
|
|
21769
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21770
|
+
"div",
|
|
21771
|
+
{
|
|
21772
|
+
className: `px-6 py-4 border-b flex items-center justify-between ${getHeaderClasses2(status)}`,
|
|
21773
|
+
children: [
|
|
21774
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21775
|
+
"div",
|
|
21776
|
+
{
|
|
21777
|
+
id: `slide-over-title-${taskIndex}`,
|
|
21778
|
+
className: "text-lg font-semibold truncate",
|
|
21779
|
+
children: title
|
|
21780
|
+
}
|
|
21781
|
+
),
|
|
21782
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21783
|
+
"button",
|
|
21784
|
+
{
|
|
21785
|
+
ref: closeButtonRef,
|
|
21786
|
+
type: "button",
|
|
21787
|
+
"aria-label": "Close details",
|
|
21788
|
+
onClick: onClose,
|
|
21789
|
+
className: "rounded-md border border-gray-300 text-gray-700 hover:bg-gray-50 px-3 py-1.5 text-base",
|
|
21790
|
+
children: "×"
|
|
21791
|
+
}
|
|
21792
|
+
)
|
|
21793
|
+
]
|
|
21794
|
+
}
|
|
21795
|
+
),
|
|
21796
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 space-y-8 overflow-y-auto h-full", children: [
|
|
21797
|
+
status === TaskState.FAILED && taskBody && /* @__PURE__ */ jsxRuntimeExports.jsx("section", { "aria-label": "Error", children: /* @__PURE__ */ jsxRuntimeExports.jsx(n$2, { role: "alert", "aria-live": "assertive", children: /* @__PURE__ */ jsxRuntimeExports.jsx(u$1, { className: "whitespace-pre-wrap break-words", children: taskBody }) }) }),
|
|
21798
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("section", { className: "mt-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
21799
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-base font-semibold text-gray-900", children: "Files" }),
|
|
21800
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center space-x-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex rounded-lg border border-gray-200 bg-gray-50 p-1", children: [
|
|
21801
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21802
|
+
"button",
|
|
21803
|
+
{
|
|
21804
|
+
onClick: () => setFilePaneType("artifacts"),
|
|
21805
|
+
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${filePaneType === "artifacts" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
21806
|
+
children: "Artifacts"
|
|
21807
|
+
}
|
|
21808
|
+
),
|
|
21809
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21810
|
+
"button",
|
|
21811
|
+
{
|
|
21812
|
+
onClick: () => setFilePaneType("logs"),
|
|
21813
|
+
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${filePaneType === "logs" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
21814
|
+
children: "Logs"
|
|
21815
|
+
}
|
|
21816
|
+
),
|
|
21817
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21818
|
+
"button",
|
|
21819
|
+
{
|
|
21820
|
+
onClick: () => setFilePaneType("tmp"),
|
|
21821
|
+
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${filePaneType === "tmp" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
21822
|
+
children: "Temp"
|
|
21823
|
+
}
|
|
21824
|
+
)
|
|
21825
|
+
] }) })
|
|
21826
|
+
] }) }),
|
|
21827
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
21828
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-gray-600", children: [
|
|
21829
|
+
filePaneType.charAt(0).toUpperCase() + filePaneType.slice(1),
|
|
21830
|
+
" files for ",
|
|
21831
|
+
taskId
|
|
21832
|
+
] }),
|
|
21833
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: filesForTab.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-gray-500 italic py-4 text-center", children: [
|
|
21834
|
+
"No ",
|
|
21835
|
+
filePaneType,
|
|
21836
|
+
" files available for this task"
|
|
21837
|
+
] }) : filesForTab.map((name) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21838
|
+
"div",
|
|
21839
|
+
{
|
|
21840
|
+
className: "flex items-center justify-between p-2 rounded border border-gray-200 hover:border-gray-300 hover:bg-gray-50 cursor-pointer transition-colors",
|
|
21841
|
+
onClick: () => handleFileClick(name),
|
|
21842
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center space-x-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: name }) })
|
|
21843
|
+
},
|
|
21844
|
+
`${filePaneType}-${name}`
|
|
21845
|
+
)) })
|
|
21846
|
+
] }),
|
|
21847
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21848
|
+
TaskFilePane,
|
|
21849
|
+
{
|
|
21850
|
+
isOpen: filePaneOpen,
|
|
21851
|
+
jobId,
|
|
21852
|
+
taskId,
|
|
21853
|
+
type: filePaneType,
|
|
21854
|
+
filename: filePaneFilename,
|
|
21855
|
+
onClose: handleFilePaneClose
|
|
21856
|
+
}
|
|
21857
|
+
)
|
|
21858
|
+
] })
|
|
21859
|
+
]
|
|
21860
|
+
}
|
|
21861
|
+
);
|
|
21862
|
+
}
|
|
21863
|
+
React.memo(TaskDetailSidebar);
|
|
21864
|
+
function RestartJobModal({
|
|
21865
|
+
open,
|
|
21866
|
+
onClose,
|
|
21867
|
+
onConfirm,
|
|
21868
|
+
jobId,
|
|
21869
|
+
taskId,
|
|
21870
|
+
isSubmitting = false
|
|
21871
|
+
}) {
|
|
21872
|
+
const modalRef = reactExports.useRef(null);
|
|
21873
|
+
reactExports.useEffect(() => {
|
|
21874
|
+
const handleKeyDown2 = (e2) => {
|
|
21875
|
+
if (e2.key === "Escape" && open) {
|
|
21876
|
+
e2.preventDefault();
|
|
21877
|
+
onClose();
|
|
21878
|
+
}
|
|
21879
|
+
};
|
|
21880
|
+
if (open) {
|
|
21881
|
+
document.addEventListener("keydown", handleKeyDown2);
|
|
21882
|
+
if (modalRef.current) {
|
|
21883
|
+
modalRef.current.focus();
|
|
21884
|
+
}
|
|
21885
|
+
return () => {
|
|
21886
|
+
document.removeEventListener("keydown", handleKeyDown2);
|
|
21887
|
+
};
|
|
21888
|
+
}
|
|
21889
|
+
}, [open, onClose]);
|
|
21890
|
+
const handleKeyDown = (e2) => {
|
|
21891
|
+
if (e2.key === "Enter" && !isSubmitting && open) {
|
|
21892
|
+
e2.preventDefault();
|
|
21893
|
+
onConfirm();
|
|
21894
|
+
}
|
|
21895
|
+
};
|
|
21896
|
+
if (!open) return null;
|
|
21897
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21898
|
+
"div",
|
|
21899
|
+
{
|
|
21900
|
+
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
21901
|
+
"aria-hidden": !open,
|
|
21902
|
+
children: [
|
|
21903
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21904
|
+
"div",
|
|
21905
|
+
{
|
|
21906
|
+
className: "absolute inset-0 bg-black/50",
|
|
21907
|
+
onClick: onClose,
|
|
21908
|
+
"aria-hidden": "true"
|
|
21909
|
+
}
|
|
21910
|
+
),
|
|
21911
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21912
|
+
"div",
|
|
21913
|
+
{
|
|
21914
|
+
ref: modalRef,
|
|
21915
|
+
role: "dialog",
|
|
21916
|
+
"aria-modal": "true",
|
|
21917
|
+
"aria-labelledby": "restart-modal-title",
|
|
21918
|
+
"aria-describedby": "restart-modal-description",
|
|
21919
|
+
className: "relative bg-white rounded-lg shadow-2xl border border-gray-200 max-w-lg w-full mx-4 outline-none",
|
|
21920
|
+
style: { minWidth: "320px", maxWidth: "560px" },
|
|
21921
|
+
tabIndex: -1,
|
|
21922
|
+
onKeyDown: handleKeyDown,
|
|
21923
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6", children: [
|
|
21924
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21925
|
+
r$8,
|
|
21926
|
+
{
|
|
21927
|
+
id: "restart-modal-title",
|
|
21928
|
+
as: "h2",
|
|
21929
|
+
size: "5",
|
|
21930
|
+
className: "mb-4 text-gray-900",
|
|
21931
|
+
children: taskId ? `Restart from ${taskId}` : "Restart job (reset progress)"
|
|
21932
|
+
}
|
|
21933
|
+
),
|
|
21934
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { id: "restart-modal-description", className: "mb-6", children: [
|
|
21935
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { 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." }),
|
|
21936
|
+
taskId && /* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { as: "p", className: "text-sm text-gray-600 mb-3", children: [
|
|
21937
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Triggered from task:" }),
|
|
21938
|
+
" ",
|
|
21939
|
+
taskId
|
|
21940
|
+
] }),
|
|
21941
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "p", className: "text-sm text-gray-500 italic", children: "Note: Job must be in current lifecycle and not running." })
|
|
21942
|
+
] }),
|
|
21943
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { gap: "3", justify: "end", children: [
|
|
21944
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21945
|
+
Button,
|
|
21946
|
+
{
|
|
21947
|
+
variant: "outline",
|
|
21948
|
+
onClick: onClose,
|
|
21949
|
+
disabled: isSubmitting,
|
|
21950
|
+
className: "min-w-[80px]",
|
|
21951
|
+
children: "Cancel"
|
|
21952
|
+
}
|
|
21953
|
+
),
|
|
21954
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21955
|
+
Button,
|
|
21956
|
+
{
|
|
21957
|
+
variant: "destructive",
|
|
21958
|
+
onClick: onConfirm,
|
|
21959
|
+
disabled: isSubmitting,
|
|
21960
|
+
className: "min-w-[80px]",
|
|
21961
|
+
children: isSubmitting ? "Restarting..." : "Restart"
|
|
21962
|
+
}
|
|
21963
|
+
)
|
|
21964
|
+
] })
|
|
21965
|
+
] })
|
|
21966
|
+
}
|
|
21967
|
+
)
|
|
21968
|
+
]
|
|
21969
|
+
}
|
|
21970
|
+
) });
|
|
21971
|
+
}
|
|
21972
|
+
async function restartJob(jobId, opts = {}) {
|
|
21973
|
+
const options = {
|
|
21974
|
+
clearTokenUsage: true,
|
|
21975
|
+
...opts.options
|
|
21976
|
+
};
|
|
21977
|
+
const requestBody = opts.fromTask ? { fromTask: opts.fromTask, options } : { mode: "clean-slate", options };
|
|
21978
|
+
try {
|
|
21979
|
+
const response = await fetch(
|
|
21980
|
+
`/api/jobs/${encodeURIComponent(jobId)}/restart`,
|
|
21981
|
+
{
|
|
21982
|
+
method: "POST",
|
|
21983
|
+
headers: {
|
|
21984
|
+
"Content-Type": "application/json"
|
|
21985
|
+
},
|
|
21986
|
+
body: JSON.stringify(requestBody)
|
|
21987
|
+
}
|
|
21988
|
+
);
|
|
21989
|
+
if (!response.ok) {
|
|
21990
|
+
let errorData;
|
|
21991
|
+
try {
|
|
21992
|
+
errorData = await response.json();
|
|
21993
|
+
} catch {
|
|
21994
|
+
errorData = { message: response.statusText };
|
|
21995
|
+
}
|
|
21996
|
+
throw {
|
|
21997
|
+
code: errorData.code || getErrorCodeFromStatus(response.status),
|
|
21998
|
+
message: getRestartErrorMessage(errorData, response.status),
|
|
21999
|
+
status: response.status
|
|
22000
|
+
};
|
|
22001
|
+
}
|
|
22002
|
+
return await response.json();
|
|
22003
|
+
} catch (error) {
|
|
22004
|
+
if (error.code && error.message) {
|
|
22005
|
+
throw error;
|
|
22006
|
+
}
|
|
22007
|
+
throw {
|
|
22008
|
+
code: "network_error",
|
|
22009
|
+
message: error.message || "Failed to connect to server"
|
|
22010
|
+
};
|
|
22011
|
+
}
|
|
22012
|
+
}
|
|
22013
|
+
function getErrorCodeFromStatus(status) {
|
|
22014
|
+
switch (status) {
|
|
22015
|
+
case 404:
|
|
22016
|
+
return "job_not_found";
|
|
22017
|
+
case 409:
|
|
22018
|
+
return "conflict";
|
|
22019
|
+
case 500:
|
|
22020
|
+
return "spawn_failed";
|
|
22021
|
+
default:
|
|
22022
|
+
return "unknown_error";
|
|
22023
|
+
}
|
|
22024
|
+
}
|
|
22025
|
+
function getRestartErrorMessage(errorData, status) {
|
|
22026
|
+
if (status === 409) {
|
|
22027
|
+
if (errorData.code === "job_running") {
|
|
22028
|
+
return "Job is currently running; restart is unavailable.";
|
|
22029
|
+
}
|
|
22030
|
+
if (errorData.code === "unsupported_lifecycle") {
|
|
22031
|
+
return "Job must be in current to restart.";
|
|
22032
|
+
}
|
|
22033
|
+
if (errorData.message?.includes("job_running")) {
|
|
22034
|
+
return "Job is currently running; restart is unavailable.";
|
|
22035
|
+
}
|
|
22036
|
+
if (errorData.message?.includes("unsupported_lifecycle")) {
|
|
22037
|
+
return "Job must be in current to restart.";
|
|
22038
|
+
}
|
|
22039
|
+
}
|
|
22040
|
+
if (status === 404) {
|
|
22041
|
+
return "Job not found.";
|
|
22042
|
+
}
|
|
22043
|
+
if (status === 500) {
|
|
22044
|
+
return "Failed to start restart. Try again.";
|
|
22045
|
+
}
|
|
22046
|
+
return errorData.message || "Failed to restart job.";
|
|
22047
|
+
}
|
|
22048
|
+
const CATEGORY_KEYS = ["artifacts", "logs", "tmp"];
|
|
22049
|
+
const LEGACY_KEY_SET = /* @__PURE__ */ new Set([
|
|
22050
|
+
"input",
|
|
22051
|
+
"inputs",
|
|
22052
|
+
"output",
|
|
22053
|
+
"outputs",
|
|
22054
|
+
"legacyInput",
|
|
22055
|
+
"legacyOutput",
|
|
22056
|
+
"inputFiles",
|
|
22057
|
+
"outputFiles"
|
|
22058
|
+
]);
|
|
22059
|
+
function createEmptyTaskFiles() {
|
|
22060
|
+
return { artifacts: [], logs: [], tmp: [] };
|
|
22061
|
+
}
|
|
22062
|
+
function coerceStringArray(value) {
|
|
22063
|
+
if (!Array.isArray(value)) return [];
|
|
22064
|
+
return value.filter((entry) => typeof entry === "string");
|
|
22065
|
+
}
|
|
22066
|
+
function reportUnsupportedKeys(keys) {
|
|
22067
|
+
if (keys.length === 0) return;
|
|
22068
|
+
const legacyKeys = keys.filter((key) => LEGACY_KEY_SET.has(key));
|
|
22069
|
+
const otherKeys = keys.filter((key) => !LEGACY_KEY_SET.has(key));
|
|
22070
|
+
if (legacyKeys.length > 0) {
|
|
22071
|
+
console.warn(
|
|
22072
|
+
`[task-files] Ignoring unsupported legacy keys: ${legacyKeys.join(", ")}`
|
|
22073
|
+
);
|
|
22074
|
+
}
|
|
22075
|
+
if (otherKeys.length > 0) {
|
|
22076
|
+
console.warn(
|
|
22077
|
+
`[task-files] Ignoring unsupported task.files keys: ${otherKeys.join(", ")}`
|
|
22078
|
+
);
|
|
22079
|
+
}
|
|
22080
|
+
}
|
|
22081
|
+
function normalizeTaskFiles(candidate) {
|
|
22082
|
+
const safeCandidate = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : {};
|
|
22083
|
+
const unsupportedKeys = Object.keys(safeCandidate).filter(
|
|
22084
|
+
(key) => !CATEGORY_KEYS.includes(key)
|
|
22085
|
+
);
|
|
22086
|
+
reportUnsupportedKeys(unsupportedKeys);
|
|
22087
|
+
return {
|
|
22088
|
+
artifacts: coerceStringArray(safeCandidate.artifacts),
|
|
22089
|
+
logs: coerceStringArray(safeCandidate.logs),
|
|
22090
|
+
tmp: coerceStringArray(safeCandidate.tmp)
|
|
22091
|
+
};
|
|
22092
|
+
}
|
|
22093
|
+
function ensureTaskFiles(task) {
|
|
22094
|
+
const normalized = normalizeTaskFiles(task?.files);
|
|
22095
|
+
if (task && typeof task === "object") {
|
|
22096
|
+
task.files = normalized;
|
|
22097
|
+
}
|
|
22098
|
+
return normalized;
|
|
22099
|
+
}
|
|
22100
|
+
function matchesTaskIdentifier(task, taskId) {
|
|
22101
|
+
if (!task || typeof task !== "object" || taskId == null) return false;
|
|
22102
|
+
const target = String(taskId);
|
|
22103
|
+
if (task.id != null && String(task.id) === target) return true;
|
|
22104
|
+
if (task.name != null && String(task.name) === target) return true;
|
|
22105
|
+
return false;
|
|
22106
|
+
}
|
|
22107
|
+
function findTaskCandidate(tasks, taskId) {
|
|
22108
|
+
if (!tasks || taskId == null) return null;
|
|
22109
|
+
if (Array.isArray(tasks)) {
|
|
22110
|
+
if (typeof taskId === "number" && tasks[taskId]) {
|
|
22111
|
+
const indexedTask = tasks[taskId];
|
|
22112
|
+
if (indexedTask && typeof indexedTask === "object") {
|
|
22113
|
+
return indexedTask;
|
|
22114
|
+
}
|
|
22115
|
+
}
|
|
22116
|
+
return tasks.find((task) => matchesTaskIdentifier(task, taskId)) ?? null;
|
|
22117
|
+
}
|
|
22118
|
+
if (typeof tasks === "object") {
|
|
22119
|
+
const direct = tasks[taskId];
|
|
22120
|
+
if (direct && typeof direct === "object") {
|
|
22121
|
+
return direct;
|
|
22122
|
+
}
|
|
22123
|
+
for (const task of Object.values(tasks)) {
|
|
21445
22124
|
if (matchesTaskIdentifier(task, taskId)) {
|
|
21446
22125
|
return task;
|
|
21447
22126
|
}
|
|
@@ -21467,6 +22146,10 @@ function getTaskFilesForTask(job, taskId) {
|
|
|
21467
22146
|
console.debug("[getTaskFilesForTask] Task files result:", { taskId, result });
|
|
21468
22147
|
return result;
|
|
21469
22148
|
}
|
|
22149
|
+
const prefersReducedMotion = () => {
|
|
22150
|
+
if (typeof window === "undefined") return false;
|
|
22151
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
22152
|
+
};
|
|
21470
22153
|
function upperFirst(s2) {
|
|
21471
22154
|
return typeof s2 === "string" && s2.length > 0 ? s2.charAt(0).toUpperCase() + s2.slice(1) : s2;
|
|
21472
22155
|
}
|
|
@@ -21489,26 +22172,136 @@ function formatStepName(item, idx) {
|
|
|
21489
22172
|
const raw = item.title ?? item.id ?? `Step ${idx + 1}`;
|
|
21490
22173
|
return upperFirst(item.title ? item.title : raw);
|
|
21491
22174
|
}
|
|
21492
|
-
const
|
|
21493
|
-
|
|
21494
|
-
|
|
21495
|
-
|
|
21496
|
-
|
|
21497
|
-
|
|
21498
|
-
|
|
21499
|
-
|
|
21500
|
-
|
|
21501
|
-
|
|
21502
|
-
|
|
21503
|
-
},
|
|
21504
|
-
group: (label) => console.group(`${prefix} ${label}`),
|
|
21505
|
-
groupEnd: () => console.groupEnd(),
|
|
21506
|
-
table: (data, title) => {
|
|
21507
|
-
console.log(`${prefix} ${title}:`);
|
|
21508
|
-
console.table(data);
|
|
21509
|
-
}
|
|
21510
|
-
};
|
|
22175
|
+
const getHeaderClasses = (status) => {
|
|
22176
|
+
switch (status) {
|
|
22177
|
+
case TaskState.DONE:
|
|
22178
|
+
return "bg-green-50 border-green-200 text-green-700";
|
|
22179
|
+
case TaskState.RUNNING:
|
|
22180
|
+
return "bg-amber-50 border-amber-200 text-amber-700";
|
|
22181
|
+
case TaskState.FAILED:
|
|
22182
|
+
return "bg-pink-50 border-pink-200 text-pink-700";
|
|
22183
|
+
default:
|
|
22184
|
+
return "bg-gray-100 border-gray-200 text-gray-700";
|
|
22185
|
+
}
|
|
21511
22186
|
};
|
|
22187
|
+
const canShowRestart = (status) => {
|
|
22188
|
+
return status === TaskState.FAILED || status === TaskState.DONE;
|
|
22189
|
+
};
|
|
22190
|
+
const TaskCard = reactExports.memo(function TaskCard2({
|
|
22191
|
+
item,
|
|
22192
|
+
idx,
|
|
22193
|
+
nodeRef,
|
|
22194
|
+
status,
|
|
22195
|
+
isActive,
|
|
22196
|
+
canRestart,
|
|
22197
|
+
isSubmitting,
|
|
22198
|
+
getRestartDisabledReason,
|
|
22199
|
+
onClick,
|
|
22200
|
+
onKeyDown,
|
|
22201
|
+
handleRestartClick
|
|
22202
|
+
}) {
|
|
22203
|
+
const { startMs, endMs } = taskToTimerProps(item);
|
|
22204
|
+
const reducedMotion = prefersReducedMotion();
|
|
22205
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
22206
|
+
"div",
|
|
22207
|
+
{
|
|
22208
|
+
ref: nodeRef,
|
|
22209
|
+
role: "listitem",
|
|
22210
|
+
"aria-current": isActive ? "step" : void 0,
|
|
22211
|
+
tabIndex: 0,
|
|
22212
|
+
onClick,
|
|
22213
|
+
onKeyDown,
|
|
22214
|
+
className: `cursor-pointer rounded-lg border border-gray-400 ${status === TaskState.PENDING ? "bg-gray-50" : "bg-white"} overflow-hidden flex flex-col ${reducedMotion ? "" : "transition-all duration-200 ease-in-out"} outline outline-2 outline-transparent hover:outline-gray-400/70 focus-visible:outline-blue-500/60`,
|
|
22215
|
+
children: [
|
|
22216
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
22217
|
+
"div",
|
|
22218
|
+
{
|
|
22219
|
+
"data-role": "card-header",
|
|
22220
|
+
className: `rounded-t-lg px-4 py-2 border-b flex items-center justify-between gap-3 ${reducedMotion ? "" : "transition-opacity duration-300 ease-in-out"} ${getHeaderClasses(status)}`,
|
|
22221
|
+
children: [
|
|
22222
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium truncate", children: formatStepName(item, idx) }),
|
|
22223
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: status === TaskState.RUNNING ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
22224
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative h-4 w-4", "aria-label": "Active", children: [
|
|
22225
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Active" }),
|
|
22226
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-0 rounded-full border-2 border-amber-200" }),
|
|
22227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22228
|
+
"span",
|
|
22229
|
+
{
|
|
22230
|
+
className: `absolute inset-0 rounded-full border-2 border-transparent border-t-amber-600 ${reducedMotion ? "" : "animate-spin"}`
|
|
22231
|
+
}
|
|
22232
|
+
)
|
|
22233
|
+
] }),
|
|
22234
|
+
item.stage && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22235
|
+
"span",
|
|
22236
|
+
{
|
|
22237
|
+
className: "text-[11px] font-medium opacity-80 truncate uppercase tracking-wide",
|
|
22238
|
+
title: item.stage,
|
|
22239
|
+
children: formatStageLabel(item.stage)
|
|
22240
|
+
}
|
|
22241
|
+
),
|
|
22242
|
+
startMs && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22243
|
+
TimerText,
|
|
22244
|
+
{
|
|
22245
|
+
startMs,
|
|
22246
|
+
granularity: "second",
|
|
22247
|
+
className: "text-[11px] opacity-80"
|
|
22248
|
+
}
|
|
22249
|
+
)
|
|
22250
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
22251
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
22252
|
+
"span",
|
|
22253
|
+
{
|
|
22254
|
+
className: `text-[11px] uppercase tracking-wide opacity-80${reducedMotion ? "" : " transition-opacity duration-200"}`,
|
|
22255
|
+
children: [
|
|
22256
|
+
status,
|
|
22257
|
+
status === TaskState.FAILED && item.stage && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
22258
|
+
"span",
|
|
22259
|
+
{
|
|
22260
|
+
className: "text-[11px] font-medium opacity-80 truncate ml-2 uppercase tracking-wide",
|
|
22261
|
+
title: item.stage,
|
|
22262
|
+
children: [
|
|
22263
|
+
"(",
|
|
22264
|
+
formatStageLabel(item.stage),
|
|
22265
|
+
")"
|
|
22266
|
+
]
|
|
22267
|
+
}
|
|
22268
|
+
)
|
|
22269
|
+
]
|
|
22270
|
+
}
|
|
22271
|
+
),
|
|
22272
|
+
status === TaskState.DONE && startMs && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22273
|
+
TimerText,
|
|
22274
|
+
{
|
|
22275
|
+
startMs,
|
|
22276
|
+
endMs: endMs || item.finishedAt,
|
|
22277
|
+
granularity: "minute",
|
|
22278
|
+
className: "text-[11px] opacity-80"
|
|
22279
|
+
}
|
|
22280
|
+
)
|
|
22281
|
+
] }) })
|
|
22282
|
+
]
|
|
22283
|
+
}
|
|
22284
|
+
),
|
|
22285
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4", children: [
|
|
22286
|
+
item.subtitle && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-gray-600", children: item.subtitle }),
|
|
22287
|
+
item.body && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 text-sm text-gray-700", children: item.body }),
|
|
22288
|
+
canShowRestart(status) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3 pt-3 border-t border-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22289
|
+
Button,
|
|
22290
|
+
{
|
|
22291
|
+
variant: "outline",
|
|
22292
|
+
size: "sm",
|
|
22293
|
+
onClick: (e2) => handleRestartClick(e2, item.id),
|
|
22294
|
+
disabled: !canRestart || isSubmitting,
|
|
22295
|
+
className: "text-xs cursor-pointer disabled:cursor-not-allowed",
|
|
22296
|
+
title: !canRestart ? getRestartDisabledReason() : `Restart job from ${item.id}`,
|
|
22297
|
+
children: "Restart"
|
|
22298
|
+
}
|
|
22299
|
+
) })
|
|
22300
|
+
] })
|
|
22301
|
+
]
|
|
22302
|
+
}
|
|
22303
|
+
);
|
|
22304
|
+
});
|
|
21512
22305
|
function DAGGrid({
|
|
21513
22306
|
items,
|
|
21514
22307
|
cols = 3,
|
|
@@ -21517,28 +22310,19 @@ function DAGGrid({
|
|
|
21517
22310
|
jobId,
|
|
21518
22311
|
filesByTypeForItem = () => createEmptyTaskFiles()
|
|
21519
22312
|
}) {
|
|
21520
|
-
const logger = React.useMemo(() => createDAGGridLogger(jobId), [jobId]);
|
|
21521
22313
|
const overlayRef = reactExports.useRef(null);
|
|
21522
22314
|
const gridRef = reactExports.useRef(null);
|
|
21523
22315
|
const nodeRefs = reactExports.useRef([]);
|
|
21524
22316
|
const [lines, setLines] = reactExports.useState([]);
|
|
21525
22317
|
const [effectiveCols, setEffectiveCols] = reactExports.useState(cols);
|
|
21526
|
-
const [openIdx, setOpenIdx] = reactExports.useState(
|
|
21527
|
-
const [
|
|
21528
|
-
const [
|
|
21529
|
-
const [
|
|
21530
|
-
const [
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
21534
|
-
itemCount: items?.length,
|
|
21535
|
-
cols,
|
|
21536
|
-
activeIndex,
|
|
21537
|
-
jobId
|
|
21538
|
-
});
|
|
21539
|
-
logger.log("Items data:", items);
|
|
21540
|
-
logger.groupEnd();
|
|
21541
|
-
}, [items, cols, activeIndex, jobId, logger]);
|
|
22318
|
+
const [openIdx, setOpenIdx] = reactExports.useState(-1);
|
|
22319
|
+
const [restartModalOpen, setRestartModalOpen] = reactExports.useState(false);
|
|
22320
|
+
const [restartTaskId, setRestartTaskId] = reactExports.useState(null);
|
|
22321
|
+
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
22322
|
+
const [alertMessage, setAlertMessage] = reactExports.useState(null);
|
|
22323
|
+
const [alertType, setAlertType] = reactExports.useState("info");
|
|
22324
|
+
const prevGeometryRef = reactExports.useRef(null);
|
|
22325
|
+
const rafRef = reactExports.useRef(null);
|
|
21542
22326
|
nodeRefs.current = reactExports.useMemo(
|
|
21543
22327
|
() => items.map((_, i2) => nodeRefs.current[i2] ?? reactExports.createRef()),
|
|
21544
22328
|
[items.length]
|
|
@@ -21564,9 +22348,10 @@ function DAGGrid({
|
|
|
21564
22348
|
const end = Math.min(start + effectiveCols, items.length);
|
|
21565
22349
|
const slice = Array.from({ length: end - start }, (_, k) => start + k);
|
|
21566
22350
|
const rowLen = slice.length;
|
|
21567
|
-
const
|
|
21568
|
-
if (
|
|
22351
|
+
const isReversedRow = r2 % 2 === 1;
|
|
22352
|
+
if (isReversedRow) {
|
|
21569
22353
|
const reversed = slice.reverse();
|
|
22354
|
+
const pad = effectiveCols - rowLen;
|
|
21570
22355
|
order.push(...Array(pad).fill(-1), ...reversed);
|
|
21571
22356
|
} else {
|
|
21572
22357
|
order.push(...slice);
|
|
@@ -21578,11 +22363,11 @@ function DAGGrid({
|
|
|
21578
22363
|
if (typeof window === "undefined" || !overlayRef.current || items.length === 0) {
|
|
21579
22364
|
return;
|
|
21580
22365
|
}
|
|
21581
|
-
let isComputing = false;
|
|
21582
22366
|
const compute = () => {
|
|
21583
|
-
if (
|
|
21584
|
-
|
|
21585
|
-
|
|
22367
|
+
if (rafRef.current) {
|
|
22368
|
+
cancelAnimationFrame(rafRef.current);
|
|
22369
|
+
}
|
|
22370
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
21586
22371
|
if (!overlayRef.current) return;
|
|
21587
22372
|
const overlayBox = overlayRef.current.getBoundingClientRect();
|
|
21588
22373
|
const boxes = nodeRefs.current.map((r2) => {
|
|
@@ -21604,6 +22389,17 @@ function DAGGrid({
|
|
|
21604
22389
|
headerMidY
|
|
21605
22390
|
};
|
|
21606
22391
|
});
|
|
22392
|
+
const currentGeometry = {
|
|
22393
|
+
overlayBox,
|
|
22394
|
+
boxes: boxes.filter(Boolean),
|
|
22395
|
+
effectiveCols,
|
|
22396
|
+
itemsLength: items.length
|
|
22397
|
+
};
|
|
22398
|
+
const geometryChanged = !prevGeometryRef.current || !areGeometriesEqual(prevGeometryRef.current, currentGeometry);
|
|
22399
|
+
if (!geometryChanged) {
|
|
22400
|
+
rafRef.current = null;
|
|
22401
|
+
return;
|
|
22402
|
+
}
|
|
21607
22403
|
const newLines = [];
|
|
21608
22404
|
for (let i2 = 0; i2 < items.length - 1; i2++) {
|
|
21609
22405
|
const a2 = boxes[i2];
|
|
@@ -21638,10 +22434,10 @@ function DAGGrid({
|
|
|
21638
22434
|
});
|
|
21639
22435
|
}
|
|
21640
22436
|
}
|
|
22437
|
+
prevGeometryRef.current = currentGeometry;
|
|
21641
22438
|
setLines(newLines);
|
|
21642
|
-
|
|
21643
|
-
|
|
21644
|
-
}
|
|
22439
|
+
rafRef.current = null;
|
|
22440
|
+
});
|
|
21645
22441
|
};
|
|
21646
22442
|
compute();
|
|
21647
22443
|
let ro = null;
|
|
@@ -21658,66 +22454,147 @@ function DAGGrid({
|
|
|
21658
22454
|
if (ro) ro.disconnect();
|
|
21659
22455
|
window.removeEventListener("resize", handleResize);
|
|
21660
22456
|
window.removeEventListener("scroll", handleScroll, true);
|
|
22457
|
+
if (rafRef.current) {
|
|
22458
|
+
cancelAnimationFrame(rafRef.current);
|
|
22459
|
+
}
|
|
21661
22460
|
};
|
|
21662
22461
|
}, [items, effectiveCols, visualOrder]);
|
|
21663
22462
|
const getStatus = (index2) => {
|
|
21664
22463
|
const item = items[index2];
|
|
21665
22464
|
const s2 = item?.status;
|
|
21666
|
-
if (s2 ===
|
|
21667
|
-
if (s2 ===
|
|
21668
|
-
if (s2 ===
|
|
22465
|
+
if (s2 === TaskState.FAILED) return TaskState.FAILED;
|
|
22466
|
+
if (s2 === TaskState.DONE) return TaskState.DONE;
|
|
22467
|
+
if (s2 === TaskState.RUNNING) return TaskState.RUNNING;
|
|
21669
22468
|
if (typeof activeIndex === "number") {
|
|
21670
|
-
if (index2 < activeIndex) return
|
|
21671
|
-
if (index2 === activeIndex) return
|
|
21672
|
-
return
|
|
21673
|
-
}
|
|
21674
|
-
return "pending";
|
|
21675
|
-
};
|
|
21676
|
-
const getHeaderClasses = (status) => {
|
|
21677
|
-
switch (status) {
|
|
21678
|
-
case "done":
|
|
21679
|
-
return "bg-green-50 border-green-200 text-green-700";
|
|
21680
|
-
case "running":
|
|
21681
|
-
return "bg-amber-50 border-amber-200 text-amber-700";
|
|
21682
|
-
case "failed":
|
|
21683
|
-
return "bg-pink-50 border-pink-200 text-pink-700";
|
|
21684
|
-
default:
|
|
21685
|
-
return "bg-gray-100 border-gray-200 text-gray-700";
|
|
22469
|
+
if (index2 < activeIndex) return TaskState.DONE;
|
|
22470
|
+
if (index2 === activeIndex) return TaskState.RUNNING;
|
|
22471
|
+
return TaskState.PENDING;
|
|
21686
22472
|
}
|
|
22473
|
+
return TaskState.PENDING;
|
|
21687
22474
|
};
|
|
21688
22475
|
React.useEffect(() => {
|
|
21689
22476
|
const handleKeyDown = (e2) => {
|
|
21690
|
-
if (e2.key === "Escape" && openIdx !==
|
|
21691
|
-
setOpenIdx(
|
|
21692
|
-
setSelectedFile(null);
|
|
22477
|
+
if (e2.key === "Escape" && openIdx !== -1) {
|
|
22478
|
+
setOpenIdx(-1);
|
|
21693
22479
|
}
|
|
21694
22480
|
};
|
|
21695
|
-
if (openIdx !==
|
|
22481
|
+
if (openIdx !== -1) {
|
|
21696
22482
|
document.addEventListener("keydown", handleKeyDown);
|
|
21697
22483
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
21698
22484
|
}
|
|
21699
22485
|
}, [openIdx]);
|
|
21700
|
-
const
|
|
21701
|
-
|
|
21702
|
-
|
|
21703
|
-
|
|
21704
|
-
|
|
21705
|
-
|
|
21706
|
-
|
|
21707
|
-
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
|
|
21712
|
-
|
|
21713
|
-
|
|
21714
|
-
|
|
22486
|
+
const handleRestartClick = (e2, taskId) => {
|
|
22487
|
+
e2.stopPropagation();
|
|
22488
|
+
setRestartTaskId(taskId);
|
|
22489
|
+
setRestartModalOpen(true);
|
|
22490
|
+
};
|
|
22491
|
+
const handleRestartConfirm = async () => {
|
|
22492
|
+
if (!jobId || isSubmitting) return;
|
|
22493
|
+
setIsSubmitting(true);
|
|
22494
|
+
setAlertMessage(null);
|
|
22495
|
+
try {
|
|
22496
|
+
const restartOptions = {};
|
|
22497
|
+
if (restartTaskId) {
|
|
22498
|
+
restartOptions.fromTask = restartTaskId;
|
|
22499
|
+
}
|
|
22500
|
+
await restartJob(jobId, restartOptions);
|
|
22501
|
+
const successMessage = 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.";
|
|
22502
|
+
setAlertMessage(successMessage);
|
|
22503
|
+
setAlertType("success");
|
|
22504
|
+
setRestartModalOpen(false);
|
|
22505
|
+
setRestartTaskId(null);
|
|
22506
|
+
} catch (error) {
|
|
22507
|
+
let message = "Failed to start restart. Try again.";
|
|
22508
|
+
let type = "error";
|
|
22509
|
+
switch (error.code) {
|
|
22510
|
+
case "job_running":
|
|
22511
|
+
message = "Job is currently running; restart is unavailable.";
|
|
22512
|
+
type = "warning";
|
|
22513
|
+
break;
|
|
22514
|
+
case "unsupported_lifecycle":
|
|
22515
|
+
message = "Job must be in current lifecycle to restart.";
|
|
22516
|
+
type = "warning";
|
|
22517
|
+
break;
|
|
22518
|
+
case "job_not_found":
|
|
22519
|
+
message = "Job not found.";
|
|
22520
|
+
type = "error";
|
|
22521
|
+
break;
|
|
22522
|
+
case "spawn_failed":
|
|
22523
|
+
message = "Failed to start restart. Try again.";
|
|
22524
|
+
type = "error";
|
|
22525
|
+
break;
|
|
22526
|
+
default:
|
|
22527
|
+
message = error.message || "An unexpected error occurred.";
|
|
22528
|
+
type = "error";
|
|
22529
|
+
}
|
|
22530
|
+
setAlertMessage(message);
|
|
22531
|
+
setAlertType(type);
|
|
22532
|
+
} finally {
|
|
22533
|
+
setIsSubmitting(false);
|
|
21715
22534
|
}
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
22535
|
+
};
|
|
22536
|
+
const handleRestartCancel = () => {
|
|
22537
|
+
setRestartModalOpen(false);
|
|
22538
|
+
setRestartTaskId(null);
|
|
22539
|
+
};
|
|
22540
|
+
React.useEffect(() => {
|
|
22541
|
+
if (alertMessage) {
|
|
22542
|
+
const timer = setTimeout(() => {
|
|
22543
|
+
setAlertMessage(null);
|
|
22544
|
+
}, 5e3);
|
|
22545
|
+
return () => clearTimeout(timer);
|
|
22546
|
+
}
|
|
22547
|
+
}, [alertMessage]);
|
|
22548
|
+
const isRestartEnabled = React.useCallback(() => {
|
|
22549
|
+
const isJobRunning = items.some(
|
|
22550
|
+
(item) => item?.state === TaskState.RUNNING
|
|
22551
|
+
);
|
|
22552
|
+
const hasRunningTask = items.some(
|
|
22553
|
+
(item) => item?.status === TaskState.RUNNING
|
|
22554
|
+
);
|
|
22555
|
+
const jobLifecycle = items[0]?.lifecycle || "current";
|
|
22556
|
+
return jobLifecycle === "current" && !isJobRunning && !hasRunningTask;
|
|
22557
|
+
}, [items]);
|
|
22558
|
+
const getRestartDisabledReason = React.useCallback(() => {
|
|
22559
|
+
const isJobRunning = items.some(
|
|
22560
|
+
(item) => item?.state === TaskState.RUNNING
|
|
22561
|
+
);
|
|
22562
|
+
const hasRunningTask = items.some(
|
|
22563
|
+
(item) => item?.status === TaskState.RUNNING
|
|
22564
|
+
);
|
|
22565
|
+
const jobLifecycle = items[0]?.lifecycle || "current";
|
|
22566
|
+
if (isJobRunning || hasRunningTask) return "Job is currently running";
|
|
22567
|
+
if (jobLifecycle !== "current") return "Job must be in current lifecycle";
|
|
22568
|
+
return "";
|
|
22569
|
+
}, [items]);
|
|
21720
22570
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative w-full", role: "list", children: [
|
|
22571
|
+
alertMessage && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22572
|
+
"div",
|
|
22573
|
+
{
|
|
22574
|
+
className: `fixed top-4 right-4 z-[3000] max-w-sm p-4 rounded-lg shadow-lg border ${alertType === "success" ? "bg-green-50 border-green-200 text-green-800" : alertType === "error" ? "bg-red-50 border-red-200 text-red-800" : alertType === "warning" ? "bg-yellow-50 border-yellow-200 text-yellow-800" : "bg-blue-50 border-blue-200 text-blue-800"}`,
|
|
22575
|
+
role: "alert",
|
|
22576
|
+
"aria-live": "polite",
|
|
22577
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start", children: [
|
|
22578
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: alertMessage }) }),
|
|
22579
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22580
|
+
"button",
|
|
22581
|
+
{
|
|
22582
|
+
onClick: () => setAlertMessage(null),
|
|
22583
|
+
className: "ml-3 flex-shrink-0 inline-flex text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",
|
|
22584
|
+
"aria-label": "Dismiss notification",
|
|
22585
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "h-4 w-4", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22586
|
+
"path",
|
|
22587
|
+
{
|
|
22588
|
+
fillRule: "evenodd",
|
|
22589
|
+
d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
|
|
22590
|
+
clipRule: "evenodd"
|
|
22591
|
+
}
|
|
22592
|
+
) })
|
|
22593
|
+
}
|
|
22594
|
+
)
|
|
22595
|
+
] })
|
|
22596
|
+
}
|
|
22597
|
+
),
|
|
21721
22598
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21722
22599
|
"svg",
|
|
21723
22600
|
{
|
|
@@ -21736,7 +22613,8 @@ function DAGGrid({
|
|
|
21736
22613
|
markerHeight: "8",
|
|
21737
22614
|
orient: "auto",
|
|
21738
22615
|
markerUnits: "userSpaceOnUse",
|
|
21739
|
-
|
|
22616
|
+
className: "text-gray-400",
|
|
22617
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M 0 0 L 10 5 L 0 10 z" })
|
|
21740
22618
|
}
|
|
21741
22619
|
) }),
|
|
21742
22620
|
lines.map((line, idx) => /* @__PURE__ */ jsxRuntimeExports.jsx("g", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -21745,9 +22623,9 @@ function DAGGrid({
|
|
|
21745
22623
|
d: line.d,
|
|
21746
22624
|
fill: "none",
|
|
21747
22625
|
stroke: "currentColor",
|
|
21748
|
-
strokeWidth: "
|
|
21749
|
-
strokeLinecap: "
|
|
21750
|
-
className: "text-gray-
|
|
22626
|
+
strokeWidth: "1",
|
|
22627
|
+
strokeLinecap: "square",
|
|
22628
|
+
className: "text-gray-400",
|
|
21751
22629
|
strokeLinejoin: "round",
|
|
21752
22630
|
markerEnd: "url(#arrow)"
|
|
21753
22631
|
}
|
|
@@ -21774,195 +22652,58 @@ function DAGGrid({
|
|
|
21774
22652
|
const item = items[idx];
|
|
21775
22653
|
const status = getStatus(idx);
|
|
21776
22654
|
const isActive = idx === activeIndex;
|
|
21777
|
-
|
|
21778
|
-
|
|
22655
|
+
const canRestart = isRestartEnabled();
|
|
22656
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22657
|
+
TaskCard,
|
|
21779
22658
|
{
|
|
21780
|
-
|
|
21781
|
-
|
|
21782
|
-
|
|
21783
|
-
|
|
22659
|
+
idx,
|
|
22660
|
+
nodeRef: nodeRefs.current[idx],
|
|
22661
|
+
status,
|
|
22662
|
+
isActive,
|
|
22663
|
+
canRestart,
|
|
22664
|
+
isSubmitting,
|
|
22665
|
+
getRestartDisabledReason,
|
|
21784
22666
|
onClick: () => {
|
|
21785
22667
|
setOpenIdx(idx);
|
|
21786
|
-
setSelectedFile(null);
|
|
21787
22668
|
},
|
|
21788
22669
|
onKeyDown: (e2) => {
|
|
21789
22670
|
if (e2.key === "Enter" || e2.key === " ") {
|
|
21790
22671
|
e2.preventDefault();
|
|
21791
22672
|
setOpenIdx(idx);
|
|
21792
|
-
setSelectedFile(null);
|
|
21793
22673
|
}
|
|
21794
22674
|
},
|
|
21795
|
-
|
|
21796
|
-
|
|
21797
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21798
|
-
"div",
|
|
21799
|
-
{
|
|
21800
|
-
"data-role": "card-header",
|
|
21801
|
-
className: `rounded-t-lg px-4 py-2 border-b flex items-center justify-between gap-3 ${getHeaderClasses(status)}`,
|
|
21802
|
-
children: [
|
|
21803
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium truncate", children: formatStepName(item, idx) }),
|
|
21804
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: status === "running" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
21805
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative h-4 w-4", "aria-label": "Running", children: [
|
|
21806
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Running" }),
|
|
21807
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-0 rounded-full border-2 border-amber-200" }),
|
|
21808
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-0 rounded-full border-2 border-transparent border-t-amber-600 animate-spin" })
|
|
21809
|
-
] }),
|
|
21810
|
-
item.stage && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21811
|
-
"span",
|
|
21812
|
-
{
|
|
21813
|
-
className: "text-[11px] font-medium opacity-80 truncate",
|
|
21814
|
-
title: item.stage,
|
|
21815
|
-
children: formatStageLabel(item.stage)
|
|
21816
|
-
}
|
|
21817
|
-
)
|
|
21818
|
-
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[11px] uppercase tracking-wide opacity-80", children: [
|
|
21819
|
-
status,
|
|
21820
|
-
status === "failed" && item.stage && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21821
|
-
"span",
|
|
21822
|
-
{
|
|
21823
|
-
className: "text-[11px] font-medium opacity-80 truncate ml-2",
|
|
21824
|
-
title: item.stage,
|
|
21825
|
-
children: [
|
|
21826
|
-
"(",
|
|
21827
|
-
formatStageLabel(item.stage),
|
|
21828
|
-
")"
|
|
21829
|
-
]
|
|
21830
|
-
}
|
|
21831
|
-
)
|
|
21832
|
-
] }) })
|
|
21833
|
-
]
|
|
21834
|
-
}
|
|
21835
|
-
),
|
|
21836
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4", children: [
|
|
21837
|
-
item.subtitle && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-gray-600", children: item.subtitle }),
|
|
21838
|
-
item.body && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 text-sm text-gray-700", children: item.body })
|
|
21839
|
-
] })
|
|
21840
|
-
]
|
|
22675
|
+
handleRestartClick,
|
|
22676
|
+
item
|
|
21841
22677
|
},
|
|
21842
22678
|
item.id ?? idx
|
|
21843
22679
|
);
|
|
21844
22680
|
})
|
|
21845
22681
|
}
|
|
21846
22682
|
),
|
|
22683
|
+
openIdx !== -1 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22684
|
+
TaskDetailSidebar,
|
|
22685
|
+
{
|
|
22686
|
+
open: openIdx !== -1,
|
|
22687
|
+
title: formatStepName(items[openIdx], openIdx),
|
|
22688
|
+
status: getStatus(openIdx),
|
|
22689
|
+
jobId,
|
|
22690
|
+
taskId: items[openIdx]?.id || `task-${openIdx}`,
|
|
22691
|
+
taskBody: items[openIdx]?.body || null,
|
|
22692
|
+
filesByTypeForItem,
|
|
22693
|
+
task: items[openIdx],
|
|
22694
|
+
taskIndex: openIdx,
|
|
22695
|
+
onClose: () => setOpenIdx(-1)
|
|
22696
|
+
}
|
|
22697
|
+
),
|
|
21847
22698
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21848
|
-
|
|
22699
|
+
RestartJobModal,
|
|
21849
22700
|
{
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
21856
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21857
|
-
"div",
|
|
21858
|
-
{
|
|
21859
|
-
className: `px-6 py-4 border-b flex items-center justify-between ${getHeaderClasses(getStatus(openIdx))}`,
|
|
21860
|
-
children: [
|
|
21861
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21862
|
-
"div",
|
|
21863
|
-
{
|
|
21864
|
-
id: `slide-over-title-${openIdx}`,
|
|
21865
|
-
className: "text-lg font-semibold truncate",
|
|
21866
|
-
children: formatStepName(items[openIdx], openIdx)
|
|
21867
|
-
}
|
|
21868
|
-
),
|
|
21869
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21870
|
-
"button",
|
|
21871
|
-
{
|
|
21872
|
-
ref: closeButtonRef,
|
|
21873
|
-
type: "button",
|
|
21874
|
-
"aria-label": "Close details",
|
|
21875
|
-
onClick: () => {
|
|
21876
|
-
setOpenIdx(null);
|
|
21877
|
-
setSelectedFile(null);
|
|
21878
|
-
},
|
|
21879
|
-
className: "rounded-md border border-gray-300 text-gray-700 hover:bg-gray-50 px-3 py-1.5 text-base",
|
|
21880
|
-
children: "×"
|
|
21881
|
-
}
|
|
21882
|
-
)
|
|
21883
|
-
]
|
|
21884
|
-
}
|
|
21885
|
-
),
|
|
21886
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 space-y-8 overflow-y-auto h-full", children: [
|
|
21887
|
-
items[openIdx]?.status === "failed" && items[openIdx]?.body && /* @__PURE__ */ jsxRuntimeExports.jsx("section", { "aria-label": "Error", children: /* @__PURE__ */ jsxRuntimeExports.jsx(n$2, { role: "alert", "aria-live": "assertive", children: /* @__PURE__ */ jsxRuntimeExports.jsx(u$1, { className: "whitespace-pre-wrap break-words", children: items[openIdx].body }) }) }),
|
|
21888
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("section", { className: "mt-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
21889
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-base font-semibold text-gray-900", children: "Files" }),
|
|
21890
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center space-x-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex rounded-lg border border-gray-200 bg-gray-50 p-1", children: [
|
|
21891
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21892
|
-
"button",
|
|
21893
|
-
{
|
|
21894
|
-
onClick: () => setFilePaneType("artifacts"),
|
|
21895
|
-
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${filePaneType === "artifacts" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
21896
|
-
children: "Artifacts"
|
|
21897
|
-
}
|
|
21898
|
-
),
|
|
21899
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21900
|
-
"button",
|
|
21901
|
-
{
|
|
21902
|
-
onClick: () => setFilePaneType("logs"),
|
|
21903
|
-
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${filePaneType === "logs" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
21904
|
-
children: "Logs"
|
|
21905
|
-
}
|
|
21906
|
-
),
|
|
21907
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21908
|
-
"button",
|
|
21909
|
-
{
|
|
21910
|
-
onClick: () => setFilePaneType("tmp"),
|
|
21911
|
-
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${filePaneType === "tmp" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
21912
|
-
children: "Temp"
|
|
21913
|
-
}
|
|
21914
|
-
)
|
|
21915
|
-
] }) })
|
|
21916
|
-
] }) }),
|
|
21917
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
21918
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-gray-600", children: [
|
|
21919
|
-
filePaneType.charAt(0).toUpperCase() + filePaneType.slice(1),
|
|
21920
|
-
" ",
|
|
21921
|
-
"files for ",
|
|
21922
|
-
items[openIdx]?.id || `Task ${openIdx + 1}`
|
|
21923
|
-
] }),
|
|
21924
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: (() => {
|
|
21925
|
-
const filesForStep = filesByTypeForItem(items[openIdx]);
|
|
21926
|
-
const filesForTab = filesForStep[filePaneType] ?? [];
|
|
21927
|
-
if (filesForTab.length === 0) {
|
|
21928
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-gray-500 italic py-4 text-center", children: [
|
|
21929
|
-
"No ",
|
|
21930
|
-
filePaneType,
|
|
21931
|
-
" files available for this task"
|
|
21932
|
-
] });
|
|
21933
|
-
}
|
|
21934
|
-
return filesForTab.map((name) => {
|
|
21935
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21936
|
-
"div",
|
|
21937
|
-
{
|
|
21938
|
-
className: "flex items-center justify-between p-2 rounded border border-gray-200 hover:border-gray-300 hover:bg-gray-50 cursor-pointer transition-colors",
|
|
21939
|
-
onClick: () => {
|
|
21940
|
-
setFilePaneFilename(name);
|
|
21941
|
-
setFilePaneOpen(true);
|
|
21942
|
-
},
|
|
21943
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center space-x-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-700", children: name }) })
|
|
21944
|
-
},
|
|
21945
|
-
`${filePaneType}-${name}`
|
|
21946
|
-
);
|
|
21947
|
-
});
|
|
21948
|
-
})() })
|
|
21949
|
-
] }),
|
|
21950
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21951
|
-
TaskFilePane,
|
|
21952
|
-
{
|
|
21953
|
-
isOpen: filePaneOpen,
|
|
21954
|
-
jobId,
|
|
21955
|
-
taskId: items[openIdx]?.id || `task-${openIdx}`,
|
|
21956
|
-
type: filePaneType,
|
|
21957
|
-
filename: filePaneFilename,
|
|
21958
|
-
onClose: () => {
|
|
21959
|
-
setFilePaneOpen(false);
|
|
21960
|
-
setFilePaneFilename(null);
|
|
21961
|
-
}
|
|
21962
|
-
}
|
|
21963
|
-
)
|
|
21964
|
-
] })
|
|
21965
|
-
] })
|
|
22701
|
+
open: restartModalOpen,
|
|
22702
|
+
onClose: handleRestartCancel,
|
|
22703
|
+
onConfirm: handleRestartConfirm,
|
|
22704
|
+
jobId,
|
|
22705
|
+
taskId: restartTaskId,
|
|
22706
|
+
isSubmitting
|
|
21966
22707
|
}
|
|
21967
22708
|
)
|
|
21968
22709
|
] });
|
|
@@ -22003,7 +22744,7 @@ function computeDagItems(job, pipeline) {
|
|
|
22003
22744
|
const jobTask = jobTasks[taskId];
|
|
22004
22745
|
return {
|
|
22005
22746
|
id: taskId,
|
|
22006
|
-
status: jobTask ? jobTask.state :
|
|
22747
|
+
status: jobTask ? jobTask.state : TaskState.PENDING,
|
|
22007
22748
|
source: "pipeline",
|
|
22008
22749
|
stage: computeTaskStage(job, taskId)
|
|
22009
22750
|
};
|
|
@@ -22026,28 +22767,35 @@ function computeDagItems(job, pipeline) {
|
|
|
22026
22767
|
function computeActiveIndex(items) {
|
|
22027
22768
|
if (!items || items.length === 0) return 0;
|
|
22028
22769
|
const firstRunningIndex = items.findIndex(
|
|
22029
|
-
(item) => item.status ===
|
|
22770
|
+
(item) => item.status === TaskState.RUNNING
|
|
22030
22771
|
);
|
|
22031
22772
|
if (firstRunningIndex !== -1) return firstRunningIndex;
|
|
22032
|
-
const firstFailedIndex = items.findIndex(
|
|
22773
|
+
const firstFailedIndex = items.findIndex(
|
|
22774
|
+
(item) => item.status === TaskState.FAILED
|
|
22775
|
+
);
|
|
22033
22776
|
if (firstFailedIndex !== -1) return firstFailedIndex;
|
|
22034
22777
|
let lastDoneIndex = -1;
|
|
22035
22778
|
items.forEach((item, index2) => {
|
|
22036
|
-
if (item.status ===
|
|
22779
|
+
if (item.status === TaskState.DONE) lastDoneIndex = index2;
|
|
22037
22780
|
});
|
|
22038
22781
|
if (lastDoneIndex !== -1) return lastDoneIndex;
|
|
22039
22782
|
return 0;
|
|
22040
22783
|
}
|
|
22041
|
-
function
|
|
22042
|
-
|
|
22043
|
-
const
|
|
22044
|
-
|
|
22045
|
-
|
|
22046
|
-
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
)
|
|
22050
|
-
}
|
|
22784
|
+
function formatCurrency4(x) {
|
|
22785
|
+
if (typeof x !== "number" || x === 0) return "$0.0000";
|
|
22786
|
+
const formatted = x.toFixed(4);
|
|
22787
|
+
return `$${formatted.replace(/\.?0+$/, "")}`;
|
|
22788
|
+
}
|
|
22789
|
+
function formatTokensCompact(n2) {
|
|
22790
|
+
if (typeof n2 !== "number" || n2 === 0) return "0 tok";
|
|
22791
|
+
if (n2 >= 1e6) {
|
|
22792
|
+
return `${(n2 / 1e6).toFixed(1).replace(/\.0$/, "")}M tokens`;
|
|
22793
|
+
} else if (n2 >= 1e3) {
|
|
22794
|
+
return `${(n2 / 1e3).toFixed(1).replace(/\.0$/, "")}k tokens`;
|
|
22795
|
+
}
|
|
22796
|
+
return `${n2} tokens`;
|
|
22797
|
+
}
|
|
22798
|
+
function JobDetail({ job, pipeline }) {
|
|
22051
22799
|
const taskById = React.useMemo(() => {
|
|
22052
22800
|
const tasks = job?.tasks;
|
|
22053
22801
|
let result;
|
|
@@ -22082,18 +22830,9 @@ function JobDetail({ job, pipeline, onClose, onResume }) {
|
|
|
22082
22830
|
}
|
|
22083
22831
|
return result;
|
|
22084
22832
|
}, [pipeline, job?.tasks]);
|
|
22085
|
-
const
|
|
22833
|
+
const stableDagItems = React.useMemo(() => {
|
|
22086
22834
|
const rawDagItems = computeDagItems(job, computedPipeline);
|
|
22087
|
-
|
|
22088
|
-
{
|
|
22089
|
-
console.debug("[JobDetail] computed DAG item", {
|
|
22090
|
-
id: item.id,
|
|
22091
|
-
status: item.status,
|
|
22092
|
-
stage: item.stage,
|
|
22093
|
-
jobHasTasks: !!job?.tasks,
|
|
22094
|
-
taskKeys: job?.tasks ? Object.keys(job.tasks) : null
|
|
22095
|
-
});
|
|
22096
|
-
}
|
|
22835
|
+
return rawDagItems.map((item, index2) => {
|
|
22097
22836
|
const task = taskById[item.id];
|
|
22098
22837
|
const taskConfig = task?.config || {};
|
|
22099
22838
|
const subtitleParts = [];
|
|
@@ -22103,30 +22842,41 @@ function JobDetail({ job, pipeline, onClose, onResume }) {
|
|
|
22103
22842
|
if (taskConfig?.temperature != null) {
|
|
22104
22843
|
subtitleParts.push(`temp ${taskConfig.temperature}`);
|
|
22105
22844
|
}
|
|
22106
|
-
if (task?.attempts != null) {
|
|
22107
|
-
subtitleParts.push(`${task.attempts} attempts`);
|
|
22108
|
-
}
|
|
22109
22845
|
if (task?.refinementAttempts != null) {
|
|
22110
22846
|
subtitleParts.push(`${task.refinementAttempts} refinements`);
|
|
22111
22847
|
}
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22848
|
+
const taskBreakdown = job?.costs?.taskBreakdown?.[item.id]?.summary || {};
|
|
22849
|
+
if (taskBreakdown.totalTokens > 0) {
|
|
22850
|
+
subtitleParts.push(formatTokensCompact(taskBreakdown.totalTokens));
|
|
22851
|
+
}
|
|
22852
|
+
if (taskBreakdown.totalCost > 0) {
|
|
22853
|
+
subtitleParts.push(formatCurrency4(taskBreakdown.totalCost));
|
|
22117
22854
|
}
|
|
22118
22855
|
const errorMsg = task?.error?.message;
|
|
22119
|
-
const body = item.status === "failed" && errorMsg ? errorMsg : null;
|
|
22120
|
-
|
|
22856
|
+
const body = (item.status === "failed" || item.status === "error") && errorMsg ? errorMsg : null;
|
|
22857
|
+
return {
|
|
22121
22858
|
...item,
|
|
22122
22859
|
title: typeof item.id === "string" ? item.id : item.id?.name || item.id?.id || `Task ${item.id}`,
|
|
22123
22860
|
subtitle: subtitleParts.length > 0 ? subtitleParts.join(" · ") : null,
|
|
22124
|
-
body
|
|
22861
|
+
body,
|
|
22862
|
+
startedAt: task?.startedAt,
|
|
22863
|
+
endedAt: task?.endedAt
|
|
22125
22864
|
};
|
|
22126
|
-
return resultItem;
|
|
22127
22865
|
});
|
|
22128
|
-
|
|
22129
|
-
|
|
22866
|
+
}, [job, computedPipeline, taskById]);
|
|
22867
|
+
const prevDagItemsRef = React.useRef([]);
|
|
22868
|
+
const dagItems = React.useMemo(() => {
|
|
22869
|
+
const prevItems = prevDagItemsRef.current;
|
|
22870
|
+
const newItems = stableDagItems.map((item, index2) => {
|
|
22871
|
+
const prevItem = prevItems[index2];
|
|
22872
|
+
if (prevItem && prevItem.id === item.id && prevItem.status === item.status && prevItem.stage === item.stage && prevItem.title === item.title && prevItem.subtitle === item.subtitle && prevItem.body === item.body) {
|
|
22873
|
+
return prevItem;
|
|
22874
|
+
}
|
|
22875
|
+
return item;
|
|
22876
|
+
});
|
|
22877
|
+
prevDagItemsRef.current = newItems;
|
|
22878
|
+
return newItems;
|
|
22879
|
+
}, [stableDagItems]);
|
|
22130
22880
|
const activeIndex = React.useMemo(() => {
|
|
22131
22881
|
const index2 = computeActiveIndex(dagItems);
|
|
22132
22882
|
return index2;
|
|
@@ -22149,40 +22899,6 @@ function JobDetail({ job, pipeline, onClose, onResume }) {
|
|
|
22149
22899
|
) });
|
|
22150
22900
|
}
|
|
22151
22901
|
const REFRESH_DEBOUNCE_MS = 200;
|
|
22152
|
-
const createHookLogger = (jobId) => {
|
|
22153
|
-
const prefix = `[useJobDetailWithUpdates:${jobId || "unknown"}]`;
|
|
22154
|
-
return {
|
|
22155
|
-
log: (message, data = null) => {
|
|
22156
|
-
console.log(`${prefix} ${message}`, data ? data : "");
|
|
22157
|
-
},
|
|
22158
|
-
warn: (message, data = null) => {
|
|
22159
|
-
console.warn(`${prefix} ${message}`, data ? data : "");
|
|
22160
|
-
},
|
|
22161
|
-
error: (message, data = null) => {
|
|
22162
|
-
console.error(`${prefix} ${message}`, data ? data : "");
|
|
22163
|
-
},
|
|
22164
|
-
group: (label) => console.group(`${prefix} ${label}`),
|
|
22165
|
-
groupEnd: () => console.groupEnd(),
|
|
22166
|
-
table: (data, title) => {
|
|
22167
|
-
console.log(`${prefix} ${title}:`);
|
|
22168
|
-
console.table(data);
|
|
22169
|
-
},
|
|
22170
|
-
sse: (eventType, eventData) => {
|
|
22171
|
-
console.log(
|
|
22172
|
-
`%c${prefix} SSE Event: ${eventType}`,
|
|
22173
|
-
"color: #0066cc; font-weight: bold;",
|
|
22174
|
-
eventData
|
|
22175
|
-
);
|
|
22176
|
-
},
|
|
22177
|
-
state: (stateName, value) => {
|
|
22178
|
-
console.log(
|
|
22179
|
-
`%c${prefix} State Change: ${stateName}`,
|
|
22180
|
-
"color: #006600; font-weight: bold;",
|
|
22181
|
-
value
|
|
22182
|
-
);
|
|
22183
|
-
}
|
|
22184
|
-
};
|
|
22185
|
-
};
|
|
22186
22902
|
async function fetchJobDetail(jobId, { signal } = {}) {
|
|
22187
22903
|
const response = await fetch(`/api/jobs/${jobId}`, { signal });
|
|
22188
22904
|
if (!response.ok) {
|
|
@@ -22267,90 +22983,63 @@ function matchesJobTasksStatusPath(path, jobId) {
|
|
|
22267
22983
|
}
|
|
22268
22984
|
}
|
|
22269
22985
|
function useJobDetailWithUpdates(jobId) {
|
|
22270
|
-
const logger = reactExports.useMemo(() => createHookLogger(jobId), [jobId]);
|
|
22271
22986
|
const [data, setData] = reactExports.useState(null);
|
|
22272
22987
|
const [loading, setLoading] = reactExports.useState(true);
|
|
22273
22988
|
const [error, setError] = reactExports.useState(null);
|
|
22274
22989
|
const [connectionStatus, setConnectionStatus] = reactExports.useState("disconnected");
|
|
22990
|
+
const [isRefreshing, setIsRefreshing] = reactExports.useState(false);
|
|
22991
|
+
const [isPending, startTransition] = reactExports.useTransition();
|
|
22992
|
+
const [isHydrated, setIsHydrated] = reactExports.useState(false);
|
|
22275
22993
|
const esRef = reactExports.useRef(null);
|
|
22276
22994
|
const reconnectTimer = reactExports.useRef(null);
|
|
22277
22995
|
const hydratedRef = reactExports.useRef(false);
|
|
22278
22996
|
const eventQueue = reactExports.useRef([]);
|
|
22279
22997
|
const mountedRef = reactExports.useRef(true);
|
|
22280
22998
|
const refetchTimerRef = reactExports.useRef(null);
|
|
22281
|
-
reactExports.useEffect(() => {
|
|
22282
|
-
logger.group("Hook Initialization");
|
|
22283
|
-
logger.log("Job ID:", jobId);
|
|
22284
|
-
logger.log("Initial state:", { data, loading, error, connectionStatus });
|
|
22285
|
-
logger.groupEnd();
|
|
22286
|
-
}, [jobId, logger]);
|
|
22287
|
-
reactExports.useEffect(() => {
|
|
22288
|
-
logger.state("data", data);
|
|
22289
|
-
}, [data, logger]);
|
|
22290
|
-
reactExports.useEffect(() => {
|
|
22291
|
-
logger.state("loading", loading);
|
|
22292
|
-
}, [loading, logger]);
|
|
22293
|
-
reactExports.useEffect(() => {
|
|
22294
|
-
logger.state("error", error);
|
|
22295
|
-
}, [error, logger]);
|
|
22296
|
-
reactExports.useEffect(() => {
|
|
22297
|
-
logger.state("connectionStatus", connectionStatus);
|
|
22298
|
-
}, [connectionStatus, logger]);
|
|
22299
22999
|
const scheduleDebouncedRefetch = reactExports.useCallback(
|
|
22300
23000
|
(context = {}) => {
|
|
22301
|
-
logger.group("Debounced Refetch Request");
|
|
22302
|
-
logger.log("Request context:", context);
|
|
22303
|
-
logger.log("Scheduling debounced refetch");
|
|
22304
23001
|
if (refetchTimerRef.current) {
|
|
22305
|
-
logger.log("Clearing existing refetch timer");
|
|
22306
23002
|
clearTimeout(refetchTimerRef.current);
|
|
22307
23003
|
}
|
|
22308
23004
|
refetchTimerRef.current = setTimeout(async () => {
|
|
22309
23005
|
if (!mountedRef.current || !hydratedRef.current) {
|
|
22310
|
-
logger.warn(
|
|
22311
|
-
"Refetch aborted - component not mounted or not hydrated",
|
|
22312
|
-
{ mounted: mountedRef.current, hydrated: hydratedRef.current }
|
|
22313
|
-
);
|
|
22314
|
-
logger.groupEnd();
|
|
22315
23006
|
return;
|
|
22316
23007
|
}
|
|
22317
|
-
logger.log("Executing debounced refetch");
|
|
22318
|
-
logger.log("Refetch jobId:", jobId);
|
|
22319
23008
|
const abortController = new AbortController();
|
|
22320
23009
|
try {
|
|
23010
|
+
startTransition(() => {
|
|
23011
|
+
setIsRefreshing(true);
|
|
23012
|
+
});
|
|
22321
23013
|
const jobData = await fetchJobDetail(jobId, {
|
|
22322
23014
|
signal: abortController.signal
|
|
22323
23015
|
});
|
|
22324
|
-
logger.log("Refetch response received");
|
|
22325
|
-
logger.log("Refetch job data preview:", {
|
|
22326
|
-
status: jobData?.status,
|
|
22327
|
-
hasTasks: !!jobData?.tasks,
|
|
22328
|
-
taskKeys: jobData?.tasks ? Object.keys(jobData.tasks) : [],
|
|
22329
|
-
hasTasksStatus: !!jobData?.tasksStatus
|
|
22330
|
-
});
|
|
22331
23016
|
if (mountedRef.current) {
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
23017
|
+
startTransition(() => {
|
|
23018
|
+
setData(jobData);
|
|
23019
|
+
setError(null);
|
|
23020
|
+
setIsRefreshing(false);
|
|
23021
|
+
});
|
|
22337
23022
|
}
|
|
22338
23023
|
} catch (err) {
|
|
22339
|
-
|
|
22340
|
-
|
|
23024
|
+
if (mountedRef.current) {
|
|
23025
|
+
startTransition(() => {
|
|
23026
|
+
setError(err.message);
|
|
23027
|
+
setIsRefreshing(false);
|
|
23028
|
+
});
|
|
23029
|
+
}
|
|
22341
23030
|
} finally {
|
|
22342
23031
|
refetchTimerRef.current = null;
|
|
22343
|
-
logger.groupEnd();
|
|
22344
23032
|
}
|
|
22345
23033
|
}, REFRESH_DEBOUNCE_MS);
|
|
22346
23034
|
},
|
|
22347
|
-
[jobId
|
|
23035
|
+
[jobId]
|
|
22348
23036
|
);
|
|
22349
23037
|
reactExports.useEffect(() => {
|
|
22350
23038
|
setData(null);
|
|
22351
23039
|
setLoading(true);
|
|
22352
23040
|
setError(null);
|
|
22353
23041
|
setConnectionStatus("disconnected");
|
|
23042
|
+
setIsHydrated(false);
|
|
22354
23043
|
hydratedRef.current = false;
|
|
22355
23044
|
eventQueue.current = [];
|
|
22356
23045
|
if (refetchTimerRef.current) {
|
|
@@ -22361,92 +23050,80 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22361
23050
|
reactExports.useEffect(() => {
|
|
22362
23051
|
if (!jobId || !mountedRef.current) return;
|
|
22363
23052
|
const doFetch = async () => {
|
|
22364
|
-
logger.group("Initial Data Fetch");
|
|
22365
23053
|
try {
|
|
22366
|
-
|
|
23054
|
+
if (!hydratedRef.current) {
|
|
23055
|
+
setLoading(true);
|
|
23056
|
+
}
|
|
22367
23057
|
setError(null);
|
|
22368
|
-
logger.log("Starting initial job data fetch");
|
|
22369
23058
|
const jobData = await fetchJobDetail(jobId);
|
|
22370
|
-
logger.log("Initial fetch successful", jobData);
|
|
22371
23059
|
let finalData = jobData;
|
|
22372
23060
|
let queuedNeedsRefetch = false;
|
|
22373
23061
|
if (eventQueue.current.length > 0) {
|
|
22374
|
-
logger.log(`Processing ${eventQueue.current.length} queued events`);
|
|
22375
23062
|
for (const ev of eventQueue.current) {
|
|
22376
|
-
logger.log("Processing queued event:", ev);
|
|
22377
23063
|
if (ev.type === "state:change") {
|
|
22378
23064
|
const d2 = ev.payload && (ev.payload.data || ev.payload) || {};
|
|
22379
23065
|
if (typeof d2.path === "string" && matchesJobTasksStatusPath(d2.path, jobId)) {
|
|
22380
|
-
logger.log(
|
|
22381
|
-
"Queued state:change matches tasks-status path, scheduling refetch"
|
|
22382
|
-
);
|
|
22383
23066
|
queuedNeedsRefetch = true;
|
|
22384
23067
|
continue;
|
|
22385
23068
|
}
|
|
22386
23069
|
}
|
|
22387
23070
|
finalData = applyJobEvent(finalData, ev, jobId);
|
|
22388
|
-
logger.log("Applied queued event, result:", finalData);
|
|
22389
23071
|
}
|
|
22390
23072
|
eventQueue.current = [];
|
|
22391
23073
|
}
|
|
22392
23074
|
if (mountedRef.current) {
|
|
22393
|
-
|
|
22394
|
-
|
|
22395
|
-
|
|
22396
|
-
|
|
22397
|
-
|
|
23075
|
+
startTransition(() => {
|
|
23076
|
+
setData(finalData);
|
|
23077
|
+
setError(null);
|
|
23078
|
+
const wasHydrated = hydratedRef.current;
|
|
23079
|
+
hydratedRef.current = true;
|
|
23080
|
+
if (!wasHydrated) {
|
|
23081
|
+
setIsHydrated(true);
|
|
23082
|
+
setLoading(false);
|
|
23083
|
+
}
|
|
23084
|
+
});
|
|
22398
23085
|
if (queuedNeedsRefetch) {
|
|
22399
|
-
logger.log("Scheduling refetch for queued path changes");
|
|
22400
23086
|
scheduleDebouncedRefetch();
|
|
22401
23087
|
}
|
|
22402
23088
|
}
|
|
22403
23089
|
} catch (err) {
|
|
22404
|
-
logger.error("Failed to fetch job detail:", err);
|
|
22405
23090
|
if (mountedRef.current) {
|
|
22406
|
-
|
|
22407
|
-
|
|
23091
|
+
startTransition(() => {
|
|
23092
|
+
setError(err.message);
|
|
23093
|
+
setData(null);
|
|
23094
|
+
if (!hydratedRef.current) {
|
|
23095
|
+
setLoading(false);
|
|
23096
|
+
}
|
|
23097
|
+
});
|
|
22408
23098
|
}
|
|
22409
23099
|
} finally {
|
|
22410
|
-
if (mountedRef.current) {
|
|
23100
|
+
if (mountedRef.current && !hydratedRef.current) {
|
|
22411
23101
|
setLoading(false);
|
|
22412
23102
|
}
|
|
22413
|
-
logger.groupEnd();
|
|
22414
23103
|
}
|
|
22415
23104
|
};
|
|
22416
23105
|
doFetch();
|
|
22417
|
-
}, [jobId, scheduleDebouncedRefetch
|
|
23106
|
+
}, [jobId, scheduleDebouncedRefetch]);
|
|
22418
23107
|
reactExports.useEffect(() => {
|
|
22419
23108
|
if (!jobId) {
|
|
22420
|
-
logger.log("SSE setup skipped - no jobId available", {
|
|
22421
|
-
hasJobId: !!jobId,
|
|
22422
|
-
hasExistingEs: !!esRef.current,
|
|
22423
|
-
isMounted: mountedRef.current
|
|
22424
|
-
});
|
|
22425
23109
|
return void 0;
|
|
22426
23110
|
}
|
|
22427
23111
|
if (esRef.current) {
|
|
22428
|
-
logger.log("Closing existing EventSource before reinitializing");
|
|
22429
23112
|
try {
|
|
22430
23113
|
esRef.current.close();
|
|
22431
23114
|
} catch (err) {
|
|
22432
|
-
logger.warn("Error closing existing EventSource during reinit", err);
|
|
22433
23115
|
}
|
|
22434
23116
|
esRef.current = null;
|
|
22435
23117
|
}
|
|
22436
|
-
logger.group("SSE Connection Setup");
|
|
22437
|
-
logger.log("Setting up SSE connection for job:", jobId);
|
|
22438
23118
|
const attachListeners = (es) => {
|
|
22439
23119
|
const onOpen = () => {
|
|
22440
|
-
logger.log("SSE connection opened");
|
|
22441
23120
|
if (mountedRef.current) {
|
|
22442
23121
|
setConnectionStatus("connected");
|
|
22443
23122
|
}
|
|
22444
23123
|
};
|
|
22445
23124
|
const onError = () => {
|
|
22446
|
-
logger.warn("SSE connection error");
|
|
22447
23125
|
try {
|
|
22448
23126
|
const rs = esRef.current?.readyState;
|
|
22449
|
-
logger.log("SSE readyState:", rs);
|
|
22450
23127
|
if (rs === 0) {
|
|
22451
23128
|
if (mountedRef.current) setConnectionStatus("disconnected");
|
|
22452
23129
|
} else if (rs === 1) {
|
|
@@ -22457,11 +23134,9 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22457
23134
|
if (mountedRef.current) setConnectionStatus("disconnected");
|
|
22458
23135
|
}
|
|
22459
23136
|
} catch (err) {
|
|
22460
|
-
logger.error("Error getting readyState:", err);
|
|
22461
23137
|
if (mountedRef.current) setConnectionStatus("disconnected");
|
|
22462
23138
|
}
|
|
22463
23139
|
if (esRef.current && esRef.current.readyState === 2 && mountedRef.current) {
|
|
22464
|
-
logger.log("Scheduling SSE reconnection");
|
|
22465
23140
|
if (reconnectTimer.current) clearTimeout(reconnectTimer.current);
|
|
22466
23141
|
reconnectTimer.current = setTimeout(() => {
|
|
22467
23142
|
if (!mountedRef.current) return;
|
|
@@ -22471,7 +23146,6 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22471
23146
|
} catch (e2) {
|
|
22472
23147
|
}
|
|
22473
23148
|
const eventsUrl = jobId ? `/api/events?jobId=${encodeURIComponent(jobId)}` : "/api/events";
|
|
22474
|
-
logger.log("Creating new EventSource for reconnection");
|
|
22475
23149
|
const newEs = new EventSource(eventsUrl);
|
|
22476
23150
|
newEs.addEventListener("open", onOpen);
|
|
22477
23151
|
newEs.addEventListener("job:updated", onJobUpdated);
|
|
@@ -22482,7 +23156,7 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22482
23156
|
newEs.addEventListener("error", onError);
|
|
22483
23157
|
esRef.current = newEs;
|
|
22484
23158
|
} catch (err) {
|
|
22485
|
-
|
|
23159
|
+
console.error("Failed to reconnect SSE:", err);
|
|
22486
23160
|
}
|
|
22487
23161
|
}, 2e3);
|
|
22488
23162
|
}
|
|
@@ -22491,64 +23165,37 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22491
23165
|
try {
|
|
22492
23166
|
const payload = evt && evt.data ? JSON.parse(evt.data) : null;
|
|
22493
23167
|
const eventObj = { type, payload };
|
|
22494
|
-
logger.sse(type, payload);
|
|
22495
23168
|
if (payload && payload.jobId && payload.jobId !== jobId) {
|
|
22496
|
-
logger.log(
|
|
22497
|
-
`Ignoring event for different job: ${payload.jobId} (current: ${jobId})`
|
|
22498
|
-
);
|
|
22499
23169
|
return;
|
|
22500
23170
|
}
|
|
22501
23171
|
if (!hydratedRef.current) {
|
|
22502
|
-
logger.log(`Queueing event until hydration: ${type}`);
|
|
22503
23172
|
eventQueue.current = (eventQueue.current || []).concat(eventObj);
|
|
22504
23173
|
return;
|
|
22505
23174
|
}
|
|
22506
23175
|
if (type === "state:change") {
|
|
22507
23176
|
const d2 = payload && (payload.data || payload) || {};
|
|
22508
|
-
logger.log("Processing state:change event:", d2);
|
|
22509
23177
|
if (typeof d2.path === "string" && matchesJobTasksStatusPath(d2.path, jobId)) {
|
|
22510
|
-
logger.log(
|
|
22511
|
-
`state:change matches tasks-status path: ${d2.path}, scheduling refetch`
|
|
22512
|
-
);
|
|
22513
23178
|
scheduleDebouncedRefetch({
|
|
22514
23179
|
reason: "state:change",
|
|
22515
23180
|
path: d2.path
|
|
22516
23181
|
});
|
|
22517
23182
|
return;
|
|
22518
|
-
} else {
|
|
22519
|
-
logger.log(
|
|
22520
|
-
`state:change does not match tasks-status path: ${d2.path}`
|
|
22521
|
-
);
|
|
22522
23183
|
}
|
|
22523
23184
|
}
|
|
22524
|
-
|
|
22525
|
-
|
|
22526
|
-
|
|
22527
|
-
|
|
22528
|
-
|
|
22529
|
-
|
|
22530
|
-
|
|
22531
|
-
|
|
22532
|
-
|
|
22533
|
-
try {
|
|
22534
|
-
if (JSON.stringify(prev) === JSON.stringify(next)) {
|
|
22535
|
-
logger.log("Event application resulted in no state change");
|
|
22536
|
-
logger.groupEnd();
|
|
22537
|
-
return prev;
|
|
23185
|
+
startTransition(() => {
|
|
23186
|
+
setData((prev) => {
|
|
23187
|
+
const next = applyJobEvent(prev, eventObj, jobId);
|
|
23188
|
+
try {
|
|
23189
|
+
if (JSON.stringify(prev) === JSON.stringify(next)) {
|
|
23190
|
+
return prev;
|
|
23191
|
+
}
|
|
23192
|
+
} catch (e2) {
|
|
23193
|
+
console.error("Error comparing states:", e2);
|
|
22538
23194
|
}
|
|
22539
|
-
|
|
22540
|
-
logger.error("Error comparing states:", e2);
|
|
22541
|
-
}
|
|
22542
|
-
logger.log("Event applied, state updated", {
|
|
22543
|
-
hasTasks: !!next?.tasks,
|
|
22544
|
-
taskKeys: next?.tasks ? Object.keys(next.tasks) : [],
|
|
22545
|
-
status: next?.status
|
|
23195
|
+
return next;
|
|
22546
23196
|
});
|
|
22547
|
-
logger.groupEnd();
|
|
22548
|
-
return next;
|
|
22549
23197
|
});
|
|
22550
23198
|
} catch (err) {
|
|
22551
|
-
logger.error("Failed to handle SSE event:", err);
|
|
22552
23199
|
console.error("Failed to handle SSE event:", err);
|
|
22553
23200
|
}
|
|
22554
23201
|
};
|
|
@@ -22557,7 +23204,6 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22557
23204
|
const onJobRemoved = (evt) => handleIncomingEvent("job:removed", evt);
|
|
22558
23205
|
const onStatusChanged = (evt) => handleIncomingEvent("status:changed", evt);
|
|
22559
23206
|
const onStateChange = (evt) => handleIncomingEvent("state:change", evt);
|
|
22560
|
-
logger.log("Attaching SSE event listeners");
|
|
22561
23207
|
es.addEventListener("open", onOpen);
|
|
22562
23208
|
es.addEventListener("job:updated", onJobUpdated);
|
|
22563
23209
|
es.addEventListener("job:created", onJobCreated);
|
|
@@ -22566,14 +23212,11 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22566
23212
|
es.addEventListener("state:change", onStateChange);
|
|
22567
23213
|
es.addEventListener("error", onError);
|
|
22568
23214
|
if (es.readyState === 1 && mountedRef.current) {
|
|
22569
|
-
logger.log("SSE already open, setting connected");
|
|
22570
23215
|
setConnectionStatus("connected");
|
|
22571
23216
|
} else if (es.readyState === 0 && mountedRef.current) {
|
|
22572
|
-
logger.log("SSE connecting, setting disconnected");
|
|
22573
23217
|
setConnectionStatus("disconnected");
|
|
22574
23218
|
}
|
|
22575
23219
|
return () => {
|
|
22576
|
-
logger.log("Cleaning up SSE connection");
|
|
22577
23220
|
try {
|
|
22578
23221
|
es.removeEventListener("open", onOpen);
|
|
22579
23222
|
es.removeEventListener("job:updated", onJobUpdated);
|
|
@@ -22583,9 +23226,8 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22583
23226
|
es.removeEventListener("state:change", onStateChange);
|
|
22584
23227
|
es.removeEventListener("error", onError);
|
|
22585
23228
|
es.close();
|
|
22586
|
-
logger.log("SSE connection closed");
|
|
22587
23229
|
} catch (err) {
|
|
22588
|
-
|
|
23230
|
+
console.error("Error during SSE cleanup:", err);
|
|
22589
23231
|
}
|
|
22590
23232
|
if (reconnectTimer.current) {
|
|
22591
23233
|
clearTimeout(reconnectTimer.current);
|
|
@@ -22596,21 +23238,18 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22596
23238
|
};
|
|
22597
23239
|
try {
|
|
22598
23240
|
const eventsUrl = jobId ? `/api/events?jobId=${encodeURIComponent(jobId)}` : "/api/events";
|
|
22599
|
-
logger.log(`Creating EventSource with URL: ${eventsUrl}`);
|
|
22600
23241
|
const es = new EventSource(eventsUrl);
|
|
22601
23242
|
esRef.current = es;
|
|
22602
23243
|
const cleanup = attachListeners(es);
|
|
22603
|
-
logger.groupEnd();
|
|
22604
23244
|
return cleanup;
|
|
22605
23245
|
} catch (err) {
|
|
22606
|
-
|
|
23246
|
+
console.error("Failed to create SSE connection:", err);
|
|
22607
23247
|
if (mountedRef.current) {
|
|
22608
23248
|
setConnectionStatus("error");
|
|
22609
23249
|
}
|
|
22610
|
-
logger.groupEnd();
|
|
22611
23250
|
return void 0;
|
|
22612
23251
|
}
|
|
22613
|
-
}, [jobId, scheduleDebouncedRefetch
|
|
23252
|
+
}, [jobId, scheduleDebouncedRefetch]);
|
|
22614
23253
|
reactExports.useEffect(() => {
|
|
22615
23254
|
mountedRef.current = true;
|
|
22616
23255
|
return () => {
|
|
@@ -22636,26 +23275,77 @@ function useJobDetailWithUpdates(jobId) {
|
|
|
22636
23275
|
data,
|
|
22637
23276
|
loading,
|
|
22638
23277
|
error,
|
|
22639
|
-
connectionStatus
|
|
23278
|
+
connectionStatus,
|
|
23279
|
+
isRefreshing,
|
|
23280
|
+
isTransitioning: isPending,
|
|
23281
|
+
isHydrated
|
|
22640
23282
|
};
|
|
22641
23283
|
}
|
|
22642
23284
|
function PipelineDetail() {
|
|
22643
23285
|
const { jobId } = useParams();
|
|
22644
23286
|
if (jobId === void 0 || jobId === null) {
|
|
22645
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23287
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23288
|
+
Layout,
|
|
23289
|
+
{
|
|
23290
|
+
pageTitle: "Pipeline Details",
|
|
23291
|
+
breadcrumbs: [{ label: "Home", href: "/" }],
|
|
23292
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", justify: "center", className: "min-h-64", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "5", weight: "medium", color: "red", className: "mb-2", children: "No job ID provided" }) }) })
|
|
23293
|
+
}
|
|
23294
|
+
);
|
|
22646
23295
|
}
|
|
22647
|
-
const {
|
|
22648
|
-
|
|
22649
|
-
|
|
23296
|
+
const {
|
|
23297
|
+
data: job,
|
|
23298
|
+
loading,
|
|
23299
|
+
error,
|
|
23300
|
+
isRefreshing,
|
|
23301
|
+
isHydrated
|
|
23302
|
+
} = useJobDetailWithUpdates(jobId);
|
|
23303
|
+
const showLoadingScreen = loading && !isHydrated;
|
|
23304
|
+
if (showLoadingScreen) {
|
|
23305
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23306
|
+
Layout,
|
|
23307
|
+
{
|
|
23308
|
+
pageTitle: "Pipeline Details",
|
|
23309
|
+
breadcrumbs: [
|
|
23310
|
+
{ label: "Home", href: "/" },
|
|
23311
|
+
{
|
|
23312
|
+
label: job && job?.pipelineLabel ? job.pipelineLabel : "Pipeline Details"
|
|
23313
|
+
}
|
|
23314
|
+
],
|
|
23315
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", justify: "center", className: "min-h-64", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "5", weight: "medium", className: "mb-2", children: "Loading job details..." }) }) })
|
|
23316
|
+
}
|
|
23317
|
+
);
|
|
22650
23318
|
}
|
|
22651
23319
|
if (error) {
|
|
22652
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22653
|
-
|
|
22654
|
-
|
|
22655
|
-
|
|
23320
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23321
|
+
Layout,
|
|
23322
|
+
{
|
|
23323
|
+
pageTitle: "Pipeline Details",
|
|
23324
|
+
breadcrumbs: [
|
|
23325
|
+
{ label: "Home", href: "/" },
|
|
23326
|
+
{
|
|
23327
|
+
label: job && job?.pipelineLabel ? job.pipelineLabel : "Pipeline Details"
|
|
23328
|
+
}
|
|
23329
|
+
],
|
|
23330
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", justify: "center", className: "min-h-64", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { className: "text-center", children: [
|
|
23331
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "5", weight: "medium", color: "red", className: "mb-2", children: "Failed to load job details" }),
|
|
23332
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", color: "gray", className: "mt-2", children: error })
|
|
23333
|
+
] }) })
|
|
23334
|
+
}
|
|
23335
|
+
);
|
|
22656
23336
|
}
|
|
22657
23337
|
if (!job) {
|
|
22658
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23338
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23339
|
+
Layout,
|
|
23340
|
+
{
|
|
23341
|
+
pageTitle: "Pipeline Details",
|
|
23342
|
+
breadcrumbs: [
|
|
23343
|
+
{ label: "Home", href: "/" },
|
|
23344
|
+
{ label: job.pipelineLabel || "Pipeline Details" }
|
|
23345
|
+
],
|
|
23346
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$4, { align: "center", justify: "center", className: "min-h-64", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { className: "text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "5", weight: "medium", className: "mb-2", children: "Job not found" }) }) })
|
|
23347
|
+
}
|
|
23348
|
+
);
|
|
22659
23349
|
}
|
|
22660
23350
|
const pipeline = job?.pipeline || (() => {
|
|
22661
23351
|
if (!job?.tasks) return { tasks: [] };
|
|
@@ -22667,25 +23357,380 @@ function PipelineDetail() {
|
|
|
22667
23357
|
}
|
|
22668
23358
|
return { tasks: pipelineTasks };
|
|
22669
23359
|
})();
|
|
22670
|
-
const
|
|
22671
|
-
|
|
23360
|
+
const pageTitle = job.name || "Pipeline Details";
|
|
23361
|
+
const breadcrumbs = [
|
|
23362
|
+
{ label: "Home", href: "/" },
|
|
23363
|
+
{
|
|
23364
|
+
label: job && job?.pipelineLabel ? job.pipelineLabel : "Pipeline Details"
|
|
23365
|
+
},
|
|
23366
|
+
...job.name ? [{ label: job.name }] : []
|
|
23367
|
+
];
|
|
23368
|
+
const totalCost = job?.totalCost || job?.costs?.summary?.totalCost || 0;
|
|
23369
|
+
const totalTokens = job?.totalTokens || job?.costs?.summary?.totalTokens || 0;
|
|
23370
|
+
const totalInputTokens = job?.costs?.summary?.totalInputTokens || 0;
|
|
23371
|
+
const totalOutputTokens = job?.costs?.summary?.totalOutputTokens || 0;
|
|
23372
|
+
const costIndicator = /* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { size: "2", color: "gray", children: [
|
|
23373
|
+
"Cost: ",
|
|
23374
|
+
totalCost > 0 ? formatCurrency4(totalCost) : "—"
|
|
23375
|
+
] });
|
|
23376
|
+
const costIndicatorWithTooltip = totalCost > 0 && totalTokens > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(Provider, { delayDuration: 100, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Root3, { children: [
|
|
23377
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23378
|
+
p$7,
|
|
23379
|
+
{
|
|
23380
|
+
className: "cursor-help border-b border-dotted border-gray-400 hover:border-gray-600 transition-colors",
|
|
23381
|
+
"aria-label": `Total cost: ${formatCurrency4(totalCost)}, ${formatTokensCompact(totalTokens)}`,
|
|
23382
|
+
children: costIndicator
|
|
23383
|
+
}
|
|
23384
|
+
) }),
|
|
23385
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
23386
|
+
Content2,
|
|
23387
|
+
{
|
|
23388
|
+
className: "bg-gray-900 text-white px-2 py-1 rounded text-xs max-w-xs",
|
|
23389
|
+
sideOffset: 5,
|
|
23390
|
+
children: [
|
|
23391
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
|
|
23392
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold", children: formatTokensCompact(totalTokens) }),
|
|
23393
|
+
totalInputTokens > 0 && totalOutputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-gray-300", children: [
|
|
23394
|
+
"Input: ",
|
|
23395
|
+
formatTokensCompact(totalInputTokens),
|
|
23396
|
+
" • Output:",
|
|
23397
|
+
" ",
|
|
23398
|
+
formatTokensCompact(totalOutputTokens)
|
|
23399
|
+
] })
|
|
23400
|
+
] }),
|
|
23401
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Arrow2, { className: "fill-gray-900" })
|
|
23402
|
+
]
|
|
23403
|
+
}
|
|
23404
|
+
) })
|
|
23405
|
+
] }) }) : costIndicator;
|
|
23406
|
+
const subheaderRightContent = /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { align: "center", gap: "3", className: "shrink-0 flex-wrap", children: [
|
|
23407
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { size: "2", color: "gray", children: [
|
|
22672
23408
|
"ID: ",
|
|
22673
23409
|
job.id || jobId
|
|
22674
23410
|
] }),
|
|
23411
|
+
costIndicatorWithTooltip,
|
|
22675
23412
|
statusBadge(job.status)
|
|
22676
23413
|
] });
|
|
23414
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Layout, { pageTitle, breadcrumbs, children: [
|
|
23415
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(PageSubheader, { breadcrumbs, maxWidth: "max-w-7xl", children: [
|
|
23416
|
+
subheaderRightContent,
|
|
23417
|
+
isRefreshing && /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { size: "2", color: "blue", className: "ml-3 animate-pulse", children: "Refreshing..." })
|
|
23418
|
+
] }),
|
|
23419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(JobDetail, { job, pipeline })
|
|
23420
|
+
] });
|
|
23421
|
+
}
|
|
23422
|
+
const ioFunctions = [
|
|
23423
|
+
{
|
|
23424
|
+
name: "writeArtifact",
|
|
23425
|
+
description: "Write an artifact file",
|
|
23426
|
+
params: 'name: string, content: string, options?: { mode?: "replace"|"append"=replace }',
|
|
23427
|
+
returns: "Promise<string>",
|
|
23428
|
+
notes: "Writes to {workDir}/files/artifacts; updates tasks-status.json"
|
|
23429
|
+
},
|
|
23430
|
+
{
|
|
23431
|
+
name: "writeLog",
|
|
23432
|
+
description: "Write a log file",
|
|
23433
|
+
params: 'name: string, content: string, options?: { mode?: "append"|"replace"=append }',
|
|
23434
|
+
returns: "Promise<string>",
|
|
23435
|
+
notes: "Writes to {workDir}/files/logs; default append; updates tasks-status.json"
|
|
23436
|
+
},
|
|
23437
|
+
{
|
|
23438
|
+
name: "writeTmp",
|
|
23439
|
+
description: "Write a temporary file",
|
|
23440
|
+
params: 'name: string, content: string, options?: { mode?: "replace"|"append"=replace }',
|
|
23441
|
+
returns: "Promise<string>",
|
|
23442
|
+
notes: "Writes to {workDir}/files/tmp; updates tasks-status.json"
|
|
23443
|
+
},
|
|
23444
|
+
{
|
|
23445
|
+
name: "readArtifact",
|
|
23446
|
+
description: "Read an artifact file",
|
|
23447
|
+
params: "name: string",
|
|
23448
|
+
returns: "Promise<string>",
|
|
23449
|
+
notes: "Reads from {workDir}/files/artifacts"
|
|
23450
|
+
},
|
|
23451
|
+
{
|
|
23452
|
+
name: "readLog",
|
|
23453
|
+
description: "Read a log file",
|
|
23454
|
+
params: "name: string",
|
|
23455
|
+
returns: "Promise<string>",
|
|
23456
|
+
notes: "Reads from {workDir}/files/logs"
|
|
23457
|
+
},
|
|
23458
|
+
{
|
|
23459
|
+
name: "readTmp",
|
|
23460
|
+
description: "Read a temporary file",
|
|
23461
|
+
params: "name: string",
|
|
23462
|
+
returns: "Promise<string>",
|
|
23463
|
+
notes: "Reads from {workDir}/files/tmp"
|
|
23464
|
+
},
|
|
23465
|
+
{
|
|
23466
|
+
name: "getTaskDir",
|
|
23467
|
+
description: "Get the task directory path",
|
|
23468
|
+
params: "",
|
|
23469
|
+
returns: "string",
|
|
23470
|
+
notes: "Returns {workDir}/tasks/{taskName}"
|
|
23471
|
+
},
|
|
23472
|
+
{
|
|
23473
|
+
name: "getCurrentStage",
|
|
23474
|
+
description: "Get the current stage name",
|
|
23475
|
+
params: "",
|
|
23476
|
+
returns: "string",
|
|
23477
|
+
notes: "Calls injected getStage()"
|
|
23478
|
+
}
|
|
23479
|
+
];
|
|
23480
|
+
const sampleSeed = {
|
|
23481
|
+
name: "some-name",
|
|
23482
|
+
pipeline: "content-generation",
|
|
23483
|
+
data: {
|
|
23484
|
+
type: "some-type",
|
|
23485
|
+
contentType: "blog-post",
|
|
23486
|
+
targetAudience: "software-developers",
|
|
23487
|
+
tone: "professional-yet-accessible",
|
|
23488
|
+
length: "1500-2000 words",
|
|
23489
|
+
outputFormat: "blog-post"
|
|
23490
|
+
}
|
|
23491
|
+
};
|
|
23492
|
+
function CodePage() {
|
|
23493
|
+
const [llmFunctions, setLlmFunctions] = reactExports.useState(null);
|
|
23494
|
+
reactExports.useEffect(() => {
|
|
23495
|
+
fetch("/api/llm/functions").then((res) => res.json()).then(setLlmFunctions).catch(console.error);
|
|
23496
|
+
}, []);
|
|
23497
|
+
const breadcrumbs = [{ label: "Home", href: "/" }, { label: "Code" }];
|
|
23498
|
+
const handleCopySeed = () => {
|
|
23499
|
+
navigator.clipboard.writeText(JSON.stringify(sampleSeed, null, 2));
|
|
23500
|
+
};
|
|
23501
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Layout, { children: [
|
|
23502
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(PageSubheader, { breadcrumbs }),
|
|
23503
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { children: [
|
|
23504
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { mb: "8", children: [
|
|
23505
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "6", mb: "4", children: "Seed File Example" }),
|
|
23506
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "p", mb: "3", size: "2", children: "A seed file is a JSON object used to start a new pipeline job. It defines the job name, the pipeline to run, and any contextual data the pipeline requires to begin." }),
|
|
23507
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "p", mb: "3", size: "2", weight: "bold", children: "Required fields:" }),
|
|
23508
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "list-disc list-inside mb-4 space-y-1", children: [
|
|
23509
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-sm text-gray-700", children: [
|
|
23510
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "span", weight: "bold", children: "name" }),
|
|
23511
|
+
" ",
|
|
23512
|
+
"(string): Human-friendly title; non-empty, printable only, ≤120 chars; must be unique."
|
|
23513
|
+
] }),
|
|
23514
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-sm text-gray-700", children: [
|
|
23515
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "span", weight: "bold", children: "pipeline" }),
|
|
23516
|
+
" ",
|
|
23517
|
+
"(string): Pipeline slug defined in your registry (e.g., content-generation)."
|
|
23518
|
+
] }),
|
|
23519
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-sm text-gray-700", children: [
|
|
23520
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "span", weight: "bold", children: "data" }),
|
|
23521
|
+
" ",
|
|
23522
|
+
"(object): Required but flexible; include any arbitrary keys your pipeline tasks expect."
|
|
23523
|
+
] })
|
|
23524
|
+
] }),
|
|
23525
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { mb: "3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23526
|
+
Button,
|
|
23527
|
+
{
|
|
23528
|
+
size: "1",
|
|
23529
|
+
onClick: handleCopySeed,
|
|
23530
|
+
"data-testid": "copy-seed-example",
|
|
23531
|
+
children: "Copy"
|
|
23532
|
+
}
|
|
23533
|
+
) }),
|
|
23534
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs bg-gray-50 p-3 rounded overflow-auto max-h-60 border border-gray-200", children: JSON.stringify(sampleSeed, null, 2) })
|
|
23535
|
+
] }),
|
|
23536
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "6", mb: "4", children: "Pipeline Task IO API" }),
|
|
23537
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { overflowX: "auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(m$1, { children: [
|
|
23538
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(d, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(P$1, { children: [
|
|
23539
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Function" }),
|
|
23540
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Parameters" }),
|
|
23541
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Returns" }),
|
|
23542
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Notes" })
|
|
23543
|
+
] }) }),
|
|
23544
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(b$1, { children: ioFunctions.map((fn) => /* @__PURE__ */ jsxRuntimeExports.jsxs(P$1, { children: [
|
|
23545
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$2, { size: "3", children: [
|
|
23546
|
+
"io.",
|
|
23547
|
+
fn.name
|
|
23548
|
+
] }) }),
|
|
23549
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: fn.params || "—" }) }),
|
|
23550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: fn.returns }) }),
|
|
23551
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(T, { children: [
|
|
23552
|
+
fn.description,
|
|
23553
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
23554
|
+
fn.notes
|
|
23555
|
+
] })
|
|
23556
|
+
] }, fn.name)) })
|
|
23557
|
+
] }) }),
|
|
23558
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "6", mt: "8", mb: "4", children: "Pipeline Task LLM API" }),
|
|
23559
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { mb: "4", children: [
|
|
23560
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", children: "Arguments" }),
|
|
23561
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", mb: "4", children: `{
|
|
23562
|
+
messages: Array<{role: "system"|"user"|"assistant", content: string }>,
|
|
23563
|
+
temperature?: number,
|
|
23564
|
+
maxTokens?: number,
|
|
23565
|
+
responseFormat?: "json" | { type: "json_object" | { type: "json_schema", name: string, json_schema: object } },
|
|
23566
|
+
stop?: string | string[],
|
|
23567
|
+
topP?: number,
|
|
23568
|
+
frequencyPenalty?: number,
|
|
23569
|
+
presencePenalty?: number,
|
|
23570
|
+
seed?: number,
|
|
23571
|
+
provider?: string,
|
|
23572
|
+
model?: string,
|
|
23573
|
+
metadata?: object,
|
|
23574
|
+
maxRetries?: number
|
|
23575
|
+
}` }),
|
|
23576
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", children: "Returns" }),
|
|
23577
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: `Promise<{ content: any, usage?: object, raw?: any }>` })
|
|
23578
|
+
] }),
|
|
23579
|
+
llmFunctions && /* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { overflowX: "auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(m$1, { children: [
|
|
23580
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(d, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(P$1, { children: [
|
|
23581
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Function" }),
|
|
23582
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Model" })
|
|
23583
|
+
] }) }),
|
|
23584
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(b$1, { children: Object.entries(llmFunctions).map(
|
|
23585
|
+
([provider, functions]) => functions.map((fn) => /* @__PURE__ */ jsxRuntimeExports.jsxs(P$1, { children: [
|
|
23586
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: fn.fullPath }) }),
|
|
23587
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(T, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: fn.model }) })
|
|
23588
|
+
] }, fn.fullPath))
|
|
23589
|
+
) })
|
|
23590
|
+
] }) }),
|
|
23591
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "6", mt: "8", mb: "4", children: "Validation API" }),
|
|
23592
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "p", mb: "3", size: "2", children: "Schema validation helper available to task stages via validators." }),
|
|
23593
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { mb: "4", children: [
|
|
23594
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", children: "Function Signature" }),
|
|
23595
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: `validateWithSchema(schema: object, data: object | string): { valid: true } | { valid: false, errors: AjvError[] }` }),
|
|
23596
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", mt: "4", children: "Behavior" }),
|
|
23597
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "list-disc list-inside mb-4 space-y-1", children: [
|
|
23598
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "text-sm text-gray-700", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { as: "span", children: [
|
|
23599
|
+
"Parses string data to JSON; on parse failure returns",
|
|
23600
|
+
" ",
|
|
23601
|
+
`{ valid:false, errors:[{ keyword:"type", message:"must be a valid JSON object (string parsing failed)"} ]`
|
|
23602
|
+
] }) }),
|
|
23603
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "text-sm text-gray-700", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$b, { as: "span", children: [
|
|
23604
|
+
"Uses Ajv(",
|
|
23605
|
+
`{ allErrors: true, strict: false }`,
|
|
23606
|
+
"); compiles provided schema"
|
|
23607
|
+
] }) }),
|
|
23608
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "text-sm text-gray-700", children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { as: "span", children: "Returns AJV errors array when invalid" }) })
|
|
23609
|
+
] }),
|
|
23610
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", children: "Source" }),
|
|
23611
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: "src/api/validators/json.js" }),
|
|
23612
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", mt: "4", children: "Usage Example" }),
|
|
23613
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: `export const validateStructure = async ({
|
|
23614
|
+
io,
|
|
23615
|
+
flags,
|
|
23616
|
+
validators: { validateWithSchema },
|
|
23617
|
+
}) => {
|
|
23618
|
+
const content = await io.readArtifact("research-output.json");
|
|
23619
|
+
const result = validateWithSchema(researchJsonSchema, content);
|
|
23620
|
+
|
|
23621
|
+
if (!result.valid) {
|
|
23622
|
+
console.warn("[Research:validateStructure] Validation failed", result.errors);
|
|
23623
|
+
return { output: {}, flags: { ...flags, validationFailed: true } };
|
|
23624
|
+
}
|
|
23625
|
+
return { output: {}, flags };
|
|
23626
|
+
};` })
|
|
23627
|
+
] }),
|
|
23628
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "6", mt: "8", mb: "4", children: "Environment Configuration" }),
|
|
23629
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(p$7, { mb: "4", children: [
|
|
23630
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(r$8, { size: "4", mb: "2", children: "Example .env Configuration" }),
|
|
23631
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$7, { overflowX: "auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(m$1, { children: [
|
|
23632
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(d, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(P$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(f$1, { children: "Environment Variable" }) }) }),
|
|
23633
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(b$1, { children: [
|
|
23634
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(P$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: "OPENAI_API_KEY=" }) }) }),
|
|
23635
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(P$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: "DEEPSEEK_API_KEY=" }) }) }),
|
|
23636
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(P$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: "GEMINI_API_KEY=" }) }) }),
|
|
23637
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(P$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: "ANTHROPIC_API_KEY=" }) }) }),
|
|
23638
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(P$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(R, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(p$2, { size: "3", children: "ZHIPU_API_KEY=" }) }) })
|
|
23639
|
+
] })
|
|
23640
|
+
] }) })
|
|
23641
|
+
] })
|
|
23642
|
+
] })
|
|
23643
|
+
] });
|
|
23644
|
+
}
|
|
23645
|
+
const ToastContext = reactExports.createContext();
|
|
23646
|
+
function ToastProvider({ children }) {
|
|
23647
|
+
const [toasts, setToasts] = reactExports.useState([]);
|
|
23648
|
+
const addToast = reactExports.useCallback((message, options = {}) => {
|
|
23649
|
+
const toast = {
|
|
23650
|
+
id: Date.now() + Math.random(),
|
|
23651
|
+
message,
|
|
23652
|
+
type: options.type || "info",
|
|
23653
|
+
duration: options.duration || 5e3
|
|
23654
|
+
};
|
|
23655
|
+
setToasts((prev) => [...prev, toast]);
|
|
23656
|
+
if (toast.duration > 0) {
|
|
23657
|
+
setTimeout(() => {
|
|
23658
|
+
removeToast(toast.id);
|
|
23659
|
+
}, toast.duration);
|
|
23660
|
+
}
|
|
23661
|
+
return toast.id;
|
|
23662
|
+
}, []);
|
|
23663
|
+
const removeToast = reactExports.useCallback((id) => {
|
|
23664
|
+
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
23665
|
+
}, []);
|
|
23666
|
+
const value = {
|
|
23667
|
+
addToast,
|
|
23668
|
+
removeToast,
|
|
23669
|
+
success: (message, options) => addToast(message, { ...options, type: "success" }),
|
|
23670
|
+
error: (message, options) => addToast(message, { ...options, type: "error" }),
|
|
23671
|
+
warning: (message, options) => addToast(message, { ...options, type: "warning" }),
|
|
23672
|
+
info: (message, options) => addToast(message, { ...options, type: "info" })
|
|
23673
|
+
};
|
|
23674
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(ToastContext.Provider, { value, children: [
|
|
23675
|
+
children,
|
|
23676
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ToastContainer, { toasts, onRemove: removeToast })
|
|
23677
|
+
] });
|
|
23678
|
+
}
|
|
23679
|
+
function ToastContainer({ toasts, onRemove }) {
|
|
23680
|
+
if (toasts.length === 0) return null;
|
|
23681
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed top-4 right-4 z-50 space-y-2", children: toasts.map((toast) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToastItem, { toast, onRemove }, toast.id)) });
|
|
23682
|
+
}
|
|
23683
|
+
function ToastItem({ toast, onRemove }) {
|
|
23684
|
+
const getToastStyles = (type) => {
|
|
23685
|
+
switch (type) {
|
|
23686
|
+
case "success":
|
|
23687
|
+
return "bg-green-50 border-green-200 text-green-800";
|
|
23688
|
+
case "error":
|
|
23689
|
+
return "bg-red-50 border-red-200 text-red-800";
|
|
23690
|
+
case "warning":
|
|
23691
|
+
return "bg-yellow-50 border-yellow-200 text-yellow-800";
|
|
23692
|
+
default:
|
|
23693
|
+
return "bg-blue-50 border-blue-200 text-blue-800";
|
|
23694
|
+
}
|
|
23695
|
+
};
|
|
23696
|
+
const getIcon = (type) => {
|
|
23697
|
+
switch (type) {
|
|
23698
|
+
case "success":
|
|
23699
|
+
return "✓";
|
|
23700
|
+
case "error":
|
|
23701
|
+
return "✕";
|
|
23702
|
+
case "warning":
|
|
23703
|
+
return "⚠";
|
|
23704
|
+
default:
|
|
23705
|
+
return "ℹ";
|
|
23706
|
+
}
|
|
23707
|
+
};
|
|
22677
23708
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22678
|
-
|
|
23709
|
+
p$7,
|
|
22679
23710
|
{
|
|
22680
|
-
|
|
22681
|
-
|
|
22682
|
-
|
|
22683
|
-
|
|
23711
|
+
className: `relative flex items-start p-4 border rounded-lg shadow-lg max-w-sm ${getToastStyles(
|
|
23712
|
+
toast.type
|
|
23713
|
+
)}`,
|
|
23714
|
+
role: "alert",
|
|
23715
|
+
"aria-live": "polite",
|
|
23716
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(p$4, { gap: "3", align: "start", children: [
|
|
23717
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { className: "flex-shrink-0 text-lg font-semibold", children: getIcon(toast.type) }),
|
|
23718
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(p$b, { className: "text-sm font-medium flex-1", children: toast.message }),
|
|
23719
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23720
|
+
"button",
|
|
23721
|
+
{
|
|
23722
|
+
onClick: () => onRemove(toast.id),
|
|
23723
|
+
className: "flex-shrink-0 ml-4 text-sm opacity-60 hover:opacity-100 focus:outline-none focus:opacity-100",
|
|
23724
|
+
"aria-label": "Dismiss notification",
|
|
23725
|
+
children: "✕"
|
|
23726
|
+
}
|
|
23727
|
+
)
|
|
23728
|
+
] })
|
|
22684
23729
|
}
|
|
22685
23730
|
);
|
|
22686
23731
|
}
|
|
22687
|
-
ReactDOM.createRoot(document.getElementById("root")).render(
|
|
22688
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(React.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
23732
|
+
ReactDOM$1.createRoot(document.getElementById("root")).render(
|
|
23733
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(React.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ToastProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
22689
23734
|
R$1,
|
|
22690
23735
|
{
|
|
22691
23736
|
accentColor: "iris",
|
|
@@ -22695,8 +23740,9 @@ ReactDOM.createRoot(document.getElementById("root")).render(
|
|
|
22695
23740
|
radius: "full",
|
|
22696
23741
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(BrowserRouter, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Routes, { children: [
|
|
22697
23742
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "/", element: /* @__PURE__ */ jsxRuntimeExports.jsx(PromptPipelineDashboard, {}) }),
|
|
22698
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "/pipeline/:jobId", element: /* @__PURE__ */ jsxRuntimeExports.jsx(PipelineDetail, {}) })
|
|
23743
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "/pipeline/:jobId", element: /* @__PURE__ */ jsxRuntimeExports.jsx(PipelineDetail, {}) }),
|
|
23744
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "/code", element: /* @__PURE__ */ jsxRuntimeExports.jsx(CodePage, {}) })
|
|
22699
23745
|
] }) })
|
|
22700
23746
|
}
|
|
22701
|
-
) })
|
|
23747
|
+
) }) })
|
|
22702
23748
|
);
|