@anchrd/intel-ui 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/flows/flows.tsx +285 -35
- package/src/i18n/de.json +17 -4
- package/src/i18n/en.json +16 -3
- package/src/i18n/es.json +16 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anchrd/intel-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"typecheck": "tsc --noEmit"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@anchrd/intel-contract": "^0.
|
|
36
|
+
"@anchrd/intel-contract": "^0.19.0",
|
|
37
37
|
"@blocknote/core": "^0.52.1",
|
|
38
38
|
"@blocknote/react": "^0.52.1",
|
|
39
39
|
"@blocknote/shadcn": "^0.52.1",
|
package/src/flows/flows.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Flow, FlowGraph, FlowNode } from "@anchrd/intel-contract/flow";
|
|
2
2
|
import { flowNodeLayer } from "@anchrd/intel-contract/flow";
|
|
3
3
|
import type { Node } from "@anchrd/intel-contract/node";
|
|
4
|
+
import { serverOf } from "@anchrd/intel-contract/tool";
|
|
4
5
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
5
6
|
import { useNavigate, useRouterState } from "@tanstack/react-router";
|
|
6
7
|
import {
|
|
@@ -367,9 +368,25 @@ function FlowsEditor() {
|
|
|
367
368
|
const navigate = useNavigate();
|
|
368
369
|
// The servers a tool step can name (#489). The flat function list the picker used to show is
|
|
369
370
|
// what that ticket set out to remove; which function runs is decided while the flow runs.
|
|
371
|
+
// ⚠️ The flat function list is NOT what a step is chosen from any more (#489) — it is only what
|
|
372
|
+
// an author narrows a chosen server WITH. It is asked for regardless of whether a tool step is
|
|
373
|
+
// selected, because a query that starts when a panel opens shows a spinner inside the panel.
|
|
374
|
+
const tools = useQuery({
|
|
375
|
+
queryKey: ["tools"],
|
|
376
|
+
queryFn: () => data.listTools(),
|
|
377
|
+
// ⚠️ No retry. This query only ENRICHES the panel — the server is already chosen without it —
|
|
378
|
+
// and a retry is paused while the tab is unfocused, so a deterministic failure would leave the
|
|
379
|
+
// function list empty for as long as the reader looks away, with nothing saying why (#212).
|
|
380
|
+
retry: false,
|
|
381
|
+
});
|
|
370
382
|
const toolServers = useQuery({
|
|
371
383
|
queryKey: ["tool-servers"],
|
|
372
384
|
queryFn: () => data.listToolServers(),
|
|
385
|
+
// ⚠️ No retry here either, and for a sharper reason than the list above: the panel shows
|
|
386
|
+
// NOTHING while this is pending. A deterministic 502 with an unfocused tab pauses the retry,
|
|
387
|
+
// and the author then sits in front of an empty server field with no sentence saying why —
|
|
388
|
+
// which is #212 exactly. `error` is a state this panel can speak; `pending` is not.
|
|
389
|
+
retry: false,
|
|
373
390
|
});
|
|
374
391
|
// A tree link points at a node, so the editor needs candidates. The graph is the authorized
|
|
375
392
|
// flat list of them; walking the folder tree for a picker would be the N+1 all over again.
|
|
@@ -420,6 +437,13 @@ function FlowsEditor() {
|
|
|
420
437
|
// guarantee that the loaded document is both the selected flow and settled.
|
|
421
438
|
const documentReady = selectedFlowId !== null && document.data?.flow.id === selectedFlowId;
|
|
422
439
|
const canMutate = documentReady && !document.isFetching;
|
|
440
|
+
// ⚠️ A tool step without a server cannot be saved at all — `ToolServerHandle` has a minimum
|
|
441
|
+
// length. Letting the request go out anyway answers with a generic failure that names no step, so
|
|
442
|
+
// the author learns "something is wrong" instead of "this one needs a server". The refusal
|
|
443
|
+
// belongs here, before the write (#517).
|
|
444
|
+
const stepsMissingServer = nodes.filter(
|
|
445
|
+
(node) => node.data.node.kind === "tool" && node.data.node.configuration.server === "",
|
|
446
|
+
);
|
|
423
447
|
useEffect(() => {
|
|
424
448
|
if (!document.data || document.data.flow.id !== selectedFlowId) return;
|
|
425
449
|
const next = canvas(document.data.version?.graph ?? defaultGraph());
|
|
@@ -468,6 +492,7 @@ function FlowsEditor() {
|
|
|
468
492
|
dirty={dirty}
|
|
469
493
|
saving={save.isPending}
|
|
470
494
|
canMutate={canMutate}
|
|
495
|
+
incomplete={stepsMissingServer.map((node) => ({ label: node.data.node.label }))}
|
|
471
496
|
onSave={() => save.mutate()}
|
|
472
497
|
onPublish={() => setPublishing(true)}
|
|
473
498
|
/>
|
|
@@ -647,6 +672,18 @@ function FlowsEditor() {
|
|
|
647
672
|
node={selectedNode}
|
|
648
673
|
update={updateNode}
|
|
649
674
|
toolServers={toolServers.data?.items ?? []}
|
|
675
|
+
toolServersState={
|
|
676
|
+
toolServers.isPending
|
|
677
|
+
? "pending"
|
|
678
|
+
: toolServers.isError
|
|
679
|
+
? "error"
|
|
680
|
+
: toolServers.data?.portalConnected === false
|
|
681
|
+
? "disconnected"
|
|
682
|
+
: "ready"
|
|
683
|
+
}
|
|
684
|
+
toolNames={(tools.data?.items ?? []).map((entry) => entry.name)}
|
|
685
|
+
toolNamesFailed={tools.isError}
|
|
686
|
+
toolNamesPending={tools.isPending}
|
|
650
687
|
flows={(callable.data?.items ?? []).filter(
|
|
651
688
|
(entry) => entry.id !== selectedFlowId,
|
|
652
689
|
)}
|
|
@@ -707,6 +744,7 @@ function FlowTitle({
|
|
|
707
744
|
dirty,
|
|
708
745
|
saving,
|
|
709
746
|
canMutate,
|
|
747
|
+
incomplete,
|
|
710
748
|
onSave,
|
|
711
749
|
onPublish,
|
|
712
750
|
}: {
|
|
@@ -714,6 +752,9 @@ function FlowTitle({
|
|
|
714
752
|
dirty: boolean;
|
|
715
753
|
saving: boolean;
|
|
716
754
|
canMutate: boolean;
|
|
755
|
+
// Tool steps that name no server yet. They cannot be saved, so the refusal is shown here rather
|
|
756
|
+
// than fetched from the server as a message that names no step.
|
|
757
|
+
incomplete: Array<{ label: string }>;
|
|
717
758
|
onSave(): void;
|
|
718
759
|
onPublish(): void;
|
|
719
760
|
}) {
|
|
@@ -740,7 +781,16 @@ function FlowTitle({
|
|
|
740
781
|
applies EVERYWHERE stands. But it says how THIS flow is shown, and so belongs in the line
|
|
741
782
|
that names this flow. A flow is the only level with runs, and therefore the only one with
|
|
742
783
|
three views (#35). */}
|
|
743
|
-
|
|
784
|
+
{incomplete.length > 0 && (
|
|
785
|
+
<p className="mr-2 text-xs text-destructive">
|
|
786
|
+
{i18n.t("flows.toolStepNeedsServer", { label: incomplete[0]?.label ?? "" })}
|
|
787
|
+
</p>
|
|
788
|
+
)}
|
|
789
|
+
<SaveButton
|
|
790
|
+
dirty={dirty && canMutate && incomplete.length === 0}
|
|
791
|
+
saving={saving}
|
|
792
|
+
onSave={onSave}
|
|
793
|
+
/>
|
|
744
794
|
<TooltipProvider delayDuration={300}>
|
|
745
795
|
<Tooltip>
|
|
746
796
|
<TooltipTrigger asChild>
|
|
@@ -804,10 +854,34 @@ function PublishPreview({
|
|
|
804
854
|
) : (
|
|
805
855
|
<>
|
|
806
856
|
<p className="text-sm text-muted-foreground">
|
|
807
|
-
{preview.data.calls.length === 0
|
|
857
|
+
{preview.data.calls.length === 0 && preview.data.tools.length === 0
|
|
808
858
|
? i18n.t("flows.publishPreviewEmpty")
|
|
809
859
|
: i18n.t("flows.publishPreviewIntro")}
|
|
810
860
|
</p>
|
|
861
|
+
{/* ⚠️ The tool surface belongs in the preview because publishing FREEZES it: after this
|
|
862
|
+
confirmation the step is pinned to these functions and inherits nothing the provider
|
|
863
|
+
adds later. An author who is not shown it is asked to freeze something unseen (#517). */}
|
|
864
|
+
{preview.data.tools.length > 0 && (
|
|
865
|
+
<ul className="mt-4 space-y-2">
|
|
866
|
+
{preview.data.tools.map((tool) => (
|
|
867
|
+
<li key={tool.nodeId} className="rounded-md border p-3 text-sm">
|
|
868
|
+
<span className="block font-medium">{tool.nodeLabel}</span>
|
|
869
|
+
<span className="block text-xs text-muted-foreground">{tool.server}</span>
|
|
870
|
+
<span
|
|
871
|
+
className={`mt-1 block text-xs ${tool.available ? "text-muted-foreground" : "text-destructive"}`}
|
|
872
|
+
>
|
|
873
|
+
{!tool.available
|
|
874
|
+
? i18n.t("flows.publishPreviewToolUnavailable")
|
|
875
|
+
: tool.allow === null
|
|
876
|
+
? i18n.t("flows.toolAllowAll")
|
|
877
|
+
: i18n.t("flows.publishPreviewToolAllow", {
|
|
878
|
+
functions: tool.allow.join(", "),
|
|
879
|
+
})}
|
|
880
|
+
</span>
|
|
881
|
+
</li>
|
|
882
|
+
))}
|
|
883
|
+
</ul>
|
|
884
|
+
)}
|
|
811
885
|
<ul className="mt-4 space-y-2">
|
|
812
886
|
{preview.data.calls.map((call) => {
|
|
813
887
|
// ⚠️ One condition for the sentence and its colour. They were two, so a call that
|
|
@@ -860,11 +934,29 @@ function NodeInspector({
|
|
|
860
934
|
node,
|
|
861
935
|
update,
|
|
862
936
|
toolServers,
|
|
937
|
+
toolServersState,
|
|
938
|
+
toolNames,
|
|
939
|
+
toolNamesFailed,
|
|
940
|
+
toolNamesPending,
|
|
863
941
|
flows,
|
|
864
942
|
}: {
|
|
865
943
|
node: CanvasNode | null;
|
|
866
944
|
update(fn: (node: FlowNode) => FlowNode): void;
|
|
867
945
|
toolServers: Array<{ handle: string; name: string; toolCount: number }>;
|
|
946
|
+
// ⚠️ FOUR answers, not two. A list that is still loading is not one that came back empty; a
|
|
947
|
+
// failure is neither; and a portal this user never connected is not a portal that reaches
|
|
948
|
+
// nothing. Drawing them all as "no servers" is the mistake #350 records for the tools screen —
|
|
949
|
+
// and the fourth one is the worst of them: it answers a SIGN-IN problem with a sentence about
|
|
950
|
+
// reach, in a place that offers no way to sign in.
|
|
951
|
+
toolServersState: "pending" | "error" | "disconnected" | "ready";
|
|
952
|
+
toolNames: string[];
|
|
953
|
+
// Told apart from "this server offers nothing": a function list that could not be loaded must not
|
|
954
|
+
// read as a narrowing that lost its functions.
|
|
955
|
+
toolNamesFailed: boolean;
|
|
956
|
+
// ⚠️ A query that has not answered is not one that answered "nothing". Without this a step opened
|
|
957
|
+
// while the catalog is still loading shows its allowed functions as missing — the panel accusing
|
|
958
|
+
// the author of a narrowing that broke, moments before the list arrives.
|
|
959
|
+
toolNamesPending: boolean;
|
|
868
960
|
flows: Flow[];
|
|
869
961
|
}) {
|
|
870
962
|
const i18n = useI18n();
|
|
@@ -953,40 +1045,198 @@ function NodeInspector({
|
|
|
953
1045
|
</div>
|
|
954
1046
|
)}
|
|
955
1047
|
{contract.kind === "tool" && (
|
|
956
|
-
<
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1048
|
+
<ToolStepFields
|
|
1049
|
+
configuration={contract.configuration}
|
|
1050
|
+
servers={toolServers}
|
|
1051
|
+
state={toolServersState}
|
|
1052
|
+
toolNames={toolNames}
|
|
1053
|
+
toolNamesFailed={toolNamesFailed}
|
|
1054
|
+
toolNamesPending={toolNamesPending}
|
|
1055
|
+
update={update}
|
|
1056
|
+
/>
|
|
1057
|
+
)}
|
|
1058
|
+
</div>
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* What a tool step may reach: one server, and optionally only some of its functions.
|
|
1064
|
+
*
|
|
1065
|
+
* ⚠️ The server comes first and the functions are a NARROWING, not the other way round (#489). The
|
|
1066
|
+
* old field offered every function of every server in one flat list — 85 entries here, portal
|
|
1067
|
+
* management tools among them — and asked the author to pick the one call they wanted before they
|
|
1068
|
+
* knew what the step would say. Which function runs is a run-time answer; which server may be
|
|
1069
|
+
* reached is an authoring decision, and that is the one this asks for.
|
|
1070
|
+
*/
|
|
1071
|
+
export function ToolStepFields({
|
|
1072
|
+
configuration,
|
|
1073
|
+
servers,
|
|
1074
|
+
state,
|
|
1075
|
+
toolNames,
|
|
1076
|
+
toolNamesFailed,
|
|
1077
|
+
toolNamesPending,
|
|
1078
|
+
update,
|
|
1079
|
+
}: {
|
|
1080
|
+
configuration: { server: string; allow: string[] | null; fingerprint: string | null };
|
|
1081
|
+
servers: Array<{ handle: string; name: string; toolCount: number }>;
|
|
1082
|
+
state: "pending" | "error" | "disconnected" | "ready";
|
|
1083
|
+
toolNames: string[];
|
|
1084
|
+
toolNamesFailed: boolean;
|
|
1085
|
+
toolNamesPending: boolean;
|
|
1086
|
+
update(fn: (node: FlowNode) => FlowNode): void;
|
|
1087
|
+
}) {
|
|
1088
|
+
const i18n = useI18n();
|
|
1089
|
+
// ⚠️ The group's identity, not its data. Two steps on one screen with the same server would
|
|
1090
|
+
// otherwise share one radio group and unset each other — and the component is exported now, so
|
|
1091
|
+
// that invariant no longer lives in the file that guarantees it.
|
|
1092
|
+
const groupId = useId();
|
|
1093
|
+
const hintId = `${groupId}-hint`;
|
|
1094
|
+
// The one sentence this field has to say, or none. Derived once so the control and the paragraph
|
|
1095
|
+
// cannot disagree about whether there is something to point at.
|
|
1096
|
+
const hint =
|
|
1097
|
+
state === "error"
|
|
1098
|
+
? ({ key: "flows.toolServersFailed", tone: "bad" } as const)
|
|
1099
|
+
: state === "disconnected"
|
|
1100
|
+
? ({ key: "flows.toolServersDisconnected", tone: "bad" } as const)
|
|
1101
|
+
: state === "ready" && servers.length === 0
|
|
1102
|
+
? ({ key: "flows.toolServersEmpty", tone: "plain" } as const)
|
|
1103
|
+
: null;
|
|
1104
|
+
const ownFunctions = toolNames.filter(
|
|
1105
|
+
(name) => configuration.server !== "" && serverOf(name, [configuration.server]) !== null,
|
|
1106
|
+
);
|
|
1107
|
+
// ⚠️ An allowed function the catalog does not carry is DRAWN, not dropped. Rendering only what
|
|
1108
|
+
// the catalog knows would let the panel and the saved graph disagree in silence: the author reads
|
|
1109
|
+
// "narrowed to nothing" while the step still names something. The API treats the same condition
|
|
1110
|
+
// as serious enough to refuse a publish, so the editor may not swallow it.
|
|
1111
|
+
// Nothing is "missing" until the catalog has actually answered.
|
|
1112
|
+
const missing = toolNamesPending
|
|
1113
|
+
? []
|
|
1114
|
+
: (configuration.allow ?? []).filter((name) => !ownFunctions.includes(name));
|
|
1115
|
+
const functions = [...ownFunctions, ...missing];
|
|
1116
|
+
|
|
1117
|
+
function setTool(
|
|
1118
|
+
change: (current: { server: string; allow: string[] | null; fingerprint: string | null }) => {
|
|
1119
|
+
server: string;
|
|
1120
|
+
allow: string[] | null;
|
|
1121
|
+
fingerprint: string | null;
|
|
1122
|
+
},
|
|
1123
|
+
) {
|
|
1124
|
+
update((value) =>
|
|
1125
|
+
value.kind === "tool" ? { ...value, configuration: change(value.configuration) } : value,
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
return (
|
|
1130
|
+
<div className="mt-4 space-y-3">
|
|
1131
|
+
<label className="block text-sm font-medium">
|
|
1132
|
+
{i18n.t("flows.tool")}
|
|
1133
|
+
<select
|
|
1134
|
+
value={configuration.server}
|
|
1135
|
+
// ⚠️ A disabled control drops out of the tab order, so the reason has to be ANNOUNCED
|
|
1136
|
+
// rather than merely printed beside it. It points at the hint only when the hint is
|
|
1137
|
+
// actually rendered — `pending` prints nothing on purpose, and a reference to an id that
|
|
1138
|
+
// does not exist is worse than none: a screen reader reads it as a broken relation.
|
|
1139
|
+
aria-describedby={hint === null ? undefined : hintId}
|
|
1140
|
+
disabled={state !== "ready" || servers.length === 0}
|
|
1141
|
+
onChange={(event) => {
|
|
1142
|
+
// ⚠️ Read out of the event NOW, not inside the updater. The updater runs later, and by
|
|
1143
|
+
// then this controlled select has been set back to the state's value — the change would
|
|
1144
|
+
// apply to itself and nothing would move.
|
|
1145
|
+
const server = event.target.value;
|
|
1146
|
+
// Changing the server drops the narrowing AND the frozen surface. Keeping `allow` would
|
|
1147
|
+
// leave functions of the old server behind — the contract refuses that outright — and
|
|
1148
|
+
// keeping the fingerprint would claim a surface nobody has confirmed.
|
|
1149
|
+
setTool(() => ({ server, allow: null, fingerprint: null }));
|
|
1150
|
+
}}
|
|
1151
|
+
className="mt-2 w-full rounded-md border bg-background px-3 py-2 outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
|
|
1152
|
+
>
|
|
1153
|
+
<option value="">{i18n.t("flows.selectTool")}</option>
|
|
1154
|
+
{servers.map((entry) => (
|
|
1155
|
+
<option key={entry.handle} value={entry.handle}>
|
|
1156
|
+
{entry.name}
|
|
1157
|
+
</option>
|
|
1158
|
+
))}
|
|
1159
|
+
</select>
|
|
1160
|
+
</label>
|
|
1161
|
+
{/* The three states of the list, told apart. Silence while loading; a reason when it failed;
|
|
1162
|
+
and "you reach none" only once that is actually known. */}
|
|
1163
|
+
{hint !== null && (
|
|
1164
|
+
<p
|
|
1165
|
+
id={hintId}
|
|
1166
|
+
className={`text-xs ${hint.tone === "bad" ? "text-destructive" : "text-muted-foreground"}`}
|
|
1167
|
+
>
|
|
1168
|
+
{i18n.t(hint.key)}
|
|
1169
|
+
</p>
|
|
1170
|
+
)}
|
|
1171
|
+
{configuration.server !== "" && (
|
|
1172
|
+
<fieldset className="space-y-2">
|
|
1173
|
+
<legend className="text-sm font-medium">{i18n.t("flows.toolFunctions")}</legend>
|
|
1174
|
+
<label className="flex items-center gap-2 text-sm">
|
|
1175
|
+
<input
|
|
1176
|
+
type="radio"
|
|
1177
|
+
name={groupId}
|
|
1178
|
+
checked={configuration.allow === null}
|
|
1179
|
+
onChange={() =>
|
|
1180
|
+
setTool((current) => ({ ...current, allow: null, fingerprint: null }))
|
|
1181
|
+
}
|
|
1182
|
+
className="size-4"
|
|
1183
|
+
/>
|
|
1184
|
+
{i18n.t("flows.toolAllowAll")}
|
|
988
1185
|
</label>
|
|
989
|
-
|
|
1186
|
+
<label className="flex items-center gap-2 text-sm">
|
|
1187
|
+
<input
|
|
1188
|
+
type="radio"
|
|
1189
|
+
name={groupId}
|
|
1190
|
+
checked={configuration.allow !== null}
|
|
1191
|
+
onChange={() => setTool((current) => ({ ...current, allow: [], fingerprint: null }))}
|
|
1192
|
+
className="size-4"
|
|
1193
|
+
/>
|
|
1194
|
+
{i18n.t("flows.toolAllowSome")}
|
|
1195
|
+
</label>
|
|
1196
|
+
{configuration.allow !== null && (
|
|
1197
|
+
<ul className="max-h-48 space-y-1 overflow-y-auto pl-6">
|
|
1198
|
+
{functions.map((name) => (
|
|
1199
|
+
<li key={name}>
|
|
1200
|
+
<label className="flex items-center gap-2 text-sm">
|
|
1201
|
+
<input
|
|
1202
|
+
type="checkbox"
|
|
1203
|
+
checked={configuration.allow?.includes(name) ?? false}
|
|
1204
|
+
onChange={(event) => {
|
|
1205
|
+
// Same reason as the select above: the checked flag is read now, the
|
|
1206
|
+
// updater runs later.
|
|
1207
|
+
const add = event.target.checked;
|
|
1208
|
+
setTool((current) => ({
|
|
1209
|
+
...current,
|
|
1210
|
+
allow: add
|
|
1211
|
+
? [...(current.allow ?? []), name]
|
|
1212
|
+
: (current.allow ?? []).filter((entry) => entry !== name),
|
|
1213
|
+
fingerprint: null,
|
|
1214
|
+
}));
|
|
1215
|
+
}}
|
|
1216
|
+
className="size-4"
|
|
1217
|
+
/>
|
|
1218
|
+
<span className="min-w-0 truncate">{name}</span>
|
|
1219
|
+
</label>
|
|
1220
|
+
</li>
|
|
1221
|
+
))}
|
|
1222
|
+
</ul>
|
|
1223
|
+
)}
|
|
1224
|
+
{/* Two sentences that only appear when they are true, and neither is the generic hint:
|
|
1225
|
+
a narrowing to nothing cannot be published, and a name the catalog does not carry is
|
|
1226
|
+
something the author has to see rather than lose. */}
|
|
1227
|
+
{configuration.allow?.length === 0 && (
|
|
1228
|
+
<p className="text-xs text-destructive">{i18n.t("flows.toolAllowNone")}</p>
|
|
1229
|
+
)}
|
|
1230
|
+
{toolNamesFailed && (
|
|
1231
|
+
<p className="text-xs text-destructive">{i18n.t("flows.toolFunctionsFailed")}</p>
|
|
1232
|
+
)}
|
|
1233
|
+
{!toolNamesFailed && missing.length > 0 && (
|
|
1234
|
+
<p className="text-xs text-destructive">
|
|
1235
|
+
{i18n.t("flows.toolAllowUnknown", { count: missing.length })}
|
|
1236
|
+
</p>
|
|
1237
|
+
)}
|
|
1238
|
+
<p className="text-xs text-muted-foreground">{i18n.t("flows.toolAllowHint")}</p>
|
|
1239
|
+
</fieldset>
|
|
990
1240
|
)}
|
|
991
1241
|
</div>
|
|
992
1242
|
);
|
package/src/i18n/de.json
CHANGED
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"archive.restoreFailed": "Es wurde nicht wiederhergestellt. Vielleicht hat jemand anderes es geändert — lade neu und versuche es erneut.",
|
|
98
98
|
"archive.purge": "{title} endgültig löschen",
|
|
99
99
|
"archive.purge.title": "Endgültig löschen?",
|
|
100
|
-
"archive.purge.body": "„{title}
|
|
100
|
+
"archive.purge.body": "„{title}“ und alles, was dazugehört — jede Version, der Inhalt und die Einträge im Suchindex — ist danach weg. Das lässt sich nicht rückgängig machen.",
|
|
101
101
|
"archive.purge.links.none": "Keine anderen Dokumente verweisen darauf.",
|
|
102
102
|
"archive.purge.links.one": "Ein anderes Dokument verweist darauf; dieser Verweis wird brechen.",
|
|
103
103
|
"archive.purge.links.many": "{count} andere Dokumente verweisen darauf; diese Verweise werden brechen.",
|
|
@@ -275,8 +275,8 @@
|
|
|
275
275
|
"flows.publishPreviewUnavailable": "Der aufgerufene Flow hat noch nichts veröffentlicht, das lässt sich nicht einfrieren.",
|
|
276
276
|
"flows.publishConfirm": "Veröffentlichen",
|
|
277
277
|
"flows.publishFailed": "Das Veröffentlichen ist fehlgeschlagen. Lade die neueste Fassung und versuche es erneut.",
|
|
278
|
-
"flows.tool": "MCP-
|
|
279
|
-
"flows.selectTool": "
|
|
278
|
+
"flows.tool": "MCP-Server",
|
|
279
|
+
"flows.selectTool": "Server auswählen",
|
|
280
280
|
"flows.operationFailed": "Der Flow-Vorgang ist fehlgeschlagen. Lade die neueste Fassung und versuche es erneut.",
|
|
281
281
|
"flows.needs": "Was dieser Flow braucht",
|
|
282
282
|
"flows.needsNodes": "Dokumente",
|
|
@@ -351,5 +351,18 @@
|
|
|
351
351
|
"common.noAccess": "Das ist für dich nicht verfügbar. Es existiert nicht, oder es ist nicht mehr für dich freigegeben.",
|
|
352
352
|
"common.noPermission": "Dir fehlt die Berechtigung, das zu sehen.",
|
|
353
353
|
"title.descriptionMore": "Mehr",
|
|
354
|
-
"title.descriptionLess": "Weniger"
|
|
354
|
+
"title.descriptionLess": "Weniger",
|
|
355
|
+
"flows.toolServersEmpty": "Über das Portal erreichst du noch keinen MCP-Server.",
|
|
356
|
+
"flows.toolServersFailed": "Die Serverliste ließ sich nicht laden, daher lässt sich gerade keiner auswählen.",
|
|
357
|
+
"flows.toolAllowAll": "Der Agent darf jede Funktion nutzen",
|
|
358
|
+
"flows.toolAllowSome": "Den Agenten auf bestimmte Funktionen hinweisen",
|
|
359
|
+
"flows.toolAllowHint": "Intel sagt, wofür ein Schritt da ist; der Agent wählt den Aufruf und erreicht das Portal mit seinen eigenen Rechten.",
|
|
360
|
+
"flows.toolFunctions": "Funktionen",
|
|
361
|
+
"flows.toolServersDisconnected": "Du bist nicht mit dem Portal verbunden, daher lässt sich kein Server wählen. Verbinde es zuerst in den Werkzeug-Einstellungen.",
|
|
362
|
+
"flows.toolAllowNone": "Es ist noch keine Funktion ausgewählt, daher lässt sich dieser Schritt nicht veröffentlichen.",
|
|
363
|
+
"flows.toolAllowUnknown": "{count} ausgewählte Funktion(en) bietet dieser Server gerade nicht an.",
|
|
364
|
+
"flows.toolStepNeedsServer": "Dem Schritt „{label}“ fehlt noch ein Server.",
|
|
365
|
+
"flows.toolFunctionsFailed": "Die Funktionsliste ließ sich nicht laden, daher ist die Auswahl möglicherweise unvollständig.",
|
|
366
|
+
"flows.publishPreviewToolUnavailable": "Diesen Server erreichst du nicht, daher wird das Veröffentlichen abgelehnt.",
|
|
367
|
+
"flows.publishPreviewToolAllow": "Eingefroren auf: {functions}"
|
|
355
368
|
}
|
package/src/i18n/en.json
CHANGED
|
@@ -275,8 +275,8 @@
|
|
|
275
275
|
"flows.publishPreviewUnavailable": "The called flow has published nothing yet, so this cannot be frozen.",
|
|
276
276
|
"flows.publishConfirm": "Publish",
|
|
277
277
|
"flows.publishFailed": "Publishing failed. Reload the latest version and try again.",
|
|
278
|
-
"flows.tool": "MCP
|
|
279
|
-
"flows.selectTool": "Select a
|
|
278
|
+
"flows.tool": "MCP server",
|
|
279
|
+
"flows.selectTool": "Select a server",
|
|
280
280
|
"flows.operationFailed": "The flow operation failed. Reload the latest version and try again.",
|
|
281
281
|
"flows.needs": "What this flow needs",
|
|
282
282
|
"flows.needsNodes": "Documents",
|
|
@@ -351,5 +351,18 @@
|
|
|
351
351
|
"common.noAccess": "This is not available to you. It may not exist, or it may no longer be shared with you.",
|
|
352
352
|
"common.noPermission": "You do not have permission to see this.",
|
|
353
353
|
"title.descriptionMore": "More",
|
|
354
|
-
"title.descriptionLess": "Less"
|
|
354
|
+
"title.descriptionLess": "Less",
|
|
355
|
+
"flows.toolServersEmpty": "You reach no MCP server through the portal yet.",
|
|
356
|
+
"flows.toolServersFailed": "The list of servers could not be loaded, so none can be chosen right now.",
|
|
357
|
+
"flows.toolAllowAll": "Let the agent use any function",
|
|
358
|
+
"flows.toolAllowSome": "Point the agent at specific functions",
|
|
359
|
+
"flows.toolAllowHint": "Intel says what a step is for; the agent chooses the call and reaches the portal with its own permissions.",
|
|
360
|
+
"flows.toolFunctions": "Functions",
|
|
361
|
+
"flows.toolServersDisconnected": "You are not connected to the portal, so no server can be chosen. Connect it in the tool settings first.",
|
|
362
|
+
"flows.toolAllowNone": "No function is selected yet, so this step cannot be published.",
|
|
363
|
+
"flows.toolAllowUnknown": "{count} selected function(s) are not offered by this server right now.",
|
|
364
|
+
"flows.toolStepNeedsServer": "The step “{label}” still needs a server.",
|
|
365
|
+
"flows.toolFunctionsFailed": "The list of functions could not be loaded, so the selection may be incomplete.",
|
|
366
|
+
"flows.publishPreviewToolUnavailable": "You do not reach this server, so publishing will be refused.",
|
|
367
|
+
"flows.publishPreviewToolAllow": "Frozen to: {functions}"
|
|
355
368
|
}
|
package/src/i18n/es.json
CHANGED
|
@@ -275,8 +275,8 @@
|
|
|
275
275
|
"flows.publishPreviewUnavailable": "El flujo llamado todavía no ha publicado nada, así que esto no se puede congelar.",
|
|
276
276
|
"flows.publishConfirm": "Publicar",
|
|
277
277
|
"flows.publishFailed": "La publicación ha fallado. Carga la versión más reciente e inténtalo de nuevo.",
|
|
278
|
-
"flows.tool": "
|
|
279
|
-
"flows.selectTool": "
|
|
278
|
+
"flows.tool": "Servidor MCP",
|
|
279
|
+
"flows.selectTool": "Elegir un servidor",
|
|
280
280
|
"flows.operationFailed": "La operación del flujo ha fallado. Carga la versión más reciente e inténtalo de nuevo.",
|
|
281
281
|
"flows.needs": "Qué necesita este flujo",
|
|
282
282
|
"flows.needsNodes": "Documentos",
|
|
@@ -351,5 +351,18 @@
|
|
|
351
351
|
"common.noAccess": "Esto no está disponible para ti. Puede que no exista o que ya no esté compartido contigo.",
|
|
352
352
|
"common.noPermission": "No tienes permiso para ver esto.",
|
|
353
353
|
"title.descriptionMore": "Más",
|
|
354
|
-
"title.descriptionLess": "Menos"
|
|
354
|
+
"title.descriptionLess": "Menos",
|
|
355
|
+
"flows.toolServersEmpty": "Todavía no alcanzas ningún servidor MCP a través del portal.",
|
|
356
|
+
"flows.toolServersFailed": "No se pudo cargar la lista de servidores, así que ahora no se puede elegir ninguno.",
|
|
357
|
+
"flows.toolAllowAll": "El agente puede usar cualquier función",
|
|
358
|
+
"flows.toolAllowSome": "Indicar al agente funciones concretas",
|
|
359
|
+
"flows.toolAllowHint": "Intel dice para qué sirve un paso; el agente elige la llamada y accede al portal con sus propios permisos.",
|
|
360
|
+
"flows.toolFunctions": "Funciones",
|
|
361
|
+
"flows.toolServersDisconnected": "No estás conectado al portal, así que no se puede elegir ningún servidor. Conéctalo primero en la configuración de herramientas.",
|
|
362
|
+
"flows.toolAllowNone": "Todavía no hay ninguna función seleccionada, así que este paso no se puede publicar.",
|
|
363
|
+
"flows.toolAllowUnknown": "Este servidor no ofrece ahora mismo {count} función(es) seleccionada(s).",
|
|
364
|
+
"flows.toolStepNeedsServer": "Al paso «{label}» todavía le falta un servidor.",
|
|
365
|
+
"flows.toolFunctionsFailed": "No se pudo cargar la lista de funciones, así que la selección puede estar incompleta.",
|
|
366
|
+
"flows.publishPreviewToolUnavailable": "No alcanzas este servidor, así que la publicación será rechazada.",
|
|
367
|
+
"flows.publishPreviewToolAllow": "Congelado en: {functions}"
|
|
355
368
|
}
|