@burdenoff/fluidgrids-fe-sdk 2026.1021.9 → 2026.1021.11

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.
@@ -1,5 +1,5 @@
1
- export { ExecutionDetailPage } from './chunk-XOUL22OI.js';
2
- import './chunk-3SCUZ75C.js';
1
+ export { ExecutionDetailPage } from './chunk-QL7CDZ7B.js';
2
+ import './chunk-GU233T6U.js';
3
3
  import './chunk-QBFAJNUC.js';
4
4
  import './chunk-ONVGFVNH.js';
5
5
  import './chunk-JL7CASN5.js';
@@ -1,5 +1,5 @@
1
- export { ExecutionsListPage } from './chunk-OM24EQUG.js';
2
- import './chunk-3SCUZ75C.js';
1
+ export { ExecutionsListPage } from './chunk-YB6WGQTY.js';
2
+ import './chunk-GU233T6U.js';
3
3
  import './chunk-QBFAJNUC.js';
4
4
  import './chunk-O6E247J6.js';
5
5
  import './chunk-D3UWK7GY.js';
@@ -1,4 +1,4 @@
1
- import { useDataSinks, useDataSinkData, useInsightsData, useRunReplayActions } from './chunk-5WSBID2F.js';
1
+ import { useDataSinks, useDataSinkData, useInsightsData, useRunReplayActions } from './chunk-OM5X65LG.js';
2
2
  import { useTr } from './chunk-UULVIT25.js';
3
3
  import { useState, useMemo, useEffect } from 'react';
4
4
  import { Icon } from '@iconify/react';
@@ -122,6 +122,14 @@ var NODE_STATUS_CONFIG = {
122
122
  borderColor: "border-red-200 dark:border-red-800",
123
123
  icon: "mdi:timer-off-outline"
124
124
  },
