@bikdotai/bik-component-library 0.0.874 → 0.0.875-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js +11 -11
- package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js +2 -2
- package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js +4 -4
- package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
- package/dist/cjs/components/agent-builder/utils/sourceIcons.js +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.d.ts +6 -0
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +143 -141
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.d.ts +6 -0
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js +83 -81
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/MentionPicker.js +5 -5
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.d.ts +6 -0
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js +50 -48
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/index.d.ts +18 -2
- package/dist/esm/components/agent-builder/utils/sourceIcons.js +43 -43
- package/dist/esm/components/agent-builder/utils/toolActions.js +3 -3
- package/dist/esm/index.js +816 -772
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { jsx as o, jsxs as E } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { TitleSmall as
|
|
6
|
-
import { COLORS as
|
|
7
|
-
import { FieldBlock as
|
|
8
|
-
import { AGENT_CHAR_LIMITS as
|
|
9
|
-
import { DRAWER_BODY_STYLE as
|
|
10
|
-
import { ToolInstructionsField as
|
|
11
|
-
import { VariableTriggerArea as
|
|
12
|
-
import { SideModal as
|
|
13
|
-
import { Switch as
|
|
14
|
-
import { Input as
|
|
15
|
-
import { Tag as
|
|
16
|
-
const
|
|
2
|
+
import D from "../../../assets/icons/cross.svg.js";
|
|
3
|
+
import j, { useState as I, useRef as b } from "react";
|
|
4
|
+
import v from "styled-components";
|
|
5
|
+
import { TitleSmall as O, BodyCaption as F } from "../../TypographyStyle.js";
|
|
6
|
+
import { COLORS as c } from "../../../constants/Theme.js";
|
|
7
|
+
import { FieldBlock as P } from "../AgentBuilder.styled.js";
|
|
8
|
+
import { AGENT_CHAR_LIMITS as G } from "../constants/charLimits.js";
|
|
9
|
+
import { DRAWER_BODY_STYLE as V, DRAWER_HEADER_STYLE as z, DrawerHeaderText as M } from "./DrawerHeaderText.js";
|
|
10
|
+
import { ToolInstructionsField as q } from "./ToolInstructionsField.js";
|
|
11
|
+
import { VariableTriggerArea as L } from "./VariableTriggerArea.js";
|
|
12
|
+
import { SideModal as H } from "../../side-modal/SideModal.js";
|
|
13
|
+
import { Switch as W } from "../../switch/Switch.js";
|
|
14
|
+
import { Input as N } from "../../input/Input.js";
|
|
15
|
+
import { Tag as J } from "../../tag/Tag.js";
|
|
16
|
+
const K = {
|
|
17
17
|
send_email: {
|
|
18
18
|
title: "Send email",
|
|
19
19
|
subtitle: "Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message."
|
|
@@ -30,269 +30,271 @@ const J = {
|
|
|
30
30
|
title: "Add row to sheet",
|
|
31
31
|
subtitle: "Append a row to a Google Sheet. You pick the sheet and its columns, the AI fills them in from the conversation."
|
|
32
32
|
}
|
|
33
|
-
},
|
|
33
|
+
}, Q = ({
|
|
34
34
|
chips: n,
|
|
35
|
-
onChange:
|
|
36
|
-
placeholder:
|
|
37
|
-
nativeID:
|
|
38
|
-
hint:
|
|
39
|
-
variablesData:
|
|
35
|
+
onChange: i,
|
|
36
|
+
placeholder: d,
|
|
37
|
+
nativeID: u,
|
|
38
|
+
hint: w,
|
|
39
|
+
variablesData: T
|
|
40
40
|
}) => {
|
|
41
|
-
const [
|
|
42
|
-
const t =
|
|
43
|
-
t.length &&
|
|
44
|
-
}, f =
|
|
45
|
-
f.current =
|
|
46
|
-
const
|
|
47
|
-
return /* @__PURE__ */ E(
|
|
41
|
+
const [l, h] = I(""), [R, C] = I(!1), a = b(null), _ = b(null), y = () => {
|
|
42
|
+
const t = l.split(",").map((s) => s.trim()).filter(Boolean);
|
|
43
|
+
t.length && i([...n, ...t.filter((s) => !n.includes(s))]), h("");
|
|
44
|
+
}, f = b(y);
|
|
45
|
+
f.current = y;
|
|
46
|
+
const k = b(!1), x = b(!1);
|
|
47
|
+
return /* @__PURE__ */ E(Z, { ref: a, children: [
|
|
48
48
|
/* @__PURE__ */ o(
|
|
49
|
-
|
|
49
|
+
L,
|
|
50
50
|
{
|
|
51
51
|
addDataButton: !0,
|
|
52
|
-
variablesData:
|
|
52
|
+
variablesData: T,
|
|
53
53
|
onOpenChange: (t) => {
|
|
54
|
-
|
|
55
|
-
!
|
|
54
|
+
k.current = t, !t && setTimeout(() => {
|
|
55
|
+
!x.current && !a.current?.contains(document.activeElement) && f.current(), x.current = !1;
|
|
56
56
|
}, 0);
|
|
57
57
|
},
|
|
58
|
-
onInsert: (t,
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
58
|
+
onInsert: (t, s) => {
|
|
59
|
+
x.current = !0;
|
|
60
|
+
const g = s ?? l.length;
|
|
61
|
+
h(`${l.slice(0, g)}${t}${l.slice(g)}`), requestAnimationFrame(() => {
|
|
62
|
+
const S = _.current;
|
|
63
|
+
S?.focus(), S?.setSelectionRange(g + t.length, g + t.length);
|
|
64
64
|
});
|
|
65
65
|
},
|
|
66
66
|
children: /* @__PURE__ */ o(
|
|
67
|
-
|
|
67
|
+
ee,
|
|
68
68
|
{
|
|
69
|
-
id:
|
|
70
|
-
name:
|
|
71
|
-
ref:
|
|
69
|
+
id: u,
|
|
70
|
+
name: u,
|
|
71
|
+
ref: _,
|
|
72
72
|
type: "text",
|
|
73
73
|
autoComplete: "off",
|
|
74
|
-
placeholder: R &&
|
|
75
|
-
value:
|
|
76
|
-
onChange: (t) =>
|
|
77
|
-
onFocus: () =>
|
|
74
|
+
placeholder: R && l === "" && (T?.length ?? 0) > 0 ? "Enter text, type @ to add variable" : d,
|
|
75
|
+
value: l,
|
|
76
|
+
onChange: (t) => h(t.target.value),
|
|
77
|
+
onFocus: () => C(!0),
|
|
78
78
|
onBlur: () => {
|
|
79
|
-
|
|
80
|
-
!
|
|
79
|
+
C(!1), setTimeout(() => {
|
|
80
|
+
!k.current && !a.current?.contains(document.activeElement) && f.current();
|
|
81
81
|
}, 0);
|
|
82
82
|
},
|
|
83
83
|
onKeyDown: (t) => {
|
|
84
|
-
t.key === "Enter" || t.key === "," ? (t.preventDefault(),
|
|
84
|
+
t.key === "Enter" || t.key === "," ? (t.preventDefault(), y()) : t.key === "Backspace" && l === "" && n.length > 0 && i(n.slice(0, -1));
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
)
|
|
88
88
|
}
|
|
89
89
|
),
|
|
90
|
-
|
|
91
|
-
n.length > 0 && /* @__PURE__ */ o(
|
|
92
|
-
|
|
90
|
+
w,
|
|
91
|
+
n.length > 0 && /* @__PURE__ */ o(te, { children: n.map((t, s) => /* @__PURE__ */ o(
|
|
92
|
+
J,
|
|
93
93
|
{
|
|
94
94
|
tagText: t.replace(/\{\{variable:([^}]+)\}\}/g, "{{$1}}"),
|
|
95
95
|
theme: "light",
|
|
96
96
|
type: "neutral",
|
|
97
97
|
variant: "regular",
|
|
98
|
-
TrailingIcon:
|
|
99
|
-
onTrailingIconClicked: () =>
|
|
98
|
+
TrailingIcon: D,
|
|
99
|
+
onTrailingIconClicked: () => i(n.filter((g, S) => S !== s))
|
|
100
100
|
},
|
|
101
|
-
`${t}-${
|
|
101
|
+
`${t}-${s}`
|
|
102
102
|
)) })
|
|
103
103
|
] });
|
|
104
|
-
},
|
|
105
|
-
const
|
|
106
|
-
return Object.keys(n).forEach((
|
|
107
|
-
|
|
108
|
-
}),
|
|
109
|
-
},
|
|
104
|
+
}, U = (n, i) => {
|
|
105
|
+
const d = {};
|
|
106
|
+
return Object.keys(n).forEach((u) => {
|
|
107
|
+
d[u] = i?.params[u]?.value ?? n[u].value;
|
|
108
|
+
}), d;
|
|
109
|
+
}, X = (n) => String(n ?? "").split(",").map((i) => i.trim()).filter(Boolean), xe = ({
|
|
110
110
|
toolKey: n,
|
|
111
|
-
template:
|
|
112
|
-
onClose:
|
|
113
|
-
onSave:
|
|
114
|
-
initial:
|
|
115
|
-
onImprove:
|
|
116
|
-
charLimits:
|
|
117
|
-
variablesData:
|
|
118
|
-
zIndex: R
|
|
111
|
+
template: i,
|
|
112
|
+
onClose: d,
|
|
113
|
+
onSave: u,
|
|
114
|
+
initial: w,
|
|
115
|
+
onImprove: T,
|
|
116
|
+
charLimits: l = G,
|
|
117
|
+
variablesData: h,
|
|
118
|
+
zIndex: R,
|
|
119
|
+
element: C
|
|
119
120
|
}) => {
|
|
120
|
-
const [a,
|
|
121
|
-
() =>
|
|
122
|
-
), [
|
|
123
|
-
if (!
|
|
121
|
+
const [a, _] = I(
|
|
122
|
+
() => U(i, w)
|
|
123
|
+
), [y, f] = I(!1), k = Object.values(i), x = n === "send_email", t = (e, m) => _((p) => ({ ...p, [e]: m })), s = k.every((e) => !(e.required && String(a[e.key] ?? "").trim() === "" || e.component === "MultilineInput" && String(a[e.key] ?? "").length > l.instructions)), g = async () => {
|
|
124
|
+
if (!s || y)
|
|
124
125
|
return;
|
|
125
126
|
const e = {};
|
|
126
|
-
|
|
127
|
+
k.forEach((r) => {
|
|
127
128
|
e[r.key] = { ...r, value: a[r.key] };
|
|
128
129
|
});
|
|
129
|
-
const
|
|
130
|
-
id:
|
|
130
|
+
const m = {
|
|
131
|
+
id: w?.id ?? `${n}_${Date.now().toString(36)}`,
|
|
131
132
|
tool_key: n,
|
|
132
133
|
params: e
|
|
133
|
-
},
|
|
134
|
-
if (
|
|
135
|
-
|
|
134
|
+
}, p = u(m);
|
|
135
|
+
if (p && typeof p.then == "function") {
|
|
136
|
+
f(!0);
|
|
136
137
|
try {
|
|
137
|
-
await
|
|
138
|
+
await p;
|
|
138
139
|
} finally {
|
|
139
|
-
|
|
140
|
+
f(!1);
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
|
-
},
|
|
143
|
-
const
|
|
143
|
+
}, S = (e) => {
|
|
144
|
+
const m = `config-tool-${e.key.toLowerCase()}`;
|
|
144
145
|
switch (e.component) {
|
|
145
146
|
// Multi-value email chips — only for the email tool. Slack's KeywordInput
|
|
146
147
|
// (channelId) falls through to the plain input below.
|
|
147
148
|
case "KeywordInput":
|
|
148
|
-
if (!
|
|
149
|
+
if (!x)
|
|
149
150
|
break;
|
|
150
|
-
return /* @__PURE__ */ E(
|
|
151
|
-
/* @__PURE__ */ o(
|
|
151
|
+
return /* @__PURE__ */ E(P, { children: [
|
|
152
|
+
/* @__PURE__ */ o(O, { color: c.content.primary, children: e.title }),
|
|
152
153
|
/* @__PURE__ */ o(
|
|
153
|
-
|
|
154
|
+
Q,
|
|
154
155
|
{
|
|
155
|
-
nativeID:
|
|
156
|
+
nativeID: m,
|
|
156
157
|
placeholder: e.hint ?? "",
|
|
157
|
-
chips:
|
|
158
|
-
onChange: (r) =>
|
|
159
|
-
variablesData:
|
|
160
|
-
hint: /* @__PURE__ */ o(
|
|
158
|
+
chips: X(a[e.key]),
|
|
159
|
+
onChange: (r) => t(e.key, r.join(",")),
|
|
160
|
+
variablesData: h,
|
|
161
|
+
hint: /* @__PURE__ */ o(F, { color: c.content.secondary, children: "Press Enter or comma to add multiple emails" })
|
|
161
162
|
}
|
|
162
163
|
)
|
|
163
164
|
] }, e.key);
|
|
164
165
|
case "MultilineInput":
|
|
165
166
|
return /* @__PURE__ */ o(
|
|
166
|
-
|
|
167
|
+
q,
|
|
167
168
|
{
|
|
168
|
-
"data-test":
|
|
169
|
+
"data-test": m,
|
|
169
170
|
label: e.title,
|
|
170
171
|
value: String(a[e.key] ?? ""),
|
|
171
|
-
onChange: (r) =>
|
|
172
|
-
maxLength:
|
|
172
|
+
onChange: (r) => t(e.key, r),
|
|
173
|
+
maxLength: l.instructions,
|
|
173
174
|
placeholder: e.hint ?? "",
|
|
174
|
-
onImprove:
|
|
175
|
-
variablesData:
|
|
175
|
+
onImprove: T,
|
|
176
|
+
variablesData: h
|
|
176
177
|
},
|
|
177
178
|
e.key
|
|
178
179
|
);
|
|
179
180
|
case "Switch":
|
|
180
|
-
return /* @__PURE__ */ E(
|
|
181
|
-
/* @__PURE__ */ E(
|
|
182
|
-
/* @__PURE__ */ o(
|
|
183
|
-
e.hint && /* @__PURE__ */ o(
|
|
181
|
+
return /* @__PURE__ */ E(ne, { children: [
|
|
182
|
+
/* @__PURE__ */ E(oe, { children: [
|
|
183
|
+
/* @__PURE__ */ o(O, { color: c.content.primary, children: e.title }),
|
|
184
|
+
e.hint && /* @__PURE__ */ o(F, { color: c.content.secondary, children: e.hint })
|
|
184
185
|
] }),
|
|
185
186
|
/* @__PURE__ */ o(
|
|
186
|
-
|
|
187
|
+
W,
|
|
187
188
|
{
|
|
188
|
-
"data-test":
|
|
189
|
+
"data-test": m,
|
|
189
190
|
value: !!a[e.key],
|
|
190
|
-
onValueChange: async (r) =>
|
|
191
|
+
onValueChange: async (r) => t(e.key, r)
|
|
191
192
|
}
|
|
192
193
|
)
|
|
193
194
|
] }, e.key);
|
|
194
195
|
}
|
|
195
|
-
const
|
|
196
|
-
|
|
196
|
+
const p = /* @__PURE__ */ o(
|
|
197
|
+
N,
|
|
197
198
|
{
|
|
198
|
-
"data-test":
|
|
199
|
+
"data-test": m,
|
|
199
200
|
variant: "small",
|
|
200
201
|
labelText: e.title,
|
|
201
202
|
labelTextBold: !0,
|
|
202
203
|
placeholder: e.hint ?? "",
|
|
203
204
|
value: String(a[e.key] ?? ""),
|
|
204
|
-
onChangeText: (r) =>
|
|
205
|
+
onChangeText: (r) => t(e.key, r)
|
|
205
206
|
}
|
|
206
207
|
);
|
|
207
|
-
return
|
|
208
|
-
|
|
208
|
+
return x ? /* @__PURE__ */ o(
|
|
209
|
+
L,
|
|
209
210
|
{
|
|
210
211
|
addDataButton: !0,
|
|
211
|
-
variablesData:
|
|
212
|
-
onInsert: (r,
|
|
213
|
-
const
|
|
214
|
-
|
|
212
|
+
variablesData: h,
|
|
213
|
+
onInsert: (r, Y) => {
|
|
214
|
+
const B = String(a[e.key] ?? ""), A = Y ?? B.length;
|
|
215
|
+
t(
|
|
215
216
|
e.key,
|
|
216
|
-
`${
|
|
217
|
+
`${B.slice(0, A)}${r}${B.slice(A)}`
|
|
217
218
|
);
|
|
218
219
|
},
|
|
219
|
-
children:
|
|
220
|
+
children: p
|
|
220
221
|
},
|
|
221
222
|
e.key
|
|
222
|
-
) : /* @__PURE__ */ o(
|
|
223
|
-
},
|
|
223
|
+
) : /* @__PURE__ */ o(j.Fragment, { children: p }, e.key);
|
|
224
|
+
}, $ = K[n];
|
|
224
225
|
return /* @__PURE__ */ o(
|
|
225
|
-
|
|
226
|
+
H,
|
|
226
227
|
{
|
|
227
|
-
header:
|
|
228
|
+
header: $.title,
|
|
228
229
|
closeOnEscapeKey: !1,
|
|
229
230
|
zIndex: R,
|
|
230
|
-
|
|
231
|
+
element: C,
|
|
232
|
+
headerCustomComponent: /* @__PURE__ */ o(M, { title: $.title, subtitle: $.subtitle }),
|
|
231
233
|
hideCrossButton: !1,
|
|
232
234
|
width: "431px",
|
|
233
|
-
headerStyle:
|
|
234
|
-
bodyStyle:
|
|
235
|
-
onClose:
|
|
235
|
+
headerStyle: z,
|
|
236
|
+
bodyStyle: V,
|
|
237
|
+
onClose: d,
|
|
236
238
|
saveButtonProps: {
|
|
237
239
|
"data-test": "config-tool-save",
|
|
238
240
|
buttonText: "Save",
|
|
239
241
|
buttonType: "primary",
|
|
240
242
|
size: "small",
|
|
241
|
-
disabled: !
|
|
242
|
-
isLoading:
|
|
243
|
-
onClick:
|
|
243
|
+
disabled: !s,
|
|
244
|
+
isLoading: y,
|
|
245
|
+
onClick: g
|
|
244
246
|
},
|
|
245
247
|
cancelButtonProps: {
|
|
246
248
|
"data-test": "config-tool-cancel",
|
|
247
249
|
buttonText: "Cancel",
|
|
248
250
|
buttonType: "tertiaryGray",
|
|
249
251
|
size: "small",
|
|
250
|
-
onClick:
|
|
252
|
+
onClick: d
|
|
251
253
|
},
|
|
252
|
-
children:
|
|
254
|
+
children: k.map(S)
|
|
253
255
|
}
|
|
254
256
|
);
|
|
255
|
-
},
|
|
257
|
+
}, Z = v.div`
|
|
256
258
|
display: flex;
|
|
257
259
|
flex-direction: column;
|
|
258
260
|
gap: 8px;
|
|
259
|
-
`,
|
|
261
|
+
`, ee = v.input`
|
|
260
262
|
width: 100%;
|
|
261
263
|
min-width: 0;
|
|
262
264
|
box-sizing: border-box;
|
|
263
265
|
height: 32px;
|
|
264
266
|
padding: 0 8px;
|
|
265
|
-
border: 1px solid ${
|
|
267
|
+
border: 1px solid ${c.stroke.primary};
|
|
266
268
|
border-radius: 4px;
|
|
267
269
|
font-family: 'Inter', sans-serif;
|
|
268
270
|
font-size: 14px;
|
|
269
|
-
color: ${
|
|
270
|
-
background: ${
|
|
271
|
+
color: ${c.content.primary};
|
|
272
|
+
background: ${c.surface.standard};
|
|
271
273
|
outline: none;
|
|
272
274
|
|
|
273
275
|
&::placeholder {
|
|
274
|
-
color: ${
|
|
276
|
+
color: ${c.content.secondary};
|
|
275
277
|
}
|
|
276
278
|
|
|
277
279
|
&:focus {
|
|
278
|
-
border-color: ${
|
|
280
|
+
border-color: ${c.stroke.brand};
|
|
279
281
|
}
|
|
280
|
-
`,
|
|
282
|
+
`, te = v.div`
|
|
281
283
|
display: flex;
|
|
282
284
|
flex-wrap: wrap;
|
|
283
285
|
gap: 6px;
|
|
284
|
-
`,
|
|
286
|
+
`, ne = v.div`
|
|
285
287
|
display: flex;
|
|
286
288
|
align-items: center;
|
|
287
289
|
justify-content: space-between;
|
|
288
290
|
gap: 12px;
|
|
289
|
-
`,
|
|
291
|
+
`, oe = v.div`
|
|
290
292
|
display: flex;
|
|
291
293
|
flex-direction: column;
|
|
292
294
|
gap: 4px;
|
|
293
295
|
min-width: 0;
|
|
294
296
|
`;
|
|
295
297
|
export {
|
|
296
|
-
|
|
298
|
+
xe as ConfigToolPanel
|
|
297
299
|
};
|
|
298
300
|
//# sourceMappingURL=ConfigToolPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigToolPanel.js","sources":["../../../../../src/components/agent-builder/components/ConfigToolPanel.tsx"],"sourcesContent":["import CrossIcon from '@src/assets/icons/cross.svg';\nimport React, { useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { Switch } from '@src/components/switch';\nimport { Tag } from '@src/components/tag';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tConfigToolConfig,\n\tConfigToolKey,\n\tParamField,\n\tParamsBlob,\n} from '../AgentBuilder.model';\nimport { FieldBlock } from '../AgentBuilder.styled';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { ToolInstructionsField } from './ToolInstructionsField';\nimport { VariableTriggerArea } from './VariableTriggerArea';\n\n/** Header copy per shared-drawer tool. */\nconst TOOL_COPY: Record<ConfigToolKey, { title: string; subtitle: string }> = {\n\tsend_email: {\n\t\ttitle: 'Send email',\n\t\tsubtitle:\n\t\t\t\"Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message.\",\n\t},\n\tsend_slack_message: {\n\t\ttitle: 'Send Slack message',\n\t\tsubtitle:\n\t\t\t'Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation.',\n\t},\n\tgoogle_sheet_get_data: {\n\t\ttitle: 'Get data from sheet',\n\t\tsubtitle:\n\t\t\t'Look up rows in a Google Sheet. You pick the sheet and describe its columns, the AI writes the query it needs.',\n\t},\n\tgoogle_sheet_add_row: {\n\t\ttitle: 'Add row to sheet',\n\t\tsubtitle:\n\t\t\t'Append a row to a Google Sheet. You pick the sheet and its columns, the AI fills them in from the conversation.',\n\t},\n};\n\ninterface ConfigToolPanelProps {\n\t/** Which tool this drawer configures (drives copy + persistence). */\n\ttoolKey: ConfigToolKey;\n\t/**\n\t * The backend template (`list-catalog` → params) for `toolKey`. The form is\n\t * DYNAMIC: exactly these fields render, in this order, each by its\n\t * `component` kind (KeywordInput | MultilineInput | Switch | fallback input).\n\t */\n\ttemplate: ParamsBlob;\n\tonClose: () => void;\n\t/** Persist the filled template. A pending promise shows the Save loader. */\n\tonSave: (config: ConfigToolConfig) => void | Promise<void>;\n\t/** Seed values when editing an existing tool. */\n\tinitial?: ConfigToolConfig;\n\t/** Optional \"Improve with AI\" for multiline fields. Omit to hide it. */\n\tonImprove?: (text: string) => Promise<string>;\n\tcharLimits?: AgentCharLimits;\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` in the email\n\t * tool's Subject / Send To / Reply To / CC opens the variable picker\n\t * directly, and Message Instructions upgrades to the variables-only mention\n\t * editor. Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t/** SideModal stacking order — raise it when opened over another drawer. */\n\tzIndex?: number;\n}\n\ninterface EmailChipsFieldProps {\n\tchips: string[];\n\tonChange: (next: string[]) => void;\n\tplaceholder: string;\n\tnativeID?: string;\n\t/** Optional helper caption shown between the input and the chips. */\n\thint?: React.ReactNode;\n\t/**\n\t * Variable catalog for the `@` trigger. A picked variable is interpolated\n\t * into the entry TEXT at the caret (so values can mix text and variables,\n\t * e.g. `ops-{{variable:store_name}}@acme.com`) — it becomes a chip on\n\t * Enter / comma like any typed value.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\n/**\n * Email entry field: type an address and press Enter / comma (or blur) to add\n * it. Added emails render as removable chips BELOW the input — not inside it.\n * Backspace on an empty input removes the last chip.\n */\nconst EmailChipsField: React.FC<EmailChipsFieldProps> = ({\n\tchips,\n\tonChange,\n\tplaceholder,\n\tnativeID,\n\thint,\n\tvariablesData,\n}) => {\n\tconst [buffer, setBuffer] = useState('');\n\tconst [entryFocused, setEntryFocused] = useState(false);\n\tconst wrapRef = useRef<HTMLDivElement>(null);\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\n\tconst commit = () => {\n\t\tconst parts = buffer\n\t\t\t.split(',')\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\tif (parts.length) {\n\t\t\tonChange([...chips, ...parts.filter((p) => !chips.includes(p))]);\n\t\t}\n\t\tsetBuffer('');\n\t};\n\t// The blur handler defers via setTimeout — read the LATEST commit (with the\n\t// current buffer), not the one captured when the blur fired.\n\tconst commitRef = useRef(commit);\n\tcommitRef.current = commit;\n\t// While the variable panel is open, focus bounces through it (search box,\n\t// rows) — blur must not commit the half-composed entry.\n\tconst panelOpenRef = useRef(false);\n\t// A variable was just picked — the panel-close commit below must not fire\n\t// (onInsert refocuses the entry, so its eventual blur commits instead).\n\tconst insertedRef = useRef(false);\n\n\treturn (\n\t\t<ChipsFieldWrap ref={wrapRef}>\n\t\t\t<VariableTriggerArea\n\t\t\t\taddDataButton\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\tonOpenChange={(open) => {\n\t\t\t\t\tpanelOpenRef.current = open;\n\t\t\t\t\tif (open) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Panel closed (Escape / outside click / pick). If the entry's\n\t\t\t\t\t// blur-commit was skipped while the panel was open and focus is\n\t\t\t\t\t// not coming back, the half-typed entry would be silently lost\n\t\t\t\t\t// on save — commit it now.\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!insertedRef.current &&\n\t\t\t\t\t\t\t!wrapRef.current?.contains(document.activeElement)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcommitRef.current();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinsertedRef.current = false;\n\t\t\t\t\t}, 0);\n\t\t\t\t}}\n\t\t\t\tonInsert={(token, caret) => {\n\t\t\t\t\tinsertedRef.current = true;\n\t\t\t\t\tconst at = caret ?? buffer.length;\n\t\t\t\t\tsetBuffer(`${buffer.slice(0, at)}${token}${buffer.slice(at)}`);\n\t\t\t\t\t// Put the caret after the inserted token so typing continues\n\t\t\t\t\t// naturally (e.g. `{{variable:store_name}}|@acme.com`).\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tconst el = inputRef.current;\n\t\t\t\t\t\tel?.focus();\n\t\t\t\t\t\tel?.setSelectionRange(at + token.length, at + token.length);\n\t\t\t\t\t});\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<EmailInputBox\n\t\t\t\t\tid={nativeID}\n\t\t\t\t\tname={nativeID}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t// Focused + empty → the @ hint (only when a catalog makes @ do\n\t\t\t\t\t// anything); otherwise the field's own text.\n\t\t\t\t\tplaceholder={\n\t\t\t\t\t\tentryFocused && buffer === '' && (variablesData?.length ?? 0) > 0\n\t\t\t\t\t\t\t? 'Enter text, type @ to add variable'\n\t\t\t\t\t\t\t: placeholder\n\t\t\t\t\t}\n\t\t\t\t\tvalue={buffer}\n\t\t\t\t\tonChange={(e) => setBuffer(e.target.value)}\n\t\t\t\t\tonFocus={() => setEntryFocused(true)}\n\t\t\t\t\tonBlur={() => {\n\t\t\t\t\t\tsetEntryFocused(false);\n\t\t\t\t\t\t// Focus moving into the variable panel / pill is not \"leaving\n\t\t\t\t\t\t// the field\" — committing then would chip a half-composed value.\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!panelOpenRef.current &&\n\t\t\t\t\t\t\t\t!wrapRef.current?.contains(document.activeElement)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcommitRef.current();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 0);\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\tif (e.key === 'Enter' || e.key === ',') {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tcommit();\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\te.key === 'Backspace' &&\n\t\t\t\t\t\t\tbuffer === '' &&\n\t\t\t\t\t\t\tchips.length > 0\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tonChange(chips.slice(0, -1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</VariableTriggerArea>\n\t\t\t{hint}\n\t\t\t{chips.length > 0 && (\n\t\t\t\t<ChipRow>\n\t\t\t\t\t{chips.map((email, i) => (\n\t\t\t\t\t\t<Tag\n\t\t\t\t\t\t\tkey={`${email}-${i}`}\n\t\t\t\t\t\t\t// Variable tokens display as the short {{name}} (values can mix\n\t\t\t\t\t\t\t// text and tokens); the stored value keeps {{variable:<name>}}.\n\t\t\t\t\t\t\ttagText={email.replace(/\\{\\{variable:([^}]+)\\}\\}/g, '{{$1}}')}\n\t\t\t\t\t\t\ttheme=\"light\"\n\t\t\t\t\t\t\ttype=\"neutral\"\n\t\t\t\t\t\t\tvariant=\"regular\"\n\t\t\t\t\t\t\tTrailingIcon={CrossIcon}\n\t\t\t\t\t\t\tonTrailingIconClicked={() =>\n\t\t\t\t\t\t\t\tonChange(chips.filter((_, idx) => idx !== i))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ChipRow>\n\t\t\t)}\n\t\t</ChipsFieldWrap>\n\t);\n};\n\n/** Field values keyed by param key (the editable part of a {@link ParamsBlob}). */\ntype ParamValues = Record<string, string | boolean | number | object>;\n\nconst seedValues = (\n\ttemplate: ParamsBlob,\n\tinitial?: ConfigToolConfig,\n): ParamValues => {\n\tconst values: ParamValues = {};\n\tObject.keys(template).forEach((key) => {\n\t\tvalues[key] = initial?.params[key]?.value ?? template[key].value;\n\t});\n\treturn values;\n};\n\n/** Chips ↔ the string value KeywordInput fields carry (comma-separated). */\nconst toChips = (value: unknown): string[] =>\n\tString(value ?? '')\n\t\t.split(',')\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean);\n\n/**\n * Shared right-side drawer for the params-driven configurable tools (email /\n * Slack). Fully backend-driven: it renders the template fields by their\n * `component` kind and returns the same blob with values filled in. KeywordInput\n * renders as multi-value email chips only for `send_email`; every other tool\n * gets a plain single-line input. Mount it fresh per open (key it) so `initial`\n * seeds the state. Built on the shared `SideModal` shell.\n */\nexport const ConfigToolPanel: React.FC<ConfigToolPanelProps> = ({\n\ttoolKey,\n\ttemplate,\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tvariablesData,\n\tzIndex,\n}) => {\n\tconst [values, setValues] = useState<ParamValues>(() =>\n\t\tseedValues(template, initial),\n\t);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst fields = Object.values(template);\n\tconst isEmail = toolKey === 'send_email';\n\tconst setValue = (key: string, value: string | boolean | number | object) =>\n\t\tsetValues((prev) => ({ ...prev, [key]: value }));\n\n\tconst canSave = fields.every((f) => {\n\t\tif (f.required && String(values[f.key] ?? '').trim() === '') {\n\t\t\treturn false;\n\t\t}\n\t\t// MultilineInput renders the soft-limit editor (a paste may exceed the\n\t\t// cap, rendered grey) — gate the save so over-limit text can't persist.\n\t\tif (\n\t\t\tf.component === 'MultilineInput' &&\n\t\t\tString(values[f.key] ?? '').length > charLimits.instructions\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst params: ParamsBlob = {};\n\t\tfields.forEach((f) => {\n\t\t\t// Save the FULL descriptor with only `value` changed — the backend\n\t\t\t// infers each field's type from `component` and reads `required`.\n\t\t\tparams[f.key] = { ...f, value: values[f.key] };\n\t\t});\n\t\tconst config: ConfigToolConfig = {\n\t\t\tid: initial?.id ?? `${toolKey}_${Date.now().toString(36)}`,\n\t\t\ttool_key: toolKey,\n\t\t\tparams,\n\t\t};\n\t\tconst result = onSave(config);\n\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\tsetSaving(true);\n\t\t\ttry {\n\t\t\t\tawait result;\n\t\t\t} finally {\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst renderField = (field: ParamField) => {\n\t\tconst testId = `config-tool-${field.key.toLowerCase()}`;\n\t\tswitch (field.component) {\n\t\t\t// Multi-value email chips — only for the email tool. Slack's KeywordInput\n\t\t\t// (channelId) falls through to the plain input below.\n\t\t\tcase 'KeywordInput':\n\t\t\t\tif (!isEmail) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<FieldBlock key={field.key}>\n\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t{/* `@` at a word boundary (or the \"+ Add data\" pill) interpolates\n\t\t\t\t\t\t a variable into the entry TEXT at the caret — mixed values like\n\t\t\t\t\t\t ops-{{variable:store_name}}@acme.com chip on Enter / comma. */}\n\t\t\t\t\t\t<EmailChipsField\n\t\t\t\t\t\t\tnativeID={testId}\n\t\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\t\tchips={toChips(values[field.key])}\n\t\t\t\t\t\t\tonChange={(chips) => setValue(field.key, chips.join(','))}\n\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\thint={\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\tPress Enter or comma to add multiple emails\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldBlock>\n\t\t\t\t);\n\t\t\tcase 'MultilineInput':\n\t\t\t\treturn (\n\t\t\t\t\t<ToolInstructionsField\n\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\tlabel={field.title}\n\t\t\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\t\t\tonChange={(text) => setValue(field.key, text)}\n\t\t\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\tonImprove={onImprove}\n\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'Switch':\n\t\t\t\treturn (\n\t\t\t\t\t<SwitchRow key={field.key}>\n\t\t\t\t\t\t<SwitchText>\n\t\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t\t{field.hint && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{field.hint}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</SwitchText>\n\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\t\tvalue={Boolean(values[field.key])}\n\t\t\t\t\t\t\tonValueChange={async (next) => setValue(field.key, next)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</SwitchRow>\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tconst plainInput = (\n\t\t\t<Input\n\t\t\t\tdata-test={testId}\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText={field.title}\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\tonChangeText={(text) => setValue(field.key, text)}\n\t\t\t/>\n\t\t);\n\t\t// `@` variables only in the email tool's free-text fields (Subject) —\n\t\t// a Slack channel id can't hold a variable.\n\t\tif (!isEmail) {\n\t\t\treturn <React.Fragment key={field.key}>{plainInput}</React.Fragment>;\n\t\t}\n\t\treturn (\n\t\t\t<VariableTriggerArea\n\t\t\t\taddDataButton\n\t\t\t\tkey={field.key}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\tonInsert={(token, caret) => {\n\t\t\t\t\tconst current = String(values[field.key] ?? '');\n\t\t\t\t\tconst at = caret ?? current.length;\n\t\t\t\t\tsetValue(\n\t\t\t\t\t\tfield.key,\n\t\t\t\t\t\t`${current.slice(0, at)}${token}${current.slice(at)}`,\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{plainInput}\n\t\t\t</VariableTriggerArea>\n\t\t);\n\t};\n\n\tconst copy = TOOL_COPY[toolKey];\n\n\treturn (\n\t\t<SideModal\n\t\t\theader={copy.title}\n\t\t\tcloseOnEscapeKey={false}\n\t\t\tzIndex={zIndex}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText title={copy.title} subtitle={copy.subtitle} />\n\t\t\t}\n\t\t\thideCrossButton={false}\n\t\t\twidth=\"431px\"\n\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\tonClose={onClose}\n\t\t\tsaveButtonProps={{\n\t\t\t\t'data-test': 'config-tool-save',\n\t\t\t\tbuttonText: 'Save',\n\t\t\t\tbuttonType: 'primary',\n\t\t\t\tsize: 'small',\n\t\t\t\tdisabled: !canSave,\n\t\t\t\tisLoading: saving,\n\t\t\t\tonClick: handleSave,\n\t\t\t}}\n\t\t\tcancelButtonProps={{\n\t\t\t\t'data-test': 'config-tool-cancel',\n\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\tsize: 'small',\n\t\t\t\tonClick: onClose,\n\t\t\t}}\n\t\t>\n\t\t\t{fields.map(renderField)}\n\t\t</SideModal>\n\t);\n};\n\nconst ChipsFieldWrap = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n`;\n\nconst EmailInputBox = styled.input`\n\twidth: 100%;\n\tmin-width: 0;\n\tbox-sizing: border-box;\n\theight: 32px;\n\tpadding: 0 8px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tfont-family: 'Inter', sans-serif;\n\tfont-size: 14px;\n\tcolor: ${COLORS.content.primary};\n\tbackground: ${COLORS.surface.standard};\n\toutline: none;\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.secondary};\n\t}\n\n\t&:focus {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t}\n`;\n\nconst ChipRow = styled.div`\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n`;\n\nconst SwitchRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n`;\n\nconst SwitchText = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n`;\n"],"names":["TOOL_COPY","EmailChipsField","chips","onChange","placeholder","nativeID","hint","variablesData","buffer","setBuffer","useState","entryFocused","setEntryFocused","wrapRef","useRef","inputRef","commit","parts","s","p","commitRef","panelOpenRef","insertedRef","jsxs","ChipsFieldWrap","jsx","VariableTriggerArea","open","token","caret","at","el","EmailInputBox","e","ChipRow","email","i","Tag","CrossIcon","_","idx","seedValues","template","initial","values","key","toChips","value","ConfigToolPanel","toolKey","onClose","onSave","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","setValues","saving","setSaving","fields","isEmail","setValue","prev","canSave","f","handleSave","params","config","result","renderField","field","testId","FieldBlock","TitleSmall","COLORS","BodyCaption","ToolInstructionsField","text","SwitchRow","SwitchText","Switch","next","plainInput","Input","current","React","copy","SideModal","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","styled"],"mappings":";;;;;;;;;;;;;;;AA4BA,MAAMA,IAAwE;AAAA,EAC7E,YAAY;AAAA,IACX,OAAO;AAAA,IACP,UACC;AAAA,EAAA;AAAA,EAEF,oBAAoB;AAAA,IACnB,OAAO;AAAA,IACP,UACC;AAAA,EAAA;AAAA,EAEF,uBAAuB;AAAA,IACtB,OAAO;AAAA,IACP,UACC;AAAA,EAAA;AAAA,EAEF,sBAAsB;AAAA,IACrB,OAAO;AAAA,IACP,UACC;AAAA,EAAA;AAEH,GAmDMC,IAAkD,CAAC;AAAA,EACxD,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC;AAAA,EACA,eAAAC;AACD,MAAM;AACL,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAS,EAAE,GACjC,CAACC,GAAcC,CAAe,IAAIF,EAAS,EAAK,GAChDG,IAAUC,EAAuB,IAAI,GACrCC,IAAWD,EAAyB,IAAI,GAExCE,IAAS,MAAM;AACpB,UAAMC,IAAQT,EACZ,MAAM,GAAG,EACT,IAAI,CAACU,MAAMA,EAAE,KAAA,CAAM,EACnB,OAAO,OAAO;AAChB,IAAID,EAAM,UACTd,EAAS,CAAC,GAAGD,GAAO,GAAGe,EAAM,OAAO,CAACE,MAAM,CAACjB,EAAM,SAASiB,CAAC,CAAC,CAAC,CAAC,GAEhEV,EAAU,EAAE;AAAA,EACb,GAGMW,IAAYN,EAAOE,CAAM;AAC/B,EAAAI,EAAU,UAAUJ;AAGpB,QAAMK,IAAeP,EAAO,EAAK,GAG3BQ,IAAcR,EAAO,EAAK;AAEhC,SACC,gBAAAS,EAACC,GAAA,EAAe,KAAKX,GACpB,UAAA;AAAA,IAAA,gBAAAY;AAAA,MAACC;AAAA,MAAA;AAAA,QACA,eAAa;AAAA,QACb,eAAAnB;AAAA,QACA,cAAc,CAACoB,MAAS;AAEvB,UADAN,EAAa,UAAUM,GACnB,CAAAA,KAOJ,WAAW,MAAM;AAChB,YACC,CAACL,EAAY,WACb,CAACT,EAAQ,SAAS,SAAS,SAAS,aAAa,KAEjDO,EAAU,QAAA,GAEXE,EAAY,UAAU;AAAA,UACvB,GAAG,CAAC;AAAA,QACL;AAAA,QACA,UAAU,CAACM,GAAOC,MAAU;AAC3B,UAAAP,EAAY,UAAU;AACtB,gBAAMQ,IAAKD,KAASrB,EAAO;AAC3B,UAAAC,EAAU,GAAGD,EAAO,MAAM,GAAGsB,CAAE,CAAC,GAAGF,CAAK,GAAGpB,EAAO,MAAMsB,CAAE,CAAC,EAAE,GAG7D,sBAAsB,MAAM;AAC3B,kBAAMC,IAAKhB,EAAS;AACpB,YAAAgB,GAAI,MAAA,GACJA,GAAI,kBAAkBD,IAAKF,EAAM,QAAQE,IAAKF,EAAM,MAAM;AAAA,UAC3D,CAAC;AAAA,QACF;AAAA,QAEA,UAAA,gBAAAH;AAAA,UAACO;AAAA,UAAA;AAAA,YACA,IAAI3B;AAAA,YACJ,MAAMA;AAAA,YACN,KAAKU;AAAA,YACL,MAAK;AAAA,YACL,cAAa;AAAA,YAGb,aACCJ,KAAgBH,MAAW,OAAOD,GAAe,UAAU,KAAK,IAC7D,uCACAH;AAAA,YAEJ,OAAOI;AAAA,YACP,UAAU,CAACyB,MAAMxB,EAAUwB,EAAE,OAAO,KAAK;AAAA,YACzC,SAAS,MAAMrB,EAAgB,EAAI;AAAA,YACnC,QAAQ,MAAM;AACb,cAAAA,EAAgB,EAAK,GAGrB,WAAW,MAAM;AAChB,gBACC,CAACS,EAAa,WACd,CAACR,EAAQ,SAAS,SAAS,SAAS,aAAa,KAEjDO,EAAU,QAAA;AAAA,cAEZ,GAAG,CAAC;AAAA,YACL;AAAA,YACA,WAAW,CAACa,MAAM;AACjB,cAAIA,EAAE,QAAQ,WAAWA,EAAE,QAAQ,OAClCA,EAAE,eAAA,GACFjB,EAAA,KAEAiB,EAAE,QAAQ,eACVzB,MAAW,MACXN,EAAM,SAAS,KAEfC,EAASD,EAAM,MAAM,GAAG,EAAE,CAAC;AAAA,YAE7B;AAAA,UAAA;AAAA,QAAA;AAAA,MACD;AAAA,IAAA;AAAA,IAEAI;AAAA,IACAJ,EAAM,SAAS,KACf,gBAAAuB,EAACS,MACC,UAAAhC,EAAM,IAAI,CAACiC,GAAOC,MAClB,gBAAAX;AAAA,MAACY;AAAA,MAAA;AAAA,QAIA,SAASF,EAAM,QAAQ,6BAA6B,QAAQ;AAAA,QAC5D,OAAM;AAAA,QACN,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,cAAcG;AAAAA,QACd,uBAAuB,MACtBnC,EAASD,EAAM,OAAO,CAACqC,GAAGC,MAAQA,MAAQJ,CAAC,CAAC;AAAA,MAAA;AAAA,MATxC,GAAGD,CAAK,IAAIC,CAAC;AAAA,IAAA,CAYnB,EAAA,CACF;AAAA,EAAA,GAEF;AAEF,GAKMK,IAAa,CAClBC,GACAC,MACiB;AACjB,QAAMC,IAAsB,CAAA;AAC5B,gBAAO,KAAKF,CAAQ,EAAE,QAAQ,CAACG,MAAQ;AACtC,IAAAD,EAAOC,CAAG,IAAIF,GAAS,OAAOE,CAAG,GAAG,SAASH,EAASG,CAAG,EAAE;AAAA,EAC5D,CAAC,GACMD;AACR,GAGME,IAAU,CAACC,MAChB,OAAOA,KAAS,EAAE,EAChB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,MAAM,EACnB,OAAO,OAAO,GAUJC,KAAkD,CAAC;AAAA,EAC/D,SAAAC;AAAA,EACA,UAAAP;AAAA,EACA,SAAAQ;AAAA,EACA,QAAAC;AAAA,EACA,SAAAR;AAAA,EACA,WAAAS;AAAA,EACA,YAAAC,IAAaC;AAAA,EACb,eAAA/C;AAAA,EACA,QAAAgD;AACD,MAAM;AACL,QAAM,CAACX,GAAQY,CAAS,IAAI9C;AAAA,IAAsB,MACjD+B,EAAWC,GAAUC,CAAO;AAAA,EAAA,GAEvB,CAACc,GAAQC,CAAS,IAAIhD,EAAS,EAAK,GAEpCiD,IAAS,OAAO,OAAOjB,CAAQ,GAC/BkB,IAAUX,MAAY,cACtBY,IAAW,CAAChB,GAAaE,MAC9BS,EAAU,CAACM,OAAU,EAAE,GAAGA,GAAM,CAACjB,CAAG,GAAGE,IAAQ,GAE1CgB,IAAUJ,EAAO,MAAM,CAACK,MACzB,EAAAA,EAAE,YAAY,OAAOpB,EAAOoB,EAAE,GAAG,KAAK,EAAE,EAAE,KAAA,MAAW,MAMxDA,EAAE,cAAc,oBAChB,OAAOpB,EAAOoB,EAAE,GAAG,KAAK,EAAE,EAAE,SAASX,EAAW,aAKjD,GAEKY,IAAa,YAAY;AAC9B,QAAI,CAACF,KAAWN;AACf;AAED,UAAMS,IAAqB,CAAA;AAC3B,IAAAP,EAAO,QAAQ,CAACK,MAAM;AAGrB,MAAAE,EAAOF,EAAE,GAAG,IAAI,EAAE,GAAGA,GAAG,OAAOpB,EAAOoB,EAAE,GAAG,EAAA;AAAA,IAC5C,CAAC;AACD,UAAMG,IAA2B;AAAA,MAChC,IAAIxB,GAAS,MAAM,GAAGM,CAAO,IAAI,KAAK,IAAA,EAAM,SAAS,EAAE,CAAC;AAAA,MACxD,UAAUA;AAAA,MACV,QAAAiB;AAAA,IAAA,GAEKE,IAASjB,EAAOgB,CAAM;AAC5B,QAAIC,KAAU,OAAQA,EAAyB,QAAS,YAAY;AACnE,MAAAV,EAAU,EAAI;AACd,UAAI;AACH,cAAMU;AAAA,MACP,UAAA;AACC,QAAAV,EAAU,EAAK;AAAA,MAChB;AAAA,IACD;AAAA,EACD,GAEMW,IAAc,CAACC,MAAsB;AAC1C,UAAMC,IAAS,eAAeD,EAAM,IAAI,aAAa;AACrD,YAAQA,EAAM,WAAA;AAAA;AAAA;AAAA,MAGb,KAAK;AACJ,YAAI,CAACV;AACJ;AAED,iCACEY,GAAA,EACA,UAAA;AAAA,UAAA,gBAAA/C,EAACgD,KAAW,OAAOC,EAAO,QAAQ,SAChC,YAAM,OACR;AAAA,UAIA,gBAAAjD;AAAA,YAACxB;AAAA,YAAA;AAAA,cACA,UAAUsE;AAAA,cACV,aAAaD,EAAM,QAAQ;AAAA,cAC3B,OAAOxB,EAAQF,EAAO0B,EAAM,GAAG,CAAC;AAAA,cAChC,UAAU,CAACpE,MAAU2D,EAASS,EAAM,KAAKpE,EAAM,KAAK,GAAG,CAAC;AAAA,cACxD,eAAAK;AAAA,cACA,MACC,gBAAAkB,EAACkD,GAAA,EAAY,OAAOD,EAAO,QAAQ,WAAW,UAAA,8CAAA,CAE9C;AAAA,YAAA;AAAA,UAAA;AAAA,QAEF,EAAA,GAlBgBJ,EAAM,GAmBvB;AAAA,MAEF,KAAK;AACJ,eACC,gBAAA7C;AAAA,UAACmD;AAAA,UAAA;AAAA,YAEA,aAAWL;AAAA,YACX,OAAOD,EAAM;AAAA,YACb,OAAO,OAAO1B,EAAO0B,EAAM,GAAG,KAAK,EAAE;AAAA,YACrC,UAAU,CAACO,MAAShB,EAASS,EAAM,KAAKO,CAAI;AAAA,YAC5C,WAAWxB,EAAW;AAAA,YACtB,aAAaiB,EAAM,QAAQ;AAAA,YAC3B,WAAAlB;AAAA,YACA,eAAA7C;AAAA,UAAA;AAAA,UARK+D,EAAM;AAAA,QAAA;AAAA,MAWd,KAAK;AACJ,iCACEQ,IAAA,EACA,UAAA;AAAA,UAAA,gBAAAvD,EAACwD,IAAA,EACA,UAAA;AAAA,YAAA,gBAAAtD,EAACgD,KAAW,OAAOC,EAAO,QAAQ,SAChC,YAAM,OACR;AAAA,YACCJ,EAAM,QACN,gBAAA7C,EAACkD,GAAA,EAAY,OAAOD,EAAO,QAAQ,WACjC,UAAAJ,EAAM,KAAA,CACR;AAAA,UAAA,GAEF;AAAA,UACA,gBAAA7C;AAAA,YAACuD;AAAA,YAAA;AAAA,cACA,aAAWT;AAAA,cACX,OAAO,EAAQ3B,EAAO0B,EAAM,GAAG;AAAA,cAC/B,eAAe,OAAOW,MAASpB,EAASS,EAAM,KAAKW,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,QACxD,EAAA,GAfeX,EAAM,GAgBtB;AAAA,IAGD;AAEF,UAAMY,IACL,gBAAAzD;AAAA,MAAC0D;AAAA,MAAA;AAAA,QACA,aAAWZ;AAAA,QACX,SAAQ;AAAA,QACR,WAAWD,EAAM;AAAA,QACjB,eAAa;AAAA,QACb,aAAaA,EAAM,QAAQ;AAAA,QAC3B,OAAO,OAAO1B,EAAO0B,EAAM,GAAG,KAAK,EAAE;AAAA,QACrC,cAAc,CAACO,MAAShB,EAASS,EAAM,KAAKO,CAAI;AAAA,MAAA;AAAA,IAAA;AAKlD,WAAKjB,IAIJ,gBAAAnC;AAAA,MAACC;AAAA,MAAA;AAAA,QACA,eAAa;AAAA,QAEb,eAAAnB;AAAA,QACA,UAAU,CAACqB,GAAOC,MAAU;AAC3B,gBAAMuD,IAAU,OAAOxC,EAAO0B,EAAM,GAAG,KAAK,EAAE,GACxCxC,IAAKD,KAASuD,EAAQ;AAC5B,UAAAvB;AAAA,YACCS,EAAM;AAAA,YACN,GAAGc,EAAQ,MAAM,GAAGtD,CAAE,CAAC,GAAGF,CAAK,GAAGwD,EAAQ,MAAMtD,CAAE,CAAC;AAAA,UAAA;AAAA,QAErD;AAAA,QAEC,UAAAoD;AAAA,MAAA;AAAA,MAXIZ,EAAM;AAAA,IAAA,sBALJe,EAAM,UAAN,EAAgC,UAAAH,EAAA,GAAZZ,EAAM,GAAiB;AAAA,EAmBrD,GAEMgB,IAAOtF,EAAUiD,CAAO;AAE9B,SACC,gBAAAxB;AAAA,IAAC8D;AAAA,IAAA;AAAA,MACA,QAAQD,EAAK;AAAA,MACb,kBAAkB;AAAA,MAClB,QAAA/B;AAAA,MACA,yCACEiC,GAAA,EAAiB,OAAOF,EAAK,OAAO,UAAUA,EAAK,UAAU;AAAA,MAE/D,iBAAiB;AAAA,MACjB,OAAM;AAAA,MACN,aAAaG;AAAA,MACb,WAAWC;AAAA,MACX,SAAAxC;AAAA,MACA,iBAAiB;AAAA,QAChB,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,UAAU,CAACa;AAAA,QACX,WAAWN;AAAA,QACX,SAASQ;AAAA,MAAA;AAAA,MAEV,mBAAmB;AAAA,QAClB,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,SAASf;AAAA,MAAA;AAAA,MAGT,UAAAS,EAAO,IAAIU,CAAW;AAAA,IAAA;AAAA,EAAA;AAG1B,GAEM7C,IAAiBmE,EAAO;AAAA;AAAA;AAAA;AAAA,GAMxB3D,IAAgB2D,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMRjB,EAAO,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA,UAIhCA,EAAO,QAAQ,OAAO;AAAA,eACjBA,EAAO,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA,WAI3BA,EAAO,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA,kBAIjBA,EAAO,OAAO,KAAK;AAAA;AAAA,GAI/BxC,KAAUyD,EAAO;AAAA;AAAA;AAAA;AAAA,GAMjBb,KAAYa,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,GAOnBZ,KAAaY,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;"}
|
|
1
|
+
{"version":3,"file":"ConfigToolPanel.js","sources":["../../../../../src/components/agent-builder/components/ConfigToolPanel.tsx"],"sourcesContent":["import CrossIcon from '@src/assets/icons/cross.svg';\nimport React, { useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { Switch } from '@src/components/switch';\nimport { Tag } from '@src/components/tag';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tConfigToolConfig,\n\tConfigToolKey,\n\tParamField,\n\tParamsBlob,\n} from '../AgentBuilder.model';\nimport { FieldBlock } from '../AgentBuilder.styled';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { ToolInstructionsField } from './ToolInstructionsField';\nimport { VariableTriggerArea } from './VariableTriggerArea';\n\n/** Header copy per shared-drawer tool. */\nconst TOOL_COPY: Record<ConfigToolKey, { title: string; subtitle: string }> = {\n\tsend_email: {\n\t\ttitle: 'Send email',\n\t\tsubtitle:\n\t\t\t\"Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message.\",\n\t},\n\tsend_slack_message: {\n\t\ttitle: 'Send Slack message',\n\t\tsubtitle:\n\t\t\t'Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation.',\n\t},\n\tgoogle_sheet_get_data: {\n\t\ttitle: 'Get data from sheet',\n\t\tsubtitle:\n\t\t\t'Look up rows in a Google Sheet. You pick the sheet and describe its columns, the AI writes the query it needs.',\n\t},\n\tgoogle_sheet_add_row: {\n\t\ttitle: 'Add row to sheet',\n\t\tsubtitle:\n\t\t\t'Append a row to a Google Sheet. You pick the sheet and its columns, the AI fills them in from the conversation.',\n\t},\n};\n\ninterface ConfigToolPanelProps {\n\t/** Which tool this drawer configures (drives copy + persistence). */\n\ttoolKey: ConfigToolKey;\n\t/**\n\t * The backend template (`list-catalog` → params) for `toolKey`. The form is\n\t * DYNAMIC: exactly these fields render, in this order, each by its\n\t * `component` kind (KeywordInput | MultilineInput | Switch | fallback input).\n\t */\n\ttemplate: ParamsBlob;\n\tonClose: () => void;\n\t/** Persist the filled template. A pending promise shows the Save loader. */\n\tonSave: (config: ConfigToolConfig) => void | Promise<void>;\n\t/** Seed values when editing an existing tool. */\n\tinitial?: ConfigToolConfig;\n\t/** Optional \"Improve with AI\" for multiline fields. Omit to hide it. */\n\tonImprove?: (text: string) => Promise<string>;\n\tcharLimits?: AgentCharLimits;\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` in the email\n\t * tool's Subject / Send To / Reply To / CC opens the variable picker\n\t * directly, and Message Instructions upgrades to the variables-only mention\n\t * editor. Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t/**\n\t * Portal target for the drawer, passed straight to {@link SideModal}\n\t * (default `document.body`). Lets a host render it into its own positioned\n\t * slot rather than as a viewport overlay.\n\t */\n\telement?: Element | DocumentFragment;\n\t/** SideModal stacking order — raise it when opened over another drawer. */\n\tzIndex?: number;\n}\n\ninterface EmailChipsFieldProps {\n\tchips: string[];\n\tonChange: (next: string[]) => void;\n\tplaceholder: string;\n\tnativeID?: string;\n\t/** Optional helper caption shown between the input and the chips. */\n\thint?: React.ReactNode;\n\t/**\n\t * Variable catalog for the `@` trigger. A picked variable is interpolated\n\t * into the entry TEXT at the caret (so values can mix text and variables,\n\t * e.g. `ops-{{variable:store_name}}@acme.com`) — it becomes a chip on\n\t * Enter / comma like any typed value.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\n/**\n * Email entry field: type an address and press Enter / comma (or blur) to add\n * it. Added emails render as removable chips BELOW the input — not inside it.\n * Backspace on an empty input removes the last chip.\n */\nconst EmailChipsField: React.FC<EmailChipsFieldProps> = ({\n\tchips,\n\tonChange,\n\tplaceholder,\n\tnativeID,\n\thint,\n\tvariablesData,\n}) => {\n\tconst [buffer, setBuffer] = useState('');\n\tconst [entryFocused, setEntryFocused] = useState(false);\n\tconst wrapRef = useRef<HTMLDivElement>(null);\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\n\tconst commit = () => {\n\t\tconst parts = buffer\n\t\t\t.split(',')\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\tif (parts.length) {\n\t\t\tonChange([...chips, ...parts.filter((p) => !chips.includes(p))]);\n\t\t}\n\t\tsetBuffer('');\n\t};\n\t// The blur handler defers via setTimeout — read the LATEST commit (with the\n\t// current buffer), not the one captured when the blur fired.\n\tconst commitRef = useRef(commit);\n\tcommitRef.current = commit;\n\t// While the variable panel is open, focus bounces through it (search box,\n\t// rows) — blur must not commit the half-composed entry.\n\tconst panelOpenRef = useRef(false);\n\t// A variable was just picked — the panel-close commit below must not fire\n\t// (onInsert refocuses the entry, so its eventual blur commits instead).\n\tconst insertedRef = useRef(false);\n\n\treturn (\n\t\t<ChipsFieldWrap ref={wrapRef}>\n\t\t\t<VariableTriggerArea\n\t\t\t\taddDataButton\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\tonOpenChange={(open) => {\n\t\t\t\t\tpanelOpenRef.current = open;\n\t\t\t\t\tif (open) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Panel closed (Escape / outside click / pick). If the entry's\n\t\t\t\t\t// blur-commit was skipped while the panel was open and focus is\n\t\t\t\t\t// not coming back, the half-typed entry would be silently lost\n\t\t\t\t\t// on save — commit it now.\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!insertedRef.current &&\n\t\t\t\t\t\t\t!wrapRef.current?.contains(document.activeElement)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcommitRef.current();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinsertedRef.current = false;\n\t\t\t\t\t}, 0);\n\t\t\t\t}}\n\t\t\t\tonInsert={(token, caret) => {\n\t\t\t\t\tinsertedRef.current = true;\n\t\t\t\t\tconst at = caret ?? buffer.length;\n\t\t\t\t\tsetBuffer(`${buffer.slice(0, at)}${token}${buffer.slice(at)}`);\n\t\t\t\t\t// Put the caret after the inserted token so typing continues\n\t\t\t\t\t// naturally (e.g. `{{variable:store_name}}|@acme.com`).\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tconst el = inputRef.current;\n\t\t\t\t\t\tel?.focus();\n\t\t\t\t\t\tel?.setSelectionRange(at + token.length, at + token.length);\n\t\t\t\t\t});\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<EmailInputBox\n\t\t\t\t\tid={nativeID}\n\t\t\t\t\tname={nativeID}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t// Focused + empty → the @ hint (only when a catalog makes @ do\n\t\t\t\t\t// anything); otherwise the field's own text.\n\t\t\t\t\tplaceholder={\n\t\t\t\t\t\tentryFocused && buffer === '' && (variablesData?.length ?? 0) > 0\n\t\t\t\t\t\t\t? 'Enter text, type @ to add variable'\n\t\t\t\t\t\t\t: placeholder\n\t\t\t\t\t}\n\t\t\t\t\tvalue={buffer}\n\t\t\t\t\tonChange={(e) => setBuffer(e.target.value)}\n\t\t\t\t\tonFocus={() => setEntryFocused(true)}\n\t\t\t\t\tonBlur={() => {\n\t\t\t\t\t\tsetEntryFocused(false);\n\t\t\t\t\t\t// Focus moving into the variable panel / pill is not \"leaving\n\t\t\t\t\t\t// the field\" — committing then would chip a half-composed value.\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!panelOpenRef.current &&\n\t\t\t\t\t\t\t\t!wrapRef.current?.contains(document.activeElement)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcommitRef.current();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 0);\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\tif (e.key === 'Enter' || e.key === ',') {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tcommit();\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\te.key === 'Backspace' &&\n\t\t\t\t\t\t\tbuffer === '' &&\n\t\t\t\t\t\t\tchips.length > 0\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tonChange(chips.slice(0, -1));\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</VariableTriggerArea>\n\t\t\t{hint}\n\t\t\t{chips.length > 0 && (\n\t\t\t\t<ChipRow>\n\t\t\t\t\t{chips.map((email, i) => (\n\t\t\t\t\t\t<Tag\n\t\t\t\t\t\t\tkey={`${email}-${i}`}\n\t\t\t\t\t\t\t// Variable tokens display as the short {{name}} (values can mix\n\t\t\t\t\t\t\t// text and tokens); the stored value keeps {{variable:<name>}}.\n\t\t\t\t\t\t\ttagText={email.replace(/\\{\\{variable:([^}]+)\\}\\}/g, '{{$1}}')}\n\t\t\t\t\t\t\ttheme=\"light\"\n\t\t\t\t\t\t\ttype=\"neutral\"\n\t\t\t\t\t\t\tvariant=\"regular\"\n\t\t\t\t\t\t\tTrailingIcon={CrossIcon}\n\t\t\t\t\t\t\tonTrailingIconClicked={() =>\n\t\t\t\t\t\t\t\tonChange(chips.filter((_, idx) => idx !== i))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ChipRow>\n\t\t\t)}\n\t\t</ChipsFieldWrap>\n\t);\n};\n\n/** Field values keyed by param key (the editable part of a {@link ParamsBlob}). */\ntype ParamValues = Record<string, string | boolean | number | object>;\n\nconst seedValues = (\n\ttemplate: ParamsBlob,\n\tinitial?: ConfigToolConfig,\n): ParamValues => {\n\tconst values: ParamValues = {};\n\tObject.keys(template).forEach((key) => {\n\t\tvalues[key] = initial?.params[key]?.value ?? template[key].value;\n\t});\n\treturn values;\n};\n\n/** Chips ↔ the string value KeywordInput fields carry (comma-separated). */\nconst toChips = (value: unknown): string[] =>\n\tString(value ?? '')\n\t\t.split(',')\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean);\n\n/**\n * Shared right-side drawer for the params-driven configurable tools (email /\n * Slack). Fully backend-driven: it renders the template fields by their\n * `component` kind and returns the same blob with values filled in. KeywordInput\n * renders as multi-value email chips only for `send_email`; every other tool\n * gets a plain single-line input. Mount it fresh per open (key it) so `initial`\n * seeds the state. Built on the shared `SideModal` shell.\n */\nexport const ConfigToolPanel: React.FC<ConfigToolPanelProps> = ({\n\ttoolKey,\n\ttemplate,\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tvariablesData,\n\tzIndex,\n\telement,\n}) => {\n\tconst [values, setValues] = useState<ParamValues>(() =>\n\t\tseedValues(template, initial),\n\t);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst fields = Object.values(template);\n\tconst isEmail = toolKey === 'send_email';\n\tconst setValue = (key: string, value: string | boolean | number | object) =>\n\t\tsetValues((prev) => ({ ...prev, [key]: value }));\n\n\tconst canSave = fields.every((f) => {\n\t\tif (f.required && String(values[f.key] ?? '').trim() === '') {\n\t\t\treturn false;\n\t\t}\n\t\t// MultilineInput renders the soft-limit editor (a paste may exceed the\n\t\t// cap, rendered grey) — gate the save so over-limit text can't persist.\n\t\tif (\n\t\t\tf.component === 'MultilineInput' &&\n\t\t\tString(values[f.key] ?? '').length > charLimits.instructions\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst params: ParamsBlob = {};\n\t\tfields.forEach((f) => {\n\t\t\t// Save the FULL descriptor with only `value` changed — the backend\n\t\t\t// infers each field's type from `component` and reads `required`.\n\t\t\tparams[f.key] = { ...f, value: values[f.key] };\n\t\t});\n\t\tconst config: ConfigToolConfig = {\n\t\t\tid: initial?.id ?? `${toolKey}_${Date.now().toString(36)}`,\n\t\t\ttool_key: toolKey,\n\t\t\tparams,\n\t\t};\n\t\tconst result = onSave(config);\n\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\tsetSaving(true);\n\t\t\ttry {\n\t\t\t\tawait result;\n\t\t\t} finally {\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst renderField = (field: ParamField) => {\n\t\tconst testId = `config-tool-${field.key.toLowerCase()}`;\n\t\tswitch (field.component) {\n\t\t\t// Multi-value email chips — only for the email tool. Slack's KeywordInput\n\t\t\t// (channelId) falls through to the plain input below.\n\t\t\tcase 'KeywordInput':\n\t\t\t\tif (!isEmail) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<FieldBlock key={field.key}>\n\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t{/* `@` at a word boundary (or the \"+ Add data\" pill) interpolates\n\t\t\t\t\t\t a variable into the entry TEXT at the caret — mixed values like\n\t\t\t\t\t\t ops-{{variable:store_name}}@acme.com chip on Enter / comma. */}\n\t\t\t\t\t\t<EmailChipsField\n\t\t\t\t\t\t\tnativeID={testId}\n\t\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\t\tchips={toChips(values[field.key])}\n\t\t\t\t\t\t\tonChange={(chips) => setValue(field.key, chips.join(','))}\n\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\thint={\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\tPress Enter or comma to add multiple emails\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldBlock>\n\t\t\t\t);\n\t\t\tcase 'MultilineInput':\n\t\t\t\treturn (\n\t\t\t\t\t<ToolInstructionsField\n\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\tlabel={field.title}\n\t\t\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\t\t\tonChange={(text) => setValue(field.key, text)}\n\t\t\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\tonImprove={onImprove}\n\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'Switch':\n\t\t\t\treturn (\n\t\t\t\t\t<SwitchRow key={field.key}>\n\t\t\t\t\t\t<SwitchText>\n\t\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t\t{field.hint && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{field.hint}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</SwitchText>\n\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\t\tvalue={Boolean(values[field.key])}\n\t\t\t\t\t\t\tonValueChange={async (next) => setValue(field.key, next)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</SwitchRow>\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tconst plainInput = (\n\t\t\t<Input\n\t\t\t\tdata-test={testId}\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText={field.title}\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\tonChangeText={(text) => setValue(field.key, text)}\n\t\t\t/>\n\t\t);\n\t\t// `@` variables only in the email tool's free-text fields (Subject) —\n\t\t// a Slack channel id can't hold a variable.\n\t\tif (!isEmail) {\n\t\t\treturn <React.Fragment key={field.key}>{plainInput}</React.Fragment>;\n\t\t}\n\t\treturn (\n\t\t\t<VariableTriggerArea\n\t\t\t\taddDataButton\n\t\t\t\tkey={field.key}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\tonInsert={(token, caret) => {\n\t\t\t\t\tconst current = String(values[field.key] ?? '');\n\t\t\t\t\tconst at = caret ?? current.length;\n\t\t\t\t\tsetValue(\n\t\t\t\t\t\tfield.key,\n\t\t\t\t\t\t`${current.slice(0, at)}${token}${current.slice(at)}`,\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{plainInput}\n\t\t\t</VariableTriggerArea>\n\t\t);\n\t};\n\n\tconst copy = TOOL_COPY[toolKey];\n\n\treturn (\n\t\t<SideModal\n\t\t\theader={copy.title}\n\t\t\tcloseOnEscapeKey={false}\n\t\t\tzIndex={zIndex}\n\t\t\telement={element}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText title={copy.title} subtitle={copy.subtitle} />\n\t\t\t}\n\t\t\thideCrossButton={false}\n\t\t\twidth=\"431px\"\n\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\tonClose={onClose}\n\t\t\tsaveButtonProps={{\n\t\t\t\t'data-test': 'config-tool-save',\n\t\t\t\tbuttonText: 'Save',\n\t\t\t\tbuttonType: 'primary',\n\t\t\t\tsize: 'small',\n\t\t\t\tdisabled: !canSave,\n\t\t\t\tisLoading: saving,\n\t\t\t\tonClick: handleSave,\n\t\t\t}}\n\t\t\tcancelButtonProps={{\n\t\t\t\t'data-test': 'config-tool-cancel',\n\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\tsize: 'small',\n\t\t\t\tonClick: onClose,\n\t\t\t}}\n\t\t>\n\t\t\t{fields.map(renderField)}\n\t\t</SideModal>\n\t);\n};\n\nconst ChipsFieldWrap = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n`;\n\nconst EmailInputBox = styled.input`\n\twidth: 100%;\n\tmin-width: 0;\n\tbox-sizing: border-box;\n\theight: 32px;\n\tpadding: 0 8px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tfont-family: 'Inter', sans-serif;\n\tfont-size: 14px;\n\tcolor: ${COLORS.content.primary};\n\tbackground: ${COLORS.surface.standard};\n\toutline: none;\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.secondary};\n\t}\n\n\t&:focus {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t}\n`;\n\nconst ChipRow = styled.div`\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n`;\n\nconst SwitchRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n`;\n\nconst SwitchText = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n`;\n"],"names":["TOOL_COPY","EmailChipsField","chips","onChange","placeholder","nativeID","hint","variablesData","buffer","setBuffer","useState","entryFocused","setEntryFocused","wrapRef","useRef","inputRef","commit","parts","p","commitRef","panelOpenRef","insertedRef","jsxs","ChipsFieldWrap","jsx","VariableTriggerArea","open","token","caret","at","el","EmailInputBox","e","ChipRow","email","i","Tag","CrossIcon","_","idx","seedValues","template","initial","values","key","toChips","value","s","ConfigToolPanel","toolKey","onClose","onSave","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","element","setValues","saving","setSaving","fields","isEmail","setValue","prev","canSave","f","handleSave","params","config","result","renderField","field","testId","FieldBlock","TitleSmall","COLORS","BodyCaption","ToolInstructionsField","text","SwitchRow","SwitchText","Switch","next","plainInput","Input","current","React","copy","SideModal","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","styled"],"mappings":"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"}
|
|
@@ -39,6 +39,12 @@ interface CreateSubAgentPanelProps {
|
|
|
39
39
|
appLabel?: string;
|
|
40
40
|
/** Resolved character limits (defaults to {@link AGENT_CHAR_LIMITS}). */
|
|
41
41
|
charLimits?: AgentCharLimits;
|
|
42
|
+
/**
|
|
43
|
+
* Portal target for the drawer, passed straight to {@link SideModal}
|
|
44
|
+
* (default `document.body`). Lets a host render it into its own positioned
|
|
45
|
+
* slot rather than as a viewport overlay.
|
|
46
|
+
*/
|
|
47
|
+
element?: Element | DocumentFragment;
|
|
42
48
|
/** Variable catalog for the editors' `@` picker "Variables" view. */
|
|
43
49
|
variablesData?: VariableListInterfaceV3[];
|
|
44
50
|
}
|