@bikdotai/bik-component-library 0.0.849-beta.5 → 0.0.849-beta.6

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.
Files changed (28) hide show
  1. package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js +10 -10
  2. package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
  3. package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js +2 -2
  4. package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
  5. package/dist/cjs/components/agent-builder/components/MentionPicker.js +49 -25
  6. package/dist/cjs/components/agent-builder/components/MentionPicker.js.map +1 -1
  7. package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js +9 -8
  8. package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
  9. package/dist/cjs/components/agent-builder/components/VariableInlineField.js +56 -0
  10. package/dist/cjs/components/agent-builder/components/VariableInlineField.js.map +1 -0
  11. package/dist/cjs/components/agent-builder/components/VariableTriggerArea.js +5 -10
  12. package/dist/cjs/components/agent-builder/components/VariableTriggerArea.js.map +1 -1
  13. package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +164 -149
  14. package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
  15. package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js +15 -13
  16. package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
  17. package/dist/esm/components/agent-builder/components/MentionPicker.js +199 -165
  18. package/dist/esm/components/agent-builder/components/MentionPicker.js.map +1 -1
  19. package/dist/esm/components/agent-builder/components/RestApiToolPanel.d.ts +3 -2
  20. package/dist/esm/components/agent-builder/components/RestApiToolPanel.js +160 -197
  21. package/dist/esm/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
  22. package/dist/esm/components/agent-builder/components/VariableInlineField.d.ts +26 -0
  23. package/dist/esm/components/agent-builder/components/VariableInlineField.js +142 -0
  24. package/dist/esm/components/agent-builder/components/VariableInlineField.js.map +1 -0
  25. package/dist/esm/components/agent-builder/components/VariableTriggerArea.d.ts +13 -0
  26. package/dist/esm/components/agent-builder/components/VariableTriggerArea.js +75 -66
  27. package/dist/esm/components/agent-builder/components/VariableTriggerArea.js.map +1 -1
  28. package/package.json +2 -1
@@ -1,18 +1,18 @@
1
- import { jsx as o, jsxs as S } from "react/jsx-runtime";
2
- import j from "../../../assets/icons/cross.svg.js";
3
- import F, { useState as w } from "react";
4
- import y from "styled-components";
5
- import { TitleSmall as $, BodyCaption as R } from "../../TypographyStyle.js";
6
- import { COLORS as s } from "../../../constants/Theme.js";
1
+ import { jsx as o, jsxs as w } from "react/jsx-runtime";
2
+ import F from "../../../assets/icons/cross.svg.js";
3
+ import j, { useState as $, useRef as T } from "react";
4
+ import v from "styled-components";
5
+ import { TitleSmall as R, BodyCaption as _ } from "../../TypographyStyle.js";
6
+ import { COLORS as c } from "../../../constants/Theme.js";
7
7
  import { FieldBlock as P } from "../AgentBuilder.styled.js";
8
8
  import { AGENT_CHAR_LIMITS as Y } from "../constants/charLimits.js";
9
9
  import { DRAWER_BODY_STYLE as V, DRAWER_HEADER_STYLE as z, DrawerHeaderText as H } from "./DrawerHeaderText.js";
10
10
  import { ToolInstructionsField as M } from "./ToolInstructionsField.js";
11
- import { VariableTriggerArea as D } from "./VariableTriggerArea.js";
11
+ import { VariableTriggerArea as O } from "./VariableTriggerArea.js";
12
12
  import { SideModal as W } from "../../side-modal/SideModal.js";