125
+ // A node parked by a Wait node, an external webhook/form resume, or a person (BOFF-7651).
126
+ WAITING: {
127
+ label: "Waiting",
128
+ color: "text-purple-600 dark:text-purple-400",
129
+ bgColor: "bg-purple-50 dark:bg-purple-900/20",
130
+ borderColor: "border-purple-200 dark:border-purple-800",
131
+ icon: "mdi:timer-sand"
132
+ },
125
133
  WAITING_SUBWORKFLOW: {
126
134
  label: "Waiting",
127
135
  color: "text-purple-600 dark:text-purple-400",
@@ -138,7 +146,7 @@ function ExecutionStatusBadge({
138
146
  animated = true
139
147
  }) {
140
148
  const tr = useTr();
141
- const config = RUN_STATUS_CONFIG[status];
149
+ const config = RUN_STATUS_CONFIG[status] ?? RUN_STATUS_CONFIG.PENDING;
142
150
  const labels = {
143
151
  PENDING: tr(
144
152
  "fluidgrids.executions.executionFilters.statusPending",
@@ -196,7 +204,7 @@ function ExecutionStatusBadge({
196
204
  className: animated && isRunning ? "animate-spin" : ""
197
205
  }
198
206
  ),
199
- showLabel && /* @__PURE__ */ jsx("span", { children: labels[status] })
207
+ showLabel && /* @__PURE__ */ jsx("span", { children: labels[status] ?? config.label })
200
208
  ]
201
209
  }
202
210
  );
@@ -208,7 +216,7 @@ function NodeStatusBadge({
208
216
  showLabel = true,
209
217
  animated = true
210
218
  }) {
211
- const config = NODE_STATUS_CONFIG[status];
219
+ const config = NODE_STATUS_CONFIG[status] ?? NODE_STATUS_CONFIG.PENDING;
212
220
  const sizeClasses = {
213
221
  sm: "px-1.5 py-0.5 text-xs gap-1",
214
222
  md: "px-2 py-1 text-sm gap-1.5",
@@ -1,4 +1,4 @@
1
- import { LogStreamingTab } from './chunk-5WSBID2F.js';
1
+ import { useFluidGridsFlag, FLUIDGRIDS_FLAGS, LogStreamingTab } from './chunk-OM5X65LG.js';
2
2
  import { useFlowStore } from './chunk-EGYJKHAL.js';
3
3
  import { useWorkflowDefinitionQuery, useUpdateWorkflowDefinitionMutation, useWorkflowDefinitionsQuery } from './chunk-L2UWPFJM.js';
4
4
  import { useTr } from './chunk-UULVIT25.js';
@@ -633,6 +633,8 @@ function SettingsPage({
633
633
  const activeWorkflowKey = useFlowStore((s) => s.workflow.workflowKey);
634
634
  const workflowKey = workflowKeyProp || routeParams.workflowKey || routeParams.id || activeWorkflowKey || void 0;
635
635
  const [activeTab, setActiveTab] = useState("general");
636
+ const logStreamsEnabled = useFluidGridsFlag(FLUIDGRIDS_FLAGS.logStreams);
637
+ const visibleTab = !logStreamsEnabled && activeTab === "log-streaming" ? "general" : activeTab;
636
638
  return /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-6 bg-background-primary min-h-screen", children: [
637
639
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6", children: [
638
640
  /* @__PURE__ */ jsxs("div", { children: [
@@ -647,7 +649,7 @@ function SettingsPage({
647
649
  tr("fluidgrids.settings.page.backToWorkflows", "Back to Workflows")
648
650
  ] })
649
651
  ] }),
650
- /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [
652
+ /* @__PURE__ */ jsxs(Tabs, { value: visibleTab, onValueChange: setActiveTab, className: "w-full", children: [
651
653
  /* @__PURE__ */ jsxs(TabsList, { className: "bg-background-secondary border border-border-secondary mb-6", children: [
652
654
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "general", className: "gap-1.5", children: [
653
655
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:cog", width: 16 }),
@@ -661,10 +663,10 @@ function SettingsPage({
661
663
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:bell-outline", width: 16 }),
662
664
  tr("fluidgrids.settings.page.notificationsTab", "Notifications")
663
665
  ] }),
664
- /* @__PURE__ */ jsxs(TabsTrigger, { value: "log-streaming", className: "gap-1.5", children: [
666
+ logStreamsEnabled ? /* @__PURE__ */ jsxs(TabsTrigger, { value: "log-streaming", className: "gap-1.5", children: [
665
667
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:transit-connection-variant", width: 16 }),
666
668
  tr("fluidgrids.settings.page.logStreamingTab", "Log streaming")
667
- ] }),
669
+ ] }) : null,
668
670
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "api", className: "gap-1.5", children: [
669
671
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:api", width: 16 }),
670
672
  tr("fluidgrids.settings.page.apiTab", "API")
@@ -673,7 +675,7 @@ function SettingsPage({
673
675
  /* @__PURE__ */ jsx(TabsContent, { value: "general", children: /* @__PURE__ */ jsx(GeneralTab, {}) }),
674
676
  /* @__PURE__ */ jsx(TabsContent, { value: "execution", children: /* @__PURE__ */ jsx(ExecutionTab, { workflowKey }) }),
675
677
  /* @__PURE__ */ jsx(TabsContent, { value: "notifications", children: /* @__PURE__ */ jsx(NotificationsTab, {}) }),
676
- /* @__PURE__ */ jsx(TabsContent, { value: "log-streaming", children: /* @__PURE__ */ jsx(LogStreamingTab, {}) }),
678
+ logStreamsEnabled ? /* @__PURE__ */ jsx(TabsContent, { value: "log-streaming", children: /* @__PURE__ */ jsx(LogStreamingTab, {}) }) : null,
677
679
  /* @__PURE__ */ jsx(TabsContent, { value: "api", children: /* @__PURE__ */ jsx(ApiTab, {}) })
678
680
  ] })
679
681
  ] });
@@ -2,13 +2,25 @@ import { LOG_STREAM_DESTINATIONS, CREATE_LOG_STREAM_DESTINATION, UPDATE_LOG_STRE
2
2
  import { throwIfResultError, describeOperationError } from './chunk-CFCUM4CN.js';
3
3
  import { useTr } from './chunk-UULVIT25.js';
4
4
  import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
5
+ import { useOptionalFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags';
5
6
  import { useCallback, useState, useMemo, useEffect } from 'react';
6
7
  import { Icon } from '@iconify/react';
7
8
  import { toast } from 'sonner';
8
9
  import { Button } from '@burdenoff/fe-libs/button';
9
- import { Card, CardHeader, CardContent, Label, Input } from '@burdenoff/fe-libs/ui';
10
- import { jsxs, jsx } from 'react/jsx-runtime';
10
+ import { Card, CardContent, CardHeader, Label, Input } from '@burdenoff/fe-libs/ui';
11
+ import { jsx, jsxs } from 'react/jsx-runtime';
11
12
 
13
+ var FLUIDGRIDS_FLAGS = {
14
+ /**
15
+ * Operational kill switch for log stream destinations (webhook, syslog,
16
+ * Sentry). Defaults on; an admin turning it off hides the Log streaming
17
+ * settings and the backend rejects destination writes with FEATURE_DISABLED.
18
+ */
19
+ logStreams: "fluidgrids.log-streams"
20
+ };
21
+ function useFluidGridsFlag(flag) {
22
+ return useOptionalFeatureFlag(flag, true);
23
+ }
12
24
  function useAsyncRefresh(fetcher, initial) {
13
25
  const [data, setData] = useState(initial);
14
26
  const [loading, setLoading] = useState(true);
@@ -306,6 +318,42 @@ function formToInput(form) {
306
318
  };
307
319
  }
308
320
  function LogStreamingTab() {
321
+ const enabled = useFluidGridsFlag(FLUIDGRIDS_FLAGS.logStreams);
322
+ if (!enabled) return /* @__PURE__ */ jsx(LogStreamingDisabledNotice, {});
323
+ return /* @__PURE__ */ jsx(LogStreamingSettings, {});
324
+ }
325
+ function LogStreamingDisabledNotice() {
326
+ const tr = useTr();
327
+ return /* @__PURE__ */ jsx(
328
+ Card,
329
+ {
330
+ className: "bg-background-secondary border-border-secondary",
331
+ "data-testid": "log-streaming-disabled",
332
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "flex items-start gap-3 p-6", children: [
333
+ /* @__PURE__ */ jsx(
334
+ Icon,
335
+ {
336
+ icon: "mdi:transit-connection-variant",
337
+ width: 20,
338
+ className: "mt-0.5 shrink-0 text-text-tertiary",
339
+ "aria-hidden": "true"
340
+ }
341
+ ),
342
+ /* @__PURE__ */ jsxs("div", { children: [
343
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-text-primary", children: tr(
344
+ "fluidgrids.settings.logStreaming.disabledTitle",
345
+ "Log streaming is turned off"
346
+ ) }),
347
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-text-secondary", children: tr(
348
+ "fluidgrids.settings.logStreaming.disabledBody",
349
+ "An administrator has turned off log streaming for this workspace. Run events are not forwarded to external destinations."
350
+ ) })
351
+ ] })
352
+ ] })
353
+ }
354
+ );
355
+ }
356
+ function LogStreamingSettings() {
309
357
  const tr = useTr();
310
358
  const { destinations, loading, error, refetch } = useLogStreamDestinations();
311
359
  const actions = useLogStreamDestinationActions();
@@ -724,4 +772,4 @@ function LogStreamingTab() {
724
772
  ] });
725
773
  }
