@arbidocs/blocks 0.4.135 → 0.4.137
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/dist/agents/index.cjs +422 -367
- package/dist/agents/index.js +8 -9
- package/dist/agents/skills/index.d.ts +2 -0
- package/dist/agents/skills/skillFiles.d.ts +65 -0
- package/dist/agents/skills/skillImport.d.ts +36 -0
- package/dist/agents/workflows/WorkflowDocumentsField.d.ts +42 -5
- package/dist/agents/workflows/index.d.ts +3 -3
- package/dist/agents/workflows/workflow.d.ts +19 -0
- package/dist/agents/workflows/workspaceScope.d.ts +12 -0
- package/dist/chat/index.cjs +138 -138
- package/dist/chat/index.js +3 -3
- package/dist/chunk-2KUCVSFF.js +51 -0
- package/dist/chunk-2KUCVSFF.js.map +1 -0
- package/dist/{chunk-GDBDHOI4.js → chunk-3RJN2VTL.js} +36 -6
- package/dist/chunk-3RJN2VTL.js.map +1 -0
- package/dist/{chunk-6AALMYPS.cjs → chunk-6F7SZCVL.cjs} +23 -2
- package/dist/chunk-6F7SZCVL.cjs.map +1 -0
- package/dist/{chunk-PUCY3UXN.js → chunk-7M4C6CK7.js} +3 -3
- package/dist/{chunk-PUCY3UXN.js.map → chunk-7M4C6CK7.js.map} +1 -1
- package/dist/{chunk-2PNNCEPH.js → chunk-ATJUVHVB.js} +1545 -8
- package/dist/chunk-ATJUVHVB.js.map +1 -0
- package/dist/{chunk-4S5IDT5F.cjs → chunk-BUNZWOPX.cjs} +5 -5
- package/dist/{chunk-4S5IDT5F.cjs.map → chunk-BUNZWOPX.cjs.map} +1 -1
- package/dist/{chunk-KYDRUFWT.cjs → chunk-C3ZRLULA.cjs} +5 -5
- package/dist/{chunk-KYDRUFWT.cjs.map → chunk-C3ZRLULA.cjs.map} +1 -1
- package/dist/{chunk-SARREDFP.cjs → chunk-CHVCTKF4.cjs} +1620 -47
- package/dist/chunk-CHVCTKF4.cjs.map +1 -0
- package/dist/chunk-CQCC7LE7.js +210 -0
- package/dist/chunk-CQCC7LE7.js.map +1 -0
- package/dist/{chunk-4UMXQPNA.js → chunk-E5OYHJMU.js} +3 -3
- package/dist/{chunk-4UMXQPNA.js.map → chunk-E5OYHJMU.js.map} +1 -1
- package/dist/{chunk-PJJY6CYL.cjs → chunk-EHOPZBAX.cjs} +11 -11
- package/dist/{chunk-PJJY6CYL.cjs.map → chunk-EHOPZBAX.cjs.map} +1 -1
- package/dist/{chunk-4QIIDXLF.cjs → chunk-HDYWXEQU.cjs} +8 -8
- package/dist/{chunk-4QIIDXLF.cjs.map → chunk-HDYWXEQU.cjs.map} +1 -1
- package/dist/{chunk-GZPTWHP5.cjs → chunk-HLB4DIYV.cjs} +5 -5
- package/dist/{chunk-GZPTWHP5.cjs.map → chunk-HLB4DIYV.cjs.map} +1 -1
- package/dist/{chunk-TT6XV6WM.cjs → chunk-JY73DJOS.cjs} +78 -1274
- package/dist/chunk-JY73DJOS.cjs.map +1 -0
- package/dist/{chunk-ARDHLU73.cjs → chunk-KDUGTKVI.cjs} +21 -2
- package/dist/chunk-KDUGTKVI.cjs.map +1 -0
- package/dist/{chunk-UMIY4SQS.js → chunk-KMNZ2RVO.js} +17 -1191
- package/dist/chunk-KMNZ2RVO.js.map +1 -0
- package/dist/{chunk-6S5FLMWG.js → chunk-KSHKTOY2.js} +203 -7
- package/dist/chunk-KSHKTOY2.js.map +1 -0
- package/dist/{chunk-4RLCRFZS.js → chunk-L2PAPOZ5.js} +21 -3
- package/dist/chunk-L2PAPOZ5.js.map +1 -0
- package/dist/{chunk-QYTYW74G.js → chunk-L3T7OJRX.js} +4 -4
- package/dist/{chunk-QYTYW74G.js.map → chunk-L3T7OJRX.js.map} +1 -1
- package/dist/{chunk-ENDP7JER.js → chunk-M33QUNFH.js} +3 -3
- package/dist/{chunk-ENDP7JER.js.map → chunk-M33QUNFH.js.map} +1 -1
- package/dist/chunk-RFIBUWLF.cjs +232 -0
- package/dist/chunk-RFIBUWLF.cjs.map +1 -0
- package/dist/{chunk-N26CXGXC.cjs → chunk-RQ2Y7USX.cjs} +201 -3
- package/dist/chunk-RQ2Y7USX.cjs.map +1 -0
- package/dist/chunk-UUHUQHXR.cjs +56 -0
- package/dist/chunk-UUHUQHXR.cjs.map +1 -0
- package/dist/{chunk-SZX44LCT.js → chunk-VMESMX7N.js} +3 -3
- package/dist/{chunk-SZX44LCT.js.map → chunk-VMESMX7N.js.map} +1 -1
- package/dist/{chunk-QDEODGXE.cjs → chunk-WS5EX7DN.cjs} +37 -6
- package/dist/chunk-WS5EX7DN.cjs.map +1 -0
- package/dist/{chunk-2DFDFOM7.js → chunk-YOMPLCP6.js} +22 -3
- package/dist/chunk-YOMPLCP6.js.map +1 -0
- package/dist/connect/docx.cjs +4 -4
- package/dist/connect/docx.js +3 -3
- package/dist/connect/index.cjs +463 -97
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +5 -2
- package/dist/connect/index.js +387 -49
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedSkillUpload.d.ts +26 -2
- package/dist/connection/ConnectedWorkflowBuilder.d.ts +24 -12
- package/dist/connection/ConnectedWorkflowLauncher.d.ts +35 -0
- package/dist/connection/ConnectedWorkflowsTable.d.ts +62 -0
- package/dist/connection/ConnectionProvider.d.ts +17 -0
- package/dist/connection/workspaceData.d.ts +45 -0
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +1 -1
- package/dist/files/index.js +1 -1
- package/dist/home/index.cjs +20 -21
- package/dist/home/index.cjs.map +1 -1
- package/dist/home/index.js +2 -3
- package/dist/home/index.js.map +1 -1
- package/dist/index.cjs +610 -555
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +14 -15
- package/dist/index.js.map +1 -1
- package/dist/settings/index.cjs +11 -11
- package/dist/settings/index.js +2 -2
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/site/index.cjs +5 -5
- package/dist/site/index.js +1 -1
- package/dist/studio/index.cjs +7 -7
- package/dist/studio/index.js +5 -5
- package/dist/workflow-canvas/index.cjs +122 -96
- package/dist/workflow-canvas/index.cjs.map +1 -1
- package/dist/workflow-canvas/index.d.ts +1 -1
- package/dist/workflow-canvas/index.js +73 -48
- package/dist/workflow-canvas/index.js.map +1 -1
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +4 -4
- package/dist/chunk-2DFDFOM7.js.map +0 -1
- package/dist/chunk-2PNNCEPH.js.map +0 -1
- package/dist/chunk-4RLCRFZS.js.map +0 -1
- package/dist/chunk-4XJZ6AAY.js +0 -407
- package/dist/chunk-4XJZ6AAY.js.map +0 -1
- package/dist/chunk-6AALMYPS.cjs.map +0 -1
- package/dist/chunk-6S5FLMWG.js.map +0 -1
- package/dist/chunk-7D737FLE.cjs +0 -43
- package/dist/chunk-7D737FLE.cjs.map +0 -1
- package/dist/chunk-ARDHLU73.cjs.map +0 -1
- package/dist/chunk-GDBDHOI4.js.map +0 -1
- package/dist/chunk-N26CXGXC.cjs.map +0 -1
- package/dist/chunk-QDEODGXE.cjs.map +0 -1
- package/dist/chunk-S5HZBXZA.cjs +0 -430
- package/dist/chunk-S5HZBXZA.cjs.map +0 -1
- package/dist/chunk-SARREDFP.cjs.map +0 -1
- package/dist/chunk-TT6XV6WM.cjs.map +0 -1
- package/dist/chunk-UMIY4SQS.js.map +0 -1
- package/dist/chunk-XD2M6LIG.js +0 -41
- package/dist/chunk-XD2M6LIG.js.map +0 -1
|
@@ -2,14 +2,22 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var chunkDETZZBG2_cjs = require('./chunk-DETZZBG2.cjs');
|
|
5
|
-
var
|
|
6
|
-
var
|
|
5
|
+
var chunkRQ2Y7USX_cjs = require('./chunk-RQ2Y7USX.cjs');
|
|
6
|
+
var chunkZW6FPIFC_cjs = require('./chunk-ZW6FPIFC.cjs');
|
|
7
|
+
var chunkWS5EX7DN_cjs = require('./chunk-WS5EX7DN.cjs');
|
|
8
|
+
var chunkV4ISCZJ7_cjs = require('./chunk-V4ISCZJ7.cjs');
|
|
9
|
+
var chunk2EI7NCUA_cjs = require('./chunk-2EI7NCUA.cjs');
|
|
10
|
+
var chunkC2CWWEHO_cjs = require('./chunk-C2CWWEHO.cjs');
|
|
11
|
+
var chunk7RGLTF76_cjs = require('./chunk-7RGLTF76.cjs');
|
|
12
|
+
var chunk6F7SZCVL_cjs = require('./chunk-6F7SZCVL.cjs');
|
|
7
13
|
var chunk32HW2Q33_cjs = require('./chunk-32HW2Q33.cjs');
|
|
8
14
|
var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
|
|
15
|
+
var chunkKDG6FER6_cjs = require('./chunk-KDG6FER6.cjs');
|
|
9
16
|
var react = require('react');
|
|
10
17
|
var lucideReact = require('lucide-react');
|
|
11
18
|
var ui = require('@arbidocs/react/ui');
|
|
12
19
|
var jsxRuntime = require('react/jsx-runtime');
|
|
20
|
+
var fflate = require('fflate');
|
|
13
21
|
|
|
14
22
|
var DEFAULT_SCHEMA_FORM_LABELS = {
|
|
15
23
|
optional: "(optional)",
|
|
@@ -147,11 +155,11 @@ function FieldControl({
|
|
|
147
155
|
] });
|
|
148
156
|
}
|
|
149
157
|
case "scope": {
|
|
150
|
-
const scope =
|
|
158
|
+
const scope = chunk6F7SZCVL_cjs.isWorkflowScope(value) ? value : { folders: [], labels: [] };
|
|
151
159
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": testId, children: renderScope?.(field, scope, onChange) });
|
|
152
160
|
}
|
|
153
161
|
case "documents": {
|
|
154
|
-
const picked =
|
|
162
|
+
const picked = chunk6F7SZCVL_cjs.isWorkflowScope(value) ? value : { folders: [], labels: [], documents: [] };
|
|
155
163
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": testId, children: renderDocuments?.(field, picked, onChange) });
|
|
156
164
|
}
|
|
157
165
|
case "person":
|
|
@@ -309,7 +317,7 @@ function SchemaForm({
|
|
|
309
317
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("flex flex-col gap-4", className), "data-slot": "schema-form", children: [
|
|
310
318
|
common.map(render),
|
|
311
319
|
advanced.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
312
|
-
|
|
320
|
+
chunkWS5EX7DN_cjs.FoldSection,
|
|
313
321
|
{
|
|
314
322
|
label: l.advanced,
|
|
315
323
|
open: advancedOpen,
|
|
@@ -320,6 +328,610 @@ function SchemaForm({
|
|
|
320
328
|
)
|
|
321
329
|
] });
|
|
322
330
|
}
|
|
331
|
+
function useControllableState(value, defaultValue, onChange) {
|
|
332
|
+
const [inner, setInner] = react.useState(defaultValue);
|
|
333
|
+
const isControlled = value !== void 0;
|
|
334
|
+
const current = isControlled ? value : inner;
|
|
335
|
+
const onChangeRef = react.useRef(onChange);
|
|
336
|
+
onChangeRef.current = onChange;
|
|
337
|
+
const set = react.useCallback(
|
|
338
|
+
(next) => {
|
|
339
|
+
if (!isControlled) setInner(next);
|
|
340
|
+
onChangeRef.current?.(next);
|
|
341
|
+
},
|
|
342
|
+
[isControlled]
|
|
343
|
+
);
|
|
344
|
+
return [current, set];
|
|
345
|
+
}
|
|
346
|
+
var DEFAULT_AGENT_SELECT_LABELS = {
|
|
347
|
+
label: "Run as",
|
|
348
|
+
myAssistant: "My assistant"
|
|
349
|
+
};
|
|
350
|
+
var ME = "__me__";
|
|
351
|
+
function AgentSelect({
|
|
352
|
+
agents,
|
|
353
|
+
value,
|
|
354
|
+
defaultValue = "",
|
|
355
|
+
onValueChange,
|
|
356
|
+
hideLabel,
|
|
357
|
+
disabled,
|
|
358
|
+
className,
|
|
359
|
+
labels,
|
|
360
|
+
testId,
|
|
361
|
+
optionTestId
|
|
362
|
+
}) {
|
|
363
|
+
const l = { ...DEFAULT_AGENT_SELECT_LABELS, ...labels };
|
|
364
|
+
const triggerId = react.useId();
|
|
365
|
+
const [current, setCurrent] = useControllableState(value, defaultValue, onValueChange);
|
|
366
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("flex flex-col gap-1.5", className), "data-slot": "agent-select", children: [
|
|
367
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: triggerId, className: hideLabel ? "sr-only" : void 0, children: l.label }),
|
|
368
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
369
|
+
ui.Select,
|
|
370
|
+
{
|
|
371
|
+
value: current === "" ? ME : current,
|
|
372
|
+
onValueChange: (v) => setCurrent(v === ME ? "" : v),
|
|
373
|
+
disabled,
|
|
374
|
+
children: [
|
|
375
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
376
|
+
ui.SelectTrigger,
|
|
377
|
+
{
|
|
378
|
+
id: triggerId,
|
|
379
|
+
"data-testid": chunkMHVNT4J3_cjs.testIdOr(testId, { testId: "agent-select" }),
|
|
380
|
+
className: "pointer-coarse:min-h-11",
|
|
381
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.SelectValue, {})
|
|
382
|
+
}
|
|
383
|
+
),
|
|
384
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.SelectContent, { children: [
|
|
385
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
386
|
+
ui.SelectItem,
|
|
387
|
+
{
|
|
388
|
+
value: ME,
|
|
389
|
+
"data-testid": chunkMHVNT4J3_cjs.prefixedTestId(optionTestId, "me", {
|
|
390
|
+
testId: "agent-select-option-me"
|
|
391
|
+
}),
|
|
392
|
+
children: l.myAssistant
|
|
393
|
+
}
|
|
394
|
+
),
|
|
395
|
+
agents.map((agent) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
396
|
+
ui.SelectItem,
|
|
397
|
+
{
|
|
398
|
+
value: agent.id,
|
|
399
|
+
"data-testid": chunkMHVNT4J3_cjs.prefixedTestId(optionTestId, agent.id, {
|
|
400
|
+
testId: `agent-select-option-${agent.id}`
|
|
401
|
+
}),
|
|
402
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
|
|
403
|
+
agent.avatar,
|
|
404
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: agent.label }),
|
|
405
|
+
agent.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: agent.description })
|
|
406
|
+
] })
|
|
407
|
+
},
|
|
408
|
+
agent.id
|
|
409
|
+
))
|
|
410
|
+
] })
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
)
|
|
414
|
+
] });
|
|
415
|
+
}
|
|
416
|
+
var DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS = {
|
|
417
|
+
start: "Start",
|
|
418
|
+
starting: "Starting\u2026",
|
|
419
|
+
addFilesReason: "This reads your files, and there is nothing to read yet.",
|
|
420
|
+
agentLabel: "Run as"
|
|
421
|
+
};
|
|
422
|
+
function WorkflowConfigDialog({
|
|
423
|
+
workflow,
|
|
424
|
+
open,
|
|
425
|
+
onOpenChange,
|
|
426
|
+
onLaunch,
|
|
427
|
+
initialInputs,
|
|
428
|
+
inputs: inputsProp,
|
|
429
|
+
onInputsChange,
|
|
430
|
+
scopeSource,
|
|
431
|
+
renderScope,
|
|
432
|
+
renderDocuments,
|
|
433
|
+
renderIcon,
|
|
434
|
+
addFilesAction,
|
|
435
|
+
agents,
|
|
436
|
+
agentId: agentIdProp,
|
|
437
|
+
onAgentChange,
|
|
438
|
+
isLaunching,
|
|
439
|
+
submitLabel,
|
|
440
|
+
fieldPlaceholder,
|
|
441
|
+
renderNotice,
|
|
442
|
+
labels,
|
|
443
|
+
formLabels,
|
|
444
|
+
agentLabels,
|
|
445
|
+
testId,
|
|
446
|
+
startTestId,
|
|
447
|
+
className
|
|
448
|
+
}) {
|
|
449
|
+
const l = { ...DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, ...labels };
|
|
450
|
+
const initialKey = JSON.stringify(initialInputs ?? {});
|
|
451
|
+
const seedKey = JSON.stringify({ ...chunk6F7SZCVL_cjs.defaultInputs(workflow), ...JSON.parse(initialKey) });
|
|
452
|
+
const seed = react.useMemo(() => JSON.parse(seedKey), [seedKey]);
|
|
453
|
+
const [inputs, setInputs] = useControllableState(inputsProp, seed, onInputsChange);
|
|
454
|
+
const [agentId, setAgentId] = useControllableState(
|
|
455
|
+
agentIdProp,
|
|
456
|
+
workflow.defaultAgentId ?? "",
|
|
457
|
+
onAgentChange
|
|
458
|
+
);
|
|
459
|
+
react.useEffect(() => {
|
|
460
|
+
if (open && inputsProp === void 0) setInputs(seed);
|
|
461
|
+
}, [open, seed]);
|
|
462
|
+
const setField = (name, value) => setInputs({ ...inputs, [name]: value });
|
|
463
|
+
const errors = chunk6F7SZCVL_cjs.validateInputs(workflow, inputs);
|
|
464
|
+
const valid = Object.keys(errors).length === 0;
|
|
465
|
+
const visibleErrors = Object.fromEntries(
|
|
466
|
+
Object.entries(errors).filter(([, e]) => e !== "required")
|
|
467
|
+
);
|
|
468
|
+
const scopeField = workflow.inputs.find((f) => f.type === "scope");
|
|
469
|
+
const rawScope = scopeField ? inputs[scopeField.name] : void 0;
|
|
470
|
+
const scopeValue = rawScope && typeof rawScope === "object" ? rawScope : { folders: [], labels: [] };
|
|
471
|
+
const matchedCount = scopeSource && scopeField ? scopeSource.countMatching(scopeValue) : null;
|
|
472
|
+
const noFiles = Boolean(workflow.requiresFiles && scopeSource && scopeSource.totalCount === 0);
|
|
473
|
+
const blockedByScope = matchedCount !== null && matchedCount === 0 && Boolean(workflow.requiresFiles);
|
|
474
|
+
const showAgent = workflow.run.kind === "prompt" && workflow.options?.agent !== false && agents !== void 0 && agents.length > 0;
|
|
475
|
+
const launch = (values) => {
|
|
476
|
+
Promise.resolve(onLaunch(chunk6F7SZCVL_cjs.buildLaunch(workflow, values, agentId))).catch(() => {
|
|
477
|
+
});
|
|
478
|
+
};
|
|
479
|
+
const submit = () => {
|
|
480
|
+
if (!valid || noFiles || blockedByScope || isLaunching) return;
|
|
481
|
+
launch(inputs);
|
|
482
|
+
};
|
|
483
|
+
const fields = react.useMemo(
|
|
484
|
+
() => workflow.inputs.map((f) => {
|
|
485
|
+
const placeholder = fieldPlaceholder?.(f, inputs, workflow);
|
|
486
|
+
return placeholder === void 0 ? f : { ...f, placeholder };
|
|
487
|
+
}),
|
|
488
|
+
[workflow, fieldPlaceholder, inputs]
|
|
489
|
+
);
|
|
490
|
+
const id = chunkMHVNT4J3_cjs.testIdOr(testId, { testId: "workflow-dialog" });
|
|
491
|
+
const formRef = react.useRef(null);
|
|
492
|
+
const firstField = workflow.inputs.find((f) => !f.advanced);
|
|
493
|
+
const focusPromptFirst = firstField?.type === "text" || firstField?.type === "longtext";
|
|
494
|
+
const defaultScopeRender = scopeSource ? (_field, value, onChange) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
495
|
+
chunkWS5EX7DN_cjs.ScopePicker,
|
|
496
|
+
{
|
|
497
|
+
folders: scopeSource.folders,
|
|
498
|
+
unfiledCount: scopeSource.unfiledCount,
|
|
499
|
+
labels: scopeSource.labels,
|
|
500
|
+
totalCount: scopeSource.totalCount,
|
|
501
|
+
matchedCount: scopeSource.countMatching(value),
|
|
502
|
+
scope: value,
|
|
503
|
+
onScopeChange: onChange
|
|
504
|
+
}
|
|
505
|
+
) : void 0;
|
|
506
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
507
|
+
ui.DialogContent,
|
|
508
|
+
{
|
|
509
|
+
presentation: "sheet",
|
|
510
|
+
className: `max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-xl ${className ?? ""}`,
|
|
511
|
+
"data-testid": id,
|
|
512
|
+
"data-workflow": workflow.id,
|
|
513
|
+
onOpenAutoFocus: (event) => {
|
|
514
|
+
if (!focusPromptFirst || !firstField) return;
|
|
515
|
+
const control = formRef.current?.querySelector(
|
|
516
|
+
`[data-testid="${id}-field-${firstField.name}"]`
|
|
517
|
+
);
|
|
518
|
+
if (!control) return;
|
|
519
|
+
event.preventDefault();
|
|
520
|
+
control.focus();
|
|
521
|
+
if (control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement) {
|
|
522
|
+
const end = control.value.length;
|
|
523
|
+
control.setSelectionRange(end, end);
|
|
524
|
+
}
|
|
525
|
+
},
|
|
526
|
+
children: [
|
|
527
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
528
|
+
chunkWS5EX7DN_cjs.QuickActionDialogHeader,
|
|
529
|
+
{
|
|
530
|
+
icon: workflow.icon && renderIcon ? renderIcon(workflow.icon) : null,
|
|
531
|
+
title: workflow.title,
|
|
532
|
+
description: workflow.details ?? workflow.description,
|
|
533
|
+
descriptionTestId: `${id}-description`
|
|
534
|
+
}
|
|
535
|
+
),
|
|
536
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
537
|
+
"form",
|
|
538
|
+
{
|
|
539
|
+
ref: formRef,
|
|
540
|
+
className: "mt-2 flex flex-col gap-4",
|
|
541
|
+
onSubmit: (event) => {
|
|
542
|
+
event.preventDefault();
|
|
543
|
+
submit();
|
|
544
|
+
},
|
|
545
|
+
children: noFiles ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
546
|
+
chunkWS5EX7DN_cjs.AddFilesFirst,
|
|
547
|
+
{
|
|
548
|
+
reason: l.addFilesReason,
|
|
549
|
+
action: addFilesAction,
|
|
550
|
+
testId: `${id}-empty-state`
|
|
551
|
+
}
|
|
552
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
553
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
554
|
+
SchemaForm,
|
|
555
|
+
{
|
|
556
|
+
fields,
|
|
557
|
+
values: inputs,
|
|
558
|
+
onChange: setField,
|
|
559
|
+
errors: visibleErrors,
|
|
560
|
+
renderScope: renderScope ?? defaultScopeRender,
|
|
561
|
+
renderDocuments,
|
|
562
|
+
renderIcon,
|
|
563
|
+
labels: formLabels,
|
|
564
|
+
onEnterSubmit: submit,
|
|
565
|
+
testIdPrefix: `${id}-field`
|
|
566
|
+
}
|
|
567
|
+
),
|
|
568
|
+
renderNotice?.({ workflow, inputs }),
|
|
569
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
570
|
+
"div",
|
|
571
|
+
{
|
|
572
|
+
className: "flex flex-col gap-3 border-t border-border pt-3 sm:flex-row sm:items-end sm:justify-between",
|
|
573
|
+
"data-slot": "workflow-footer",
|
|
574
|
+
children: [
|
|
575
|
+
showAgent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
576
|
+
AgentSelect,
|
|
577
|
+
{
|
|
578
|
+
agents: agents ?? [],
|
|
579
|
+
value: agentId,
|
|
580
|
+
onValueChange: setAgentId,
|
|
581
|
+
labels: { label: l.agentLabel, ...agentLabels },
|
|
582
|
+
testId: `${id}-agent`,
|
|
583
|
+
className: "sm:w-56"
|
|
584
|
+
}
|
|
585
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
586
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
587
|
+
ui.Button,
|
|
588
|
+
{
|
|
589
|
+
type: "submit",
|
|
590
|
+
className: "gap-1.5 px-5 pointer-coarse:min-h-11",
|
|
591
|
+
disabled: !valid || blockedByScope || isLaunching,
|
|
592
|
+
"data-testid": chunkMHVNT4J3_cjs.testIdOr(startTestId, { testId: "workflow-start-button" }),
|
|
593
|
+
children: [
|
|
594
|
+
isLaunching ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "size-4" }),
|
|
595
|
+
isLaunching ? l.starting : submitLabel?.({ workflow, inputs, matchedCount }) ?? workflow.startLabel ?? l.start
|
|
596
|
+
]
|
|
597
|
+
}
|
|
598
|
+
)
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
)
|
|
602
|
+
] })
|
|
603
|
+
}
|
|
604
|
+
)
|
|
605
|
+
]
|
|
606
|
+
}
|
|
607
|
+
) });
|
|
608
|
+
}
|
|
609
|
+
function WorkflowLauncher({
|
|
610
|
+
workflows,
|
|
611
|
+
tileWorkflows,
|
|
612
|
+
onLaunch,
|
|
613
|
+
showTiles = true,
|
|
614
|
+
caption,
|
|
615
|
+
captionTestId,
|
|
616
|
+
tileTestId,
|
|
617
|
+
disabledReason,
|
|
618
|
+
activeId: activeIdProp,
|
|
619
|
+
onActiveIdChange,
|
|
620
|
+
initialInputsFor,
|
|
621
|
+
testId,
|
|
622
|
+
extraTiles = [],
|
|
623
|
+
className,
|
|
624
|
+
children,
|
|
625
|
+
renderIcon,
|
|
626
|
+
...dialog
|
|
627
|
+
}) {
|
|
628
|
+
const [activeId, setActiveId] = useControllableState(
|
|
629
|
+
activeIdProp,
|
|
630
|
+
null,
|
|
631
|
+
onActiveIdChange
|
|
632
|
+
);
|
|
633
|
+
const [isLaunching, setIsLaunching] = react.useState(false);
|
|
634
|
+
const active = workflows.find((w) => w.id === activeId) ?? null;
|
|
635
|
+
const run = async (launch) => {
|
|
636
|
+
setIsLaunching(true);
|
|
637
|
+
try {
|
|
638
|
+
await onLaunch(launch);
|
|
639
|
+
setActiveId(null);
|
|
640
|
+
} finally {
|
|
641
|
+
setIsLaunching(false);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
const select = (workflow) => {
|
|
645
|
+
if (workflow.run.kind === "operation" && workflow.inputs.length === 0) {
|
|
646
|
+
const inputs = chunk6F7SZCVL_cjs.defaultInputs(workflow);
|
|
647
|
+
if (Object.keys(chunk6F7SZCVL_cjs.validateInputs(workflow, inputs)).length === 0) {
|
|
648
|
+
Promise.resolve(onLaunch(chunk6F7SZCVL_cjs.buildLaunch(workflow, inputs, void 0))).catch(() => {
|
|
649
|
+
});
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
setActiveId(workflow.id);
|
|
654
|
+
};
|
|
655
|
+
const tiles = (tileWorkflows ?? workflows).map((workflow) => {
|
|
656
|
+
const reason = disabledReason?.(workflow);
|
|
657
|
+
return {
|
|
658
|
+
id: workflow.id,
|
|
659
|
+
iconNode: workflow.icon && renderIcon ? renderIcon(workflow.icon) : void 0,
|
|
660
|
+
title: workflow.title,
|
|
661
|
+
description: workflow.description,
|
|
662
|
+
onSelect: () => select(workflow),
|
|
663
|
+
disabled: reason !== void 0,
|
|
664
|
+
disabledReason: reason,
|
|
665
|
+
testId: tileTestId?.(workflow) ?? `workflow-tile-${workflow.id}`
|
|
666
|
+
};
|
|
667
|
+
});
|
|
668
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-slot": "workflow-launcher", children: [
|
|
669
|
+
showTiles && /* @__PURE__ */ jsxRuntime.jsx(
|
|
670
|
+
chunkWS5EX7DN_cjs.StartTiles,
|
|
671
|
+
{
|
|
672
|
+
items: [...tiles, ...extraTiles],
|
|
673
|
+
caption,
|
|
674
|
+
captionTestId,
|
|
675
|
+
testId
|
|
676
|
+
}
|
|
677
|
+
),
|
|
678
|
+
children,
|
|
679
|
+
active && /* @__PURE__ */ jsxRuntime.jsx(
|
|
680
|
+
WorkflowConfigDialog,
|
|
681
|
+
{
|
|
682
|
+
...dialog,
|
|
683
|
+
renderIcon,
|
|
684
|
+
workflow: active,
|
|
685
|
+
open: true,
|
|
686
|
+
onOpenChange: (open) => !open && setActiveId(null),
|
|
687
|
+
onLaunch: run,
|
|
688
|
+
isLaunching,
|
|
689
|
+
initialInputs: initialInputsFor?.(active)
|
|
690
|
+
}
|
|
691
|
+
)
|
|
692
|
+
] });
|
|
693
|
+
}
|
|
694
|
+
function documentScopeLabels(tags) {
|
|
695
|
+
return tags.filter((tag) => {
|
|
696
|
+
if (tag.kind === "search") return false;
|
|
697
|
+
const onDocs = (tag.doctag_count ?? 0) > 0;
|
|
698
|
+
const onFacts = (tag.facttag_count ?? 0) > 0;
|
|
699
|
+
return onDocs || !onFacts;
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
var canonical = (path) => (path ?? "").split("/").map((part) => part.trim()).filter(Boolean).join("/");
|
|
703
|
+
function matchWorkflowScope(docs, scope) {
|
|
704
|
+
if (scope.documents?.length) {
|
|
705
|
+
const ids = new Set(scope.documents);
|
|
706
|
+
return docs.filter((doc) => ids.has(doc.external_id));
|
|
707
|
+
}
|
|
708
|
+
if (!scope.folders.length && !scope.labels.length) return docs;
|
|
709
|
+
const folders = scope.folders.map(canonical);
|
|
710
|
+
const labels = new Set(scope.labels);
|
|
711
|
+
return docs.filter((doc) => {
|
|
712
|
+
const folder = canonical(doc.folder);
|
|
713
|
+
return folders.some(
|
|
714
|
+
(path) => path === "" ? folder === "" : folder === path || folder.startsWith(`${path}/`)
|
|
715
|
+
) || doc.doctags?.some((tag) => labels.has(tag.tag_ext_id));
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
function buildWorkflowScopeSource(docs, labels = []) {
|
|
719
|
+
const counts = /* @__PURE__ */ new Map();
|
|
720
|
+
for (const doc of docs) {
|
|
721
|
+
const parts = canonical(doc.folder).split("/").filter(Boolean);
|
|
722
|
+
for (let i = 1; i <= parts.length; i++) {
|
|
723
|
+
const path = parts.slice(0, i).join("/");
|
|
724
|
+
counts.set(path, (counts.get(path) ?? 0) + 1);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
folders: [...counts].sort(([a], [b]) => a.localeCompare(b)).map(([path, count]) => ({
|
|
729
|
+
path,
|
|
730
|
+
count,
|
|
731
|
+
label: path.split("/").at(-1),
|
|
732
|
+
depth: path.split("/").length - 1
|
|
733
|
+
})),
|
|
734
|
+
unfiledCount: docs.filter((doc) => !canonical(doc.folder)).length,
|
|
735
|
+
labels: labels.map((label) => ({
|
|
736
|
+
id: label.external_id,
|
|
737
|
+
name: label.name,
|
|
738
|
+
color: label.color ?? ui.getEntityColor(label.external_id, "medium"),
|
|
739
|
+
count: docs.filter((doc) => doc.doctags?.some((tag) => tag.tag_ext_id === label.external_id)).length
|
|
740
|
+
})),
|
|
741
|
+
totalCount: docs.length,
|
|
742
|
+
countMatching: (scope) => matchWorkflowScope(docs, scope).length,
|
|
743
|
+
resolveDocuments: (scope) => matchWorkflowScope(docs, scope).map((doc) => doc.external_id)
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
var DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS = {
|
|
747
|
+
pickOne: "Pick a file",
|
|
748
|
+
pickMany: "Pick files",
|
|
749
|
+
allDocuments: "All documents",
|
|
750
|
+
addFiles: "Add files",
|
|
751
|
+
adding: "Adding\u2026",
|
|
752
|
+
empty: "No files in this workspace yet. Drop one here, or add it.",
|
|
753
|
+
remove: (name) => `Remove ${name}`,
|
|
754
|
+
pending: (name, status) => `${name}: ${status}. You can still pick it.`,
|
|
755
|
+
status: {
|
|
756
|
+
queued: "Queued",
|
|
757
|
+
uploading: "Uploading",
|
|
758
|
+
encrypting: "Encrypting",
|
|
759
|
+
processing: "Processing",
|
|
760
|
+
parsing: "Processing",
|
|
761
|
+
indexing: "Indexing",
|
|
762
|
+
analysing: "Analysing"
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
var isReady = (status) => !status || ["completed", "done", "ready", "success"].includes(status.toLowerCase());
|
|
766
|
+
var byTitle = (a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase());
|
|
767
|
+
function WorkflowDocumentsField({
|
|
768
|
+
field,
|
|
769
|
+
value,
|
|
770
|
+
onChange,
|
|
771
|
+
documents,
|
|
772
|
+
loaded = true,
|
|
773
|
+
thumbnailOf,
|
|
774
|
+
onAddFiles,
|
|
775
|
+
adding,
|
|
776
|
+
labels
|
|
777
|
+
}) {
|
|
778
|
+
const l = { ...DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS, ...labels };
|
|
779
|
+
const ids = value.documents ?? [];
|
|
780
|
+
const max = field.max ?? 1;
|
|
781
|
+
const multiple = max > 1;
|
|
782
|
+
const [isOver, setIsOver] = react.useState(false);
|
|
783
|
+
const docOf = (id) => documents.find((d) => d.id === id);
|
|
784
|
+
const nameOf = (id) => docOf(id)?.title || id;
|
|
785
|
+
const set = (next) => onChange({ ...value, documents: next });
|
|
786
|
+
const toggle = (id) => set(ids.includes(id) ? ids.filter((d) => d !== id) : [...ids, id].slice(-max));
|
|
787
|
+
const offered = react.useMemo(
|
|
788
|
+
() => field.accept === "image" ? documents.filter((d) => d.isImage) : documents,
|
|
789
|
+
[documents, field.accept]
|
|
790
|
+
);
|
|
791
|
+
const awaitingAdd = react.useRef(false);
|
|
792
|
+
const known = react.useRef(null);
|
|
793
|
+
const latest = react.useRef({ ids, set });
|
|
794
|
+
latest.current = { ids, set };
|
|
795
|
+
react.useEffect(() => {
|
|
796
|
+
if (!loaded) return;
|
|
797
|
+
const current = new Set(documents.map((d) => d.id));
|
|
798
|
+
const before = known.current;
|
|
799
|
+
known.current = current;
|
|
800
|
+
if (!before || !awaitingAdd.current) return;
|
|
801
|
+
const fresh = [...current].filter((id) => !before.has(id));
|
|
802
|
+
if (fresh.length === 0) return;
|
|
803
|
+
awaitingAdd.current = false;
|
|
804
|
+
latest.current.set([...latest.current.ids, ...fresh].slice(-max));
|
|
805
|
+
}, [documents, loaded, max]);
|
|
806
|
+
const addFiles = (files) => {
|
|
807
|
+
if (!onAddFiles) return;
|
|
808
|
+
awaitingAdd.current = true;
|
|
809
|
+
onAddFiles(files?.length ? files : void 0);
|
|
810
|
+
};
|
|
811
|
+
const dropProps = onAddFiles ? {
|
|
812
|
+
onDragOver: (e) => {
|
|
813
|
+
e.preventDefault();
|
|
814
|
+
setIsOver(true);
|
|
815
|
+
},
|
|
816
|
+
onDragLeave: () => setIsOver(false),
|
|
817
|
+
onDrop: (e) => {
|
|
818
|
+
e.preventDefault();
|
|
819
|
+
setIsOver(false);
|
|
820
|
+
const files = Array.from(e.dataTransfer?.files ?? []);
|
|
821
|
+
if (files.length) addFiles(files);
|
|
822
|
+
}
|
|
823
|
+
} : {};
|
|
824
|
+
const dropClass = isOver ? "ring-2 ring-primary" : "";
|
|
825
|
+
const addButton = (className, variant = "outline") => onAddFiles && /* @__PURE__ */ jsxRuntime.jsx(
|
|
826
|
+
ui.Button,
|
|
827
|
+
{
|
|
828
|
+
type: "button",
|
|
829
|
+
size: "sm",
|
|
830
|
+
variant,
|
|
831
|
+
className,
|
|
832
|
+
disabled: adding,
|
|
833
|
+
onClick: () => addFiles(),
|
|
834
|
+
"data-testid": "workflow-add-files",
|
|
835
|
+
children: adding ? l.adding : l.addFiles
|
|
836
|
+
}
|
|
837
|
+
);
|
|
838
|
+
if (loaded && documents.length === 0) {
|
|
839
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
840
|
+
"div",
|
|
841
|
+
{
|
|
842
|
+
className: ui.cn(
|
|
843
|
+
"flex flex-col items-center gap-2 rounded-lg border border-dashed border-border bg-muted/40 px-4 py-6 text-center",
|
|
844
|
+
dropClass
|
|
845
|
+
),
|
|
846
|
+
"data-testid": "workflow-documents-empty",
|
|
847
|
+
...dropProps,
|
|
848
|
+
children: [
|
|
849
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderPlus, { className: "size-5 text-muted-foreground", "aria-hidden": true }),
|
|
850
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: l.empty }),
|
|
851
|
+
addButton(void 0, "default")
|
|
852
|
+
]
|
|
853
|
+
}
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
const pending = ids.flatMap((id) => {
|
|
857
|
+
const status = docOf(id)?.status;
|
|
858
|
+
return isReady(status) ? [] : [{ id, label: l.status[String(status).toLowerCase()] ?? String(status) }];
|
|
859
|
+
});
|
|
860
|
+
const selected = multiple ? void 0 : docOf(ids[0] ?? "");
|
|
861
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
862
|
+
"div",
|
|
863
|
+
{
|
|
864
|
+
className: ui.cn("flex flex-col gap-3 rounded-lg", dropClass),
|
|
865
|
+
"data-testid": `workflow-documents-${field.name}`,
|
|
866
|
+
...dropProps,
|
|
867
|
+
children: [
|
|
868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
869
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
870
|
+
chunkRQ2Y7USX_cjs.DocumentPicker,
|
|
871
|
+
{
|
|
872
|
+
groups: [{ id: "all", heading: l.allDocuments, docs: [...offered].sort(byTitle) }],
|
|
873
|
+
value: multiple ? "" : ids[0] ?? "",
|
|
874
|
+
onValueChange: (id) => multiple ? toggle(id) : set([id]),
|
|
875
|
+
selected,
|
|
876
|
+
selectedIds: multiple ? ids : void 0,
|
|
877
|
+
labels: { placeholder: field.placeholder ?? (multiple ? l.pickMany : l.pickOne) }
|
|
878
|
+
}
|
|
879
|
+
) }),
|
|
880
|
+
addButton("shrink-0 pointer-coarse:h-11")
|
|
881
|
+
] }),
|
|
882
|
+
pending.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
883
|
+
"p",
|
|
884
|
+
{
|
|
885
|
+
className: "text-xs text-muted-foreground",
|
|
886
|
+
"data-testid": `workflow-document-status-${p.id}`,
|
|
887
|
+
children: l.pending(nameOf(p.id), p.label)
|
|
888
|
+
},
|
|
889
|
+
p.id
|
|
890
|
+
)),
|
|
891
|
+
multiple && ids.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
892
|
+
"div",
|
|
893
|
+
{
|
|
894
|
+
className: "grid grid-cols-2 gap-3 sm:grid-cols-3",
|
|
895
|
+
"data-testid": "workflow-documents-gallery",
|
|
896
|
+
children: ids.map((id) => {
|
|
897
|
+
const thumbnail = thumbnailOf?.(id);
|
|
898
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
899
|
+
"figure",
|
|
900
|
+
{
|
|
901
|
+
className: "relative overflow-hidden rounded-lg border border-border bg-muted/40",
|
|
902
|
+
"data-testid": `workflow-document-${id}`,
|
|
903
|
+
children: [
|
|
904
|
+
thumbnail ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
905
|
+
"img",
|
|
906
|
+
{
|
|
907
|
+
src: thumbnail,
|
|
908
|
+
alt: nameOf(id),
|
|
909
|
+
className: "aspect-square w-full object-cover"
|
|
910
|
+
}
|
|
911
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex aspect-square w-full items-center justify-center text-muted-foreground/50", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ImageIcon, { className: "size-8" }) }),
|
|
912
|
+
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "truncate bg-background/90 px-2 py-1 text-xs text-muted-foreground", children: nameOf(id) }),
|
|
913
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
914
|
+
"button",
|
|
915
|
+
{
|
|
916
|
+
type: "button",
|
|
917
|
+
onClick: () => toggle(id),
|
|
918
|
+
"aria-label": l.remove(nameOf(id)),
|
|
919
|
+
className: "absolute right-1 top-1 flex size-6 items-center justify-center rounded-full bg-background/80 text-muted-foreground hover:text-foreground pointer-coarse:size-11",
|
|
920
|
+
"data-testid": `workflow-document-remove-${id}`,
|
|
921
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5" })
|
|
922
|
+
}
|
|
923
|
+
)
|
|
924
|
+
]
|
|
925
|
+
},
|
|
926
|
+
id
|
|
927
|
+
);
|
|
928
|
+
})
|
|
929
|
+
}
|
|
930
|
+
)
|
|
931
|
+
]
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
}
|
|
323
935
|
|
|
324
936
|
// src/agents/workflows/planSteps.ts
|
|
325
937
|
function toPlanAssignee(a) {
|
|
@@ -429,7 +1041,7 @@ function toStepField(f) {
|
|
|
429
1041
|
}
|
|
430
1042
|
var compact = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0 && v !== ""));
|
|
431
1043
|
function placeholders(workflow) {
|
|
432
|
-
return Object.fromEntries(
|
|
1044
|
+
return Object.fromEntries(chunk6F7SZCVL_cjs.runFields(workflow).map((f) => [f.name, `{{${f.name}}}`]));
|
|
433
1045
|
}
|
|
434
1046
|
function agentStep(workflow, step, options) {
|
|
435
1047
|
const target = step.workflow ? options.resolveWorkflow?.(step.workflow) : void 0;
|
|
@@ -438,11 +1050,11 @@ function agentStep(workflow, step, options) {
|
|
|
438
1050
|
([, v]) => v !== void 0 && v !== null && v !== ""
|
|
439
1051
|
);
|
|
440
1052
|
const inputs = { ...placeholders(workflow), ...Object.fromEntries(given) };
|
|
441
|
-
return { skill: null, inputs: null, prompt:
|
|
1053
|
+
return { skill: null, inputs: null, prompt: chunk6F7SZCVL_cjs.composeStepPrompt(workflow, step, inputs, options) };
|
|
442
1054
|
}
|
|
443
1055
|
function toPlanSteps(workflow, options = {}) {
|
|
444
1056
|
const layout = workflow.run.kind === "steps" ? workflow.run.layout : void 0;
|
|
445
|
-
return
|
|
1057
|
+
return chunk6F7SZCVL_cjs.workflowSteps(workflow).map((step) => {
|
|
446
1058
|
const ui = compact({
|
|
447
1059
|
description: step.description,
|
|
448
1060
|
icon: step.icon,
|
|
@@ -469,8 +1081,8 @@ function toPlanSteps(workflow, options = {}) {
|
|
|
469
1081
|
ui,
|
|
470
1082
|
// An unfinished signal (still being typed) is not saved: the server would refuse it.
|
|
471
1083
|
...step.signals?.some((s) => !isIncompleteSignal(s)) ? { signals: step.signals.filter((s) => !isIncompleteSignal(s)).map(toPlanSignal) } : {},
|
|
472
|
-
...step.assignee &&
|
|
473
|
-
...step.remindAfterHours &&
|
|
1084
|
+
...step.assignee && chunk6F7SZCVL_cjs.canAssign(step) ? { assignee: toPlanAssignee(step.assignee) } : {},
|
|
1085
|
+
...step.remindAfterHours && chunk6F7SZCVL_cjs.canAssign(step) ? { remind_after_hours: step.remindAfterHours } : {},
|
|
474
1086
|
// A review's fields are what approving it is checked against (the server's `fields`).
|
|
475
1087
|
...step.kind === "review" && step.fields?.length ? { fields: step.fields.map(toStepField) } : {},
|
|
476
1088
|
...step.kind === "action" ? { action: toPlanAction(step.action) } : {},
|
|
@@ -571,10 +1183,51 @@ function fromStepField(f) {
|
|
|
571
1183
|
...f.max != null ? { max: f.max } : {}
|
|
572
1184
|
};
|
|
573
1185
|
}
|
|
1186
|
+
|
|
1187
|
+
// src/agents/workflows/skillMarkdown.ts
|
|
1188
|
+
var JSON_KEYS = /* @__PURE__ */ new Set(["inputs"]);
|
|
1189
|
+
var oneLine = (text) => text.replace(/\s*\n\s*/g, " ").trim();
|
|
1190
|
+
var skillSlug = (raw) => raw.toLowerCase().replace(/[^a-z0-9-]/g, "");
|
|
1191
|
+
function workflowToSkillMarkdown(workflow) {
|
|
1192
|
+
const { run } = workflow;
|
|
1193
|
+
if (run.kind !== "prompt") throw new Error("Only skills that start a chat can be copied");
|
|
1194
|
+
const lines = [
|
|
1195
|
+
"---",
|
|
1196
|
+
`name: ${skillSlug(workflow.id)}`,
|
|
1197
|
+
`description: ${oneLine(workflow.description)}`
|
|
1198
|
+
];
|
|
1199
|
+
if (workflow.icon) lines.push(`icon: ${workflow.icon}`);
|
|
1200
|
+
if (workflow.landing !== "chat") lines.push(`landing: ${workflow.landing}`);
|
|
1201
|
+
if (workflow.requiresFiles) lines.push("requires_files: true");
|
|
1202
|
+
if (workflow.inputs.length > 0) {
|
|
1203
|
+
lines.push(`inputs: ${JSON.stringify(workflow.inputs.map(chunk6F7SZCVL_cjs.fieldToFrontmatter))}`);
|
|
1204
|
+
}
|
|
1205
|
+
lines.push("---", "", run.promptTemplate.trim(), "");
|
|
1206
|
+
return lines.join("\n");
|
|
1207
|
+
}
|
|
1208
|
+
function workflowFromSkillMarkdown(id, text) {
|
|
1209
|
+
const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(text);
|
|
1210
|
+
const frontmatter = {};
|
|
1211
|
+
const body = match ? match[2] : text;
|
|
1212
|
+
for (const line of (match ? match[1] : "").split("\n")) {
|
|
1213
|
+
const i = line.indexOf(":");
|
|
1214
|
+
if (i < 1) continue;
|
|
1215
|
+
const key = line.slice(0, i).trim();
|
|
1216
|
+
const value = line.slice(i + 1).trim();
|
|
1217
|
+
if (JSON_KEYS.has(key)) {
|
|
1218
|
+
try {
|
|
1219
|
+
frontmatter[key] = JSON.parse(value);
|
|
1220
|
+
} catch {
|
|
1221
|
+
}
|
|
1222
|
+
} else if (value === "true" || value === "false") frontmatter[key] = value === "true";
|
|
1223
|
+
else frontmatter[key] = value;
|
|
1224
|
+
}
|
|
1225
|
+
return chunk6F7SZCVL_cjs.workflowFromFrontmatter(id, frontmatter, body);
|
|
1226
|
+
}
|
|
574
1227
|
var errorMessage = (e) => e instanceof Error ? e.message : typeof e === "string" ? e : "Something went wrong.";
|
|
575
1228
|
function firstOpen(steps, states) {
|
|
576
1229
|
const open = steps.find((s) => !["done", "skipped"].includes(states[s.id]?.status ?? "pending"));
|
|
577
|
-
return open?.id ?? (steps.length &&
|
|
1230
|
+
return open?.id ?? (steps.length && chunk6F7SZCVL_cjs.isRunFinished(steps, states) ? null : steps[0]?.id ?? null);
|
|
578
1231
|
}
|
|
579
1232
|
function useWorkflowView(options) {
|
|
580
1233
|
const { steps, states, inputs, setInput, loaded = true } = options;
|
|
@@ -614,11 +1267,11 @@ function useWorkflowView(options) {
|
|
|
614
1267
|
}),
|
|
615
1268
|
[]
|
|
616
1269
|
);
|
|
617
|
-
const action = busy ? "wait" :
|
|
1270
|
+
const action = busy ? "wait" : chunk6F7SZCVL_cjs.nextAction(steps, states, current, actionOptions(options));
|
|
618
1271
|
const next = react.useCallback(async () => {
|
|
619
1272
|
const { steps: s, states: st, inputs: values } = optionsRef.current;
|
|
620
1273
|
const at = s.find((x) => x.id === current);
|
|
621
|
-
const act2 =
|
|
1274
|
+
const act2 = chunk6F7SZCVL_cjs.nextAction(s, st, current, actionOptions(optionsRef.current));
|
|
622
1275
|
if (!at || act2 === "wait" || busy) return;
|
|
623
1276
|
setActionError(null);
|
|
624
1277
|
if (act2 === "finish") return setCurrent(null);
|
|
@@ -629,7 +1282,7 @@ function useWorkflowView(options) {
|
|
|
629
1282
|
await (act2 === "start" ? optionsRef.current.start?.() : optionsRef.current.retry?.(at.id));
|
|
630
1283
|
return;
|
|
631
1284
|
}
|
|
632
|
-
if (Object.keys(
|
|
1285
|
+
if (Object.keys(chunk6F7SZCVL_cjs.validateStep(at, values)).length > 0) {
|
|
633
1286
|
setShowErrors(true);
|
|
634
1287
|
return;
|
|
635
1288
|
}
|
|
@@ -730,10 +1383,10 @@ function useWorkflowView(options) {
|
|
|
730
1383
|
inputs,
|
|
731
1384
|
setInput,
|
|
732
1385
|
stateOf: (id) => states[id],
|
|
733
|
-
phaseOf: (id) =>
|
|
734
|
-
failedUpstreamOf: (id) =>
|
|
1386
|
+
phaseOf: (id) => chunk6F7SZCVL_cjs.stepPhase(steps, states, id),
|
|
1387
|
+
failedUpstreamOf: (id) => chunk6F7SZCVL_cjs.failedUpstream(steps, states, id),
|
|
735
1388
|
isLocked,
|
|
736
|
-
errors: showErrors && step && !isLocked(step.id) ?
|
|
1389
|
+
errors: showErrors && step && !isLocked(step.id) ? chunk6F7SZCVL_cjs.validateStep(step, inputs) : {},
|
|
737
1390
|
busy,
|
|
738
1391
|
actionError,
|
|
739
1392
|
isRunning: Object.values(states).some((s) => s.status === "running"),
|
|
@@ -751,11 +1404,11 @@ function useWorkflowView(options) {
|
|
|
751
1404
|
nameOf: options.nameOf,
|
|
752
1405
|
assigneeOf: (id) => {
|
|
753
1406
|
const s = steps.find((x) => x.id === id);
|
|
754
|
-
if (!s || !
|
|
755
|
-
return
|
|
1407
|
+
if (!s || !chunk6F7SZCVL_cjs.canAssign(s)) return void 0;
|
|
1408
|
+
return chunk6F7SZCVL_cjs.assigneeName(s.assignee, {
|
|
756
1409
|
nameOf: options.nameOf,
|
|
757
1410
|
inputs,
|
|
758
|
-
fields:
|
|
1411
|
+
fields: chunk6F7SZCVL_cjs.runFieldsOf(steps),
|
|
759
1412
|
announcedTo: states[id]?.announcedTo
|
|
760
1413
|
});
|
|
761
1414
|
},
|
|
@@ -889,7 +1542,7 @@ function StepBarFrame({
|
|
|
889
1542
|
}) {
|
|
890
1543
|
const l = { ...DEFAULT_STEP_BAR_LABELS, ...labels };
|
|
891
1544
|
const box = react.useRef(null);
|
|
892
|
-
const { width } =
|
|
1545
|
+
const { width } = chunk6F7SZCVL_cjs.useElementSize(box);
|
|
893
1546
|
const narrow = width > 0 && width < NARROW_PX;
|
|
894
1547
|
const [start, setStart] = react.useState(null);
|
|
895
1548
|
react.useEffect(() => setStart(null), [current]);
|
|
@@ -956,7 +1609,7 @@ function StepBarFrame({
|
|
|
956
1609
|
phase === "blocked" && "opacity-60"
|
|
957
1610
|
),
|
|
958
1611
|
"aria-hidden": true,
|
|
959
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1612
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chunk6F7SZCVL_cjs.StepBadgeMark, { phase, icon: icon?.(s) })
|
|
960
1613
|
}
|
|
961
1614
|
),
|
|
962
1615
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", title: s.title, children: s.title }),
|
|
@@ -1064,7 +1717,7 @@ function StepBarFrame({
|
|
|
1064
1717
|
};
|
|
1065
1718
|
const running = win.runningHidden;
|
|
1066
1719
|
const outOfViewChip = (s, kind) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1067
|
-
|
|
1720
|
+
chunk6F7SZCVL_cjs.StepChip,
|
|
1068
1721
|
{
|
|
1069
1722
|
kind: kindOf(s),
|
|
1070
1723
|
phase: kind === "working" ? "running" : "failed",
|
|
@@ -1237,7 +1890,7 @@ var DEFAULT_WORKFLOW_STEP_PARTS_LABELS = {
|
|
|
1237
1890
|
someone: "someone"
|
|
1238
1891
|
};
|
|
1239
1892
|
var docName = (ref, nameOfDoc) => {
|
|
1240
|
-
const { id, version } =
|
|
1893
|
+
const { id, version } = chunk6F7SZCVL_cjs.splitDocRef(ref);
|
|
1241
1894
|
const name = nameOfDoc?.(id) ?? id;
|
|
1242
1895
|
return version ? `${name} \xB7 v${version}` : name;
|
|
1243
1896
|
};
|
|
@@ -1319,7 +1972,7 @@ function SendBackControl({
|
|
|
1319
1972
|
const states = Object.fromEntries(
|
|
1320
1973
|
run.steps.map((s) => [s.id, run.stateOf(s.id) ?? { status: "pending" }])
|
|
1321
1974
|
);
|
|
1322
|
-
const targets =
|
|
1975
|
+
const targets = chunk6F7SZCVL_cjs.sendBackTargets(run.steps, states, step.id);
|
|
1323
1976
|
const [open, setOpen] = react.useState(false);
|
|
1324
1977
|
const [to, setTo] = react.useState(targets[0]?.id ?? "");
|
|
1325
1978
|
const [note, setNote] = react.useState("");
|
|
@@ -1409,7 +2062,7 @@ function ApprovalEvidence({
|
|
|
1409
2062
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex flex-wrap items-center gap-1.5 text-sm font-medium", children: [
|
|
1410
2063
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "size-4 text-primary" }),
|
|
1411
2064
|
approver ? l.approvedBy.replace("{name}", approver) : null,
|
|
1412
|
-
state.at && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-normal text-muted-foreground", children: l.approvedAt.replace("{date}",
|
|
2065
|
+
state.at && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-normal text-muted-foreground", children: l.approvedAt.replace("{date}", chunk6F7SZCVL_cjs.formatDate(state.at)) })
|
|
1413
2066
|
] }),
|
|
1414
2067
|
evidence.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
1415
2068
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: l.approvedWhat }),
|
|
@@ -1442,7 +2095,7 @@ function ApprovalEvidence({
|
|
|
1442
2095
|
] }),
|
|
1443
2096
|
(step.fields ?? []).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 text-xs", children: (step.fields ?? []).map((f) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "contents", children: [
|
|
1444
2097
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground", children: f.label }),
|
|
1445
|
-
/* @__PURE__ */ jsxRuntime.jsx("dd", { "data-testid": `${testId}-evidence-field-${f.name}`, children:
|
|
2098
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { "data-testid": `${testId}-evidence-field-${f.name}`, children: chunk6F7SZCVL_cjs.shownValue(run.inputs[f.name], f, run.nameOf) })
|
|
1446
2099
|
] }, f.name)) })
|
|
1447
2100
|
] });
|
|
1448
2101
|
}
|
|
@@ -1538,7 +2191,7 @@ function ActionStepBody({
|
|
|
1538
2191
|
waiting?.expires_at && phase === "waiting" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1539
2192
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "size-3.5" }),
|
|
1540
2193
|
" ",
|
|
1541
|
-
l.expires.replace("{date}",
|
|
2194
|
+
l.expires.replace("{date}", chunk6F7SZCVL_cjs.formatDate(waiting.expires_at))
|
|
1542
2195
|
] }),
|
|
1543
2196
|
phase === "waiting" && mine && !declining && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
1544
2197
|
actions?.sign && state && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -1696,7 +2349,7 @@ function WorkflowStepBar({
|
|
|
1696
2349
|
const name = `${title} (${l.phases[phase]})`;
|
|
1697
2350
|
if (s.id === DONE)
|
|
1698
2351
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1699
|
-
|
|
2352
|
+
chunk6F7SZCVL_cjs.StepChip,
|
|
1700
2353
|
{
|
|
1701
2354
|
inert: true,
|
|
1702
2355
|
kind: "start",
|
|
@@ -1710,17 +2363,17 @@ function WorkflowStepBar({
|
|
|
1710
2363
|
"data-testid": tid("step-done")
|
|
1711
2364
|
}
|
|
1712
2365
|
);
|
|
1713
|
-
const kind =
|
|
1714
|
-
const KindIcon =
|
|
2366
|
+
const kind = chunk6F7SZCVL_cjs.stepKindOf(s);
|
|
2367
|
+
const KindIcon = chunk6F7SZCVL_cjs.STEP_KIND_ICONS[kind];
|
|
1715
2368
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1716
|
-
|
|
2369
|
+
chunk6F7SZCVL_cjs.StepChip,
|
|
1717
2370
|
{
|
|
1718
2371
|
kind,
|
|
1719
2372
|
phase,
|
|
1720
2373
|
icon: icon(s.icon) ?? /* @__PURE__ */ jsxRuntime.jsx(KindIcon, {}),
|
|
1721
2374
|
label: s.title,
|
|
1722
2375
|
current: isCurrent,
|
|
1723
|
-
heading:
|
|
2376
|
+
heading: chunk6F7SZCVL_cjs.DEFAULT_STEP_KIND_LABELS[kind],
|
|
1724
2377
|
labelClassName: isCurrent ? STEP_LABEL_CURRENT : ui.cn(STEP_LABEL, STEP_LABEL_MAX),
|
|
1725
2378
|
labelTestId: tid(`step-${s.id}-label`),
|
|
1726
2379
|
onClick: () => run.goTo(s.id),
|
|
@@ -1753,7 +2406,7 @@ function WorkflowStepBar({
|
|
|
1753
2406
|
isSelectable: (id) => id !== DONE,
|
|
1754
2407
|
renderStep: (s) => pill(s),
|
|
1755
2408
|
icon: (s) => s.id === DONE ? doneIcon : icon(s.icon),
|
|
1756
|
-
kindOf: (s) => s.id === DONE ? "start" :
|
|
2409
|
+
kindOf: (s) => s.id === DONE ? "start" : chunk6F7SZCVL_cjs.stepKindOf(s),
|
|
1757
2410
|
disabled: run.busy,
|
|
1758
2411
|
labels,
|
|
1759
2412
|
tid,
|
|
@@ -1836,7 +2489,7 @@ function WorkflowRunner({
|
|
|
1836
2489
|
const { steps, step, isComplete, action } = run;
|
|
1837
2490
|
const completion = workflow.run.kind === "steps" ? workflow.run.completion : void 0;
|
|
1838
2491
|
const tid = (suffix) => `${testIdPrefix}-${suffix}`;
|
|
1839
|
-
const levels =
|
|
2492
|
+
const levels = chunk6F7SZCVL_cjs.stepLevels(steps);
|
|
1840
2493
|
const icon = (key) => key && renderIcon ? renderIcon(key) : void 0;
|
|
1841
2494
|
const added = step?.kind === "upload" ? (files ?? []).filter((f) => f.addedFor === step.id) : [];
|
|
1842
2495
|
const unread = added.filter((f) => f.status === "processing").length;
|
|
@@ -1844,7 +2497,7 @@ function WorkflowRunner({
|
|
|
1844
2497
|
const sending = added.filter((f) => f.status === "uploading").length;
|
|
1845
2498
|
const unsent = added.filter((f) => f.status === "upload-failed").length;
|
|
1846
2499
|
const uploadHold = step?.kind === "upload" && (sending > 0 || uploading || unsent > 0);
|
|
1847
|
-
const docsWait = !!step &&
|
|
2500
|
+
const docsWait = !!step && chunk6F7SZCVL_cjs.waitingDocuments(run.stateOf(step.id)).length > 0;
|
|
1848
2501
|
const nextLabel = sending ? sending === 1 ? l.uploadingFile : l.uploadingFiles.replace("{count}", String(sending)) : uploadHold && uploading ? l.uploadingAny : uploadHold ? unsent === 1 ? l.uploadFailed : l.uploadsFailed.replace("{count}", String(unsent)) : reading ? l.readingFiles.replace("{current}", String(Math.min(added.length - unread + 1, added.length))).replace("{count}", String(added.length)) : action === "start" ? l.start : action === "retry" ? l.retry : action === "finish" ? l.finish : action === "complete" && step?.kind === "review" ? l.approve : action === "complete" && step?.kind === "action" ? l.markSent : action === "wait" && (run.isRunning || run.busy || docsWait) ? l.working : (step && !run.isLocked(step.id) ? step.nextLabel : void 0) ?? l.next;
|
|
1849
2502
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn(compact2 ? "space-y-3" : "space-y-6", className), "data-testid": testIdPrefix, children: [
|
|
1850
2503
|
!hideStepBar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1876,7 +2529,7 @@ function WorkflowRunner({
|
|
|
1876
2529
|
/* @__PURE__ */ jsxRuntime.jsx(StepNotices, { run, step, l, tid }),
|
|
1877
2530
|
run.phaseOf(step.id) === "blocked" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { className: ui.cn(box, "p-6"), "data-testid": tid(step.id), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", "data-testid": tid(`${step.id}-blocked`), children: l.blocked.replace(
|
|
1878
2531
|
"{steps}",
|
|
1879
|
-
|
|
2532
|
+
chunk6F7SZCVL_cjs.stepDependencies(steps, step.id).map((d) => steps.find((s) => s.id === d)?.title ?? d).join(", ")
|
|
1880
2533
|
) }) }) : step.kind === "form" ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { className: ui.cn(box, "space-y-4"), "data-testid": tid(step.id), children: [
|
|
1881
2534
|
/* @__PURE__ */ jsxRuntime.jsx(StepHeading, { step, icon: icon(step.icon), testId: tid(`${step.id}-title`) }),
|
|
1882
2535
|
/* @__PURE__ */ jsxRuntime.jsx(SentBackNote, { state: run.stateOf(step.id), l: pl, testId: tid(step.id) }),
|
|
@@ -1932,7 +2585,7 @@ function WorkflowRunner({
|
|
|
1932
2585
|
] }) : step.kind === "review" ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { className: ui.cn(box, "space-y-4"), "data-testid": tid(step.id), children: [
|
|
1933
2586
|
/* @__PURE__ */ jsxRuntime.jsx(StepHeading, { step, icon: icon(step.icon) }),
|
|
1934
2587
|
/* @__PURE__ */ jsxRuntime.jsx(SentBackNote, { state: run.stateOf(step.id), l: pl, testId: tid(step.id) }),
|
|
1935
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-line text-sm text-muted-foreground", children:
|
|
2588
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-line text-sm text-muted-foreground", children: chunk6F7SZCVL_cjs.reviewInstructions(step, run.inputs) }),
|
|
1936
2589
|
/* @__PURE__ */ jsxRuntime.jsx(AssigneeLine, { run, stepId: step.id, l: pl, testId: tid(step.id) }),
|
|
1937
2590
|
!(run.phaseOf(step.id) === "done" && run.stateOf(step.id)?.by) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", "data-testid": tid(`${step.id}-status`), children: run.phaseOf(step.id) === "done" ? l.approved : run.phaseOf(step.id) === "skipped" ? l.skipped : l.awaitingReview }),
|
|
1938
2591
|
(step.fields ?? []).length > 0 && run.phaseOf(step.id) === "ready" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2199,8 +2852,8 @@ function AgentStepBody({
|
|
|
2199
2852
|
}) {
|
|
2200
2853
|
const state = run.stateOf(step.id);
|
|
2201
2854
|
const phase = run.phaseOf(step.id);
|
|
2202
|
-
const pending =
|
|
2203
|
-
const pendingNames = pending.flatMap((ref) => nameOfDoc?.(
|
|
2855
|
+
const pending = chunk6F7SZCVL_cjs.waitingDocuments(state);
|
|
2856
|
+
const pendingNames = pending.flatMap((ref) => nameOfDoc?.(chunk6F7SZCVL_cjs.splitDocRef(ref).id) ?? []);
|
|
2204
2857
|
const header = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2205
2858
|
/* @__PURE__ */ jsxRuntime.jsx(StepHeading, { step, icon }),
|
|
2206
2859
|
phase === "failed" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: run.retry && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2285,7 +2938,7 @@ function StepNotices({
|
|
|
2285
2938
|
l,
|
|
2286
2939
|
tid
|
|
2287
2940
|
}) {
|
|
2288
|
-
const notStarted = !
|
|
2941
|
+
const notStarted = !chunk6F7SZCVL_cjs.isPersonStep(step) && run.needsStart && run.phaseOf(step.id) === "ready";
|
|
2289
2942
|
const failed = run.failedUpstreamOf(step.id);
|
|
2290
2943
|
if (!notStarted && failed.length === 0) return null;
|
|
2291
2944
|
const why = (error) => error ? `: ${error}` : "";
|
|
@@ -2321,6 +2974,890 @@ function StepNotices({
|
|
|
2321
2974
|
))
|
|
2322
2975
|
] });
|
|
2323
2976
|
}
|
|
2977
|
+
|
|
2978
|
+
// src/agents/skills/skillFiles.ts
|
|
2979
|
+
var SKILL_TYPES = ["markdown", "python", "shell", "javascript", "typescript"];
|
|
2980
|
+
var SKILL_MAIN_FILENAME = "SKILL.md";
|
|
2981
|
+
var MAIN_NAMES = /* @__PURE__ */ new Set(["skill.md", "skill.py", "skill.sh", "skill.js", "skill.ts"]);
|
|
2982
|
+
function isMainSkillFile(filename, skillName) {
|
|
2983
|
+
const lower = filename.toLowerCase();
|
|
2984
|
+
if (MAIN_NAMES.has(lower)) return true;
|
|
2985
|
+
const stem = lower.includes(".") ? lower.slice(0, lower.lastIndexOf(".")) : lower;
|
|
2986
|
+
return stem === skillName;
|
|
2987
|
+
}
|
|
2988
|
+
function detectTypeFromContent(content, filename) {
|
|
2989
|
+
if (filename) {
|
|
2990
|
+
const lower = filename.toLowerCase();
|
|
2991
|
+
if (lower.endsWith(".py")) return "python";
|
|
2992
|
+
if (lower.endsWith(".sh")) return "shell";
|
|
2993
|
+
if (lower.endsWith(".js")) return "javascript";
|
|
2994
|
+
if (lower.endsWith(".ts")) return "typescript";
|
|
2995
|
+
}
|
|
2996
|
+
if (content) {
|
|
2997
|
+
const firstLine = content.split("\n", 1)[0].trim();
|
|
2998
|
+
if (firstLine.startsWith("#!")) {
|
|
2999
|
+
if (firstLine.includes("python")) return "python";
|
|
3000
|
+
if (firstLine.includes("bash") || firstLine.includes("/sh")) return "shell";
|
|
3001
|
+
if (firstLine.includes("ts-node")) return "typescript";
|
|
3002
|
+
if (firstLine.includes("node")) return "javascript";
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
return "markdown";
|
|
3006
|
+
}
|
|
3007
|
+
function parseSkillFrontmatter(raw, filename = "") {
|
|
3008
|
+
const config = {};
|
|
3009
|
+
let name = "";
|
|
3010
|
+
let description = "";
|
|
3011
|
+
let skillType = "markdown";
|
|
3012
|
+
if (!raw.startsWith("---")) {
|
|
3013
|
+
return {
|
|
3014
|
+
content: raw,
|
|
3015
|
+
name,
|
|
3016
|
+
description,
|
|
3017
|
+
config,
|
|
3018
|
+
skillType: detectTypeFromContent(raw, filename)
|
|
3019
|
+
};
|
|
3020
|
+
}
|
|
3021
|
+
const end = raw.indexOf("---", 3);
|
|
3022
|
+
if (end === -1) {
|
|
3023
|
+
return {
|
|
3024
|
+
content: raw,
|
|
3025
|
+
name,
|
|
3026
|
+
description,
|
|
3027
|
+
config,
|
|
3028
|
+
skillType: detectTypeFromContent(raw, filename)
|
|
3029
|
+
};
|
|
3030
|
+
}
|
|
3031
|
+
const frontmatter = raw.slice(3, end).trim();
|
|
3032
|
+
const body = raw.slice(end + 3).trim();
|
|
3033
|
+
for (const rawLine of frontmatter.split("\n")) {
|
|
3034
|
+
const line = rawLine.trim();
|
|
3035
|
+
if (!line || !line.includes(":")) continue;
|
|
3036
|
+
const idx = line.indexOf(":");
|
|
3037
|
+
const key = line.slice(0, idx).trim().toLowerCase();
|
|
3038
|
+
const value = line.slice(idx + 1).trim();
|
|
3039
|
+
if (key === "name" && value) {
|
|
3040
|
+
name = value;
|
|
3041
|
+
} else if (key === "description" && value) {
|
|
3042
|
+
description = value;
|
|
3043
|
+
} else if (key === "model" && value) {
|
|
3044
|
+
config.model = value;
|
|
3045
|
+
} else if (key === "temperature") {
|
|
3046
|
+
const t = Number.parseFloat(value);
|
|
3047
|
+
if (!Number.isNaN(t) && t >= 0 && t <= 2) config.temperature = t;
|
|
3048
|
+
} else if (key === "agent") {
|
|
3049
|
+
config.agent = ["true", "yes", "1"].includes(value.toLowerCase());
|
|
3050
|
+
} else if (key === "tools" && value) {
|
|
3051
|
+
config.tools = value.split(",").map((t) => t.trim()).filter(Boolean);
|
|
3052
|
+
} else if (key === "type" && value) {
|
|
3053
|
+
const v = value.toLowerCase();
|
|
3054
|
+
if (v === "python" || v === "py") skillType = "python";
|
|
3055
|
+
else if (v === "shell" || v === "sh" || v === "bash") skillType = "shell";
|
|
3056
|
+
else if (v === "javascript" || v === "js" || v === "node") skillType = "javascript";
|
|
3057
|
+
else if (v === "typescript" || v === "ts") skillType = "typescript";
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
if (skillType === "markdown") {
|
|
3061
|
+
skillType = detectTypeFromContent(body, filename);
|
|
3062
|
+
}
|
|
3063
|
+
return { content: body, name, description, config, skillType };
|
|
3064
|
+
}
|
|
3065
|
+
function serializeSkill(input) {
|
|
3066
|
+
const lines = ["---", `name: ${input.name}`, `description: ${input.description}`];
|
|
3067
|
+
if (input.type && input.type !== "markdown") {
|
|
3068
|
+
lines.push(`type: ${input.type}`);
|
|
3069
|
+
}
|
|
3070
|
+
lines.push("---", "", input.body.trim(), "");
|
|
3071
|
+
return lines.join("\n");
|
|
3072
|
+
}
|
|
3073
|
+
var SKILL_FOLDER_PREFIX = "skills/";
|
|
3074
|
+
function stripExt(name) {
|
|
3075
|
+
const i = name.lastIndexOf(".");
|
|
3076
|
+
return i > 0 ? name.slice(0, i) : name;
|
|
3077
|
+
}
|
|
3078
|
+
function isJunkPath(path) {
|
|
3079
|
+
if (path.endsWith("/")) return true;
|
|
3080
|
+
const parts = path.split("/");
|
|
3081
|
+
if (parts.some((p) => p === "__MACOSX")) return true;
|
|
3082
|
+
return parts[parts.length - 1].startsWith(".");
|
|
3083
|
+
}
|
|
3084
|
+
function folderFor(slug, relDir) {
|
|
3085
|
+
const root = `${SKILL_FOLDER_PREFIX}${slug}`;
|
|
3086
|
+
return relDir ? `${root}/${relDir}` : root;
|
|
3087
|
+
}
|
|
3088
|
+
function importMarkdownSkill(fileName, text) {
|
|
3089
|
+
const parsed = parseSkillFrontmatter(text, fileName);
|
|
3090
|
+
const slug = skillSlug(parsed.name) || skillSlug(stripExt(fileName));
|
|
3091
|
+
if (!slug) {
|
|
3092
|
+
throw new Error(
|
|
3093
|
+
"Could not derive a skill name. Add a `name:` to the frontmatter or rename the file."
|
|
3094
|
+
);
|
|
3095
|
+
}
|
|
3096
|
+
return {
|
|
3097
|
+
slug,
|
|
3098
|
+
entries: [{ folder: folderFor(slug, ""), fileName: SKILL_MAIN_FILENAME, content: text }]
|
|
3099
|
+
};
|
|
3100
|
+
}
|
|
3101
|
+
function commonTopDir(paths) {
|
|
3102
|
+
const tops = /* @__PURE__ */ new Set();
|
|
3103
|
+
for (const p of paths) {
|
|
3104
|
+
const idx = p.indexOf("/");
|
|
3105
|
+
if (idx === -1) return null;
|
|
3106
|
+
tops.add(p.slice(0, idx));
|
|
3107
|
+
}
|
|
3108
|
+
return tops.size === 1 ? [...tops][0] : null;
|
|
3109
|
+
}
|
|
3110
|
+
function buildZipSkillImport(archiveName, rawEntries) {
|
|
3111
|
+
const entries = rawEntries.filter((e) => e.path && !isJunkPath(e.path));
|
|
3112
|
+
if (entries.length === 0) throw new Error("The archive contains no importable skill files.");
|
|
3113
|
+
const top = commonTopDir(entries.map((e) => e.path));
|
|
3114
|
+
const rel = (p) => top ? p.slice(top.length + 1) : p;
|
|
3115
|
+
let slug = top ? skillSlug(top) : "";
|
|
3116
|
+
if (!slug) {
|
|
3117
|
+
const mainGuess = entries.find((e) => {
|
|
3118
|
+
const r = rel(e.path);
|
|
3119
|
+
return !r.includes("/") && isMainSkillFile(r, "__never__");
|
|
3120
|
+
}) ?? entries.find((e) => !rel(e.path).includes("/"));
|
|
3121
|
+
if (mainGuess) slug = skillSlug(parseSkillFrontmatter(mainGuess.text, rel(mainGuess.path)).name);
|
|
3122
|
+
}
|
|
3123
|
+
if (!slug) slug = skillSlug(stripExt(archiveName));
|
|
3124
|
+
if (!slug) throw new Error("Could not derive a skill name from the archive.");
|
|
3125
|
+
const rootFiles = entries.filter((e) => !rel(e.path).includes("/"));
|
|
3126
|
+
const mainEntry = rootFiles.find((e) => isMainSkillFile(rel(e.path), slug)) ?? (rootFiles.length === 1 ? rootFiles[0] : void 0);
|
|
3127
|
+
return {
|
|
3128
|
+
slug,
|
|
3129
|
+
entries: entries.map((e) => {
|
|
3130
|
+
const r = rel(e.path);
|
|
3131
|
+
const lastSlash = r.lastIndexOf("/");
|
|
3132
|
+
return {
|
|
3133
|
+
folder: folderFor(slug, lastSlash === -1 ? "" : r.slice(0, lastSlash)),
|
|
3134
|
+
fileName: mainEntry && e.path === mainEntry.path ? SKILL_MAIN_FILENAME : lastSlash === -1 ? r : r.slice(lastSlash + 1),
|
|
3135
|
+
content: e.text
|
|
3136
|
+
};
|
|
3137
|
+
})
|
|
3138
|
+
};
|
|
3139
|
+
}
|
|
3140
|
+
async function readSkillArchive(file) {
|
|
3141
|
+
const data = new Uint8Array(await file.arrayBuffer());
|
|
3142
|
+
let files;
|
|
3143
|
+
try {
|
|
3144
|
+
files = await new Promise(
|
|
3145
|
+
(resolve, reject) => fflate.unzip(
|
|
3146
|
+
data,
|
|
3147
|
+
{ filter: (f) => !isJunkPath(f.name) },
|
|
3148
|
+
(err, out) => err ? reject(err) : resolve(out)
|
|
3149
|
+
)
|
|
3150
|
+
);
|
|
3151
|
+
} catch {
|
|
3152
|
+
throw new Error("The archive is empty or could not be read.");
|
|
3153
|
+
}
|
|
3154
|
+
const entries = Object.entries(files).map(([path, bytes]) => ({ path, text: fflate.strFromU8(bytes) }));
|
|
3155
|
+
if (entries.length === 0) throw new Error("The archive is empty or could not be read.");
|
|
3156
|
+
return entries;
|
|
3157
|
+
}
|
|
3158
|
+
async function importSkillFile(file) {
|
|
3159
|
+
const lower = file.name.toLowerCase();
|
|
3160
|
+
if (lower.endsWith(".zip")) return buildZipSkillImport(file.name, await readSkillArchive(file));
|
|
3161
|
+
if (lower.endsWith(".md") || lower.endsWith(".markdown")) {
|
|
3162
|
+
return importMarkdownSkill(file.name, await file.text());
|
|
3163
|
+
}
|
|
3164
|
+
throw new Error("Unsupported file type. Choose a .md skill or a .zip archive.");
|
|
3165
|
+
}
|
|
3166
|
+
async function importSkillFromUrl(url) {
|
|
3167
|
+
let parsed;
|
|
3168
|
+
try {
|
|
3169
|
+
parsed = new URL(url.trim());
|
|
3170
|
+
} catch {
|
|
3171
|
+
throw new Error("That does not look like a link.");
|
|
3172
|
+
}
|
|
3173
|
+
const response = await fetch(parsed.toString());
|
|
3174
|
+
if (!response.ok) throw new Error(`Could not open the link (${response.status}).`);
|
|
3175
|
+
const text = await response.text();
|
|
3176
|
+
const last = parsed.pathname.split("/").filter(Boolean).pop() ?? "skill";
|
|
3177
|
+
return importMarkdownSkill(last.includes(".") ? last : `${last}.md`, text);
|
|
3178
|
+
}
|
|
3179
|
+
function PersonPill({ person, size = "sm", testId }) {
|
|
3180
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": testId, className: "inline-flex min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3181
|
+
ui.UserEntity,
|
|
3182
|
+
{
|
|
3183
|
+
variant: "pill",
|
|
3184
|
+
size,
|
|
3185
|
+
interactive: false,
|
|
3186
|
+
showTooltip: false,
|
|
3187
|
+
initials: chunkKDG6FER6_cjs.initials(person.label),
|
|
3188
|
+
displayName: person.label,
|
|
3189
|
+
avatarStyle: person.id ? ui.getEntityColorStyles(person.id) : void 0,
|
|
3190
|
+
isAgent: person.isAgent,
|
|
3191
|
+
isMe: person.isMe
|
|
3192
|
+
}
|
|
3193
|
+
) });
|
|
3194
|
+
}
|
|
3195
|
+
var DEFAULT_TASK_TRIGGER_CHIP_LABELS = {
|
|
3196
|
+
after: (name) => `After \u201C${name}\u201D is done`,
|
|
3197
|
+
afterUnknown: "After another task is done",
|
|
3198
|
+
onDemand: "Manual"
|
|
3199
|
+
};
|
|
3200
|
+
function TriggerIcon({ type, chained }) {
|
|
3201
|
+
const cls = "size-3.5 shrink-0 text-muted-foreground";
|
|
3202
|
+
if (chained) return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { className: cls, "aria-hidden": true });
|
|
3203
|
+
switch (type) {
|
|
3204
|
+
case "on_demand":
|
|
3205
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MousePointerClick, { className: cls, "aria-hidden": true });
|
|
3206
|
+
case "recurring":
|
|
3207
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: cls, "aria-hidden": true });
|
|
3208
|
+
case "event":
|
|
3209
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className: cls, "aria-hidden": true });
|
|
3210
|
+
default:
|
|
3211
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: cls, "aria-hidden": true });
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
function TaskTriggerChip({
|
|
3215
|
+
id,
|
|
3216
|
+
triggerType,
|
|
3217
|
+
summary,
|
|
3218
|
+
afterTaskId,
|
|
3219
|
+
afterTaskName,
|
|
3220
|
+
testId,
|
|
3221
|
+
labels
|
|
3222
|
+
}) {
|
|
3223
|
+
const l = { ...DEFAULT_TASK_TRIGGER_CHIP_LABELS, ...labels };
|
|
3224
|
+
const chained = Boolean(afterTaskId);
|
|
3225
|
+
const text = chained ? afterTaskName ? l.after(afterTaskName) : l.afterUnknown : triggerType === "on_demand" ? l.onDemand : summary;
|
|
3226
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3227
|
+
"span",
|
|
3228
|
+
{
|
|
3229
|
+
className: "inline-flex min-w-0 max-w-full items-center gap-1.5 text-sm font-normal text-foreground",
|
|
3230
|
+
"data-testid": chunkMHVNT4J3_cjs.testIdOr(testId, { testId: `task-trigger-${id}` }),
|
|
3231
|
+
"data-trigger": chained ? "task" : triggerType,
|
|
3232
|
+
children: [
|
|
3233
|
+
/* @__PURE__ */ jsxRuntime.jsx(TriggerIcon, { type: triggerType, chained }),
|
|
3234
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: text })
|
|
3235
|
+
]
|
|
3236
|
+
}
|
|
3237
|
+
);
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
// src/agents/tasks/workflowRows.ts
|
|
3241
|
+
var isSkillRow = (row) => row.kind === "skill";
|
|
3242
|
+
var hasTrigger = (row) => !row.on_demand && Boolean(row.rrule || row.run_at || row.event_kind || row.after_conversation_ext_id);
|
|
3243
|
+
function workflowStatus(row) {
|
|
3244
|
+
if (isSkillRow(row) || !hasTrigger(row)) return "on_demand";
|
|
3245
|
+
return row.active ? "active" : "paused";
|
|
3246
|
+
}
|
|
3247
|
+
function workflowTriggerType(workflow) {
|
|
3248
|
+
if (workflow.on_demand) return "on_demand";
|
|
3249
|
+
if (workflow.after_conversation_ext_id) return "after";
|
|
3250
|
+
if (workflow.event_kind) return "event";
|
|
3251
|
+
if (workflow.rrule) return "recurring";
|
|
3252
|
+
if (workflow.run_at) return "one_time";
|
|
3253
|
+
return "on_demand";
|
|
3254
|
+
}
|
|
3255
|
+
function workflowRunStatusLabel(status) {
|
|
3256
|
+
if (!status) return "None";
|
|
3257
|
+
const labels = {
|
|
3258
|
+
completed: "Success",
|
|
3259
|
+
success: "Success",
|
|
3260
|
+
failed: "Failed",
|
|
3261
|
+
running: "In progress",
|
|
3262
|
+
awaiting_authorization: "Awaiting access"
|
|
3263
|
+
};
|
|
3264
|
+
return labels[status] ?? status.replaceAll("_", " ");
|
|
3265
|
+
}
|
|
3266
|
+
function listedRunStatus(status, threadStatus) {
|
|
3267
|
+
if (threadStatus === "done" && status === "running") return "completed";
|
|
3268
|
+
return status;
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
// src/agents/tasks/workflowColumns.tsx
|
|
3272
|
+
var WORKFLOW_COLUMN_ORDER = [
|
|
3273
|
+
"name",
|
|
3274
|
+
"trigger",
|
|
3275
|
+
"last_run",
|
|
3276
|
+
"result",
|
|
3277
|
+
"status",
|
|
3278
|
+
"shared",
|
|
3279
|
+
"actions"
|
|
3280
|
+
];
|
|
3281
|
+
function cell(render) {
|
|
3282
|
+
return (params) => params.data ? render(params.data) : null;
|
|
3283
|
+
}
|
|
3284
|
+
var time = (iso) => iso ? Date.parse(iso) : Number.POSITIVE_INFINITY;
|
|
3285
|
+
function createWorkflowColumns(o) {
|
|
3286
|
+
const l = o.labels;
|
|
3287
|
+
const base = {
|
|
3288
|
+
sortable: false,
|
|
3289
|
+
cellStyle: { display: "flex", alignItems: "center" }
|
|
3290
|
+
};
|
|
3291
|
+
return [
|
|
3292
|
+
{
|
|
3293
|
+
...base,
|
|
3294
|
+
colId: "name",
|
|
3295
|
+
sortable: true,
|
|
3296
|
+
headerName: l.colName,
|
|
3297
|
+
flex: 3,
|
|
3298
|
+
minWidth: 210,
|
|
3299
|
+
valueGetter: (p) => p.data?.name.toLowerCase() ?? "",
|
|
3300
|
+
cellRenderer: cell(o.renderName)
|
|
3301
|
+
},
|
|
3302
|
+
{
|
|
3303
|
+
...base,
|
|
3304
|
+
colId: "trigger",
|
|
3305
|
+
headerName: l.colTrigger,
|
|
3306
|
+
flex: 2.4,
|
|
3307
|
+
minWidth: 185,
|
|
3308
|
+
valueGetter: (p) => p.data ? o.getTriggerText(p.data) : "",
|
|
3309
|
+
cellRenderer: cell(o.renderTrigger)
|
|
3310
|
+
},
|
|
3311
|
+
{
|
|
3312
|
+
...base,
|
|
3313
|
+
colId: "last_run",
|
|
3314
|
+
sortable: true,
|
|
3315
|
+
headerName: l.colLastRun,
|
|
3316
|
+
flex: 1.4,
|
|
3317
|
+
minWidth: 140,
|
|
3318
|
+
cellStyle: { display: "flex", alignItems: "center", padding: 0 },
|
|
3319
|
+
valueGetter: (p) => time(p.data?.last_fired_at),
|
|
3320
|
+
cellRenderer: cell(o.renderLastRun)
|
|
3321
|
+
},
|
|
3322
|
+
{
|
|
3323
|
+
...base,
|
|
3324
|
+
colId: "result",
|
|
3325
|
+
headerName: "Result",
|
|
3326
|
+
width: 130,
|
|
3327
|
+
valueGetter: (p) => p.data?.last_run_status ?? "",
|
|
3328
|
+
cellStyle: { display: "flex", alignItems: "center", padding: 0 },
|
|
3329
|
+
cellRenderer: cell(o.renderResult)
|
|
3330
|
+
},
|
|
3331
|
+
{
|
|
3332
|
+
...base,
|
|
3333
|
+
colId: "status",
|
|
3334
|
+
sortable: true,
|
|
3335
|
+
headerName: l.colStatus,
|
|
3336
|
+
width: 120,
|
|
3337
|
+
valueGetter: (p) => p.data ? workflowStatus(p.data) : "",
|
|
3338
|
+
cellRenderer: cell(o.renderStatus)
|
|
3339
|
+
},
|
|
3340
|
+
{
|
|
3341
|
+
...base,
|
|
3342
|
+
colId: "shared",
|
|
3343
|
+
headerName: l.colShared,
|
|
3344
|
+
headerTooltip: l.shared,
|
|
3345
|
+
width: 96,
|
|
3346
|
+
cellStyle: { display: "flex", alignItems: "center", justifyContent: "center" },
|
|
3347
|
+
valueGetter: (p) => p.data?.shared ?? false,
|
|
3348
|
+
cellRenderer: cell(o.renderShared)
|
|
3349
|
+
},
|
|
3350
|
+
{
|
|
3351
|
+
...base,
|
|
3352
|
+
colId: "actions",
|
|
3353
|
+
headerName: "",
|
|
3354
|
+
width: 180,
|
|
3355
|
+
minWidth: 180,
|
|
3356
|
+
cellStyle: { display: "flex", alignItems: "center", justifyContent: "flex-end" },
|
|
3357
|
+
cellRenderer: cell(o.renderActions)
|
|
3358
|
+
}
|
|
3359
|
+
];
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
// src/agents/tasks/workflowTableLabels.ts
|
|
3363
|
+
var DEFAULT_WORKFLOW_LIST_LABELS = {
|
|
3364
|
+
colName: "Name",
|
|
3365
|
+
colType: "Type",
|
|
3366
|
+
colTrigger: "When",
|
|
3367
|
+
colAction: "What it does",
|
|
3368
|
+
colAgent: "Agent",
|
|
3369
|
+
colStatus: "Active",
|
|
3370
|
+
colShared: "Shared",
|
|
3371
|
+
colLastRun: "Last run",
|
|
3372
|
+
colNextRun: "Next run",
|
|
3373
|
+
shared: "Shared with the workspace",
|
|
3374
|
+
sharedOwnerOnly: "Only the creator can change who can see this",
|
|
3375
|
+
deleteOwnerOnly: "Only the creator or workspace owner can delete this",
|
|
3376
|
+
typeSkill: "Skill",
|
|
3377
|
+
typeWorkflow: "Workflow",
|
|
3378
|
+
statusActive: "Active",
|
|
3379
|
+
statusPaused: "Inactive",
|
|
3380
|
+
statusOnDemand: "On demand",
|
|
3381
|
+
activeSwitch: (name) => `Active: \u201C${name}\u201D`,
|
|
3382
|
+
agent: "Agent",
|
|
3383
|
+
myAssistant: "My assistant",
|
|
3384
|
+
me: "Me",
|
|
3385
|
+
someone: "Someone",
|
|
3386
|
+
never: "Never",
|
|
3387
|
+
none: "\u2014",
|
|
3388
|
+
reminder: "Reminder",
|
|
3389
|
+
failed: "Failed",
|
|
3390
|
+
lastRunFailed: "Last run failed",
|
|
3391
|
+
openLastRun: "Open the task this run created",
|
|
3392
|
+
editWorkflow: "Edit",
|
|
3393
|
+
run: "Run",
|
|
3394
|
+
runLater: "Run later",
|
|
3395
|
+
runNow: "Run now",
|
|
3396
|
+
runs: "Runs",
|
|
3397
|
+
delete: "Delete",
|
|
3398
|
+
moreActions: "More actions",
|
|
3399
|
+
searchLabel: "Search workflows",
|
|
3400
|
+
searchPlaceholder: "Search workflows and skills\u2026",
|
|
3401
|
+
emptyTitle: "Nothing to run yet",
|
|
3402
|
+
emptyMessage: "Skills and workflows you can run will appear here.",
|
|
3403
|
+
firstRun: "Run a skill now, or choose Run later to save it as a workflow that runs on its own.",
|
|
3404
|
+
noMatches: "Nothing in this view.",
|
|
3405
|
+
filterAll: "All",
|
|
3406
|
+
filterSkills: "Skills",
|
|
3407
|
+
filterWorkflows: "Workflows",
|
|
3408
|
+
filterActive: "Active",
|
|
3409
|
+
filterPaused: "Inactive",
|
|
3410
|
+
makeActive: "Make active",
|
|
3411
|
+
makePaused: "Deactivate",
|
|
3412
|
+
selectAll: "Select all",
|
|
3413
|
+
selectWorkflow: (name) => `Select ${name}`
|
|
3414
|
+
};
|
|
3415
|
+
var ROW_HEIGHT = 40;
|
|
3416
|
+
function WorkflowsTable(props) {
|
|
3417
|
+
const { workflows, isLoading, busyId, header, testId } = props;
|
|
3418
|
+
const l = { ...DEFAULT_WORKFLOW_LIST_LABELS, ...props.labels };
|
|
3419
|
+
const [filterStates, setFilterStates] = react.useState(/* @__PURE__ */ new Map());
|
|
3420
|
+
const [filterOpen, setFilterOpen] = react.useState(false);
|
|
3421
|
+
const [query, setQuery] = react.useState("");
|
|
3422
|
+
const [selected, setSelected] = react.useState([]);
|
|
3423
|
+
const apiRef = react.useRef(null);
|
|
3424
|
+
const q = query.trim().toLowerCase();
|
|
3425
|
+
const matches = (w) => !q || `${w.name} ${w.description ?? ""} ${w.prompt ?? ""} ${w.skill_ref ?? ""}`.toLowerCase().includes(q);
|
|
3426
|
+
const inFilter = (w, f) => f === "all" || f === "skills" && isSkillRow(w) || f === "workflows" && !isSkillRow(w) || f === "active" && workflowStatus(w) === "active" || f === "paused" && workflowStatus(w) === "paused";
|
|
3427
|
+
const counts = react.useMemo(() => {
|
|
3428
|
+
const out = { all: 0, skills: 0, workflows: 0, active: 0, paused: 0 };
|
|
3429
|
+
for (const w of workflows) {
|
|
3430
|
+
if (!matches(w)) continue;
|
|
3431
|
+
for (const f of Object.keys(out)) if (inFilter(w, f)) out[f] += 1;
|
|
3432
|
+
}
|
|
3433
|
+
return out;
|
|
3434
|
+
}, [workflows, q]);
|
|
3435
|
+
const shown = react.useMemo(
|
|
3436
|
+
() => workflows.filter((w) => {
|
|
3437
|
+
if (!matches(w)) return false;
|
|
3438
|
+
for (const group of [
|
|
3439
|
+
["skills", "workflows"],
|
|
3440
|
+
["active", "paused"]
|
|
3441
|
+
]) {
|
|
3442
|
+
const included = group.filter((f) => filterStates.get(f) === "include");
|
|
3443
|
+
if (included.length && !included.some((f) => inFilter(w, f))) return false;
|
|
3444
|
+
if (group.some((f) => filterStates.get(f) === "exclude" && inFilter(w, f))) return false;
|
|
3445
|
+
}
|
|
3446
|
+
return true;
|
|
3447
|
+
}),
|
|
3448
|
+
[workflows, filterStates, q]
|
|
3449
|
+
);
|
|
3450
|
+
const renderPerson = props.renderPerson ?? ((p) => /* @__PURE__ */ jsxRuntime.jsx(PersonPill, { person: p }));
|
|
3451
|
+
const actionText = (w) => {
|
|
3452
|
+
if (w.action)
|
|
3453
|
+
return w.action.type === "email_documents" ? "Email latest documents" : "AI Review";
|
|
3454
|
+
if (isSkillRow(w))
|
|
3455
|
+
return w.description || w.skill_ref && props.skillNames?.[w.skill_ref] || w.name;
|
|
3456
|
+
return w.skill_ref ? props.skillNames?.[w.skill_ref] ?? w.skill_ref : w.prompt?.trim() || l.reminder;
|
|
3457
|
+
};
|
|
3458
|
+
const latest = react.useRef({ props, l, renderPerson, actionText });
|
|
3459
|
+
latest.current = { props, l, renderPerson, actionText };
|
|
3460
|
+
const columnDefs = react.useMemo(
|
|
3461
|
+
() => createWorkflowColumns({
|
|
3462
|
+
labels: l,
|
|
3463
|
+
getTriggerText: (w) => isSkillRow(w) ? l.statusOnDemand : latest.current.props.describeTrigger(w),
|
|
3464
|
+
renderName: (w) => {
|
|
3465
|
+
const { l: lb } = latest.current;
|
|
3466
|
+
const skill = isSkillRow(w);
|
|
3467
|
+
const text = skill ? latest.current.actionText(w) : w.description || latest.current.actionText(w);
|
|
3468
|
+
const stem = w.name.replace(/…$/, "").trim();
|
|
3469
|
+
const about = text && text.trim() !== w.name.trim() && text.trim() !== stem ? text : "";
|
|
3470
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 leading-tight", children: [
|
|
3471
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
3472
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3473
|
+
"span",
|
|
3474
|
+
{
|
|
3475
|
+
className: ui.cn(
|
|
3476
|
+
"truncate text-sm font-normal",
|
|
3477
|
+
workflowStatus(w) === "paused" && "text-muted-foreground"
|
|
3478
|
+
),
|
|
3479
|
+
"data-testid": `workflow-name-${w.external_id}`,
|
|
3480
|
+
children: w.name
|
|
3481
|
+
}
|
|
3482
|
+
),
|
|
3483
|
+
skill && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3484
|
+
"span",
|
|
3485
|
+
{
|
|
3486
|
+
className: "shrink-0 rounded-full border border-border px-1.5 text-[11px] text-muted-foreground",
|
|
3487
|
+
"data-testid": `workflow-type-${w.external_id}`,
|
|
3488
|
+
children: lb.typeSkill
|
|
3489
|
+
}
|
|
3490
|
+
)
|
|
3491
|
+
] }),
|
|
3492
|
+
about && !latest.current.props.automationsOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3493
|
+
"p",
|
|
3494
|
+
{
|
|
3495
|
+
className: "truncate text-xs text-muted-foreground",
|
|
3496
|
+
"data-testid": `workflow-action-${w.external_id}`,
|
|
3497
|
+
children: about
|
|
3498
|
+
}
|
|
3499
|
+
)
|
|
3500
|
+
] });
|
|
3501
|
+
},
|
|
3502
|
+
renderTrigger: (w) => {
|
|
3503
|
+
const { props: p } = latest.current;
|
|
3504
|
+
const after = w.after_conversation_ext_id;
|
|
3505
|
+
const skill = isSkillRow(w);
|
|
3506
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 leading-tight", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3507
|
+
TaskTriggerChip,
|
|
3508
|
+
{
|
|
3509
|
+
id: w.external_id,
|
|
3510
|
+
testId: `workflow-trigger-${w.external_id}`,
|
|
3511
|
+
triggerType: workflowTriggerType(w),
|
|
3512
|
+
summary: skill ? "" : p.describeTrigger(w),
|
|
3513
|
+
afterTaskId: after,
|
|
3514
|
+
afterTaskName: after ? p.taskNames?.[after] : void 0,
|
|
3515
|
+
labels: p.triggerChipLabels
|
|
3516
|
+
}
|
|
3517
|
+
) });
|
|
3518
|
+
},
|
|
3519
|
+
renderStatus: (w) => {
|
|
3520
|
+
const { props: p, l: lb } = latest.current;
|
|
3521
|
+
const canEdit = w.is_owner !== false || Boolean(p.canEditShared);
|
|
3522
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3523
|
+
ui.Switch,
|
|
3524
|
+
{
|
|
3525
|
+
checked: hasTrigger(w) && !isSkillRow(w) && Boolean(w.active),
|
|
3526
|
+
disabled: !hasTrigger(w) || isSkillRow(w) || !canEdit || p.busyId === w.external_id,
|
|
3527
|
+
onCheckedChange: (next) => p.onToggleActive(w, next),
|
|
3528
|
+
className: "disabled:data-[state=unchecked]:bg-muted dark:disabled:data-[state=unchecked]:bg-muted",
|
|
3529
|
+
"aria-label": lb.activeSwitch(w.name),
|
|
3530
|
+
"data-testid": `workflow-active-${w.external_id}`
|
|
3531
|
+
}
|
|
3532
|
+
);
|
|
3533
|
+
},
|
|
3534
|
+
renderShared: (w) => {
|
|
3535
|
+
const { props: p, l: lb } = latest.current;
|
|
3536
|
+
if (!p.onToggleShared || isSkillRow(w)) return null;
|
|
3537
|
+
const isCreator = w.is_owner !== false;
|
|
3538
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3539
|
+
ui.VisibilityToggle,
|
|
3540
|
+
{
|
|
3541
|
+
items: { shared: w.shared ?? false },
|
|
3542
|
+
onToggle: (share) => latest.current.props.onToggleShared?.(w, share),
|
|
3543
|
+
disabled: !isCreator || p.busyId === w.external_id,
|
|
3544
|
+
disabledTooltip: lb.sharedOwnerOnly,
|
|
3545
|
+
showLabel: false,
|
|
3546
|
+
"data-testid": `workflow-shared-${w.external_id}`
|
|
3547
|
+
}
|
|
3548
|
+
);
|
|
3549
|
+
},
|
|
3550
|
+
renderLastRun: (w) => {
|
|
3551
|
+
const { props: p, l: lb } = latest.current;
|
|
3552
|
+
const at = w.last_fired_at ?? p.lastRuns?.[w.external_id]?.at;
|
|
3553
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3554
|
+
"button",
|
|
3555
|
+
{
|
|
3556
|
+
type: "button",
|
|
3557
|
+
className: "h-full w-full truncate px-4 text-left text-sm hover:text-primary",
|
|
3558
|
+
onClick: () => p.onViewRuns?.(w),
|
|
3559
|
+
title: "View run history",
|
|
3560
|
+
"data-testid": `workflow-last-run-${w.external_id}`,
|
|
3561
|
+
children: at ? p.formatDate(at) : lb.never
|
|
3562
|
+
}
|
|
3563
|
+
);
|
|
3564
|
+
},
|
|
3565
|
+
renderResult: (w) => {
|
|
3566
|
+
const status = listedRunStatus(
|
|
3567
|
+
w.last_run_status,
|
|
3568
|
+
latest.current.props.lastRuns?.[w.external_id]?.threadStatus
|
|
3569
|
+
);
|
|
3570
|
+
const label = workflowRunStatusLabel(status);
|
|
3571
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3572
|
+
"button",
|
|
3573
|
+
{
|
|
3574
|
+
type: "button",
|
|
3575
|
+
onClick: () => latest.current.props.onViewRuns?.(w),
|
|
3576
|
+
title: "View run history",
|
|
3577
|
+
className: ui.cn(
|
|
3578
|
+
ui.badgeVariants({ variant: "outline" }),
|
|
3579
|
+
"mx-4 cursor-pointer text-xs font-medium",
|
|
3580
|
+
status === "failed" ? "border-red-border bg-red-bg text-red-text hover:bg-red-bg/80" : status === "completed" || status === "success" ? "border-green-border bg-green-bg text-green-text hover:bg-green-bg/80" : status ? "border-primary/20 bg-primary/10 text-primary hover:bg-primary/15" : "border-border bg-muted text-muted-foreground hover:bg-muted/80"
|
|
3581
|
+
),
|
|
3582
|
+
"data-testid": `workflow-result-${w.external_id}`,
|
|
3583
|
+
children: label
|
|
3584
|
+
}
|
|
3585
|
+
);
|
|
3586
|
+
},
|
|
3587
|
+
renderActions: (w) => {
|
|
3588
|
+
const { props: p, l: lb } = latest.current;
|
|
3589
|
+
const id = w.external_id;
|
|
3590
|
+
const skill = isSkillRow(w);
|
|
3591
|
+
const busy = p.busyId === id;
|
|
3592
|
+
const isOwner = w.is_owner !== false;
|
|
3593
|
+
const canEdit = isOwner || Boolean(p.canEditShared);
|
|
3594
|
+
const canAdmin = isOwner || Boolean(p.isWorkspaceOwner);
|
|
3595
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-1", children: [
|
|
3596
|
+
(skill || canEdit) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3597
|
+
ui.Button,
|
|
3598
|
+
{
|
|
3599
|
+
size: "sm",
|
|
3600
|
+
variant: "outline",
|
|
3601
|
+
className: "h-8 gap-1.5 pointer-coarse:h-11",
|
|
3602
|
+
disabled: busy,
|
|
3603
|
+
onClick: () => p.onRun(w),
|
|
3604
|
+
"data-testid": `workflow-run-btn-${id}`,
|
|
3605
|
+
children: [
|
|
3606
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "size-3.5", "aria-hidden": true }),
|
|
3607
|
+
lb.run
|
|
3608
|
+
]
|
|
3609
|
+
}
|
|
3610
|
+
),
|
|
3611
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
|
|
3612
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3613
|
+
ui.Button,
|
|
3614
|
+
{
|
|
3615
|
+
variant: "ghost",
|
|
3616
|
+
size: "icon",
|
|
3617
|
+
className: "size-8 pointer-coarse:size-11",
|
|
3618
|
+
"aria-label": lb.moreActions,
|
|
3619
|
+
"data-testid": `workflow-menu-${id}`,
|
|
3620
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "size-4", "aria-hidden": true })
|
|
3621
|
+
}
|
|
3622
|
+
) }),
|
|
3623
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenuContent, { align: "end", children: [
|
|
3624
|
+
skill && p.onRunLater && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3625
|
+
ui.DropdownMenuItem,
|
|
3626
|
+
{
|
|
3627
|
+
onSelect: () => p.onRunLater?.(w),
|
|
3628
|
+
"data-testid": `workflow-run-later-${id}`,
|
|
3629
|
+
children: [
|
|
3630
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "mr-2 size-4", "aria-hidden": true }),
|
|
3631
|
+
lb.runLater
|
|
3632
|
+
]
|
|
3633
|
+
}
|
|
3634
|
+
),
|
|
3635
|
+
!skill && canEdit && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3636
|
+
ui.DropdownMenuItem,
|
|
3637
|
+
{
|
|
3638
|
+
onSelect: () => p.onEdit(w),
|
|
3639
|
+
"data-testid": `workflow-edit-${id}`,
|
|
3640
|
+
children: [
|
|
3641
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "mr-2 size-4", "aria-hidden": true }),
|
|
3642
|
+
lb.editWorkflow
|
|
3643
|
+
]
|
|
3644
|
+
}
|
|
3645
|
+
),
|
|
3646
|
+
!skill && p.onViewRuns && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3647
|
+
ui.DropdownMenuItem,
|
|
3648
|
+
{
|
|
3649
|
+
onSelect: () => p.onViewRuns?.(w),
|
|
3650
|
+
"data-testid": `workflow-runs-${id}`,
|
|
3651
|
+
children: [
|
|
3652
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "mr-2 size-4", "aria-hidden": true }),
|
|
3653
|
+
lb.runs
|
|
3654
|
+
]
|
|
3655
|
+
}
|
|
3656
|
+
),
|
|
3657
|
+
!skill && canEdit && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3658
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenuSeparator, {}),
|
|
3659
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3660
|
+
ui.DropdownMenuItem,
|
|
3661
|
+
{
|
|
3662
|
+
disabled: busy || !canAdmin,
|
|
3663
|
+
onSelect: () => p.onDelete(w),
|
|
3664
|
+
title: canAdmin ? void 0 : lb.deleteOwnerOnly,
|
|
3665
|
+
className: "text-destructive focus:text-destructive",
|
|
3666
|
+
"data-testid": `workflow-delete-${id}`,
|
|
3667
|
+
children: [
|
|
3668
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "mr-2 size-4", "aria-hidden": true }),
|
|
3669
|
+
lb.delete
|
|
3670
|
+
]
|
|
3671
|
+
}
|
|
3672
|
+
)
|
|
3673
|
+
] })
|
|
3674
|
+
] })
|
|
3675
|
+
] })
|
|
3676
|
+
] });
|
|
3677
|
+
}
|
|
3678
|
+
}),
|
|
3679
|
+
// Stable on purpose: only the header texts rebuild the columns (see `latest`).
|
|
3680
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3681
|
+
[
|
|
3682
|
+
l.colName,
|
|
3683
|
+
l.colType,
|
|
3684
|
+
l.colTrigger,
|
|
3685
|
+
l.colAction,
|
|
3686
|
+
l.colAgent,
|
|
3687
|
+
l.colStatus,
|
|
3688
|
+
l.colShared,
|
|
3689
|
+
l.shared,
|
|
3690
|
+
l.colLastRun,
|
|
3691
|
+
l.colNextRun
|
|
3692
|
+
]
|
|
3693
|
+
);
|
|
3694
|
+
react.useEffect(() => {
|
|
3695
|
+
apiRef.current?.refreshCells({ force: true });
|
|
3696
|
+
}, [
|
|
3697
|
+
busyId,
|
|
3698
|
+
props.agentNames,
|
|
3699
|
+
props.skillNames,
|
|
3700
|
+
props.taskNames,
|
|
3701
|
+
props.lastRuns,
|
|
3702
|
+
props.renderPerson,
|
|
3703
|
+
props.labels,
|
|
3704
|
+
props.canEditShared,
|
|
3705
|
+
props.isWorkspaceOwner
|
|
3706
|
+
]);
|
|
3707
|
+
const mine = selected.filter((w) => !isSkillRow(w));
|
|
3708
|
+
const adminSelected = mine.filter((w) => w.is_owner !== false || props.isWorkspaceOwner);
|
|
3709
|
+
const editableSelected = mine.filter(
|
|
3710
|
+
(w) => hasTrigger(w) && (w.is_owner !== false || props.canEditShared)
|
|
3711
|
+
);
|
|
3712
|
+
const clearSelection = () => setSelected([]);
|
|
3713
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3714
|
+
"div",
|
|
3715
|
+
{
|
|
3716
|
+
className: "flex min-h-0 flex-1 flex-col",
|
|
3717
|
+
"data-testid": chunkMHVNT4J3_cjs.testIdOr(testId, { testId: "workflow-list" }),
|
|
3718
|
+
children: [
|
|
3719
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3720
|
+
chunk7RGLTF76_cjs.TabHeader,
|
|
3721
|
+
{
|
|
3722
|
+
testId: "automations-tab-header",
|
|
3723
|
+
tabs: [
|
|
3724
|
+
{
|
|
3725
|
+
id: "automations",
|
|
3726
|
+
label: "",
|
|
3727
|
+
count: shown.length,
|
|
3728
|
+
countIcon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Workflow, { className: "size-3.5" }),
|
|
3729
|
+
countPlacement: "leading",
|
|
3730
|
+
presentation: "count",
|
|
3731
|
+
hasActiveFilters: !!q || [...filterStates.values()].some(Boolean)
|
|
3732
|
+
},
|
|
3733
|
+
...props.tabs ?? []
|
|
3734
|
+
],
|
|
3735
|
+
activeTabId: props.activeTabId ?? "automations",
|
|
3736
|
+
onTabChange: props.onTabChange ?? (() => {
|
|
3737
|
+
}),
|
|
3738
|
+
firstTabContent: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3739
|
+
chunk2EI7NCUA_cjs.FilterInput,
|
|
3740
|
+
{
|
|
3741
|
+
value: query,
|
|
3742
|
+
onChange: setQuery,
|
|
3743
|
+
fields: ["text"],
|
|
3744
|
+
onFieldsChange: () => {
|
|
3745
|
+
},
|
|
3746
|
+
hideFieldPicker: true,
|
|
3747
|
+
ariaLabel: l.searchLabel,
|
|
3748
|
+
testIds: { input: "workflow-search" },
|
|
3749
|
+
filter: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3750
|
+
chunkRQ2Y7USX_cjs.TriStateFilterMenu,
|
|
3751
|
+
{
|
|
3752
|
+
testId: "automations-filter-button",
|
|
3753
|
+
open: filterOpen,
|
|
3754
|
+
onOpenChange: setFilterOpen,
|
|
3755
|
+
filterStates,
|
|
3756
|
+
onFiltersChange: setFilterStates,
|
|
3757
|
+
triggerClassName: "flex h-5 items-center gap-0.5 rounded px-1 text-muted-foreground hover:text-foreground pointer-coarse:h-11! pointer-coarse:min-w-11 pointer-coarse:justify-center",
|
|
3758
|
+
renderChevron: true,
|
|
3759
|
+
disableHoverOpen: true,
|
|
3760
|
+
options: [
|
|
3761
|
+
...!props.automationsOnly ? [
|
|
3762
|
+
{ id: "skills", label: l.filterSkills, count: counts.skills },
|
|
3763
|
+
{
|
|
3764
|
+
id: "workflows",
|
|
3765
|
+
label: l.filterWorkflows,
|
|
3766
|
+
count: counts.workflows
|
|
3767
|
+
}
|
|
3768
|
+
] : [],
|
|
3769
|
+
{ id: "active", label: l.filterActive, count: counts.active },
|
|
3770
|
+
{ id: "paused", label: l.filterPaused, count: counts.paused }
|
|
3771
|
+
]
|
|
3772
|
+
}
|
|
3773
|
+
)
|
|
3774
|
+
}
|
|
3775
|
+
),
|
|
3776
|
+
rightContent: header
|
|
3777
|
+
}
|
|
3778
|
+
),
|
|
3779
|
+
props.content ? props.content : workflows.length === 0 && !isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3780
|
+
chunkZW6FPIFC_cjs.EmptyState,
|
|
3781
|
+
{
|
|
3782
|
+
icon: lucideReact.Workflow,
|
|
3783
|
+
title: l.emptyTitle,
|
|
3784
|
+
description: l.emptyMessage,
|
|
3785
|
+
testId: "workflow-list-empty"
|
|
3786
|
+
}
|
|
3787
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3788
|
+
chunkC2CWWEHO_cjs.GridView,
|
|
3789
|
+
{
|
|
3790
|
+
testId: "workflow-grid",
|
|
3791
|
+
gridId: props.gridId ?? "workflows-grid-v2",
|
|
3792
|
+
items: shown,
|
|
3793
|
+
columnDefs,
|
|
3794
|
+
getItemId: (w) => w.external_id,
|
|
3795
|
+
getRowTestId: (w) => `workflow-row-${w.external_id}`,
|
|
3796
|
+
isLoading,
|
|
3797
|
+
showEmpty: shown.length === 0,
|
|
3798
|
+
emptyState: { title: l.noMatches },
|
|
3799
|
+
rowHeight: ROW_HEIGHT,
|
|
3800
|
+
height: "100%",
|
|
3801
|
+
onGridReady: ({ api }) => {
|
|
3802
|
+
apiRef.current = api;
|
|
3803
|
+
},
|
|
3804
|
+
onRowClick: (row) => props.onOpenRow?.(row),
|
|
3805
|
+
selection: { mode: "multiple", selected, onSelectionChange: setSelected },
|
|
3806
|
+
gridOptions: GRID_OPTIONS
|
|
3807
|
+
}
|
|
3808
|
+
) }),
|
|
3809
|
+
!props.content && /* @__PURE__ */ jsxRuntime.jsx(chunkV4ISCZJ7_cjs.SelectionBar, { count: selected.length, onClear: clearSelection, children: (isCompact) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3810
|
+
props.onToggleActiveMany && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3811
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3812
|
+
chunkV4ISCZJ7_cjs.SelectionBarAction,
|
|
3813
|
+
{
|
|
3814
|
+
icon: lucideReact.Play,
|
|
3815
|
+
label: l.makeActive,
|
|
3816
|
+
onClick: () => {
|
|
3817
|
+
props.onToggleActiveMany?.(editableSelected, true);
|
|
3818
|
+
clearSelection();
|
|
3819
|
+
},
|
|
3820
|
+
disabled: editableSelected.length === 0,
|
|
3821
|
+
isCompact,
|
|
3822
|
+
testId: "workflow-bulk-activate"
|
|
3823
|
+
}
|
|
3824
|
+
),
|
|
3825
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3826
|
+
chunkV4ISCZJ7_cjs.SelectionBarAction,
|
|
3827
|
+
{
|
|
3828
|
+
icon: lucideReact.Workflow,
|
|
3829
|
+
label: l.makePaused,
|
|
3830
|
+
onClick: () => {
|
|
3831
|
+
props.onToggleActiveMany?.(editableSelected, false);
|
|
3832
|
+
clearSelection();
|
|
3833
|
+
},
|
|
3834
|
+
disabled: editableSelected.length === 0,
|
|
3835
|
+
isCompact,
|
|
3836
|
+
testId: "workflow-bulk-pause"
|
|
3837
|
+
}
|
|
3838
|
+
)
|
|
3839
|
+
] }),
|
|
3840
|
+
props.onDeleteMany && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3841
|
+
chunkV4ISCZJ7_cjs.SelectionBarAction,
|
|
3842
|
+
{
|
|
3843
|
+
icon: lucideReact.Trash2,
|
|
3844
|
+
label: l.delete,
|
|
3845
|
+
onClick: () => {
|
|
3846
|
+
props.onDeleteMany?.(adminSelected);
|
|
3847
|
+
clearSelection();
|
|
3848
|
+
},
|
|
3849
|
+
disabled: adminSelected.length === 0,
|
|
3850
|
+
isCompact,
|
|
3851
|
+
className: "border-red-border text-red-text hover:bg-red-bg hover:text-red-text",
|
|
3852
|
+
testId: "workflow-bulk-delete"
|
|
3853
|
+
}
|
|
3854
|
+
)
|
|
3855
|
+
] }) })
|
|
3856
|
+
]
|
|
3857
|
+
}
|
|
3858
|
+
);
|
|
3859
|
+
}
|
|
3860
|
+
var GRID_OPTIONS = { suppressClickEdit: true };
|
|
2324
3861
|
var DEFAULT_TASK_ACTIVITY_LABELS = {
|
|
2325
3862
|
title: "Activity",
|
|
2326
3863
|
empty: "Nothing has happened yet.",
|
|
@@ -2407,12 +3944,12 @@ function taskActivityHeadline(e, labels = DEFAULT_TASK_ACTIVITY_LABELS, agentNam
|
|
|
2407
3944
|
case "step_skipped":
|
|
2408
3945
|
return "Step skipped";
|
|
2409
3946
|
case "step_waiting": {
|
|
2410
|
-
const documents =
|
|
2411
|
-
return documents ?
|
|
3947
|
+
const documents = chunk6F7SZCVL_cjs.eventWaitingDocuments(detail);
|
|
3948
|
+
return documents ? chunk6F7SZCVL_cjs.waitingForDocumentsText(documents.length) : "Waiting on people";
|
|
2412
3949
|
}
|
|
2413
3950
|
case "step_progress": {
|
|
2414
|
-
const documents =
|
|
2415
|
-
return documents ?
|
|
3951
|
+
const documents = chunk6F7SZCVL_cjs.eventWaitingDocuments(detail);
|
|
3952
|
+
return documents ? chunk6F7SZCVL_cjs.waitingForDocumentsText(documents.length) : detail.signed ? "Signed" : "Step moved on";
|
|
2416
3953
|
}
|
|
2417
3954
|
case "step_sent_back":
|
|
2418
3955
|
return "Sent the work back";
|
|
@@ -2514,13 +4051,22 @@ function TaskActivityTimeline({
|
|
|
2514
4051
|
}
|
|
2515
4052
|
|
|
2516
4053
|
exports.ActionStepBody = ActionStepBody;
|
|
4054
|
+
exports.AgentSelect = AgentSelect;
|
|
2517
4055
|
exports.ApprovalEvidence = ApprovalEvidence;
|
|
2518
4056
|
exports.AssigneeLine = AssigneeLine;
|
|
4057
|
+
exports.DEFAULT_AGENT_SELECT_LABELS = DEFAULT_AGENT_SELECT_LABELS;
|
|
2519
4058
|
exports.DEFAULT_SCHEMA_FORM_LABELS = DEFAULT_SCHEMA_FORM_LABELS;
|
|
2520
4059
|
exports.DEFAULT_STEP_BAR_LABELS = DEFAULT_STEP_BAR_LABELS;
|
|
2521
4060
|
exports.DEFAULT_TASK_ACTIVITY_LABELS = DEFAULT_TASK_ACTIVITY_LABELS;
|
|
4061
|
+
exports.DEFAULT_TASK_TRIGGER_CHIP_LABELS = DEFAULT_TASK_TRIGGER_CHIP_LABELS;
|
|
4062
|
+
exports.DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS = DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS;
|
|
4063
|
+
exports.DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS = DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS;
|
|
4064
|
+
exports.DEFAULT_WORKFLOW_LIST_LABELS = DEFAULT_WORKFLOW_LIST_LABELS;
|
|
2522
4065
|
exports.DEFAULT_WORKFLOW_RUNNER_LABELS = DEFAULT_WORKFLOW_RUNNER_LABELS;
|
|
2523
4066
|
exports.DEFAULT_WORKFLOW_STEP_PARTS_LABELS = DEFAULT_WORKFLOW_STEP_PARTS_LABELS;
|
|
4067
|
+
exports.PersonPill = PersonPill;
|
|
4068
|
+
exports.SKILL_MAIN_FILENAME = SKILL_MAIN_FILENAME;
|
|
4069
|
+
exports.SKILL_TYPES = SKILL_TYPES;
|
|
2524
4070
|
exports.STEP_LABEL = STEP_LABEL;
|
|
2525
4071
|
exports.STEP_LABEL_CURRENT = STEP_LABEL_CURRENT;
|
|
2526
4072
|
exports.STEP_LABEL_MAX = STEP_LABEL_MAX;
|
|
@@ -2528,19 +4074,46 @@ exports.SchemaForm = SchemaForm;
|
|
|
2528
4074
|
exports.SendBackControl = SendBackControl;
|
|
2529
4075
|
exports.StepBarFrame = StepBarFrame;
|
|
2530
4076
|
exports.TaskActivityTimeline = TaskActivityTimeline;
|
|
4077
|
+
exports.TaskTriggerChip = TaskTriggerChip;
|
|
4078
|
+
exports.WORKFLOW_COLUMN_ORDER = WORKFLOW_COLUMN_ORDER;
|
|
4079
|
+
exports.WorkflowConfigDialog = WorkflowConfigDialog;
|
|
4080
|
+
exports.WorkflowDocumentsField = WorkflowDocumentsField;
|
|
4081
|
+
exports.WorkflowLauncher = WorkflowLauncher;
|
|
2531
4082
|
exports.WorkflowRunner = WorkflowRunner;
|
|
2532
4083
|
exports.WorkflowStepBar = WorkflowStepBar;
|
|
4084
|
+
exports.WorkflowsTable = WorkflowsTable;
|
|
2533
4085
|
exports.activeStepId = activeStepId;
|
|
4086
|
+
exports.buildWorkflowScopeSource = buildWorkflowScopeSource;
|
|
4087
|
+
exports.buildZipSkillImport = buildZipSkillImport;
|
|
4088
|
+
exports.createWorkflowColumns = createWorkflowColumns;
|
|
4089
|
+
exports.documentScopeLabels = documentScopeLabels;
|
|
2534
4090
|
exports.fromPlanAssignee = fromPlanAssignee;
|
|
2535
4091
|
exports.fromPlanDocumentRef = fromPlanDocumentRef;
|
|
2536
4092
|
exports.fromPlanSteps = fromPlanSteps;
|
|
4093
|
+
exports.hasTrigger = hasTrigger;
|
|
4094
|
+
exports.importMarkdownSkill = importMarkdownSkill;
|
|
4095
|
+
exports.importSkillFile = importSkillFile;
|
|
4096
|
+
exports.importSkillFromUrl = importSkillFromUrl;
|
|
2537
4097
|
exports.isIncompleteSignal = isIncompleteSignal;
|
|
4098
|
+
exports.isMainSkillFile = isMainSkillFile;
|
|
4099
|
+
exports.isSkillRow = isSkillRow;
|
|
2538
4100
|
exports.layoutFromPlanSteps = layoutFromPlanSteps;
|
|
4101
|
+
exports.matchWorkflowScope = matchWorkflowScope;
|
|
4102
|
+
exports.parseSkillFrontmatter = parseSkillFrontmatter;
|
|
4103
|
+
exports.readSkillArchive = readSkillArchive;
|
|
4104
|
+
exports.serializeSkill = serializeSkill;
|
|
4105
|
+
exports.skillSlug = skillSlug;
|
|
2539
4106
|
exports.stepWindow = stepWindow;
|
|
2540
4107
|
exports.taskActivityHeadline = taskActivityHeadline;
|
|
2541
4108
|
exports.toPlanAssignee = toPlanAssignee;
|
|
2542
4109
|
exports.toPlanDocumentRef = toPlanDocumentRef;
|
|
2543
4110
|
exports.toPlanSteps = toPlanSteps;
|
|
4111
|
+
exports.useControllableState = useControllableState;
|
|
2544
4112
|
exports.useWorkflowView = useWorkflowView;
|
|
2545
|
-
|
|
2546
|
-
|
|
4113
|
+
exports.workflowFromSkillMarkdown = workflowFromSkillMarkdown;
|
|
4114
|
+
exports.workflowRunStatusLabel = workflowRunStatusLabel;
|
|
4115
|
+
exports.workflowStatus = workflowStatus;
|
|
4116
|
+
exports.workflowToSkillMarkdown = workflowToSkillMarkdown;
|
|
4117
|
+
exports.workflowTriggerType = workflowTriggerType;
|
|
4118
|
+
//# sourceMappingURL=chunk-CHVCTKF4.cjs.map
|
|
4119
|
+
//# sourceMappingURL=chunk-CHVCTKF4.cjs.map
|