@bikdotai/bik-component-library 0.0.850-beta.1 → 0.0.850-beta.2
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/AgentBuilder.styled.js +14 -7
- package/dist/cjs/components/agent-builder/AgentBuilder.styled.js.map +1 -1
- 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/CreateSubAgentPanel.js +5 -5
- package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.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/MentionPicker.js +24 -24
- package/dist/cjs/components/agent-builder/components/MentionPicker.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/SelectableListSection.js +2 -2
- package/dist/cjs/components/agent-builder/components/SelectableListSection.js.map +1 -1
- package/dist/cjs/components/agent-builder/constants/tools.js +1 -1
- package/dist/cjs/components/agent-builder/constants/tools.js.map +1 -1
- package/dist/cjs/components/agent-builder/context/AgentBuilderContext.js +1 -1
- package/dist/cjs/components/agent-builder/context/AgentBuilderContext.js.map +1 -1
- package/dist/cjs/components/agent-builder/steps/Step3HowItResponds.js +1 -1
- package/dist/cjs/components/agent-builder/steps/Step3HowItResponds.js.map +1 -1
- package/dist/cjs/components/agent-builder/utils/mentionSerialization.js +2 -2
- package/dist/cjs/components/agent-builder/utils/mentionSerialization.js.map +1 -1
- package/dist/cjs/components/agent-builder/utils/sourceIcons.js +1 -1
- package/dist/cjs/components/agent-builder/utils/sourceIcons.js.map +1 -1
- package/dist/cjs/components/agent-listing/AgentListing.js +1 -1
- package/dist/cjs/components/agent-listing/AgentListing.js.map +1 -1
- package/dist/cjs/components/agent-listing/AgentTable.js +1 -1
- package/dist/cjs/components/agent-listing/AgentTable.js.map +1 -1
- package/dist/cjs/components/agent-listing/AgentTableRow.js +1 -1
- package/dist/cjs/components/agent-listing/AgentTableRow.js.map +1 -1
- package/dist/cjs/components/bik-layout/CommonStyles.js +6 -4
- package/dist/cjs/components/bik-layout/CommonStyles.js.map +1 -1
- package/dist/cjs/components/button/themes.js +3 -3
- package/dist/cjs/components/button/themes.js.map +1 -1
- package/dist/cjs/components/datePicker/DatePicker.js +1 -1
- package/dist/cjs/components/datePicker/DatePicker.js.map +1 -1
- package/dist/cjs/components/datePicker/DatePicker.styled.js +14 -20
- package/dist/cjs/components/datePicker/DatePicker.styled.js.map +1 -1
- package/dist/cjs/components/dropdown/ChipInput.js +1 -1
- package/dist/cjs/components/dropdown/ChipInput.js.map +1 -1
- package/dist/cjs/components/dropdown/Common.styled.js +5 -6
- package/dist/cjs/components/dropdown/Common.styled.js.map +1 -1
- package/dist/cjs/components/dropdown/Dropdown.js +1 -1
- package/dist/cjs/components/dropdown/Dropdown.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/OpennedDropdown.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/OpennedDropdown.js.map +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/searchbox/SearchBox.js +1 -1
- package/dist/cjs/components/dropdown/OpenedDropdown/components/searchbox/SearchBox.js.map +1 -1
- package/dist/cjs/components/input/Input.js +1 -1
- package/dist/cjs/components/input/Input.js.map +1 -1
- package/dist/cjs/components/input/Input.styled.js +12 -25
- package/dist/cjs/components/input/Input.styled.js.map +1 -1
- package/dist/cjs/components/tabs/Tabs.js +1 -1
- package/dist/cjs/components/tabs/Tabs.js.map +1 -1
- package/dist/cjs/components/tabs/Tabs.styles.js +8 -22
- package/dist/cjs/components/tabs/Tabs.styles.js.map +1 -1
- package/dist/cjs/components/tag/Tag.js +1 -1
- package/dist/cjs/components/tag/Tag.js.map +1 -1
- package/dist/cjs/components/tag/Tag.styled.js +0 -4
- package/dist/cjs/components/tag/Tag.styled.js.map +1 -1
- package/dist/cjs/components/tag/model.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 +4 -4
- package/dist/cjs/editor/BikEditor.styles.js.map +1 -1
- package/dist/cjs/editor/BikEditor.types.js.map +1 -1
- package/dist/cjs/editor/extensions/buildExtensions.js +2 -2
- package/dist/cjs/editor/extensions/buildExtensions.js.map +1 -1
- package/dist/cjs/editor/extensions/mention/MentionChipNodeView.js +2 -0
- package/dist/cjs/editor/extensions/mention/MentionChipNodeView.js.map +1 -0
- package/dist/cjs/editor/extensions/mention/MentionExtension.js +1 -1
- package/dist/cjs/editor/extensions/mention/MentionExtension.js.map +1 -1
- package/dist/esm/components/agent-builder/AgentBuilder.styled.js +17 -10
- package/dist/esm/components/agent-builder/AgentBuilder.styled.js.map +1 -1
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +1 -1
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.d.ts +5 -0
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js +243 -227
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/MentionEditor.d.ts +1 -1
- package/dist/esm/components/agent-builder/components/MentionEditor.js +93 -78
- package/dist/esm/components/agent-builder/components/MentionEditor.js.map +1 -1
- package/dist/esm/components/agent-builder/components/MentionPicker.js +179 -161
- package/dist/esm/components/agent-builder/components/MentionPicker.js.map +1 -1
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js +118 -109
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/SelectableListSection.js +117 -110
- package/dist/esm/components/agent-builder/components/SelectableListSection.js.map +1 -1
- package/dist/esm/components/agent-builder/constants/tools.d.ts +10 -0
- package/dist/esm/components/agent-builder/constants/tools.js +27 -14
- package/dist/esm/components/agent-builder/constants/tools.js.map +1 -1
- package/dist/esm/components/agent-builder/context/AgentBuilderContext.d.ts +6 -2
- package/dist/esm/components/agent-builder/context/AgentBuilderContext.js +46 -43
- package/dist/esm/components/agent-builder/context/AgentBuilderContext.js.map +1 -1
- package/dist/esm/components/agent-builder/steps/Step3HowItResponds.js +132 -117
- package/dist/esm/components/agent-builder/steps/Step3HowItResponds.js.map +1 -1
- package/dist/esm/components/agent-builder/utils/mentionSerialization.d.ts +3 -2
- package/dist/esm/components/agent-builder/utils/mentionSerialization.js +24 -19
- package/dist/esm/components/agent-builder/utils/mentionSerialization.js.map +1 -1
- package/dist/esm/components/agent-builder/utils/sourceIcons.d.ts +9 -1
- package/dist/esm/components/agent-builder/utils/sourceIcons.js +15 -9
- package/dist/esm/components/agent-builder/utils/sourceIcons.js.map +1 -1
- package/dist/esm/components/agent-listing/AgentListing.js +71 -69
- package/dist/esm/components/agent-listing/AgentListing.js.map +1 -1
- package/dist/esm/components/agent-listing/AgentListing.model.d.ts +6 -0
- package/dist/esm/components/agent-listing/AgentTable.d.ts +2 -0
- package/dist/esm/components/agent-listing/AgentTable.js +29 -27
- package/dist/esm/components/agent-listing/AgentTable.js.map +1 -1
- package/dist/esm/components/agent-listing/AgentTableRow.d.ts +2 -0
- package/dist/esm/components/agent-listing/AgentTableRow.js +50 -36
- package/dist/esm/components/agent-listing/AgentTableRow.js.map +1 -1
- package/dist/esm/components/bik-layout/CommonStyles.js +3 -1
- package/dist/esm/components/bik-layout/CommonStyles.js.map +1 -1
- package/dist/esm/components/button/themes.js +1 -1
- package/dist/esm/components/button/themes.js.map +1 -1
- package/dist/esm/components/datePicker/DatePicker.js +21 -22
- package/dist/esm/components/datePicker/DatePicker.js.map +1 -1
- package/dist/esm/components/datePicker/DatePicker.styled.d.ts +0 -10
- package/dist/esm/components/datePicker/DatePicker.styled.js +16 -23
- package/dist/esm/components/datePicker/DatePicker.styled.js.map +1 -1
- package/dist/esm/components/dropdown/ChipInput.d.ts +0 -1
- package/dist/esm/components/dropdown/ChipInput.js +30 -37
- package/dist/esm/components/dropdown/ChipInput.js.map +1 -1
- package/dist/esm/components/dropdown/Common.styled.js +6 -7
- package/dist/esm/components/dropdown/Common.styled.js.map +1 -1
- package/dist/esm/components/dropdown/Dropdown.d.ts +0 -2
- package/dist/esm/components/dropdown/Dropdown.js +89 -96
- package/dist/esm/components/dropdown/Dropdown.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/OpennedDropdown.js +95 -103
- package/dist/esm/components/dropdown/OpenedDropdown/components/OpennedDropdown.js.map +1 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/searchbox/SearchBox.d.ts +0 -1
- package/dist/esm/components/dropdown/OpenedDropdown/components/searchbox/SearchBox.js +17 -17
- package/dist/esm/components/dropdown/OpenedDropdown/components/searchbox/SearchBox.js.map +1 -1
- package/dist/esm/components/dropdown/type.d.ts +0 -2
- package/dist/esm/components/input/Input.js +101 -104
- package/dist/esm/components/input/Input.js.map +1 -1
- package/dist/esm/components/input/Input.model.d.ts +0 -2
- package/dist/esm/components/input/Input.styled.d.ts +0 -2
- package/dist/esm/components/input/Input.styled.js +25 -38
- package/dist/esm/components/input/Input.styled.js.map +1 -1
- package/dist/esm/components/tabs/Tabs.js +81 -103
- package/dist/esm/components/tabs/Tabs.js.map +1 -1
- package/dist/esm/components/tabs/Tabs.model.d.ts +0 -7
- package/dist/esm/components/tabs/Tabs.styles.d.ts +0 -2
- package/dist/esm/components/tabs/Tabs.styles.js +9 -23
- package/dist/esm/components/tabs/Tabs.styles.js.map +1 -1
- package/dist/esm/components/tag/Tag.d.ts +1 -1
- package/dist/esm/components/tag/Tag.js +15 -17
- package/dist/esm/components/tag/Tag.js.map +1 -1
- package/dist/esm/components/tag/Tag.styled.d.ts +0 -1
- package/dist/esm/components/tag/Tag.styled.js +6 -10
- package/dist/esm/components/tag/Tag.styled.js.map +1 -1
- package/dist/esm/components/tag/model.d.ts +0 -5
- package/dist/esm/components/tag/model.js.map +1 -1
- package/dist/esm/editor/BikEditor.js +84 -83
- package/dist/esm/editor/BikEditor.js.map +1 -1
- package/dist/esm/editor/BikEditor.styles.js +4 -4
- package/dist/esm/editor/BikEditor.styles.js.map +1 -1
- package/dist/esm/editor/BikEditor.types.d.ts +7 -0
- package/dist/esm/editor/BikEditor.types.js.map +1 -1
- package/dist/esm/editor/extensions/buildExtensions.d.ts +1 -0
- package/dist/esm/editor/extensions/buildExtensions.js +13 -12
- package/dist/esm/editor/extensions/buildExtensions.js.map +1 -1
- package/dist/esm/editor/extensions/mention/MentionChipNodeView.d.ts +17 -0
- package/dist/esm/editor/extensions/mention/MentionChipNodeView.js +39 -0
- package/dist/esm/editor/extensions/mention/MentionChipNodeView.js.map +1 -0
- package/dist/esm/editor/extensions/mention/MentionExtension.d.ts +1 -1
- package/dist/esm/editor/extensions/mention/MentionExtension.js +67 -45
- package/dist/esm/editor/extensions/mention/MentionExtension.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 { 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\teditorDocToInstructions,\n\tinstructionsToEditorHtml,\n\tMentionKindMeta,\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/** 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\taction,\n\t...rest\n}) => {\n\tconst editorRef = useRef<BikEditorRef>(null);\n\tconst [count, setCount] = useState(value.length);\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\tconst initialHtml = useMemo(\n\t\t() => instructionsToEditorHtml(value, mentionItems),\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/>\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\tif (kind) {\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","action","rest","editorRef","useRef","count","setCount","useState","insert","useCallback","kind","id","overrideLabel","editor","item","m","finalLabel","buildMentionHtml","useEffect","initialHtml","useMemo","instructionsToEditorHtml","FieldBlock","jsxs","FieldLabelRow","jsx","TitleSmall","COLORS","BodyCaption","AiTextAreaShell","BikEditor","AGENT_EDITOR_STYLE","props","MentionPicker","snapshot","doc","editorDocToInstructions"],"mappings":"+ZAqEaA,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,OAAAC,EACA,GAAGC,CACJ,IAAM,CACL,MAAMC,EAAYC,EAAAA,OAAqB,IAAI,EACrC,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAASrB,EAAM,MAAM,EAEzCsB,EAASC,EAAAA,YACd,CAACC,EAAMC,EAAIC,IAAkB,CAC5B,MAAMC,EAASV,EAAU,QACzB,GAAI,CAACU,EACJ,OAED,MAAMC,EAAOtB,EAAa,KACxBuB,GACA,OAAOA,EAAE,EAAE,IAAM,OAAOJ,CAAE,GACzBI,EAAE,MAAiD,OAASL,CAAA,EAEzDM,EAAaJ,GAAiBE,GAAM,OAASH,EACnDE,EAAO,oBACN,GAAGI,EAAAA,iBAAiB,OAAON,CAAE,EAAGK,EAAYN,CAAI,CAAC,QAAA,CAEnD,EACA,CAAClB,CAAY,CAAA,EAGd0B,EAAAA,UAAU,IAAM,CACf,GAAKtB,EAGL,OAAAA,EAAeY,CAAM,EACd,IAAMZ,EAAe,IAAI,CACjC,EAAG,CAACA,EAAgBY,CAAM,CAAC,EAG3B,MAAMW,EAAcC,EAAAA,QACnB,IAAMC,EAAAA,yBAAyBnC,EAAOM,CAAY,EAElD,CAACD,CAAQ,CAAA,EAGV2B,OAAAA,EAAAA,UACC,IAAMZ,EAASpB,EAAM,MAAM,EAE3B,CAACK,CAAQ,CAAA,SAIR+B,aAAA,CACA,SAAA,CAAAC,OAACC,EAAAA,cAAA,CACA,SAAA,CAAAC,MAACC,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAU,SAAA1C,EAAM,EAClDsC,EAAAA,KAACK,EAAAA,YAAA,CAAY,MAAOD,EAAAA,OAAO,QAAQ,UACjC,SAAA,CAAAtB,EAAM,IAAEjB,CAAA,CAAA,CACV,CAAA,EACD,SAECyC,EAAAA,gBAAA,CAAgB,UAAAvC,EAAsB,YAAWY,EAAK,WAAW,EACjE,SAAA,CAAAuB,EAAAA,IAACK,EAAAA,UAAA,CAEA,IAAK3B,EACL,eAAgBgB,EAChB,YAAA9B,EAGA,eAAgBD,EAChB,UAAU,QACV,UAAU,QACV,MAAO,CAAE,OAAQ,MAAA,EACjB,YAAa2C,EAAAA,mBACb,QAAApC,EACA,SAAU,CACT,OAAQH,EACR,uBAAwB,GACxB,eAAiBwC,GAChBP,EAAAA,IAACQ,EAAAA,cAAA,CACC,GAAGD,EACJ,iBAAAnC,EACA,YAAAC,EACA,kBAAAC,EACA,qBAAAC,CAAA,CAAA,EAGF,SAAWc,GAAS,CACnB,MAAMJ,EAAQI,EAAK,MAChB,KACCJ,GACHhB,IAAkBgB,EAAM,OAAOI,EAAK,EAAE,CAAC,CAEzC,CAAA,EAED,SAAWoB,GAAa,CACvB5B,EAAS4B,EAAS,cAAc,EAChC,MAAMC,EAAMhC,EAAU,SAAS,QAAA,GAAa,KAC5ChB,EAASiD,EAAAA,wBAAwBD,EAAK1C,CAAK,CAAC,CAC7C,CAAA,EApCKF,CAAA,EAsCLU,CAAA,CAAA,CACF,CAAA,EACD,CAEF"}
|
|
1
|
+
{"version":3,"file":"MentionEditor.js","sources":["../../../../../src/components/agent-builder/components/MentionEditor.tsx"],"sourcesContent":["import { BikEditor, BikEditorRef, MentionItem, PasteData } 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 { 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\teditorDocToInstructions,\n\tinstructionsToEditorHtml,\n\tMentionKindMeta,\n} from '../utils/mentionSerialization';\nimport { renderSourceIcon, sourceIcon } from '../utils/sourceIcons';\nimport { MentionPicker } from './MentionPicker';\n\ntype InsertFn = (\n\tkind: 'tool' | 'subagent',\n\tid: string,\n\tlabel?: string,\n\tsource?: string,\n) => void;\n\n// Insert-safe HTML for a plain-text run: escape entities so pasted text is never\n// interpreted as markup, and keep line breaks (mirrors the plain-paste pipeline).\nconst plainTextToHtml = (text: string): string =>\n\ttext\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\\r?\\n/g, '<br>');\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/** 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\taction,\n\t...rest\n}) => {\n\tconst editorRef = useRef<BikEditorRef>(null);\n\tconst [count, setCount] = useState(value.length);\n\t// Live character count for the paste handler (BikEditor captures onPaste once\n\t// at mount, so it can't read the `count` state without going stale).\n\tconst countRef = useRef(value.length);\n\n\t// On paste, insert only the characters that still fit under the limit instead\n\t// of letting the paste overflow. Pastes that fit fall through to the editor's\n\t// normal (break-preserving) plain-paste pipeline.\n\tconst handlePaste = useCallback(\n\t\t({ text }: PasteData): boolean | void => {\n\t\t\tif (!text) {\n\t\t\t\treturn false; // non-text (e.g. images) → default handling\n\t\t\t}\n\t\t\tconst editor = editorRef.current;\n\t\t\tconst selectionLength = editor?.getSelectedText().length ?? 0;\n\t\t\tconst room = maxLength - (countRef.current - selectionLength);\n\t\t\tif (text.length <= room) {\n\t\t\t\treturn false; // fits → let the default plain-paste pipeline run\n\t\t\t}\n\t\t\tif (room <= 0) {\n\t\t\t\treturn true; // already full → drop the paste\n\t\t\t}\n\t\t\teditor?.insertContent(plainTextToHtml(text.slice(0, room)));\n\t\t\treturn true;\n\t\t},\n\t\t[maxLength],\n\t);\n\n\tconst insert = useCallback<InsertFn>(\n\t\t(kind, id, overrideLabel, overrideSource) => {\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\t// Prefer the caller-supplied source: a JUST-created custom tool (Rest API /\n\t\t\t// email / Slack) isn't in `mentionItems` yet, so the lookup would miss and\n\t\t\t// the chip would render without its icon until reload.\n\t\t\tconst source =\n\t\t\t\toverrideSource ??\n\t\t\t\t(item?.meta as unknown as MentionKindMeta | undefined)?.source;\n\t\t\teditor.insertInlineContent(\n\t\t\t\t`${buildMentionHtml(String(id), finalLabel, kind, source)} `,\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\tconst initialHtml = useMemo(\n\t\t() => instructionsToEditorHtml(value, mentionItems),\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t[resetKey],\n\t);\n\n\tuseEffect(\n\t\t() => {\n\t\t\tsetCount(value.length);\n\t\t\tcountRef.current = value.length;\n\t\t},\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; `onPaste` truncates a\n\t\t\t\t\t// paste to what still fits, and any residual overflow renders grey.\n\t\t\t\t\tcharacterLimit={maxLength}\n\t\t\t\t\tonPaste={handlePaste}\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\t// Tool chips lead with their source glyph (manifest / shopify / …);\n\t\t\t\t\t\t// sub-agent chips have no source, so no icon.\n\t\t\t\t\t\trenderChipIcon: (source) =>\n\t\t\t\t\t\t\trenderSourceIcon(sourceIcon(source ?? undefined), -6),\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/>\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\tif (kind) {\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\tcountRef.current = 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":["plainTextToHtml","text","MentionEditor","label","value","onChange","maxLength","placeholder","minHeight","resetKey","mentionItems","tools","onMentionSelect","onFocus","registerInsert","onCreateSubAgent","toolActions","integrationStatus","onConnectIntegration","action","rest","editorRef","useRef","count","setCount","useState","countRef","handlePaste","useCallback","editor","selectionLength","room","insert","kind","id","overrideLabel","overrideSource","item","m","finalLabel","source","buildMentionHtml","useEffect","initialHtml","useMemo","instructionsToEditorHtml","FieldBlock","jsxs","FieldLabelRow","jsx","TitleSmall","COLORS","BodyCaption","AiTextAreaShell","BikEditor","AGENT_EDITOR_STYLE","renderSourceIcon","sourceIcon","props","MentionPicker","snapshot","doc","editorDocToInstructions"],"mappings":"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"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),ee=require("../../../assets/icons/chevronRight.svg.js"),te=require("../../../assets/icons/searchIcon.svg.js"),ne=require("../../../icons/Arrows/Normal arrows/ArrowLeft.js"),c=require("react"),oe=require("styled-components"),N=require("../../TypographyStyle.js"),a=require("../../../constants/Theme.js"),g=require("../constants/tools.js"),G=require("../utils/mentionSerialization.js"),v=require("../utils/sourceIcons.js"),Y=require("../../../icons/Informational/Common UI/Shield.js"),re=i=>i&&typeof i=="object"&&"default"in i?i:{default:i},h=re(oe),k=i=>i.meta,C=i=>k(i)?.plainLabel??i.label,ie="__bik_create_subagent__",ae=({items:i,onSelect:L,registerKeyHandler:j,onClose:O,onCreateSubAgent:R,initialSource:U,toolActions:S,integrationStatus:F,onConnectIntegration:J})=>{const[Z,E]=c.useState(null),[u,q]=c.useState(U??null),[I,M]=c.useState(null),[A,m]=c.useState(-1),[w,Q]=c.useState(""),y=c.useMemo(()=>i.filter(e=>k(e)?.kind==="tool"),[i]),_=c.useMemo(()=>i.filter(e=>k(e)?.kind==="subagent"),[i]),P=c.useMemo(()=>{const e=[];return y.forEach(r=>{const x=k(r)?.source??"other";e.includes(x)||e.push(x)}),e},[y]),z=c.useMemo(()=>new Map((S??[]).map(e=>[e.source,e])),[S]),$=c.useMemo(()=>g.CATEGORIES.filter(e=>e.key==="tool"?y.length>0||(S?.length??0)>0:_.length>0||!!R),[y.length,_.length,R,S?.length]),D=$.length===1?$[0].key:null,d=Z??D,f=d?d==="subagent"?{title:"Sub-agent",onBack:D?void 0:()=>E(null)}:u?{title:G.toolSourceLabel(u),onBack:U?void 0:()=>q(null),icon:v.sourceIcon(u)}:I==="integrations"?{title:"Integrations",onBack:()=>M(null)}:{title:"Tools",onBack:D?void 0:()=>E(null)}:null,s=c.useMemo(()=>{if(!d)return $.map(n=>({id:n.key,label:n.label,drillsIn:!0,onActivate:()=>{E(n.key),q(null),M(null)}}));if(d==="subagent"){const n=w.trim().toLowerCase(),p=_.filter(b=>!n||C(b).toLowerCase().includes(n)).map(b=>({id:String(b.id),label:C(b),drillsIn:!1,onActivate:()=>L(b)}));return R&&p.push({id:ie,label:"Create new",drillsIn:!1,isCreate:!0,onActivate:()=>{O?.(),R()}}),p}if(!u){const n=(S??[]).map(t=>t.source).filter(t=>!P.includes(t)),p=[...P,...n],b=t=>{const l=z.get(t);if((l!==void 0?l.connected:F?.[t])===!1)return{id:t,label:G.toolSourceLabel(t),drillsIn:!1,icon:v.sourceIcon(t)??l?.icon,rightLabel:"Connect",onActivate:()=>{O?.(),l?.onConnect?l.onConnect():J?.(t)}};const X=y.filter(T=>(k(T)?.source??"other")===t);if(X.length+(l?1:0)===1){const T=v.sourceIcon(t)??l?.icon;if(l)return{id:t,label:l.label,drillsIn:!1,icon:T,onActivate:()=>{O?.(),l.onSelect()}};const B=X[0];return{id:String(B.id),label:C(B),drillsIn:!1,icon:T,authRequired:k(B)?.authRequired,onActivate:()=>L(B)}}return{id:t,label:G.toolSourceLabel(t),drillsIn:!0,icon:v.sourceIcon(t)??l?.icon,onActivate:()=>q(t)}};if(I==="integrations")return p.filter(g.isIntegrationSource).sort((t,l)=>g.toolSourceRank(t)-g.toolSourceRank(l)).map(b);const W=p.filter(t=>!g.isIntegrationSource(t)).map(t=>({rank:g.toolSourceRank(t),row:b(t)}));return p.some(g.isIntegrationSource)&&W.push({rank:g.INTEGRATIONS_RANK,row:{id:"__integrations__",label:"Integrations",drillsIn:!0,onActivate:()=>{M("integrations"),q(null)}}}),W.sort((t,l)=>t.rank-l.rank).map(t=>t.row)}const e=w.trim().toLowerCase(),r=y.filter(n=>(k(n)?.source??"other")===u).filter(n=>!e||C(n).toLowerCase().includes(e)).map(n=>({id:String(n.id),label:C(n),drillsIn:!1,authRequired:k(n)?.authRequired,onActivate:()=>L(n)})),x=z.get(u);if(x){const n=u in g.CONFIG_TOOL_SOURCES;r.push({id:`create:${u}`,label:x.label,drillsIn:!1,isCreate:!n,onActivate:()=>{O?.(),x.onSelect()}})}return r},[d,$,u,I,w,y,_,P,L,O,R,S,z,F,J]);c.useEffect(()=>m(-1),[d,u,I,w,i]),c.useEffect(()=>Q(""),[d,u,I]);const V=c.useRef({rows:s,activeIndex:A,header:f});V.current={rows:s,activeIndex:A,header:f},c.useEffect(()=>{if(j)return j(e=>{const{rows:r,activeIndex:x,header:n}=V.current;switch(e.key){case"ArrowDown":return r.length&&m(p=>(p+1)%r.length),!0;case"ArrowUp":return r.length&&m(p=>(p+r.length-1)%r.length),!0;case"ArrowRight":case"Enter":return(r[x]??r[0])?.onActivate(),!0;case"ArrowLeft":return n?.onBack?(n.onBack(),!0):!1;default:return!1}}),()=>j(null)},[j]);const K=d?s.length&&!s[0].drillsIn?"items":"sources":"categories",H=d==="tool"&&!!u||d==="subagent";return o.jsxs(le,{className:`bik-mention-picker bik-mention-picker--${K}`,children:[f&&o.jsxs(ge,{type:"button",onClick:f.onBack,disabled:!f.onBack,style:{background:a.COLORS.surface.subdued,cursor:f.onBack?"pointer":"default"},children:[f.onBack&&o.jsx(ne.default,{width:20,height:20,color:a.COLORS.content.primary}),f.icon&&v.renderSourceIcon(f.icon),o.jsxs(N.TitleSmall,{children:[" ",f.title]})]}),H&&o.jsxs(ce,{children:[o.jsx(te.default,{width:20,height:20,color:a.COLORS.content.placeholder}),o.jsx(se,{autoFocus:!0,value:w,placeholder:"Search","data-test":"mention-picker-search",onChange:e=>Q(e.target.value),onKeyDown:e=>{s.length&&(e.key==="ArrowDown"?(e.preventDefault(),m(r=>(r+1)%s.length)):e.key==="ArrowUp"?(e.preventDefault(),m(r=>(r+s.length-1)%s.length)):e.key==="Enter"&&(e.preventDefault(),(s[A]??s[0])?.onActivate()))}})]}),s.length===0?o.jsx(xe,{children:d==="subagent"?null:"No tools available"}):s.map((e,r)=>o.jsx(ue,{type:"button",$active:r===A,onMouseEnter:()=>m(r),onMouseLeave:()=>m(-1),onClick:e.onActivate,children:e.isCreate?o.jsx(he,{children:e.label}):o.jsxs(o.Fragment,{children:[o.jsxs(de,{children:[v.renderSourceIcon(e.icon),o.jsx(N.BodySecondary,{color:a.COLORS.content.primary,children:e.label}),e.authRequired&&o.jsx(Y.default,{size:14,"aria-label":"This tool requires customer verification"})]}),e.rightLabel?o.jsx(pe,{children:e.rightLabel}):e.drillsIn&&o.jsx(ee.default,{width:12,height:12})]})},e.id)),s.some(e=>e.authRequired)&&o.jsxs(fe,{children:[o.jsx(Y.default,{size:14}),o.jsx(N.BodyCaption,{color:a.COLORS.content.secondary,children:"This tool requires customer verification"})]})]})},le=h.default.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
min-width: 240px;
|
|
5
5
|
max-height: 301px;
|
|
6
6
|
overflow-y: auto;
|
|
7
|
-
background: ${
|
|
8
|
-
border: 1px solid ${
|
|
7
|
+
background: ${a.COLORS.surface.standard};
|
|
8
|
+
border: 1px solid ${a.COLORS.stroke.primary};
|
|
9
9
|
border-radius: 4px;
|
|
10
10
|
box-shadow: 0px -2px 8px 0px #0000001f;
|
|
11
|
-
`,
|
|
11
|
+
`,ce=h.default.div`
|
|
12
12
|
display: flex;
|
|
13
13
|
align-items: center;
|
|
14
14
|
gap: 8px;
|
|
15
15
|
padding: 10px 12px;
|
|
16
|
-
border-bottom: 1px solid ${
|
|
17
|
-
`,
|
|
16
|
+
border-bottom: 1px solid ${a.COLORS.stroke.primary};
|
|
17
|
+
`,se=h.default.input`
|
|
18
18
|
flex: 1;
|
|
19
19
|
min-width: 0;
|
|
20
20
|
border: none;
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
background: transparent;
|
|
23
23
|
font-family: Inter;
|
|
24
24
|
font-size: 14px;
|
|
25
|
-
color: ${
|
|
25
|
+
color: ${a.COLORS.content.primary};
|
|
26
26
|
|
|
27
27
|
&::placeholder {
|
|
28
|
-
color: ${
|
|
28
|
+
color: ${a.COLORS.content.placeholder};
|
|
29
29
|
}
|
|
30
|
-
`,
|
|
30
|
+
`,ue=h.default.button`
|
|
31
31
|
display: flex;
|
|
32
32
|
justify-content: space-between;
|
|
33
33
|
align-items: center;
|
|
@@ -36,45 +36,45 @@
|
|
|
36
36
|
padding: 8px 10px;
|
|
37
37
|
height: 48px;
|
|
38
38
|
border: none;
|
|
39
|
-
border-bottom: 1px solid ${
|
|
40
|
-
background: ${
|
|
39
|
+
border-bottom: 1px solid ${a.COLORS.stroke.primary};
|
|
40
|
+
background: ${i=>i.$active?a.COLORS.surface.subdued:"transparent"};
|
|
41
41
|
cursor: pointer;
|
|
42
42
|
text-align: left;
|
|
43
43
|
|
|
44
44
|
&:hover {
|
|
45
|
-
background: ${
|
|
45
|
+
background: ${a.COLORS.surface.hovered};
|
|
46
46
|
}
|
|
47
|
-
`,
|
|
47
|
+
`,de=h.default.div`
|
|
48
48
|
display: flex;
|
|
49
49
|
align-items: center;
|
|
50
50
|
gap: 12px;
|
|
51
51
|
min-width: 0;
|
|
52
|
-
`,
|
|
52
|
+
`,fe=h.default.div`
|
|
53
53
|
display: flex;
|
|
54
54
|
align-items: center;
|
|
55
55
|
gap: 6px;
|
|
56
56
|
padding: 8px 12px;
|
|
57
|
-
border-top: 1px solid ${
|
|
58
|
-
`,
|
|
57
|
+
border-top: 1px solid ${a.COLORS.stroke.primary};
|
|
58
|
+
`,pe=h.default.span`
|
|
59
59
|
flex-shrink: 0;
|
|
60
|
-
color: ${
|
|
60
|
+
color: ${a.COLORS.content.brand};
|
|
61
61
|
font-family: Inter;
|
|
62
62
|
font-size: 14px;
|
|
63
63
|
font-weight: 600;
|
|
64
64
|
white-space: nowrap;
|
|
65
|
-
`,
|
|
65
|
+
`,he=h.default.div`
|
|
66
66
|
width: 100%;
|
|
67
67
|
text-align: center;
|
|
68
|
-
color: ${
|
|
68
|
+
color: ${a.COLORS.content.brand};
|
|
69
69
|
font-family: Inter;
|
|
70
70
|
font-size: 14px;
|
|
71
71
|
font-weight: 600;
|
|
72
|
-
`,
|
|
72
|
+
`,ge=h.default.button`
|
|
73
73
|
display: flex;
|
|
74
74
|
align-items: center;
|
|
75
75
|
padding: 12px 16px;
|
|
76
76
|
border: none;
|
|
77
|
-
border-bottom: 1px solid ${
|
|
77
|
+
border-bottom: 1px solid ${a.COLORS.stroke.primary};
|
|
78
78
|
background: transparent;
|
|
79
79
|
cursor: pointer;
|
|
80
80
|
font-family: Inter;
|
|
@@ -82,10 +82,10 @@
|
|
|
82
82
|
font-weight: 600;
|
|
83
83
|
height: 48px;
|
|
84
84
|
gap: 4px;
|
|
85
|
-
`,
|
|
85
|
+
`,xe=h.default.div`
|
|
86
86
|
padding: 12px 10px;
|
|
87
87
|
font-family: Inter;
|
|
88
88
|
font-size: 13px;
|
|
89
|
-
color: ${
|
|
90
|
-
`;exports.MentionPicker=
|
|
89
|
+
color: ${a.COLORS.content.secondary};
|
|
90
|
+
`;exports.MentionPicker=ae;
|
|
91
91
|
//# sourceMappingURL=MentionPicker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentionPicker.js","sources":["../../../../../src/components/agent-builder/components/MentionPicker.tsx"],"sourcesContent":["// import ChevronLeft from '@src/assets/icons/chevronLeft.svg';\nimport ChevronRight from '@src/assets/icons/chevronRight.svg';\nimport SearchIcon from '@src/assets/icons/searchIcon.svg';\nimport type { MentionDropdownRenderProps, MentionItem } from '@src/editor';\nimport { Shield } from '@src/icons';\nimport SvgArrowLeft from '@src/icons/Arrows/Normal arrows/ArrowLeft';\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport {\n\tBodyCaption,\n\tBodySecondary,\n\tTitleSmall,\n} from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport {\n\tCATEGORIES,\n\tCONFIG_TOOL_SOURCES,\n\ttoolSourceRank,\n} from '../constants/tools';\nimport type { Category, ToolAction, ToolSource } from '../constants/tools';\nimport {\n\tMentionKindMeta,\n\ttoolSourceLabel,\n} from '../utils/mentionSerialization';\nimport { renderSourceIcon, sourceIcon, SourceIcon } from '../utils/sourceIcons';\n\nconst metaOf = (item: MentionItem): MentionKindMeta | undefined =>\n\titem.meta as unknown as MentionKindMeta | undefined;\n\nconst rowLabel = (item: MentionItem): string =>\n\tmetaOf(item)?.plainLabel ?? item.label;\n\n/** One navigable row in the picker's current view. */\ntype PickerRowModel = {\n\tid: string;\n\tlabel: string;\n\t/** Drill-in rows show a chevron; leaf (selectable) rows do not. */\n\tdrillsIn: boolean;\n\t/** Leading brand glyph (source rows only). */\n\ticon?: SourceIcon;\n\t/** Brand-coloured \"Create new\" action row (not a selectable item). */\n\tisCreate?: boolean;\n\t/**\n\t * Brand-coloured right-aligned action text (e.g. \"Connect\") shown in place of\n\t * the drill-in chevron — used for an unconnected integration source.\n\t */\n\trightLabel?: string;\n\t/** Tool leaf touches customer-private data → shows a shield glyph. */\n\tauthRequired?: boolean;\n\tonActivate: () => void;\n};\n\n/** Sentinel id for the sub-agent \"Create new\" row. */\nconst CREATE_SUBAGENT_ID = '__bik_create_subagent__';\n\ntype MentionPickerProps = MentionDropdownRenderProps & {\n\t/** Opens the create-sub-agent drawer (shows a \"Create new\" row in the Sub-agent view). */\n\tonCreateSubAgent?: () => void;\n\t/**\n\t * Open already drilled into this tool source (e.g. `'shopify'`) — its tool list\n\t * is shown immediately. */\n\tinitialSource?: string;\n\t/**\n\t * Built-in tool actions (Rest API / Handover to email) shown in the Tools view.\n\t * Picking one opens its config drawer (via `onSelect`) and dismisses the picker\n\t * — it never inserts a mention into the text.\n\t */\n\ttoolActions?: ToolAction[];\n\t/**\n\t * Per-source integration connection state. A source whose value is `false`\n\t * renders a \"Connect\" row (like an unconnected action) instead of drilling in —\n\t * so native source groups (Shopify / BigCommerce / ShipStation) show \"Connect\"\n\t * consistently with the config actions (Slack).\n\t */\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>;\n\t/** Open the connect flow for an unconnected source (used by the Connect row). */\n\tonConnectIntegration?: (source: ToolSource) => void;\n};\n\n/**\n * `@` reference picker. Drills:\n * root → Tools → <source> (Manifest / Shopify / …) → tool\n * → Sub-agent → sub-agent\n * (\"Add condition\" and \"Variables\" are intentionally not shown yet.)\n *\n * Owns keyboard navigation (↑/↓ move, →/Enter activate, ← go back) over the\n * CURRENTLY visible rows — registered with the editor via `registerKeyHandler`.\n */\nexport const MentionPicker: React.FC<MentionPickerProps> = ({\n\titems,\n\tonSelect,\n\tregisterKeyHandler,\n\tonClose,\n\tonCreateSubAgent,\n\tinitialSource,\n\ttoolActions,\n\tintegrationStatus,\n\tonConnectIntegration,\n}) => {\n\tconst [category, setCategory] = useState<Category | null>(null);\n\tconst [source, setSource] = useState<string | null>(initialSource ?? null);\n\t// -1 = nothing highlighted; rows highlight only on hover / arrow keys\n\t// (a default highlight reads as a stuck hover state).\n\tconst [activeIndex, setActiveIndex] = useState(-1);\n\t// Search box shown inside a source's tool list (Manifest / Shopify); filters\n\t// that source's tools by name.\n\tconst [search, setSearch] = useState('');\n\n\tconst tools = useMemo(\n\t\t() => items.filter((i) => metaOf(i)?.kind === 'tool'),\n\t\t[items],\n\t);\n\tconst subAgents = useMemo(\n\t\t() => items.filter((i) => metaOf(i)?.kind === 'subagent'),\n\t\t[items],\n\t);\n\tconst sources = useMemo(() => {\n\t\tconst acc: string[] = [];\n\t\ttools.forEach((t) => {\n\t\t\tconst s = metaOf(t)?.source ?? 'other';\n\t\t\tif (!acc.includes(s)) {\n\t\t\t\tacc.push(s);\n\t\t\t}\n\t\t});\n\t\treturn acc;\n\t}, [tools]);\n\t// The built-in \"create\" action per source (Rest API / email / Slack). A source\n\t// with an action drills into [its instances + a \"Create new\" row] — like the\n\t// Sub-agent category — instead of showing a duplicate flat \"create\" row.\n\tconst actionBySource = useMemo(\n\t\t() =>\n\t\t\tnew Map<string, ToolAction>(\n\t\t\t\t(toolActions ?? []).map((a) => [a.source, a]),\n\t\t\t),\n\t\t[toolActions],\n\t);\n\n\t// Show a category when it has items — and ALWAYS show Sub-agent when creating\n\t// one is possible, so an agent with no sub-agents yet still gets the root\n\t// \"Tools / Sub-agent\" choice (with a \"Create new\" inside). When only one is\n\t// available (e.g. the sub-agent drawer offers tools only) the selector is skipped.\n\tconst availableCategories = useMemo(\n\t\t() =>\n\t\t\tCATEGORIES.filter((c) =>\n\t\t\t\tc.key === 'tool'\n\t\t\t\t\t? tools.length > 0 || (toolActions?.length ?? 0) > 0\n\t\t\t\t\t: subAgents.length > 0 || !!onCreateSubAgent,\n\t\t\t),\n\t\t[tools.length, subAgents.length, onCreateSubAgent, toolActions?.length],\n\t);\n\tconst soleCategory =\n\t\tavailableCategories.length === 1 ? availableCategories[0].key : null;\n\tconst activeCategory = category ?? soleCategory;\n\n\t// Title shown above the current view. `onBack` is omitted at a root level (a\n\t// sole category has nowhere to go back to) — the header then shows as a plain\n\t// title. When `onBack` is set the header leads with a back arrow, followed by\n\t// the source icon in a source detail view: `[← back][icon][title]`.\n\tconst header: {\n\t\ttitle: string;\n\t\tonBack?: () => void;\n\t\ticon?: SourceIcon;\n\t} | null = !activeCategory\n\t\t? null\n\t\t: activeCategory === 'subagent'\n\t\t? // Always titled — with a back arrow only when the category chooser is above.\n\t\t {\n\t\t\t\ttitle: 'Sub-agent',\n\t\t\t\tonBack: soleCategory ? undefined : () => setCategory(null),\n\t\t }\n\t\t: source\n\t\t? {\n\t\t\t\ttitle: toolSourceLabel(source),\n\t\t\t\t// Deep-linked to a source (opened from a right-panel source button):\n\t\t\t\t// that source IS the root, so no back arrow. In the @-drill flow\n\t\t\t\t// (no initialSource) back returns to the source chooser.\n\t\t\t\tonBack: initialSource ? undefined : () => setSource(null),\n\t\t\t\ticon: sourceIcon(source),\n\t\t }\n\t\t: // Always titled — matches the Sub-agent header; back arrow only when the\n\t\t // category chooser is above (i.e. not the sole category).\n\t\t {\n\t\t\t\ttitle: 'Tools',\n\t\t\t\tonBack: soleCategory ? undefined : () => setCategory(null),\n\t\t };\n\n\t// Build the navigable rows for the current view.\n\tconst rows: PickerRowModel[] = useMemo(() => {\n\t\tif (!activeCategory) {\n\t\t\treturn availableCategories.map((c) => ({\n\t\t\t\tid: c.key,\n\t\t\t\tlabel: c.label,\n\t\t\t\tdrillsIn: true,\n\t\t\t\tonActivate: () => {\n\t\t\t\t\tsetCategory(c.key);\n\t\t\t\t\tsetSource(null);\n\t\t\t\t},\n\t\t\t}));\n\t\t}\n\t\tif (activeCategory === 'subagent') {\n\t\t\tconst sq = search.trim().toLowerCase();\n\t\t\tconst leaves: PickerRowModel[] = subAgents\n\t\t\t\t.filter((item) => !sq || rowLabel(item).toLowerCase().includes(sq))\n\t\t\t\t.map((item) => ({\n\t\t\t\t\tid: String(item.id),\n\t\t\t\t\tlabel: rowLabel(item),\n\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\tonActivate: () => onSelect(item),\n\t\t\t\t}));\n\t\t\t// \"Create new\" opens the drawer — first dismiss the menu (strips the \"@\").\n\t\t\tif (onCreateSubAgent) {\n\t\t\t\tleaves.push({\n\t\t\t\t\tid: CREATE_SUBAGENT_ID,\n\t\t\t\t\tlabel: 'Create new',\n\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\tisCreate: true,\n\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\tonClose?.();\n\t\t\t\t\t\tonCreateSubAgent();\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn leaves;\n\t\t}\n\t\tif (!source) {\n\t\t\t// One drill-in row per source: the real sources (from instances) plus any\n\t\t\t// action source (Rest API / email / Slack) with no instances yet, so it\n\t\t\t// still appears for first-time creation. Deduped — no more twin rows.\n\t\t\tconst actionOnly = (toolActions ?? [])\n\t\t\t\t.map((a) => a.source)\n\t\t\t\t.filter((s) => !sources.includes(s));\n\t\t\t// Fixed source order (manifest → shopify → rest_api → email → slack →\n\t\t\t// rest) so adding/updating a tool never reshuffles the picker rows.\n\t\t\treturn [...sources, ...actionOnly]\n\t\t\t\t.sort((a, b) => toolSourceRank(a) - toolSourceRank(b))\n\t\t\t\t.map((s) => {\n\t\t\t\t\tconst action = actionBySource.get(s);\n\t\t\t\t\t// Not connected → a \"Connect\" row (no drill-in / no instances / no\n\t\t\t\t\t// \"Create new\"); clicking dismisses the picker and runs the connect\n\t\t\t\t\t// flow. Applies to config actions (their own `connected`) AND native\n\t\t\t\t\t// source groups (via `integrationStatus`), so both look consistent.\n\t\t\t\t\tconst connected =\n\t\t\t\t\t\taction !== undefined\n\t\t\t\t\t\t\t? action.connected\n\t\t\t\t\t\t\t: integrationStatus?.[s as ToolSource];\n\t\t\t\t\tif (connected === false) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: s,\n\t\t\t\t\t\t\tlabel: toolSourceLabel(s),\n\t\t\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\t\t\ticon: sourceIcon(s) ?? action?.icon,\n\t\t\t\t\t\t\trightLabel: 'Connect',\n\t\t\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\t\t\tonClose?.();\n\t\t\t\t\t\t\t\tif (action?.onConnect) {\n\t\t\t\t\t\t\t\t\taction.onConnect();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tonConnectIntegration?.(s as ToolSource);\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}\n\t\t\t\t\t// A source whose drill-in view would hold exactly one leaf is\n\t\t\t\t\t// pointless to drill into — surface that single leaf right here at\n\t\t\t\t\t// the source level (its function name + the same source icon).\n\t\t\t\t\t// Covers \"no Rest API added yet\" (→ open the create modal directly)\n\t\t\t\t\t// and a config tool's single capability (Slack → \"Send Slack\n\t\t\t\t\t// message\", email → \"Send Email\").\n\t\t\t\t\tconst instances = tools.filter(\n\t\t\t\t\t\t(t) => (metaOf(t)?.source ?? 'other') === s,\n\t\t\t\t\t);\n\t\t\t\t\tif (instances.length + (action ? 1 : 0) === 1) {\n\t\t\t\t\t\tconst icon = sourceIcon(s) ?? action?.icon;\n\t\t\t\t\t\tif (action) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tid: s,\n\t\t\t\t\t\t\t\tlabel: action.label,\n\t\t\t\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\t\t\t\ticon,\n\t\t\t\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\t\t\t\tonClose?.();\n\t\t\t\t\t\t\t\t\taction.onSelect();\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\tconst only = instances[0];\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: String(only.id),\n\t\t\t\t\t\t\tlabel: rowLabel(only),\n\t\t\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\t\t\ticon,\n\t\t\t\t\t\t\tauthRequired: metaOf(only)?.authRequired,\n\t\t\t\t\t\t\tonActivate: () => onSelect(only),\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: s,\n\t\t\t\t\t\tlabel: toolSourceLabel(s),\n\t\t\t\t\t\tdrillsIn: true,\n\t\t\t\t\t\ticon: sourceIcon(s) ?? action?.icon,\n\t\t\t\t\t\tonActivate: () => setSource(s),\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t}\n\t\tconst q = search.trim().toLowerCase();\n\t\tconst leaves: PickerRowModel[] = tools\n\t\t\t.filter((t) => (metaOf(t)?.source ?? 'other') === source)\n\t\t\t.filter((t) => !q || rowLabel(t).toLowerCase().includes(q))\n\t\t\t.map((item) => ({\n\t\t\t\tid: String(item.id),\n\t\t\t\tlabel: rowLabel(item),\n\t\t\t\tdrillsIn: false,\n\t\t\t\tauthRequired: metaOf(item)?.authRequired,\n\t\t\t\tonActivate: () => onSelect(item),\n\t\t\t}));\n\t\t// A configurable source's add row, below any existing instances, opening\n\t\t// its drawer. Config tools (Slack / email) are a single fixed capability →\n\t\t// render like a normal tool leaf (label only, no icon — matching the tool\n\t\t// rows). Rest API instances are user-created, so its \"add\" stays a\n\t\t// brand-coloured create row.\n\t\tconst action = actionBySource.get(source);\n\t\tif (action) {\n\t\t\tconst isConfigTool = source in CONFIG_TOOL_SOURCES;\n\t\t\tleaves.push({\n\t\t\t\tid: `create:${source}`,\n\t\t\t\tlabel: action.label,\n\t\t\t\tdrillsIn: false,\n\t\t\t\tisCreate: !isConfigTool,\n\t\t\t\tonActivate: () => {\n\t\t\t\t\tonClose?.();\n\t\t\t\t\taction.onSelect();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t\treturn leaves;\n\t}, [\n\t\tactiveCategory,\n\t\tavailableCategories,\n\t\tsource,\n\t\tsearch,\n\t\ttools,\n\t\tsubAgents,\n\t\tsources,\n\t\tonSelect,\n\t\tonClose,\n\t\tonCreateSubAgent,\n\t\ttoolActions,\n\t\tactionBySource,\n\t\tintegrationStatus,\n\t\tonConnectIntegration,\n\t]);\n\n\t// Reset highlight whenever the view (or filtered result set) changes.\n\tuseEffect(() => setActiveIndex(-1), [activeCategory, source, search, items]);\n\t// Clear the search box when leaving a source view.\n\tuseEffect(() => setSearch(''), [activeCategory, source]);\n\n\t// Keep the latest rows/index reachable from the stable key handler.\n\tconst navRef = useRef({ rows, activeIndex, header });\n\tnavRef.current = { rows, activeIndex, header };\n\n\tuseEffect(() => {\n\t\tif (!registerKeyHandler) {\n\t\t\treturn;\n\t\t}\n\t\tregisterKeyHandler((event) => {\n\t\t\tconst { rows: r, activeIndex: i, header: h } = navRef.current;\n\t\t\tswitch (event.key) {\n\t\t\t\tcase 'ArrowDown':\n\t\t\t\t\tif (r.length) setActiveIndex((p) => (p + 1) % r.length);\n\t\t\t\t\treturn true;\n\t\t\t\tcase 'ArrowUp':\n\t\t\t\t\tif (r.length) setActiveIndex((p) => (p + r.length - 1) % r.length);\n\t\t\t\t\treturn true;\n\t\t\t\tcase 'ArrowRight':\n\t\t\t\tcase 'Enter':\n\t\t\t\t\t// Nothing highlighted yet → treat the first row as the target so\n\t\t\t\t\t// the editor's @-flow (type, then Enter) still works.\n\t\t\t\t\t(r[i] ?? r[0])?.onActivate();\n\t\t\t\t\treturn true;\n\t\t\t\tcase 'ArrowLeft':\n\t\t\t\t\tif (h?.onBack) {\n\t\t\t\t\t\th.onBack();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn () => registerKeyHandler(null);\n\t}, [registerKeyHandler]);\n\n\tconst variant = !activeCategory\n\t\t? 'categories'\n\t\t: rows.length && !rows[0].drillsIn\n\t\t? 'items'\n\t\t: 'sources';\n\n\t// Search lives inside a source's tool list (Manifest / Shopify) and in the\n\t// sub-agent list.\n\tconst showSearch =\n\t\t(activeCategory === 'tool' && !!source) || activeCategory === 'subagent';\n\n\treturn (\n\t\t<PickerCard className={`bik-mention-picker bik-mention-picker--${variant}`}>\n\t\t\t{header && (\n\t\t\t\t<PickerBack\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={header.onBack}\n\t\t\t\t\tdisabled={!header.onBack}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackground: COLORS.surface.subdued,\n\t\t\t\t\t\tcursor: header.onBack ? 'pointer' : 'default',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{header.onBack && (\n\t\t\t\t\t\t<SvgArrowLeft\n\t\t\t\t\t\t\twidth={20}\n\t\t\t\t\t\t\theight={20}\n\t\t\t\t\t\t\tcolor={COLORS.content.primary}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{header.icon && renderSourceIcon(header.icon)}\n\t\t\t\t\t<TitleSmall> {header.title}</TitleSmall>\n\t\t\t\t</PickerBack>\n\t\t\t)}\n\t\t\t{showSearch && (\n\t\t\t\t<PickerSearchRow>\n\t\t\t\t\t<SearchIcon\n\t\t\t\t\t\twidth={20}\n\t\t\t\t\t\theight={20}\n\t\t\t\t\t\tcolor={COLORS.content.placeholder}\n\t\t\t\t\t/>\n\t\t\t\t\t<PickerSearchInput\n\t\t\t\t\t\t// Focus on open so the user can type immediately (appears only\n\t\t\t\t\t\t// after they drill into a source).\n\t\t\t\t\t\t// eslint-disable-next-line jsx-a11y/no-autofocus\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\tvalue={search}\n\t\t\t\t\t\tplaceholder=\"Search\"\n\t\t\t\t\t\tdata-test=\"mention-picker-search\"\n\t\t\t\t\t\tonChange={(e) => setSearch(e.target.value)}\n\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\tif (!rows.length) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (e.key === 'ArrowDown') {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tsetActiveIndex((p) => (p + 1) % rows.length);\n\t\t\t\t\t\t\t} else if (e.key === 'ArrowUp') {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tsetActiveIndex((p) => (p + rows.length - 1) % rows.length);\n\t\t\t\t\t\t\t} else if (e.key === 'Enter') {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t(rows[activeIndex] ?? rows[0])?.onActivate();\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</PickerSearchRow>\n\t\t\t)}\n\t\t\t{rows.length === 0 ? (\n\t\t\t\t<PickerEmpty>\n\t\t\t\t\t{activeCategory === 'subagent' ? null : 'No tools available'}\n\t\t\t\t</PickerEmpty>\n\t\t\t) : (\n\t\t\t\trows.map((row, i) => (\n\t\t\t\t\t<PickerRow\n\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t$active={i === activeIndex}\n\t\t\t\t\t\tonMouseEnter={() => setActiveIndex(i)}\n\t\t\t\t\t\tonMouseLeave={() => setActiveIndex(-1)}\n\t\t\t\t\t\tonClick={row.onActivate}\n\t\t\t\t\t>\n\t\t\t\t\t\t{row.isCreate ? (\n\t\t\t\t\t\t\t<CreateRowText>{row.label}</CreateRowText>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<PickerRowMain>\n\t\t\t\t\t\t\t\t\t{renderSourceIcon(row.icon)}\n\t\t\t\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\t\t\t{row.label}\n\t\t\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t\t\t\t{row.authRequired && (\n\t\t\t\t\t\t\t\t\t\t<Shield\n\t\t\t\t\t\t\t\t\t\t\tsize={14}\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"This tool requires customer verification\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</PickerRowMain>\n\t\t\t\t\t\t\t\t{row.rightLabel ? (\n\t\t\t\t\t\t\t\t\t<RightActionText>{row.rightLabel}</RightActionText>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\trow.drillsIn && <ChevronRight width={12} height={12} />\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</PickerRow>\n\t\t\t\t))\n\t\t\t)}\n\t\t\t{rows.some((row) => row.authRequired) && (\n\t\t\t\t<PickerLegend>\n\t\t\t\t\t<Shield size={14} />\n\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\tThis tool requires customer verification\n\t\t\t\t\t</BodyCaption>\n\t\t\t\t</PickerLegend>\n\t\t\t)}\n\t\t</PickerCard>\n\t);\n};\n\nconst PickerCard = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 240px;\n\tmax-height: 301px;\n\toverflow-y: auto;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tbox-shadow: 0px -2px 8px 0px #0000001f;\n`;\n\n// Search box at the top of a source's tool list (Manifest / Shopify).\nconst PickerSearchRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 10px 12px;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n`;\n\nconst PickerSearchInput = styled.input`\n\tflex: 1;\n\tmin-width: 0;\n\tborder: none;\n\toutline: none;\n\tbackground: transparent;\n\tfont-family: Inter;\n\tfont-size: 14px;\n\tcolor: ${COLORS.content.primary};\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.placeholder};\n\t}\n`;\n\nconst PickerRow = styled.button<{ $active?: boolean }>`\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tgap: 2px;\n\twidth: 100%;\n\tpadding: 8px 10px;\n\theight: 48px;\n\tborder: none;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n\tbackground: ${(p) => (p.$active ? COLORS.surface.subdued : 'transparent')};\n\tcursor: pointer;\n\ttext-align: left;\n\n\t&:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t}\n`;\n\n// Left cluster: leading source glyph + label (chevron stays right via PickerRow).\nconst PickerRowMain = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 12px;\n\tmin-width: 0;\n`;\n\n// Footer legend, shown when the list holds any auth-required tool.\nconst PickerLegend = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 8px 12px;\n\tborder-top: 1px solid ${COLORS.stroke.primary};\n`;\n\n// Right-aligned brand action text (e.g. \"Connect\") in place of the chevron.\nconst RightActionText = styled.span`\n\tflex-shrink: 0;\n\tcolor: ${COLORS.content.brand};\n\tfont-family: Inter;\n\tfont-size: 14px;\n\tfont-weight: 600;\n\twhite-space: nowrap;\n`;\n\n// \"Create new\" — centered brand text, no icon (matches the side-panel dropdown).\nconst CreateRowText = styled.div`\n\twidth: 100%;\n\ttext-align: center;\n\tcolor: ${COLORS.content.brand};\n\tfont-family: Inter;\n\tfont-size: 14px;\n\tfont-weight: 600;\n`;\n\nconst PickerBack = styled.button`\n\tdisplay: flex;\n\talign-items: center;\n\tpadding: 12px 16px;\n\tborder: none;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n\tbackground: transparent;\n\tcursor: pointer;\n\tfont-family: Inter;\n\tfont-size: 12px;\n\tfont-weight: 600;\n\theight: 48px;\n\tgap: 4px;\n`;\n\nconst PickerEmpty = styled.div`\n\tpadding: 12px 10px;\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tcolor: ${COLORS.content.secondary};\n`;\n"],"names":["metaOf","item","rowLabel","CREATE_SUBAGENT_ID","MentionPicker","items","onSelect","registerKeyHandler","onClose","onCreateSubAgent","initialSource","toolActions","integrationStatus","onConnectIntegration","category","setCategory","useState","source","setSource","activeIndex","setActiveIndex","search","setSearch","tools","useMemo","i","subAgents","sources","acc","t","s","actionBySource","a","availableCategories","CATEGORIES","c","soleCategory","activeCategory","header","toolSourceLabel","sourceIcon","rows","sq","leaves","actionOnly","b","toolSourceRank","action","instances","icon","only","q","isConfigTool","CONFIG_TOOL_SOURCES","useEffect","navRef","useRef","event","h","p","variant","showSearch","jsxs","PickerCard","PickerBack","COLORS","jsx","SvgArrowLeft","renderSourceIcon","TitleSmall","PickerSearchRow","SearchIcon","PickerSearchInput","PickerEmpty","row","PickerRow","CreateRowText","Fragment","PickerRowMain","BodySecondary","Shield","RightActionText","ChevronRight","PickerLegend","BodyCaption","styled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MentionPicker.js","sources":["../../../../../src/components/agent-builder/components/MentionPicker.tsx"],"sourcesContent":["// import ChevronLeft from '@src/assets/icons/chevronLeft.svg';\nimport ChevronRight from '@src/assets/icons/chevronRight.svg';\nimport SearchIcon from '@src/assets/icons/searchIcon.svg';\nimport type { MentionDropdownRenderProps, MentionItem } from '@src/editor';\nimport { Shield } from '@src/icons';\nimport SvgArrowLeft from '@src/icons/Arrows/Normal arrows/ArrowLeft';\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport {\n\tBodyCaption,\n\tBodySecondary,\n\tTitleSmall,\n} from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport {\n\tCATEGORIES,\n\tCONFIG_TOOL_SOURCES,\n\tINTEGRATIONS_RANK,\n\tisIntegrationSource,\n\ttoolSourceRank,\n} from '../constants/tools';\nimport type { Category, ToolAction, ToolSource } from '../constants/tools';\nimport {\n\tMentionKindMeta,\n\ttoolSourceLabel,\n} from '../utils/mentionSerialization';\nimport { renderSourceIcon, sourceIcon, SourceIcon } from '../utils/sourceIcons';\n\nconst metaOf = (item: MentionItem): MentionKindMeta | undefined =>\n\titem.meta as unknown as MentionKindMeta | undefined;\n\nconst rowLabel = (item: MentionItem): string =>\n\tmetaOf(item)?.plainLabel ?? item.label;\n\n/** One navigable row in the picker's current view. */\ntype PickerRowModel = {\n\tid: string;\n\tlabel: string;\n\t/** Drill-in rows show a chevron; leaf (selectable) rows do not. */\n\tdrillsIn: boolean;\n\t/** Leading brand glyph (source rows only). */\n\ticon?: SourceIcon;\n\t/** Brand-coloured \"Create new\" action row (not a selectable item). */\n\tisCreate?: boolean;\n\t/**\n\t * Brand-coloured right-aligned action text (e.g. \"Connect\") shown in place of\n\t * the drill-in chevron — used for an unconnected integration source.\n\t */\n\trightLabel?: string;\n\t/** Tool leaf touches customer-private data → shows a shield glyph. */\n\tauthRequired?: boolean;\n\tonActivate: () => void;\n};\n\n/** Sentinel id for the sub-agent \"Create new\" row. */\nconst CREATE_SUBAGENT_ID = '__bik_create_subagent__';\n\ntype MentionPickerProps = MentionDropdownRenderProps & {\n\t/** Opens the create-sub-agent drawer (shows a \"Create new\" row in the Sub-agent view). */\n\tonCreateSubAgent?: () => void;\n\t/**\n\t * Open already drilled into this tool source (e.g. `'shopify'`) — its tool list\n\t * is shown immediately. */\n\tinitialSource?: string;\n\t/**\n\t * Built-in tool actions (Rest API / Handover to email) shown in the Tools view.\n\t * Picking one opens its config drawer (via `onSelect`) and dismisses the picker\n\t * — it never inserts a mention into the text.\n\t */\n\ttoolActions?: ToolAction[];\n\t/**\n\t * Per-source integration connection state. A source whose value is `false`\n\t * renders a \"Connect\" row (like an unconnected action) instead of drilling in —\n\t * so native source groups (Shopify / BigCommerce / ShipStation) show \"Connect\"\n\t * consistently with the config actions (Slack).\n\t */\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>;\n\t/** Open the connect flow for an unconnected source (used by the Connect row). */\n\tonConnectIntegration?: (source: ToolSource) => void;\n};\n\n/**\n * `@` reference picker. Drills:\n * root → Tools → <source> (Manifest / Shopify / …) → tool\n * → Sub-agent → sub-agent\n * (\"Add condition\" and \"Variables\" are intentionally not shown yet.)\n *\n * Owns keyboard navigation (↑/↓ move, →/Enter activate, ← go back) over the\n * CURRENTLY visible rows — registered with the editor via `registerKeyHandler`.\n */\nexport const MentionPicker: React.FC<MentionPickerProps> = ({\n\titems,\n\tonSelect,\n\tregisterKeyHandler,\n\tonClose,\n\tonCreateSubAgent,\n\tinitialSource,\n\ttoolActions,\n\tintegrationStatus,\n\tonConnectIntegration,\n}) => {\n\tconst [category, setCategory] = useState<Category | null>(null);\n\tconst [source, setSource] = useState<string | null>(initialSource ?? null);\n\t// Non-null when drilled into the consolidated \"Integrations\" group (its member\n\t// sources are shown; picking one drills into that source's tools as usual).\n\tconst [group, setGroup] = useState<'integrations' | null>(null);\n\t// -1 = nothing highlighted; rows highlight only on hover / arrow keys\n\t// (a default highlight reads as a stuck hover state).\n\tconst [activeIndex, setActiveIndex] = useState(-1);\n\t// Search box shown inside a source's tool list (Manifest / Shopify); filters\n\t// that source's tools by name.\n\tconst [search, setSearch] = useState('');\n\n\tconst tools = useMemo(\n\t\t() => items.filter((i) => metaOf(i)?.kind === 'tool'),\n\t\t[items],\n\t);\n\tconst subAgents = useMemo(\n\t\t() => items.filter((i) => metaOf(i)?.kind === 'subagent'),\n\t\t[items],\n\t);\n\tconst sources = useMemo(() => {\n\t\tconst acc: string[] = [];\n\t\ttools.forEach((t) => {\n\t\t\tconst s = metaOf(t)?.source ?? 'other';\n\t\t\tif (!acc.includes(s)) {\n\t\t\t\tacc.push(s);\n\t\t\t}\n\t\t});\n\t\treturn acc;\n\t}, [tools]);\n\t// The built-in \"create\" action per source (Rest API / email / Slack). A source\n\t// with an action drills into [its instances + a \"Create new\" row] — like the\n\t// Sub-agent category — instead of showing a duplicate flat \"create\" row.\n\tconst actionBySource = useMemo(\n\t\t() =>\n\t\t\tnew Map<string, ToolAction>(\n\t\t\t\t(toolActions ?? []).map((a) => [a.source, a]),\n\t\t\t),\n\t\t[toolActions],\n\t);\n\n\t// Show a category when it has items — and ALWAYS show Sub-agent when creating\n\t// one is possible, so an agent with no sub-agents yet still gets the root\n\t// \"Tools / Sub-agent\" choice (with a \"Create new\" inside). When only one is\n\t// available (e.g. the sub-agent drawer offers tools only) the selector is skipped.\n\tconst availableCategories = useMemo(\n\t\t() =>\n\t\t\tCATEGORIES.filter((c) =>\n\t\t\t\tc.key === 'tool'\n\t\t\t\t\t? tools.length > 0 || (toolActions?.length ?? 0) > 0\n\t\t\t\t\t: subAgents.length > 0 || !!onCreateSubAgent,\n\t\t\t),\n\t\t[tools.length, subAgents.length, onCreateSubAgent, toolActions?.length],\n\t);\n\tconst soleCategory =\n\t\tavailableCategories.length === 1 ? availableCategories[0].key : null;\n\tconst activeCategory = category ?? soleCategory;\n\n\t// Title shown above the current view. `onBack` is omitted at a root level (a\n\t// sole category has nowhere to go back to) — the header then shows as a plain\n\t// title. When `onBack` is set the header leads with a back arrow, followed by\n\t// the source icon in a source detail view: `[← back][icon][title]`.\n\tconst header: {\n\t\ttitle: string;\n\t\tonBack?: () => void;\n\t\ticon?: SourceIcon;\n\t} | null = !activeCategory\n\t\t? null\n\t\t: activeCategory === 'subagent'\n\t\t? // Always titled — with a back arrow only when the category chooser is above.\n\t\t {\n\t\t\t\ttitle: 'Sub-agent',\n\t\t\t\tonBack: soleCategory ? undefined : () => setCategory(null),\n\t\t }\n\t\t: source\n\t\t? {\n\t\t\t\ttitle: toolSourceLabel(source),\n\t\t\t\t// Deep-linked to a source (opened from a right-panel source button):\n\t\t\t\t// that source IS the root, so no back arrow. Otherwise back clears the\n\t\t\t\t// source — returning to the Integrations group if we came via it (its\n\t\t\t\t// `group` state is untouched), else to the source chooser.\n\t\t\t\tonBack: initialSource ? undefined : () => setSource(null),\n\t\t\t\ticon: sourceIcon(source),\n\t\t }\n\t\t: group === 'integrations'\n\t\t? { title: 'Integrations', onBack: () => setGroup(null) }\n\t\t: // Always titled — matches the Sub-agent header; back arrow only when the\n\t\t // category chooser is above (i.e. not the sole category).\n\t\t {\n\t\t\t\ttitle: 'Tools',\n\t\t\t\tonBack: soleCategory ? undefined : () => setCategory(null),\n\t\t };\n\n\t// Build the navigable rows for the current view.\n\tconst rows: PickerRowModel[] = useMemo(() => {\n\t\tif (!activeCategory) {\n\t\t\treturn availableCategories.map((c) => ({\n\t\t\t\tid: c.key,\n\t\t\t\tlabel: c.label,\n\t\t\t\tdrillsIn: true,\n\t\t\t\tonActivate: () => {\n\t\t\t\t\tsetCategory(c.key);\n\t\t\t\t\tsetSource(null);\n\t\t\t\t\tsetGroup(null);\n\t\t\t\t},\n\t\t\t}));\n\t\t}\n\t\tif (activeCategory === 'subagent') {\n\t\t\tconst sq = search.trim().toLowerCase();\n\t\t\tconst leaves: PickerRowModel[] = subAgents\n\t\t\t\t.filter((item) => !sq || rowLabel(item).toLowerCase().includes(sq))\n\t\t\t\t.map((item) => ({\n\t\t\t\t\tid: String(item.id),\n\t\t\t\t\tlabel: rowLabel(item),\n\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\tonActivate: () => onSelect(item),\n\t\t\t\t}));\n\t\t\t// \"Create new\" opens the drawer — first dismiss the menu (strips the \"@\").\n\t\t\tif (onCreateSubAgent) {\n\t\t\t\tleaves.push({\n\t\t\t\t\tid: CREATE_SUBAGENT_ID,\n\t\t\t\t\tlabel: 'Create new',\n\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\tisCreate: true,\n\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\tonClose?.();\n\t\t\t\t\t\tonCreateSubAgent();\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn leaves;\n\t\t}\n\t\tif (!source) {\n\t\t\t// The real sources (from instances) plus any action source (Rest API /\n\t\t\t// email / Slack) with no instances yet, so it still appears for first-time\n\t\t\t// creation. Deduped — no more twin rows.\n\t\t\tconst actionOnly = (toolActions ?? [])\n\t\t\t\t.map((a) => a.source)\n\t\t\t\t.filter((s) => !sources.includes(s));\n\t\t\tconst combined = [...sources, ...actionOnly];\n\n\t\t\t// One drill-in row per source: Connect (unconnected) / a single collapsed\n\t\t\t// leaf / a drill-in. Reused at the top level AND inside the Integrations\n\t\t\t// group so both behave identically.\n\t\t\tconst buildSourceRow = (s: string): PickerRowModel => {\n\t\t\t\tconst action = actionBySource.get(s);\n\t\t\t\t// Not connected → a \"Connect\" row (no drill-in / no instances / no\n\t\t\t\t// \"Create new\"); clicking dismisses the picker and runs the connect\n\t\t\t\t// flow. Applies to config actions (their own `connected`) AND native\n\t\t\t\t// source groups (via `integrationStatus`), so both look consistent.\n\t\t\t\tconst connected =\n\t\t\t\t\taction !== undefined\n\t\t\t\t\t\t? action.connected\n\t\t\t\t\t\t: integrationStatus?.[s as ToolSource];\n\t\t\t\tif (connected === false) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: s,\n\t\t\t\t\t\tlabel: toolSourceLabel(s),\n\t\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\t\ticon: sourceIcon(s) ?? action?.icon,\n\t\t\t\t\t\trightLabel: 'Connect',\n\t\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\t\tonClose?.();\n\t\t\t\t\t\t\tif (action?.onConnect) {\n\t\t\t\t\t\t\t\taction.onConnect();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tonConnectIntegration?.(s as ToolSource);\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}\n\t\t\t\t// A source whose drill-in view would hold exactly one leaf is pointless\n\t\t\t\t// to drill into — surface that single leaf right here (its function name\n\t\t\t\t// + the same source icon). Covers \"no Rest API added yet\" (→ open the\n\t\t\t\t// create modal directly) and a config tool's single capability (Slack →\n\t\t\t\t// \"Send Slack message\", email → \"Send email\").\n\t\t\t\tconst instances = tools.filter(\n\t\t\t\t\t(t) => (metaOf(t)?.source ?? 'other') === s,\n\t\t\t\t);\n\t\t\t\tif (instances.length + (action ? 1 : 0) === 1) {\n\t\t\t\t\tconst icon = sourceIcon(s) ?? action?.icon;\n\t\t\t\t\tif (action) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: s,\n\t\t\t\t\t\t\tlabel: action.label,\n\t\t\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\t\t\ticon,\n\t\t\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\t\t\tonClose?.();\n\t\t\t\t\t\t\t\taction.onSelect();\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\tconst only = instances[0];\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: String(only.id),\n\t\t\t\t\t\tlabel: rowLabel(only),\n\t\t\t\t\t\tdrillsIn: false,\n\t\t\t\t\t\ticon,\n\t\t\t\t\t\tauthRequired: metaOf(only)?.authRequired,\n\t\t\t\t\t\tonActivate: () => onSelect(only),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tid: s,\n\t\t\t\t\tlabel: toolSourceLabel(s),\n\t\t\t\t\tdrillsIn: true,\n\t\t\t\t\ticon: sourceIcon(s) ?? action?.icon,\n\t\t\t\t\tonActivate: () => setSource(s),\n\t\t\t\t};\n\t\t\t};\n\n\t\t\t// Inside the Integrations group: just its member sources, ranked.\n\t\t\tif (group === 'integrations') {\n\t\t\t\treturn combined\n\t\t\t\t\t.filter(isIntegrationSource)\n\t\t\t\t\t.sort((a, b) => toolSourceRank(a) - toolSourceRank(b))\n\t\t\t\t\t.map(buildSourceRow);\n\t\t\t}\n\n\t\t\t// Top level: non-integration sources as their own rows, plus ONE\n\t\t\t// \"Integrations\" drill-in row (only when a member exists). Fixed rank order\n\t\t\t// so adding/updating a tool never reshuffles the picker rows.\n\t\t\tconst topRows = combined\n\t\t\t\t.filter((s) => !isIntegrationSource(s))\n\t\t\t\t.map((s) => ({ rank: toolSourceRank(s), row: buildSourceRow(s) }));\n\t\t\tif (combined.some(isIntegrationSource)) {\n\t\t\t\ttopRows.push({\n\t\t\t\t\trank: INTEGRATIONS_RANK,\n\t\t\t\t\trow: {\n\t\t\t\t\t\tid: '__integrations__',\n\t\t\t\t\t\tlabel: 'Integrations',\n\t\t\t\t\t\tdrillsIn: true,\n\t\t\t\t\t\tonActivate: () => {\n\t\t\t\t\t\t\tsetGroup('integrations');\n\t\t\t\t\t\t\tsetSource(null);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn topRows.sort((a, b) => a.rank - b.rank).map((x) => x.row);\n\t\t}\n\t\tconst q = search.trim().toLowerCase();\n\t\tconst leaves: PickerRowModel[] = tools\n\t\t\t.filter((t) => (metaOf(t)?.source ?? 'other') === source)\n\t\t\t.filter((t) => !q || rowLabel(t).toLowerCase().includes(q))\n\t\t\t.map((item) => ({\n\t\t\t\tid: String(item.id),\n\t\t\t\tlabel: rowLabel(item),\n\t\t\t\tdrillsIn: false,\n\t\t\t\tauthRequired: metaOf(item)?.authRequired,\n\t\t\t\tonActivate: () => onSelect(item),\n\t\t\t}));\n\t\t// A configurable source's add row, below any existing instances, opening\n\t\t// its drawer. Config tools (Slack / email) are a single fixed capability →\n\t\t// render like a normal tool leaf (label only, no icon — matching the tool\n\t\t// rows). Rest API instances are user-created, so its \"add\" stays a\n\t\t// brand-coloured create row.\n\t\tconst action = actionBySource.get(source);\n\t\tif (action) {\n\t\t\tconst isConfigTool = source in CONFIG_TOOL_SOURCES;\n\t\t\tleaves.push({\n\t\t\t\tid: `create:${source}`,\n\t\t\t\tlabel: action.label,\n\t\t\t\tdrillsIn: false,\n\t\t\t\tisCreate: !isConfigTool,\n\t\t\t\tonActivate: () => {\n\t\t\t\t\tonClose?.();\n\t\t\t\t\taction.onSelect();\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t\treturn leaves;\n\t}, [\n\t\tactiveCategory,\n\t\tavailableCategories,\n\t\tsource,\n\t\tgroup,\n\t\tsearch,\n\t\ttools,\n\t\tsubAgents,\n\t\tsources,\n\t\tonSelect,\n\t\tonClose,\n\t\tonCreateSubAgent,\n\t\ttoolActions,\n\t\tactionBySource,\n\t\tintegrationStatus,\n\t\tonConnectIntegration,\n\t]);\n\n\t// Reset highlight whenever the view (or filtered result set) changes.\n\tuseEffect(\n\t\t() => setActiveIndex(-1),\n\t\t[activeCategory, source, group, search, items],\n\t);\n\t// Clear the search box when leaving a source view.\n\tuseEffect(() => setSearch(''), [activeCategory, source, group]);\n\n\t// Keep the latest rows/index reachable from the stable key handler.\n\tconst navRef = useRef({ rows, activeIndex, header });\n\tnavRef.current = { rows, activeIndex, header };\n\n\tuseEffect(() => {\n\t\tif (!registerKeyHandler) {\n\t\t\treturn;\n\t\t}\n\t\tregisterKeyHandler((event) => {\n\t\t\tconst { rows: r, activeIndex: i, header: h } = navRef.current;\n\t\t\tswitch (event.key) {\n\t\t\t\tcase 'ArrowDown':\n\t\t\t\t\tif (r.length) setActiveIndex((p) => (p + 1) % r.length);\n\t\t\t\t\treturn true;\n\t\t\t\tcase 'ArrowUp':\n\t\t\t\t\tif (r.length) setActiveIndex((p) => (p + r.length - 1) % r.length);\n\t\t\t\t\treturn true;\n\t\t\t\tcase 'ArrowRight':\n\t\t\t\tcase 'Enter':\n\t\t\t\t\t// Nothing highlighted yet → treat the first row as the target so\n\t\t\t\t\t// the editor's @-flow (type, then Enter) still works.\n\t\t\t\t\t(r[i] ?? r[0])?.onActivate();\n\t\t\t\t\treturn true;\n\t\t\t\tcase 'ArrowLeft':\n\t\t\t\t\tif (h?.onBack) {\n\t\t\t\t\t\th.onBack();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn () => registerKeyHandler(null);\n\t}, [registerKeyHandler]);\n\n\tconst variant = !activeCategory\n\t\t? 'categories'\n\t\t: rows.length && !rows[0].drillsIn\n\t\t? 'items'\n\t\t: 'sources';\n\n\t// Search lives inside a source's tool list (Manifest / Shopify) and in the\n\t// sub-agent list.\n\tconst showSearch =\n\t\t(activeCategory === 'tool' && !!source) || activeCategory === 'subagent';\n\n\treturn (\n\t\t<PickerCard className={`bik-mention-picker bik-mention-picker--${variant}`}>\n\t\t\t{header && (\n\t\t\t\t<PickerBack\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={header.onBack}\n\t\t\t\t\tdisabled={!header.onBack}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackground: COLORS.surface.subdued,\n\t\t\t\t\t\tcursor: header.onBack ? 'pointer' : 'default',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{header.onBack && (\n\t\t\t\t\t\t<SvgArrowLeft\n\t\t\t\t\t\t\twidth={20}\n\t\t\t\t\t\t\theight={20}\n\t\t\t\t\t\t\tcolor={COLORS.content.primary}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{header.icon && renderSourceIcon(header.icon)}\n\t\t\t\t\t<TitleSmall> {header.title}</TitleSmall>\n\t\t\t\t</PickerBack>\n\t\t\t)}\n\t\t\t{showSearch && (\n\t\t\t\t<PickerSearchRow>\n\t\t\t\t\t<SearchIcon\n\t\t\t\t\t\twidth={20}\n\t\t\t\t\t\theight={20}\n\t\t\t\t\t\tcolor={COLORS.content.placeholder}\n\t\t\t\t\t/>\n\t\t\t\t\t<PickerSearchInput\n\t\t\t\t\t\t// Focus on open so the user can type immediately (appears only\n\t\t\t\t\t\t// after they drill into a source).\n\t\t\t\t\t\t// eslint-disable-next-line jsx-a11y/no-autofocus\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\tvalue={search}\n\t\t\t\t\t\tplaceholder=\"Search\"\n\t\t\t\t\t\tdata-test=\"mention-picker-search\"\n\t\t\t\t\t\tonChange={(e) => setSearch(e.target.value)}\n\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\tif (!rows.length) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (e.key === 'ArrowDown') {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tsetActiveIndex((p) => (p + 1) % rows.length);\n\t\t\t\t\t\t\t} else if (e.key === 'ArrowUp') {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tsetActiveIndex((p) => (p + rows.length - 1) % rows.length);\n\t\t\t\t\t\t\t} else if (e.key === 'Enter') {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t(rows[activeIndex] ?? rows[0])?.onActivate();\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</PickerSearchRow>\n\t\t\t)}\n\t\t\t{rows.length === 0 ? (\n\t\t\t\t<PickerEmpty>\n\t\t\t\t\t{activeCategory === 'subagent' ? null : 'No tools available'}\n\t\t\t\t</PickerEmpty>\n\t\t\t) : (\n\t\t\t\trows.map((row, i) => (\n\t\t\t\t\t<PickerRow\n\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t$active={i === activeIndex}\n\t\t\t\t\t\tonMouseEnter={() => setActiveIndex(i)}\n\t\t\t\t\t\tonMouseLeave={() => setActiveIndex(-1)}\n\t\t\t\t\t\tonClick={row.onActivate}\n\t\t\t\t\t>\n\t\t\t\t\t\t{row.isCreate ? (\n\t\t\t\t\t\t\t<CreateRowText>{row.label}</CreateRowText>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<PickerRowMain>\n\t\t\t\t\t\t\t\t\t{renderSourceIcon(row.icon)}\n\t\t\t\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\t\t\t{row.label}\n\t\t\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t\t\t\t{row.authRequired && (\n\t\t\t\t\t\t\t\t\t\t<Shield\n\t\t\t\t\t\t\t\t\t\t\tsize={14}\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"This tool requires customer verification\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</PickerRowMain>\n\t\t\t\t\t\t\t\t{row.rightLabel ? (\n\t\t\t\t\t\t\t\t\t<RightActionText>{row.rightLabel}</RightActionText>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\trow.drillsIn && <ChevronRight width={12} height={12} />\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</PickerRow>\n\t\t\t\t))\n\t\t\t)}\n\t\t\t{rows.some((row) => row.authRequired) && (\n\t\t\t\t<PickerLegend>\n\t\t\t\t\t<Shield size={14} />\n\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\tThis tool requires customer verification\n\t\t\t\t\t</BodyCaption>\n\t\t\t\t</PickerLegend>\n\t\t\t)}\n\t\t</PickerCard>\n\t);\n};\n\nconst PickerCard = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 240px;\n\tmax-height: 301px;\n\toverflow-y: auto;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tbox-shadow: 0px -2px 8px 0px #0000001f;\n`;\n\n// Search box at the top of a source's tool list (Manifest / Shopify).\nconst PickerSearchRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 10px 12px;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n`;\n\nconst PickerSearchInput = styled.input`\n\tflex: 1;\n\tmin-width: 0;\n\tborder: none;\n\toutline: none;\n\tbackground: transparent;\n\tfont-family: Inter;\n\tfont-size: 14px;\n\tcolor: ${COLORS.content.primary};\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.placeholder};\n\t}\n`;\n\nconst PickerRow = styled.button<{ $active?: boolean }>`\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tgap: 2px;\n\twidth: 100%;\n\tpadding: 8px 10px;\n\theight: 48px;\n\tborder: none;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n\tbackground: ${(p) => (p.$active ? COLORS.surface.subdued : 'transparent')};\n\tcursor: pointer;\n\ttext-align: left;\n\n\t&:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t}\n`;\n\n// Left cluster: leading source glyph + label (chevron stays right via PickerRow).\nconst PickerRowMain = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 12px;\n\tmin-width: 0;\n`;\n\n// Footer legend, shown when the list holds any auth-required tool.\nconst PickerLegend = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 8px 12px;\n\tborder-top: 1px solid ${COLORS.stroke.primary};\n`;\n\n// Right-aligned brand action text (e.g. \"Connect\") in place of the chevron.\nconst RightActionText = styled.span`\n\tflex-shrink: 0;\n\tcolor: ${COLORS.content.brand};\n\tfont-family: Inter;\n\tfont-size: 14px;\n\tfont-weight: 600;\n\twhite-space: nowrap;\n`;\n\n// \"Create new\" — centered brand text, no icon (matches the side-panel dropdown).\nconst CreateRowText = styled.div`\n\twidth: 100%;\n\ttext-align: center;\n\tcolor: ${COLORS.content.brand};\n\tfont-family: Inter;\n\tfont-size: 14px;\n\tfont-weight: 600;\n`;\n\nconst PickerBack = styled.button`\n\tdisplay: flex;\n\talign-items: center;\n\tpadding: 12px 16px;\n\tborder: none;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n\tbackground: transparent;\n\tcursor: pointer;\n\tfont-family: Inter;\n\tfont-size: 12px;\n\tfont-weight: 600;\n\theight: 48px;\n\tgap: 4px;\n`;\n\nconst PickerEmpty = styled.div`\n\tpadding: 12px 10px;\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tcolor: ${COLORS.content.secondary};\n`;\n"],"names":["metaOf","item","rowLabel","CREATE_SUBAGENT_ID","MentionPicker","items","onSelect","registerKeyHandler","onClose","onCreateSubAgent","initialSource","toolActions","integrationStatus","onConnectIntegration","category","setCategory","useState","source","setSource","group","setGroup","activeIndex","setActiveIndex","search","setSearch","tools","useMemo","i","subAgents","sources","acc","t","s","actionBySource","a","availableCategories","CATEGORIES","c","soleCategory","activeCategory","header","toolSourceLabel","sourceIcon","rows","sq","leaves","actionOnly","combined","buildSourceRow","action","instances","icon","only","isIntegrationSource","b","toolSourceRank","topRows","INTEGRATIONS_RANK","x","q","isConfigTool","CONFIG_TOOL_SOURCES","useEffect","navRef","useRef","event","h","variant","showSearch","jsxs","PickerCard","PickerBack","COLORS","jsx","SvgArrowLeft","renderSourceIcon","TitleSmall","PickerSearchRow","SearchIcon","PickerSearchInput","p","PickerEmpty","row","PickerRow","CreateRowText","Fragment","PickerRowMain","BodySecondary","Shield","RightActionText","ChevronRight","PickerLegend","BodyCaption","styled"],"mappings":"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"}
|
|
@@ -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"),Y=require("../../../assets/icons/delete.svg.js"),V=require("../../../assets/icons/plus.svg.js"),o=require("react"),K=require("styled-components"),p=require("../../TypographyStyle.js"),l=require("../../../constants/Theme.js"),d=require("../AgentBuilder.styled.js"),Q=require("../constants/charLimits.js"),g=require("./DrawerHeaderText.js"),X=require("./ToolInstructionsField.js"),Z=require("../../side-modal/SideModal.js"),h=require("../../input/Input.js"),ee=require("../../dropdown/Dropdown.js"),te=require("../../dropdown/utils.js"),se=require("../../button/Button.js"),I=require("../../../editor/BikEditor.js"),re=r=>r&&typeof r=="object"&&"default"in r?r:{default:r},R=re(K),ae=["GET","POST","PUT","PATCH","DELETE"],ne=ae.map(r=>({label:r,value:r})),k=r=>{try{const i=new URL(r);return(i.protocol==="http:"||i.protocol==="https:")&&i.hostname.length>0}catch{return!1}},oe=({onClose:r,onSave:i,initial:n,onImprove:D,charLimits:j=Q.AGENT_CHAR_LIMITS,zIndex:A,existingNames:P=[]})=>{const[m,_]=o.useState(n?.name??""),[C,M]=o.useState(n?.instructions??""),[x,F]=o.useState(n?.url??"https://"),[y,N]=o.useState(n?.method??"POST"),[b,T]=o.useState(n?.headers??[{key:"",value:""}]),[O,U]=o.useState(n?.requestBody??""),[L,$]=o.useState(n?.responseSample??""),[q,B]=o.useState(!1),H=(t,s)=>T(a=>a.map((u,W)=>W===t?{...u,...s}:u)),z=()=>T(t=>[...t,{key:"",value:""}]),J=t=>T(s=>s.filter((a,u)=>u!==t)),S=m.trim(),v=S.length>0&&P.some(t=>t.trim().toLowerCase()===S.toLowerCase()),c=x.trim(),w=c.length>0&&c!=="https://"&&!k(c),E=S.length>0&&k(c)&&!v,G=async()=>{if(!E||q)return;const t={id:n?.id??`restapi_${Date.now().toString(36)}`,name:m.trim(),instructions:C,url:x.trim(),method:y,headers:b.filter(a=>a.key.trim()||a.value.trim()),requestBody:O,responseSample:L},s=i(t);if(s&&typeof s.then=="function"){B(!0);try{await s}finally{B(!1)}}};return e.jsxs(Z.SideModal,{header:"Rest API",closeOnEscapeKey:!1,zIndex:A,headerCustomComponent:e.jsx(g.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:g.DRAWER_HEADER_STYLE,bodyStyle:g.DRAWER_BODY_STYLE,onClose:r,saveButtonProps:{"data-test":"restapi-save",buttonText:"Save",buttonType:"primary",size:"small",disabled:!E,isLoading:q,onClick:G},cancelButtonProps:{"data-test":"restapi-cancel",buttonText:"Cancel",buttonType:"tertiaryGray",size:"small",onClick:r},children:[e.jsx(h.Input,{"data-test":"restapi-name",variant:"small",labelText:"Name",labelTextBold:!0,placeholder:"Enter action name",value:m,maxCharLimit:j.name,state:v?"invalid":void 0,errorMessage:v?"A tool with this name already exists":void 0,onChangeText:_}),e.jsx(X.ToolInstructionsField,{"data-test":"restapi-instructions",label:"Instructions",value:C,onChange:M,maxLength:j.instructions,placeholder:"Describe how should the LLM generate the rest API",onImprove:D}),e.jsx(d.FieldBlock,{children:e.jsx(h.Input,{"data-test":"restapi-url",variant:"small",labelText:"Request URL",labelTextBold:!0,placeholder:"https://",type:"url",value:x,state:w?"invalid":void 0,errorMessage:w?"Enter a valid URL (including https://)":void 0,onChangeText:F})}),e.jsxs(d.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:l.COLORS.content.primary,children:"HTTP method"}),e.jsx(ee.Dropdown,{"data-test":"restapi-method",size:"small",width:"100%",dropdownWidth:"399px",options:ne,defaultOptions:[{label:y,value:y}],onSelect:t=>{const s=te.unwrapDropdownValue(t);s&&N(s)}})]}),e.jsxs(d.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:l.COLORS.content.primary,children:"Headers"}),b.map((t,s)=>e.jsxs(le,{"data-test":`restapi-header-${s}`,children:[e.jsx(h.Input,{variant:"small",hideInputHeader:!0,placeholder:"Enter name",value:t.key,onChangeText:a=>H(s,{key:a})}),e.jsx(h.Input,{variant:"small",hideInputHeader:!0,placeholder:"Enter value",value:t.value,onChangeText:a=>H(s,{value:a})}),e.jsx(de,{type:"button","aria-label":"Remove header","data-test":`restapi-header-remove-${s}`,onClick:()=>J(s),children:e.jsx(Y.default,{width:16,height:16,color:l.COLORS.content.secondary})})]},s)),e.jsx(ie,{children:e.jsx(se.Button,{"data-test":"restapi-add-header",buttonType:"dashRegular",size:"small",LeadingIcon:V.default,buttonText:"Add header",onClick:z})})]}),e.jsxs(d.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:l.COLORS.content.primary,children:"Request "}),e.jsx(I.BikEditor,{features:{jsonMode:!0},initialContent:O,style:f,placeholder:"Type or paste JSON here",onChange:t=>U(t.text),minHeight:"120px",maxHeight:"240px"})]}),e.jsxs(d.FieldBlock,{children:[e.jsx(p.TitleSmall,{color:l.COLORS.content.primary,children:"Response "}),e.jsx(I.BikEditor,{features:{jsonMode:!0},style:f,initialContent:L,placeholder:"Type or paste JSON here",onChange:t=>$(t.text),minHeight:"120px",maxHeight:"240px"})]})]})},le=R.default.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: center;
|
|
4
4
|
gap: 8px;
|
|
5
|
-
`,
|
|
5
|
+
`,ie=R.default.div`
|
|
6
6
|
display: flex;
|
|
7
|
-
`,
|
|
7
|
+
`,de=R.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: ${l.COLORS.content.secondary};
|
|
21
21
|
}
|
|
22
|
-
`,f={borderRadius:"4px",overflow:"hidden"};exports.JsonFieldBox=f;exports.RestApiToolPanel=
|
|
22
|
+
`,f={borderRadius:"4px",overflow:"hidden"};exports.JsonFieldBox=f;exports.RestApiToolPanel=oe;
|
|
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 } from '@src/editor';\nimport React, { 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 {\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';\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}\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}) => {\n\tconst [name, setName] = useState(initial?.name ?? '');\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/>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<Input\n\t\t\t\t\tdata-test=\"restapi-url\"\n\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\tlabelText=\"Request URL\"\n\t\t\t\t\tlabelTextBold\n\t\t\t\t\tplaceholder=\"https://\"\n\t\t\t\t\ttype=\"url\"\n\t\t\t\t\tvalue={url}\n\t\t\t\t\tonChangeText={setUrl}\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}>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<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 value\"\n\t\t\t\t\t\t\tvalue={h.value}\n\t\t\t\t\t\t\tonChangeText={(v) => patchHeader(i, { value: v })}\n\t\t\t\t\t\t/>\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<BikEditor\n\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\tinitialContent={requestBody}\n\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\tonChange={(c) => setRequestBody(c.text)}\n\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\tmaxHeight=\"240px\"\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}>Response </TitleSmall>\n\t\t\t\t<BikEditor\n\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\tinitialContent={responseSample}\n\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\tonChange={(c) => setResponseSample(c.text)}\n\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\tmaxHeight=\"240px\"\n\t\t\t\t/>\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","name","setName","useState","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","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 } from '@src/editor';\nimport React, { 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 {\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';\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}\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// A callable endpoint needs an http(s) scheme AND a host — this rejects the\n// pre-filled bare \"https://\" (and any scheme-only / malformed value).\nconst isValidHttpUrl = (value: string): boolean => {\n\ttry {\n\t\tconst parsed = new URL(value);\n\t\treturn (\n\t\t\t(parsed.protocol === 'http:' || parsed.protocol === 'https:') &&\n\t\t\tparsed.hostname.length > 0\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\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}) => {\n\tconst [name, setName] = useState(initial?.name ?? '');\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 urlTrimmed = url.trim();\n\t// Save needs a real endpoint, but don't flash the error while the field still\n\t// holds its pristine \"https://\" seed — only once the user has typed past it.\n\tconst isUrlInvalid =\n\t\turlTrimmed.length > 0 &&\n\t\turlTrimmed !== 'https://' &&\n\t\t!isValidHttpUrl(urlTrimmed);\n\tconst canSave =\n\t\tnameTrimmed.length > 0 && isValidHttpUrl(urlTrimmed) && !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/>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<Input\n\t\t\t\t\tdata-test=\"restapi-url\"\n\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\tlabelText=\"Request URL\"\n\t\t\t\t\tlabelTextBold\n\t\t\t\t\tplaceholder=\"https://\"\n\t\t\t\t\ttype=\"url\"\n\t\t\t\t\tvalue={url}\n\t\t\t\t\tstate={isUrlInvalid ? 'invalid' : undefined}\n\t\t\t\t\terrorMessage={\n\t\t\t\t\t\tisUrlInvalid ? 'Enter a valid URL (including https://)' : undefined\n\t\t\t\t\t}\n\t\t\t\t\tonChangeText={setUrl}\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}>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<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 value\"\n\t\t\t\t\t\t\tvalue={h.value}\n\t\t\t\t\t\t\tonChangeText={(v) => patchHeader(i, { value: v })}\n\t\t\t\t\t\t/>\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<BikEditor\n\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\tinitialContent={requestBody}\n\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\tonChange={(c) => setRequestBody(c.text)}\n\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\tmaxHeight=\"240px\"\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}>Response </TitleSmall>\n\t\t\t\t<BikEditor\n\t\t\t\t\tfeatures={{ jsonMode: true }}\n\t\t\t\t\tstyle={JsonFieldBox}\n\t\t\t\t\tinitialContent={responseSample}\n\t\t\t\t\tplaceholder=\"Type or paste JSON here\"\n\t\t\t\t\tonChange={(c) => setResponseSample(c.text)}\n\t\t\t\t\tminHeight=\"120px\"\n\t\t\t\t\tmaxHeight=\"240px\"\n\t\t\t\t/>\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","isValidHttpUrl","value","parsed","RestApiToolPanel","onClose","onSave","initial","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","existingNames","name","setName","useState","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","urlTrimmed","isUrlInvalid","canSave","handleSave","config","result","jsxs","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","Input","ToolInstructionsField","FieldBlock","TitleSmall","COLORS","Dropdown","opt","v","unwrapDropdownValue","HeaderRow","IconBtn","DeleteIcon","AddHeaderRow","Button","PlusIcon","BikEditor","JsonFieldBox","c","styled"],"mappings":"4xBA0CMA,GAA2B,CAAC,MAAO,OAAQ,MAAO,QAAS,QAAQ,EACnEC,GAAiCD,GAAQ,IAAKE,IAAO,CAC1D,MAAOA,EACP,MAAOA,CACR,EAAE,EAIIC,EAAkBC,GAA2B,CAClD,GAAI,CACH,MAAMC,EAAS,IAAI,IAAID,CAAK,EAC5B,OACEC,EAAO,WAAa,SAAWA,EAAO,WAAa,WACpDA,EAAO,SAAS,OAAS,CAE3B,MAAQ,CACP,MAAO,EACR,CACD,EAQaC,GAAoD,CAAC,CACjE,QAAAC,EACA,OAAAC,EACA,QAAAC,EACA,UAAAC,EAAA,WACAC,EAAaC,EAAAA,kBACb,OAAAC,EACA,cAAAC,EAAgB,CAAA,CACjB,IAAM,CACL,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAASR,GAAS,MAAQ,EAAE,EAC9C,CAACS,EAAcC,CAAe,EAAIF,EAAAA,SAASR,GAAS,cAAgB,EAAE,EAEtE,CAACW,EAAKC,CAAM,EAAIJ,EAAAA,SAASR,GAAS,KAAO,UAAU,EACnD,CAACa,EAAQC,CAAS,EAAIN,EAAAA,SAC3BR,GAAS,QAAU,MAAA,EAEd,CAACe,EAASC,CAAU,EAAIR,EAAAA,SAC7BR,GAAS,SAAW,CAAC,CAAE,IAAK,GAAI,MAAO,GAAI,CAAA,EAEtC,CAACiB,EAAaC,CAAc,EAAIV,EAAAA,SAASR,GAAS,aAAe,EAAE,EACnE,CAACmB,EAAgBC,CAAiB,EAAIZ,EAAAA,SAC3CR,GAAS,gBAAkB,EAAA,EAEtB,CAACqB,EAAQC,CAAS,EAAId,EAAAA,SAAS,EAAK,EAEpCe,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,EAAc1B,EAAK,KAAA,EAEnB2B,EACLD,EAAY,OAAS,GACrB3B,EAAc,KACZ6B,GAAMA,EAAE,KAAA,EAAO,YAAA,IAAkBF,EAAY,YAAA,CAAY,EAEtDG,EAAaxB,EAAI,KAAA,EAGjByB,EACLD,EAAW,OAAS,GACpBA,IAAe,YACf,CAACzC,EAAeyC,CAAU,EACrBE,EACLL,EAAY,OAAS,GAAKtC,EAAeyC,CAAU,GAAK,CAACF,EAEpDK,EAAa,SAAY,CAC9B,GAAI,CAACD,GAAWhB,EACf,OAED,MAAMkB,EAA4B,CACjC,GAAIvC,GAAS,IAAM,WAAW,KAAK,MAAM,SAAS,EAAE,CAAC,GACrD,KAAMM,EAAK,KAAA,EACX,aAAAG,EACA,IAAKE,EAAI,KAAA,EACT,OAAAE,EAEA,QAASE,EAAQ,OAAQY,GAAMA,EAAE,IAAI,QAAUA,EAAE,MAAM,KAAA,CAAM,EAC7D,YAAAV,EACA,eAAAE,CAAA,EAEKqB,EAASzC,EAAOwC,CAAM,EAC5B,GAAIC,GAAU,OAAQA,EAAyB,MAAS,WAAY,CACnElB,EAAU,EAAI,EACd,GAAI,CACH,MAAMkB,CACP,QAAA,CACClB,EAAU,EAAK,CAChB,CACD,CACD,EAEA,OACCmB,EAAAA,KAACC,EAAAA,UAAA,CACA,OAAO,WACP,iBAAkB,GAClB,OAAAtC,EACA,sBACCuC,EAAAA,IAACC,EAAAA,iBAAA,CACA,MAAM,WACN,SAAS,mGAAA,CAAA,EAGX,MAAM,QACN,YAAaC,EAAAA,oBACb,UAAWC,EAAAA,kBACX,QAAAhD,EACA,gBAAiB,CAChB,YAAa,eACb,WAAY,OACZ,WAAY,UACZ,KAAM,QACN,SAAU,CAACuC,EACX,UAAWhB,EACX,QAASiB,CAAA,EAEV,kBAAmB,CAClB,YAAa,iBACb,WAAY,SACZ,WAAY,eACZ,KAAM,QACN,QAASxC,CAAA,EAGV,SAAA,CAAA6C,EAAAA,IAACI,EAAAA,MAAA,CACA,YAAU,eACV,QAAQ,QACR,UAAU,OACV,cAAa,GACb,YAAY,oBACZ,MAAOzC,EACP,aAAcJ,EAAW,KACzB,MAAO+B,EAAkB,UAAY,OACrC,aACCA,EAAkB,uCAAyC,OAE5D,aAAc1B,CAAA,CAAA,EAGfoC,EAAAA,IAACK,EAAAA,sBAAA,CACA,YAAU,uBACV,MAAM,eACN,MAAOvC,EACP,SAAUC,EACV,UAAWR,EAAW,aACtB,YAAY,oDACZ,UAAAD,CAAA,CAAA,QAGAgD,EAAAA,WAAA,CACA,SAAAN,EAAAA,IAACI,EAAAA,MAAA,CACA,YAAU,cACV,QAAQ,QACR,UAAU,cACV,cAAa,GACb,YAAY,WACZ,KAAK,MACL,MAAOpC,EACP,MAAOyB,EAAe,UAAY,OAClC,aACCA,EAAe,yCAA2C,OAE3D,aAAcxB,CAAA,CAAA,EAEhB,SAECqC,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACO,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,cAAW,EACtDR,EAAAA,IAACS,GAAAA,SAAA,CACA,YAAU,iBACV,KAAK,QACL,MAAM,OACN,cAAc,QACd,QAAS5D,GACT,eAAgB,CAAC,CAAE,MAAOqB,EAAQ,MAAOA,EAAQ,EACjD,SAAWwC,GAAQ,CAClB,MAAMC,EAAIC,GAAAA,oBAAoBF,CAAG,EAC7BC,GACHxC,EAAUwC,CAAkB,CAE9B,CAAA,CAAA,CACD,EACD,SAECL,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACO,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,UAAO,EACjDpC,EAAQ,IAAI,CAACY,EAAGH,IAEhBiB,EAAAA,KAACe,GAAA,CAAkB,YAAW,kBAAkBhC,CAAC,GAChD,SAAA,CAAAmB,EAAAA,IAACI,EAAAA,MAAA,CACA,QAAQ,QACR,gBAAe,GACf,YAAY,aACZ,MAAOpB,EAAE,IACT,aAAe2B,GAAM/B,EAAYC,EAAG,CAAE,IAAK8B,EAAG,CAAA,CAAA,EAE/CX,EAAAA,IAACI,EAAAA,MAAA,CACA,QAAQ,QACR,gBAAe,GACf,YAAY,cACZ,MAAOpB,EAAE,MACT,aAAe2B,GAAM/B,EAAYC,EAAG,CAAE,MAAO8B,EAAG,CAAA,CAAA,EAEjDX,EAAAA,IAACc,GAAA,CACA,KAAK,SACL,aAAW,gBACX,YAAW,yBAAyBjC,CAAC,GACrC,QAAS,IAAMM,EAAaN,CAAC,EAE7B,SAAAmB,EAAAA,IAACe,EAAAA,QAAA,CACA,MAAO,GACP,OAAQ,GACR,MAAOP,EAAAA,OAAO,QAAQ,SAAA,CAAA,CACvB,CAAA,CACD,CAAA,EA1Be3B,CA2BhB,CACA,QACAmC,GAAA,CACA,SAAAhB,EAAAA,IAACiB,GAAAA,OAAA,CACA,YAAU,qBACV,WAAW,cACX,KAAK,QACL,YAAaC,EAAAA,QACb,WAAW,aACX,QAAShC,CAAA,CAAA,CACV,CACD,CAAA,EACD,SAECoB,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACO,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,WAAQ,EACnDR,EAAAA,IAACmB,EAAAA,UAAA,CACA,SAAU,CAAE,SAAU,EAAA,EACtB,eAAgB7C,EAChB,MAAO8C,EACP,YAAY,0BACZ,SAAWC,GAAM9C,EAAe8C,EAAE,IAAI,EACtC,UAAU,QACV,UAAU,OAAA,CAAA,CACX,EACD,SAECf,EAAAA,WAAA,CACA,SAAA,CAAAN,MAACO,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAS,SAAA,YAAS,EACpDR,EAAAA,IAACmB,EAAAA,UAAA,CACA,SAAU,CAAE,SAAU,EAAA,EACtB,MAAOC,EACP,eAAgB5C,EAChB,YAAY,0BACZ,SAAW6C,GAAM5C,EAAkB4C,EAAE,IAAI,EACzC,UAAU,QACV,UAAU,OAAA,CAAA,CACX,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 n=require("react/jsx-runtime"),oe=require("../../../assets/icons/delete.svg.js"),te=require("../../../assets/icons/edit.svg.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),oe=require("../../../assets/icons/delete.svg.js"),te=require("../../../assets/icons/edit.svg.js"),W=require("../../../assets/icons/plus.svg.js"),u=require("react"),le=require("styled-components"),a=require("../../TypographyStyle.js"),d=require("../../../constants/Theme.js"),i=require("../AgentBuilder.styled.js"),v=require("../utils/sourceIcons.js"),ce=require("./MentionPicker.js"),K=require("../../dropdown/Dropdown.js"),N=require("../../dropdown/utils.js"),re=require("../../button/Button.js"),se=require("../../states-modal/DeleteConfirmationModal.js"),$=require("../../tooltips/Tooltip.js"),ie=require("../../../icons/Informational/Common UI/Shield.js"),de=r=>r&&typeof r=="object"&&"default"in r?r:{default:r},m=de(le),J="__bik_create_new__",ue=({title:r,helper:L,items:f,addableOptions:j,onAdd:x,onRemove:q,dataTestPrefix:l,emptyText:Q,createOption:c,onConfigure:B,sourceGroups:S,mentionItems:_,actionSources:C,confirmDelete:y,pickerOpensUp:D})=>{const[p,t]=u.useState(!1),[I,g]=u.useState(null),[A,E]=u.useState(null),[U,R]=u.useState(null),b=!!S&&S.length>0,k=S?.find(e=>e.source===U),s=_!==void 0,O=u.useRef(null),z=u.useRef(null),[w,M]=u.useState(null);u.useEffect(()=>{if(!s||!p)return;const e=h=>{const V=h.target;!O.current?.contains(V)&&!z.current?.contains(V)&&t(!1)},o=h=>{h.key==="Escape"&&t(!1)};return document.addEventListener("mousedown",e),document.addEventListener("keydown",o),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("keydown",o)}},[s,p]);const X=b?s||f.length>0:s||j.length>0||!!c&&f.length>0,Y=f.length===0&&!!c&&!b&&!s,H=!!C&&C.length>0,Z=(b||H)&&f.length===0,G=()=>{if(s){M(null),t(e=>!e);return}if(b){R(null),t(e=>!e);return}if(j.length===0&&c){c.onSelect();return}t(e=>!e)},ee=(e,o)=>{if(A)return;const h=o();h&&typeof h.then=="function"&&(E(e),h.finally(()=>E(null)))},ne=()=>f.map(e=>{const o=e.onConfigure??(B?()=>B(e.id):void 0);return n.jsxs(i.SelectableRow,{"data-test":`${l}-row-${e.id}`,children:[v.renderSourceIcon(e.icon),n.jsxs(i.RowLabel,{children:[n.jsx($.Tooltip,{body:e.label,placement:"top",children:n.jsx(i.RowText,{children:n.jsx(a.BodySecondary,{numberOfLines:1,color:d.COLORS.content.primary,children:e.label})})}),e.authRequired&&n.jsx($.Tooltip,{body:"This tool requires customer verification",placement:"top",children:n.jsx("span",{"data-test":`${l}-auth-${e.id}`,style:{display:"inline-flex",flexShrink:0},children:n.jsx(ie.default,{size:16})})})]}),n.jsxs(i.RowActions,{children:[o&&n.jsx($.Tooltip,{body:"Edit",placement:"top",children:n.jsx(i.RowMenuButton,{"data-test":`${l}-edit-${e.id}`,"aria-label":`Edit ${e.label}`,disabled:A!==null,onClick:()=>ee(e.id,o),children:n.jsx(te.default,{width:16,height:16,color:d.COLORS.content.secondary})})}),o&&n.jsx(i.RowActionDivider,{"aria-hidden":!0}),n.jsx($.Tooltip,{body:"Delete",placement:"top",children:n.jsx(i.RowMenuButton,{"data-test":`${l}-delete-${e.id}`,"aria-label":`Delete ${e.label}`,onClick:()=>y?g(e.id):q(e.id),children:n.jsx(oe.default,{width:16,height:16,color:d.COLORS.content.secondary})})})]})]},e.id)}),T=c?[...j,{label:c.label,value:J,searchKey:c.label,customComponent:n.jsx("div",{style:{width:"100%",textAlign:"center",color:d.COLORS.content.brand,fontFamily:"Inter",fontSize:14,fontWeight:600},children:c.label})}]:j,F=s?n.jsx(ce.MentionPicker,{items:_??[],query:"",activeIndex:0,initialSource:w??void 0,onSelect:e=>{t(!1),x(String(e.id))},onClose:()=>t(!1),onCreateSubAgent:c?()=>{t(!1),c.onSelect()}:void 0,toolActions:H?C?.map(e=>({...e,onSelect:()=>{t(!1),e.onSelect()}})):void 0,integrationStatus:Object.fromEntries((S??[]).filter(e=>e.connected!==void 0).map(e=>[e.source,e.connected])),onConnectIntegration:e=>{t(!1),S?.find(o=>o.source===e)?.onConnect?.()}},w??"__root__"):null;return n.jsxs(i.SideSection,{children:[n.jsxs(i.SideSectionHeader,{children:[n.jsx(a.TitleSmall,{color:d.COLORS.content.primary,children:r}),X&&n.jsxs(ae,{ref:O,children:[n.jsx(i.AddIconButton,{"data-test":`${l}-add`,onClick:G,"aria-label":`Add ${r}`,children:n.jsx(W.default,{width:16,height:16,color:d.COLORS.content.primary})}),s&&p&&w===null&&n.jsx(P,{$up:D,"data-test":`${l}-picker`,children:F})]})]}),L&&n.jsx(a.BodyCaption,{color:d.COLORS.content.secondary,children:L}),Z?n.jsxs(he,{ref:s?z:void 0,children:[n.jsxs(i.SourceButtonRow,{"data-test":`${l}-sources`,children:[S?.map(e=>{const o=e.connected!==!1&&e.options.length===1?e.options[0]:void 0;return n.jsxs(i.SourceButton,{type:"button","data-test":`${l}-source-${e.source}`,onClick:()=>{if(e.connected===!1){e.onConnect?.();return}if(o){t(!1),x(o.value);return}if(s){M(e.source),t(!0);return}R(e.source)},children:[v.renderSourceIcon(v.sourceIcon(e.source),-4),n.jsx(a.BodyCaption,{color:d.COLORS.content.primary,children:o?o.label:e.label}),e.connected===!1&&n.jsx(a.BodySecondary,{color:d.COLORS.content.brand,children:"Connect"})]},e.source)}),C?.map(e=>n.jsxs(i.SourceButton,{type:"button","data-test":`${l}-action-${e.source}`,onClick:e.connected===!1?()=>e.onConnect?.():()=>{t(!1),e.onSelect()},children:[v.renderSourceIcon(e.icon,-4),n.jsx(a.BodyCaption,{color:d.COLORS.content.primary,children:e.label}),e.connected===!1&&n.jsx(a.BodySecondary,{color:d.COLORS.content.brand,children:"Connect"})]},e.source))]}),s&&p&&w!==null&&n.jsx(P,{$align:"left",$up:D,"data-test":`${l}-picker`,children:F}),!s&&k&&n.jsx(K.Dropdown,{"data-test":`${l}-dropdown`,size:"small",width:"100%",isSearchable:!0,placeHolder:`Search ${k.label} tools`,options:k.options,onSelect:e=>{const o=N.unwrapDropdownValue(e);R(null),t(!1),o&&x(o)}})]}):n.jsxs(n.Fragment,{children:[!s&&p&&T.length>0&&n.jsx(K.Dropdown,{"data-test":`${l}-dropdown`,size:"small",width:"100%",isSearchable:!0,placeHolder:`Select ${r.toLowerCase()}`,options:T,onSelect:e=>{const o=N.unwrapDropdownValue(e);t(!1),o&&(o===J?c?.onSelect():x(o))}}),f.length===0&&!p?n.jsxs(n.Fragment,{children:[n.jsx(a.BodyCaption,{color:d.COLORS.content.placeholder,children:Q}),Y&&c&&n.jsx(re.Button,{"data-test":`${l}-create`,buttonType:"secondary",size:"small",matchParentWidth:!0,LeadingIcon:W.default,buttonText:c.label,onClick:c.onSelect})]}):ne()]}),y&&I&&n.jsx(se.DeleteConfirmationModal,{"data-test":`${l}-delete-confirm`,header:`Delete this ${y.noun}?`,subHeader:`Deleting this ${y.noun} will also remove it from your instructions, wherever it's referenced.`,confirmationText:"Delete",zIndex:y.zIndex,onDeleteConfirmed:()=>{q(I),g(null)},onCancelClicked:()=>g(null)})]})},ae=m.default.div`
|
|
2
2
|
position: relative;
|
|
3
3
|
display: flex;
|
|
4
4
|
`,he=m.default.div`
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
display: flex;
|
|
7
7
|
flex-direction: column;
|
|
8
8
|
gap: 8px;
|
|
9
|
-
`,
|
|
9
|
+
`,P=m.default.div`
|
|
10
10
|
position: absolute;
|
|
11
11
|
${r=>r.$up?"bottom: calc(100% + 4px);":"top: calc(100% + 4px);"}
|
|
12
12
|
${r=>r.$align==="left"?"left: 0;":"right: 0;"}
|