726
774
 
727
- export { LogStreamingTab, useDataSinkData, useDataSinks, useInsightsData, useLogStreamDestinationActions, useLogStreamDestinations, useRunReplayActions };
775
+ export { FLUIDGRIDS_FLAGS, LogStreamingTab, useDataSinkData, useDataSinks, useFluidGridsFlag, useInsightsData, useLogStreamDestinationActions, useLogStreamDestinations, useRunReplayActions };
@@ -1,4 +1,4 @@
1
- import { useExecution, buildNodeDisplayMap, useExecutionActions, useAutoRefresh, ExecutionStatusBadge, formatRunVersion, NodeTimeline, RunLogViewer } from './chunk-3SCUZ75C.js';
1
+ import { useExecution, buildNodeDisplayMap, useExecutionActions, useAutoRefresh, ExecutionStatusBadge, formatRunVersion, NodeTimeline, RunLogViewer } from './chunk-GU233T6U.js';
2
2
  import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS } from './chunk-ONVGFVNH.js';
3
3
  import { getFluidGridsConfig } from './chunk-UZG3ZIQM.js';
4
4
  import { RunLogsDocument, RunLogAppendedDocument } from './chunk-L2UWPFJM.js';
@@ -165,6 +165,38 @@ function useRunLogs(runId, options = {}) {
165
165
  refetch
166
166
  };
