@burdenoff/fluidgrids-fe-sdk 2026.1111.16 → 2026.1111.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/dist/AiStudioPage-BHVEU4Wp.js +774 -0
- package/dist/ApprovalInboxPage-dbBDSJ-f.js +558 -0
- package/dist/DataSinkDashboardPage-1h2QsMzH.js +270 -0
- package/dist/DataTablesPage-BZy2z0LB.js +1690 -0
- package/dist/EntityTagPicker-BqRNsLCQ.js +135 -0
- package/dist/{ExecutionDetailPage-D-0_POAf.js → ExecutionDetailPage-BdcZmLT4.js} +799 -4420
- package/dist/ExecutionDetailPage-DvQ667OE.d.ts +10 -0
- package/dist/ExecutionsListPage-BCUJoAIE.js +2742 -0
- package/dist/{FailureTriagePanel-BHiduL7A.js → FailureTriagePanel-B9hDQymi.js} +4 -97
- package/dist/{FluidGridsProvider-DmvFADFa.js → FluidGridsProvider-dvZSNtSW.js} +10 -350
- package/dist/HistoryPage-BLoRpJ1R.d.ts +6 -0
- package/dist/{HistoryPage-BbUgxx1I.js → HistoryPage-U0tqupBN.js} +6 -4
- package/dist/HumanRequestCard-D-ooVPDn.js +439 -0
- package/dist/{InsightsPage-s6f5bU-8.js → InsightsPage-CALo16eB.js} +17 -328
- package/dist/ManagedAiPolicyAuthority-BxwJ3ptd.js +40 -0
- package/dist/{ManagedAiPolicyAuthority-CGux_DaV.d.ts → ManagedAiPolicyAuthority-DM3t3wNr.d.ts} +1 -5
- package/dist/ManagedAiPolicyAuthorityContext-CNkxIOZ1.js +10 -0
- package/dist/{MissingNodesInstallModal-B-9gHy2K.js → MissingNodesInstallModal-CMybsI8h.js} +3 -2
- package/dist/{NodesPage-ClvhUfbh.js → NodesPage-Bf5PhfBK.js} +7 -3
- package/dist/NodesPage-DEbnz9iU.d.ts +6 -0
- package/dist/{PublishCustomNodeAction-D2F7oN0S.js → PublishCustomNodeAction-5XXnSA3H.js} +3 -45
- package/dist/QuotaExhaustedDialog-7IFSaLyi.js +54 -0
- package/dist/RunnerStatusPill-Ctg4TJcP.js +187 -0
- package/dist/RunnersPage-CLCOCclc.js +467 -0
- package/dist/{ManagedAiPolicyAuthority-DsSaz-vg.js → SettingsPage-CJLZvv4J.js} +743 -773
- package/dist/SettingsPage-DMHQFj5-.d.ts +9 -0
- package/dist/TagFilterSelect-DCBOH6Ou.js +41 -0
- package/dist/TaskQueuesPage-9VgSnLdL.js +951 -0
- package/dist/TemplateCard-DsC0KNH1.js +1416 -0
- package/dist/{TemplateConfigurationModal-D_Mvgxqa.js → TemplateConfigurationModal-BhGWIzpm.js} +3 -2
- package/dist/{TemplateDetailPanel-DfFfUcOe.js → TemplateDetailPanel-D4cUVr-m.js} +3 -3
- package/dist/TemplatePreview-FayF6jxh.js +231 -0
- package/dist/TemplatesPage-BG3H-6v6.d.ts +10 -0
- package/dist/{TemplatesPage-Cku13bav.js → TemplatesPage-CsDNT54N.js} +11 -228
- package/dist/VariablesPage-67WR_lVE.js +949 -0
- package/dist/{VersionDiffDialog-Dq2xlPFI.js → VersionDiffDialog-DSN0mU0f.js} +2 -1
- package/dist/WorkflowBuilder-CPnXEL5J.js +555 -0
- package/dist/{WorkflowSearchRedirect-CaoOOpEl.js → WorkflowBuilder-YXRysvZc.js} +19 -585
- package/dist/{WorkflowProposalCard-8Vr56kQa.js → WorkflowProposalCard-qrEeNyYG.js} +4 -405
- package/dist/WorkflowSearchRedirect-DwDNZ_q5.js +36 -0
- package/dist/WorkflowShareDialog-mbIwRQUY.js +168 -0
- package/dist/WorkflowsList-CcNDQge5.d.ts +6 -0
- package/dist/{WorkflowsList-B2j1Pehb.js → WorkflowsList-DiiGyZkT.js} +12 -6
- package/dist/agent-form-Bfvm32j1.js +83 -0
- package/dist/{agentTools-DJ5o2ekg.js → agentTools-8s_25Q_F.js} +3 -2
- package/dist/{ai-usage-D5p7ZeRR.js → ai-usage-glCwHyQz.js} +1 -1
- package/dist/api-BrCHB5oA.js +224 -0
- package/dist/api-C8e0iV-Q.js +55 -0
- package/dist/button-DG7y_FVJ.js +48 -0
- package/dist/{canvasNoteTools-D3zUdEeg.js → canvasNoteTools-B6pYARgU.js} +2 -2
- package/dist/client-C9XSzSXr.js +1147 -0
- package/dist/code-editor-field-9-GdVE_8.js +111 -0
- package/dist/{codec-client-DstqyzTN.js → codec-client-CJ95Rmqo.js} +1 -1
- package/dist/constants-B2lhWNoN.js +202 -0
- package/dist/constants-XdvUxeWK.d.ts +162 -0
- package/dist/dialog-Cjb4lB4D.js +105 -0
- package/dist/executions.d.ts +1 -1
- package/dist/executions.js +2 -1
- package/dist/feature-flags-DM5myWaD.js +296 -0
- package/dist/flags.d.ts +3 -0
- package/dist/flags.js +4 -0
- package/dist/{flow-builder-DEzT8TQu.js → flow-builder-CZDKRc6f.js} +662 -10716
- package/dist/{node-endpoint-configs-DHFGA5MQ.js → graphql-operation-types-kX-MMjgW.js} +1 -1194
- package/dist/{graphql-types-XcDLtFwU.js → graphql-types-CDKVWH2R.js} +2 -202
- package/dist/history.d.ts +1 -1
- package/dist/history.js +1 -1
- package/dist/{index-DRf25-D3.d.ts → index-6JR2vD9J.d.ts} +33 -215
- package/dist/index-72XFgvbn.d.ts +132 -0
- package/dist/index-BcdtKBM-.d.ts +56 -0
- package/dist/{index-B3BWqafN.d.ts → index-DjiFgEQl.d.ts} +5 -131
- package/dist/index.d.ts +13 -9
- package/dist/index.js +52 -5300
- package/dist/{node-detail-view-LNqeIqN-.js → node-detail-view-CV4ZRwqh.js} +13 -8
- package/dist/node-editor-tab-body-DU-dh35X.js +174 -0
- package/dist/node-endpoint-configs-B5bjNMDW.js +37 -0
- package/dist/node-registry-refresh-Dy0uRg9f.js +84 -0
- package/dist/nodes.d.ts +1 -1
- package/dist/nodes.js +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -1
- package/dist/popover-BJHvrFGR.js +472 -0
- package/dist/{quick-config-panel-D3ogsaFL.js → quick-config-panel-ws3pLvbt.js} +3 -2
- package/dist/rolldown-runtime-hDbaFkMy.js +18 -0
- package/dist/run-display-BycKYSU0.js +46 -0
- package/dist/run-list-links-ByYC0OlV.js +98 -0
- package/dist/schedule-panel-C0mfGQSD.js +7542 -0
- package/dist/settings.d.ts +2 -1
- package/dist/settings.js +2 -1
- package/dist/shared-CMfn30xT.js +196 -0
- package/dist/sidebar-node-editor-CR1PiZO-.js +177 -0
- package/dist/templates.d.ts +1 -1
- package/dist/templates.js +2 -1
- package/dist/theme-provider-B3mIuz2d.js +11 -0
- package/dist/{useAgentDefinitions-NFtLytDR.js → useAgentDefinitions-B0dam3_o.js} +3 -397
- package/dist/useConnections-Cs7LCWEM.js +401 -0
- package/dist/useDurableParity-CzUQMFJ3.js +415 -0
- package/dist/useEntityTags-DhnsZcTl.js +236 -0
- package/dist/{useExecutions-DAzeWHS6.js → useExecutions-9aLuOt1c.js} +4 -3
- package/dist/{useObservability-COCZ0hUS.js → useObservability-CfEw3ZFD.js} +2 -2
- package/dist/{useRunHistory-CsYUbouO.js → useRunHistory-B1xJDwl1.js} +4 -3
- package/dist/{WorkflowShareDialog-6RRDe-_v.js → useWorkflowCodeExport-Bu2QYJzA.js} +7 -210
- package/dist/{useWorkflows-w4Dx2fF2.js → useWorkflows-BlVVu8NM.js} +3 -2
- package/dist/utils-uaL5UVxb.js +65 -0
- package/dist/workflow-builder.d.ts +1 -1
- package/dist/workflow-builder.js +4 -2
- package/dist/workflow-host.d.ts +6 -0
- package/dist/workflow-host.js +9 -0
- package/dist/workflow-pages.d.ts +55 -0
- package/dist/workflow-pages.js +113 -0
- package/dist/workflows-list.d.ts +1 -1
- package/dist/workflows-list.js +1 -1
- package/package.json +13 -1
- package/dist/ExecutionDetailPage-MvsnOnE1.d.ts +0 -4
- package/dist/HistoryPage-BqUizaFv.d.ts +0 -3
- package/dist/NodesPage-C97-9K2Y.d.ts +0 -3
- package/dist/TemplatesPage-D0qnXzHh.d.ts +0 -4
- package/dist/WorkflowsList-0d5GSKdh.d.ts +0 -3
- package/dist/agent-form-BvMWhQ42.js +0 -496
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { At as useSaveStatusStore, Dn as FLUIDGRIDS_FLAGS, Fn as useFluidGridsFlag, Pn as useDurableParityEnabled, Qt as findSaveConflict, Rn as usePhaseCFlags, Zn as getGlobalStoreClient } from "./FluidGridsProvider-DmvFADFa.js";
|
|
4
|
-
import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
5
3
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-B2lhWNoN.js";
|
|
5
|
+
import { n as useManagedAiPolicyAuthority } from "./ManagedAiPolicyAuthorityContext-CNkxIOZ1.js";
|
|
6
|
+
import { Br as WorkflowNotificationSettingsDocument, cr as UpdateWorkflowNotificationSettingsDocument, et as DurableHistoryCapsDocument, ir as UpdateManagedAiWorkspacePolicyDocument, rr as UpdateDurableHistoryCapsDocument, wt as ManagedAiWorkspacePolicyDocument } from "./graphql-operation-types-kX-MMjgW.js";
|
|
7
|
+
import { c as budgetInputValue, d as withBudgetMode, f as EffectBadge, m as useActionPolicies, n as checkCodecServerUrl, p as effectLabel, s as BUDGET_DIMENSIONS, u as withBudgetLimit } from "./codec-client-CJ95Rmqo.js";
|
|
8
|
+
import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient, x as getFluidGridsConfig } from "./client-C9XSzSXr.js";
|
|
9
|
+
import { c as useDurableParityEnabled, f as usePhaseCFlags, l as useFluidGridsFlag, t as FLUIDGRIDS_FLAGS } from "./feature-flags-DM5myWaD.js";
|
|
10
|
+
import { M as saveCodecServerSettings, _ as fetchPauseRules, a as createPauseRule, c as deletePauseRule, f as fetchArchiveSettings, g as fetchCodecServerSettings, j as saveArchiveSettings, l as deleteSearchAttribute, o as createSearchAttribute, r as clearArchiveSettings, x as fetchSearchAttributes } from "./api-BrCHB5oA.js";
|
|
11
|
+
import { i as NativeSelect, o as StatusPill, t as FieldError, u as useResource } from "./shared-CMfn30xT.js";
|
|
12
|
+
import { KF as WorkflowSearchAttributeType } from "./graphql-types-CDKVWH2R.js";
|
|
13
|
+
import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
|
|
14
|
+
import { At as useSaveStatusStore, Qt as findSaveConflict } from "./FluidGridsProvider-dvZSNtSW.js";
|
|
15
|
+
import { a as useLogStreamDestinations, i as useLogStreamDestinationActions } from "./useObservability-CfEw3ZFD.js";
|
|
16
|
+
import { n as useConnections } from "./useConnections-Cs7LCWEM.js";
|
|
17
|
+
import { Nt as useUpdateWorkflowDefinitionMutation, Rt as useWorkflowDefinitionQuery, Vt as useWorkflowDefinitionsQuery, n as useAgentDefinitions } from "./useAgentDefinitions-B0dam3_o.js";
|
|
18
|
+
import { a as formToInput$2, i as emptyAgentForm, n as agentToForm, o as grantDays, r as describeRule, t as AgentFormError } from "./agent-form-Bfvm32j1.js";
|
|
19
|
+
import { i as getGlobalStoreClient } from "./node-registry-refresh-Dy0uRg9f.js";
|
|
8
20
|
import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-JxkBpOeb.js";
|
|
9
|
-
import {
|
|
10
|
-
import { c as budgetInputValue, d as withBudgetMode, f as EffectBadge, m as useActionPolicies, n as checkCodecServerUrl, p as effectLabel, s as BUDGET_DIMENSIONS, u as withBudgetLimit } from "./codec-client-DstqyzTN.js";
|
|
11
|
-
import { a as useLogStreamDestinations, i as useLogStreamDestinationActions } from "./useObservability-COCZ0hUS.js";
|
|
12
|
-
import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
21
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
13
22
|
import { useNavigate, useParams } from "react-router";
|
|
14
23
|
import { Icon } from "@iconify/react";
|
|
15
24
|
import { cn } from "@burdenoff/fe-libs/utils";
|
|
@@ -22,621 +31,190 @@ import { print } from "graphql";
|
|
|
22
31
|
import { clearGraphqlFetchResponseCache, getStoredOrganizationId, getStoredProjectId, getWorkspaceTokenPayload, graphqlFetchPinned, isWorkspaceTokenValidForContext, prepareWorkspaceRequest } from "@burdenoff/fe-libs/shared";
|
|
23
32
|
import { resolveExternalGatewayUrls } from "@burdenoff/fe-libs/shared/config";
|
|
24
33
|
|
|
25
|
-
// src/modules/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
// src/modules/action-policies/utils/policy-form.ts
|
|
35
|
+
const POLICY_EFFECTS = [
|
|
36
|
+
"REQUIRE_APPROVAL",
|
|
37
|
+
"DENY",
|
|
38
|
+
"ALLOW",
|
|
39
|
+
"LOG"
|
|
40
|
+
];
|
|
41
|
+
const POLICY_ENVIRONMENTS = [
|
|
42
|
+
"DEV",
|
|
43
|
+
"STAGING",
|
|
44
|
+
"PROD"
|
|
45
|
+
];
|
|
46
|
+
const CONDITION_OPERATORS = [
|
|
47
|
+
{
|
|
48
|
+
value: "gt",
|
|
49
|
+
label: "is greater than",
|
|
50
|
+
kind: "number"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
value: "gte",
|
|
54
|
+
label: "is at least",
|
|
55
|
+
kind: "number"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: "lt",
|
|
59
|
+
label: "is less than",
|
|
60
|
+
kind: "number"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
value: "lte",
|
|
64
|
+
label: "is at most",
|
|
65
|
+
kind: "number"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
value: "eq",
|
|
69
|
+
label: "equals",
|
|
70
|
+
kind: "single"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
value: "neq",
|
|
74
|
+
label: "does not equal",
|
|
75
|
+
kind: "single"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
value: "in",
|
|
79
|
+
label: "is one of",
|
|
80
|
+
kind: "list"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
value: "not_in",
|
|
84
|
+
label: "is not one of",
|
|
85
|
+
kind: "list"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
value: "contains",
|
|
89
|
+
label: "contains",
|
|
90
|
+
kind: "single"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
value: "count_gt",
|
|
94
|
+
label: "has more items than",
|
|
95
|
+
kind: "number"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
value: "count_gte",
|
|
99
|
+
label: "has at least … items",
|
|
100
|
+
kind: "number"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
value: "count_lt",
|
|
104
|
+
label: "has fewer items than",
|
|
105
|
+
kind: "number"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
value: "count_lte",
|
|
109
|
+
label: "has at most … items",
|
|
110
|
+
kind: "number"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
value: "exists",
|
|
114
|
+
label: "is set",
|
|
115
|
+
kind: "none"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
value: "not_exists",
|
|
119
|
+
label: "is not set",
|
|
120
|
+
kind: "none"
|
|
121
|
+
}
|
|
122
|
+
];
|
|
123
|
+
var PolicyFormError = class extends Error {};
|
|
124
|
+
const OPERATOR_KIND = new Map(CONDITION_OPERATORS.map((operator) => [operator.value, operator.kind]));
|
|
125
|
+
function operatorKind(op) {
|
|
126
|
+
return OPERATOR_KIND.get(op) ?? "single";
|
|
39
127
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
128
|
+
function emptyPolicyForm() {
|
|
129
|
+
return {
|
|
130
|
+
name: "",
|
|
131
|
+
description: "",
|
|
132
|
+
enabled: true,
|
|
133
|
+
priority: "100",
|
|
134
|
+
effect: "REQUIRE_APPROVAL",
|
|
135
|
+
nodeTypes: "",
|
|
136
|
+
operations: "",
|
|
137
|
+
connectionProviders: "",
|
|
138
|
+
workflowTags: "",
|
|
139
|
+
environments: ["PROD"],
|
|
140
|
+
join: "all",
|
|
141
|
+
rows: []
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function splitList(text) {
|
|
145
|
+
return [...new Set(text.split(",").map((item) => item.trim()).filter(Boolean))];
|
|
146
|
+
}
|
|
147
|
+
/** "1500" -> 1500, "true" -> true, "null" -> null, anything else stays text. */
|
|
148
|
+
function parseScalar(text) {
|
|
149
|
+
const trimmed = text.trim();
|
|
150
|
+
if (trimmed === "true") return true;
|
|
151
|
+
if (trimmed === "false") return false;
|
|
152
|
+
if (trimmed === "null") return null;
|
|
153
|
+
if (trimmed !== "" && Number.isFinite(Number(trimmed))) return Number(trimmed);
|
|
154
|
+
return trimmed;
|
|
155
|
+
}
|
|
156
|
+
function formatScalar(value) {
|
|
157
|
+
if (value === null) return "null";
|
|
158
|
+
return String(value);
|
|
159
|
+
}
|
|
160
|
+
function rowToLeaf(row, index) {
|
|
161
|
+
const path = row.path.trim();
|
|
162
|
+
if (!path) throw new PolicyFormError(`Condition ${index + 1} needs a parameter path`);
|
|
163
|
+
switch (operatorKind(row.op)) {
|
|
164
|
+
case "none": return {
|
|
165
|
+
path,
|
|
166
|
+
op: row.op
|
|
167
|
+
};
|
|
168
|
+
case "number": {
|
|
169
|
+
const value = Number(row.value.trim());
|
|
170
|
+
if (row.value.trim() === "" || !Number.isFinite(value)) throw new PolicyFormError(`Condition ${index + 1} needs a number`);
|
|
171
|
+
return {
|
|
172
|
+
path,
|
|
173
|
+
op: row.op,
|
|
174
|
+
value
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
case "list": {
|
|
178
|
+
const values = splitList(row.value).map(parseScalar);
|
|
179
|
+
if (values.length === 0) throw new PolicyFormError(`Condition ${index + 1} needs at least one value`);
|
|
180
|
+
return {
|
|
181
|
+
path,
|
|
182
|
+
op: row.op,
|
|
183
|
+
value: values
|
|
184
|
+
};
|
|
64
185
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
children: tr("fluidgrids.agents.active", "Active")
|
|
98
|
-
})]
|
|
99
|
-
})]
|
|
100
|
-
}),
|
|
101
|
-
/* @__PURE__ */ jsxs("div", {
|
|
102
|
-
className: "space-y-1",
|
|
103
|
-
children: [/* @__PURE__ */ jsx(Label, {
|
|
104
|
-
htmlFor: "agent-description",
|
|
105
|
-
children: tr("fluidgrids.agents.description", "Description")
|
|
106
|
-
}), /* @__PURE__ */ jsx(Textarea, {
|
|
107
|
-
id: "agent-description",
|
|
108
|
-
value: form.description,
|
|
109
|
-
onChange: (e) => setForm({
|
|
110
|
-
...form,
|
|
111
|
-
description: e.target.value
|
|
112
|
-
}),
|
|
113
|
-
rows: 2
|
|
114
|
-
})]
|
|
115
|
-
}),
|
|
116
|
-
/* @__PURE__ */ jsxs("div", {
|
|
117
|
-
className: "space-y-2",
|
|
118
|
-
children: [
|
|
119
|
-
/* @__PURE__ */ jsx(Label, { children: tr("fluidgrids.agents.tools", "Tools the agent may call") }),
|
|
120
|
-
/* @__PURE__ */ jsx("p", {
|
|
121
|
-
className: "text-xs text-text-secondary",
|
|
122
|
-
children: tr("fluidgrids.agents.toolsHelp", "A node type (for example store/slack) and the operations of it the agent may call, separated by commas. Leave the operations empty to allow every operation of that node type. Nothing else can be called.")
|
|
123
|
-
}),
|
|
124
|
-
form.tools.map((row, index) => /* @__PURE__ */ jsxs("div", {
|
|
125
|
-
className: "flex flex-wrap items-center gap-2",
|
|
126
|
-
"data-testid": `agent-definition-tool-${index}`,
|
|
127
|
-
children: [
|
|
128
|
-
/* @__PURE__ */ jsx(Input, {
|
|
129
|
-
className: "w-48",
|
|
130
|
-
placeholder: "store/slack",
|
|
131
|
-
value: row.nodeType,
|
|
132
|
-
onChange: (e) => setTool(index, { nodeType: e.target.value }),
|
|
133
|
-
"aria-label": tr("fluidgrids.agents.nodeType", "Node type")
|
|
134
|
-
}),
|
|
135
|
-
/* @__PURE__ */ jsx(Input, {
|
|
136
|
-
className: "min-w-48 flex-1",
|
|
137
|
-
placeholder: "postMessage, listChannels",
|
|
138
|
-
value: row.operations,
|
|
139
|
-
onChange: (e) => setTool(index, { operations: e.target.value }),
|
|
140
|
-
"aria-label": tr("fluidgrids.agents.operations", "Operations")
|
|
141
|
-
}),
|
|
142
|
-
/* @__PURE__ */ jsx(Button$1, {
|
|
143
|
-
variant: "ghost",
|
|
144
|
-
size: "sm",
|
|
145
|
-
onClick: () => setForm({
|
|
146
|
-
...form,
|
|
147
|
-
tools: form.tools.filter((_, i) => i !== index)
|
|
148
|
-
}),
|
|
149
|
-
"aria-label": tr("fluidgrids.agents.removeTool", "Remove tool"),
|
|
150
|
-
children: /* @__PURE__ */ jsx(Icon, {
|
|
151
|
-
icon: "mdi:close",
|
|
152
|
-
width: 16
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
]
|
|
156
|
-
}, index)),
|
|
157
|
-
/* @__PURE__ */ jsxs(Button$1, {
|
|
158
|
-
variant: "outline",
|
|
159
|
-
size: "sm",
|
|
160
|
-
onClick: () => setForm({
|
|
161
|
-
...form,
|
|
162
|
-
tools: [...form.tools, {
|
|
163
|
-
nodeType: "",
|
|
164
|
-
operations: ""
|
|
165
|
-
}]
|
|
166
|
-
}),
|
|
167
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
168
|
-
icon: "mdi:plus",
|
|
169
|
-
width: 16
|
|
170
|
-
}), tr("fluidgrids.agents.addTool", "Add tool")]
|
|
171
|
-
})
|
|
172
|
-
]
|
|
173
|
-
}),
|
|
174
|
-
/* @__PURE__ */ jsxs("div", {
|
|
175
|
-
className: "space-y-2",
|
|
176
|
-
children: [/* @__PURE__ */ jsx(Label, { children: tr("fluidgrids.agents.connections", "Connections the agent's tools may use") }), connectionsLoading ? /* @__PURE__ */ jsx("p", {
|
|
177
|
-
className: "text-xs text-text-secondary",
|
|
178
|
-
children: tr("fluidgrids.agents.loadingConnections", "Loading connections…")
|
|
179
|
-
}) : connections.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
180
|
-
className: "text-xs text-text-secondary",
|
|
181
|
-
children: tr("fluidgrids.agents.noConnections", "This workspace has no connections yet.")
|
|
182
|
-
}) : /* @__PURE__ */ jsx("div", {
|
|
183
|
-
className: "grid gap-1 sm:grid-cols-2",
|
|
184
|
-
children: connections.map((connection) => /* @__PURE__ */ jsxs("label", {
|
|
185
|
-
className: "flex items-center gap-2 text-sm text-text-primary",
|
|
186
|
-
children: [
|
|
187
|
-
/* @__PURE__ */ jsx(Checkbox, {
|
|
188
|
-
checked: form.connectionScope.includes(connection.id),
|
|
189
|
-
onCheckedChange: (on) => toggleConnection(connection.id, on === true)
|
|
190
|
-
}),
|
|
191
|
-
/* @__PURE__ */ jsx("span", { children: connection.name }),
|
|
192
|
-
/* @__PURE__ */ jsx("span", {
|
|
193
|
-
className: "text-xs text-text-tertiary",
|
|
194
|
-
children: connection.provider?.name ?? connection.providerId
|
|
195
|
-
})
|
|
196
|
-
]
|
|
197
|
-
}, connection.id))
|
|
198
|
-
})]
|
|
199
|
-
}),
|
|
200
|
-
/* @__PURE__ */ jsxs("div", {
|
|
201
|
-
className: "flex items-center gap-2",
|
|
202
|
-
children: [/* @__PURE__ */ jsx(Switch, {
|
|
203
|
-
id: "agent-approval",
|
|
204
|
-
checked: form.requireToolApproval,
|
|
205
|
-
onCheckedChange: (on) => setForm({
|
|
206
|
-
...form,
|
|
207
|
-
requireToolApproval: on
|
|
208
|
-
})
|
|
209
|
-
}), /* @__PURE__ */ jsx(Label, {
|
|
210
|
-
htmlFor: "agent-approval",
|
|
211
|
-
children: tr("fluidgrids.agents.requireApproval", "Every tool call waits for a person's approval")
|
|
212
|
-
})]
|
|
213
|
-
}),
|
|
214
|
-
/* @__PURE__ */ jsxs("div", {
|
|
215
|
-
className: "flex gap-2",
|
|
216
|
-
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
217
|
-
onClick: () => void submit(),
|
|
218
|
-
disabled: busy,
|
|
219
|
-
"data-testid": "agent-definition-save",
|
|
220
|
-
children: tr("fluidgrids.agents.save", "Save agent")
|
|
221
|
-
}), /* @__PURE__ */ jsx(Button$1, {
|
|
222
|
-
variant: "outline",
|
|
223
|
-
onClick: onCancel,
|
|
224
|
-
disabled: busy,
|
|
225
|
-
children: tr("fluidgrids.agents.cancel", "Cancel")
|
|
226
|
-
})]
|
|
227
|
-
})
|
|
228
|
-
]
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
function AgentGrants({ agent, loadGrants, onGrant, onRevoke }) {
|
|
232
|
-
const tr = useTr();
|
|
233
|
-
const [grants, setGrants] = useState(null);
|
|
234
|
-
const [days, setDays] = useState(String(30));
|
|
235
|
-
const [busy, setBusy] = useState(false);
|
|
236
|
-
const load = useCallback(async () => {
|
|
237
|
-
try {
|
|
238
|
-
setGrants(await loadGrants(agent.id));
|
|
239
|
-
} catch (err) {
|
|
240
|
-
setGrants([]);
|
|
241
|
-
toast.error(errorMessage$2(err));
|
|
242
|
-
}
|
|
243
|
-
}, [agent.id, loadGrants]);
|
|
244
|
-
useEffect(() => {
|
|
245
|
-
load();
|
|
246
|
-
}, [load]);
|
|
247
|
-
const run = async (action, done) => {
|
|
248
|
-
setBusy(true);
|
|
249
|
-
try {
|
|
250
|
-
await action();
|
|
251
|
-
toast.success(done);
|
|
252
|
-
await load();
|
|
253
|
-
} catch (err) {
|
|
254
|
-
toast.error(errorMessage$2(err));
|
|
255
|
-
} finally {
|
|
256
|
-
setBusy(false);
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
const mine = grants?.find((grant) => grant.isMine && grant.status === "ACTIVE");
|
|
260
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
261
|
-
className: "space-y-2",
|
|
262
|
-
"data-testid": `agent-grants-${agent.id}`,
|
|
263
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
264
|
-
className: "flex flex-wrap items-center gap-2",
|
|
265
|
-
children: mine ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
266
|
-
className: "text-sm text-text-primary",
|
|
267
|
-
children: mine.expiresAt ? tr("fluidgrids.agents.myGrantUntil", "This agent may act for you until {{date}}.", { date: new Date(mine.expiresAt).toLocaleDateString() }) : tr("fluidgrids.agents.myGrant", "This agent may act for you.")
|
|
268
|
-
}), /* @__PURE__ */ jsx(Button$1, {
|
|
269
|
-
variant: "outline",
|
|
270
|
-
size: "sm",
|
|
271
|
-
disabled: busy,
|
|
272
|
-
onClick: () => void run(() => onRevoke(agent.id, null), tr("fluidgrids.agents.withdrawn", "Grant withdrawn")),
|
|
273
|
-
"data-testid": "agent-grant-withdraw",
|
|
274
|
-
children: tr("fluidgrids.agents.withdraw", "Withdraw my grant")
|
|
275
|
-
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
276
|
-
/* @__PURE__ */ jsx(Label, {
|
|
277
|
-
htmlFor: `grant-days-${agent.id}`,
|
|
278
|
-
className: "text-sm",
|
|
279
|
-
children: tr("fluidgrids.agents.grantFor", "Let it act for me for")
|
|
280
|
-
}),
|
|
281
|
-
/* @__PURE__ */ jsx(Input, {
|
|
282
|
-
id: `grant-days-${agent.id}`,
|
|
283
|
-
className: "w-20",
|
|
284
|
-
type: "number",
|
|
285
|
-
min: 1,
|
|
286
|
-
max: 365,
|
|
287
|
-
value: days,
|
|
288
|
-
onChange: (e) => setDays(e.target.value)
|
|
289
|
-
}),
|
|
290
|
-
/* @__PURE__ */ jsx("span", {
|
|
291
|
-
className: "text-sm text-text-secondary",
|
|
292
|
-
children: tr("fluidgrids.agents.days", "days")
|
|
293
|
-
}),
|
|
294
|
-
/* @__PURE__ */ jsx(Button$1, {
|
|
295
|
-
size: "sm",
|
|
296
|
-
disabled: busy || agent.status !== "ACTIVE",
|
|
297
|
-
onClick: () => void run(async () => onGrant(agent.id, grantDays(days)), tr("fluidgrids.agents.granted", "Grant given")),
|
|
298
|
-
"data-testid": "agent-grant-give",
|
|
299
|
-
children: tr("fluidgrids.agents.grant", "Grant")
|
|
300
|
-
})
|
|
301
|
-
] })
|
|
302
|
-
}), grants && grants.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
303
|
-
className: "space-y-1 text-xs text-text-secondary",
|
|
304
|
-
children: grants.map((grant) => /* @__PURE__ */ jsxs("li", {
|
|
305
|
-
className: "flex items-center gap-2",
|
|
306
|
-
children: [
|
|
307
|
-
/* @__PURE__ */ jsx("span", {
|
|
308
|
-
className: "font-mono",
|
|
309
|
-
children: grant.userId
|
|
310
|
-
}),
|
|
311
|
-
/* @__PURE__ */ jsx(Badge, {
|
|
312
|
-
variant: "outline",
|
|
313
|
-
children: grant.status
|
|
314
|
-
}),
|
|
315
|
-
grant.expiresAt ? /* @__PURE__ */ jsx("span", { children: tr("fluidgrids.agents.until", "until {{date}}", { date: new Date(grant.expiresAt).toLocaleDateString() }) }) : null,
|
|
316
|
-
!grant.isMine && grant.status === "ACTIVE" ? /* @__PURE__ */ jsx(Button$1, {
|
|
317
|
-
variant: "ghost",
|
|
318
|
-
size: "sm",
|
|
319
|
-
disabled: busy,
|
|
320
|
-
onClick: () => void run(() => onRevoke(agent.id, grant.userId), tr("fluidgrids.agents.revoked", "Grant revoked")),
|
|
321
|
-
children: tr("fluidgrids.agents.revoke", "Revoke")
|
|
322
|
-
}) : null
|
|
323
|
-
]
|
|
324
|
-
}, grant.userId))
|
|
325
|
-
}) : null]
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
function AgentsTab() {
|
|
329
|
-
const tr = useTr();
|
|
330
|
-
const { agents, loading, error, save, remove, grants, grant, revoke } = useAgentDefinitions();
|
|
331
|
-
const [editing, setEditing] = useState(null);
|
|
332
|
-
const onSave = async (form) => {
|
|
333
|
-
const input = formToInput$2(form);
|
|
334
|
-
await save(editing?.id ?? null, input);
|
|
335
|
-
toast.success(tr("fluidgrids.agents.saved", "Agent saved"));
|
|
336
|
-
setEditing(null);
|
|
337
|
-
};
|
|
338
|
-
const onDelete = async (agent) => {
|
|
339
|
-
try {
|
|
340
|
-
await remove(agent.id);
|
|
341
|
-
toast.success(tr("fluidgrids.agents.deleted", "Agent deleted"));
|
|
342
|
-
} catch (err) {
|
|
343
|
-
toast.error(errorMessage$2(err));
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
347
|
-
className: "space-y-4",
|
|
348
|
-
"data-testid": "agents-tab",
|
|
349
|
-
children: [
|
|
350
|
-
/* @__PURE__ */ jsxs("div", {
|
|
351
|
-
className: "flex flex-wrap items-start justify-between gap-2",
|
|
352
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
353
|
-
className: "text-base font-semibold text-text-primary",
|
|
354
|
-
children: tr("fluidgrids.agents.title", "Agents")
|
|
355
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
356
|
-
className: "text-sm text-text-secondary",
|
|
357
|
-
children: tr("fluidgrids.agents.subtitle", "Give an AI Agent node an identity of its own. It can only call the tools and connections you allow, only for people who granted it, and every tool call is recorded under the agent and the person.")
|
|
358
|
-
})] }), !editing ? /* @__PURE__ */ jsxs(Button$1, {
|
|
359
|
-
onClick: () => setEditing({
|
|
360
|
-
id: null,
|
|
361
|
-
form: emptyAgentForm()
|
|
362
|
-
}),
|
|
363
|
-
"data-testid": "agent-definition-new",
|
|
364
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
365
|
-
icon: "mdi:plus",
|
|
366
|
-
width: 16
|
|
367
|
-
}), tr("fluidgrids.agents.new", "New agent")]
|
|
368
|
-
}) : null]
|
|
369
|
-
}),
|
|
370
|
-
editing ? /* @__PURE__ */ jsx(AgentEditor, {
|
|
371
|
-
initial: editing.form,
|
|
372
|
-
onCancel: () => setEditing(null),
|
|
373
|
-
onSave
|
|
374
|
-
}) : null,
|
|
375
|
-
error ? /* @__PURE__ */ jsx("p", {
|
|
376
|
-
className: "text-sm text-destructive",
|
|
377
|
-
children: errorMessage$2(error)
|
|
378
|
-
}) : null,
|
|
379
|
-
loading ? /* @__PURE__ */ jsx("p", {
|
|
380
|
-
className: "text-sm text-text-secondary",
|
|
381
|
-
children: tr("fluidgrids.agents.loading", "Loading agents…")
|
|
382
|
-
}) : agents.length === 0 && !error ? /* @__PURE__ */ jsx("p", {
|
|
383
|
-
className: "text-sm text-text-secondary",
|
|
384
|
-
children: tr("fluidgrids.agents.empty", "No agents yet.")
|
|
385
|
-
}) : /* @__PURE__ */ jsx("ul", {
|
|
386
|
-
className: "space-y-3",
|
|
387
|
-
children: agents.map((agent) => /* @__PURE__ */ jsxs("li", {
|
|
388
|
-
className: "rounded-lg border border-border-secondary bg-background-secondary p-3 space-y-2",
|
|
389
|
-
"data-testid": `agent-definition-${agent.id}`,
|
|
390
|
-
children: [
|
|
391
|
-
/* @__PURE__ */ jsxs("div", {
|
|
392
|
-
className: "flex flex-wrap items-center justify-between gap-2",
|
|
393
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
394
|
-
className: "flex items-center gap-2",
|
|
395
|
-
children: [
|
|
396
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
397
|
-
icon: "mdi:robot-outline",
|
|
398
|
-
width: 18
|
|
399
|
-
}),
|
|
400
|
-
/* @__PURE__ */ jsx("span", {
|
|
401
|
-
className: "font-medium text-text-primary",
|
|
402
|
-
children: agent.name
|
|
403
|
-
}),
|
|
404
|
-
/* @__PURE__ */ jsx(Badge, {
|
|
405
|
-
variant: "outline",
|
|
406
|
-
children: agent.status
|
|
407
|
-
}),
|
|
408
|
-
agent.requireToolApproval ? /* @__PURE__ */ jsx(Badge, {
|
|
409
|
-
variant: "outline",
|
|
410
|
-
children: tr("fluidgrids.agents.approvalBadge", "Approval required")
|
|
411
|
-
}) : null
|
|
412
|
-
]
|
|
413
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
414
|
-
className: "flex gap-1",
|
|
415
|
-
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
416
|
-
variant: "ghost",
|
|
417
|
-
size: "sm",
|
|
418
|
-
onClick: () => setEditing({
|
|
419
|
-
id: agent.id,
|
|
420
|
-
form: agentToForm(agent)
|
|
421
|
-
}),
|
|
422
|
-
children: tr("fluidgrids.agents.edit", "Edit")
|
|
423
|
-
}), /* @__PURE__ */ jsx(Button$1, {
|
|
424
|
-
variant: "ghost",
|
|
425
|
-
size: "sm",
|
|
426
|
-
onClick: () => void onDelete(agent),
|
|
427
|
-
children: tr("fluidgrids.agents.delete", "Delete")
|
|
428
|
-
})]
|
|
429
|
-
})]
|
|
430
|
-
}),
|
|
431
|
-
agent.description ? /* @__PURE__ */ jsx("p", {
|
|
432
|
-
className: "text-sm text-text-secondary",
|
|
433
|
-
children: agent.description
|
|
434
|
-
}) : null,
|
|
435
|
-
/* @__PURE__ */ jsx("div", {
|
|
436
|
-
className: "text-xs text-text-secondary",
|
|
437
|
-
children: agent.toolAllowlist.length > 0 ? agent.toolAllowlist.map(describeRule).join(" · ") : tr("fluidgrids.agents.noTools", "No tools allowed")
|
|
438
|
-
}),
|
|
439
|
-
/* @__PURE__ */ jsx("div", {
|
|
440
|
-
className: "text-xs text-text-tertiary",
|
|
441
|
-
children: tr("fluidgrids.agents.connectionCount", "{{count}} connections in scope", { count: agent.connectionScope.length })
|
|
442
|
-
}),
|
|
443
|
-
/* @__PURE__ */ jsx(AgentGrants, {
|
|
444
|
-
agent,
|
|
445
|
-
loadGrants: grants,
|
|
446
|
-
onGrant: grant,
|
|
447
|
-
onRevoke: revoke
|
|
448
|
-
})
|
|
449
|
-
]
|
|
450
|
-
}, agent.id))
|
|
451
|
-
})
|
|
452
|
-
]
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// src/modules/action-policies/utils/policy-form.ts
|
|
457
|
-
const POLICY_EFFECTS = [
|
|
458
|
-
"REQUIRE_APPROVAL",
|
|
459
|
-
"DENY",
|
|
460
|
-
"ALLOW",
|
|
461
|
-
"LOG"
|
|
462
|
-
];
|
|
463
|
-
const POLICY_ENVIRONMENTS = [
|
|
464
|
-
"DEV",
|
|
465
|
-
"STAGING",
|
|
466
|
-
"PROD"
|
|
467
|
-
];
|
|
468
|
-
const CONDITION_OPERATORS = [
|
|
469
|
-
{
|
|
470
|
-
value: "gt",
|
|
471
|
-
label: "is greater than",
|
|
472
|
-
kind: "number"
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
value: "gte",
|
|
476
|
-
label: "is at least",
|
|
477
|
-
kind: "number"
|
|
478
|
-
},
|
|
479
|
-
{
|
|
480
|
-
value: "lt",
|
|
481
|
-
label: "is less than",
|
|
482
|
-
kind: "number"
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
value: "lte",
|
|
486
|
-
label: "is at most",
|
|
487
|
-
kind: "number"
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
value: "eq",
|
|
491
|
-
label: "equals",
|
|
492
|
-
kind: "single"
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
value: "neq",
|
|
496
|
-
label: "does not equal",
|
|
497
|
-
kind: "single"
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
value: "in",
|
|
501
|
-
label: "is one of",
|
|
502
|
-
kind: "list"
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
value: "not_in",
|
|
506
|
-
label: "is not one of",
|
|
507
|
-
kind: "list"
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
value: "contains",
|
|
511
|
-
label: "contains",
|
|
512
|
-
kind: "single"
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
value: "count_gt",
|
|
516
|
-
label: "has more items than",
|
|
517
|
-
kind: "number"
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
value: "count_gte",
|
|
521
|
-
label: "has at least … items",
|
|
522
|
-
kind: "number"
|
|
523
|
-
},
|
|
524
|
-
{
|
|
525
|
-
value: "count_lt",
|
|
526
|
-
label: "has fewer items than",
|
|
527
|
-
kind: "number"
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
value: "count_lte",
|
|
531
|
-
label: "has at most … items",
|
|
532
|
-
kind: "number"
|
|
533
|
-
},
|
|
534
|
-
{
|
|
535
|
-
value: "exists",
|
|
536
|
-
label: "is set",
|
|
537
|
-
kind: "none"
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
value: "not_exists",
|
|
541
|
-
label: "is not set",
|
|
542
|
-
kind: "none"
|
|
543
|
-
}
|
|
544
|
-
];
|
|
545
|
-
var PolicyFormError = class extends Error {};
|
|
546
|
-
const OPERATOR_KIND = new Map(CONDITION_OPERATORS.map((operator) => [operator.value, operator.kind]));
|
|
547
|
-
function operatorKind(op) {
|
|
548
|
-
return OPERATOR_KIND.get(op) ?? "single";
|
|
549
|
-
}
|
|
550
|
-
function emptyPolicyForm() {
|
|
551
|
-
return {
|
|
552
|
-
name: "",
|
|
553
|
-
description: "",
|
|
554
|
-
enabled: true,
|
|
555
|
-
priority: "100",
|
|
556
|
-
effect: "REQUIRE_APPROVAL",
|
|
557
|
-
nodeTypes: "",
|
|
558
|
-
operations: "",
|
|
559
|
-
connectionProviders: "",
|
|
560
|
-
workflowTags: "",
|
|
561
|
-
environments: ["PROD"],
|
|
562
|
-
join: "all",
|
|
563
|
-
rows: []
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
function splitList(text) {
|
|
567
|
-
return [...new Set(text.split(",").map((item) => item.trim()).filter(Boolean))];
|
|
568
|
-
}
|
|
569
|
-
/** "1500" -> 1500, "true" -> true, "null" -> null, anything else stays text. */
|
|
570
|
-
function parseScalar(text) {
|
|
571
|
-
const trimmed = text.trim();
|
|
572
|
-
if (trimmed === "true") return true;
|
|
573
|
-
if (trimmed === "false") return false;
|
|
574
|
-
if (trimmed === "null") return null;
|
|
575
|
-
if (trimmed !== "" && Number.isFinite(Number(trimmed))) return Number(trimmed);
|
|
576
|
-
return trimmed;
|
|
577
|
-
}
|
|
578
|
-
function formatScalar(value) {
|
|
579
|
-
if (value === null) return "null";
|
|
580
|
-
return String(value);
|
|
581
|
-
}
|
|
582
|
-
function rowToLeaf(row, index) {
|
|
583
|
-
const path = row.path.trim();
|
|
584
|
-
if (!path) throw new PolicyFormError(`Condition ${index + 1} needs a parameter path`);
|
|
585
|
-
switch (operatorKind(row.op)) {
|
|
586
|
-
case "none": return {
|
|
587
|
-
path,
|
|
588
|
-
op: row.op
|
|
589
|
-
};
|
|
590
|
-
case "number": {
|
|
591
|
-
const value = Number(row.value.trim());
|
|
592
|
-
if (row.value.trim() === "" || !Number.isFinite(value)) throw new PolicyFormError(`Condition ${index + 1} needs a number`);
|
|
593
|
-
return {
|
|
594
|
-
path,
|
|
595
|
-
op: row.op,
|
|
596
|
-
value
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
case "list": {
|
|
600
|
-
const values = splitList(row.value).map(parseScalar);
|
|
601
|
-
if (values.length === 0) throw new PolicyFormError(`Condition ${index + 1} needs at least one value`);
|
|
602
|
-
return {
|
|
603
|
-
path,
|
|
604
|
-
op: row.op,
|
|
605
|
-
value: values
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
default: return {
|
|
609
|
-
path,
|
|
610
|
-
op: row.op,
|
|
611
|
-
value: parseScalar(row.value)
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
/** The editor state as the API input. Throws PolicyFormError with a readable reason. */
|
|
616
|
-
function formToInput$1(form) {
|
|
617
|
-
const name = form.name.trim();
|
|
618
|
-
if (!name) throw new PolicyFormError("Give the policy a name");
|
|
619
|
-
const priority = Number(form.priority);
|
|
620
|
-
if (!Number.isInteger(priority) || priority < 0 || priority > 1e5) throw new PolicyFormError("Priority is a whole number from 0 to 100000");
|
|
621
|
-
const leaves = form.rows.map(rowToLeaf);
|
|
622
|
-
let condition = null;
|
|
623
|
-
if (leaves.length === 1) condition = leaves[0];
|
|
624
|
-
else if (leaves.length > 1) condition = { [form.join]: leaves };
|
|
625
|
-
return {
|
|
626
|
-
...form.id ? { id: form.id } : {},
|
|
627
|
-
name,
|
|
628
|
-
description: form.description.trim() || null,
|
|
629
|
-
enabled: form.enabled,
|
|
630
|
-
priority,
|
|
631
|
-
effect: form.effect,
|
|
632
|
-
matcher: {
|
|
633
|
-
nodeTypes: splitList(form.nodeTypes),
|
|
634
|
-
operations: splitList(form.operations),
|
|
635
|
-
connectionProviders: splitList(form.connectionProviders),
|
|
636
|
-
workflowTags: splitList(form.workflowTags)
|
|
637
|
-
},
|
|
638
|
-
condition,
|
|
639
|
-
environments: form.environments
|
|
186
|
+
default: return {
|
|
187
|
+
path,
|
|
188
|
+
op: row.op,
|
|
189
|
+
value: parseScalar(row.value)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** The editor state as the API input. Throws PolicyFormError with a readable reason. */
|
|
194
|
+
function formToInput$1(form) {
|
|
195
|
+
const name = form.name.trim();
|
|
196
|
+
if (!name) throw new PolicyFormError("Give the policy a name");
|
|
197
|
+
const priority = Number(form.priority);
|
|
198
|
+
if (!Number.isInteger(priority) || priority < 0 || priority > 1e5) throw new PolicyFormError("Priority is a whole number from 0 to 100000");
|
|
199
|
+
const leaves = form.rows.map(rowToLeaf);
|
|
200
|
+
let condition = null;
|
|
201
|
+
if (leaves.length === 1) condition = leaves[0];
|
|
202
|
+
else if (leaves.length > 1) condition = { [form.join]: leaves };
|
|
203
|
+
return {
|
|
204
|
+
...form.id ? { id: form.id } : {},
|
|
205
|
+
name,
|
|
206
|
+
description: form.description.trim() || null,
|
|
207
|
+
enabled: form.enabled,
|
|
208
|
+
priority,
|
|
209
|
+
effect: form.effect,
|
|
210
|
+
matcher: {
|
|
211
|
+
nodeTypes: splitList(form.nodeTypes),
|
|
212
|
+
operations: splitList(form.operations),
|
|
213
|
+
connectionProviders: splitList(form.connectionProviders),
|
|
214
|
+
workflowTags: splitList(form.workflowTags)
|
|
215
|
+
},
|
|
216
|
+
condition,
|
|
217
|
+
environments: form.environments
|
|
640
218
|
};
|
|
641
219
|
}
|
|
642
220
|
function isRecord$1(value) {
|
|
@@ -736,7 +314,7 @@ function needsAllowFallback(draft, others) {
|
|
|
736
314
|
* rule; changing a policy or deciding an approval needs workflow publish rights.
|
|
737
315
|
*/
|
|
738
316
|
const FIELD$1 = "rounded-md border border-border-secondary bg-background-secondary px-2 py-1.5 text-sm text-text-primary";
|
|
739
|
-
function errorMessage$
|
|
317
|
+
function errorMessage$2(err) {
|
|
740
318
|
if (err instanceof PolicyFormError) return err.message;
|
|
741
319
|
return describeOperationError(err);
|
|
742
320
|
}
|
|
@@ -850,7 +428,7 @@ function PolicyEditor({ initial, conditionEditable, storedCondition, others, onC
|
|
|
850
428
|
try {
|
|
851
429
|
await action();
|
|
852
430
|
} catch (err) {
|
|
853
|
-
toast.error(errorMessage$
|
|
431
|
+
toast.error(errorMessage$2(err));
|
|
854
432
|
} finally {
|
|
855
433
|
setBusy(false);
|
|
856
434
|
}
|
|
@@ -1205,7 +783,7 @@ function ApprovalsList({ approvals, onDecide }) {
|
|
|
1205
783
|
await onDecide(approval.id, true);
|
|
1206
784
|
toast.success(tr("fluidgrids.actionPolicies.approved", "Approved — the run continues"));
|
|
1207
785
|
} catch (err) {
|
|
1208
|
-
toast.error(errorMessage$
|
|
786
|
+
toast.error(errorMessage$2(err));
|
|
1209
787
|
} finally {
|
|
1210
788
|
setBusy(null);
|
|
1211
789
|
}
|
|
@@ -1221,7 +799,7 @@ function ApprovalsList({ approvals, onDecide }) {
|
|
|
1221
799
|
await onDecide(approval.id, false);
|
|
1222
800
|
toast.success(tr("fluidgrids.actionPolicies.declined", "Declined — the node fails"));
|
|
1223
801
|
} catch (err) {
|
|
1224
|
-
toast.error(errorMessage$
|
|
802
|
+
toast.error(errorMessage$2(err));
|
|
1225
803
|
} finally {
|
|
1226
804
|
setBusy(null);
|
|
1227
805
|
}
|
|
@@ -1348,7 +926,7 @@ function ActionPoliciesTab() {
|
|
|
1348
926
|
try {
|
|
1349
927
|
setPreview(await dryRun({ excludePolicyId: policy.id }));
|
|
1350
928
|
} catch (err) {
|
|
1351
|
-
toast.error(errorMessage$
|
|
929
|
+
toast.error(errorMessage$2(err));
|
|
1352
930
|
}
|
|
1353
931
|
},
|
|
1354
932
|
children: tr("fluidgrids.actionPolicies.withoutIt", "Without it")
|
|
@@ -1381,7 +959,7 @@ function ActionPoliciesTab() {
|
|
|
1381
959
|
await remove(policy.id);
|
|
1382
960
|
toast.success(tr("fluidgrids.actionPolicies.deleted", "Policy deleted"));
|
|
1383
961
|
} catch (err) {
|
|
1384
|
-
toast.error(errorMessage$
|
|
962
|
+
toast.error(errorMessage$2(err));
|
|
1385
963
|
}
|
|
1386
964
|
},
|
|
1387
965
|
children: confirmDelete === policy.id ? tr("fluidgrids.actionPolicies.confirmDelete", "Confirm delete") : tr("fluidgrids.actionPolicies.delete", "Delete")
|
|
@@ -1394,12 +972,6 @@ function ActionPoliciesTab() {
|
|
|
1394
972
|
});
|
|
1395
973
|
}
|
|
1396
974
|
|
|
1397
|
-
// src/modules/settings/api/ManagedAiPolicyAuthorityContext.ts
|
|
1398
|
-
const ManagedAiAuthorityContext = createContext(null);
|
|
1399
|
-
function useManagedAiPolicyAuthority() {
|
|
1400
|
-
return useContext(ManagedAiAuthorityContext);
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
975
|
// src/modules/settings/api/managed-ai-request.ts
|
|
1404
976
|
const canonical = {
|
|
1405
977
|
prepare: prepareWorkspaceRequest,
|
|
@@ -3805,127 +3377,558 @@ function LogStreamingSettings() {
|
|
|
3805
3377
|
className: "size-4 rounded border-border-secondary accent-action-primary-bg"
|
|
3806
3378
|
}), tr("fluidgrids.settings.logStreaming.enabled", "Destination enabled")]
|
|
3807
3379
|
}),
|
|
3808
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3809
|
-
className: "flex justify-end gap-2",
|
|
3810
|
-
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
3811
|
-
variant: "outline",
|
|
3812
|
-
onClick: resetForm,
|
|
3813
|
-
children: tr("fluidgrids.settings.logStreaming.cancel", "Cancel")
|
|
3814
|
-
}), /* @__PURE__ */ jsx(Button$1, {
|
|
3815
|
-
"data-agent": "confirm",
|
|
3816
|
-
onClick: () => void save(),
|
|
3817
|
-
disabled: actions.loading,
|
|
3818
|
-
children: actions.loading ? tr("fluidgrids.settings.logStreaming.saving", "Saving…") : tr("fluidgrids.settings.logStreaming.save", "Save destination")
|
|
3819
|
-
})]
|
|
3380
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3381
|
+
className: "flex justify-end gap-2",
|
|
3382
|
+
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
3383
|
+
variant: "outline",
|
|
3384
|
+
onClick: resetForm,
|
|
3385
|
+
children: tr("fluidgrids.settings.logStreaming.cancel", "Cancel")
|
|
3386
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
3387
|
+
"data-agent": "confirm",
|
|
3388
|
+
onClick: () => void save(),
|
|
3389
|
+
disabled: actions.loading,
|
|
3390
|
+
children: actions.loading ? tr("fluidgrids.settings.logStreaming.saving", "Saving…") : tr("fluidgrids.settings.logStreaming.save", "Save destination")
|
|
3391
|
+
})]
|
|
3392
|
+
})
|
|
3393
|
+
]
|
|
3394
|
+
})]
|
|
3395
|
+
}),
|
|
3396
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3397
|
+
className: "space-y-3",
|
|
3398
|
+
children: [
|
|
3399
|
+
loading && destinations.length === 0 && /* @__PURE__ */ jsx("div", {
|
|
3400
|
+
className: "rounded-lg border border-border-secondary bg-background-secondary p-6 text-sm text-text-secondary",
|
|
3401
|
+
children: tr("fluidgrids.settings.logStreaming.loading", "Loading destinations…")
|
|
3402
|
+
}),
|
|
3403
|
+
!loading && destinations.length === 0 && /* @__PURE__ */ jsxs("div", {
|
|
3404
|
+
className: "rounded-lg border border-dashed border-border-secondary bg-background-secondary p-8 text-center",
|
|
3405
|
+
children: [
|
|
3406
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
3407
|
+
icon: "mdi:transit-connection-variant",
|
|
3408
|
+
className: "mx-auto mb-3 text-text-secondary",
|
|
3409
|
+
width: 32
|
|
3410
|
+
}),
|
|
3411
|
+
/* @__PURE__ */ jsx("p", {
|
|
3412
|
+
className: "font-medium text-text-primary",
|
|
3413
|
+
children: tr("fluidgrids.settings.logStreaming.emptyTitle", "No log destinations yet")
|
|
3414
|
+
}),
|
|
3415
|
+
/* @__PURE__ */ jsx("p", {
|
|
3416
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
3417
|
+
children: tr("fluidgrids.settings.logStreaming.emptyDescription", "Add a webhook, syslog target, or Sentry DSN to start streaming events.")
|
|
3418
|
+
})
|
|
3419
|
+
]
|
|
3420
|
+
}),
|
|
3421
|
+
destinations.map((destination) => /* @__PURE__ */ jsx(Card, {
|
|
3422
|
+
className: "border-border-secondary bg-background-secondary",
|
|
3423
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
3424
|
+
className: "flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between",
|
|
3425
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
3426
|
+
className: "min-w-0",
|
|
3427
|
+
children: [
|
|
3428
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3429
|
+
className: "flex flex-wrap items-center gap-2",
|
|
3430
|
+
children: [
|
|
3431
|
+
/* @__PURE__ */ jsx("h3", {
|
|
3432
|
+
className: "font-medium text-text-primary",
|
|
3433
|
+
children: destination.name
|
|
3434
|
+
}),
|
|
3435
|
+
/* @__PURE__ */ jsx("span", {
|
|
3436
|
+
className: "rounded-full bg-background-tertiary px-2 py-0.5 text-xs text-text-secondary",
|
|
3437
|
+
children: destination.provider
|
|
3438
|
+
}),
|
|
3439
|
+
/* @__PURE__ */ jsx("span", {
|
|
3440
|
+
className: destination.isEnabled ? "text-xs text-status-success-text" : "text-xs text-text-secondary",
|
|
3441
|
+
children: destination.isEnabled ? tr("fluidgrids.settings.logStreaming.enabledBadge", "Enabled") : tr("fluidgrids.settings.logStreaming.disabledBadge", "Disabled")
|
|
3442
|
+
})
|
|
3443
|
+
]
|
|
3444
|
+
}),
|
|
3445
|
+
/* @__PURE__ */ jsx("p", {
|
|
3446
|
+
className: "mt-1 truncate text-sm text-text-secondary",
|
|
3447
|
+
children: destination.endpoint
|
|
3448
|
+
}),
|
|
3449
|
+
/* @__PURE__ */ jsxs("p", {
|
|
3450
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
3451
|
+
children: [destination.eventFilters.length > 0 ? destination.eventFilters.map(eventLabel).join(", ") : tr("fluidgrids.settings.logStreaming.allEvents", "All events"), destination.hasSecret && " · Secret configured"]
|
|
3452
|
+
}),
|
|
3453
|
+
destination.lastDispatchError && /* @__PURE__ */ jsx("p", {
|
|
3454
|
+
className: "mt-2 text-xs text-status-error-text",
|
|
3455
|
+
children: destination.lastDispatchError
|
|
3456
|
+
})
|
|
3457
|
+
]
|
|
3458
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3459
|
+
className: "flex shrink-0 flex-wrap gap-2",
|
|
3460
|
+
children: [
|
|
3461
|
+
/* @__PURE__ */ jsxs(Button$1, {
|
|
3462
|
+
variant: "outline",
|
|
3463
|
+
size: "sm",
|
|
3464
|
+
onClick: () => void sendTest(destination),
|
|
3465
|
+
disabled: actions.loading,
|
|
3466
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3467
|
+
icon: "mdi:send-check-outline",
|
|
3468
|
+
className: "mr-1",
|
|
3469
|
+
width: 15
|
|
3470
|
+
}), tr("fluidgrids.settings.logStreaming.test", "Send test")]
|
|
3471
|
+
}),
|
|
3472
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
3473
|
+
variant: "outline",
|
|
3474
|
+
size: "sm",
|
|
3475
|
+
onClick: () => {
|
|
3476
|
+
setEditingId(destination.id);
|
|
3477
|
+
setShowForm(true);
|
|
3478
|
+
},
|
|
3479
|
+
disabled: actions.loading,
|
|
3480
|
+
children: tr("fluidgrids.settings.logStreaming.editButton", "Edit")
|
|
3481
|
+
}),
|
|
3482
|
+
/* @__PURE__ */ jsxs(Button$1, {
|
|
3483
|
+
variant: "ghost",
|
|
3484
|
+
size: "sm",
|
|
3485
|
+
onClick: () => void remove(destination),
|
|
3486
|
+
disabled: actions.loading,
|
|
3487
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3488
|
+
icon: "mdi:trash-can-outline",
|
|
3489
|
+
className: "text-status-error-text",
|
|
3490
|
+
width: 17
|
|
3491
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3492
|
+
className: "sr-only",
|
|
3493
|
+
children: tr("fluidgrids.settings.logStreaming.delete", "Delete")
|
|
3494
|
+
})]
|
|
3495
|
+
})
|
|
3496
|
+
]
|
|
3497
|
+
})]
|
|
3498
|
+
})
|
|
3499
|
+
}, destination.id))
|
|
3500
|
+
]
|
|
3501
|
+
})
|
|
3502
|
+
]
|
|
3503
|
+
});
|
|
3504
|
+
}
|
|
3505
|
+
|
|
3506
|
+
// src/modules/agent-definitions/components/AgentsTab.tsx
|
|
3507
|
+
/**
|
|
3508
|
+
* Settings → Agents (BOFF-9962): FluidGrids agents with their own identity.
|
|
3509
|
+
*
|
|
3510
|
+
* Builders create an agent, choose the tools it may call (node type and operations) and the
|
|
3511
|
+
* connections those tools may use, and can require approval for every tool call. Each person
|
|
3512
|
+
* lets the agent act for them with a time-boxed grant (30 days by default, 365 at most) and can
|
|
3513
|
+
* withdraw it at any time; admins can revoke anyone's grant. An AI Agent node that names the agent
|
|
3514
|
+
* runs its tools as "agent for user", and every call is recorded under both identities. Giving an
|
|
3515
|
+
* agent more access withdraws other people's grants until they grant again.
|
|
3516
|
+
*/
|
|
3517
|
+
function errorMessage$1(err) {
|
|
3518
|
+
if (err instanceof AgentFormError) return err.message;
|
|
3519
|
+
return describeOperationError(err);
|
|
3520
|
+
}
|
|
3521
|
+
function AgentEditor({ initial, onCancel, onSave }) {
|
|
3522
|
+
const tr = useTr();
|
|
3523
|
+
const [form, setForm] = useState(initial);
|
|
3524
|
+
const [busy, setBusy] = useState(false);
|
|
3525
|
+
const { connections, loading: connectionsLoading } = useConnections();
|
|
3526
|
+
const setTool = (index, patch) => setForm((current) => ({
|
|
3527
|
+
...current,
|
|
3528
|
+
tools: current.tools.map((row, i) => i === index ? {
|
|
3529
|
+
...row,
|
|
3530
|
+
...patch
|
|
3531
|
+
} : row)
|
|
3532
|
+
}));
|
|
3533
|
+
const toggleConnection = (id, on) => setForm((current) => ({
|
|
3534
|
+
...current,
|
|
3535
|
+
connectionScope: on ? [.../* @__PURE__ */ new Set([...current.connectionScope, id])] : current.connectionScope.filter((value) => value !== id)
|
|
3536
|
+
}));
|
|
3537
|
+
const submit = async () => {
|
|
3538
|
+
setBusy(true);
|
|
3539
|
+
try {
|
|
3540
|
+
await onSave(form);
|
|
3541
|
+
} catch (err) {
|
|
3542
|
+
toast.error(errorMessage$1(err));
|
|
3543
|
+
} finally {
|
|
3544
|
+
setBusy(false);
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3548
|
+
className: "rounded-lg border border-border-secondary bg-background-primary p-4 space-y-4",
|
|
3549
|
+
"data-testid": "agent-definition-editor",
|
|
3550
|
+
children: [
|
|
3551
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3552
|
+
className: "grid gap-3 sm:grid-cols-2",
|
|
3553
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
3554
|
+
className: "space-y-1",
|
|
3555
|
+
children: [/* @__PURE__ */ jsx(Label, {
|
|
3556
|
+
htmlFor: "agent-name",
|
|
3557
|
+
children: tr("fluidgrids.agents.name", "Name")
|
|
3558
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
3559
|
+
id: "agent-name",
|
|
3560
|
+
value: form.name,
|
|
3561
|
+
onChange: (e) => setForm({
|
|
3562
|
+
...form,
|
|
3563
|
+
name: e.target.value
|
|
3564
|
+
}),
|
|
3565
|
+
"data-testid": "agent-definition-name"
|
|
3566
|
+
})]
|
|
3567
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3568
|
+
className: "flex items-end gap-2",
|
|
3569
|
+
children: [/* @__PURE__ */ jsx(Switch, {
|
|
3570
|
+
id: "agent-active",
|
|
3571
|
+
checked: form.status === "ACTIVE",
|
|
3572
|
+
onCheckedChange: (on) => setForm({
|
|
3573
|
+
...form,
|
|
3574
|
+
status: on ? "ACTIVE" : "DISABLED"
|
|
3820
3575
|
})
|
|
3821
|
-
|
|
3576
|
+
}), /* @__PURE__ */ jsx(Label, {
|
|
3577
|
+
htmlFor: "agent-active",
|
|
3578
|
+
children: tr("fluidgrids.agents.active", "Active")
|
|
3579
|
+
})]
|
|
3822
3580
|
})]
|
|
3823
3581
|
}),
|
|
3824
3582
|
/* @__PURE__ */ jsxs("div", {
|
|
3825
|
-
className: "space-y-
|
|
3583
|
+
className: "space-y-1",
|
|
3584
|
+
children: [/* @__PURE__ */ jsx(Label, {
|
|
3585
|
+
htmlFor: "agent-description",
|
|
3586
|
+
children: tr("fluidgrids.agents.description", "Description")
|
|
3587
|
+
}), /* @__PURE__ */ jsx(Textarea, {
|
|
3588
|
+
id: "agent-description",
|
|
3589
|
+
value: form.description,
|
|
3590
|
+
onChange: (e) => setForm({
|
|
3591
|
+
...form,
|
|
3592
|
+
description: e.target.value
|
|
3593
|
+
}),
|
|
3594
|
+
rows: 2
|
|
3595
|
+
})]
|
|
3596
|
+
}),
|
|
3597
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3598
|
+
className: "space-y-2",
|
|
3599
|
+
children: [
|
|
3600
|
+
/* @__PURE__ */ jsx(Label, { children: tr("fluidgrids.agents.tools", "Tools the agent may call") }),
|
|
3601
|
+
/* @__PURE__ */ jsx("p", {
|
|
3602
|
+
className: "text-xs text-text-secondary",
|
|
3603
|
+
children: tr("fluidgrids.agents.toolsHelp", "A node type (for example store/slack) and the operations of it the agent may call, separated by commas. Leave the operations empty to allow every operation of that node type. Nothing else can be called.")
|
|
3604
|
+
}),
|
|
3605
|
+
form.tools.map((row, index) => /* @__PURE__ */ jsxs("div", {
|
|
3606
|
+
className: "flex flex-wrap items-center gap-2",
|
|
3607
|
+
"data-testid": `agent-definition-tool-${index}`,
|
|
3608
|
+
children: [
|
|
3609
|
+
/* @__PURE__ */ jsx(Input, {
|
|
3610
|
+
className: "w-48",
|
|
3611
|
+
placeholder: "store/slack",
|
|
3612
|
+
value: row.nodeType,
|
|
3613
|
+
onChange: (e) => setTool(index, { nodeType: e.target.value }),
|
|
3614
|
+
"aria-label": tr("fluidgrids.agents.nodeType", "Node type")
|
|
3615
|
+
}),
|
|
3616
|
+
/* @__PURE__ */ jsx(Input, {
|
|
3617
|
+
className: "min-w-48 flex-1",
|
|
3618
|
+
placeholder: "postMessage, listChannels",
|
|
3619
|
+
value: row.operations,
|
|
3620
|
+
onChange: (e) => setTool(index, { operations: e.target.value }),
|
|
3621
|
+
"aria-label": tr("fluidgrids.agents.operations", "Operations")
|
|
3622
|
+
}),
|
|
3623
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
3624
|
+
variant: "ghost",
|
|
3625
|
+
size: "sm",
|
|
3626
|
+
onClick: () => setForm({
|
|
3627
|
+
...form,
|
|
3628
|
+
tools: form.tools.filter((_, i) => i !== index)
|
|
3629
|
+
}),
|
|
3630
|
+
"aria-label": tr("fluidgrids.agents.removeTool", "Remove tool"),
|
|
3631
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
3632
|
+
icon: "mdi:close",
|
|
3633
|
+
width: 16
|
|
3634
|
+
})
|
|
3635
|
+
})
|
|
3636
|
+
]
|
|
3637
|
+
}, index)),
|
|
3638
|
+
/* @__PURE__ */ jsxs(Button$1, {
|
|
3639
|
+
variant: "outline",
|
|
3640
|
+
size: "sm",
|
|
3641
|
+
onClick: () => setForm({
|
|
3642
|
+
...form,
|
|
3643
|
+
tools: [...form.tools, {
|
|
3644
|
+
nodeType: "",
|
|
3645
|
+
operations: ""
|
|
3646
|
+
}]
|
|
3647
|
+
}),
|
|
3648
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3649
|
+
icon: "mdi:plus",
|
|
3650
|
+
width: 16
|
|
3651
|
+
}), tr("fluidgrids.agents.addTool", "Add tool")]
|
|
3652
|
+
})
|
|
3653
|
+
]
|
|
3654
|
+
}),
|
|
3655
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3656
|
+
className: "space-y-2",
|
|
3657
|
+
children: [/* @__PURE__ */ jsx(Label, { children: tr("fluidgrids.agents.connections", "Connections the agent's tools may use") }), connectionsLoading ? /* @__PURE__ */ jsx("p", {
|
|
3658
|
+
className: "text-xs text-text-secondary",
|
|
3659
|
+
children: tr("fluidgrids.agents.loadingConnections", "Loading connections…")
|
|
3660
|
+
}) : connections.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
3661
|
+
className: "text-xs text-text-secondary",
|
|
3662
|
+
children: tr("fluidgrids.agents.noConnections", "This workspace has no connections yet.")
|
|
3663
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
3664
|
+
className: "grid gap-1 sm:grid-cols-2",
|
|
3665
|
+
children: connections.map((connection) => /* @__PURE__ */ jsxs("label", {
|
|
3666
|
+
className: "flex items-center gap-2 text-sm text-text-primary",
|
|
3667
|
+
children: [
|
|
3668
|
+
/* @__PURE__ */ jsx(Checkbox, {
|
|
3669
|
+
checked: form.connectionScope.includes(connection.id),
|
|
3670
|
+
onCheckedChange: (on) => toggleConnection(connection.id, on === true)
|
|
3671
|
+
}),
|
|
3672
|
+
/* @__PURE__ */ jsx("span", { children: connection.name }),
|
|
3673
|
+
/* @__PURE__ */ jsx("span", {
|
|
3674
|
+
className: "text-xs text-text-tertiary",
|
|
3675
|
+
children: connection.provider?.name ?? connection.providerId
|
|
3676
|
+
})
|
|
3677
|
+
]
|
|
3678
|
+
}, connection.id))
|
|
3679
|
+
})]
|
|
3680
|
+
}),
|
|
3681
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3682
|
+
className: "flex items-center gap-2",
|
|
3683
|
+
children: [/* @__PURE__ */ jsx(Switch, {
|
|
3684
|
+
id: "agent-approval",
|
|
3685
|
+
checked: form.requireToolApproval,
|
|
3686
|
+
onCheckedChange: (on) => setForm({
|
|
3687
|
+
...form,
|
|
3688
|
+
requireToolApproval: on
|
|
3689
|
+
})
|
|
3690
|
+
}), /* @__PURE__ */ jsx(Label, {
|
|
3691
|
+
htmlFor: "agent-approval",
|
|
3692
|
+
children: tr("fluidgrids.agents.requireApproval", "Every tool call waits for a person's approval")
|
|
3693
|
+
})]
|
|
3694
|
+
}),
|
|
3695
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3696
|
+
className: "flex gap-2",
|
|
3697
|
+
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
3698
|
+
onClick: () => void submit(),
|
|
3699
|
+
disabled: busy,
|
|
3700
|
+
"data-testid": "agent-definition-save",
|
|
3701
|
+
children: tr("fluidgrids.agents.save", "Save agent")
|
|
3702
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
3703
|
+
variant: "outline",
|
|
3704
|
+
onClick: onCancel,
|
|
3705
|
+
disabled: busy,
|
|
3706
|
+
children: tr("fluidgrids.agents.cancel", "Cancel")
|
|
3707
|
+
})]
|
|
3708
|
+
})
|
|
3709
|
+
]
|
|
3710
|
+
});
|
|
3711
|
+
}
|
|
3712
|
+
function AgentGrants({ agent, loadGrants, onGrant, onRevoke }) {
|
|
3713
|
+
const tr = useTr();
|
|
3714
|
+
const [grants, setGrants] = useState(null);
|
|
3715
|
+
const [days, setDays] = useState(String(30));
|
|
3716
|
+
const [busy, setBusy] = useState(false);
|
|
3717
|
+
const load = useCallback(async () => {
|
|
3718
|
+
try {
|
|
3719
|
+
setGrants(await loadGrants(agent.id));
|
|
3720
|
+
} catch (err) {
|
|
3721
|
+
setGrants([]);
|
|
3722
|
+
toast.error(errorMessage$1(err));
|
|
3723
|
+
}
|
|
3724
|
+
}, [agent.id, loadGrants]);
|
|
3725
|
+
useEffect(() => {
|
|
3726
|
+
load();
|
|
3727
|
+
}, [load]);
|
|
3728
|
+
const run = async (action, done) => {
|
|
3729
|
+
setBusy(true);
|
|
3730
|
+
try {
|
|
3731
|
+
await action();
|
|
3732
|
+
toast.success(done);
|
|
3733
|
+
await load();
|
|
3734
|
+
} catch (err) {
|
|
3735
|
+
toast.error(errorMessage$1(err));
|
|
3736
|
+
} finally {
|
|
3737
|
+
setBusy(false);
|
|
3738
|
+
}
|
|
3739
|
+
};
|
|
3740
|
+
const mine = grants?.find((grant) => grant.isMine && grant.status === "ACTIVE");
|
|
3741
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3742
|
+
className: "space-y-2",
|
|
3743
|
+
"data-testid": `agent-grants-${agent.id}`,
|
|
3744
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3745
|
+
className: "flex flex-wrap items-center gap-2",
|
|
3746
|
+
children: mine ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
3747
|
+
className: "text-sm text-text-primary",
|
|
3748
|
+
children: mine.expiresAt ? tr("fluidgrids.agents.myGrantUntil", "This agent may act for you until {{date}}.", { date: new Date(mine.expiresAt).toLocaleDateString() }) : tr("fluidgrids.agents.myGrant", "This agent may act for you.")
|
|
3749
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
3750
|
+
variant: "outline",
|
|
3751
|
+
size: "sm",
|
|
3752
|
+
disabled: busy,
|
|
3753
|
+
onClick: () => void run(() => onRevoke(agent.id, null), tr("fluidgrids.agents.withdrawn", "Grant withdrawn")),
|
|
3754
|
+
"data-testid": "agent-grant-withdraw",
|
|
3755
|
+
children: tr("fluidgrids.agents.withdraw", "Withdraw my grant")
|
|
3756
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3757
|
+
/* @__PURE__ */ jsx(Label, {
|
|
3758
|
+
htmlFor: `grant-days-${agent.id}`,
|
|
3759
|
+
className: "text-sm",
|
|
3760
|
+
children: tr("fluidgrids.agents.grantFor", "Let it act for me for")
|
|
3761
|
+
}),
|
|
3762
|
+
/* @__PURE__ */ jsx(Input, {
|
|
3763
|
+
id: `grant-days-${agent.id}`,
|
|
3764
|
+
className: "w-20",
|
|
3765
|
+
type: "number",
|
|
3766
|
+
min: 1,
|
|
3767
|
+
max: 365,
|
|
3768
|
+
value: days,
|
|
3769
|
+
onChange: (e) => setDays(e.target.value)
|
|
3770
|
+
}),
|
|
3771
|
+
/* @__PURE__ */ jsx("span", {
|
|
3772
|
+
className: "text-sm text-text-secondary",
|
|
3773
|
+
children: tr("fluidgrids.agents.days", "days")
|
|
3774
|
+
}),
|
|
3775
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
3776
|
+
size: "sm",
|
|
3777
|
+
disabled: busy || agent.status !== "ACTIVE",
|
|
3778
|
+
onClick: () => void run(async () => onGrant(agent.id, grantDays(days)), tr("fluidgrids.agents.granted", "Grant given")),
|
|
3779
|
+
"data-testid": "agent-grant-give",
|
|
3780
|
+
children: tr("fluidgrids.agents.grant", "Grant")
|
|
3781
|
+
})
|
|
3782
|
+
] })
|
|
3783
|
+
}), grants && grants.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
3784
|
+
className: "space-y-1 text-xs text-text-secondary",
|
|
3785
|
+
children: grants.map((grant) => /* @__PURE__ */ jsxs("li", {
|
|
3786
|
+
className: "flex items-center gap-2",
|
|
3826
3787
|
children: [
|
|
3827
|
-
|
|
3828
|
-
className: "
|
|
3829
|
-
children:
|
|
3788
|
+
/* @__PURE__ */ jsx("span", {
|
|
3789
|
+
className: "font-mono",
|
|
3790
|
+
children: grant.userId
|
|
3830
3791
|
}),
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
children:
|
|
3834
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
3835
|
-
icon: "mdi:transit-connection-variant",
|
|
3836
|
-
className: "mx-auto mb-3 text-text-secondary",
|
|
3837
|
-
width: 32
|
|
3838
|
-
}),
|
|
3839
|
-
/* @__PURE__ */ jsx("p", {
|
|
3840
|
-
className: "font-medium text-text-primary",
|
|
3841
|
-
children: tr("fluidgrids.settings.logStreaming.emptyTitle", "No log destinations yet")
|
|
3842
|
-
}),
|
|
3843
|
-
/* @__PURE__ */ jsx("p", {
|
|
3844
|
-
className: "mt-1 text-sm text-text-secondary",
|
|
3845
|
-
children: tr("fluidgrids.settings.logStreaming.emptyDescription", "Add a webhook, syslog target, or Sentry DSN to start streaming events.")
|
|
3846
|
-
})
|
|
3847
|
-
]
|
|
3792
|
+
/* @__PURE__ */ jsx(Badge, {
|
|
3793
|
+
variant: "outline",
|
|
3794
|
+
children: grant.status
|
|
3848
3795
|
}),
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3796
|
+
grant.expiresAt ? /* @__PURE__ */ jsx("span", { children: tr("fluidgrids.agents.until", "until {{date}}", { date: new Date(grant.expiresAt).toLocaleDateString() }) }) : null,
|
|
3797
|
+
!grant.isMine && grant.status === "ACTIVE" ? /* @__PURE__ */ jsx(Button$1, {
|
|
3798
|
+
variant: "ghost",
|
|
3799
|
+
size: "sm",
|
|
3800
|
+
disabled: busy,
|
|
3801
|
+
onClick: () => void run(() => onRevoke(agent.id, grant.userId), tr("fluidgrids.agents.revoked", "Grant revoked")),
|
|
3802
|
+
children: tr("fluidgrids.agents.revoke", "Revoke")
|
|
3803
|
+
}) : null
|
|
3804
|
+
]
|
|
3805
|
+
}, grant.userId))
|
|
3806
|
+
}) : null]
|
|
3807
|
+
});
|
|
3808
|
+
}
|
|
3809
|
+
function AgentsTab() {
|
|
3810
|
+
const tr = useTr();
|
|
3811
|
+
const { agents, loading, error, save, remove, grants, grant, revoke } = useAgentDefinitions();
|
|
3812
|
+
const [editing, setEditing] = useState(null);
|
|
3813
|
+
const onSave = async (form) => {
|
|
3814
|
+
const input = formToInput$2(form);
|
|
3815
|
+
await save(editing?.id ?? null, input);
|
|
3816
|
+
toast.success(tr("fluidgrids.agents.saved", "Agent saved"));
|
|
3817
|
+
setEditing(null);
|
|
3818
|
+
};
|
|
3819
|
+
const onDelete = async (agent) => {
|
|
3820
|
+
try {
|
|
3821
|
+
await remove(agent.id);
|
|
3822
|
+
toast.success(tr("fluidgrids.agents.deleted", "Agent deleted"));
|
|
3823
|
+
} catch (err) {
|
|
3824
|
+
toast.error(errorMessage$1(err));
|
|
3825
|
+
}
|
|
3826
|
+
};
|
|
3827
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3828
|
+
className: "space-y-4",
|
|
3829
|
+
"data-testid": "agents-tab",
|
|
3830
|
+
children: [
|
|
3831
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3832
|
+
className: "flex flex-wrap items-start justify-between gap-2",
|
|
3833
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
3834
|
+
className: "text-base font-semibold text-text-primary",
|
|
3835
|
+
children: tr("fluidgrids.agents.title", "Agents")
|
|
3836
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
3837
|
+
className: "text-sm text-text-secondary",
|
|
3838
|
+
children: tr("fluidgrids.agents.subtitle", "Give an AI Agent node an identity of its own. It can only call the tools and connections you allow, only for people who granted it, and every tool call is recorded under the agent and the person.")
|
|
3839
|
+
})] }), !editing ? /* @__PURE__ */ jsxs(Button$1, {
|
|
3840
|
+
onClick: () => setEditing({
|
|
3841
|
+
id: null,
|
|
3842
|
+
form: emptyAgentForm()
|
|
3843
|
+
}),
|
|
3844
|
+
"data-testid": "agent-definition-new",
|
|
3845
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3846
|
+
icon: "mdi:plus",
|
|
3847
|
+
width: 16
|
|
3848
|
+
}), tr("fluidgrids.agents.new", "New agent")]
|
|
3849
|
+
}) : null]
|
|
3850
|
+
}),
|
|
3851
|
+
editing ? /* @__PURE__ */ jsx(AgentEditor, {
|
|
3852
|
+
initial: editing.form,
|
|
3853
|
+
onCancel: () => setEditing(null),
|
|
3854
|
+
onSave
|
|
3855
|
+
}) : null,
|
|
3856
|
+
error ? /* @__PURE__ */ jsx("p", {
|
|
3857
|
+
className: "text-sm text-destructive",
|
|
3858
|
+
children: errorMessage$1(error)
|
|
3859
|
+
}) : null,
|
|
3860
|
+
loading ? /* @__PURE__ */ jsx("p", {
|
|
3861
|
+
className: "text-sm text-text-secondary",
|
|
3862
|
+
children: tr("fluidgrids.agents.loading", "Loading agents…")
|
|
3863
|
+
}) : agents.length === 0 && !error ? /* @__PURE__ */ jsx("p", {
|
|
3864
|
+
className: "text-sm text-text-secondary",
|
|
3865
|
+
children: tr("fluidgrids.agents.empty", "No agents yet.")
|
|
3866
|
+
}) : /* @__PURE__ */ jsx("ul", {
|
|
3867
|
+
className: "space-y-3",
|
|
3868
|
+
children: agents.map((agent) => /* @__PURE__ */ jsxs("li", {
|
|
3869
|
+
className: "rounded-lg border border-border-secondary bg-background-secondary p-3 space-y-2",
|
|
3870
|
+
"data-testid": `agent-definition-${agent.id}`,
|
|
3871
|
+
children: [
|
|
3872
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3873
|
+
className: "flex flex-wrap items-center justify-between gap-2",
|
|
3853
3874
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
3854
|
-
className: "
|
|
3875
|
+
className: "flex items-center gap-2",
|
|
3855
3876
|
children: [
|
|
3856
|
-
/* @__PURE__ */
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
/* @__PURE__ */ jsx("h3", {
|
|
3860
|
-
className: "font-medium text-text-primary",
|
|
3861
|
-
children: destination.name
|
|
3862
|
-
}),
|
|
3863
|
-
/* @__PURE__ */ jsx("span", {
|
|
3864
|
-
className: "rounded-full bg-background-tertiary px-2 py-0.5 text-xs text-text-secondary",
|
|
3865
|
-
children: destination.provider
|
|
3866
|
-
}),
|
|
3867
|
-
/* @__PURE__ */ jsx("span", {
|
|
3868
|
-
className: destination.isEnabled ? "text-xs text-status-success-text" : "text-xs text-text-secondary",
|
|
3869
|
-
children: destination.isEnabled ? tr("fluidgrids.settings.logStreaming.enabledBadge", "Enabled") : tr("fluidgrids.settings.logStreaming.disabledBadge", "Disabled")
|
|
3870
|
-
})
|
|
3871
|
-
]
|
|
3872
|
-
}),
|
|
3873
|
-
/* @__PURE__ */ jsx("p", {
|
|
3874
|
-
className: "mt-1 truncate text-sm text-text-secondary",
|
|
3875
|
-
children: destination.endpoint
|
|
3877
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
3878
|
+
icon: "mdi:robot-outline",
|
|
3879
|
+
width: 18
|
|
3876
3880
|
}),
|
|
3877
|
-
/* @__PURE__ */
|
|
3878
|
-
className: "
|
|
3879
|
-
children:
|
|
3881
|
+
/* @__PURE__ */ jsx("span", {
|
|
3882
|
+
className: "font-medium text-text-primary",
|
|
3883
|
+
children: agent.name
|
|
3880
3884
|
}),
|
|
3881
|
-
|
|
3882
|
-
className: "mt-2 text-xs text-status-error-text",
|
|
3883
|
-
children: destination.lastDispatchError
|
|
3884
|
-
})
|
|
3885
|
-
]
|
|
3886
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3887
|
-
className: "flex shrink-0 flex-wrap gap-2",
|
|
3888
|
-
children: [
|
|
3889
|
-
/* @__PURE__ */ jsxs(Button$1, {
|
|
3885
|
+
/* @__PURE__ */ jsx(Badge, {
|
|
3890
3886
|
variant: "outline",
|
|
3891
|
-
|
|
3892
|
-
onClick: () => void sendTest(destination),
|
|
3893
|
-
disabled: actions.loading,
|
|
3894
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3895
|
-
icon: "mdi:send-check-outline",
|
|
3896
|
-
className: "mr-1",
|
|
3897
|
-
width: 15
|
|
3898
|
-
}), tr("fluidgrids.settings.logStreaming.test", "Send test")]
|
|
3887
|
+
children: agent.status
|
|
3899
3888
|
}),
|
|
3900
|
-
/* @__PURE__ */ jsx(
|
|
3889
|
+
agent.requireToolApproval ? /* @__PURE__ */ jsx(Badge, {
|
|
3901
3890
|
variant: "outline",
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
setEditingId(destination.id);
|
|
3905
|
-
setShowForm(true);
|
|
3906
|
-
},
|
|
3907
|
-
disabled: actions.loading,
|
|
3908
|
-
children: tr("fluidgrids.settings.logStreaming.editButton", "Edit")
|
|
3909
|
-
}),
|
|
3910
|
-
/* @__PURE__ */ jsxs(Button$1, {
|
|
3911
|
-
variant: "ghost",
|
|
3912
|
-
size: "sm",
|
|
3913
|
-
onClick: () => void remove(destination),
|
|
3914
|
-
disabled: actions.loading,
|
|
3915
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
3916
|
-
icon: "mdi:trash-can-outline",
|
|
3917
|
-
className: "text-status-error-text",
|
|
3918
|
-
width: 17
|
|
3919
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
3920
|
-
className: "sr-only",
|
|
3921
|
-
children: tr("fluidgrids.settings.logStreaming.delete", "Delete")
|
|
3922
|
-
})]
|
|
3923
|
-
})
|
|
3891
|
+
children: tr("fluidgrids.agents.approvalBadge", "Approval required")
|
|
3892
|
+
}) : null
|
|
3924
3893
|
]
|
|
3894
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3895
|
+
className: "flex gap-1",
|
|
3896
|
+
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
3897
|
+
variant: "ghost",
|
|
3898
|
+
size: "sm",
|
|
3899
|
+
onClick: () => setEditing({
|
|
3900
|
+
id: agent.id,
|
|
3901
|
+
form: agentToForm(agent)
|
|
3902
|
+
}),
|
|
3903
|
+
children: tr("fluidgrids.agents.edit", "Edit")
|
|
3904
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
3905
|
+
variant: "ghost",
|
|
3906
|
+
size: "sm",
|
|
3907
|
+
onClick: () => void onDelete(agent),
|
|
3908
|
+
children: tr("fluidgrids.agents.delete", "Delete")
|
|
3909
|
+
})]
|
|
3925
3910
|
})]
|
|
3911
|
+
}),
|
|
3912
|
+
agent.description ? /* @__PURE__ */ jsx("p", {
|
|
3913
|
+
className: "text-sm text-text-secondary",
|
|
3914
|
+
children: agent.description
|
|
3915
|
+
}) : null,
|
|
3916
|
+
/* @__PURE__ */ jsx("div", {
|
|
3917
|
+
className: "text-xs text-text-secondary",
|
|
3918
|
+
children: agent.toolAllowlist.length > 0 ? agent.toolAllowlist.map(describeRule).join(" · ") : tr("fluidgrids.agents.noTools", "No tools allowed")
|
|
3919
|
+
}),
|
|
3920
|
+
/* @__PURE__ */ jsx("div", {
|
|
3921
|
+
className: "text-xs text-text-tertiary",
|
|
3922
|
+
children: tr("fluidgrids.agents.connectionCount", "{{count}} connections in scope", { count: agent.connectionScope.length })
|
|
3923
|
+
}),
|
|
3924
|
+
/* @__PURE__ */ jsx(AgentGrants, {
|
|
3925
|
+
agent,
|
|
3926
|
+
loadGrants: grants,
|
|
3927
|
+
onGrant: grant,
|
|
3928
|
+
onRevoke: revoke
|
|
3926
3929
|
})
|
|
3927
|
-
|
|
3928
|
-
|
|
3930
|
+
]
|
|
3931
|
+
}, agent.id))
|
|
3929
3932
|
})
|
|
3930
3933
|
]
|
|
3931
3934
|
});
|
|
@@ -5202,6 +5205,7 @@ function isRecord(value) {
|
|
|
5202
5205
|
}
|
|
5203
5206
|
|
|
5204
5207
|
// src/modules/settings/pages/SettingsPage.tsx
|
|
5208
|
+
var SettingsPage_exports = /* @__PURE__ */ __exportAll({ SettingsPage: () => SettingsPage });
|
|
5205
5209
|
/**
|
|
5206
5210
|
* A workflow's `definitionJson.config` (a sibling of `data`, not nested inside it): the same
|
|
5207
5211
|
* shared type the SDK exports, so the form and typed readers agree on every field.
|
|
@@ -5984,38 +5988,4 @@ function SettingsPage({ workflowKey: workflowKeyProp } = {}) {
|
|
|
5984
5988
|
});
|
|
5985
5989
|
}
|
|
5986
5990
|
|
|
5987
|
-
|
|
5988
|
-
/** Hosts explicitly bridge their authority; a missing profile never becomes an embed fallback. */
|
|
5989
|
-
function ManagedAiPolicyAuthorityProvider({ scope, children }) {
|
|
5990
|
-
const { authority, url, actorId, workspaceId, organizationId, tenantId, projectId, authToken, workspaceToken } = scope ?? {};
|
|
5991
|
-
const value = useMemo(() => {
|
|
5992
|
-
if (!authority || !url || !actorId || !workspaceId || !organizationId || !tenantId || !authToken) return null;
|
|
5993
|
-
return Object.freeze({
|
|
5994
|
-
authority,
|
|
5995
|
-
url,
|
|
5996
|
-
actorId,
|
|
5997
|
-
workspaceId,
|
|
5998
|
-
organizationId,
|
|
5999
|
-
tenantId,
|
|
6000
|
-
projectId,
|
|
6001
|
-
authToken,
|
|
6002
|
-
workspaceToken
|
|
6003
|
-
});
|
|
6004
|
-
}, [
|
|
6005
|
-
authority,
|
|
6006
|
-
url,
|
|
6007
|
-
actorId,
|
|
6008
|
-
workspaceId,
|
|
6009
|
-
organizationId,
|
|
6010
|
-
tenantId,
|
|
6011
|
-
projectId,
|
|
6012
|
-
authToken,
|
|
6013
|
-
workspaceToken
|
|
6014
|
-
]);
|
|
6015
|
-
return /* @__PURE__ */ jsx(ManagedAiAuthorityContext.Provider, {
|
|
6016
|
-
value,
|
|
6017
|
-
children
|
|
6018
|
-
});
|
|
6019
|
-
}
|
|
6020
|
-
|
|
6021
|
-
export { SettingsPage as n, ManagedAiPolicyAuthorityProvider as t };
|
|
5991
|
+
export { SettingsPage_exports as n, SettingsPage as t };
|