13
- import { Switch as G } from "../../switch/Switch.js";
14
- import { Input as N } from "../../input/Input.js";
15
- import { Tag as q } from "../../tag/Tag.js";
13
+ import { Switch as q } from "../../switch/Switch.js";
14
+ import { Input as G } from "../../input/Input.js";
15
+ import { Tag as N } from "../../tag/Tag.js";
16
16
  const J = {
17
17
  send_email: {
18
18
  title: "Send Email",
@@ -23,196 +23,211 @@ const J = {
23
23
  subtitle: "Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation."
24
24
  }
25
25
  }, K = ({
26
- chips: e,
27
- onChange: i,
28
- placeholder: p,
29
- nativeID: m,
30
- hint: g
26
+ chips: n,
27
+ onChange: s,
28
+ placeholder: d,
29
+ nativeID: h,
30
+ hint: S,
31
+ variablesData: C
31
32
  }) => {
32
- const [h, k] = w(""), u = () => {
33
- const a = h.split(",").map((r) => r.trim()).filter(Boolean);
34
- a.length && i([...e, ...a.filter((r) => !e.includes(r))]), k("");
35
- };
36
- return /* @__PURE__ */ S(U, { children: [
33
+ const [u, y] = $(""), b = T(null), l = T(null), f = () => {
34
+ const t = u.split(",").map((a) => a.trim()).filter(Boolean);
35
+ t.length && s([...n, ...t.filter((a) => !n.includes(a))]), y("");
36
+ }, k = T(f);
37
+ k.current = f;
38
+ const x = T(!1);
39
+ return /* @__PURE__ */ w(X, { ref: b, children: [
37
40
  /* @__PURE__ */ o(
38
- X,
41
+ O,
39
42
  {
40
- id: m,
41
- type: "text",
42
- placeholder: p,
43
- value: h,
44
- onChange: (a) => k(a.target.value),
45
- onBlur: u,
46
- onKeyDown: (a) => {
47
- a.key === "Enter" || a.key === "," ? (a.preventDefault(), u()) : a.key === "Backspace" && h === "" && e.length > 0 && i(e.slice(0, -1));
48
- }
43
+ addDataButton: !0,
44
+ variablesData: C,
45
+ onOpenChange: (t) => {
46
+ x.current = t;
47
+ },
48
+ onInsert: (t, a) => {
49
+ const i = a ?? u.length;
50
+ y(`${u.slice(0, i)}${t}${u.slice(i)}`), requestAnimationFrame(() => {
51
+ const g = l.current;
52
+ g?.focus(), g?.setSelectionRange(i + t.length, i + t.length);
53
+ });
54
+ },
55
+ children: /* @__PURE__ */ o(
56
+ Z,
57
+ {
58
+ id: h,
59
+ ref: l,
60
+ type: "text",
61
+ placeholder: d,
62
+ value: u,
63
+ onChange: (t) => y(t.target.value),
64
+ onBlur: () => {
65
+ setTimeout(() => {
66
+ !x.current && !b.current?.contains(document.activeElement) && k.current();
67
+ }, 0);
68
+ },
69
+ onKeyDown: (t) => {
70
+ t.key === "Enter" || t.key === "," ? (t.preventDefault(), f()) : t.key === "Backspace" && u === "" && n.length > 0 && s(n.slice(0, -1));
71
+ }
72
+ }
73
+ )
49
74
  }
50
75
  ),
51
- g,
52
- e.length > 0 && /* @__PURE__ */ o(Z, { children: e.map((a, r) => /* @__PURE__ */ o(
53
- q,
76
+ S,
77
+ n.length > 0 && /* @__PURE__ */ o(ee, { children: n.map((t, a) => /* @__PURE__ */ o(
78
+ N,
54
79
  {
55
- tagText: a,
80
+ tagText: t.replace(/\{\{variable:([^}]+)\}\}/g, "{{$1}}"),
56
81
  theme: "light",
57
82
  type: "neutral",
58
83
  variant: "regular",
59
- TrailingIcon: j,
60
- onTrailingIconClicked: () => i(e.filter((C, f) => f !== r))
84
+ TrailingIcon: F,
85
+ onTrailingIconClicked: () => s(n.filter((i, g) => g !== a))
61
86
  },
62
- `${a}-${r}`
87
+ `${t}-${a}`
63
88
  )) })
64
89
  ] });
65
- }, Q = (e, i) => {
66
- const p = {};
67
- return Object.keys(e).forEach((m) => {
68
- p[m] = i?.params[m]?.value ?? e[m].value;
69
- }), p;
70
- }, O = (e) => String(e ?? "").split(",").map((i) => i.trim()).filter(Boolean), kt = ({
71
- toolKey: e,
72
- template: i,
73
- onClose: p,
74
- onSave: m,
75
- initial: g,
76
- onImprove: h,
77
- charLimits: k = Y,
78
- variablesData: u,
79
- zIndex: a
90
+ }, Q = (n, s) => {
91
+ const d = {};
92
+ return Object.keys(n).forEach((h) => {
93
+ d[h] = s?.params[h]?.value ?? n[h].value;
94
+ }), d;
95
+ }, U = (n) => String(n ?? "").split(",").map((s) => s.trim()).filter(Boolean), ke = ({
96
+ toolKey: n,
97
+ template: s,
98
+ onClose: d,
99
+ onSave: h,
100
+ initial: S,
101
+ onImprove: C,
102
+ charLimits: u = Y,
103
+ variablesData: y,
104
+ zIndex: b
80
105
  }) => {
81
- const [r, C] = w(
82
- () => Q(i, g)
83
- ), [f, I] = w(!1), v = Object.values(i), B = e === "send_email", d = (t, l) => C((c) => ({ ...c, [t]: l })), E = v.every(
84
- (t) => !t.required || String(r[t.key] ?? "").trim() !== ""
106
+ const [l, f] = $(
107
+ () => Q(s, S)
108
+ ), [k, x] = $(!1), t = Object.values(s), a = n === "send_email", i = (e, p) => f((m) => ({ ...m, [e]: p })), g = t.every(
109
+ (e) => !e.required || String(l[e.key] ?? "").trim() !== ""
85
110
  ), A = async () => {
86
- if (!E || f)
111
+ if (!g || k)
87
112
  return;
88
- const t = {};
89
- v.forEach((n) => {
90
- t[n.key] = { ...n, value: r[n.key] };
113
+ const e = {};
114
+ t.forEach((r) => {
115
+ e[r.key] = { ...r, value: l[r.key] };
91
116
  });
92
- const l = {
93
- id: g?.id ?? `${e}_${Date.now().toString(36)}`,
94
- tool_key: e,
95
- params: t
96
- }, c = m(l);
97
- if (c && typeof c.then == "function") {
98
- I(!0);
117
+ const p = {
118
+ id: S?.id ?? `${n}_${Date.now().toString(36)}`,
119
+ tool_key: n,
120
+ params: e
121
+ }, m = h(p);
122
+ if (m && typeof m.then == "function") {
123
+ x(!0);
99
124
  try {
100
- await c;
125
+ await m;
101
126
  } finally {
102
- I(!1);
127
+ x(!1);
103
128
  }
104
129
  }
105
- }, L = (t) => {
106
- const l = `config-tool-${t.key.toLowerCase()}`;
107
- switch (t.component) {
130
+ }, D = (e) => {
131
+ const p = `config-tool-${e.key.toLowerCase()}`;
132
+ switch (e.component) {
108
133
  // Multi-value email chips — only for the email tool. Slack's KeywordInput
109
134
  // (channelId) falls through to the plain input below.
110
135
  case "KeywordInput":
111
- if (!B)
136
+ if (!a)
112
137
  break;
113
- return /* @__PURE__ */ S(P, { children: [
114
- /* @__PURE__ */ o($, { color: s.content.primary, children: t.title }),
138
+ return /* @__PURE__ */ w(P, { children: [
139
+ /* @__PURE__ */ o(R, { color: c.content.primary, children: e.title }),
115
140
  /* @__PURE__ */ o(
116
- D,
141
+ K,
117
142
  {
118
- addDataButton: !0,
119
- variablesData: u,
120
- onInsert: (n) => {
121
- const x = O(r[t.key]);
122
- x.includes(n) || d(t.key, [...x, n].join(","));
123
- },
124
- children: /* @__PURE__ */ o(
125
- K,
126
- {
127
- nativeID: l,
128
- placeholder: t.hint ?? "",
129
- chips: O(r[t.key]),
130
- onChange: (n) => d(t.key, n.join(",")),
131
- hint: /* @__PURE__ */ o(R, { color: s.content.secondary, children: "Press Enter or comma to add multiple emails" })
132
- }
133
- )
143
+ nativeID: p,
144
+ placeholder: e.hint ?? "",
145
+ chips: U(l[e.key]),
146
+ onChange: (r) => i(e.key, r.join(",")),
147
+ variablesData: y,
148
+ hint: /* @__PURE__ */ o(_, { color: c.content.secondary, children: "Press Enter or comma to add multiple emails" })
134
149
  }
135
150
  )
136
- ] }, t.key);
151
+ ] }, e.key);
137
152
  case "MultilineInput":
138
153
  return /* @__PURE__ */ o(
139
154
  M,
140
155
  {
141
- "data-test": l,
142
- label: t.title,
143
- value: String(r[t.key] ?? ""),
144
- onChange: (n) => d(t.key, n),
145
- maxLength: k.instructions,
146
- placeholder: t.hint ?? "",
147
- onImprove: h,
148
- variablesData: u
156
+ "data-test": p,
157
+ label: e.title,
158
+ value: String(l[e.key] ?? ""),
159
+ onChange: (r) => i(e.key, r),
160
+ maxLength: u.instructions,
161
+ placeholder: e.hint ?? "",
162
+ onImprove: C,
163
+ variablesData: y
149
164
  },
150
- t.key
165
+ e.key
151
166
  );
152
167
  case "Switch":
153
- return /* @__PURE__ */ S(tt, { children: [
154
- /* @__PURE__ */ S(et, { children: [
155
- /* @__PURE__ */ o($, { color: s.content.primary, children: t.title }),
156
- t.hint && /* @__PURE__ */ o(R, { color: s.content.secondary, children: t.hint })
168
+ return /* @__PURE__ */ w(te, { children: [
169
+ /* @__PURE__ */ w(ne, { children: [
170
+ /* @__PURE__ */ o(R, { color: c.content.primary, children: e.title }),
171
+ e.hint && /* @__PURE__ */ o(_, { color: c.content.secondary, children: e.hint })
157
172
  ] }),
158
173
  /* @__PURE__ */ o(
159
- G,
174
+ q,
160
175
  {
161
- "data-test": l,
162
- value: !!r[t.key],
163
- onValueChange: async (n) => d(t.key, n)
176
+ "data-test": p,
177
+ value: !!l[e.key],
178
+ onValueChange: async (r) => i(e.key, r)
164
179
  }
165
180
  )
166
- ] }, t.key);
181
+ ] }, e.key);
167
182
  }
168
- const c = /* @__PURE__ */ o(
169
- N,
183
+ const m = /* @__PURE__ */ o(
184
+ G,
170
185
  {
171
- "data-test": l,
186
+ "data-test": p,
172
187
  variant: "small",
173
- labelText: t.title,
188
+ labelText: e.title,
174
189
  labelTextBold: !0,
175
- placeholder: t.hint ?? "",
176
- value: String(r[t.key] ?? ""),
177
- onChangeText: (n) => d(t.key, n)
190
+ placeholder: e.hint ?? "",
191
+ value: String(l[e.key] ?? ""),
192
+ onChangeText: (r) => i(e.key, r)
178
193
  }
179
194
  );
180
- return B ? /* @__PURE__ */ o(
181
- D,
195
+ return a ? /* @__PURE__ */ o(
196
+ O,
182
197
  {
183
198
  addDataButton: !0,
184
- variablesData: u,
185
- onInsert: (n, x) => {
186
- const T = String(r[t.key] ?? ""), _ = x ?? T.length;
187
- d(
188
- t.key,
189
- `${T.slice(0, _)}${n}${T.slice(_)}`
199
+ variablesData: y,
200
+ onInsert: (r, L) => {
201
+ const I = String(l[e.key] ?? ""), B = L ?? I.length;
202
+ i(
203
+ e.key,
204
+ `${I.slice(0, B)}${r}${I.slice(B)}`
190
205
  );
191
206
  },
192
- children: c
207
+ children: m
193
208
  },
194
- t.key
195
- ) : /* @__PURE__ */ o(F.Fragment, { children: c }, t.key);
196
- }, b = J[e];
209
+ e.key
210
+ ) : /* @__PURE__ */ o(j.Fragment, { children: m }, e.key);
211
+ }, E = J[n];
197
212
  return /* @__PURE__ */ o(
198
213
  W,
199
214
  {
200
- header: b.title,
215
+ header: E.title,
201
216
  closeOnEscapeKey: !1,
202
- zIndex: a,
203
- headerCustomComponent: /* @__PURE__ */ o(H, { title: b.title, subtitle: b.subtitle }),
217
+ zIndex: b,
218
+ headerCustomComponent: /* @__PURE__ */ o(H, { title: E.title, subtitle: E.subtitle }),
204
219
  hideCrossButton: !1,
205
220
  width: "431px",
206
221
  headerStyle: z,
207
222
  bodyStyle: V,
208
- onClose: p,
223
+ onClose: d,
209
224
  saveButtonProps: {
210
225
  "data-test": "config-tool-save",
211
226
  buttonText: "Save",
212
227
  buttonType: "primary",
213
228
  size: "small",
214
- disabled: !E,
215
- isLoading: f,
229
+ disabled: !g,
230
+ isLoading: k,
216
231
  onClick: A
217
232
  },
218
233
  cancelButtonProps: {
@@ -220,52 +235,52 @@ const J = {
220
235
  buttonText: "Cancel",
221
236
  buttonType: "tertiaryGray",
222
237
  size: "small",
223
- onClick: p
238
+ onClick: d
224
239
  },
225
- children: v.map(L)
240
+ children: t.map(D)
226
241
  }
227
242
  );
228
- }, U = y.div`
243
+ }, X = v.div`
229
244
  display: flex;
230
245
  flex-direction: column;
231
246
  gap: 8px;
232
- `, X = y.input`
247
+ `, Z = v.input`
233
248
  width: 100%;
234
249
  min-width: 0;
235
250
  box-sizing: border-box;
236
251
  height: 32px;
237
252
  padding: 0 8px;
238
- border: 1px solid ${s.stroke.primary};
253
+ border: 1px solid ${c.stroke.primary};
239
254
  border-radius: 4px;
240
255
  font-family: 'Inter', sans-serif;
241
256
  font-size: 14px;
242
- color: ${s.content.primary};
243
- background: ${s.surface.standard};
257
+ color: ${c.content.primary};
258
+ background: ${c.surface.standard};
244
259
  outline: none;
245
260
 
246
261
  &::placeholder {
247
- color: ${s.content.secondary};
262
+ color: ${c.content.secondary};
248
263
  }
249
264
 
250
265
  &:focus {
251
- border-color: ${s.stroke.brand};
266
+ border-color: ${c.stroke.brand};
252
267
  }
253
- `, Z = y.div`
268
+ `, ee = v.div`
254
269
  display: flex;
255
270
  flex-wrap: wrap;
256
271
  gap: 6px;
257
- `, tt = y.div`
272
+ `, te = v.div`
258
273
  display: flex;
259
274
  align-items: center;
260
275
  justify-content: space-between;
261
276
  gap: 12px;
262
- `, et = y.div`
277
+ `, ne = v.div`
263
278
  display: flex;
264
279
  flex-direction: column;
265
280
  gap: 4px;
266
281
  min-width: 0;
267
282
  `;
268
283
  export {
269
- kt as ConfigToolPanel
284
+ ke as ConfigToolPanel
270
285
  };
271
286
  //# 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, { 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};\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}\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}) => {\n\tconst [buffer, setBuffer] = useState('');\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\n\treturn (\n\t\t<ChipsFieldWrap>\n\t\t\t<EmailInputBox\n\t\t\t\tid={nativeID}\n\t\t\t\ttype=\"text\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tvalue={buffer}\n\t\t\t\tonChange={(e) => setBuffer(e.target.value)}\n\t\t\t\tonBlur={commit}\n\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\tif (e.key === 'Enter' || e.key === ',') {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tcommit();\n\t\t\t\t\t} else if (\n\t\t\t\t\t\te.key === 'Backspace' &&\n\t\t\t\t\t\tbuffer === '' &&\n\t\t\t\t\t\tchips.length > 0\n\t\t\t\t\t) {\n\t\t\t\t\t\tonChange(chips.slice(0, -1));\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\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\ttagText={email}\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(\n\t\t(f) => !f.required || String(values[f.key] ?? '').trim() !== '',\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 the start of an entry picks a variable (added as a\n\t\t\t\t\t\t chip); `@` inside an address types normally. */}\n\t\t\t\t\t\t<VariableTriggerArea\n\t\t\t\t\t\t\taddDataButton\n\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\tonInsert={(token) => {\n\t\t\t\t\t\t\t\tconst chips = toChips(values[field.key]);\n\t\t\t\t\t\t\t\tif (!chips.includes(token)) {\n\t\t\t\t\t\t\t\t\tsetValue(field.key, [...chips, token].join(','));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<EmailChipsField\n\t\t\t\t\t\t\t\tnativeID={testId}\n\t\t\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\t\t\tchips={toChips(values[field.key])}\n\t\t\t\t\t\t\t\tonChange={(chips) => setValue(field.key, chips.join(','))}\n\t\t\t\t\t\t\t\thint={\n\t\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\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\t</BodyCaption>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</VariableTriggerArea>\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","buffer","setBuffer","useState","commit","parts","s","p","ChipsFieldWrap","jsx","EmailInputBox","e","ChipRow","email","i","Tag","CrossIcon","_","idx","seedValues","template","initial","values","key","toChips","value","ConfigToolPanel","toolKey","onClose","onSave","onImprove","charLimits","AGENT_CHAR_LIMITS","variablesData","zIndex","setValues","saving","setSaving","fields","isEmail","setValue","prev","canSave","f","handleSave","params","config","result","renderField","field","testId","FieldBlock","TitleSmall","COLORS","VariableTriggerArea","token","BodyCaption","ToolInstructionsField","text","SwitchRow","jsxs","SwitchText","Switch","next","plainInput","Input","caret","current","at","React","copy","SideModal","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","styled"],"mappings":"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"}
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};\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 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\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}}\n\t\t\t\tonInsert={(token, caret) => {\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\tref={inputRef}\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tvalue={buffer}\n\t\t\t\t\tonChange={(e) => setBuffer(e.target.value)}\n\t\t\t\t\tonBlur={() => {\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(\n\t\t(f) => !f.required || String(values[f.key] ?? '').trim() !== '',\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","wrapRef","useRef","inputRef","commit","parts","s","p","commitRef","panelOpenRef","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;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,GACjCC,IAAUC,EAAuB,IAAI,GACrCC,IAAWD,EAAyB,IAAI,GAExCE,IAAS,MAAM;AACpB,UAAMC,IAAQP,EACZ,MAAM,GAAG,EACT,IAAI,CAACQ,MAAMA,EAAE,KAAA,CAAM,EACnB,OAAO,OAAO;AAChB,IAAID,EAAM,UACTZ,EAAS,CAAC,GAAGD,GAAO,GAAGa,EAAM,OAAO,CAACE,MAAM,CAACf,EAAM,SAASe,CAAC,CAAC,CAAC,CAAC,GAEhER,EAAU,EAAE;AAAA,EACb,GAGMS,IAAYN,EAAOE,CAAM;AAC/B,EAAAI,EAAU,UAAUJ;AAGpB,QAAMK,IAAeP,EAAO,EAAK;AAEjC,SACC,gBAAAQ,EAACC,GAAA,EAAe,KAAKV,GACpB,UAAA;AAAA,IAAA,gBAAAW;AAAA,MAACC;AAAA,MAAA;AAAA,QACA,eAAa;AAAA,QACb,eAAAhB;AAAA,QACA,cAAc,CAACiB,MAAS;AACvB,UAAAL,EAAa,UAAUK;AAAA,QACxB;AAAA,QACA,UAAU,CAACC,GAAOC,MAAU;AAC3B,gBAAMC,IAAKD,KAASlB,EAAO;AAC3B,UAAAC,EAAU,GAAGD,EAAO,MAAM,GAAGmB,CAAE,CAAC,GAAGF,CAAK,GAAGjB,EAAO,MAAMmB,CAAE,CAAC,EAAE,GAG7D,sBAAsB,MAAM;AAC3B,kBAAMC,IAAKf,EAAS;AACpB,YAAAe,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,IAAIxB;AAAA,YACJ,KAAKQ;AAAA,YACL,MAAK;AAAA,YACL,aAAAT;AAAA,YACA,OAAOI;AAAA,YACP,UAAU,CAACsB,MAAMrB,EAAUqB,EAAE,OAAO,KAAK;AAAA,YACzC,QAAQ,MAAM;AAGb,yBAAW,MAAM;AAChB,gBACC,CAACX,EAAa,WACd,CAACR,EAAQ,SAAS,SAAS,SAAS,aAAa,KAEjDO,EAAU,QAAA;AAAA,cAEZ,GAAG,CAAC;AAAA,YACL;AAAA,YACA,WAAW,CAACY,MAAM;AACjB,cAAIA,EAAE,QAAQ,WAAWA,EAAE,QAAQ,OAClCA,EAAE,eAAA,GACFhB,EAAA,KAEAgB,EAAE,QAAQ,eACVtB,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,gBAAAoB,EAACS,MACC,UAAA7B,EAAM,IAAI,CAAC8B,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,MACtBhC,EAASD,EAAM,OAAO,CAACkC,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,eAAA5C;AAAA,EACA,QAAA6C;AACD,MAAM;AACL,QAAM,CAACX,GAAQY,CAAS,IAAI3C;AAAA,IAAsB,MACjD4B,EAAWC,GAAUC,CAAO;AAAA,EAAA,GAEvB,CAACc,GAAQC,CAAS,IAAI7C,EAAS,EAAK,GAEpC8C,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;AAAA,IACtB,CAACK,MAAM,CAACA,EAAE,YAAY,OAAOpB,EAAOoB,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW;AAAA,EAAA,GAGxDC,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,YAACrB;AAAA,YAAA;AAAA,cACA,UAAUmE;AAAA,cACV,aAAaD,EAAM,QAAQ;AAAA,cAC3B,OAAOxB,EAAQF,EAAO0B,EAAM,GAAG,CAAC;AAAA,cAChC,UAAU,CAACjE,MAAUwD,EAASS,EAAM,KAAKjE,EAAM,KAAK,GAAG,CAAC;AAAA,cACxD,eAAAK;AAAA,cACA,MACC,gBAAAe,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,eAAA1C;AAAA,UAAA;AAAA,UARK4D,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,eAAAhB;AAAA,QACA,UAAU,CAACkB,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,IAAOnF,EAAU8C,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,10 +1,10 @@
1
1
  import { jsxs as lt, Fragment as Kt, jsx as c } from "react/jsx-runtime";
2
2
  import { useState as r, useRef as h, useMemo as Nt, useCallback as a } from "react";
3
- import Gt from "styled-components";
3
+ import Bt from "styled-components";
4
4
  import { addUnique as at } from "../../../utils/arrayUtils.js";
5
5
  import { COLORS as j } from "../../../constants/Theme.js";
6
- import { AGENT_CHAR_LIMITS as Bt } from "../constants/charLimits.js";
7
- import { CONFIG_TOOL_SOURCES as Dt, ToolSource as p } from "../constants/tools.js";
6
+ import { AGENT_CHAR_LIMITS as Dt } from "../constants/charLimits.js";
7
+ import { CONFIG_TOOL_SOURCES as Gt, ToolSource as p } from "../constants/tools.js";
8
8
  import { buildAgentMentionItems as Pt, buildCustomToolMentionItems as zt, restApiMentionItem as Lt, configToolMentionItem as Ut, restApiToolName as Ht, configToolName as $t, toolSourceLabel as Ft } from "../utils/mentionSerialization.js";
9
9
  import { sourceIcon as W, SOURCE_ICONS as ct, renderSourceIcon as ut } from "../utils/sourceIcons.js";
10
10
  import { buildToolActions as jt } from "../utils/toolActions.js";
@@ -19,7 +19,7 @@ import { Toaster as te } from "../../toaster/Toaster.js";
19
19
  const ee = 1e3, Y = 1002, mt = (A, f) => {
20
20
  const s = A ?? [];
21
21
  return s.some((u) => u.id === f.id) ? s.map((u) => u.id === f.id ? f : u) : [...s, f];
22
- }, pt = Gt.button`
22
+ }, pt = Bt.button`
23
23
  align-self: flex-start;
24
24
  border: 1px solid ${j.stroke.primary};
25
25
  color: ${j.content.primary};
@@ -45,14 +45,14 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
45
45
  title: q = "Create sub-agent",
46
46
  initial: g,
47
47
  appLabel: J = "Manifest",
48
- charLimits: T = Bt,
48
+ charLimits: T = Dt,
49
49
  variablesData: v
50
50
  }) => {
51
51
  const [w, ft] = r(g?.name ?? ""), [b, R] = r(g?.instructions ?? ""), [I, _] = r(g?.guardrail ?? ""), [O, k] = r(g?.tools ?? []), [m, K] = r(
52
52
  g?.configTools ?? []
53
53
  ), [d, N] = r(
54
54
  g?.restApiTools ?? []
55
- ), [i, y] = r(null), E = h(0), [Q, V] = r(!1), [gt, G] = r(0), [yt, B] = r(0), [S, tt] = r(null), D = Nt(
55
+ ), [i, y] = r(null), E = h(0), [Q, V] = r(!1), [gt, B] = r(0), [yt, D] = r(0), [S, tt] = r(null), G = Nt(
56
56
  () => [
57
57
  ...Pt(s, [], J),
58
58
  ...zt(m, d)
@@ -95,7 +95,7 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
95
95
  []
96
96
  ), St = a(
97
97
  (t) => {
98
- const e = Dt[t];
98
+ const e = Gt[t];
99
99
  e ? L(e) : z();
100
100
  },
101
101
  [L, z]
@@ -121,10 +121,10 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
121
121
  tools: O,
122
122
  configTools: m,
123
123
  restApiTools: d
124
- }, R((n) => l(n)), _((n) => l(n)), k((n) => n.filter((x) => x !== t)), K((n) => n.filter((x) => x.id !== t)), N((n) => n.filter((x) => x.id !== t)), G((n) => n + 1), B((n) => n + 1), nt.current += 1, H({ id: nt.current, message: `Tool "${e}" removed` });
124
+ }, R((n) => l(n)), _((n) => l(n)), k((n) => n.filter((x) => x !== t)), K((n) => n.filter((x) => x.id !== t)), N((n) => n.filter((x) => x.id !== t)), B((n) => n + 1), D((n) => n + 1), nt.current += 1, H({ id: nt.current, message: `Tool "${e}" removed` });
125
125
  }, vt = () => {
126
126
  const t = $.current;
127
- t && (R(t.instructions), _(t.guardrail), k(t.tools), K(t.configTools), N(t.restApiTools), G((e) => e + 1), B((e) => e + 1), $.current = null), H(null);
127
+ t && (R(t.instructions), _(t.guardrail), k(t.tools), K(t.configTools), N(t.restApiTools), B((e) => e + 1), D((e) => e + 1), $.current = null), H(null);
128
128
  }, st = w.trim().length > 0 && (b.trim().length > 0 || I.trim().length > 0), Rt = O.map((t) => {
129
129
  const e = s.find((o) => o.tool_id === t);
130
130
  return e ? {
@@ -191,7 +191,7 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
191
191
  tt(t);
192
192
  try {
193
193
  const o = await u(t, t === "instructions" ? b : I);
194
- t === "instructions" ? (R(o), G((l) => l + 1)) : (_(o), B((l) => l + 1));
194
+ t === "instructions" ? (R(o), B((l) => l + 1)) : (_(o), D((l) => l + 1));
195
195
  } finally {
196
196
  tt(null);
197
197
  }
@@ -257,10 +257,11 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
257
257
  placeholder: "Write the steps in plain English. Type @ to reference a tool.",
258
258
  minHeight: "160px",
259
259
  resetKey: `instr-${gt}`,
260
- mentionItems: D,
260
+ mentionItems: G,
261
261
  tools: s,
262
262
  toolActions: F,
263
263
  variablesData: v,
264
+ addDataButton: !0,
264
265
  onMentionSelect: ot,
265
266
  onFocus: bt,
266
267
  registerInsert: ht,
@@ -287,10 +288,11 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
287
288
  placeholder: "e.g. Never discuss competitor pricing. Type @ to reference a tool.",
288
289
  minHeight: "160px",
289
290
  resetKey: `guard-${yt}`,
290
- mentionItems: D,
291
+ mentionItems: G,
291
292
  tools: s,
292
293
  toolActions: F,
293
294
  variablesData: v,
295
+ addDataButton: !0,
294
296
  onMentionSelect: ot,
295
297
  onFocus: It,
296
298
  registerInsert: Tt,
@@ -314,7 +316,7 @@ const ee = 1e3, Y = 1002, mt = (A, f) => {
314
316
  items: Et,
315
317
  addableOptions: Mt,
316
318
  sourceGroups: wt,
317
- mentionItems: D,
319
+ mentionItems: G,
318
320
  actionSources: F,
319
321
  emptyText: "No tools added yet.",
320
322
  pickerOpensUp: !0,