167
167
  }
168
+
169
+ // src/modules/human-response/utils/recipient.ts
170
+ var USER_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
171
+ function recipientParts(recipient) {
172
+ return (recipient ?? "").split(",").map((part) => part.trim()).filter(Boolean);
173
+ }
174
+ function inAppResponderIds(recipient) {
175
+ return [
176
+ ...new Set(recipientParts(recipient).filter((part) => USER_ID.test(part)))
177
+ ];
178
+ }
179
+
180
+ // src/modules/human-response/hooks/useRecipientLabel.ts
181
+ function useRecipientLabel(request, fallback) {
182
+ const idsKey = request.channel === "IN_APP" ? inAppResponderIds(request.recipient).join(",") : "";
183
+ const inputs = useMemo(
184
+ () => idsKey ? idsKey.split(",").map((actorId) => ({ actorId, actorType: "user" })) : [],
185
+ [idsKey]
186
+ );
187
+ const config = getFluidGridsConfig();
188
+ const profiles = useActorProfiles(inputs, {
189
+ workspaceId: config.workspaceId || void 0,
190
+ orgId: config.organizationId,
191
+ authToken: config.authToken
192
+ });
193
+ if (!request.recipient) return fallback;
194
+ if (!idsKey) return request.recipient;
195
+ const ids = new Set(idsKey.split(","));
196
+ return recipientParts(request.recipient).map(
197
+ (part) => ids.has(part) ? profiles[part]?.displayName ?? buildActorFallback({ actorId: part, actorType: "user" }).displayName : part
198
+ ).join(", ");
199
+ }
168
200
  var HUMAN_REQUEST_FIELDS = gql`
169
201
  fragment WorkflowHumanRequestFields on WorkflowHumanRequest {
170
202
  id
@@ -446,7 +478,10 @@ function HumanRequestCard({
446
478
  (field) => field.required && !(values[field.name] ?? "").trim()
447
479
  );
448
480
  const emptyText = request.responseType === "FREE_TEXT" && !text.trim();
449
- const recipient = request.channel === "IN_APP" && !request.recipient ? tr("fluidgrids.humanResponse.anyMember", "any workspace member") : request.recipient;
481
+ const recipient = useRecipientLabel(
482
+ request,
483
+ request.channel === "IN_APP" ? tr("fluidgrids.humanResponse.anyMember", "any workspace member") : ""
484
+ );
450
485
  return /* @__PURE__ */ jsxs(
451
486
  Card,
452
487
  {
@@ -474,7 +509,7 @@ function HumanRequestCard({
474
509
  "fluidgrids.humanResponse.askedVia",
475
510
  "Asked {{recipient}} via {{channel}}",
476
511
  {
477
- recipient: recipient ?? "",
512
+ recipient,
478
513
  channel: channelLabel(request.channel, tr)
479
514
  }
480
515
  ),
@@ -640,45 +675,49 @@ function RunHumanRequests({ requests }) {
640
675
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:account-clock-outline", width: 18 }),
641
676
  tr("fluidgrids.humanResponse.runHeading", "Waiting on people")
642
677
  ] }),
643
- requests.map((request) => {
644
- const answer = answerRows(request, tr);
645
- const recipient = request.recipient || tr("fluidgrids.humanResponse.anyMember", "any workspace member");
646
- return /* @__PURE__ */ jsxs(
647
- "div",
648
- {
649
- className: "flex flex-col gap-0.5 text-sm sm:flex-row sm:flex-wrap sm:items-baseline sm:gap-x-2",
650
- "data-testid": "run-human-request",
651
- "data-status": request.status,
652
- children: [
653
- /* @__PURE__ */ jsx("span", { className: "font-medium text-text-primary", children: request.title }),
654
- /* @__PURE__ */ jsxs("span", { className: "text-text-secondary", children: [
655
- tr(
656
- "fluidgrids.humanResponse.askedVia",
657
- "Asked {{recipient}} via {{channel}}",
658
- { recipient, channel: channelLabel(request.channel, tr) }
659
- ),
660
- " \xB7 ",
661
- outcome(request, tr)
662
- ] }),
663
- answer.length > 0 && /* @__PURE__ */ jsx(
664
- "dl",
665
- {
666
- className: "mt-1 w-full space-y-0.5 text-xs sm:mt-0",
667
- "data-testid": "run-human-answer",
668
- children: answer.map((row) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
669
- /* @__PURE__ */ jsxs("dt", { className: "shrink-0 font-medium text-text-secondary", children: [
670
- row.label,
671
- ":"
672
- ] }),
673
- /* @__PURE__ */ jsx("dd", { className: "whitespace-pre-wrap break-words text-text-primary", children: row.value })
674
- ] }, row.key))
675
- }
676
- )
677
- ]
678
- },
679
- request.id
680
- );
681
- })
678
+ requests.map((request) => /* @__PURE__ */ jsx(RunHumanRequestRow, { request }, request.id))
679
+ ]
680
+ }
681
+ );
682
+ }
683
+ function RunHumanRequestRow({ request }) {
684
+ const tr = useTr();
685
+ const answer = answerRows(request, tr);
686
+ const recipient = useRecipientLabel(
687
+ request,
688
+ tr("fluidgrids.humanResponse.anyMember", "any workspace member")
689
+ );
690
+ return /* @__PURE__ */ jsxs(
691
+ "div",
692
+ {
693
+ className: "flex flex-col gap-0.5 text-sm sm:flex-row sm:flex-wrap sm:items-baseline sm:gap-x-2",
694
+ "data-testid": "run-human-request",
695
+ "data-status": request.status,
696
+ children: [
697
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-primary", children: request.title }),
698
+ /* @__PURE__ */ jsxs("span", { className: "text-text-secondary", children: [
699
+ tr(
700
+ "fluidgrids.humanResponse.askedVia",
701
+ "Asked {{recipient}} via {{channel}}",
702
+ { recipient, channel: channelLabel(request.channel, tr) }
703
+ ),
704
+ " \xB7 ",
705
+ outcome(request, tr)
706
+ ] }),
707
+ answer.length > 0 && /* @__PURE__ */ jsx(
708
+ "dl",
709
+ {
710
+ className: "mt-1 w-full space-y-0.5 text-xs sm:mt-0",
711
+ "data-testid": "run-human-answer",
712
+ children: answer.map((row) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
713
+ /* @__PURE__ */ jsxs("dt", { className: "shrink-0 font-medium text-text-secondary", children: [
714
+ row.label,
715
+ ":"
716
+ ] }),
717
+ /* @__PURE__ */ jsx("dd", { className: "whitespace-pre-wrap break-words text-text-primary", children: row.value })
718
+ ] }, row.key))
719
+ }
720
+ )
682
721
  ]
683
722
  }
684
723
  );
@@ -1,4 +1,4 @@
1
- import { useExecutionsWithStore, useExecutionStats, useExecutionActions, useAutoRefresh, ExecutionStats, ExecutionFilters, ExecutionTable, ExecutionCards, ExecutionTimeline, Pagination } from './chunk-3SCUZ75C.js';
1
+ import { useExecutionsWithStore, useExecutionStats, useExecutionActions, useAutoRefresh, ExecutionStats, ExecutionFilters, ExecutionTable, ExecutionCards, ExecutionTimeline, Pagination } from './chunk-GU233T6U.js';
2
2
  import { useWorkflowDefinitions } from './chunk-O6E247J6.js';
3
3
  import { useExecutionsStore } from './chunk-UZG3ZIQM.js';
4
4
  import { useTr } from './chunk-UULVIT25.js';
@@ -1,7 +1,7 @@
1
1
  import './chunk-AD3BXTJS.js';
2
- export { ExecutionsListPage } from './chunk-OM24EQUG.js';
3
- export { ExecutionDetailPage } from './chunk-XOUL22OI.js';
4
- import './chunk-3SCUZ75C.js';
2
+ export { ExecutionsListPage } from './chunk-YB6WGQTY.js';
3
+ export { ExecutionDetailPage } from './chunk-QL7CDZ7B.js';
4
+ import './chunk-GU233T6U.js';
5
5
  import './chunk-QBFAJNUC.js';
6
6
  import './chunk-ONVGFVNH.js';
7
7
  import './chunk-JL7CASN5.js';