@bikdotai/bik-component-library 0.0.849-beta.3 → 0.0.849-beta.5
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/AddDataPill.js +10 -0
- package/dist/cjs/components/agent-builder/components/AddDataPill.js.map +1 -0
- package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js +1 -1
- package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/MentionEditor.js +1 -1
- package/dist/cjs/components/agent-builder/components/MentionEditor.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/MentionField.js +1 -1
- package/dist/cjs/components/agent-builder/components/MentionField.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/components/ToolInstructionsField.js +1 -1
- package/dist/cjs/components/agent-builder/components/ToolInstructionsField.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/VariableTriggerArea.js +10 -4
- package/dist/cjs/components/agent-builder/components/VariableTriggerArea.js.map +1 -1
- package/dist/cjs/components/agent-builder/utils/mentionSerialization.js +4 -4
- package/dist/cjs/components/agent-builder/utils/mentionSerialization.js.map +1 -1
- package/dist/cjs/editor/BikEditor.js +1 -1
- package/dist/cjs/editor/BikEditor.js.map +1 -1
- package/dist/cjs/editor/BikEditor.styles.js +5 -3
- package/dist/cjs/editor/BikEditor.styles.js.map +1 -1
- package/dist/cjs/editor/BikEditor.types.js.map +1 -1
- package/dist/esm/components/agent-builder/components/AddDataPill.d.ts +18 -0
- package/dist/esm/components/agent-builder/components/AddDataPill.js +32 -0
- package/dist/esm/components/agent-builder/components/AddDataPill.js.map +1 -0
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +21 -19
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/MentionEditor.d.ts +7 -2
- package/dist/esm/components/agent-builder/components/MentionEditor.js +119 -102
- package/dist/esm/components/agent-builder/components/MentionEditor.js.map +1 -1
- package/dist/esm/components/agent-builder/components/MentionField.js +30 -29
- package/dist/esm/components/agent-builder/components/MentionField.js.map +1 -1
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.d.ts +9 -0
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js +126 -119
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/ToolInstructionsField.js +20 -19
- package/dist/esm/components/agent-builder/components/ToolInstructionsField.js.map +1 -1
- package/dist/esm/components/agent-builder/components/VariableTriggerArea.d.ts +15 -0
- package/dist/esm/components/agent-builder/components/VariableTriggerArea.js +112 -56
- package/dist/esm/components/agent-builder/components/VariableTriggerArea.js.map +1 -1
- package/dist/esm/components/agent-builder/utils/mentionSerialization.js +26 -20
- package/dist/esm/components/agent-builder/utils/mentionSerialization.js.map +1 -1
- package/dist/esm/editor/BikEditor.js +24 -18
- package/dist/esm/editor/BikEditor.js.map +1 -1
- package/dist/esm/editor/BikEditor.styles.js +5 -3
- package/dist/esm/editor/BikEditor.styles.js.map +1 -1
- package/dist/esm/editor/BikEditor.types.d.ts +9 -0
- package/dist/esm/editor/BikEditor.types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),l=require("../../../assets/icons/plus.svg.js"),i=require("styled-components"),o=require("../../add-variableV2/AddVariableBox.styled.js"),s=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},n=s(i),r=({onOpen:t,...d})=>e.jsx(c,{type:"button","data-test":d["data-test"]??"add-data-pill",onMouseDown:a=>a.preventDefault(),onClick:t,children:e.jsxs("div",{className:"add",children:[e.jsx(l.default,{width:16,height:16,color:"white"}),e.jsx("div",{children:"Add data"})]})}),c=n.default(o.AddVariableStyled)`
|
|
2
|
+
bottom: -30px;
|
|
3
|
+
z-index: 20;
|
|
4
|
+
white-space: nowrap;
|
|
5
|
+
|
|
6
|
+
.add {
|
|
7
|
+
gap: 4px;
|
|
8
|
+
}
|
|
9
|
+
`;exports.AddDataPill=r;
|
|
10
|
+
//# sourceMappingURL=AddDataPill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddDataPill.js","sources":["../../../../../src/components/agent-builder/components/AddDataPill.tsx"],"sourcesContent":["import PlusIcon from '@src/assets/icons/plus.svg';\nimport React from 'react';\nimport styled from 'styled-components';\nimport { AddVariableStyled } from '../../add-variableV2/AddVariableBox.styled';\n\ninterface AddDataPillProps {\n\t/** Open the reference / variable menu (same as typing `@` in the field). */\n\tonOpen: () => void;\n\t'data-test'?: string;\n}\n\n/**\n * The floating \"+ Add data\" affordance shown at a focused field's bottom-right\n * corner. Reuses the dashboard's standard Add-variable button\n * (`InputWithVariables`). The parent anchors it: render inside a\n * `position: relative` container.\n *\n * `onMouseDown` is swallowed so clicking never blurs the field — the pill is\n * typically shown only while the field has focus, and the menu inserts at the\n * field's caret.\n */\nexport const AddDataPill: React.FC<AddDataPillProps> = ({\n\tonOpen,\n\t...rest\n}) => (\n\t<PillStyled\n\t\ttype=\"button\"\n\t\tdata-test={rest['data-test'] ?? 'add-data-pill'}\n\t\tonMouseDown={(e) => e.preventDefault()}\n\t\tonClick={onOpen}\n\t>\n\t\t<div className=\"add\">\n\t\t\t{/* svgr strips svg dimensions — size explicitly or it renders huge. */}\n\t\t\t<PlusIcon width={16} height={16} color=\"white\" />\n\t\t\t<div>Add data</div>\n\t\t</div>\n\t</PillStyled>\n);\n\nconst PillStyled = styled(AddVariableStyled)`\n\tbottom: -30px;\n\tz-index: 20;\n\twhite-space: nowrap;\n\n\t.add {\n\t\tgap: 4px;\n\t}\n`;\n"],"names":["AddDataPill","onOpen","rest","jsx","PillStyled","e","jsxs","PlusIcon","styled","AddVariableStyled"],"mappings":"6TAqBaA,EAA0C,CAAC,CACvD,OAAAC,EACA,GAAGC,CACJ,IACCC,EAAAA,IAACC,EAAA,CACA,KAAK,SACL,YAAWF,EAAK,WAAW,GAAK,gBAChC,YAAcG,GAAMA,EAAE,eAAA,EACtB,QAASJ,EAET,SAAAK,EAAAA,KAAC,MAAA,CAAI,UAAU,MAEd,SAAA,CAAAH,MAACI,EAAAA,SAAS,MAAO,GAAI,OAAQ,GAAI,MAAM,QAAQ,EAC/CJ,EAAAA,IAAC,OAAI,SAAA,UAAA,CAAQ,CAAA,CAAA,CACd,CAAA,CACD,EAGKC,EAAaI,EAAAA,QAAOC,mBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),A=require("../../../assets/icons/cross.svg.js"),T=require("react"),D=require("styled-components"),f=require("../../TypographyStyle.js"),i=require("../../../constants/Theme.js"),P=require("../AgentBuilder.styled.js"),F=require("../constants/charLimits.js"),v=require("./DrawerHeaderText.js"),V=require("./ToolInstructionsField.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),A=require("../../../assets/icons/cross.svg.js"),T=require("react"),D=require("styled-components"),f=require("../../TypographyStyle.js"),i=require("../../../constants/Theme.js"),P=require("../AgentBuilder.styled.js"),F=require("../constants/charLimits.js"),v=require("./DrawerHeaderText.js"),V=require("./ToolInstructionsField.js"),B=require("./VariableTriggerArea.js"),Y=require("../../side-modal/SideModal.js"),M=require("../../switch/Switch.js"),z=require("../../input/Input.js"),H=require("../../tag/Tag.js"),q=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},W=q(T),g=q(D),G={send_email:{title:"Send Email",subtitle:"Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message."},send_slack_message:{title:"Send Slack message",subtitle:"Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation."}},N=({chips:t,onChange:s,placeholder:u,nativeID:d,hint:m})=>{const[y,x]=T.useState(""),p=()=>{const a=y.split(",").map(o=>o.trim()).filter(Boolean);a.length&&s([...t,...a.filter(o=>!t.includes(o))]),x("")};return n.jsxs(Q,{children:[n.jsx(U,{id:d,type:"text",placeholder:u,value:y,onChange:a=>x(a.target.value),onBlur:p,onKeyDown:a=>{a.key==="Enter"||a.key===","?(a.preventDefault(),p()):a.key==="Backspace"&&y===""&&t.length>0&&s(t.slice(0,-1))}}),m,t.length>0&&n.jsx(X,{children:t.map((a,o)=>n.jsx(H.Tag,{tagText:a,theme:"light",type:"neutral",variant:"regular",TrailingIcon:A.default,onTrailingIconClicked:()=>s(t.filter((O,S)=>S!==o))},`${a}-${o}`))})]})},J=(t,s)=>{const u={};return Object.keys(t).forEach(d=>{u[d]=s?.params[d]?.value??t[d].value}),u},L=t=>String(t??"").split(",").map(s=>s.trim()).filter(Boolean),K=({toolKey:t,template:s,onClose:u,onSave:d,initial:m,onImprove:y,charLimits:x=F.AGENT_CHAR_LIMITS,variablesData:p,zIndex:a})=>{const[o,O]=T.useState(()=>J(s,m)),[S,w]=T.useState(!1),b=Object.values(s),R=t==="send_email",h=(e,l)=>O(c=>({...c,[e]:l})),_=b.every(e=>!e.required||String(o[e.key]??"").trim()!==""),E=async()=>{if(!_||S)return;const e={};b.forEach(r=>{e[r.key]={...r,value:o[r.key]}});const l={id:m?.id??`${t}_${Date.now().toString(36)}`,tool_key:t,params:e},c=d(l);if(c&&typeof c.then=="function"){w(!0);try{await c}finally{w(!1)}}},$=e=>{const l=`config-tool-${e.key.toLowerCase()}`;switch(e.component){case"KeywordInput":if(!R)break;return n.jsxs(P.FieldBlock,{children:[n.jsx(f.TitleSmall,{color:i.COLORS.content.primary,children:e.title}),n.jsx(B.VariableTriggerArea,{addDataButton:!0,variablesData:p,onInsert:r=>{const k=L(o[e.key]);k.includes(r)||h(e.key,[...k,r].join(","))},children:n.jsx(N,{nativeID:l,placeholder:e.hint??"",chips:L(o[e.key]),onChange:r=>h(e.key,r.join(",")),hint:n.jsx(f.BodyCaption,{color:i.COLORS.content.secondary,children:"Press Enter or comma to add multiple emails"})})})]},e.key);case"MultilineInput":return n.jsx(V.ToolInstructionsField,{"data-test":l,label:e.title,value:String(o[e.key]??""),onChange:r=>h(e.key,r),maxLength:x.instructions,placeholder:e.hint??"",onImprove:y,variablesData:p},e.key);case"Switch":return n.jsxs(Z,{children:[n.jsxs(ee,{children:[n.jsx(f.TitleSmall,{color:i.COLORS.content.primary,children:e.title}),e.hint&&n.jsx(f.BodyCaption,{color:i.COLORS.content.secondary,children:e.hint})]}),n.jsx(M.Switch,{"data-test":l,value:!!o[e.key],onValueChange:async r=>h(e.key,r)})]},e.key)}const c=n.jsx(z.Input,{"data-test":l,variant:"small",labelText:e.title,labelTextBold:!0,placeholder:e.hint??"",value:String(o[e.key]??""),onChangeText:r=>h(e.key,r)});return R?n.jsx(B.VariableTriggerArea,{addDataButton:!0,variablesData:p,onInsert:(r,k)=>{const j=String(o[e.key]??""),I=k??j.length;h(e.key,`${j.slice(0,I)}${r}${j.slice(I)}`)},children:c},e.key):n.jsx(W.default.Fragment,{children:c},e.key)},C=G[t];return n.jsx(Y.SideModal,{header:C.title,closeOnEscapeKey:!1,zIndex:a,headerCustomComponent:n.jsx(v.DrawerHeaderText,{title:C.title,subtitle:C.subtitle}),hideCrossButton:!1,width:"431px",headerStyle:v.DRAWER_HEADER_STYLE,bodyStyle:v.DRAWER_BODY_STYLE,onClose:u,saveButtonProps:{"data-test":"config-tool-save",buttonText:"Save",buttonType:"primary",size:"small",disabled:!_,isLoading:S,onClick:E},cancelButtonProps:{"data-test":"config-tool-cancel",buttonText:"Cancel",buttonType:"tertiaryGray",size:"small",onClick:u},children:b.map($)})},Q=g.default.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
gap: 8px;
|
|
@@ -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\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\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, { 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,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),i=require("react"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),i=require("react"),x=require("../../TypographyStyle.js"),T=require("../../../constants/Theme.js"),u=require("../AgentBuilder.styled.js"),v=require("../constants/editorStyle.js"),o=require("../utils/mentionSerialization.js"),w=require("./AddDataPill.js"),z=require("./MentionPicker.js"),G=require("../../../editor/BikEditor.js"),J=({label:y,value:c,onChange:C,maxLength:d,placeholder:M,minHeight:j="200px",resetKey:a,mentionItems:l,tools:k,onMentionSelect:q,onFocus:E,registerInsert:s,onCreateSubAgent:O,toolActions:R,integrationStatus:A,onConnectIntegration:B,variablesData:S,addDataButton:H,action:D,...L})=>{const r=i.useRef(null),[P,b]=i.useState(c.length),[f,m]=i.useState(!1),F=i.useCallback(t=>{const e=o.variableTokenName(t.actualValue);r.current?.insertInlineContent(`${o.buildMentionHtml(e,`{{${e}}}`,"variable")} `)},[]),g=i.useCallback((t,e,V)=>{const h=r.current;if(!h)return;const _=l.find(p=>String(p.id)===String(e)&&p.meta?.kind===t),$=V??_?.label??e;h.insertInlineContent(`${o.buildMentionHtml(String(e),$,t)} `)},[l]);i.useEffect(()=>{if(s)return s(g),()=>s(null)},[s,g]);const N=i.useMemo(()=>o.instructionsToEditorHtml(c,[...l,...o.buildVariableMentionItems(S)]),[a]);return i.useEffect(()=>b(c.length),[a]),n.jsxs(u.FieldBlock,{children:[n.jsxs(u.FieldLabelRow,{children:[n.jsx(x.TitleSmall,{color:T.COLORS.content.primary,children:y}),n.jsxs(x.BodyCaption,{color:T.COLORS.content.secondary,children:[P,"/",d]})]}),n.jsxs(u.AiTextAreaShell,{minHeight:j,focused:f,style:{position:"relative"},"data-test":L["data-test"],children:[n.jsx(G.BikEditor,{ref:r,initialContent:N,placeholder:M,characterLimit:d,minHeight:"120px",maxHeight:"320px",style:{border:"none"},editorStyle:v.AGENT_EDITOR_STYLE,onFocus:()=>{m(!0),E?.()},onBlur:()=>m(!1),mentions:{agents:l,removeTriggerOnDismiss:!0,renderDropdown:t=>n.jsx(z.MentionPicker,{...t,onCreateSubAgent:O,toolActions:R,integrationStatus:A,onConnectIntegration:B,variablesData:S,onSelectVariable:F}),onSelect:t=>{const e=t.meta?.kind;(e==="tool"||e==="subagent")&&q?.(e,String(t.id))}},onChange:t=>{b(t.characterCount);const e=r.current?.getJSON()??null;C(o.editorDocToInstructions(e,k))}},a),D,H&&f&&n.jsx(w.AddDataPill,{"data-test":"mention-add-data",onOpen:()=>r.current?.actions.openMentionMenu("@")})]})]})};exports.MentionEditor=J;
|
|
2
2
|
//# sourceMappingURL=MentionEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentionEditor.js","sources":["../../../../../src/components/agent-builder/components/MentionEditor.tsx"],"sourcesContent":["import { BikEditor, BikEditorRef, MentionItem } from '@src/editor';\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type {\n\tVariableListInterfaceV3,\n\tVariableV3,\n} from '../../variable-picker-v3/model';\nimport { AgentTool } from '../AgentBuilder.model';\nimport {\n\tAiTextAreaShell,\n\tFieldBlock,\n\tFieldLabelRow,\n} from '../AgentBuilder.styled';\nimport { AGENT_EDITOR_STYLE } from '../constants/editorStyle';\nimport type { ToolAction, ToolSource } from '../constants/tools';\nimport {\n\tbuildMentionHtml,\n\tbuildVariableMentionItems,\n\teditorDocToInstructions,\n\tinstructionsToEditorHtml,\n\tMentionKindMeta,\n\tvariableTokenName,\n} from '../utils/mentionSerialization';\nimport { MentionPicker } from './MentionPicker';\n\ntype InsertFn = (kind: 'tool' | 'subagent', id: string, label?: string) => void;\n\ninterface MentionEditorProps {\n\tlabel: string;\n\tvalue: string;\n\tonChange: (text: string) => void;\n\tmaxLength: number;\n\tplaceholder?: string;\n\tminHeight?: string;\n\t/** Changing this remounts the editor with fresh content. */\n\tresetKey?: string | number;\n\t/** Items shown in the `@` picker (tools, and sub-agents where allowed). */\n\tmentionItems: MentionItem[];\n\t/** Tools used to serialise mention nodes back to `{{tool:KEY}}`. */\n\ttools: AgentTool[];\n\t/** Called when an item is picked from the `@` menu (to attach it upstream). */\n\tonMentionSelect?: (kind: 'tool' | 'subagent', id: string) => void;\n\tonFocus?: () => void;\n\t/** Receives an insert-at-cursor fn (and null on unmount) for side-panel adds. */\n\tregisterInsert?: (fn: InsertFn | null) => void;\n\t/**\n\t * When set, the `@` picker's Sub-agent view shows a \"Create new\" row that calls\n\t * this (opens the create-sub-agent drawer). Omit to hide it (e.g. the drawer's\n\t * own editors, which can't nest sub-agents).\n\t */\n\tonCreateSubAgent?: () => void;\n\t/**\n\t * Built-in tool actions (Rest API / Handover to email) shown in the `@` picker's\n\t * Tools view. Picking one opens its drawer instead of inserting a mention.\n\t */\n\ttoolActions?: ToolAction[];\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>;\n\tonConnectIntegration?: (source: ToolSource) => void;\n\t/**\n\t * Variable catalog for the `@` picker's \"Variables\" view. Picking one inserts\n\t * a `Variable: <name>` mention chip at the cursor, persisted as a\n\t * `{{variable:<name>}}` token. Omit to hide the category.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t/** Optional action(s) rendered inside the shell, below the editor. */\n\taction?: React.ReactNode;\n\t'data-test'?: string;\n}\n\n/**\n * Presentational BikEditor field with `@` mentions. Stores firebase token text\n * (`{{tool:KEY}}` / `{{subagent:ID}}`). Context-free — both the builder's\n * Step-3 fields and the create-sub-agent drawer compose it.\n */\nexport const MentionEditor: React.FC<MentionEditorProps> = ({\n\tlabel,\n\tvalue,\n\tonChange,\n\tmaxLength,\n\tplaceholder,\n\tminHeight = '200px',\n\tresetKey,\n\tmentionItems,\n\ttools,\n\tonMentionSelect,\n\tonFocus,\n\tregisterInsert,\n\tonCreateSubAgent,\n\ttoolActions,\n\tintegrationStatus,\n\tonConnectIntegration,\n\tvariablesData,\n\taction,\n\t...rest\n}) => {\n\tconst editorRef = useRef<BikEditorRef>(null);\n\tconst [count, setCount] = useState(value.length);\n\n\t// The picker dismissed itself already (stripping the \"@\" + query) — drop a\n\t// `Variable: <name>` mention chip at the cursor, same shape as tool /\n\t// sub-agent chips. `editorDocToInstructions` serializes it back to a\n\t// `{{variable:<name>}}` token.\n\tconst onSelectVariable = useCallback((variable: VariableV3) => {\n\t\tconst name = variableTokenName(variable.actualValue);\n\t\teditorRef.current?.insertInlineContent(\n\t\t\t`${buildMentionHtml(\n\t\t\t\tname,\n\t\t\t\t`Variable: ${variable.displayName}`,\n\t\t\t\t'variable',\n\t\t\t)} `,\n\t\t);\n\t}, []);\n\n\tconst insert = useCallback<InsertFn>(\n\t\t(kind, id, overrideLabel) => {\n\t\t\tconst editor = editorRef.current;\n\t\t\tif (!editor) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst item = mentionItems.find(\n\t\t\t\t(m) =>\n\t\t\t\t\tString(m.id) === String(id) &&\n\t\t\t\t\t(m.meta as unknown as MentionKindMeta | undefined)?.kind === kind,\n\t\t\t);\n\t\t\tconst finalLabel = overrideLabel ?? item?.label ?? id;\n\t\t\teditor.insertInlineContent(\n\t\t\t\t`${buildMentionHtml(String(id), finalLabel, kind)} `,\n\t\t\t);\n\t\t},\n\t\t[mentionItems],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!registerInsert) {\n\t\t\treturn;\n\t\t}\n\t\tregisterInsert(insert);\n\t\treturn () => registerInsert(null);\n\t}, [registerInsert, insert]);\n\n\t// Mount-only initial HTML; recomputed (editor remounted via key) on resetKey.\n\t// Variable items are merged in so stored `{{name}}` tokens rehydrate as chips.\n\tconst initialHtml = useMemo(\n\t\t() =>\n\t\t\tinstructionsToEditorHtml(value, [\n\t\t\t\t...mentionItems,\n\t\t\t\t...buildVariableMentionItems(variablesData),\n\t\t\t]),\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[resetKey],\n\t);\n\n\tuseEffect(\n\t\t() => setCount(value.length),\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[resetKey],\n\t);\n\n\treturn (\n\t\t<FieldBlock>\n\t\t\t<FieldLabelRow>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>{label}</TitleSmall>\n\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t{count}/{maxLength}\n\t\t\t\t</BodyCaption>\n\t\t\t</FieldLabelRow>\n\n\t\t\t<AiTextAreaShell minHeight={minHeight} data-test={rest['data-test']}>\n\t\t\t\t<BikEditor\n\t\t\t\t\tkey={resetKey}\n\t\t\t\t\tref={editorRef}\n\t\t\t\t\tinitialContent={initialHtml}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t// Soft limit: blocks typing past the cap but lets a paste through\n\t\t\t\t\t// (overflow rendered grey) instead of rejecting the whole paste.\n\t\t\t\t\tcharacterLimit={maxLength}\n\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\tmaxHeight=\"320px\"\n\t\t\t\t\tstyle={{ border: 'none' }}\n\t\t\t\t\teditorStyle={AGENT_EDITOR_STYLE}\n\t\t\t\t\tonFocus={onFocus}\n\t\t\t\t\tmentions={{\n\t\t\t\t\t\tagents: mentionItems,\n\t\t\t\t\t\tremoveTriggerOnDismiss: true,\n\t\t\t\t\t\trenderDropdown: (props) => (\n\t\t\t\t\t\t\t<MentionPicker\n\t\t\t\t\t\t\t\t{...props}\n\t\t\t\t\t\t\t\tonCreateSubAgent={onCreateSubAgent}\n\t\t\t\t\t\t\t\ttoolActions={toolActions}\n\t\t\t\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\t\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\t\tonSelectVariable={onSelectVariable}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tonSelect: (item) => {\n\t\t\t\t\t\t\tconst kind = (item.meta as unknown as MentionKindMeta | undefined)\n\t\t\t\t\t\t\t\t?.kind;\n\t\t\t\t\t\t\t// Variables never come through this path (they use the embedded\n\t\t\t\t\t\t\t// picker's onSelectVariable) and have nothing to attach upstream.\n\t\t\t\t\t\t\tif (kind === 'tool' || kind === 'subagent') {\n\t\t\t\t\t\t\t\tonMentionSelect?.(kind, String(item.id));\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\tonChange={(snapshot) => {\n\t\t\t\t\t\tsetCount(snapshot.characterCount);\n\t\t\t\t\t\tconst doc = editorRef.current?.getJSON() ?? null;\n\t\t\t\t\t\tonChange(editorDocToInstructions(doc, tools));\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t{action}\n\t\t\t</AiTextAreaShell>\n\t\t</FieldBlock>\n\t);\n};\n"],"names":["MentionEditor","label","value","onChange","maxLength","placeholder","minHeight","resetKey","mentionItems","tools","onMentionSelect","onFocus","registerInsert","onCreateSubAgent","toolActions","integrationStatus","onConnectIntegration","variablesData","action","rest","editorRef","useRef","count","setCount","useState","onSelectVariable","useCallback","variable","name","variableTokenName","buildMentionHtml","insert","kind","id","overrideLabel","editor","item","m","finalLabel","useEffect","initialHtml","useMemo","instructionsToEditorHtml","buildVariableMentionItems","FieldBlock","jsxs","FieldLabelRow","jsx","TitleSmall","COLORS","BodyCaption","AiTextAreaShell","BikEditor","AGENT_EDITOR_STYLE","props","MentionPicker","snapshot","doc","editorDocToInstructions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MentionEditor.js","sources":["../../../../../src/components/agent-builder/components/MentionEditor.tsx"],"sourcesContent":["import { BikEditor, BikEditorRef, MentionItem } from '@src/editor';\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type {\n\tVariableListInterfaceV3,\n\tVariableV3,\n} from '../../variable-picker-v3/model';\nimport { AgentTool } from '../AgentBuilder.model';\nimport {\n\tAiTextAreaShell,\n\tFieldBlock,\n\tFieldLabelRow,\n} from '../AgentBuilder.styled';\nimport { AGENT_EDITOR_STYLE } from '../constants/editorStyle';\nimport type { ToolAction, ToolSource } from '../constants/tools';\nimport {\n\tbuildMentionHtml,\n\tbuildVariableMentionItems,\n\teditorDocToInstructions,\n\tinstructionsToEditorHtml,\n\tMentionKindMeta,\n\tvariableTokenName,\n} from '../utils/mentionSerialization';\nimport { AddDataPill } from './AddDataPill';\nimport { MentionPicker } from './MentionPicker';\n\ntype InsertFn = (kind: 'tool' | 'subagent', id: string, label?: string) => void;\n\ninterface MentionEditorProps {\n\tlabel: string;\n\tvalue: string;\n\tonChange: (text: string) => void;\n\tmaxLength: number;\n\tplaceholder?: string;\n\tminHeight?: string;\n\t/** Changing this remounts the editor with fresh content. */\n\tresetKey?: string | number;\n\t/** Items shown in the `@` picker (tools, and sub-agents where allowed). */\n\tmentionItems: MentionItem[];\n\t/** Tools used to serialise mention nodes back to `{{tool:KEY}}`. */\n\ttools: AgentTool[];\n\t/** Called when an item is picked from the `@` menu (to attach it upstream). */\n\tonMentionSelect?: (kind: 'tool' | 'subagent', id: string) => void;\n\tonFocus?: () => void;\n\t/** Receives an insert-at-cursor fn (and null on unmount) for side-panel adds. */\n\tregisterInsert?: (fn: InsertFn | null) => void;\n\t/**\n\t * When set, the `@` picker's Sub-agent view shows a \"Create new\" row that calls\n\t * this (opens the create-sub-agent drawer). Omit to hide it (e.g. the drawer's\n\t * own editors, which can't nest sub-agents).\n\t */\n\tonCreateSubAgent?: () => void;\n\t/**\n\t * Built-in tool actions (Rest API / Handover to email) shown in the `@` picker's\n\t * Tools view. Picking one opens its drawer instead of inserting a mention.\n\t */\n\ttoolActions?: ToolAction[];\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>;\n\tonConnectIntegration?: (source: ToolSource) => void;\n\t/**\n\t * Variable catalog for the `@` picker's \"Variables\" view. Picking one inserts\n\t * a `{{<name>}}` mention chip (rendered as the purple raw token) at the\n\t * cursor, persisted as `{{variable:<name>}}`. Omit to hide the category.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t/**\n\t * Show a floating \"+ Add data\" pill at the field's bottom-right while it is\n\t * focused. Clicking it opens the same `@` reference menu at the cursor.\n\t */\n\taddDataButton?: boolean;\n\t/** Optional action(s) rendered inside the shell, below the editor. */\n\taction?: React.ReactNode;\n\t'data-test'?: string;\n}\n\n/**\n * Presentational BikEditor field with `@` mentions. Stores firebase token text\n * (`{{tool:KEY}}` / `{{subagent:ID}}`). Context-free — both the builder's\n * Step-3 fields and the create-sub-agent drawer compose it.\n */\nexport const MentionEditor: React.FC<MentionEditorProps> = ({\n\tlabel,\n\tvalue,\n\tonChange,\n\tmaxLength,\n\tplaceholder,\n\tminHeight = '200px',\n\tresetKey,\n\tmentionItems,\n\ttools,\n\tonMentionSelect,\n\tonFocus,\n\tregisterInsert,\n\tonCreateSubAgent,\n\ttoolActions,\n\tintegrationStatus,\n\tonConnectIntegration,\n\tvariablesData,\n\taddDataButton,\n\taction,\n\t...rest\n}) => {\n\tconst editorRef = useRef<BikEditorRef>(null);\n\tconst [count, setCount] = useState(value.length);\n\tconst [focused, setFocused] = useState(false);\n\n\t// The picker dismissed itself already (stripping the \"@\" + query) — drop a\n\t// mention chip at the cursor whose text is the raw token (`{{<name>}}`,\n\t// rendered purple by the editor). `editorDocToInstructions` serializes it\n\t// back to a `{{variable:<name>}}` token.\n\tconst onSelectVariable = useCallback((variable: VariableV3) => {\n\t\tconst name = variableTokenName(variable.actualValue);\n\t\teditorRef.current?.insertInlineContent(\n\t\t\t`${buildMentionHtml(name, `{{${name}}}`, 'variable')} `,\n\t\t);\n\t}, []);\n\n\tconst insert = useCallback<InsertFn>(\n\t\t(kind, id, overrideLabel) => {\n\t\t\tconst editor = editorRef.current;\n\t\t\tif (!editor) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst item = mentionItems.find(\n\t\t\t\t(m) =>\n\t\t\t\t\tString(m.id) === String(id) &&\n\t\t\t\t\t(m.meta as unknown as MentionKindMeta | undefined)?.kind === kind,\n\t\t\t);\n\t\t\tconst finalLabel = overrideLabel ?? item?.label ?? id;\n\t\t\teditor.insertInlineContent(\n\t\t\t\t`${buildMentionHtml(String(id), finalLabel, kind)} `,\n\t\t\t);\n\t\t},\n\t\t[mentionItems],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!registerInsert) {\n\t\t\treturn;\n\t\t}\n\t\tregisterInsert(insert);\n\t\treturn () => registerInsert(null);\n\t}, [registerInsert, insert]);\n\n\t// Mount-only initial HTML; recomputed (editor remounted via key) on resetKey.\n\t// Variable items are merged in so stored `{{name}}` tokens rehydrate as chips.\n\tconst initialHtml = useMemo(\n\t\t() =>\n\t\t\tinstructionsToEditorHtml(value, [\n\t\t\t\t...mentionItems,\n\t\t\t\t...buildVariableMentionItems(variablesData),\n\t\t\t]),\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[resetKey],\n\t);\n\n\tuseEffect(\n\t\t() => setCount(value.length),\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[resetKey],\n\t);\n\n\treturn (\n\t\t<FieldBlock>\n\t\t\t<FieldLabelRow>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>{label}</TitleSmall>\n\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t{count}/{maxLength}\n\t\t\t\t</BodyCaption>\n\t\t\t</FieldLabelRow>\n\n\t\t\t<AiTextAreaShell\n\t\t\t\tminHeight={minHeight}\n\t\t\t\tfocused={focused}\n\t\t\t\t// Anchors the floating \"+ Add data\" pill to the shell's corner.\n\t\t\t\tstyle={{ position: 'relative' }}\n\t\t\t\tdata-test={rest['data-test']}\n\t\t\t>\n\t\t\t\t<BikEditor\n\t\t\t\t\tkey={resetKey}\n\t\t\t\t\tref={editorRef}\n\t\t\t\t\tinitialContent={initialHtml}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t// Soft limit: blocks typing past the cap but lets a paste through\n\t\t\t\t\t// (overflow rendered grey) instead of rejecting the whole paste.\n\t\t\t\t\tcharacterLimit={maxLength}\n\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\tmaxHeight=\"320px\"\n\t\t\t\t\tstyle={{ border: 'none' }}\n\t\t\t\t\teditorStyle={AGENT_EDITOR_STYLE}\n\t\t\t\t\tonFocus={() => {\n\t\t\t\t\t\tsetFocused(true);\n\t\t\t\t\t\tonFocus?.();\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={() => setFocused(false)}\n\t\t\t\t\tmentions={{\n\t\t\t\t\t\tagents: mentionItems,\n\t\t\t\t\t\tremoveTriggerOnDismiss: true,\n\t\t\t\t\t\trenderDropdown: (props) => (\n\t\t\t\t\t\t\t<MentionPicker\n\t\t\t\t\t\t\t\t{...props}\n\t\t\t\t\t\t\t\tonCreateSubAgent={onCreateSubAgent}\n\t\t\t\t\t\t\t\ttoolActions={toolActions}\n\t\t\t\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\t\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\t\tonSelectVariable={onSelectVariable}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tonSelect: (item) => {\n\t\t\t\t\t\t\tconst kind = (item.meta as unknown as MentionKindMeta | undefined)\n\t\t\t\t\t\t\t\t?.kind;\n\t\t\t\t\t\t\t// Variables never come through this path (they use the embedded\n\t\t\t\t\t\t\t// picker's onSelectVariable) and have nothing to attach upstream.\n\t\t\t\t\t\t\tif (kind === 'tool' || kind === 'subagent') {\n\t\t\t\t\t\t\t\tonMentionSelect?.(kind, String(item.id));\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\tonChange={(snapshot) => {\n\t\t\t\t\t\tsetCount(snapshot.characterCount);\n\t\t\t\t\t\tconst doc = editorRef.current?.getJSON() ?? null;\n\t\t\t\t\t\tonChange(editorDocToInstructions(doc, tools));\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t{action}\n\t\t\t\t{addDataButton && focused && (\n\t\t\t\t\t<AddDataPill\n\t\t\t\t\t\tdata-test=\"mention-add-data\"\n\t\t\t\t\t\tonOpen={() => editorRef.current?.actions.openMentionMenu('@')}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</AiTextAreaShell>\n\t\t</FieldBlock>\n\t);\n};\n"],"names":["MentionEditor","label","value","onChange","maxLength","placeholder","minHeight","resetKey","mentionItems","tools","onMentionSelect","onFocus","registerInsert","onCreateSubAgent","toolActions","integrationStatus","onConnectIntegration","variablesData","addDataButton","action","rest","editorRef","useRef","count","setCount","useState","focused","setFocused","onSelectVariable","useCallback","variable","name","variableTokenName","buildMentionHtml","insert","kind","id","overrideLabel","editor","item","m","finalLabel","useEffect","initialHtml","useMemo","instructionsToEditorHtml","buildVariableMentionItems","FieldBlock","jsxs","FieldLabelRow","jsx","TitleSmall","COLORS","BodyCaption","AiTextAreaShell","BikEditor","AGENT_EDITOR_STYLE","props","MentionPicker","snapshot","doc","editorDocToInstructions","AddDataPill"],"mappings":"6bAuFaA,EAA8C,CAAC,CAC3D,MAAAC,EACA,MAAAC,EACA,SAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EAAY,QACZ,SAAAC,EACA,aAAAC,EACA,MAAAC,EACA,gBAAAC,EACA,QAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,YAAAC,EACA,kBAAAC,EACA,qBAAAC,EACA,cAAAC,EACA,cAAAC,EACA,OAAAC,EACA,GAAGC,CACJ,IAAM,CACL,MAAMC,EAAYC,EAAAA,OAAqB,IAAI,EACrC,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAASvB,EAAM,MAAM,EACzC,CAACwB,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EAMtCG,EAAmBC,cAAaC,GAAyB,CAC9D,MAAMC,EAAOC,EAAAA,kBAAkBF,EAAS,WAAW,EACnDT,EAAU,SAAS,oBAClB,GAAGY,EAAAA,iBAAiBF,EAAM,KAAKA,CAAI,KAAM,UAAU,CAAC,QAAA,CAEtD,EAAG,CAAA,CAAE,EAECG,EAASL,EAAAA,YACd,CAACM,EAAMC,EAAIC,IAAkB,CAC5B,MAAMC,EAASjB,EAAU,QACzB,GAAI,CAACiB,EACJ,OAED,MAAMC,EAAO/B,EAAa,KACxBgC,GACA,OAAOA,EAAE,EAAE,IAAM,OAAOJ,CAAE,GACzBI,EAAE,MAAiD,OAASL,CAAA,EAEzDM,EAAaJ,GAAiBE,GAAM,OAASH,EACnDE,EAAO,oBACN,GAAGL,EAAAA,iBAAiB,OAAOG,CAAE,EAAGK,EAAYN,CAAI,CAAC,QAAA,CAEnD,EACA,CAAC3B,CAAY,CAAA,EAGdkC,EAAAA,UAAU,IAAM,CACf,GAAK9B,EAGL,OAAAA,EAAesB,CAAM,EACd,IAAMtB,EAAe,IAAI,CACjC,EAAG,CAACA,EAAgBsB,CAAM,CAAC,EAI3B,MAAMS,EAAcC,EAAAA,QACnB,IACCC,EAAAA,yBAAyB3C,EAAO,CAC/B,GAAGM,EACH,GAAGsC,EAAAA,0BAA0B7B,CAAa,CAAA,CAC1C,EAEF,CAACV,CAAQ,CAAA,EAGVmC,OAAAA,EAAAA,UACC,IAAMlB,EAAStB,EAAM,MAAM,EAE3B,CAACK,CAAQ,CAAA,SAIRwC,aAAA,CACA,SAAA,CAAAC,OAACC,EAAAA,cAAA,CACA,SAAA,CAAAC,MAACC,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAU,SAAAnD,EAAM,EAClD+C,EAAAA,KAACK,EAAAA,YAAA,CAAY,MAAOD,EAAAA,OAAO,QAAQ,UACjC,SAAA,CAAA7B,EAAM,IAAEnB,CAAA,CAAA,CACV,CAAA,EACD,EAEA4C,EAAAA,KAACM,EAAAA,gBAAA,CACA,UAAAhD,EACA,QAAAoB,EAEA,MAAO,CAAE,SAAU,UAAA,EACnB,YAAWN,EAAK,WAAW,EAE3B,SAAA,CAAA8B,EAAAA,IAACK,EAAAA,UAAA,CAEA,IAAKlC,EACL,eAAgBsB,EAChB,YAAAtC,EAGA,eAAgBD,EAChB,UAAU,QACV,UAAU,QACV,MAAO,CAAE,OAAQ,MAAA,EACjB,YAAaoD,EAAAA,mBACb,QAAS,IAAM,CACd7B,EAAW,EAAI,EACfhB,IAAA,CACD,EACA,OAAQ,IAAMgB,EAAW,EAAK,EAC9B,SAAU,CACT,OAAQnB,EACR,uBAAwB,GACxB,eAAiBiD,GAChBP,EAAAA,IAACQ,EAAAA,cAAA,CACC,GAAGD,EACJ,iBAAA5C,EACA,YAAAC,EACA,kBAAAC,EACA,qBAAAC,EACA,cAAAC,EACA,iBAAAW,CAAA,CAAA,EAGF,SAAWW,GAAS,CACnB,MAAMJ,EAAQI,EAAK,MAChB,MAGCJ,IAAS,QAAUA,IAAS,aAC/BzB,IAAkByB,EAAM,OAAOI,EAAK,EAAE,CAAC,CAEzC,CAAA,EAED,SAAWoB,GAAa,CACvBnC,EAASmC,EAAS,cAAc,EAChC,MAAMC,EAAMvC,EAAU,SAAS,QAAA,GAAa,KAC5ClB,EAAS0D,EAAAA,wBAAwBD,EAAKnD,CAAK,CAAC,CAC7C,CAAA,EA5CKF,CAAA,EA8CLY,EACAD,GAAiBQ,GACjBwB,EAAAA,IAACY,EAAAA,YAAA,CACA,YAAU,mBACV,OAAQ,IAAMzC,EAAU,SAAS,QAAQ,gBAAgB,GAAG,CAAA,CAAA,CAC7D,CAAA,CAAA,CAEF,EACD,CAEF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("react/jsx-runtime"),n=require("react"),k=require("../context/AgentBuilderContext.js"),r=require("../utils/mentionSerialization.js"),y=require("../utils/toolActions.js"),D=require("./MentionEditor.js"),E=({fieldKey:e,label:A,placeholder:T,maxLength:m,minHeight:M,...p})=>{const{value:t,patch:C,addReference:l,availableTools:i,availableSubAgents:u,applicationType:c,mentionResetKey:S,registerMentionField:g,notifyMentionFocus:q,onCreateSubAgent:v,requestCreateSubAgent:F,requestToolAction:b,configToolTemplates:d,integrationStatus:s,onConnectIntegration:a,variablesData:I}=k.useAgentBuilderContext(),x=n.useMemo(()=>[...r.buildAgentMentionItems(i,u,r.appTypeLabel(c)),...r.buildCustomToolMentionItems(t.configTools,t.restApiTools)],[i,u,c,t.configTools,t.restApiTools]),R=n.useMemo(()=>y.buildToolActions(d,b,s,a),[b,d,s,a]),$=n.useCallback(o=>g(e,o),[g,e]),j=n.useCallback((o,B)=>l(o,B),[l]);return h.jsx(D.MentionEditor,{label:A,value:t[e]??"",onChange:o=>C({[e]:o}),maxLength:m,placeholder:T,minHeight:M,resetKey:`${t.id}:${e}:${S}`,mentionItems:x,tools:i,onMentionSelect:j,onFocus:()=>q(e),registerInsert:$,onCreateSubAgent:v?F:void 0,toolActions:R,integrationStatus:s,onConnectIntegration:a,variablesData:I,addDataButton:!0,"data-test":p["data-test"]})};exports.MentionField=E;
|
|
2
2
|
//# sourceMappingURL=MentionField.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentionField.js","sources":["../../../../../src/components/agent-builder/components/MentionField.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from 'react';\nimport { AgentValue } from '../AgentBuilder.model';\nimport { ToolAction } from '../constants/tools';\nimport {\n\tMentionFieldKey,\n\tuseAgentBuilderContext,\n} from '../context/AgentBuilderContext';\nimport {\n\tappTypeLabel,\n\tbuildAgentMentionItems,\n\tbuildCustomToolMentionItems,\n} from '../utils/mentionSerialization';\nimport { buildToolActions } from '../utils/toolActions';\nimport { MentionEditor } from './MentionEditor';\n\ninterface MentionFieldProps {\n\t/** Which AgentValue field this editor reads / writes. */\n\tfieldKey: MentionFieldKey;\n\tlabel: string;\n\tplaceholder?: string;\n\tmaxLength: number;\n\tminHeight?: string;\n\t'data-test'?: string;\n}\n\n/**\n * Context-bound {@link MentionEditor} for the builder's Step-3 Instructions /\n * Guardrails. Both `@` tools and sub-agents are offered; the field registers its\n * insert + focus with the context so side-panel adds drop a chip into whichever\n * field was last focused, and remounts on `mentionResetKey`.\n */\nexport const MentionField: React.FC<MentionFieldProps> = ({\n\tfieldKey,\n\tlabel,\n\tplaceholder,\n\tmaxLength,\n\tminHeight,\n\t...rest\n}) => {\n\tconst {\n\t\tvalue,\n\t\tpatch,\n\t\taddReference,\n\t\tavailableTools,\n\t\tavailableSubAgents,\n\t\tapplicationType,\n\t\tmentionResetKey,\n\t\tregisterMentionField,\n\t\tnotifyMentionFocus,\n\t\tonCreateSubAgent,\n\t\trequestCreateSubAgent,\n\t\trequestToolAction,\n\t\tconfigToolTemplates,\n\t\tintegrationStatus,\n\t\tonConnectIntegration,\n\t\tvariablesData,\n\t} = useAgentBuilderContext();\n\n\t// Catalog tools + sub-agents, PLUS the inline custom tools (Rest API / email /\n\t// Slack) so their `{{tool:<id>}}` tokens rehydrate as chips on remount — they\n\t// live on the value, not in `availableTools`.\n\tconst mentionItems = useMemo(\n\t\t() => [\n\t\t\t...buildAgentMentionItems(\n\t\t\t\tavailableTools,\n\t\t\t\tavailableSubAgents,\n\t\t\t\tappTypeLabel(applicationType),\n\t\t\t),\n\t\t\t...buildCustomToolMentionItems(value.configTools, value.restApiTools),\n\t\t],\n\t\t[\n\t\t\tavailableTools,\n\t\t\tavailableSubAgents,\n\t\t\tapplicationType,\n\t\t\tvalue.configTools,\n\t\t\tvalue.restApiTools,\n\t\t],\n\t);\n\n\t// Built-in tool actions (Rest API / email / Slack) shown in the `@` picker's\n\t// Tools view — picking one opens its drawer (Step 3) instead of inserting text.\n\t// The shared email / Slack forms are backend-driven: each is offered only when\n\t// its template was provided.\n\tconst toolActions = useMemo<ToolAction[]>(\n\t\t() =>\n\t\t\tbuildToolActions(\n\t\t\t\tconfigToolTemplates,\n\t\t\t\trequestToolAction,\n\t\t\t\tintegrationStatus,\n\t\t\t\tonConnectIntegration,\n\t\t\t),\n\t\t[\n\t\t\trequestToolAction,\n\t\t\tconfigToolTemplates,\n\t\t\tintegrationStatus,\n\t\t\tonConnectIntegration,\n\t\t],\n\t);\n\n\tconst registerInsert = useCallback(\n\t\t(fn: Parameters<typeof registerMentionField>[1]) =>\n\t\t\tregisterMentionField(fieldKey, fn),\n\t\t[registerMentionField, fieldKey],\n\t);\n\n\t// Route through the context's ref-backed `addReference`: BikEditor captures\n\t// this handler at mount, so reading `value.tools` here would keep only the last\n\t// pick. `addReference` always appends against the latest lists.\n\tconst onMentionSelect = useCallback(\n\t\t(kind: 'tool' | 'subagent', id: string) => addReference(kind, id),\n\t\t[addReference],\n\t);\n\n\treturn (\n\t\t<MentionEditor\n\t\t\tlabel={label}\n\t\t\tvalue={(value[fieldKey] as string | undefined) ?? ''}\n\t\t\tonChange={(text) => patch({ [fieldKey]: text } as Partial<AgentValue>)}\n\t\t\tmaxLength={maxLength}\n\t\t\tplaceholder={placeholder}\n\t\t\tminHeight={minHeight}\n\t\t\tresetKey={`${value.id}:${fieldKey}:${mentionResetKey}`}\n\t\t\tmentionItems={mentionItems}\n\t\t\ttools={availableTools}\n\t\t\tonMentionSelect={onMentionSelect}\n\t\t\tonFocus={() => notifyMentionFocus(fieldKey)}\n\t\t\tregisterInsert={registerInsert}\n\t\t\tonCreateSubAgent={onCreateSubAgent ? requestCreateSubAgent : undefined}\n\t\t\ttoolActions={toolActions}\n\t\t\tintegrationStatus={integrationStatus}\n\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\tvariablesData={variablesData}\n\t\t\tdata-test={rest['data-test']}\n\t\t/>\n\t);\n};\n"],"names":["MentionField","fieldKey","label","placeholder","maxLength","minHeight","rest","value","patch","addReference","availableTools","availableSubAgents","applicationType","mentionResetKey","registerMentionField","notifyMentionFocus","onCreateSubAgent","requestCreateSubAgent","requestToolAction","configToolTemplates","integrationStatus","onConnectIntegration","variablesData","useAgentBuilderContext","mentionItems","useMemo","buildAgentMentionItems","appTypeLabel","buildCustomToolMentionItems","toolActions","buildToolActions","registerInsert","useCallback","fn","onMentionSelect","kind","id","jsx","MentionEditor","text"],"mappings":"0SA+BaA,EAA4C,CAAC,CACzD,SAAAC,EACA,MAAAC,EACA,YAAAC,EACA,UAAAC,EACA,UAAAC,EACA,GAAGC,CACJ,IAAM,CACL,KAAM,CACL,MAAAC,EACA,MAAAC,EACA,aAAAC,EACA,eAAAC,EACA,mBAAAC,EACA,gBAAAC,EACA,gBAAAC,EACA,qBAAAC,EACA,mBAAAC,EACA,iBAAAC,EACA,sBAAAC,EACA,kBAAAC,EACA,oBAAAC,EACA,kBAAAC,EACA,qBAAAC,EACA,cAAAC,CAAA,EACGC,yBAAA,EAKEC,EAAeC,EAAAA,QACpB,IAAM,CACL,GAAGC,EAAAA,uBACFhB,EACAC,EACAgB,EAAAA,aAAaf,CAAe,CAAA,EAE7B,GAAGgB,8BAA4BrB,EAAM,YAAaA,EAAM,YAAY,CAAA,EAErE,CACCG,EACAC,EACAC,EACAL,EAAM,YACNA,EAAM,YAAA,CACP,EAOKsB,EAAcJ,EAAAA,QACnB,IACCK,EAAAA,iBACCX,EACAD,EACAE,EACAC,CAAA,EAEF,CACCH,EACAC,EACAC,EACAC,CAAA,CACD,EAGKU,EAAiBC,EAAAA,YACrBC,GACAnB,EAAqBb,EAAUgC,CAAE,EAClC,CAACnB,EAAsBb,CAAQ,CAAA,EAM1BiC,EAAkBF,EAAAA,YACvB,CAACG,EAA2BC,IAAe3B,EAAa0B,EAAMC,CAAE,EAChE,CAAC3B,CAAY,CAAA,EAGd,OACC4B,EAAAA,IAACC,EAAAA,cAAA,CACA,MAAApC,EACA,MAAQK,EAAMN,CAAQ,GAA4B,GAClD,SAAWsC,GAAS/B,EAAM,CAAE,CAACP,CAAQ,EAAGsC,EAA6B,EACrE,UAAAnC,EACA,YAAAD,EACA,UAAAE,EACA,SAAU,GAAGE,EAAM,EAAE,IAAIN,CAAQ,IAAIY,CAAe,GACpD,aAAAW,EACA,MAAOd,EACP,gBAAAwB,EACA,QAAS,IAAMnB,EAAmBd,CAAQ,EAC1C,eAAA8B,EACA,iBAAkBf,EAAmBC,EAAwB,OAAA,YAC7DY,EACA,kBAAAT,EACA,qBAAAC,EACA,cAAAC,
|
|
1
|
+
{"version":3,"file":"MentionField.js","sources":["../../../../../src/components/agent-builder/components/MentionField.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from 'react';\nimport { AgentValue } from '../AgentBuilder.model';\nimport { ToolAction } from '../constants/tools';\nimport {\n\tMentionFieldKey,\n\tuseAgentBuilderContext,\n} from '../context/AgentBuilderContext';\nimport {\n\tappTypeLabel,\n\tbuildAgentMentionItems,\n\tbuildCustomToolMentionItems,\n} from '../utils/mentionSerialization';\nimport { buildToolActions } from '../utils/toolActions';\nimport { MentionEditor } from './MentionEditor';\n\ninterface MentionFieldProps {\n\t/** Which AgentValue field this editor reads / writes. */\n\tfieldKey: MentionFieldKey;\n\tlabel: string;\n\tplaceholder?: string;\n\tmaxLength: number;\n\tminHeight?: string;\n\t'data-test'?: string;\n}\n\n/**\n * Context-bound {@link MentionEditor} for the builder's Step-3 Instructions /\n * Guardrails. Both `@` tools and sub-agents are offered; the field registers its\n * insert + focus with the context so side-panel adds drop a chip into whichever\n * field was last focused, and remounts on `mentionResetKey`.\n */\nexport const MentionField: React.FC<MentionFieldProps> = ({\n\tfieldKey,\n\tlabel,\n\tplaceholder,\n\tmaxLength,\n\tminHeight,\n\t...rest\n}) => {\n\tconst {\n\t\tvalue,\n\t\tpatch,\n\t\taddReference,\n\t\tavailableTools,\n\t\tavailableSubAgents,\n\t\tapplicationType,\n\t\tmentionResetKey,\n\t\tregisterMentionField,\n\t\tnotifyMentionFocus,\n\t\tonCreateSubAgent,\n\t\trequestCreateSubAgent,\n\t\trequestToolAction,\n\t\tconfigToolTemplates,\n\t\tintegrationStatus,\n\t\tonConnectIntegration,\n\t\tvariablesData,\n\t} = useAgentBuilderContext();\n\n\t// Catalog tools + sub-agents, PLUS the inline custom tools (Rest API / email /\n\t// Slack) so their `{{tool:<id>}}` tokens rehydrate as chips on remount — they\n\t// live on the value, not in `availableTools`.\n\tconst mentionItems = useMemo(\n\t\t() => [\n\t\t\t...buildAgentMentionItems(\n\t\t\t\tavailableTools,\n\t\t\t\tavailableSubAgents,\n\t\t\t\tappTypeLabel(applicationType),\n\t\t\t),\n\t\t\t...buildCustomToolMentionItems(value.configTools, value.restApiTools),\n\t\t],\n\t\t[\n\t\t\tavailableTools,\n\t\t\tavailableSubAgents,\n\t\t\tapplicationType,\n\t\t\tvalue.configTools,\n\t\t\tvalue.restApiTools,\n\t\t],\n\t);\n\n\t// Built-in tool actions (Rest API / email / Slack) shown in the `@` picker's\n\t// Tools view — picking one opens its drawer (Step 3) instead of inserting text.\n\t// The shared email / Slack forms are backend-driven: each is offered only when\n\t// its template was provided.\n\tconst toolActions = useMemo<ToolAction[]>(\n\t\t() =>\n\t\t\tbuildToolActions(\n\t\t\t\tconfigToolTemplates,\n\t\t\t\trequestToolAction,\n\t\t\t\tintegrationStatus,\n\t\t\t\tonConnectIntegration,\n\t\t\t),\n\t\t[\n\t\t\trequestToolAction,\n\t\t\tconfigToolTemplates,\n\t\t\tintegrationStatus,\n\t\t\tonConnectIntegration,\n\t\t],\n\t);\n\n\tconst registerInsert = useCallback(\n\t\t(fn: Parameters<typeof registerMentionField>[1]) =>\n\t\t\tregisterMentionField(fieldKey, fn),\n\t\t[registerMentionField, fieldKey],\n\t);\n\n\t// Route through the context's ref-backed `addReference`: BikEditor captures\n\t// this handler at mount, so reading `value.tools` here would keep only the last\n\t// pick. `addReference` always appends against the latest lists.\n\tconst onMentionSelect = useCallback(\n\t\t(kind: 'tool' | 'subagent', id: string) => addReference(kind, id),\n\t\t[addReference],\n\t);\n\n\treturn (\n\t\t<MentionEditor\n\t\t\tlabel={label}\n\t\t\tvalue={(value[fieldKey] as string | undefined) ?? ''}\n\t\t\tonChange={(text) => patch({ [fieldKey]: text } as Partial<AgentValue>)}\n\t\t\tmaxLength={maxLength}\n\t\t\tplaceholder={placeholder}\n\t\t\tminHeight={minHeight}\n\t\t\tresetKey={`${value.id}:${fieldKey}:${mentionResetKey}`}\n\t\t\tmentionItems={mentionItems}\n\t\t\ttools={availableTools}\n\t\t\tonMentionSelect={onMentionSelect}\n\t\t\tonFocus={() => notifyMentionFocus(fieldKey)}\n\t\t\tregisterInsert={registerInsert}\n\t\t\tonCreateSubAgent={onCreateSubAgent ? requestCreateSubAgent : undefined}\n\t\t\ttoolActions={toolActions}\n\t\t\tintegrationStatus={integrationStatus}\n\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\tvariablesData={variablesData}\n\t\t\t// Step-3 fields get the floating \"+ Add data\" pill (same as typing @).\n\t\t\taddDataButton\n\t\t\tdata-test={rest['data-test']}\n\t\t/>\n\t);\n};\n"],"names":["MentionField","fieldKey","label","placeholder","maxLength","minHeight","rest","value","patch","addReference","availableTools","availableSubAgents","applicationType","mentionResetKey","registerMentionField","notifyMentionFocus","onCreateSubAgent","requestCreateSubAgent","requestToolAction","configToolTemplates","integrationStatus","onConnectIntegration","variablesData","useAgentBuilderContext","mentionItems","useMemo","buildAgentMentionItems","appTypeLabel","buildCustomToolMentionItems","toolActions","buildToolActions","registerInsert","useCallback","fn","onMentionSelect","kind","id","jsx","MentionEditor","text"],"mappings":"0SA+BaA,EAA4C,CAAC,CACzD,SAAAC,EACA,MAAAC,EACA,YAAAC,EACA,UAAAC,EACA,UAAAC,EACA,GAAGC,CACJ,IAAM,CACL,KAAM,CACL,MAAAC,EACA,MAAAC,EACA,aAAAC,EACA,eAAAC,EACA,mBAAAC,EACA,gBAAAC,EACA,gBAAAC,EACA,qBAAAC,EACA,mBAAAC,EACA,iBAAAC,EACA,sBAAAC,EACA,kBAAAC,EACA,oBAAAC,EACA,kBAAAC,EACA,qBAAAC,EACA,cAAAC,CAAA,EACGC,yBAAA,EAKEC,EAAeC,EAAAA,QACpB,IAAM,CACL,GAAGC,EAAAA,uBACFhB,EACAC,EACAgB,EAAAA,aAAaf,CAAe,CAAA,EAE7B,GAAGgB,8BAA4BrB,EAAM,YAAaA,EAAM,YAAY,CAAA,EAErE,CACCG,EACAC,EACAC,EACAL,EAAM,YACNA,EAAM,YAAA,CACP,EAOKsB,EAAcJ,EAAAA,QACnB,IACCK,EAAAA,iBACCX,EACAD,EACAE,EACAC,CAAA,EAEF,CACCH,EACAC,EACAC,EACAC,CAAA,CACD,EAGKU,EAAiBC,EAAAA,YACrBC,GACAnB,EAAqBb,EAAUgC,CAAE,EAClC,CAACnB,EAAsBb,CAAQ,CAAA,EAM1BiC,EAAkBF,EAAAA,YACvB,CAACG,EAA2BC,IAAe3B,EAAa0B,EAAMC,CAAE,EAChE,CAAC3B,CAAY,CAAA,EAGd,OACC4B,EAAAA,IAACC,EAAAA,cAAA,CACA,MAAApC,EACA,MAAQK,EAAMN,CAAQ,GAA4B,GAClD,SAAWsC,GAAS/B,EAAM,CAAE,CAACP,CAAQ,EAAGsC,EAA6B,EACrE,UAAAnC,EACA,YAAAD,EACA,UAAAE,EACA,SAAU,GAAGE,EAAM,EAAE,IAAIN,CAAQ,IAAIY,CAAe,GACpD,aAAAW,EACA,MAAOd,EACP,gBAAAwB,EACA,QAAS,IAAMnB,EAAmBd,CAAQ,EAC1C,eAAA8B,EACA,iBAAkBf,EAAmBC,EAAwB,OAAA,YAC7DY,EACA,kBAAAT,EACA,qBAAAC,EACA,cAAAC,EAEA,cAAa,GACb,YAAWhB,EAAK,WAAW,CAAA,CAAA,CAG9B"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),Q=require("../../../assets/icons/delete.svg.js"),K=require("../../../assets/icons/plus.svg.js"),o=require("react"),X=require("styled-components"),p=require("../../TypographyStyle.js"),i=require("../../../constants/Theme.js"),c=require("../AgentBuilder.styled.js"),Z=require("../constants/charLimits.js"),R=require("./DrawerHeaderText.js"),ee=require("./ToolInstructionsField.js"),h=require("./VariableTriggerArea.js"),te=require("../../side-modal/SideModal.js"),m=require("../../input/Input.js"),re=require("../../dropdown/Dropdown.js"),ne=require("../../dropdown/utils.js"),se=require("../../button/Button.js"),_=require("../../../editor/BikEditor.js"),oe=s=>s&&typeof s=="object"&&"default"in s?s:{default:s},O=oe(X),ae=["GET","POST","PUT","PATCH","DELETE"],le=ae.map(s=>({label:s,value:s})),C=(s,x)=>(x.textBefore.match(new RegExp('(?<!\\\\)"',"g"))?.length??0)%2===1?s:`"${s}"`,ie=({onClose:s,onSave:x,initial:a,onImprove:$,charLimits:q=Z.AGENT_CHAR_LIMITS,zIndex:M,existingNames:F=[],variablesData:d})=>{const[T,N]=o.useState(a?.name??""),B=o.useRef(null),I=o.useRef(null),[k,V]=o.useState(a?.instructions??""),[y,E]=o.useState(a?.url??"https://"),[g,z]=o.useState(a?.method??"POST"),[L,f]=o.useState(a?.headers??[{key:"",value:""}]),[A,J]=o.useState(a?.requestBody??""),[H,G]=o.useState(a?.responseSample??""),[w,D]=o.useState(!1),S=(t,r)=>f(n=>n.map((l,u)=>u===t?{...l,...r}:l)),U=()=>f(t=>[...t,{key:"",value:""}]),W=t=>f(r=>r.filter((n,l)=>l!==t)),j=T.trim(),v=j.length>0&&F.some(t=>t.trim().toLowerCase()===j.toLowerCase()),P=j.length>0&&y.trim().length>0&&!v,Y=async()=>{if(!P||w)return;const t={id:a?.id??`restapi_${Date.now().toString(36)}`,name:T.trim(),instructions:k,url:y.trim(),method:g,headers:L.filter(n=>n.key.trim()||n.value.trim()),requestBody:A,responseSample:H},r=x(t);if(r&&typeof r.then=="function"){D(!0);try{await r}finally{D(!1)}}};return e.jsxs(te.SideModal,{header:"Rest API",closeOnEscapeKey:!1,zIndex:M,headerCustomComponent:e.jsx(R.DrawerHeaderText,{title:"Rest API",subtitle:"Connect to any API endpoint. Define the request and a sample response for the agent to reference."}),width:"431px",headerStyle:R.DRAWER_HEADER_STYLE,bodyStyle:R.DRAWER_BODY_STYLE,onClose:s,saveButtonProps:{"data-test":"restapi-save",buttonText:"Save",buttonType:"primary",size:"small",disabled:!P,isLoading:w,onClick:Y},cancelButtonProps:{"data-test":"restapi-cancel",buttonText:"Cancel",buttonType:"tertiaryGray",size:"small",onClick:s},children:[e.jsx(m.Input,{"data-test":"restapi-name",variant:"small",labelText:"Name",labelTextBold:!0,placeholder:"Enter action name",value:T,maxCharLimit:q.name,state:v?"invalid":void 0,errorMessage:v?"A tool with this name already exists":void 0,onChangeText:N}),e.jsx(ee.ToolInstructionsField,{"data-test":"restapi-instructions",label:"Instructions",value:k,onChange:V,maxLength:q.instructions,placeholder:"Describe how should the LLM generate the rest API",onImprove:$,variablesData:d}),e.jsx(c.FieldBlock,{children:e.jsx(h.VariableTriggerArea,{addDataButton:!0,variablesData:d,onInsert:(t,r)=>E(n=>{const l=r??n.length;return`${n.slice(0,l)}${t}${n.slice(l)}`}),children:e.jsx(m.Input,{"data-test":"restapi-url",variant:"small",labelText:"Request URL",labelTextBold:!0,placeholder:"https://",type:"url",value:y,onChangeText:E})})}),e.jsxs(c.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:i.COLORS.content.primary,children:"HTTP method"}),e.jsx(re.Dropdown,{"data-test":"restapi-method",size:"small",width:"100%",dropdownWidth:"399px",options:le,defaultOptions:[{label:g,value:g}],onSelect:t=>{const r=ne.unwrapDropdownValue(t);r&&z(r)}})]}),e.jsxs(c.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:i.COLORS.content.primary,children:"Headers"}),L.map((t,r)=>e.jsxs(de,{"data-test":`restapi-header-${r}`,children:[e.jsx(m.Input,{variant:"small",hideInputHeader:!0,placeholder:"Enter name",value:t.key,onChangeText:n=>S(r,{key:n})}),e.jsx(h.VariableTriggerArea,{addDataButton:!0,variablesData:d,onInsert:(n,l)=>{const u=l??t.value.length;S(r,{value:`${t.value.slice(0,u)}${n}${t.value.slice(u)}`})},children:e.jsx(m.Input,{variant:"small",hideInputHeader:!0,placeholder:"Enter value",value:t.value,onChangeText:n=>S(r,{value:n})})}),e.jsx(ue,{type:"button","aria-label":"Remove header","data-test":`restapi-header-remove-${r}`,onClick:()=>W(r),children:e.jsx(Q.default,{width:16,height:16,color:i.COLORS.content.secondary})})]},r)),e.jsx(ce,{children:e.jsx(se.Button,{"data-test":"restapi-add-header",buttonType:"dashRegular",size:"small",LeadingIcon:K.default,buttonText:"Add header",onClick:U})})]}),e.jsxs(c.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:i.COLORS.content.primary,children:"Request "}),e.jsx(h.VariableTriggerArea,{addDataButton:!0,variablesData:d,transformToken:C,onInsert:t=>B.current?.insertInlineContent(t),children:e.jsx(_.BikEditor,{ref:B,features:{jsonMode:!0},initialContent:A,style:b,placeholder:"Type or paste JSON here",onChange:t=>J(t.text),minHeight:"120px",maxHeight:"240px"})})]}),e.jsxs(c.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:i.COLORS.content.primary,children:"Response "}),e.jsx(h.VariableTriggerArea,{addDataButton:!0,variablesData:d,transformToken:C,onInsert:t=>I.current?.insertInlineContent(t),children:e.jsx(_.BikEditor,{ref:I,features:{jsonMode:!0},style:b,initialContent:H,placeholder:"Type or paste JSON here",onChange:t=>G(t.text),minHeight:"120px",maxHeight:"240px"})})]})]})},de=O.default.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: center;
|
|
4
4
|
gap: 8px;
|
|
5
|
-
`,
|
|
5
|
+
`,ce=O.default.div`
|
|
6
6
|
display: flex;
|
|
7
|
-
`,
|
|
7
|
+
`,ue=O.default.button`
|
|
8
8
|
display: inline-flex;
|
|
9
9
|
align-items: center;
|
|
10
10
|
justify-content: center;
|
|
@@ -19,5 +19,5 @@
|
|
|
19
19
|
&:hover {
|
|
20
20
|
border-color: ${i.COLORS.content.secondary};
|
|
21
21
|
}
|
|
22
|
-
`,
|
|
22
|
+
`,b={borderRadius:"4px",overflow:"hidden"};exports.JsonFieldBox=b;exports.RestApiToolPanel=ie;exports.jsonQuoteToken=C;
|
|
23
23
|
//# sourceMappingURL=RestApiToolPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RestApiToolPanel.js","sources":["../../../../../src/components/agent-builder/components/RestApiToolPanel.tsx"],"sourcesContent":["import DeleteIcon from '@src/assets/icons/delete.svg';\nimport PlusIcon from '@src/assets/icons/plus.svg';\nimport { BikEditor, BikEditorRef } from '@src/editor';\nimport React, { useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Button } from '@src/components/button';\nimport { Dropdown, unwrapDropdownValue } from '@src/components/dropdown';\nimport { SingleOption } from '@src/components/dropdown/type';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tRestApiHeader,\n\tRestApiMethod,\n\tRestApiToolConfig,\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\ninterface RestApiToolPanelProps {\n\tonClose: () => void;\n\t/** Persist the config. A pending promise shows the Save loader. */\n\tonSave: (config: RestApiToolConfig) => void | Promise<void>;\n\t/** Seed values when editing an existing tool. */\n\tinitial?: RestApiToolConfig;\n\t/** Optional \"Improve with AI\" for the instructions field. Omit to hide it. */\n\tonImprove?: (text: string) => Promise<string>;\n\tcharLimits?: AgentCharLimits;\n\t/** SideModal stacking order — raise it when opened over another drawer. */\n\tzIndex?: number;\n\t/** Names of the OTHER tools — a new tool can't reuse one of these. */\n\texistingNames?: string[];\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` opens the\n\t * variable picker directly in Instructions / Request URL / header values /\n\t * Request / Response. Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\nconst METHODS: RestApiMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\nconst METHOD_OPTIONS: SingleOption[] = METHODS.map((m) => ({\n\tlabel: m,\n\tvalue: m,\n}));\n\n/**\n * Right-side drawer to configure a \"Rest API\" tool: the endpoint the agent can\n * call, plus a JSON request-body template and a sample response. Mount it fresh\n * per open (key it) so `initial` seeds the state. Built on the shared `SideModal`\n * shell and the BikEditor JSON body mode for the Request / Response editors.\n */\nexport const RestApiToolPanel: React.FC<RestApiToolPanelProps> = ({\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tzIndex,\n\texistingNames = [],\n\tvariablesData,\n}) => {\n\tconst [name, setName] = useState(initial?.name ?? '');\n\t// `@`-picked variables insert into the JSON editors at their own cursor.\n\tconst requestEditorRef = useRef<BikEditorRef>(null);\n\tconst responseEditorRef = useRef<BikEditorRef>(null);\n\tconst [instructions, setInstructions] = useState(initial?.instructions ?? '');\n\t// New tools start with the scheme pre-filled so the user only types the host.\n\tconst [url, setUrl] = useState(initial?.url ?? 'https://');\n\tconst [method, setMethod] = useState<RestApiMethod>(\n\t\tinitial?.method ?? 'POST',\n\t);\n\tconst [headers, setHeaders] = useState<RestApiHeader[]>(\n\t\tinitial?.headers ?? [{ key: '', value: '' }],\n\t);\n\tconst [requestBody, setRequestBody] = useState(initial?.requestBody ?? '');\n\tconst [responseSample, setResponseSample] = useState(\n\t\tinitial?.responseSample ?? '',\n\t);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst patchHeader = (i: number, patch: Partial<RestApiHeader>) =>\n\t\tsetHeaders((prev) =>\n\t\t\tprev.map((h, idx) => (idx === i ? { ...h, ...patch } : h)),\n\t\t);\n\tconst addHeader = () =>\n\t\tsetHeaders((prev) => [...prev, { key: '', value: '' }]);\n\tconst removeHeader = (i: number) =>\n\t\tsetHeaders((prev) => prev.filter((_, idx) => idx !== i));\n\n\tconst nameTrimmed = name.trim();\n\t// Case-insensitive: two tools can't share a name (the LLM references them by it).\n\tconst isDuplicateName =\n\t\tnameTrimmed.length > 0 &&\n\t\texistingNames.some(\n\t\t\t(n) => n.trim().toLowerCase() === nameTrimmed.toLowerCase(),\n\t\t);\n\tconst canSave =\n\t\tnameTrimmed.length > 0 && url.trim().length > 0 && !isDuplicateName;\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst config: RestApiToolConfig = {\n\t\t\tid: initial?.id ?? `restapi_${Date.now().toString(36)}`,\n\t\t\tname: name.trim(),\n\t\t\tinstructions,\n\t\t\turl: url.trim(),\n\t\t\tmethod,\n\t\t\t// Drop fully-empty header rows.\n\t\t\theaders: headers.filter((h) => h.key.trim() || h.value.trim()),\n\t\t\trequestBody,\n\t\t\tresponseSample,\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\treturn (\n\t\t<SideModal\n\t\t\theader=\"Rest API\"\n\t\t\tcloseOnEscapeKey={false}\n\t\t\tzIndex={zIndex}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText\n\t\t\t\t\ttitle=\"Rest API\"\n\t\t\t\t\tsubtitle=\"Connect to any API endpoint. Define the request and a sample response for the agent to reference.\"\n\t\t\t\t/>\n\t\t\t}\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': 'restapi-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': 'restapi-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<Input\n\t\t\t\tdata-test=\"restapi-name\"\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText=\"Name\"\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder=\"Enter action name\"\n\t\t\t\tvalue={name}\n\t\t\t\tmaxCharLimit={charLimits.name}\n\t\t\t\tstate={isDuplicateName ? 'invalid' : undefined}\n\t\t\t\terrorMessage={\n\t\t\t\t\tisDuplicateName ? 'A tool with this name already exists' : undefined\n\t\t\t\t}\n\t\t\t\tonChangeText={setName}\n\t\t\t/>\n\n\t\t\t<ToolInstructionsField\n\t\t\t\tdata-test=\"restapi-instructions\"\n\t\t\t\tlabel=\"Instructions\"\n\t\t\t\tvalue={instructions}\n\t\t\t\tonChange={setInstructions}\n\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\tplaceholder=\"Describe how should the LLM generate the rest API\"\n\t\t\t\tonImprove={onImprove}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t/>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<VariableTriggerArea\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\tonInsert={(token, caret) =>\n\t\t\t\t\t\tsetUrl((u) => {\n\t\t\t\t\t\t\tconst at = caret ?? u.length;\n\t\t\t\t\t\t\treturn `${u.slice(0, at)}${token}${u.slice(at)}`;\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<Input\n\t\t\t\t\t\tdata-test=\"restapi-url\"\n\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\tlabelText=\"Request URL\"\n\t\t\t\t\t\tlabelTextBold\n\t\t\t\t\t\tplaceholder=\"https://\"\n\t\t\t\t\t\ttype=\"url\"\n\t\t\t\t\t\tvalue={url}\n\t\t\t\t\t\tonChangeText={setUrl}\n\t\t\t\t\t/>\n\t\t\t\t</VariableTriggerArea>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>HTTP method</TitleSmall>\n\t\t\t\t<Dropdown\n\t\t\t\t\tdata-test=\"restapi-method\"\n\t\t\t\t\tsize=\"small\"\n\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\tdropdownWidth=\"399px\"\n\t\t\t\t\toptions={METHOD_OPTIONS}\n\t\t\t\t\tdefaultOptions={[{ label: method, value: method }]}\n\t\t\t\t\tonSelect={(opt) => {\n\t\t\t\t\t\tconst v = unwrapDropdownValue(opt);\n\t\t\t\t\t\tif (v) {\n\t\t\t\t\t\t\tsetMethod(v as RestApiMethod);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>Headers</TitleSmall>\n\t\t\t\t{headers.map((h, i) => (\n\t\t\t\t\t// eslint-disable-next-line react/no-array-index-key\n\t\t\t\t\t<HeaderRow key={i} data-test={`restapi-header-${i}`}>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\t\thideInputHeader\n\t\t\t\t\t\t\tplaceholder=\"Enter name\"\n\t\t\t\t\t\t\tvalue={h.key}\n\t\t\t\t\t\t\tonChangeText={(v) => patchHeader(i, { key: v })}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<VariableTriggerArea\n\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\tonInsert={(token, caret) => {\n\t\t\t\t\t\t\t\tconst at = caret ?? h.value.length;\n\t\t\t\t\t\t\t\tpatchHeader(i, {\n\t\t\t\t\t\t\t\t\tvalue: `${h.value.slice(0, at)}${token}${h.value.slice(at)}`,\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<Input\n\t\t\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\t\t\thideInputHeader\n\t\t\t\t\t\t\t\tplaceholder=\"Enter value\"\n\t\t\t\t\t\t\t\tvalue={h.value}\n\t\t\t\t\t\t\t\tonChangeText={(v) => patchHeader(i, { value: v })}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</VariableTriggerArea>\n\t\t\t\t\t\t<IconBtn\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label=\"Remove header\"\n\t\t\t\t\t\t\tdata-test={`restapi-header-remove-${i}`}\n\t\t\t\t\t\t\tonClick={() => removeHeader(i)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<DeleteIcon\n\t\t\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\t\t\theight={16}\n\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</IconBtn>\n\t\t\t\t\t</HeaderRow>\n\t\t\t\t))}\n\t\t\t\t<AddHeaderRow>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tdata-test=\"restapi-add-header\"\n\t\t\t\t\t\tbuttonType=\"dashRegular\"\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\tLeadingIcon={PlusIcon}\n\t\t\t\t\t\tbuttonText=\"Add header\"\n\t\t\t\t\t\tonClick={addHeader}\n\t\t\t\t\t/>\n\t\t\t\t</AddHeaderRow>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>Request </TitleSmall>\n\t\t\t\t<VariableTriggerArea\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\tonInsert={(token) =>\n\t\t\t\t\t\trequestEditorRef.current?.insertInlineContent(token)\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<BikEditor\n\t\t\t\t\t\tref={requestEditorRef}\n\t\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\t\tinitialContent={requestBody}\n\t\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\t\tonChange={(c) => setRequestBody(c.text)}\n\t\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\t\tmaxHeight=\"240px\"\n\t\t\t\t\t/>\n\t\t\t\t</VariableTriggerArea>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>Response </TitleSmall>\n\t\t\t\t<VariableTriggerArea\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\tonInsert={(token) =>\n\t\t\t\t\t\tresponseEditorRef.current?.insertInlineContent(token)\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<BikEditor\n\t\t\t\t\t\tref={responseEditorRef}\n\t\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\t\tinitialContent={responseSample}\n\t\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\t\tonChange={(c) => setResponseSample(c.text)}\n\t\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\t\tmaxHeight=\"240px\"\n\t\t\t\t\t/>\n\t\t\t\t</VariableTriggerArea>\n\t\t\t</FieldBlock>\n\t\t</SideModal>\n\t);\n};\n\nconst HeaderRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n`;\n\nconst AddHeaderRow = styled.div`\n\tdisplay: flex;\n`;\n\nconst IconBtn = styled.button`\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex-shrink: 0;\n\twidth: 32px;\n\theight: 32px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tbackground: ${COLORS.surface.standard};\n\tcursor: pointer;\n\n\t&:hover {\n\t\tborder-color: ${COLORS.content.secondary};\n\t}\n`;\n\nexport const JsonFieldBox = {\n\tborderRadius: '4px',\n\toverflow: 'hidden',\n};\n"],"names":["METHODS","METHOD_OPTIONS","m","RestApiToolPanel","onClose","onSave","initial","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","existingNames","variablesData","name","setName","useState","requestEditorRef","useRef","responseEditorRef","instructions","setInstructions","url","setUrl","method","setMethod","headers","setHeaders","requestBody","setRequestBody","responseSample","setResponseSample","saving","setSaving","patchHeader","i","patch","prev","h","idx","addHeader","removeHeader","_","nameTrimmed","isDuplicateName","n","canSave","handleSave","config","result","jsxs","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","Input","ToolInstructionsField","FieldBlock","VariableTriggerArea","token","caret","u","at","TitleSmall","COLORS","Dropdown","opt","v","unwrapDropdownValue","HeaderRow","IconBtn","DeleteIcon","AddHeaderRow","Button","PlusIcon","BikEditor","JsonFieldBox","c","styled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RestApiToolPanel.js","sources":["../../../../../src/components/agent-builder/components/RestApiToolPanel.tsx"],"sourcesContent":["import DeleteIcon from '@src/assets/icons/delete.svg';\nimport PlusIcon from '@src/assets/icons/plus.svg';\nimport { BikEditor, BikEditorRef } from '@src/editor';\nimport React, { useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Button } from '@src/components/button';\nimport { Dropdown, unwrapDropdownValue } from '@src/components/dropdown';\nimport { SingleOption } from '@src/components/dropdown/type';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tRestApiHeader,\n\tRestApiMethod,\n\tRestApiToolConfig,\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\ninterface RestApiToolPanelProps {\n\tonClose: () => void;\n\t/** Persist the config. A pending promise shows the Save loader. */\n\tonSave: (config: RestApiToolConfig) => void | Promise<void>;\n\t/** Seed values when editing an existing tool. */\n\tinitial?: RestApiToolConfig;\n\t/** Optional \"Improve with AI\" for the instructions field. Omit to hide it. */\n\tonImprove?: (text: string) => Promise<string>;\n\tcharLimits?: AgentCharLimits;\n\t/** SideModal stacking order — raise it when opened over another drawer. */\n\tzIndex?: number;\n\t/** Names of the OTHER tools — a new tool can't reuse one of these. */\n\texistingNames?: string[];\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` opens the\n\t * variable picker directly in Instructions / Request URL / header values /\n\t * Request / Response. Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\nconst METHODS: RestApiMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\nconst METHOD_OPTIONS: SingleOption[] = METHODS.map((m) => ({\n\tlabel: m,\n\tvalue: m,\n}));\n\n/**\n * Keep the Request / Response bodies valid JSON: wrap the picked token in\n * quotes (`\"email\": \"{{variable:customer.email}}\"`) — unless the `@` was typed\n * inside a string literal already (odd number of unescaped `\"` before it, e.g.\n * `\"Bearer @`), where the bare token interpolates into the existing string.\n */\nexport const jsonQuoteToken = (\n\ttoken: string,\n\tctx: { textBefore: string },\n): string => {\n\tconst quotes = ctx.textBefore.match(/(?<!\\\\)\"/g)?.length ?? 0;\n\treturn quotes % 2 === 1 ? token : `\"${token}\"`;\n};\n\n/**\n * Right-side drawer to configure a \"Rest API\" tool: the endpoint the agent can\n * call, plus a JSON request-body template and a sample response. Mount it fresh\n * per open (key it) so `initial` seeds the state. Built on the shared `SideModal`\n * shell and the BikEditor JSON body mode for the Request / Response editors.\n */\nexport const RestApiToolPanel: React.FC<RestApiToolPanelProps> = ({\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tzIndex,\n\texistingNames = [],\n\tvariablesData,\n}) => {\n\tconst [name, setName] = useState(initial?.name ?? '');\n\t// `@`-picked variables insert into the JSON editors at their own cursor.\n\tconst requestEditorRef = useRef<BikEditorRef>(null);\n\tconst responseEditorRef = useRef<BikEditorRef>(null);\n\tconst [instructions, setInstructions] = useState(initial?.instructions ?? '');\n\t// New tools start with the scheme pre-filled so the user only types the host.\n\tconst [url, setUrl] = useState(initial?.url ?? 'https://');\n\tconst [method, setMethod] = useState<RestApiMethod>(\n\t\tinitial?.method ?? 'POST',\n\t);\n\tconst [headers, setHeaders] = useState<RestApiHeader[]>(\n\t\tinitial?.headers ?? [{ key: '', value: '' }],\n\t);\n\tconst [requestBody, setRequestBody] = useState(initial?.requestBody ?? '');\n\tconst [responseSample, setResponseSample] = useState(\n\t\tinitial?.responseSample ?? '',\n\t);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst patchHeader = (i: number, patch: Partial<RestApiHeader>) =>\n\t\tsetHeaders((prev) =>\n\t\t\tprev.map((h, idx) => (idx === i ? { ...h, ...patch } : h)),\n\t\t);\n\tconst addHeader = () =>\n\t\tsetHeaders((prev) => [...prev, { key: '', value: '' }]);\n\tconst removeHeader = (i: number) =>\n\t\tsetHeaders((prev) => prev.filter((_, idx) => idx !== i));\n\n\tconst nameTrimmed = name.trim();\n\t// Case-insensitive: two tools can't share a name (the LLM references them by it).\n\tconst isDuplicateName =\n\t\tnameTrimmed.length > 0 &&\n\t\texistingNames.some(\n\t\t\t(n) => n.trim().toLowerCase() === nameTrimmed.toLowerCase(),\n\t\t);\n\tconst canSave =\n\t\tnameTrimmed.length > 0 && url.trim().length > 0 && !isDuplicateName;\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst config: RestApiToolConfig = {\n\t\t\tid: initial?.id ?? `restapi_${Date.now().toString(36)}`,\n\t\t\tname: name.trim(),\n\t\t\tinstructions,\n\t\t\turl: url.trim(),\n\t\t\tmethod,\n\t\t\t// Drop fully-empty header rows.\n\t\t\theaders: headers.filter((h) => h.key.trim() || h.value.trim()),\n\t\t\trequestBody,\n\t\t\tresponseSample,\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\treturn (\n\t\t<SideModal\n\t\t\theader=\"Rest API\"\n\t\t\tcloseOnEscapeKey={false}\n\t\t\tzIndex={zIndex}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText\n\t\t\t\t\ttitle=\"Rest API\"\n\t\t\t\t\tsubtitle=\"Connect to any API endpoint. Define the request and a sample response for the agent to reference.\"\n\t\t\t\t/>\n\t\t\t}\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': 'restapi-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': 'restapi-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<Input\n\t\t\t\tdata-test=\"restapi-name\"\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText=\"Name\"\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder=\"Enter action name\"\n\t\t\t\tvalue={name}\n\t\t\t\tmaxCharLimit={charLimits.name}\n\t\t\t\tstate={isDuplicateName ? 'invalid' : undefined}\n\t\t\t\terrorMessage={\n\t\t\t\t\tisDuplicateName ? 'A tool with this name already exists' : undefined\n\t\t\t\t}\n\t\t\t\tonChangeText={setName}\n\t\t\t/>\n\n\t\t\t<ToolInstructionsField\n\t\t\t\tdata-test=\"restapi-instructions\"\n\t\t\t\tlabel=\"Instructions\"\n\t\t\t\tvalue={instructions}\n\t\t\t\tonChange={setInstructions}\n\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\tplaceholder=\"Describe how should the LLM generate the rest API\"\n\t\t\t\tonImprove={onImprove}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t/>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<VariableTriggerArea\n\t\t\t\t\taddDataButton\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\tonInsert={(token, caret) =>\n\t\t\t\t\t\tsetUrl((u) => {\n\t\t\t\t\t\t\tconst at = caret ?? u.length;\n\t\t\t\t\t\t\treturn `${u.slice(0, at)}${token}${u.slice(at)}`;\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<Input\n\t\t\t\t\t\tdata-test=\"restapi-url\"\n\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\tlabelText=\"Request URL\"\n\t\t\t\t\t\tlabelTextBold\n\t\t\t\t\t\tplaceholder=\"https://\"\n\t\t\t\t\t\ttype=\"url\"\n\t\t\t\t\t\tvalue={url}\n\t\t\t\t\t\tonChangeText={setUrl}\n\t\t\t\t\t/>\n\t\t\t\t</VariableTriggerArea>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>HTTP method</TitleSmall>\n\t\t\t\t<Dropdown\n\t\t\t\t\tdata-test=\"restapi-method\"\n\t\t\t\t\tsize=\"small\"\n\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\tdropdownWidth=\"399px\"\n\t\t\t\t\toptions={METHOD_OPTIONS}\n\t\t\t\t\tdefaultOptions={[{ label: method, value: method }]}\n\t\t\t\t\tonSelect={(opt) => {\n\t\t\t\t\t\tconst v = unwrapDropdownValue(opt);\n\t\t\t\t\t\tif (v) {\n\t\t\t\t\t\t\tsetMethod(v as RestApiMethod);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>Headers</TitleSmall>\n\t\t\t\t{headers.map((h, i) => (\n\t\t\t\t\t// eslint-disable-next-line react/no-array-index-key\n\t\t\t\t\t<HeaderRow key={i} data-test={`restapi-header-${i}`}>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\t\thideInputHeader\n\t\t\t\t\t\t\tplaceholder=\"Enter name\"\n\t\t\t\t\t\t\tvalue={h.key}\n\t\t\t\t\t\t\tonChangeText={(v) => patchHeader(i, { key: v })}\n\t\t\t\t\t\t/>\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, caret) => {\n\t\t\t\t\t\t\t\tconst at = caret ?? h.value.length;\n\t\t\t\t\t\t\t\tpatchHeader(i, {\n\t\t\t\t\t\t\t\t\tvalue: `${h.value.slice(0, at)}${token}${h.value.slice(at)}`,\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<Input\n\t\t\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\t\t\thideInputHeader\n\t\t\t\t\t\t\t\tplaceholder=\"Enter value\"\n\t\t\t\t\t\t\t\tvalue={h.value}\n\t\t\t\t\t\t\t\tonChangeText={(v) => patchHeader(i, { value: v })}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</VariableTriggerArea>\n\t\t\t\t\t\t<IconBtn\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label=\"Remove header\"\n\t\t\t\t\t\t\tdata-test={`restapi-header-remove-${i}`}\n\t\t\t\t\t\t\tonClick={() => removeHeader(i)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<DeleteIcon\n\t\t\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\t\t\theight={16}\n\t\t\t\t\t\t\t\tcolor={COLORS.content.secondary}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</IconBtn>\n\t\t\t\t\t</HeaderRow>\n\t\t\t\t))}\n\t\t\t\t<AddHeaderRow>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tdata-test=\"restapi-add-header\"\n\t\t\t\t\t\tbuttonType=\"dashRegular\"\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\tLeadingIcon={PlusIcon}\n\t\t\t\t\t\tbuttonText=\"Add header\"\n\t\t\t\t\t\tonClick={addHeader}\n\t\t\t\t\t/>\n\t\t\t\t</AddHeaderRow>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>Request </TitleSmall>\n\t\t\t\t<VariableTriggerArea\n\t\t\t\t\taddDataButton\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\ttransformToken={jsonQuoteToken}\n\t\t\t\t\tonInsert={(token) =>\n\t\t\t\t\t\trequestEditorRef.current?.insertInlineContent(token)\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<BikEditor\n\t\t\t\t\t\tref={requestEditorRef}\n\t\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\t\tinitialContent={requestBody}\n\t\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\t\tonChange={(c) => setRequestBody(c.text)}\n\t\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\t\tmaxHeight=\"240px\"\n\t\t\t\t\t/>\n\t\t\t\t</VariableTriggerArea>\n\t\t\t</FieldBlock>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<TitleSmall color={COLORS.content.primary}>Response </TitleSmall>\n\t\t\t\t<VariableTriggerArea\n\t\t\t\t\taddDataButton\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\ttransformToken={jsonQuoteToken}\n\t\t\t\t\tonInsert={(token) =>\n\t\t\t\t\t\tresponseEditorRef.current?.insertInlineContent(token)\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<BikEditor\n\t\t\t\t\t\tref={responseEditorRef}\n\t\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\t\tinitialContent={responseSample}\n\t\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\t\tonChange={(c) => setResponseSample(c.text)}\n\t\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\t\tmaxHeight=\"240px\"\n\t\t\t\t\t/>\n\t\t\t\t</VariableTriggerArea>\n\t\t\t</FieldBlock>\n\t\t</SideModal>\n\t);\n};\n\nconst HeaderRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n`;\n\nconst AddHeaderRow = styled.div`\n\tdisplay: flex;\n`;\n\nconst IconBtn = styled.button`\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex-shrink: 0;\n\twidth: 32px;\n\theight: 32px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tbackground: ${COLORS.surface.standard};\n\tcursor: pointer;\n\n\t&:hover {\n\t\tborder-color: ${COLORS.content.secondary};\n\t}\n`;\n\nexport const JsonFieldBox = {\n\tborderRadius: '4px',\n\toverflow: 'hidden',\n};\n"],"names":["METHODS","METHOD_OPTIONS","m","jsonQuoteToken","token","ctx","RestApiToolPanel","onClose","onSave","initial","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","existingNames","variablesData","name","setName","useState","requestEditorRef","useRef","responseEditorRef","instructions","setInstructions","url","setUrl","method","setMethod","headers","setHeaders","requestBody","setRequestBody","responseSample","setResponseSample","saving","setSaving","patchHeader","i","patch","prev","h","idx","addHeader","removeHeader","_","nameTrimmed","isDuplicateName","n","canSave","handleSave","config","result","jsxs","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","Input","ToolInstructionsField","FieldBlock","VariableTriggerArea","caret","u","at","TitleSmall","COLORS","Dropdown","opt","v","unwrapDropdownValue","HeaderRow","IconBtn","DeleteIcon","AddHeaderRow","Button","PlusIcon","BikEditor","JsonFieldBox","c","styled"],"mappings":"o0BAkDMA,GAA2B,CAAC,MAAO,OAAQ,MAAO,QAAS,QAAQ,EACnEC,GAAiCD,GAAQ,IAAKE,IAAO,CAC1D,MAAOA,EACP,MAAOA,CACR,EAAE,EAQWC,EAAiB,CAC7BC,EACAC,KAEeA,EAAI,WAAW,MAAM,WAAA,aAAA,GAAW,IAAG,QAAU,GAC5C,IAAM,EAAID,EAAQ,IAAIA,CAAK,IAS/BE,GAAoD,CAAC,CACjE,QAAAC,EACA,OAAAC,EACA,QAAAC,EACA,UAAAC,EAAA,WACAC,EAAaC,EAAAA,kBACb,OAAAC,EACA,cAAAC,EAAgB,CAAA,EAChB,cAAAC,CACD,IAAM,CACL,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAST,GAAS,MAAQ,EAAE,EAE9CU,EAAmBC,EAAAA,OAAqB,IAAI,EAC5CC,EAAoBD,EAAAA,OAAqB,IAAI,EAC7C,CAACE,EAAcC,CAAe,EAAIL,EAAAA,SAAST,GAAS,cAAgB,EAAE,EAEtE,CAACe,EAAKC,CAAM,EAAIP,EAAAA,SAAST,GAAS,KAAO,UAAU,EACnD,CAACiB,EAAQC,CAAS,EAAIT,EAAAA,SAC3BT,GAAS,QAAU,MAAA,EAEd,CAACmB,EAASC,CAAU,EAAIX,EAAAA,SAC7BT,GAAS,SAAW,CAAC,CAAE,IAAK,GAAI,MAAO,GAAI,CAAA,EAEtC,CAACqB,EAAaC,CAAc,EAAIb,EAAAA,SAAST,GAAS,aAAe,EAAE,EACnE,CAACuB,EAAgBC,CAAiB,EAAIf,EAAAA,SAC3CT,GAAS,gBAAkB,EAAA,EAEtB,CAACyB,EAAQC,CAAS,EAAIjB,EAAAA,SAAS,EAAK,EAEpCkB,EAAc,CAACC,EAAWC,IAC/BT,EAAYU,GACXA,EAAK,IAAI,CAACC,EAAGC,IAASA,IAAQJ,EAAI,CAAE,GAAGG,EAAG,GAAGF,CAAA,EAAUE,CAAE,CAAA,EAErDE,EAAY,IACjBb,EAAYU,GAAS,CAAC,GAAGA,EAAM,CAAE,IAAK,GAAI,MAAO,EAAA,CAAI,CAAC,EACjDI,EAAgBN,GACrBR,EAAYU,GAASA,EAAK,OAAO,CAACK,EAAGH,IAAQA,IAAQJ,CAAC,CAAC,EAElDQ,EAAc7B,EAAK,KAAA,EAEnB8B,EACLD,EAAY,OAAS,GACrB/B,EAAc,KACZiC,GAAMA,EAAE,KAAA,EAAO,YAAA,IAAkBF,EAAY,YAAA,CAAY,EAEtDG,EACLH,EAAY,OAAS,GAAKrB,EAAI,OAAO,OAAS,GAAK,CAACsB,EAE/CG,EAAa,SAAY,CAC9B,GAAI,CAACD,GAAWd,EACf,OAED,MAAMgB,EAA4B,CACjC,GAAIzC,GAAS,IAAM,WAAW,KAAK,MAAM,SAAS,EAAE,CAAC,GACrD,KAAMO,EAAK,KAAA,EACX,aAAAM,EACA,IAAKE,EAAI,KAAA,EACT,OAAAE,EAEA,QAASE,EAAQ,OAAQY,GAAMA,EAAE,IAAI,QAAUA,EAAE,MAAM,KAAA,CAAM,EAC7D,YAAAV,EACA,eAAAE,CAAA,EAEKmB,EAAS3C,EAAO0C,CAAM,EAC5B,GAAIC,GAAU,OAAQA,EAAyB,MAAS,WAAY,CACnEhB,EAAU,EAAI,EACd,GAAI,CACH,MAAMgB,CACP,QAAA,CACChB,EAAU,EAAK,CAChB,CACD,CACD,EAEA,OACCiB,EAAAA,KAACC,GAAAA,UAAA,CACA,OAAO,WACP,iBAAkB,GAClB,OAAAxC,EACA,sBACCyC,EAAAA,IAACC,EAAAA,iBAAA,CACA,MAAM,WACN,SAAS,mGAAA,CAAA,EAGX,MAAM,QACN,YAAaC,EAAAA,oBACb,UAAWC,EAAAA,kBACX,QAAAlD,EACA,gBAAiB,CAChB,YAAa,eACb,WAAY,OACZ,WAAY,UACZ,KAAM,QACN,SAAU,CAACyC,EACX,UAAWd,EACX,QAASe,CAAA,EAEV,kBAAmB,CAClB,YAAa,iBACb,WAAY,SACZ,WAAY,eACZ,KAAM,QACN,QAAS1C,CAAA,EAGV,SAAA,CAAA+C,EAAAA,IAACI,EAAAA,MAAA,CACA,YAAU,eACV,QAAQ,QACR,UAAU,OACV,cAAa,GACb,YAAY,oBACZ,MAAO1C,EACP,aAAcL,EAAW,KACzB,MAAOmC,EAAkB,UAAY,OACrC,aACCA,EAAkB,uCAAyC,OAE5D,aAAc7B,CAAA,CAAA,EAGfqC,EAAAA,IAACK,GAAAA,sBAAA,CACA,YAAU,uBACV,MAAM,eACN,MAAOrC,EACP,SAAUC,EACV,UAAWZ,EAAW,aACtB,YAAY,oDACZ,UAAAD,EACA,cAAAK,CAAA,CAAA,QAGA6C,EAAAA,WAAA,CACA,SAAAN,EAAAA,IAACO,EAAAA,oBAAA,CACA,cAAa,GACb,cAAA9C,EACA,SAAU,CAACX,EAAO0D,IACjBrC,EAAQsC,GAAM,CACb,MAAMC,EAAKF,GAASC,EAAE,OACtB,MAAO,GAAGA,EAAE,MAAM,EAAGC,CAAE,CAAC,GAAG5D,CAAK,GAAG2D,EAAE,MAAMC,CAAE,CAAC,EAC/C,CAAC,EAGF,SAAAV,EAAAA,IAACI,EAAAA,MAAA,CACA,YAAU,cACV,QAAQ,QACR,UAAU,cACV,cAAa,GACb,YAAY,WACZ,KAAK,MACL,MAAOlC,EACP,aAAcC,CAAA,CAAA,CACf,CAAA,EAEF,SAECmC,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACW,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,cAAW,EACtDZ,EAAAA,IAACa,GAAAA,SAAA,CACA,YAAU,iBACV,KAAK,QACL,MAAM,OACN,cAAc,QACd,QAASlE,GACT,eAAgB,CAAC,CAAE,MAAOyB,EAAQ,MAAOA,EAAQ,EACjD,SAAW0C,GAAQ,CAClB,MAAMC,EAAIC,GAAAA,oBAAoBF,CAAG,EAC7BC,GACH1C,EAAU0C,CAAkB,CAE9B,CAAA,CAAA,CACD,EACD,SAECT,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACW,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,UAAO,EACjDtC,EAAQ,IAAI,CAACY,EAAGH,IAEhBe,EAAAA,KAACmB,GAAA,CAAkB,YAAW,kBAAkBlC,CAAC,GAChD,SAAA,CAAAiB,EAAAA,IAACI,EAAAA,MAAA,CACA,QAAQ,QACR,gBAAe,GACf,YAAY,aACZ,MAAOlB,EAAE,IACT,aAAe6B,GAAMjC,EAAYC,EAAG,CAAE,IAAKgC,EAAG,CAAA,CAAA,EAE/Cf,EAAAA,IAACO,EAAAA,oBAAA,CACA,cAAa,GACb,cAAA9C,EACA,SAAU,CAACX,EAAO0D,IAAU,CAC3B,MAAME,EAAKF,GAAStB,EAAE,MAAM,OAC5BJ,EAAYC,EAAG,CACd,MAAO,GAAGG,EAAE,MAAM,MAAM,EAAGwB,CAAE,CAAC,GAAG5D,CAAK,GAAGoC,EAAE,MAAM,MAAMwB,CAAE,CAAC,EAAA,CAC1D,CACF,EAEA,SAAAV,EAAAA,IAACI,EAAAA,MAAA,CACA,QAAQ,QACR,gBAAe,GACf,YAAY,cACZ,MAAOlB,EAAE,MACT,aAAe6B,GAAMjC,EAAYC,EAAG,CAAE,MAAOgC,EAAG,CAAA,CAAA,CACjD,CAAA,EAEDf,EAAAA,IAACkB,GAAA,CACA,KAAK,SACL,aAAW,gBACX,YAAW,yBAAyBnC,CAAC,GACrC,QAAS,IAAMM,EAAaN,CAAC,EAE7B,SAAAiB,EAAAA,IAACmB,EAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOP,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,CACD,CAAA,EArCe7B,CAsChB,CACA,QACAqC,GAAA,CACA,SAAApB,EAAAA,IAACqB,GAAAA,OAAA,CACA,YAAU,qBACV,WAAW,cACX,KAAK,QACL,YAAaC,EAAAA,QACb,WAAW,aACX,QAASlC,CAAA,CAAA,CACV,CACD,CAAA,EACD,SAECkB,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACW,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,WAAQ,EACnDZ,EAAAA,IAACO,EAAAA,oBAAA,CACA,cAAa,GACb,cAAA9C,EACA,eAAgBZ,EAChB,SAAWC,GACVe,EAAiB,SAAS,oBAAoBf,CAAK,EAGpD,SAAAkD,EAAAA,IAACuB,EAAAA,UAAA,CACA,IAAK1D,EACL,SAAU,CAAE,SAAU,EAAA,EACtB,eAAgBW,EAChB,MAAOgD,EACP,YAAY,0BACZ,SAAWC,GAAMhD,EAAegD,EAAE,IAAI,EACtC,UAAU,QACV,UAAU,OAAA,CAAA,CACX,CAAA,CACD,EACD,SAECnB,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACW,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,YAAS,EACpDZ,EAAAA,IAACO,EAAAA,oBAAA,CACA,cAAa,GACb,cAAA9C,EACA,eAAgBZ,EAChB,SAAWC,GACViB,EAAkB,SAAS,oBAAoBjB,CAAK,EAGrD,SAAAkD,EAAAA,IAACuB,EAAAA,UAAA,CACA,IAAKxD,EACL,SAAU,CAAE,SAAU,EAAA,EACtB,MAAOyD,EACP,eAAgB9C,EAChB,YAAY,0BACZ,SAAW+C,GAAM9C,EAAkB8C,EAAE,IAAI,EACzC,UAAU,QACV,UAAU,OAAA,CAAA,CACX,CAAA,CACD,CAAA,CACD,CAAA,CAAA,CAAA,CAGH,EAEMR,GAAYS,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAMnBN,GAAeM,EAAAA,QAAO;AAAA;AAAA,EAItBR,GAAUQ,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAOFd,EAAAA,OAAO,OAAO,OAAO;AAAA;AAAA,eAE3BA,EAAAA,OAAO,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA,kBAIpBA,EAAAA,OAAO,QAAQ,SAAS;AAAA;AAAA,EAI7BY,EAAe,CAC3B,aAAc,MACd,SAAU,QACX"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),l=require("react"),q=require("styled-components"),I=require("../../TypographyStyle.js"),A=require("../../../constants/Theme.js"),c=require("../AgentBuilder.styled.js"),B=require("./MentionEditor.js"),b=require("../../button/Button.js"),v=require("../../../icons/BIK AI specific/WandSparkles.js"),E=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},F=E(q),w=({label:t,value:o,onChange:s,maxLength:d,placeholder:u,minHeight:p="120px",onImprove:i,variablesData:f,...n})=>{const[g,m]=l.useState(!1),[r,y]=l.useState(!1),[j,S]=l.useState(0),x=(f?.length??0)>0,T=async()=>{if(!(!i||r||o.trim().length===0)){y(!0);try{s(await i(o)),x&&S(a=>a+1)}finally{y(!1)}}},h=i?e.jsx(R,{children:e.jsx(b.Button,{"data-test":`${n["data-test"]??"tool"}-improve`,buttonType:"ai",size:"small",LeadingIcon:v.default,buttonText:"Improve with AI",isLoading:r,disabled:r||o.trim().length===0,onClick:T})}):void 0;return x?e.jsx(B.MentionEditor,{"data-test":n["data-test"],label:t,value:o,onChange:s,maxLength:d,placeholder:u,minHeight:p,resetKey:`improve-${j}`,mentionItems:[],tools:[],variablesData:f,addDataButton:!0,action:h}):e.jsxs(c.FieldBlock,{children:[e.jsx(I.TitleSmall,{color:A.COLORS.content.primary,children:t}),e.jsxs(c.AiTextAreaShell,{focused:g,minHeight:p,children:[e.jsx(c.AiTextAreaInput,{"data-test":n["data-test"],value:o,placeholder:u,maxLength:d,onFocus:()=>m(!0),onBlur:()=>m(!1),onChange:a=>s(a.target.value)}),h]})]})},R=F.default.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: center;
|
|
4
4
|
`;exports.ToolInstructionsField=w;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolInstructionsField.js","sources":["../../../../../src/components/agent-builder/components/ToolInstructionsField.tsx"],"sourcesContent":["import { WandSparkles } from '@src/icons';\nimport React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { Button } from '@src/components/button';\nimport { TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tAiTextAreaInput,\n\tAiTextAreaShell,\n\tFieldBlock,\n} from '../AgentBuilder.styled';\nimport { MentionEditor } from './MentionEditor';\n\ninterface ToolInstructionsFieldProps {\n\tlabel: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tmaxLength: number;\n\tplaceholder?: string;\n\tminHeight?: string;\n\t/** \"Improve with AI\" — resolves with rewritten text. Omit to hide the button. */\n\tonImprove?: (text: string) => Promise<string>;\n\t/**\n\t * Variable catalog. When non-empty the field upgrades from a plain textarea\n\t * to a variables-only `@` mention editor: typing `@` opens the variable\n\t * categories directly (Variables is the sole category, so the picker skips\n\t * the Tools / Sub-agent root), and picks render as chips persisted as\n\t * `{{variable:<name>}}` tokens.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t'data-test'?: string;\n}\n\n/**\n * A labelled multiline field with an inline \"Improve with AI\" action pinned to\n * the bottom-left of the box (Figma: Rest API / Handover-to-email drawers). The\n * button is hidden when `onImprove` is omitted.\n */\nexport const ToolInstructionsField: React.FC<ToolInstructionsFieldProps> = ({\n\tlabel,\n\tvalue,\n\tonChange,\n\tmaxLength,\n\tplaceholder,\n\tminHeight = '120px',\n\tonImprove,\n\tvariablesData,\n\t...rest\n}) => {\n\tconst [focused, setFocused] = useState(false);\n\tconst [improving, setImproving] = useState(false);\n\t// Bumped when \"Improve with AI\" replaces the text externally — the mention\n\t// editor only reads `value` on (re)mount, so it must be remounted.\n\tconst [editorEpoch, setEditorEpoch] = useState(0);\n\n\tconst withVariables = (variablesData?.length ?? 0) > 0;\n\n\tconst handleImprove = async () => {\n\t\tif (!onImprove || improving || value.trim().length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tsetImproving(true);\n\t\ttry {\n\t\t\tonChange(await onImprove(value));\n\t\t\tif (withVariables) {\n\t\t\t\tsetEditorEpoch((e) => e + 1);\n\t\t\t}\n\t\t} finally {\n\t\t\tsetImproving(false);\n\t\t}\n\t};\n\n\tconst improveAction = onImprove ? (\n\t\t<ImproveRow>\n\t\t\t<Button\n\t\t\t\tdata-test={`${rest['data-test'] ?? 'tool'}-improve`}\n\t\t\t\tbuttonType=\"ai\"\n\t\t\t\tsize=\"small\"\n\t\t\t\tLeadingIcon={WandSparkles}\n\t\t\t\tbuttonText=\"Improve with AI\"\n\t\t\t\tisLoading={improving}\n\t\t\t\tdisabled={improving || value.trim().length === 0}\n\t\t\t\tonClick={handleImprove}\n\t\t\t/>\n\t\t</ImproveRow>\n\t) : undefined;\n\n\t// Variables enabled → the mention-editor variant. `mentionItems` / tool\n\t// hooks stay empty so Variables is the picker's ONLY category and `@` lands\n\t// straight in the variable list.\n\tif (withVariables) {\n\t\treturn (\n\t\t\t<MentionEditor\n\t\t\t\tdata-test={rest['data-test']}\n\t\t\t\tlabel={label}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={onChange}\n\t\t\t\tmaxLength={maxLength}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tminHeight={minHeight}\n\t\t\t\tresetKey={`improve-${editorEpoch}`}\n\t\t\t\tmentionItems={[]}\n\t\t\t\ttools={[]}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\taction={improveAction}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<FieldBlock>\n\t\t\t<TitleSmall color={COLORS.content.primary}>{label}</TitleSmall>\n\t\t\t<AiTextAreaShell focused={focused} minHeight={minHeight}>\n\t\t\t\t<AiTextAreaInput\n\t\t\t\t\tdata-test={rest['data-test']}\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tmaxLength={maxLength}\n\t\t\t\t\tonFocus={() => setFocused(true)}\n\t\t\t\t\tonBlur={() => setFocused(false)}\n\t\t\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\t\t/>\n\t\t\t\t{improveAction}\n\t\t\t</AiTextAreaShell>\n\t\t</FieldBlock>\n\t);\n};\n\nconst ImproveRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n`;\n"],"names":["ToolInstructionsField","label","value","onChange","maxLength","placeholder","minHeight","onImprove","variablesData","rest","focused","setFocused","useState","improving","setImproving","editorEpoch","setEditorEpoch","withVariables","handleImprove","e","improveAction","jsx","ImproveRow","Button","WandSparkles","MentionEditor","FieldBlock","TitleSmall","COLORS","jsxs","AiTextAreaShell","AiTextAreaInput","styled"],"mappings":"4dAuCaA,EAA8D,CAAC,CAC3E,MAAAC,EACA,MAAAC,EACA,SAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EAAY,QACZ,UAAAC,EACA,cAAAC,EACA,GAAGC,CACJ,IAAM,CACL,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAAS,EAAK,EACtC,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAK,EAG1C,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAS,CAAC,EAE1CK,GAAiBT,GAAe,QAAU,GAAK,EAE/CU,EAAgB,SAAY,CACjC,GAAI,GAACX,GAAaM,GAAaX,EAAM,KAAA,EAAO,SAAW,GAGvD,CAAAY,EAAa,EAAI,EACjB,GAAI,CACHX,EAAS,MAAMI,EAAUL,CAAK,CAAC,EAC3Be,GACHD,EAAgBG,GAAMA,EAAI,CAAC,CAE7B,QAAA,CACCL,EAAa,EAAK,CACnB,EACD,EAEMM,EAAgBb,EACrBc,EAAAA,IAACC,EAAA,CACA,SAAAD,EAAAA,IAACE,EAAAA,OAAA,CACA,YAAW,GAAGd,EAAK,WAAW,GAAK,MAAM,WACzC,WAAW,KACX,KAAK,QACL,YAAae,EAAAA,QACb,WAAW,kBACX,UAAWX,EACX,SAAUA,GAAaX,EAAM,KAAA,EAAO,SAAW,EAC/C,QAASgB,CAAA,CAAA,EAEX,EACG,OAKJ,OAAID,EAEFI,EAAAA,IAACI,EAAAA,cAAA,CACA,YAAWhB,EAAK,WAAW,EAC3B,MAAAR,EACA,MAAAC,EACA,SAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EACA,SAAU,WAAWS,CAAW,GAChC,aAAc,CAAA,EACd,MAAO,CAAA,EACP,cAAAP,
|
|
1
|
+
{"version":3,"file":"ToolInstructionsField.js","sources":["../../../../../src/components/agent-builder/components/ToolInstructionsField.tsx"],"sourcesContent":["import { WandSparkles } from '@src/icons';\nimport React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { Button } from '@src/components/button';\nimport { TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tAiTextAreaInput,\n\tAiTextAreaShell,\n\tFieldBlock,\n} from '../AgentBuilder.styled';\nimport { MentionEditor } from './MentionEditor';\n\ninterface ToolInstructionsFieldProps {\n\tlabel: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tmaxLength: number;\n\tplaceholder?: string;\n\tminHeight?: string;\n\t/** \"Improve with AI\" — resolves with rewritten text. Omit to hide the button. */\n\tonImprove?: (text: string) => Promise<string>;\n\t/**\n\t * Variable catalog. When non-empty the field upgrades from a plain textarea\n\t * to a variables-only `@` mention editor: typing `@` opens the variable\n\t * categories directly (Variables is the sole category, so the picker skips\n\t * the Tools / Sub-agent root), and picks render as chips persisted as\n\t * `{{variable:<name>}}` tokens.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t'data-test'?: string;\n}\n\n/**\n * A labelled multiline field with an inline \"Improve with AI\" action pinned to\n * the bottom-left of the box (Figma: Rest API / Handover-to-email drawers). The\n * button is hidden when `onImprove` is omitted.\n */\nexport const ToolInstructionsField: React.FC<ToolInstructionsFieldProps> = ({\n\tlabel,\n\tvalue,\n\tonChange,\n\tmaxLength,\n\tplaceholder,\n\tminHeight = '120px',\n\tonImprove,\n\tvariablesData,\n\t...rest\n}) => {\n\tconst [focused, setFocused] = useState(false);\n\tconst [improving, setImproving] = useState(false);\n\t// Bumped when \"Improve with AI\" replaces the text externally — the mention\n\t// editor only reads `value` on (re)mount, so it must be remounted.\n\tconst [editorEpoch, setEditorEpoch] = useState(0);\n\n\tconst withVariables = (variablesData?.length ?? 0) > 0;\n\n\tconst handleImprove = async () => {\n\t\tif (!onImprove || improving || value.trim().length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tsetImproving(true);\n\t\ttry {\n\t\t\tonChange(await onImprove(value));\n\t\t\tif (withVariables) {\n\t\t\t\tsetEditorEpoch((e) => e + 1);\n\t\t\t}\n\t\t} finally {\n\t\t\tsetImproving(false);\n\t\t}\n\t};\n\n\tconst improveAction = onImprove ? (\n\t\t<ImproveRow>\n\t\t\t<Button\n\t\t\t\tdata-test={`${rest['data-test'] ?? 'tool'}-improve`}\n\t\t\t\tbuttonType=\"ai\"\n\t\t\t\tsize=\"small\"\n\t\t\t\tLeadingIcon={WandSparkles}\n\t\t\t\tbuttonText=\"Improve with AI\"\n\t\t\t\tisLoading={improving}\n\t\t\t\tdisabled={improving || value.trim().length === 0}\n\t\t\t\tonClick={handleImprove}\n\t\t\t/>\n\t\t</ImproveRow>\n\t) : undefined;\n\n\t// Variables enabled → the mention-editor variant. `mentionItems` / tool\n\t// hooks stay empty so Variables is the picker's ONLY category and `@` lands\n\t// straight in the variable list.\n\tif (withVariables) {\n\t\treturn (\n\t\t\t<MentionEditor\n\t\t\t\tdata-test={rest['data-test']}\n\t\t\t\tlabel={label}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={onChange}\n\t\t\t\tmaxLength={maxLength}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tminHeight={minHeight}\n\t\t\t\tresetKey={`improve-${editorEpoch}`}\n\t\t\t\tmentionItems={[]}\n\t\t\t\ttools={[]}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\t// Drawers get the same focused-field \"+ Add data\" affordance as the\n\t\t\t\t// main Step-3 editors.\n\t\t\t\taddDataButton\n\t\t\t\taction={improveAction}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<FieldBlock>\n\t\t\t<TitleSmall color={COLORS.content.primary}>{label}</TitleSmall>\n\t\t\t<AiTextAreaShell focused={focused} minHeight={minHeight}>\n\t\t\t\t<AiTextAreaInput\n\t\t\t\t\tdata-test={rest['data-test']}\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tmaxLength={maxLength}\n\t\t\t\t\tonFocus={() => setFocused(true)}\n\t\t\t\t\tonBlur={() => setFocused(false)}\n\t\t\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\t\t/>\n\t\t\t\t{improveAction}\n\t\t\t</AiTextAreaShell>\n\t\t</FieldBlock>\n\t);\n};\n\nconst ImproveRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n`;\n"],"names":["ToolInstructionsField","label","value","onChange","maxLength","placeholder","minHeight","onImprove","variablesData","rest","focused","setFocused","useState","improving","setImproving","editorEpoch","setEditorEpoch","withVariables","handleImprove","e","improveAction","jsx","ImproveRow","Button","WandSparkles","MentionEditor","FieldBlock","TitleSmall","COLORS","jsxs","AiTextAreaShell","AiTextAreaInput","styled"],"mappings":"4dAuCaA,EAA8D,CAAC,CAC3E,MAAAC,EACA,MAAAC,EACA,SAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EAAY,QACZ,UAAAC,EACA,cAAAC,EACA,GAAGC,CACJ,IAAM,CACL,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAAS,EAAK,EACtC,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAK,EAG1C,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAS,CAAC,EAE1CK,GAAiBT,GAAe,QAAU,GAAK,EAE/CU,EAAgB,SAAY,CACjC,GAAI,GAACX,GAAaM,GAAaX,EAAM,KAAA,EAAO,SAAW,GAGvD,CAAAY,EAAa,EAAI,EACjB,GAAI,CACHX,EAAS,MAAMI,EAAUL,CAAK,CAAC,EAC3Be,GACHD,EAAgBG,GAAMA,EAAI,CAAC,CAE7B,QAAA,CACCL,EAAa,EAAK,CACnB,EACD,EAEMM,EAAgBb,EACrBc,EAAAA,IAACC,EAAA,CACA,SAAAD,EAAAA,IAACE,EAAAA,OAAA,CACA,YAAW,GAAGd,EAAK,WAAW,GAAK,MAAM,WACzC,WAAW,KACX,KAAK,QACL,YAAae,EAAAA,QACb,WAAW,kBACX,UAAWX,EACX,SAAUA,GAAaX,EAAM,KAAA,EAAO,SAAW,EAC/C,QAASgB,CAAA,CAAA,EAEX,EACG,OAKJ,OAAID,EAEFI,EAAAA,IAACI,EAAAA,cAAA,CACA,YAAWhB,EAAK,WAAW,EAC3B,MAAAR,EACA,MAAAC,EACA,SAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EACA,SAAU,WAAWS,CAAW,GAChC,aAAc,CAAA,EACd,MAAO,CAAA,EACP,cAAAP,EAGA,cAAa,GACb,OAAQY,CAAA,CAAA,SAMTM,aAAA,CACA,SAAA,CAAAL,MAACM,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAU,SAAA3B,EAAM,EAClD4B,EAAAA,KAACC,EAAAA,gBAAA,CAAgB,QAAApB,EAAkB,UAAAJ,EAClC,SAAA,CAAAe,EAAAA,IAACU,EAAAA,gBAAA,CACA,YAAWtB,EAAK,WAAW,EAC3B,MAAAP,EACA,YAAAG,EACA,UAAAD,EACA,QAAS,IAAMO,EAAW,EAAI,EAC9B,OAAQ,IAAMA,EAAW,EAAK,EAC9B,SAAWQ,GAAMhB,EAASgB,EAAE,OAAO,KAAK,CAAA,CAAA,EAExCC,CAAA,CAAA,CACF,CAAA,EACD,CAEF,EAEME,EAAaU,EAAAA,QAAO;AAAA;AAAA;AAAA"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react/jsx-runtime"),i=require("react"),T=require("styled-components"),m=require("../../../constants/Theme.js"),S=require("../../variable-picker-v3/model.js"),C=require("../utils/mentionSerialization.js"),E=require("./AddDataPill.js"),L=require("../../variable-picker-v3/VariablePicker.js"),O=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},k=O(T),y=e=>`{{variable:${C.variableTokenName(e.actualValue)}}}`,h=/[\s,;:/?&=(){}[\]"'<>]/,w=e=>{if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){const o=e.selectionStart??e.value.length,p=o===0?" ":e.value[o-1]??" ";return{ok:h.test(p),caret:o,textBefore:e.value.slice(0,o)}}const u=window.getSelection(),c=u?.anchorNode?.textContent??"",l=u?.anchorOffset??0,f=l===0?" ":c[l-1]??" ";return{ok:h.test(f),caret:null,textBefore:c.slice(0,l)}},$=({variablesData:e,onInsert:u,transformToken:c,addDataButton:l,children:f})=>{const o=i.useRef(null),[p,x]=i.useState(!1),v=i.useRef(null),[r,a]=i.useState(null),g=(e?.length??0)>0,b=()=>{const t=o.current?.getBoundingClientRect();return{above:!!t&&window.innerHeight-t.bottom<340,alignRight:!!t&&window.innerWidth-t.left<360}},B=i.useCallback(t=>{if(!g||t.key!=="@")return;const n=w(t.target);n.ok&&(t.preventDefault(),t.stopPropagation(),a({caret:n.caret,textBefore:n.textBefore,...b()}))},[g]),R=()=>{const t=w(v.current);a({caret:t.caret,textBefore:t.textBefore,...b()})};return i.useEffect(()=>{if(!r)return;const t=s=>{s.key==="Escape"&&(s.stopPropagation(),a(null))},n=s=>{o.current?.contains(s.target)||a(null)};return document.addEventListener("keydown",t,!0),document.addEventListener("mousedown",n),()=>{document.removeEventListener("keydown",t,!0),document.removeEventListener("mousedown",n)}},[r]),d.jsxs(q,{ref:o,onKeyDownCapture:B,onFocus:t=>{t.target.closest?.('[data-test="variable-trigger-panel"]')||(v.current=t.target,x(!0))},onBlur:()=>x(!1),children:[f,l&&g&&(p||r)&&d.jsx(E.AddDataPill,{onOpen:R}),r&&d.jsx(F,{$above:r.above,$right:r.alignRight,"data-test":"variable-trigger-panel",children:d.jsx(L.VariablePicker,{type:S.PickerType.FLOATER,data:e??[],showRecommendedBar:!1,onClose:()=>a(null),onSelect:t=>{a(null);const n=y(t),s=c?c(n,{textBefore:r.textBefore}):n;u(s,r.caret)}})})]})},q=k.default.div`
|
|
2
2
|
position: relative;
|
|
3
|
-
`,
|
|
3
|
+
`,F=k.default.div`
|
|
4
4
|
position: absolute;
|
|
5
|
-
left: 0;
|
|
6
5
|
z-index: 1000;
|
|
6
|
+
width: 344px;
|
|
7
|
+
background: ${m.COLORS.surface.standard};
|
|
8
|
+
border: 1px solid ${m.COLORS.stroke.primary};
|
|
9
|
+
border-radius: 4px;
|
|
10
|
+
box-shadow: 0px -2px 8px 0px #0000001f;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
${e=>e.$right?"right: 0;":"left: 0;"}
|
|
7
13
|
${e=>e.$above?"bottom: calc(100% + 4px);":"top: calc(100% + 4px);"}
|
|
8
|
-
`;exports.VariableTriggerArea
|
|
14
|
+
`;exports.VariableTriggerArea=$;exports.variableToken=y;
|
|
9
15
|
//# sourceMappingURL=VariableTriggerArea.js.map
|