@bikdotai/bik-component-library 0.0.875-beta.1 → 0.0.875-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/components/ConfigToolPanel.js +6 -6
- package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js +2 -2
- package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
- package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js +4 -4
- package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.d.ts +6 -0
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +124 -122
- package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.d.ts +6 -0
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js +83 -81
- package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.d.ts +6 -0
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js +50 -48
- package/dist/esm/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateSubAgentPanel.js","sources":["../../../../../src/components/agent-builder/components/CreateSubAgentPanel.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { SingleOption } from '@src/components/dropdown/type';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { Toaster } from '@src/components/toaster';\nimport { addUnique } from '@src/utils/arrayUtils';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tAgentTool,\n\tConfigToolConfig,\n\tConfigToolKey,\n\tParamsBlob,\n\tRestApiToolConfig,\n\tSubAgentDraft,\n} from '../AgentBuilder.model';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport {\n\tCONFIG_TOOL_SOURCE_BY_KEY,\n\tCONFIG_TOOL_SOURCES,\n\tINTEGRATIONS_KEY,\n\tINTEGRATIONS_LABEL,\n\tToolSource,\n} from '../constants/tools';\nimport {\n\tbuildAgentMentionItems,\n\tbuildCustomToolMentionItems,\n\tconfigToolMentionItem,\n\tconfigToolName,\n\trestApiMentionItem,\n\trestApiToolName,\n\ttoolSourceLabel,\n} from '../utils/mentionSerialization';\nimport { partitionSources } from '../utils/sourceGrouping';\nimport {\n\trenderSourceIcon,\n\tSOURCE_ICONS,\n\tsourceIcon,\n} from '../utils/sourceIcons';\nimport { buildToolActions } from '../utils/toolActions';\nimport { ConfigToolPanel } from './ConfigToolPanel';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { MentionEditor } from './MentionEditor';\nimport { RestApiToolPanel } from './RestApiToolPanel';\nimport {\n\tSelectableItem,\n\tSelectableListSection,\n\tSourceGroup,\n} from './SelectableListSection';\n\n/**\n * The sub-agent drawer sits above the main builder; its own tool drawers\n * (Rest API / email / Slack) stack one level higher so they open ON TOP of it\n * rather than behind (SideModal defaults to z-index 10).\n */\nconst SUBAGENT_ZINDEX = 1000;\nconst TOOL_DRAWER_ZINDEX = 1002;\n\n/** Upsert an item by id (replace when present, append otherwise). */\nconst upsertById = <T extends { id: string }>(\n\tlist: T[] | undefined,\n\titem: T,\n): T[] => {\n\tconst arr = list ?? [];\n\treturn arr.some((x) => x.id === item.id)\n\t\t? arr.map((x) => (x.id === item.id ? item : x))\n\t\t: [...arr, item];\n};\n\n/** Config-tool / Rest API drawer state; `key` remounts fresh per open. */\ninterface ToolDrawerState {\n\tkey: number;\n\tkind: 'restapi' | 'config';\n\ttoolKey?: ConfigToolKey;\n\tinitialRest?: RestApiToolConfig;\n\tinitialConfig?: ConfigToolConfig;\n}\n\n/** Inline \"Improve with AI\" action rendered below a mention editor. */\nconst ImproveButton = styled.button`\n\talign-self: flex-start;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tcolor: ${COLORS.content.primary};\n\tbackground: ${COLORS.surface.standard};\n\tborder-radius: 8px;\n\tpadding: 6px 12px;\n\tfont-size: 13px;\n\tline-height: 1.1;\n\tfont-weight: 600;\n\tcursor: pointer;\n\n\t&:disabled {\n\t\tcursor: default;\n\t\topacity: 0.6;\n\t}\n`;\n\ntype InsertFn = (\n\tkind: 'tool' | 'subagent',\n\tid: string,\n\tlabel?: string,\n\tsource?: string,\n) => void;\n\ninterface CreateSubAgentPanelProps {\n\tonClose: () => void;\n\t/** Persist the draft. The drawer shows a loader while the returned promise is pending. */\n\tonSave: (draft: SubAgentDraft) => void | Promise<void>;\n\tavailableTools: AgentTool[];\n\t/** Optional \"Improve with AI\" for instructions / guardrails. Omit to hide the buttons. */\n\tonImprove?: (\n\t\tkind: 'instructions' | 'guardrail',\n\t\ttext: string,\n\t) => Promise<string>;\n\t/** Optional \"Improve with AI\" for the Rest API / config-tool drawers. */\n\tonImproveToolInstructions?: (text: string) => Promise<string>;\n\t/**\n\t * Backend templates (email / Slack) that drive the shared config-tool drawer.\n\t * Each present key enables its tool action in this drawer; absent → hidden.\n\t * Same prop the main builder gets — sub-agents can add the same tools.\n\t */\n\tconfigToolTemplates?: Partial<Record<ConfigToolKey, ParamsBlob>>;\n\t/**\n\t * Per-source integration connection state (today: Slack). A source mapped to\n\t * `false` shows a \"Connect\" affordance instead of drilling into its tools —\n\t * same gating the main builder's Step 3 tool section gets.\n\t */\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>;\n\t/** Open the consumer's connect flow for an unconnected integration source. */\n\tonConnectIntegration?: (source: ToolSource) => void;\n\t/** Header title — \"Create sub-agent\" (default) or \"Edit sub-agent\". */\n\ttitle?: string;\n\t/** Initial values, e.g. when configuring an existing sub-agent. */\n\tinitial?: SubAgentDraft;\n\t/**\n\t * Names of the other sub-agents already on this agent (exclude the one being\n\t * edited). Blocks saving a duplicate name — the LLM references sub-agents by it.\n\t */\n\texistingNames?: string[];\n\t/** Tool-source fallback label for chips (host app). */\n\tappLabel?: string;\n\t/** Resolved character limits (defaults to {@link AGENT_CHAR_LIMITS}). */\n\tcharLimits?: AgentCharLimits;\n\t/**\n\t * Portal target for the drawer, passed straight to {@link SideModal}\n\t * (default `document.body`). Lets a host render it into its own positioned\n\t * slot rather than as a viewport overlay.\n\t */\n\telement?: Element | DocumentFragment;\n\t/** Variable catalog for the editors' `@` picker \"Variables\" view. */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\n/**\n * Right-side drawer for creating / editing a sub-agent (name, instructions,\n * guardrails, tools). Instructions & Guardrails are `@`-mention editors (tools\n * only — sub-agents can't nest); adding a tool from the list inserts it at the\n * last-focused field's cursor. Mount it fresh per open (key it) so `initial`\n * seeds the draft.\n */\nexport const CreateSubAgentPanel: React.FC<CreateSubAgentPanelProps> = ({\n\tonClose,\n\tonSave,\n\tavailableTools,\n\tonImprove,\n\tonImproveToolInstructions,\n\tconfigToolTemplates,\n\tintegrationStatus,\n\tonConnectIntegration,\n\ttitle = 'Create sub-agent',\n\tinitial,\n\texistingNames = [],\n\tappLabel = 'Manifest',\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tvariablesData,\n\telement,\n}) => {\n\tconst [name, setName] = useState(initial?.name ?? '');\n\tconst [instructions, setInstructions] = useState(initial?.instructions ?? '');\n\tconst [guardrail, setGuardrail] = useState(initial?.guardrail ?? '');\n\tconst [tools, setTools] = useState<string[]>(initial?.tools ?? []);\n\t// Inline-configured tools owned by this sub-agent (same drawers as the main\n\t// agent). Local to the drawer; flow to the consumer via the saved draft.\n\tconst [configTools, setConfigTools] = useState<ConfigToolConfig[]>(\n\t\tinitial?.configTools ?? [],\n\t);\n\tconst [restApiTools, setRestApiTools] = useState<RestApiToolConfig[]>(\n\t\tinitial?.restApiTools ?? [],\n\t);\n\tconst [toolDrawer, setToolDrawer] = useState<ToolDrawerState | null>(null);\n\tconst toolDrawerKeyRef = useRef(0);\n\tconst [saving, setSaving] = useState(false);\n\t// Bumped to remount a field after its text is replaced (e.g. by Improve).\n\tconst [instrKey, setInstrKey] = useState(0);\n\tconst [guardKey, setGuardKey] = useState(0);\n\tconst [improving, setImproving] = useState<\n\t\t'instructions' | 'guardrail' | null\n\t>(null);\n\n\t// Tools-only mention list (sub-agents can't reference other sub-agents), PLUS\n\t// this drawer's inline custom tools so their `{{tool:<id>}}` tokens rehydrate\n\t// as chips on remount (they aren't in `availableTools`).\n\tconst mentionItems = useMemo(\n\t\t() => [\n\t\t\t...buildAgentMentionItems(availableTools, [], appLabel),\n\t\t\t...buildCustomToolMentionItems(configTools, restApiTools),\n\t\t],\n\t\t[availableTools, appLabel, configTools, restApiTools],\n\t);\n\n\t// Per-field insert + focus registry, so the Tools list inserts a chip into the\n\t// last-focused editor at its cursor.\n\tconst insertersRef = useRef<\n\t\tPartial<Record<'instructions' | 'guardrail', InsertFn>>\n\t>({});\n\tconst lastFocusedRef = useRef<'instructions' | 'guardrail'>('instructions');\n\tconst registerInstr = useCallback((fn: InsertFn | null) => {\n\t\tinsertersRef.current.instructions = fn ?? undefined;\n\t}, []);\n\tconst registerGuard = useCallback((fn: InsertFn | null) => {\n\t\tinsertersRef.current.guardrail = fn ?? undefined;\n\t}, []);\n\tconst focusInstr = useCallback(() => {\n\t\tlastFocusedRef.current = 'instructions';\n\t}, []);\n\tconst focusGuard = useCallback(() => {\n\t\tlastFocusedRef.current = 'guardrail';\n\t}, []);\n\t// Latest custom-tool ids, readable from the mount-captured `@` onSelect handler\n\t// (BikEditor captures it once) — mirrors the context's valueRef trick.\n\tconst customToolIdsRef = useRef<Set<string>>(new Set());\n\tcustomToolIdsRef.current = new Set(\n\t\t[...configTools, ...restApiTools].map((t) => t.id),\n\t);\n\tconst addToolMention = useCallback(\n\t\t(kind: 'tool' | 'subagent', id: string) => {\n\t\t\t// Only catalog tool ids belong in `tools`; custom tools (Rest API / email /\n\t\t\t// Slack) track themselves on their own lists. Picking an existing custom\n\t\t\t// tool from `@` must not leak its id in as a bogus native ref.\n\t\t\tif (kind === 'tool' && !customToolIdsRef.current.has(id)) {\n\t\t\t\tsetTools((prev) => addUnique(prev, id));\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\tconst insertToolAtCursor = useCallback(\n\t\t(id: string, label?: string, source?: string) => {\n\t\t\tconst target =\n\t\t\t\tinsertersRef.current[lastFocusedRef.current] ??\n\t\t\t\tinsertersRef.current.instructions;\n\t\t\ttarget?.('tool', id, label, source);\n\t\t},\n\t\t[],\n\t);\n\n\t// Rest API (bespoke) + shared config-tool (email / Slack) drawers, same as the\n\t// main builder's Step 3 — here backed by the drawer's local state.\n\t// ponytail: mirrors Step3HowItResponds; kept local rather than sharing a hook\n\t// because Step3 is context-backed and this drawer is local-state.\n\tconst openRestApi = useCallback((tool?: RestApiToolConfig) => {\n\t\ttoolDrawerKeyRef.current += 1;\n\t\tsetToolDrawer({\n\t\t\tkey: toolDrawerKeyRef.current,\n\t\t\tkind: 'restapi',\n\t\t\tinitialRest: tool,\n\t\t});\n\t}, []);\n\tconst openConfigTool = useCallback(\n\t\t(toolKey: ConfigToolKey, tool?: ConfigToolConfig) => {\n\t\t\ttoolDrawerKeyRef.current += 1;\n\t\t\tsetToolDrawer({\n\t\t\t\tkey: toolDrawerKeyRef.current,\n\t\t\t\tkind: 'config',\n\t\t\t\ttoolKey,\n\t\t\t\tinitialConfig: tool,\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\tconst openToolAction = useCallback(\n\t\t(source: ToolSource, toolKey?: ConfigToolKey) => {\n\t\t\tconst key = toolKey ?? CONFIG_TOOL_SOURCES[source]?.[0];\n\t\t\tif (key) {\n\t\t\t\topenConfigTool(key);\n\t\t\t} else {\n\t\t\t\topenRestApi();\n\t\t\t}\n\t\t},\n\t\t[openConfigTool, openRestApi],\n\t);\n\tconst handleSaveRestApi = useCallback(\n\t\t(tool: RestApiToolConfig) => {\n\t\t\tconst isNew = !restApiTools.some((t) => t.id === tool.id);\n\t\t\tsetRestApiTools((prev) => upsertById(prev, tool));\n\t\t\t// Drop a reference chip at the cursor on creation (edits keep the chip).\n\t\t\t// Pass the source so the fresh chip shows its icon (not yet in the list).\n\t\t\tif (isNew) {\n\t\t\t\tinsertToolAtCursor(\n\t\t\t\t\ttool.id,\n\t\t\t\t\trestApiMentionItem(tool).label,\n\t\t\t\t\tToolSource.RestApi,\n\t\t\t\t);\n\t\t\t}\n\t\t\tsetToolDrawer(null);\n\t\t},\n\t\t[restApiTools, insertToolAtCursor],\n\t);\n\tconst handleSaveConfigTool = useCallback(\n\t\t(tool: ConfigToolConfig) => {\n\t\t\tconst isNew = !configTools.some((t) => t.id === tool.id);\n\t\t\tsetConfigTools((prev) => upsertById(prev, tool));\n\t\t\tif (isNew) {\n\t\t\t\tinsertToolAtCursor(\n\t\t\t\t\ttool.id,\n\t\t\t\t\tconfigToolMentionItem(tool).label,\n\t\t\t\t\tCONFIG_TOOL_SOURCE_BY_KEY[tool.tool_key],\n\t\t\t\t);\n\t\t\t}\n\t\t\tsetToolDrawer(null);\n\t\t},\n\t\t[configTools, insertToolAtCursor],\n\t);\n\n\t// Local undo toast for tool removal (drawer state isn't in AgentValue).\n\tconst [undo, setUndo] = useState<{ id: number; message: string } | null>(\n\t\tnull,\n\t);\n\tconst undoSnapshotRef = useRef<{\n\t\tinstructions: string;\n\t\tguardrail: string;\n\t\ttools: string[];\n\t\tconfigTools: ConfigToolConfig[];\n\t\trestApiTools: RestApiToolConfig[];\n\t} | null>(null);\n\tconst undoIdRef = useRef(0);\n\n\t// Remove ANY tool by id: strip its `{{tool:<id>}}` tokens, remount the fields,\n\t// and drop it from whichever list holds it (catalog `tools` or an inline\n\t// custom-tool list). One undo restores all of it.\n\tconst removeTool = (id: string) => {\n\t\tconst label =\n\t\t\tavailableTools.find((t) => t.tool_id === id)?.display_name ??\n\t\t\trestApiTools.find((t) => t.id === id)?.name ??\n\t\t\t'Tool';\n\t\t// The token stores the tool id (a tool's id is its tool_id).\n\t\tconst token = `{{tool:${id}}}`;\n\t\tconst strip = (text: string) => text.split(token).join('');\n\t\tundoSnapshotRef.current = {\n\t\t\tinstructions,\n\t\t\tguardrail,\n\t\t\ttools,\n\t\t\tconfigTools,\n\t\t\trestApiTools,\n\t\t};\n\t\tsetInstructions((prev) => strip(prev));\n\t\tsetGuardrail((prev) => strip(prev));\n\t\tsetTools((prev) => prev.filter((t) => t !== id));\n\t\tsetConfigTools((prev) => prev.filter((t) => t.id !== id));\n\t\tsetRestApiTools((prev) => prev.filter((t) => t.id !== id));\n\t\tsetInstrKey((k) => k + 1);\n\t\tsetGuardKey((k) => k + 1);\n\t\tundoIdRef.current += 1;\n\t\tsetUndo({ id: undoIdRef.current, message: `Tool \"${label}\" removed` });\n\t};\n\n\tconst undoRemove = () => {\n\t\tconst snap = undoSnapshotRef.current;\n\t\tif (snap) {\n\t\t\tsetInstructions(snap.instructions);\n\t\t\tsetGuardrail(snap.guardrail);\n\t\t\tsetTools(snap.tools);\n\t\t\tsetConfigTools(snap.configTools);\n\t\t\tsetRestApiTools(snap.restApiTools);\n\t\t\tsetInstrKey((k) => k + 1);\n\t\t\tsetGuardKey((k) => k + 1);\n\t\t\tundoSnapshotRef.current = null;\n\t\t}\n\t\tsetUndo(null);\n\t};\n\n\tconst nameTrimmed = name.trim();\n\t// Case-insensitive: two sub-agents on the same agent can't share a name (the\n\t// LLM references them by it) — mirrors the Rest API tool-name check.\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 &&\n\t\t!isDuplicateName &&\n\t\t(instructions.trim().length > 0 || guardrail.trim().length > 0);\n\n\tconst toolItems: SelectableItem[] = tools\n\t\t.map((id): SelectableItem | null => {\n\t\t\tconst tool = availableTools.find((t) => t.tool_id === id);\n\t\t\treturn tool\n\t\t\t\t? {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tlabel: tool.display_name,\n\t\t\t\t\t\ticon: sourceIcon(tool.source ?? ToolSource.Manifest),\n\t\t\t\t\t\t// Shield flags a tool that needs customer verification, same as\n\t\t\t\t\t\t// the main builder's Step 3 tool rows.\n\t\t\t\t\t\tauthRequired: tool.auth_required,\n\t\t\t\t }\n\t\t\t\t: null;\n\t\t})\n\t\t.filter((x): x is SelectableItem => x !== null);\n\n\t// Inline-configured tools (Rest API + email / Slack) render as rows in the same\n\t// list, each with its own Configure (edit) action that reopens its drawer.\n\tconst restApiItems: SelectableItem[] = restApiTools.map((t) => ({\n\t\tid: t.id,\n\t\tlabel: restApiToolName(t),\n\t\ticon: SOURCE_ICONS[ToolSource.RestApi],\n\t\tonConfigure: () => openRestApi(t),\n\t}));\n\tconst configToolItems: SelectableItem[] = configTools.map((t) => ({\n\t\tid: t.id,\n\t\tlabel: configToolName(t),\n\t\ticon: SOURCE_ICONS[\n\t\t\tt.tool_key === 'send_slack_message'\n\t\t\t\t? ToolSource.Slack\n\t\t\t\t: ToolSource.EmailHandover\n\t\t],\n\t\tonConfigure: () => openConfigTool(t.tool_key, t),\n\t}));\n\tconst allToolItems: SelectableItem[] = [\n\t\t...toolItems,\n\t\t...restApiItems,\n\t\t...configToolItems,\n\t];\n\n\t// Built-in tool actions (Rest API / email / Slack); the shared email / Slack\n\t// forms appear only when their backend template was provided. Integration\n\t// state drives the \"Connect\" affordance, same as the main builder's Step 3.\n\tconst toolActionSources = buildToolActions(\n\t\tconfigToolTemplates,\n\t\topenToolAction,\n\t\tintegrationStatus,\n\t\tonConnectIntegration,\n\t);\n\n\tconst openConfigTemplate =\n\t\ttoolDrawer?.kind === 'config' && toolDrawer.toolKey\n\t\t\t? configToolTemplates?.[toolDrawer.toolKey]\n\t\t\t: undefined;\n\n\t// Offer all tools (re-add allowed); the chip list stays deduped. Icon left of\n\t// the name, no description.\n\tconst toolOptions: SingleOption[] = availableTools.map((t) => ({\n\t\tlabel: t.display_name,\n\t\tvalue: t.tool_id,\n\t\tleadingIcon:\n\t\t\trenderSourceIcon(sourceIcon(t.source ?? ToolSource.Manifest)) ??\n\t\t\tundefined,\n\t}));\n\n\t// Group tools by source (Manifest / Shopify / …) so the empty state shows the\n\t// same per-source buttons as the main builder's side panel.\n\tconst toolSourceGroups: SourceGroup[] = (() => {\n\t\tconst order: string[] = [];\n\t\tconst bySource = new Map<string, SingleOption[]>();\n\t\tavailableTools.forEach((t) => {\n\t\t\tconst src = t.source ?? ToolSource.Manifest;\n\t\t\tif (!bySource.has(src)) {\n\t\t\t\tbySource.set(src, []);\n\t\t\t\torder.push(src);\n\t\t\t}\n\t\t\tbySource.get(src)?.push({\n\t\t\t\tlabel: t.display_name,\n\t\t\t\tvalue: t.tool_id,\n\t\t\t\tleadingIcon:\n\t\t\t\t\trenderSourceIcon(sourceIcon(t.source ?? ToolSource.Manifest)) ??\n\t\t\t\t\tundefined,\n\t\t\t});\n\t\t});\n\t\t// Same rule as the `@` picker: a source the store hasn't connected doesn't\n\t\t// get its own button — they all collapse into one \"Integrations\" button that\n\t\t// opens the picker on that group (SelectableListSection deep-links a source\n\t\t// button straight into the picker, and the umbrella key works like any other\n\t\t// source there). Action sources join the split too: Slack has no catalog\n\t\t// tools of its own, so without them an unconnected Slack would have nowhere\n\t\t// to live.\n\t\tconst { outside, inside } = partitionSources(\n\t\t\t[...order, ...toolActionSources.map((a) => a.source)],\n\t\t\tintegrationStatus,\n\t\t);\n\t\tconst shownOutside = new Set(outside);\n\t\tconst groups: SourceGroup[] = order\n\t\t\t.filter((src) => shownOutside.has(src))\n\t\t\t.map((src) => ({\n\t\t\t\tsource: src,\n\t\t\t\tlabel: toolSourceLabel(src, appLabel),\n\t\t\t\toptions: bySource.get(src) ?? [],\n\t\t\t\t// Reachable only when connected or ungated, so no connect flow needed —\n\t\t\t\t// kept for the picker's own gating, which reads these groups.\n\t\t\t\tconnected: integrationStatus?.[src as ToolSource],\n\t\t\t\tonConnect: () => onConnectIntegration?.(src as ToolSource),\n\t\t\t}));\n\t\tif (inside.length > 0) {\n\t\t\tgroups.push({\n\t\t\t\tsource: INTEGRATIONS_KEY,\n\t\t\t\tlabel: INTEGRATIONS_LABEL,\n\t\t\t\t// No options of its own: clicking opens the picker at the umbrella,\n\t\t\t\t// where each unconnected source offers \"Connect\".\n\t\t\t\toptions: [],\n\t\t\t});\n\t\t}\n\t\treturn groups;\n\t})();\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst result = onSave({\n\t\t\tname: name.trim(),\n\t\t\tinstructions,\n\t\t\tguardrail,\n\t\t\ttools,\n\t\t\tconfigTools,\n\t\t\trestApiTools,\n\t\t});\n\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\tsetSaving(true);\n\t\t\ttry {\n\t\t\t\tawait result;\n\t\t\t} finally {\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst handleImprove = async (kind: 'instructions' | 'guardrail') => {\n\t\tif (!onImprove || improving) {\n\t\t\treturn;\n\t\t}\n\t\tsetImproving(kind);\n\t\ttry {\n\t\t\tconst current = kind === 'instructions' ? instructions : guardrail;\n\t\t\tconst improved = await onImprove(kind, current);\n\t\t\tif (kind === 'instructions') {\n\t\t\t\tsetInstructions(improved);\n\t\t\t\tsetInstrKey((k) => k + 1);\n\t\t\t} else {\n\t\t\t\tsetGuardrail(improved);\n\t\t\t\tsetGuardKey((k) => k + 1);\n\t\t\t}\n\t\t} finally {\n\t\t\tsetImproving(null);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SideModal\n\t\t\t\theader={title}\n\t\t\t\tcloseOnEscapeKey={false}\n\t\t\t\tzIndex={SUBAGENT_ZINDEX}\n\t\t\t\telement={element}\n\t\t\t\theaderCustomComponent={\n\t\t\t\t\t<DrawerHeaderText\n\t\t\t\t\t\ttitle={title}\n\t\t\t\t\t\tsubtitle=\"Each sub-agent handles one piece of the job. Use @ in the main instructions to call them.\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\twidth=\"421px\"\n\t\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\t\tonClose={onClose}\n\t\t\t\tsaveButtonProps={{\n\t\t\t\t\t'data-test': 'subagent-save',\n\t\t\t\t\tbuttonText: 'Save',\n\t\t\t\t\tbuttonType: 'primary',\n\t\t\t\t\tsize: 'small',\n\t\t\t\t\tdisabled: !canSave,\n\t\t\t\t\tisLoading: saving,\n\t\t\t\t\tonClick: handleSave,\n\t\t\t\t}}\n\t\t\t\tcancelButtonProps={{\n\t\t\t\t\t'data-test': 'subagent-cancel',\n\t\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\t\tsize: 'small',\n\t\t\t\t\tonClick: onClose,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tdata-test=\"subagent-name\"\n\t\t\t\t\tlabelText=\"Agent name\"\n\t\t\t\t\tlabelTextBold\n\t\t\t\t\tplaceholder=\"Enter agent name\"\n\t\t\t\t\tvalue={name}\n\t\t\t\t\tmaxCharLimit={charLimits.name}\n\t\t\t\t\tmaxCharLimitPosition=\"TOP\"\n\t\t\t\t\tmaxCharStyle={{ fontSize: 12, lineHeight: '16px' }}\n\t\t\t\t\tstate={isDuplicateName ? 'invalid' : undefined}\n\t\t\t\t\terrorMessage={\n\t\t\t\t\t\tisDuplicateName\n\t\t\t\t\t\t\t? 'A sub-agent with this name already exists'\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tonChangeText={setName}\n\t\t\t\t/>\n\n\t\t\t\t<MentionEditor\n\t\t\t\t\tdata-test=\"subagent-instructions\"\n\t\t\t\t\tlabel=\"Instructions\"\n\t\t\t\t\tvalue={instructions}\n\t\t\t\t\tonChange={setInstructions}\n\t\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\t\tplaceholder=\"Write the steps in plain English. The agent will follow them exactly. The more specific you are, the better it performs.\"\n\t\t\t\t\tminHeight=\"160px\"\n\t\t\t\t\tresetKey={`instr-${instrKey}`}\n\t\t\t\t\tmentionItems={mentionItems}\n\t\t\t\t\ttools={availableTools}\n\t\t\t\t\ttoolActions={toolActionSources}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\taddDataButton\n\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\tappLabel={appLabel}\n\t\t\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\t\t\tonMentionSelect={addToolMention}\n\t\t\t\t\tonFocus={focusInstr}\n\t\t\t\t\tregisterInsert={registerInstr}\n\t\t\t\t\taction={\n\t\t\t\t\t\tonImprove ? (\n\t\t\t\t\t\t\t<ImproveButton\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tdata-test=\"subagent-improve-instructions\"\n\t\t\t\t\t\t\t\tdisabled={improving !== null}\n\t\t\t\t\t\t\t\tonClick={() => handleImprove('instructions')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{improving === 'instructions'\n\t\t\t\t\t\t\t\t\t? 'Improving…'\n\t\t\t\t\t\t\t\t\t: 'Improve with AI'}\n\t\t\t\t\t\t\t</ImproveButton>\n\t\t\t\t\t\t) : undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<MentionEditor\n\t\t\t\t\tdata-test=\"subagent-guardrail\"\n\t\t\t\t\tlabel=\"Guardrails\"\n\t\t\t\t\tvalue={guardrail}\n\t\t\t\t\tonChange={setGuardrail}\n\t\t\t\t\tmaxLength={charLimits.guardrail}\n\t\t\t\t\tplaceholder=\"e.g. Never discuss competitor pricing. Always stay within the cancellation policy. Do not process refunds above ₹10,000 without human approval.\"\n\t\t\t\t\tminHeight=\"160px\"\n\t\t\t\t\tresetKey={`guard-${guardKey}`}\n\t\t\t\t\tmentionItems={mentionItems}\n\t\t\t\t\ttools={availableTools}\n\t\t\t\t\ttoolActions={toolActionSources}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\taddDataButton\n\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\tappLabel={appLabel}\n\t\t\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\t\t\tonMentionSelect={addToolMention}\n\t\t\t\t\tonFocus={focusGuard}\n\t\t\t\t\tregisterInsert={registerGuard}\n\t\t\t\t\taction={\n\t\t\t\t\t\tonImprove ? (\n\t\t\t\t\t\t\t<ImproveButton\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tdata-test=\"subagent-improve-guardrail\"\n\t\t\t\t\t\t\t\tdisabled={improving !== null}\n\t\t\t\t\t\t\t\tonClick={() => handleImprove('guardrail')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{improving === 'guardrail' ? 'Improving…' : 'Improve with AI'}\n\t\t\t\t\t\t\t</ImproveButton>\n\t\t\t\t\t\t) : undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<SelectableListSection\n\t\t\t\t\ttitle=\"Tools this agent can use\"\n\t\t\t\t\tdataTestPrefix=\"subagent-tools\"\n\t\t\t\t\titems={allToolItems}\n\t\t\t\t\taddableOptions={toolOptions}\n\t\t\t\t\tsourceGroups={toolSourceGroups}\n\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\tonConnectIntegration={(source) =>\n\t\t\t\t\t\tonConnectIntegration?.(source as ToolSource)\n\t\t\t\t\t}\n\t\t\t\t\tmentionItems={mentionItems}\n\t\t\t\t\tactionSources={toolActionSources}\n\t\t\t\t\temptyText=\"No tools added yet.\"\n\t\t\t\t\tappLabel={appLabel}\n\t\t\t\t\tpickerOpensUp\n\t\t\t\t\tonAdd={(id) => {\n\t\t\t\t\t\tinsertToolAtCursor(id);\n\t\t\t\t\t\tsetTools((prev) => addUnique(prev, id));\n\t\t\t\t\t}}\n\t\t\t\t\tonRemove={removeTool}\n\t\t\t\t\tconfirmDelete={{ noun: 'tool', zIndex: TOOL_DRAWER_ZINDEX + 1 }}\n\t\t\t\t/>\n\t\t\t</SideModal>\n\n\t\t\t{toolDrawer?.kind === 'restapi' && (\n\t\t\t\t<RestApiToolPanel\n\t\t\t\t\tkey={toolDrawer.key}\n\t\t\t\t\tinitial={toolDrawer.initialRest}\n\t\t\t\t\tcharLimits={charLimits}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\tonImprove={onImproveToolInstructions}\n\t\t\t\t\tonClose={() => setToolDrawer(null)}\n\t\t\t\t\tonSave={handleSaveRestApi}\n\t\t\t\t\tzIndex={TOOL_DRAWER_ZINDEX}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{toolDrawer?.kind === 'config' &&\n\t\t\t\ttoolDrawer.toolKey &&\n\t\t\t\topenConfigTemplate && (\n\t\t\t\t\t<ConfigToolPanel\n\t\t\t\t\t\tkey={toolDrawer.key}\n\t\t\t\t\t\ttoolKey={toolDrawer.toolKey}\n\t\t\t\t\t\ttemplate={openConfigTemplate}\n\t\t\t\t\t\tinitial={toolDrawer.initialConfig}\n\t\t\t\t\t\tcharLimits={charLimits}\n\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\tonImprove={onImproveToolInstructions}\n\t\t\t\t\t\tonClose={() => setToolDrawer(null)}\n\t\t\t\t\t\tonSave={handleSaveConfigTool}\n\t\t\t\t\t\tzIndex={TOOL_DRAWER_ZINDEX}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t{undo && (\n\t\t\t\t<Toaster\n\t\t\t\t\tkey={undo.id}\n\t\t\t\t\ttext={undo.message}\n\t\t\t\t\ttype=\"info\"\n\t\t\t\t\tposition=\"top-right\"\n\t\t\t\t\tautoClose={5000}\n\t\t\t\t\thideCloseButton\n\t\t\t\t\tbuttonProps={{\n\t\t\t\t\t\tbuttonText: 'Undo',\n\t\t\t\t\t\tshowButton: true,\n\t\t\t\t\t\tonButtonClick: () => {\n\t\t\t\t\t\t\tundoRemove();\n\t\t\t\t\t\t\treturn {} as Record<string, never>;\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tonCloseToast={() => setUndo(null)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n};\n"],"names":["SUBAGENT_ZINDEX","TOOL_DRAWER_ZINDEX","upsertById","list","item","arr","x","ImproveButton","styled","COLORS","CreateSubAgentPanel","onClose","onSave","availableTools","onImprove","onImproveToolInstructions","configToolTemplates","integrationStatus","onConnectIntegration","title","initial","existingNames","appLabel","charLimits","AGENT_CHAR_LIMITS","variablesData","element","name","setName","useState","instructions","setInstructions","guardrail","setGuardrail","tools","setTools","configTools","setConfigTools","restApiTools","setRestApiTools","toolDrawer","setToolDrawer","toolDrawerKeyRef","useRef","saving","setSaving","instrKey","setInstrKey","guardKey","setGuardKey","improving","setImproving","mentionItems","useMemo","buildAgentMentionItems","buildCustomToolMentionItems","insertersRef","lastFocusedRef","registerInstr","useCallback","fn","registerGuard","focusInstr","focusGuard","customToolIdsRef","t","addToolMention","kind","id","prev","addUnique","insertToolAtCursor","label","source","openRestApi","tool","openConfigTool","toolKey","openToolAction","key","CONFIG_TOOL_SOURCES","handleSaveRestApi","isNew","restApiMentionItem","ToolSource","handleSaveConfigTool","configToolMentionItem","CONFIG_TOOL_SOURCE_BY_KEY","undo","setUndo","undoSnapshotRef","undoIdRef","removeTool","token","strip","text","k","undoRemove","snap","nameTrimmed","isDuplicateName","n","canSave","toolItems","sourceIcon","restApiItems","restApiToolName","SOURCE_ICONS","configToolItems","configToolName","allToolItems","toolActionSources","buildToolActions","openConfigTemplate","toolOptions","renderSourceIcon","toolSourceGroups","order","bySource","src","outside","inside","partitionSources","a","shownOutside","groups","toolSourceLabel","INTEGRATIONS_KEY","INTEGRATIONS_LABEL","handleSave","result","handleImprove","improved","jsxs","Fragment","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","Input","MentionEditor","SelectableListSection","RestApiToolPanel","ConfigToolPanel","Toaster"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateSubAgentPanel.js","sources":["../../../../../src/components/agent-builder/components/CreateSubAgentPanel.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { SingleOption } from '@src/components/dropdown/type';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { Toaster } from '@src/components/toaster';\nimport { addUnique } from '@src/utils/arrayUtils';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tAgentTool,\n\tConfigToolConfig,\n\tConfigToolKey,\n\tParamsBlob,\n\tRestApiToolConfig,\n\tSubAgentDraft,\n} from '../AgentBuilder.model';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport {\n\tCONFIG_TOOL_SOURCE_BY_KEY,\n\tCONFIG_TOOL_SOURCES,\n\tINTEGRATIONS_KEY,\n\tINTEGRATIONS_LABEL,\n\tToolSource,\n} from '../constants/tools';\nimport {\n\tbuildAgentMentionItems,\n\tbuildCustomToolMentionItems,\n\tconfigToolMentionItem,\n\tconfigToolName,\n\trestApiMentionItem,\n\trestApiToolName,\n\ttoolSourceLabel,\n} from '../utils/mentionSerialization';\nimport { partitionSources } from '../utils/sourceGrouping';\nimport {\n\trenderSourceIcon,\n\tSOURCE_ICONS,\n\tsourceIcon,\n} from '../utils/sourceIcons';\nimport { buildToolActions } from '../utils/toolActions';\nimport { ConfigToolPanel } from './ConfigToolPanel';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { MentionEditor } from './MentionEditor';\nimport { RestApiToolPanel } from './RestApiToolPanel';\nimport {\n\tSelectableItem,\n\tSelectableListSection,\n\tSourceGroup,\n} from './SelectableListSection';\n\n/**\n * The sub-agent drawer sits above the main builder; its own tool drawers\n * (Rest API / email / Slack) stack one level higher so they open ON TOP of it\n * rather than behind (SideModal defaults to z-index 10).\n */\nconst SUBAGENT_ZINDEX = 1000;\nconst TOOL_DRAWER_ZINDEX = 1002;\n\n/** Upsert an item by id (replace when present, append otherwise). */\nconst upsertById = <T extends { id: string }>(\n\tlist: T[] | undefined,\n\titem: T,\n): T[] => {\n\tconst arr = list ?? [];\n\treturn arr.some((x) => x.id === item.id)\n\t\t? arr.map((x) => (x.id === item.id ? item : x))\n\t\t: [...arr, item];\n};\n\n/** Config-tool / Rest API drawer state; `key` remounts fresh per open. */\ninterface ToolDrawerState {\n\tkey: number;\n\tkind: 'restapi' | 'config';\n\ttoolKey?: ConfigToolKey;\n\tinitialRest?: RestApiToolConfig;\n\tinitialConfig?: ConfigToolConfig;\n}\n\n/** Inline \"Improve with AI\" action rendered below a mention editor. */\nconst ImproveButton = styled.button`\n\talign-self: flex-start;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tcolor: ${COLORS.content.primary};\n\tbackground: ${COLORS.surface.standard};\n\tborder-radius: 8px;\n\tpadding: 6px 12px;\n\tfont-size: 13px;\n\tline-height: 1.1;\n\tfont-weight: 600;\n\tcursor: pointer;\n\n\t&:disabled {\n\t\tcursor: default;\n\t\topacity: 0.6;\n\t}\n`;\n\ntype InsertFn = (\n\tkind: 'tool' | 'subagent',\n\tid: string,\n\tlabel?: string,\n\tsource?: string,\n) => void;\n\ninterface CreateSubAgentPanelProps {\n\tonClose: () => void;\n\t/** Persist the draft. The drawer shows a loader while the returned promise is pending. */\n\tonSave: (draft: SubAgentDraft) => void | Promise<void>;\n\tavailableTools: AgentTool[];\n\t/** Optional \"Improve with AI\" for instructions / guardrails. Omit to hide the buttons. */\n\tonImprove?: (\n\t\tkind: 'instructions' | 'guardrail',\n\t\ttext: string,\n\t) => Promise<string>;\n\t/** Optional \"Improve with AI\" for the Rest API / config-tool drawers. */\n\tonImproveToolInstructions?: (text: string) => Promise<string>;\n\t/**\n\t * Backend templates (email / Slack) that drive the shared config-tool drawer.\n\t * Each present key enables its tool action in this drawer; absent → hidden.\n\t * Same prop the main builder gets — sub-agents can add the same tools.\n\t */\n\tconfigToolTemplates?: Partial<Record<ConfigToolKey, ParamsBlob>>;\n\t/**\n\t * Per-source integration connection state (today: Slack). A source mapped to\n\t * `false` shows a \"Connect\" affordance instead of drilling into its tools —\n\t * same gating the main builder's Step 3 tool section gets.\n\t */\n\tintegrationStatus?: Partial<Record<ToolSource, boolean>>;\n\t/** Open the consumer's connect flow for an unconnected integration source. */\n\tonConnectIntegration?: (source: ToolSource) => void;\n\t/** Header title — \"Create sub-agent\" (default) or \"Edit sub-agent\". */\n\ttitle?: string;\n\t/** Initial values, e.g. when configuring an existing sub-agent. */\n\tinitial?: SubAgentDraft;\n\t/**\n\t * Names of the other sub-agents already on this agent (exclude the one being\n\t * edited). Blocks saving a duplicate name — the LLM references sub-agents by it.\n\t */\n\texistingNames?: string[];\n\t/** Tool-source fallback label for chips (host app). */\n\tappLabel?: string;\n\t/** Resolved character limits (defaults to {@link AGENT_CHAR_LIMITS}). */\n\tcharLimits?: AgentCharLimits;\n\t/**\n\t * Portal target for the drawer, passed straight to {@link SideModal}\n\t * (default `document.body`). Lets a host render it into its own positioned\n\t * slot rather than as a viewport overlay.\n\t */\n\telement?: Element | DocumentFragment;\n\t/**\n\t * Footer button order, passed straight to {@link SideModal} (default\n\t * `'row'`). Hosts that show this drawer beside their own footer can set\n\t * `'row-reverse'` to line the Cancel / Save order up with it.\n\t */\n\tfooterDirection?: 'row' | 'row-reverse';\n\t/** Variable catalog for the editors' `@` picker \"Variables\" view. */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\n/**\n * Right-side drawer for creating / editing a sub-agent (name, instructions,\n * guardrails, tools). Instructions & Guardrails are `@`-mention editors (tools\n * only — sub-agents can't nest); adding a tool from the list inserts it at the\n * last-focused field's cursor. Mount it fresh per open (key it) so `initial`\n * seeds the draft.\n */\nexport const CreateSubAgentPanel: React.FC<CreateSubAgentPanelProps> = ({\n\tonClose,\n\tonSave,\n\tavailableTools,\n\tonImprove,\n\tonImproveToolInstructions,\n\tconfigToolTemplates,\n\tintegrationStatus,\n\tonConnectIntegration,\n\ttitle = 'Create sub-agent',\n\tinitial,\n\texistingNames = [],\n\tappLabel = 'Manifest',\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tvariablesData,\n\telement,\n\tfooterDirection,\n}) => {\n\tconst [name, setName] = useState(initial?.name ?? '');\n\tconst [instructions, setInstructions] = useState(initial?.instructions ?? '');\n\tconst [guardrail, setGuardrail] = useState(initial?.guardrail ?? '');\n\tconst [tools, setTools] = useState<string[]>(initial?.tools ?? []);\n\t// Inline-configured tools owned by this sub-agent (same drawers as the main\n\t// agent). Local to the drawer; flow to the consumer via the saved draft.\n\tconst [configTools, setConfigTools] = useState<ConfigToolConfig[]>(\n\t\tinitial?.configTools ?? [],\n\t);\n\tconst [restApiTools, setRestApiTools] = useState<RestApiToolConfig[]>(\n\t\tinitial?.restApiTools ?? [],\n\t);\n\tconst [toolDrawer, setToolDrawer] = useState<ToolDrawerState | null>(null);\n\tconst toolDrawerKeyRef = useRef(0);\n\tconst [saving, setSaving] = useState(false);\n\t// Bumped to remount a field after its text is replaced (e.g. by Improve).\n\tconst [instrKey, setInstrKey] = useState(0);\n\tconst [guardKey, setGuardKey] = useState(0);\n\tconst [improving, setImproving] = useState<\n\t\t'instructions' | 'guardrail' | null\n\t>(null);\n\n\t// Tools-only mention list (sub-agents can't reference other sub-agents), PLUS\n\t// this drawer's inline custom tools so their `{{tool:<id>}}` tokens rehydrate\n\t// as chips on remount (they aren't in `availableTools`).\n\tconst mentionItems = useMemo(\n\t\t() => [\n\t\t\t...buildAgentMentionItems(availableTools, [], appLabel),\n\t\t\t...buildCustomToolMentionItems(configTools, restApiTools),\n\t\t],\n\t\t[availableTools, appLabel, configTools, restApiTools],\n\t);\n\n\t// Per-field insert + focus registry, so the Tools list inserts a chip into the\n\t// last-focused editor at its cursor.\n\tconst insertersRef = useRef<\n\t\tPartial<Record<'instructions' | 'guardrail', InsertFn>>\n\t>({});\n\tconst lastFocusedRef = useRef<'instructions' | 'guardrail'>('instructions');\n\tconst registerInstr = useCallback((fn: InsertFn | null) => {\n\t\tinsertersRef.current.instructions = fn ?? undefined;\n\t}, []);\n\tconst registerGuard = useCallback((fn: InsertFn | null) => {\n\t\tinsertersRef.current.guardrail = fn ?? undefined;\n\t}, []);\n\tconst focusInstr = useCallback(() => {\n\t\tlastFocusedRef.current = 'instructions';\n\t}, []);\n\tconst focusGuard = useCallback(() => {\n\t\tlastFocusedRef.current = 'guardrail';\n\t}, []);\n\t// Latest custom-tool ids, readable from the mount-captured `@` onSelect handler\n\t// (BikEditor captures it once) — mirrors the context's valueRef trick.\n\tconst customToolIdsRef = useRef<Set<string>>(new Set());\n\tcustomToolIdsRef.current = new Set(\n\t\t[...configTools, ...restApiTools].map((t) => t.id),\n\t);\n\tconst addToolMention = useCallback(\n\t\t(kind: 'tool' | 'subagent', id: string) => {\n\t\t\t// Only catalog tool ids belong in `tools`; custom tools (Rest API / email /\n\t\t\t// Slack) track themselves on their own lists. Picking an existing custom\n\t\t\t// tool from `@` must not leak its id in as a bogus native ref.\n\t\t\tif (kind === 'tool' && !customToolIdsRef.current.has(id)) {\n\t\t\t\tsetTools((prev) => addUnique(prev, id));\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\tconst insertToolAtCursor = useCallback(\n\t\t(id: string, label?: string, source?: string) => {\n\t\t\tconst target =\n\t\t\t\tinsertersRef.current[lastFocusedRef.current] ??\n\t\t\t\tinsertersRef.current.instructions;\n\t\t\ttarget?.('tool', id, label, source);\n\t\t},\n\t\t[],\n\t);\n\n\t// Rest API (bespoke) + shared config-tool (email / Slack) drawers, same as the\n\t// main builder's Step 3 — here backed by the drawer's local state.\n\t// ponytail: mirrors Step3HowItResponds; kept local rather than sharing a hook\n\t// because Step3 is context-backed and this drawer is local-state.\n\tconst openRestApi = useCallback((tool?: RestApiToolConfig) => {\n\t\ttoolDrawerKeyRef.current += 1;\n\t\tsetToolDrawer({\n\t\t\tkey: toolDrawerKeyRef.current,\n\t\t\tkind: 'restapi',\n\t\t\tinitialRest: tool,\n\t\t});\n\t}, []);\n\tconst openConfigTool = useCallback(\n\t\t(toolKey: ConfigToolKey, tool?: ConfigToolConfig) => {\n\t\t\ttoolDrawerKeyRef.current += 1;\n\t\t\tsetToolDrawer({\n\t\t\t\tkey: toolDrawerKeyRef.current,\n\t\t\t\tkind: 'config',\n\t\t\t\ttoolKey,\n\t\t\t\tinitialConfig: tool,\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\tconst openToolAction = useCallback(\n\t\t(source: ToolSource, toolKey?: ConfigToolKey) => {\n\t\t\tconst key = toolKey ?? CONFIG_TOOL_SOURCES[source]?.[0];\n\t\t\tif (key) {\n\t\t\t\topenConfigTool(key);\n\t\t\t} else {\n\t\t\t\topenRestApi();\n\t\t\t}\n\t\t},\n\t\t[openConfigTool, openRestApi],\n\t);\n\tconst handleSaveRestApi = useCallback(\n\t\t(tool: RestApiToolConfig) => {\n\t\t\tconst isNew = !restApiTools.some((t) => t.id === tool.id);\n\t\t\tsetRestApiTools((prev) => upsertById(prev, tool));\n\t\t\t// Drop a reference chip at the cursor on creation (edits keep the chip).\n\t\t\t// Pass the source so the fresh chip shows its icon (not yet in the list).\n\t\t\tif (isNew) {\n\t\t\t\tinsertToolAtCursor(\n\t\t\t\t\ttool.id,\n\t\t\t\t\trestApiMentionItem(tool).label,\n\t\t\t\t\tToolSource.RestApi,\n\t\t\t\t);\n\t\t\t}\n\t\t\tsetToolDrawer(null);\n\t\t},\n\t\t[restApiTools, insertToolAtCursor],\n\t);\n\tconst handleSaveConfigTool = useCallback(\n\t\t(tool: ConfigToolConfig) => {\n\t\t\tconst isNew = !configTools.some((t) => t.id === tool.id);\n\t\t\tsetConfigTools((prev) => upsertById(prev, tool));\n\t\t\tif (isNew) {\n\t\t\t\tinsertToolAtCursor(\n\t\t\t\t\ttool.id,\n\t\t\t\t\tconfigToolMentionItem(tool).label,\n\t\t\t\t\tCONFIG_TOOL_SOURCE_BY_KEY[tool.tool_key],\n\t\t\t\t);\n\t\t\t}\n\t\t\tsetToolDrawer(null);\n\t\t},\n\t\t[configTools, insertToolAtCursor],\n\t);\n\n\t// Local undo toast for tool removal (drawer state isn't in AgentValue).\n\tconst [undo, setUndo] = useState<{ id: number; message: string } | null>(\n\t\tnull,\n\t);\n\tconst undoSnapshotRef = useRef<{\n\t\tinstructions: string;\n\t\tguardrail: string;\n\t\ttools: string[];\n\t\tconfigTools: ConfigToolConfig[];\n\t\trestApiTools: RestApiToolConfig[];\n\t} | null>(null);\n\tconst undoIdRef = useRef(0);\n\n\t// Remove ANY tool by id: strip its `{{tool:<id>}}` tokens, remount the fields,\n\t// and drop it from whichever list holds it (catalog `tools` or an inline\n\t// custom-tool list). One undo restores all of it.\n\tconst removeTool = (id: string) => {\n\t\tconst label =\n\t\t\tavailableTools.find((t) => t.tool_id === id)?.display_name ??\n\t\t\trestApiTools.find((t) => t.id === id)?.name ??\n\t\t\t'Tool';\n\t\t// The token stores the tool id (a tool's id is its tool_id).\n\t\tconst token = `{{tool:${id}}}`;\n\t\tconst strip = (text: string) => text.split(token).join('');\n\t\tundoSnapshotRef.current = {\n\t\t\tinstructions,\n\t\t\tguardrail,\n\t\t\ttools,\n\t\t\tconfigTools,\n\t\t\trestApiTools,\n\t\t};\n\t\tsetInstructions((prev) => strip(prev));\n\t\tsetGuardrail((prev) => strip(prev));\n\t\tsetTools((prev) => prev.filter((t) => t !== id));\n\t\tsetConfigTools((prev) => prev.filter((t) => t.id !== id));\n\t\tsetRestApiTools((prev) => prev.filter((t) => t.id !== id));\n\t\tsetInstrKey((k) => k + 1);\n\t\tsetGuardKey((k) => k + 1);\n\t\tundoIdRef.current += 1;\n\t\tsetUndo({ id: undoIdRef.current, message: `Tool \"${label}\" removed` });\n\t};\n\n\tconst undoRemove = () => {\n\t\tconst snap = undoSnapshotRef.current;\n\t\tif (snap) {\n\t\t\tsetInstructions(snap.instructions);\n\t\t\tsetGuardrail(snap.guardrail);\n\t\t\tsetTools(snap.tools);\n\t\t\tsetConfigTools(snap.configTools);\n\t\t\tsetRestApiTools(snap.restApiTools);\n\t\t\tsetInstrKey((k) => k + 1);\n\t\t\tsetGuardKey((k) => k + 1);\n\t\t\tundoSnapshotRef.current = null;\n\t\t}\n\t\tsetUndo(null);\n\t};\n\n\tconst nameTrimmed = name.trim();\n\t// Case-insensitive: two sub-agents on the same agent can't share a name (the\n\t// LLM references them by it) — mirrors the Rest API tool-name check.\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 &&\n\t\t!isDuplicateName &&\n\t\t(instructions.trim().length > 0 || guardrail.trim().length > 0);\n\n\tconst toolItems: SelectableItem[] = tools\n\t\t.map((id): SelectableItem | null => {\n\t\t\tconst tool = availableTools.find((t) => t.tool_id === id);\n\t\t\treturn tool\n\t\t\t\t? {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tlabel: tool.display_name,\n\t\t\t\t\t\ticon: sourceIcon(tool.source ?? ToolSource.Manifest),\n\t\t\t\t\t\t// Shield flags a tool that needs customer verification, same as\n\t\t\t\t\t\t// the main builder's Step 3 tool rows.\n\t\t\t\t\t\tauthRequired: tool.auth_required,\n\t\t\t\t }\n\t\t\t\t: null;\n\t\t})\n\t\t.filter((x): x is SelectableItem => x !== null);\n\n\t// Inline-configured tools (Rest API + email / Slack) render as rows in the same\n\t// list, each with its own Configure (edit) action that reopens its drawer.\n\tconst restApiItems: SelectableItem[] = restApiTools.map((t) => ({\n\t\tid: t.id,\n\t\tlabel: restApiToolName(t),\n\t\ticon: SOURCE_ICONS[ToolSource.RestApi],\n\t\tonConfigure: () => openRestApi(t),\n\t}));\n\tconst configToolItems: SelectableItem[] = configTools.map((t) => ({\n\t\tid: t.id,\n\t\tlabel: configToolName(t),\n\t\ticon: SOURCE_ICONS[\n\t\t\tt.tool_key === 'send_slack_message'\n\t\t\t\t? ToolSource.Slack\n\t\t\t\t: ToolSource.EmailHandover\n\t\t],\n\t\tonConfigure: () => openConfigTool(t.tool_key, t),\n\t}));\n\tconst allToolItems: SelectableItem[] = [\n\t\t...toolItems,\n\t\t...restApiItems,\n\t\t...configToolItems,\n\t];\n\n\t// Built-in tool actions (Rest API / email / Slack); the shared email / Slack\n\t// forms appear only when their backend template was provided. Integration\n\t// state drives the \"Connect\" affordance, same as the main builder's Step 3.\n\tconst toolActionSources = buildToolActions(\n\t\tconfigToolTemplates,\n\t\topenToolAction,\n\t\tintegrationStatus,\n\t\tonConnectIntegration,\n\t);\n\n\tconst openConfigTemplate =\n\t\ttoolDrawer?.kind === 'config' && toolDrawer.toolKey\n\t\t\t? configToolTemplates?.[toolDrawer.toolKey]\n\t\t\t: undefined;\n\n\t// Offer all tools (re-add allowed); the chip list stays deduped. Icon left of\n\t// the name, no description.\n\tconst toolOptions: SingleOption[] = availableTools.map((t) => ({\n\t\tlabel: t.display_name,\n\t\tvalue: t.tool_id,\n\t\tleadingIcon:\n\t\t\trenderSourceIcon(sourceIcon(t.source ?? ToolSource.Manifest)) ??\n\t\t\tundefined,\n\t}));\n\n\t// Group tools by source (Manifest / Shopify / …) so the empty state shows the\n\t// same per-source buttons as the main builder's side panel.\n\tconst toolSourceGroups: SourceGroup[] = (() => {\n\t\tconst order: string[] = [];\n\t\tconst bySource = new Map<string, SingleOption[]>();\n\t\tavailableTools.forEach((t) => {\n\t\t\tconst src = t.source ?? ToolSource.Manifest;\n\t\t\tif (!bySource.has(src)) {\n\t\t\t\tbySource.set(src, []);\n\t\t\t\torder.push(src);\n\t\t\t}\n\t\t\tbySource.get(src)?.push({\n\t\t\t\tlabel: t.display_name,\n\t\t\t\tvalue: t.tool_id,\n\t\t\t\tleadingIcon:\n\t\t\t\t\trenderSourceIcon(sourceIcon(t.source ?? ToolSource.Manifest)) ??\n\t\t\t\t\tundefined,\n\t\t\t});\n\t\t});\n\t\t// Same rule as the `@` picker: a source the store hasn't connected doesn't\n\t\t// get its own button — they all collapse into one \"Integrations\" button that\n\t\t// opens the picker on that group (SelectableListSection deep-links a source\n\t\t// button straight into the picker, and the umbrella key works like any other\n\t\t// source there). Action sources join the split too: Slack has no catalog\n\t\t// tools of its own, so without them an unconnected Slack would have nowhere\n\t\t// to live.\n\t\tconst { outside, inside } = partitionSources(\n\t\t\t[...order, ...toolActionSources.map((a) => a.source)],\n\t\t\tintegrationStatus,\n\t\t);\n\t\tconst shownOutside = new Set(outside);\n\t\tconst groups: SourceGroup[] = order\n\t\t\t.filter((src) => shownOutside.has(src))\n\t\t\t.map((src) => ({\n\t\t\t\tsource: src,\n\t\t\t\tlabel: toolSourceLabel(src, appLabel),\n\t\t\t\toptions: bySource.get(src) ?? [],\n\t\t\t\t// Reachable only when connected or ungated, so no connect flow needed —\n\t\t\t\t// kept for the picker's own gating, which reads these groups.\n\t\t\t\tconnected: integrationStatus?.[src as ToolSource],\n\t\t\t\tonConnect: () => onConnectIntegration?.(src as ToolSource),\n\t\t\t}));\n\t\tif (inside.length > 0) {\n\t\t\tgroups.push({\n\t\t\t\tsource: INTEGRATIONS_KEY,\n\t\t\t\tlabel: INTEGRATIONS_LABEL,\n\t\t\t\t// No options of its own: clicking opens the picker at the umbrella,\n\t\t\t\t// where each unconnected source offers \"Connect\".\n\t\t\t\toptions: [],\n\t\t\t});\n\t\t}\n\t\treturn groups;\n\t})();\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst result = onSave({\n\t\t\tname: name.trim(),\n\t\t\tinstructions,\n\t\t\tguardrail,\n\t\t\ttools,\n\t\t\tconfigTools,\n\t\t\trestApiTools,\n\t\t});\n\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\tsetSaving(true);\n\t\t\ttry {\n\t\t\t\tawait result;\n\t\t\t} finally {\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst handleImprove = async (kind: 'instructions' | 'guardrail') => {\n\t\tif (!onImprove || improving) {\n\t\t\treturn;\n\t\t}\n\t\tsetImproving(kind);\n\t\ttry {\n\t\t\tconst current = kind === 'instructions' ? instructions : guardrail;\n\t\t\tconst improved = await onImprove(kind, current);\n\t\t\tif (kind === 'instructions') {\n\t\t\t\tsetInstructions(improved);\n\t\t\t\tsetInstrKey((k) => k + 1);\n\t\t\t} else {\n\t\t\t\tsetGuardrail(improved);\n\t\t\t\tsetGuardKey((k) => k + 1);\n\t\t\t}\n\t\t} finally {\n\t\t\tsetImproving(null);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SideModal\n\t\t\t\theader={title}\n\t\t\t\tcloseOnEscapeKey={false}\n\t\t\t\tzIndex={SUBAGENT_ZINDEX}\n\t\t\t\telement={element}\n\t\t\t\tfooterDirection={footerDirection}\n\t\t\t\theaderCustomComponent={\n\t\t\t\t\t<DrawerHeaderText\n\t\t\t\t\t\ttitle={title}\n\t\t\t\t\t\tsubtitle=\"Each sub-agent handles one piece of the job. Use @ in the main instructions to call them.\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\twidth=\"421px\"\n\t\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\t\tonClose={onClose}\n\t\t\t\tsaveButtonProps={{\n\t\t\t\t\t'data-test': 'subagent-save',\n\t\t\t\t\tbuttonText: 'Save',\n\t\t\t\t\tbuttonType: 'primary',\n\t\t\t\t\tsize: 'small',\n\t\t\t\t\tdisabled: !canSave,\n\t\t\t\t\tisLoading: saving,\n\t\t\t\t\tonClick: handleSave,\n\t\t\t\t}}\n\t\t\t\tcancelButtonProps={{\n\t\t\t\t\t'data-test': 'subagent-cancel',\n\t\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\t\tsize: 'small',\n\t\t\t\t\tonClick: onClose,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tdata-test=\"subagent-name\"\n\t\t\t\t\tlabelText=\"Agent name\"\n\t\t\t\t\tlabelTextBold\n\t\t\t\t\tplaceholder=\"Enter agent name\"\n\t\t\t\t\tvalue={name}\n\t\t\t\t\tmaxCharLimit={charLimits.name}\n\t\t\t\t\tmaxCharLimitPosition=\"TOP\"\n\t\t\t\t\tmaxCharStyle={{ fontSize: 12, lineHeight: '16px' }}\n\t\t\t\t\tstate={isDuplicateName ? 'invalid' : undefined}\n\t\t\t\t\terrorMessage={\n\t\t\t\t\t\tisDuplicateName\n\t\t\t\t\t\t\t? 'A sub-agent with this name already exists'\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tonChangeText={setName}\n\t\t\t\t/>\n\n\t\t\t\t<MentionEditor\n\t\t\t\t\tdata-test=\"subagent-instructions\"\n\t\t\t\t\tlabel=\"Instructions\"\n\t\t\t\t\tvalue={instructions}\n\t\t\t\t\tonChange={setInstructions}\n\t\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\t\tplaceholder=\"Write the steps in plain English. The agent will follow them exactly. The more specific you are, the better it performs.\"\n\t\t\t\t\tminHeight=\"160px\"\n\t\t\t\t\tresetKey={`instr-${instrKey}`}\n\t\t\t\t\tmentionItems={mentionItems}\n\t\t\t\t\ttools={availableTools}\n\t\t\t\t\ttoolActions={toolActionSources}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\taddDataButton\n\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\tappLabel={appLabel}\n\t\t\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\t\t\tonMentionSelect={addToolMention}\n\t\t\t\t\tonFocus={focusInstr}\n\t\t\t\t\tregisterInsert={registerInstr}\n\t\t\t\t\taction={\n\t\t\t\t\t\tonImprove ? (\n\t\t\t\t\t\t\t<ImproveButton\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tdata-test=\"subagent-improve-instructions\"\n\t\t\t\t\t\t\t\tdisabled={improving !== null}\n\t\t\t\t\t\t\t\tonClick={() => handleImprove('instructions')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{improving === 'instructions'\n\t\t\t\t\t\t\t\t\t? 'Improving…'\n\t\t\t\t\t\t\t\t\t: 'Improve with AI'}\n\t\t\t\t\t\t\t</ImproveButton>\n\t\t\t\t\t\t) : undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<MentionEditor\n\t\t\t\t\tdata-test=\"subagent-guardrail\"\n\t\t\t\t\tlabel=\"Guardrails\"\n\t\t\t\t\tvalue={guardrail}\n\t\t\t\t\tonChange={setGuardrail}\n\t\t\t\t\tmaxLength={charLimits.guardrail}\n\t\t\t\t\tplaceholder=\"e.g. Never discuss competitor pricing. Always stay within the cancellation policy. Do not process refunds above ₹10,000 without human approval.\"\n\t\t\t\t\tminHeight=\"160px\"\n\t\t\t\t\tresetKey={`guard-${guardKey}`}\n\t\t\t\t\tmentionItems={mentionItems}\n\t\t\t\t\ttools={availableTools}\n\t\t\t\t\ttoolActions={toolActionSources}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\taddDataButton\n\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\tappLabel={appLabel}\n\t\t\t\t\tonConnectIntegration={onConnectIntegration}\n\t\t\t\t\tonMentionSelect={addToolMention}\n\t\t\t\t\tonFocus={focusGuard}\n\t\t\t\t\tregisterInsert={registerGuard}\n\t\t\t\t\taction={\n\t\t\t\t\t\tonImprove ? (\n\t\t\t\t\t\t\t<ImproveButton\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tdata-test=\"subagent-improve-guardrail\"\n\t\t\t\t\t\t\t\tdisabled={improving !== null}\n\t\t\t\t\t\t\t\tonClick={() => handleImprove('guardrail')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{improving === 'guardrail' ? 'Improving…' : 'Improve with AI'}\n\t\t\t\t\t\t\t</ImproveButton>\n\t\t\t\t\t\t) : undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<SelectableListSection\n\t\t\t\t\ttitle=\"Tools this agent can use\"\n\t\t\t\t\tdataTestPrefix=\"subagent-tools\"\n\t\t\t\t\titems={allToolItems}\n\t\t\t\t\taddableOptions={toolOptions}\n\t\t\t\t\tsourceGroups={toolSourceGroups}\n\t\t\t\t\tintegrationStatus={integrationStatus}\n\t\t\t\t\tonConnectIntegration={(source) =>\n\t\t\t\t\t\tonConnectIntegration?.(source as ToolSource)\n\t\t\t\t\t}\n\t\t\t\t\tmentionItems={mentionItems}\n\t\t\t\t\tactionSources={toolActionSources}\n\t\t\t\t\temptyText=\"No tools added yet.\"\n\t\t\t\t\tappLabel={appLabel}\n\t\t\t\t\tpickerOpensUp\n\t\t\t\t\tonAdd={(id) => {\n\t\t\t\t\t\tinsertToolAtCursor(id);\n\t\t\t\t\t\tsetTools((prev) => addUnique(prev, id));\n\t\t\t\t\t}}\n\t\t\t\t\tonRemove={removeTool}\n\t\t\t\t\tconfirmDelete={{ noun: 'tool', zIndex: TOOL_DRAWER_ZINDEX + 1 }}\n\t\t\t\t/>\n\t\t\t</SideModal>\n\n\t\t\t{toolDrawer?.kind === 'restapi' && (\n\t\t\t\t<RestApiToolPanel\n\t\t\t\t\tkey={toolDrawer.key}\n\t\t\t\t\tinitial={toolDrawer.initialRest}\n\t\t\t\t\tcharLimits={charLimits}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\tonImprove={onImproveToolInstructions}\n\t\t\t\t\tonClose={() => setToolDrawer(null)}\n\t\t\t\t\tonSave={handleSaveRestApi}\n\t\t\t\t\tzIndex={TOOL_DRAWER_ZINDEX}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{toolDrawer?.kind === 'config' &&\n\t\t\t\ttoolDrawer.toolKey &&\n\t\t\t\topenConfigTemplate && (\n\t\t\t\t\t<ConfigToolPanel\n\t\t\t\t\t\tkey={toolDrawer.key}\n\t\t\t\t\t\ttoolKey={toolDrawer.toolKey}\n\t\t\t\t\t\ttemplate={openConfigTemplate}\n\t\t\t\t\t\tinitial={toolDrawer.initialConfig}\n\t\t\t\t\t\tcharLimits={charLimits}\n\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\tonImprove={onImproveToolInstructions}\n\t\t\t\t\t\tonClose={() => setToolDrawer(null)}\n\t\t\t\t\t\tonSave={handleSaveConfigTool}\n\t\t\t\t\t\tzIndex={TOOL_DRAWER_ZINDEX}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t{undo && (\n\t\t\t\t<Toaster\n\t\t\t\t\tkey={undo.id}\n\t\t\t\t\ttext={undo.message}\n\t\t\t\t\ttype=\"info\"\n\t\t\t\t\tposition=\"top-right\"\n\t\t\t\t\tautoClose={5000}\n\t\t\t\t\thideCloseButton\n\t\t\t\t\tbuttonProps={{\n\t\t\t\t\t\tbuttonText: 'Undo',\n\t\t\t\t\t\tshowButton: true,\n\t\t\t\t\t\tonButtonClick: () => {\n\t\t\t\t\t\t\tundoRemove();\n\t\t\t\t\t\t\treturn {} as Record<string, never>;\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tonCloseToast={() => setUndo(null)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n};\n"],"names":["SUBAGENT_ZINDEX","TOOL_DRAWER_ZINDEX","upsertById","list","item","arr","x","ImproveButton","styled","COLORS","CreateSubAgentPanel","onClose","onSave","availableTools","onImprove","onImproveToolInstructions","configToolTemplates","integrationStatus","onConnectIntegration","title","initial","existingNames","appLabel","charLimits","AGENT_CHAR_LIMITS","variablesData","element","footerDirection","name","setName","useState","instructions","setInstructions","guardrail","setGuardrail","tools","setTools","configTools","setConfigTools","restApiTools","setRestApiTools","toolDrawer","setToolDrawer","toolDrawerKeyRef","useRef","saving","setSaving","instrKey","setInstrKey","guardKey","setGuardKey","improving","setImproving","mentionItems","useMemo","buildAgentMentionItems","buildCustomToolMentionItems","insertersRef","lastFocusedRef","registerInstr","useCallback","fn","registerGuard","focusInstr","focusGuard","customToolIdsRef","t","addToolMention","kind","id","prev","addUnique","insertToolAtCursor","label","source","openRestApi","tool","openConfigTool","toolKey","openToolAction","key","CONFIG_TOOL_SOURCES","handleSaveRestApi","isNew","restApiMentionItem","ToolSource","handleSaveConfigTool","configToolMentionItem","CONFIG_TOOL_SOURCE_BY_KEY","undo","setUndo","undoSnapshotRef","undoIdRef","removeTool","token","strip","text","k","undoRemove","snap","nameTrimmed","isDuplicateName","n","canSave","toolItems","sourceIcon","restApiItems","restApiToolName","SOURCE_ICONS","configToolItems","configToolName","allToolItems","toolActionSources","buildToolActions","openConfigTemplate","toolOptions","renderSourceIcon","toolSourceGroups","order","bySource","src","outside","inside","partitionSources","a","shownOutside","groups","toolSourceLabel","INTEGRATIONS_KEY","INTEGRATIONS_LABEL","handleSave","result","handleImprove","improved","jsxs","Fragment","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","Input","MentionEditor","SelectableListSection","RestApiToolPanel","ConfigToolPanel","Toaster"],"mappings":"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"}
|
|
@@ -19,6 +19,12 @@ interface RestApiToolPanelProps {
|
|
|
19
19
|
* slot rather than as a viewport overlay.
|
|
20
20
|
*/
|
|
21
21
|
element?: Element | DocumentFragment;
|
|
22
|
+
/**
|
|
23
|
+
* Footer button order, passed straight to {@link SideModal} (default
|
|
24
|
+
* `'row'`). Hosts that show this drawer beside their own footer can set
|
|
25
|
+
* `'row-reverse'` to line the Cancel / Save order up with it.
|
|
26
|
+
*/
|
|
27
|
+
footerDirection?: 'row' | 'row-reverse';
|
|
22
28
|
/** Names of the OTHER tools — a new tool can't reuse one of these. */
|
|
23
29
|
existingNames?: string[];
|
|
24
30
|
/**
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { jsxs as i, jsx as r } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import ee from "../../../assets/icons/delete.svg.js";
|
|
3
|
+
import te from "../../../assets/icons/plus.svg.js";
|
|
4
4
|
import { useState as l, useRef as B } from "react";
|
|
5
5
|
import C from "styled-components";
|
|
6
|
-
import { BodyCaption as
|
|
6
|
+
import { BodyCaption as re, TitleSmall as u } from "../../TypographyStyle.js";
|
|
7
7
|
import { COLORS as a } from "../../../constants/Theme.js";
|
|
8
8
|
import { FieldBlock as m } from "../AgentBuilder.styled.js";
|
|
9
|
-
import { AGENT_CHAR_LIMITS as
|
|
10
|
-
import { DRAWER_BODY_STYLE as
|
|
11
|
-
import { ToolInstructionsField as
|
|
9
|
+
import { AGENT_CHAR_LIMITS as ne } from "../constants/charLimits.js";
|
|
10
|
+
import { DRAWER_BODY_STYLE as oe, DRAWER_HEADER_STYLE as ae, DrawerHeaderText as se } from "./DrawerHeaderText.js";
|
|
11
|
+
import { ToolInstructionsField as le } from "./ToolInstructionsField.js";
|
|
12
12
|
import { VariableInlineField as D } from "./VariableInlineField.js";
|
|
13
|
-
import { SideModal as
|
|
13
|
+
import { SideModal as ie } from "../../side-modal/SideModal.js";
|
|
14
14
|
import { Input as _ } from "../../input/Input.js";
|
|
15
|
-
import { Dropdown as
|
|
16
|
-
import { unwrapDropdownValue as
|
|
17
|
-
import { Button as
|
|
15
|
+
import { Dropdown as de } from "../../dropdown/Dropdown.js";
|
|
16
|
+
import { unwrapDropdownValue as ce } from "../../dropdown/utils.js";
|
|
17
|
+
import { Button as pe } from "../../button/Button.js";
|
|
18
18
|
import { BikEditor as M } from "../../../editor/BikEditor.js";
|
|
19
|
-
const
|
|
19
|
+
const me = ["GET", "POST", "PUT", "PATCH", "DELETE"], he = me.map((s) => ({
|
|
20
20
|
label: s,
|
|
21
21
|
value: s
|
|
22
|
-
})),
|
|
22
|
+
})), ue = (s) => {
|
|
23
23
|
if (!/^https?:\/\//i.test(s))
|
|
24
24
|
return !1;
|
|
25
25
|
let d;
|
|
@@ -29,55 +29,57 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
29
29
|
return !1;
|
|
30
30
|
}
|
|
31
31
|
return d.includes(".") && !d.startsWith(".") && !d.endsWith(".");
|
|
32
|
-
},
|
|
32
|
+
}, Ue = ({
|
|
33
33
|
onClose: s,
|
|
34
34
|
onSave: d,
|
|
35
35
|
initial: o,
|
|
36
36
|
onImprove: N,
|
|
37
|
-
charLimits: f =
|
|
37
|
+
charLimits: f = ne,
|
|
38
38
|
zIndex: q,
|
|
39
39
|
existingNames: $ = [],
|
|
40
40
|
variablesData: y,
|
|
41
|
-
element: j
|
|
41
|
+
element: j,
|
|
42
|
+
footerDirection: V
|
|
42
43
|
}) => {
|
|
43
|
-
const [g,
|
|
44
|
+
const [g, W] = l(o?.name ?? ""), [v, z] = l(o?.instructions ?? ""), [x, F] = l(o?.url ?? "https://"), [T, G] = l(
|
|
44
45
|
o?.method ?? "POST"
|
|
45
46
|
), [H, S] = l(
|
|
46
47
|
o?.headers ?? [{ key: "", value: "" }]
|
|
47
|
-
), [w,
|
|
48
|
+
), [w, J] = l(o?.requestBody ?? ""), [E, Y] = l(
|
|
48
49
|
o?.responseSample ?? ""
|
|
49
50
|
), [I, k] = l(!1), c = B(
|
|
50
51
|
(o?.headers ?? [{ key: "", value: "" }]).map(
|
|
51
52
|
(e, t) => t
|
|
52
53
|
)
|
|
53
54
|
), A = B(c.current.length), L = (e, t) => S(
|
|
54
|
-
(n) => n.map((h,
|
|
55
|
-
),
|
|
55
|
+
(n) => n.map((h, Z) => Z === e ? { ...h, ...t } : h)
|
|
56
|
+
), K = () => {
|
|
56
57
|
c.current = [...c.current, A.current], A.current += 1, S((e) => [...e, { key: "", value: "" }]);
|
|
57
|
-
},
|
|
58
|
+
}, Q = (e) => {
|
|
58
59
|
c.current = c.current.filter((t, n) => n !== e), S((t) => t.filter((n, h) => h !== e));
|
|
59
60
|
}, b = g.trim(), R = b.length > 0 && $.some(
|
|
60
61
|
(e) => e.trim().toLowerCase() === b.toLowerCase()
|
|
61
|
-
), p = x.trim(), O = p.includes("{{variable:") ? /^https?:\/\/./.test(p) :
|
|
62
|
+
), p = x.trim(), O = p.includes("{{variable:") ? /^https?:\/\/./.test(p) : ue(p), X = p.length > 0 && p !== "https://" && !O, P = b.length > 0 && O && !R && // The editor's characterLimit is soft (a paste may exceed it, rendered
|
|
62
63
|
// grey) — gate the save so over-limit instructions can't be persisted.
|
|
63
64
|
v.length <= f.instructions;
|
|
64
65
|
return /* @__PURE__ */ i(
|
|
65
|
-
|
|
66
|
+
ie,
|
|
66
67
|
{
|
|
67
68
|
header: "Rest API",
|
|
68
69
|
closeOnEscapeKey: !1,
|
|
69
70
|
zIndex: q,
|
|
70
71
|
element: j,
|
|
72
|
+
footerDirection: V,
|
|
71
73
|
headerCustomComponent: /* @__PURE__ */ r(
|
|
72
|
-
|
|
74
|
+
se,
|
|
73
75
|
{
|
|
74
76
|
title: "Rest API",
|
|
75
77
|
subtitle: "Connect to any API endpoint. Define the request and a sample response for the agent to reference."
|
|
76
78
|
}
|
|
77
79
|
),
|
|
78
80
|
width: "431px",
|
|
79
|
-
headerStyle:
|
|
80
|
-
bodyStyle:
|
|
81
|
+
headerStyle: ae,
|
|
82
|
+
bodyStyle: oe,
|
|
81
83
|
onClose: s,
|
|
82
84
|
saveButtonProps: {
|
|
83
85
|
"data-test": "restapi-save",
|
|
@@ -130,16 +132,16 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
130
132
|
maxCharLimit: f.name,
|
|
131
133
|
state: R ? "invalid" : void 0,
|
|
132
134
|
errorMessage: R ? "A tool with this name already exists" : void 0,
|
|
133
|
-
onChangeText:
|
|
135
|
+
onChangeText: W
|
|
134
136
|
}
|
|
135
137
|
),
|
|
136
138
|
/* @__PURE__ */ r(
|
|
137
|
-
|
|
139
|
+
le,
|
|
138
140
|
{
|
|
139
141
|
"data-test": "restapi-instructions",
|
|
140
142
|
label: "Instructions",
|
|
141
143
|
value: v,
|
|
142
|
-
onChange:
|
|
144
|
+
onChange: z,
|
|
143
145
|
maxLength: f.instructions,
|
|
144
146
|
placeholder: "Describe how should the LLM generate the rest API",
|
|
145
147
|
onImprove: N,
|
|
@@ -154,26 +156,26 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
154
156
|
label: "Request URL",
|
|
155
157
|
placeholder: "https://",
|
|
156
158
|
value: x,
|
|
157
|
-
onChange:
|
|
159
|
+
onChange: F,
|
|
158
160
|
variablesData: y
|
|
159
161
|
}
|
|
160
162
|
),
|
|
161
|
-
|
|
163
|
+
X && /* @__PURE__ */ r(re, { color: a.content.negative, children: "Enter a valid URL (including https://)" })
|
|
162
164
|
] }),
|
|
163
165
|
/* @__PURE__ */ i(m, { children: [
|
|
164
166
|
/* @__PURE__ */ r(u, { color: a.content.primary, children: "HTTP method" }),
|
|
165
167
|
/* @__PURE__ */ r(
|
|
166
|
-
|
|
168
|
+
de,
|
|
167
169
|
{
|
|
168
170
|
"data-test": "restapi-method",
|
|
169
171
|
size: "small",
|
|
170
172
|
width: "100%",
|
|
171
173
|
dropdownWidth: "399px",
|
|
172
|
-
options:
|
|
174
|
+
options: he,
|
|
173
175
|
defaultOptions: [{ label: T, value: T }],
|
|
174
176
|
onSelect: (e) => {
|
|
175
|
-
const t =
|
|
176
|
-
t &&
|
|
177
|
+
const t = ce(e);
|
|
178
|
+
t && G(t);
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
181
|
)
|
|
@@ -181,7 +183,7 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
181
183
|
/* @__PURE__ */ i(m, { children: [
|
|
182
184
|
/* @__PURE__ */ r(u, { color: a.content.primary, children: "Headers" }),
|
|
183
185
|
H.map((e, t) => /* @__PURE__ */ i(
|
|
184
|
-
|
|
186
|
+
fe,
|
|
185
187
|
{
|
|
186
188
|
"data-test": `restapi-header-${t}`,
|
|
187
189
|
children: [
|
|
@@ -205,14 +207,14 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
205
207
|
}
|
|
206
208
|
),
|
|
207
209
|
/* @__PURE__ */ r(
|
|
208
|
-
|
|
210
|
+
ge,
|
|
209
211
|
{
|
|
210
212
|
type: "button",
|
|
211
213
|
"aria-label": "Remove header",
|
|
212
214
|
"data-test": `restapi-header-remove-${t}`,
|
|
213
|
-
onClick: () =>
|
|
215
|
+
onClick: () => Q(t),
|
|
214
216
|
children: /* @__PURE__ */ r(
|
|
215
|
-
|
|
217
|
+
ee,
|
|
216
218
|
{
|
|
217
219
|
width: 16,
|
|
218
220
|
height: 16,
|
|
@@ -225,15 +227,15 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
225
227
|
},
|
|
226
228
|
c.current[t]
|
|
227
229
|
)),
|
|
228
|
-
/* @__PURE__ */ r(
|
|
229
|
-
|
|
230
|
+
/* @__PURE__ */ r(ye, { children: /* @__PURE__ */ r(
|
|
231
|
+
pe,
|
|
230
232
|
{
|
|
231
233
|
"data-test": "restapi-add-header",
|
|
232
234
|
buttonType: "dashRegular",
|
|
233
235
|
size: "small",
|
|
234
|
-
LeadingIcon:
|
|
236
|
+
LeadingIcon: te,
|
|
235
237
|
buttonText: "Add header",
|
|
236
|
-
onClick:
|
|
238
|
+
onClick: K
|
|
237
239
|
}
|
|
238
240
|
) })
|
|
239
241
|
] }),
|
|
@@ -246,7 +248,7 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
246
248
|
initialContent: w,
|
|
247
249
|
style: U,
|
|
248
250
|
placeholder: "Type or paste JSON here",
|
|
249
|
-
onChange: (e) =>
|
|
251
|
+
onChange: (e) => J(e.text),
|
|
250
252
|
minHeight: "120px",
|
|
251
253
|
maxHeight: "240px"
|
|
252
254
|
}
|
|
@@ -261,7 +263,7 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
261
263
|
style: U,
|
|
262
264
|
initialContent: E,
|
|
263
265
|
placeholder: "Type or paste JSON here",
|
|
264
|
-
onChange: (e) =>
|
|
266
|
+
onChange: (e) => Y(e.text),
|
|
265
267
|
minHeight: "120px",
|
|
266
268
|
maxHeight: "240px"
|
|
267
269
|
}
|
|
@@ -270,14 +272,14 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
270
272
|
]
|
|
271
273
|
}
|
|
272
274
|
);
|
|
273
|
-
},
|
|
275
|
+
}, fe = C.div`
|
|
274
276
|
display: grid;
|
|
275
277
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) 32px;
|
|
276
278
|
align-items: center;
|
|
277
279
|
gap: 8px;
|
|
278
|
-
`,
|
|
280
|
+
`, ye = C.div`
|
|
279
281
|
display: flex;
|
|
280
|
-
`,
|
|
282
|
+
`, ge = C.button`
|
|
281
283
|
display: inline-flex;
|
|
282
284
|
align-items: center;
|
|
283
285
|
justify-content: center;
|
|
@@ -298,6 +300,6 @@ const pe = ["GET", "POST", "PUT", "PATCH", "DELETE"], me = pe.map((s) => ({
|
|
|
298
300
|
};
|
|
299
301
|
export {
|
|
300
302
|
U as JsonFieldBox,
|
|
301
|
-
|
|
303
|
+
Ue as RestApiToolPanel
|
|
302
304
|
};
|
|
303
305
|
//# 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, { useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Button } from '@src/components/button';\nimport { Dropdown, unwrapDropdownValue } from '@src/components/dropdown';\nimport { SingleOption } from '@src/components/dropdown/type';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tRestApiHeader,\n\tRestApiMethod,\n\tRestApiToolConfig,\n} from '../AgentBuilder.model';\nimport { FieldBlock } from '../AgentBuilder.styled';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { ToolInstructionsField } from './ToolInstructionsField';\nimport { VariableInlineField } from './VariableInlineField';\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/**\n\t * Portal target for the drawer, passed straight to {@link SideModal}\n\t * (default `document.body`). Lets a host render it into its own positioned\n\t * slot rather than as a viewport overlay.\n\t */\n\telement?: Element | DocumentFragment;\n\t/** Names of the OTHER tools — a new tool can't reuse one of these. */\n\texistingNames?: string[];\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` opens the\n\t * variable picker directly in Instructions / Request URL / header values.\n\t * (Request / Response JSON editors are deliberately not wired for now.)\n\t * Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\nconst METHODS: RestApiMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\nconst METHOD_OPTIONS: SingleOption[] = METHODS.map((m) => ({\n\tlabel: m,\n\tvalue: m,\n}));\n\n// A callable endpoint needs an explicit http(s):// scheme AND a real, dotted\n// host. `new URL` alone is too lenient — it accepts single-label hosts\n// (\"https://abc\"), a one-slash scheme (\"https:/abc.com\"), and dangling-dot\n// hosts (\"https://.com\" / \"https://abc.\"). Require the `://` prefix on the raw\n// value plus a hostname that is either dotted (example.com) or an IPv4.\nconst isValidHttpUrl = (value: string): boolean => {\n\tif (!/^https?:\\/\\//i.test(value)) {\n\t\treturn false;\n\t}\n\tlet host: string;\n\ttry {\n\t\thost = new URL(value).hostname;\n\t} catch {\n\t\treturn false;\n\t}\n\treturn host.includes('.') && !host.startsWith('.') && !host.endsWith('.');\n};\n\n/**\n * Right-side drawer to configure a \"Rest API\" tool: the endpoint the agent can\n * call, plus a JSON request-body template and a sample response. Mount it fresh\n * per open (key it) so `initial` seeds the state. Built on the shared `SideModal`\n * shell and the BikEditor JSON body mode for the Request / Response editors.\n */\nexport const RestApiToolPanel: React.FC<RestApiToolPanelProps> = ({\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tzIndex,\n\texistingNames = [],\n\tvariablesData,\n\telement,\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\t// Stable per-row identity for React keys, parallel to `headers`. The value\n\t// field is an uncontrolled editor, so a row must keep its mount across\n\t// sibling add/remove — index-based keys would remount every row (dropping\n\t// focus mid-edit) or let a deleted row's text linger in a reused neighbour.\n\tconst headerIdsRef = useRef<number[]>(\n\t\t(initial?.headers ?? [{ key: '', value: '' }]).map(\n\t\t\t(_h: RestApiHeader, i: number) => i,\n\t\t),\n\t);\n\tconst nextHeaderIdRef = useRef(headerIdsRef.current.length);\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\theaderIdsRef.current = [...headerIdsRef.current, nextHeaderIdRef.current];\n\t\tnextHeaderIdRef.current += 1;\n\t\tsetHeaders((prev) => [...prev, { key: '', value: '' }]);\n\t};\n\tconst removeHeader = (i: number) => {\n\t\theaderIdsRef.current = headerIdsRef.current.filter((_, idx) => idx !== i);\n\t\tsetHeaders((prev) => prev.filter((_, idx) => idx !== i));\n\t};\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\t// A URL that interpolates variables can't be parsed literally (braces are\n\t// invalid URL characters) — accept it once a scheme + something follows;\n\t// it only becomes a concrete URL after runtime substitution.\n\tconst urlUsesVariables = urlTrimmed.includes('{{variable:');\n\tconst urlOk = urlUsesVariables\n\t\t? /^https?:\\/\\/./.test(urlTrimmed)\n\t\t: isValidHttpUrl(urlTrimmed);\n\tconst isUrlInvalid =\n\t\turlTrimmed.length > 0 && urlTrimmed !== 'https://' && !urlOk;\n\tconst canSave =\n\t\tnameTrimmed.length > 0 &&\n\t\turlOk &&\n\t\t!isDuplicateName &&\n\t\t// The editor's characterLimit is soft (a paste may exceed it, rendered\n\t\t// grey) — gate the save so over-limit instructions can't be persisted.\n\t\tinstructions.length <= charLimits.instructions;\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\telement={element}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText\n\t\t\t\t\ttitle=\"Rest API\"\n\t\t\t\t\tsubtitle=\"Connect to any API endpoint. Define the request and a sample response for the agent to reference.\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\twidth=\"431px\"\n\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\tonClose={onClose}\n\t\t\tsaveButtonProps={{\n\t\t\t\t'data-test': 'restapi-save',\n\t\t\t\tbuttonText: 'Save',\n\t\t\t\tbuttonType: 'primary',\n\t\t\t\tsize: 'small',\n\t\t\t\tdisabled: !canSave,\n\t\t\t\tisLoading: saving,\n\t\t\t\tonClick: handleSave,\n\t\t\t}}\n\t\t\tcancelButtonProps={{\n\t\t\t\t'data-test': 'restapi-cancel',\n\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\tsize: 'small',\n\t\t\t\tonClick: onClose,\n\t\t\t}}\n\t\t>\n\t\t\t<Input\n\t\t\t\tdata-test=\"restapi-name\"\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText=\"Name\"\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder=\"Enter action name\"\n\t\t\t\tvalue={name}\n\t\t\t\tmaxCharLimit={charLimits.name}\n\t\t\t\tstate={isDuplicateName ? 'invalid' : undefined}\n\t\t\t\terrorMessage={\n\t\t\t\t\tisDuplicateName ? 'A tool with this name already exists' : undefined\n\t\t\t\t}\n\t\t\t\tonChangeText={setName}\n\t\t\t/>\n\n\t\t\t<ToolInstructionsField\n\t\t\t\tdata-test=\"restapi-instructions\"\n\t\t\t\tlabel=\"Instructions\"\n\t\t\t\tvalue={instructions}\n\t\t\t\tonChange={setInstructions}\n\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\tplaceholder=\"Describe how should the LLM generate the rest API\"\n\t\t\t\tonImprove={onImprove}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t/>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<VariableInlineField\n\t\t\t\t\tdata-test=\"restapi-url\"\n\t\t\t\t\tlabel=\"Request URL\"\n\t\t\t\t\tplaceholder=\"https://\"\n\t\t\t\t\tvalue={url}\n\t\t\t\t\tonChange={setUrl}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t/>\n\t\t\t\t{/* VariableInlineField has no invalid state of its own — surface the\n\t\t\t\t URL validation (from main) as a caption below the field. */}\n\t\t\t\t{isUrlInvalid && (\n\t\t\t\t\t<BodyCaption color={COLORS.content.negative}>\n\t\t\t\t\t\tEnter a valid URL (including https://)\n\t\t\t\t\t</BodyCaption>\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<HeaderRow\n\t\t\t\t\t\tkey={headerIdsRef.current[i]}\n\t\t\t\t\t\tdata-test={`restapi-header-${i}`}\n\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 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<VariableInlineField\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\tonChange={(v) => patchHeader(i, { value: v })}\n\t\t\t\t\t\t\tvariablesData={variablesData}\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{/* Variables intentionally NOT wired here (yet) — the JSON editors are\n\t\t\t plain code fields; @ types a literal @. */}\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\n// Fixed tracks (name / value / delete): minmax(0, …) lets the fields shrink\n// below their content width, so a long value scrolls inside its field and the\n// delete button can never be pushed off the row.\nconst HeaderRow = styled.div`\n\tdisplay: grid;\n\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) 32px;\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","host","RestApiToolPanel","onClose","onSave","initial","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","existingNames","variablesData","element","name","setName","useState","instructions","setInstructions","url","setUrl","method","setMethod","headers","setHeaders","requestBody","setRequestBody","responseSample","setResponseSample","saving","setSaving","headerIdsRef","useRef","_h","i","nextHeaderIdRef","patchHeader","patch","prev","idx","addHeader","removeHeader","_","nameTrimmed","isDuplicateName","n","urlTrimmed","urlOk","isUrlInvalid","canSave","jsxs","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","config","h","result","Input","ToolInstructionsField","FieldBlock","VariableInlineField","BodyCaption","COLORS","TitleSmall","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, { useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Button } from '@src/components/button';\nimport { Dropdown, unwrapDropdownValue } from '@src/components/dropdown';\nimport { SingleOption } from '@src/components/dropdown/type';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tRestApiHeader,\n\tRestApiMethod,\n\tRestApiToolConfig,\n} from '../AgentBuilder.model';\nimport { FieldBlock } from '../AgentBuilder.styled';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { ToolInstructionsField } from './ToolInstructionsField';\nimport { VariableInlineField } from './VariableInlineField';\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/**\n\t * Portal target for the drawer, passed straight to {@link SideModal}\n\t * (default `document.body`). Lets a host render it into its own positioned\n\t * slot rather than as a viewport overlay.\n\t */\n\telement?: Element | DocumentFragment;\n\t/**\n\t * Footer button order, passed straight to {@link SideModal} (default\n\t * `'row'`). Hosts that show this drawer beside their own footer can set\n\t * `'row-reverse'` to line the Cancel / Save order up with it.\n\t */\n\tfooterDirection?: 'row' | 'row-reverse';\n\t/** Names of the OTHER tools — a new tool can't reuse one of these. */\n\texistingNames?: string[];\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` opens the\n\t * variable picker directly in Instructions / Request URL / header values.\n\t * (Request / Response JSON editors are deliberately not wired for now.)\n\t * Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n}\n\nconst METHODS: RestApiMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\nconst METHOD_OPTIONS: SingleOption[] = METHODS.map((m) => ({\n\tlabel: m,\n\tvalue: m,\n}));\n\n// A callable endpoint needs an explicit http(s):// scheme AND a real, dotted\n// host. `new URL` alone is too lenient — it accepts single-label hosts\n// (\"https://abc\"), a one-slash scheme (\"https:/abc.com\"), and dangling-dot\n// hosts (\"https://.com\" / \"https://abc.\"). Require the `://` prefix on the raw\n// value plus a hostname that is either dotted (example.com) or an IPv4.\nconst isValidHttpUrl = (value: string): boolean => {\n\tif (!/^https?:\\/\\//i.test(value)) {\n\t\treturn false;\n\t}\n\tlet host: string;\n\ttry {\n\t\thost = new URL(value).hostname;\n\t} catch {\n\t\treturn false;\n\t}\n\treturn host.includes('.') && !host.startsWith('.') && !host.endsWith('.');\n};\n\n/**\n * Right-side drawer to configure a \"Rest API\" tool: the endpoint the agent can\n * call, plus a JSON request-body template and a sample response. Mount it fresh\n * per open (key it) so `initial` seeds the state. Built on the shared `SideModal`\n * shell and the BikEditor JSON body mode for the Request / Response editors.\n */\nexport const RestApiToolPanel: React.FC<RestApiToolPanelProps> = ({\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tzIndex,\n\texistingNames = [],\n\tvariablesData,\n\telement,\n\tfooterDirection,\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\t// Stable per-row identity for React keys, parallel to `headers`. The value\n\t// field is an uncontrolled editor, so a row must keep its mount across\n\t// sibling add/remove — index-based keys would remount every row (dropping\n\t// focus mid-edit) or let a deleted row's text linger in a reused neighbour.\n\tconst headerIdsRef = useRef<number[]>(\n\t\t(initial?.headers ?? [{ key: '', value: '' }]).map(\n\t\t\t(_h: RestApiHeader, i: number) => i,\n\t\t),\n\t);\n\tconst nextHeaderIdRef = useRef(headerIdsRef.current.length);\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\theaderIdsRef.current = [...headerIdsRef.current, nextHeaderIdRef.current];\n\t\tnextHeaderIdRef.current += 1;\n\t\tsetHeaders((prev) => [...prev, { key: '', value: '' }]);\n\t};\n\tconst removeHeader = (i: number) => {\n\t\theaderIdsRef.current = headerIdsRef.current.filter((_, idx) => idx !== i);\n\t\tsetHeaders((prev) => prev.filter((_, idx) => idx !== i));\n\t};\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\t// A URL that interpolates variables can't be parsed literally (braces are\n\t// invalid URL characters) — accept it once a scheme + something follows;\n\t// it only becomes a concrete URL after runtime substitution.\n\tconst urlUsesVariables = urlTrimmed.includes('{{variable:');\n\tconst urlOk = urlUsesVariables\n\t\t? /^https?:\\/\\/./.test(urlTrimmed)\n\t\t: isValidHttpUrl(urlTrimmed);\n\tconst isUrlInvalid =\n\t\turlTrimmed.length > 0 && urlTrimmed !== 'https://' && !urlOk;\n\tconst canSave =\n\t\tnameTrimmed.length > 0 &&\n\t\turlOk &&\n\t\t!isDuplicateName &&\n\t\t// The editor's characterLimit is soft (a paste may exceed it, rendered\n\t\t// grey) — gate the save so over-limit instructions can't be persisted.\n\t\tinstructions.length <= charLimits.instructions;\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\telement={element}\n\t\t\tfooterDirection={footerDirection}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText\n\t\t\t\t\ttitle=\"Rest API\"\n\t\t\t\t\tsubtitle=\"Connect to any API endpoint. Define the request and a sample response for the agent to reference.\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\twidth=\"431px\"\n\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\tonClose={onClose}\n\t\t\tsaveButtonProps={{\n\t\t\t\t'data-test': 'restapi-save',\n\t\t\t\tbuttonText: 'Save',\n\t\t\t\tbuttonType: 'primary',\n\t\t\t\tsize: 'small',\n\t\t\t\tdisabled: !canSave,\n\t\t\t\tisLoading: saving,\n\t\t\t\tonClick: handleSave,\n\t\t\t}}\n\t\t\tcancelButtonProps={{\n\t\t\t\t'data-test': 'restapi-cancel',\n\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\tsize: 'small',\n\t\t\t\tonClick: onClose,\n\t\t\t}}\n\t\t>\n\t\t\t<Input\n\t\t\t\tdata-test=\"restapi-name\"\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText=\"Name\"\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder=\"Enter action name\"\n\t\t\t\tvalue={name}\n\t\t\t\tmaxCharLimit={charLimits.name}\n\t\t\t\tstate={isDuplicateName ? 'invalid' : undefined}\n\t\t\t\terrorMessage={\n\t\t\t\t\tisDuplicateName ? 'A tool with this name already exists' : undefined\n\t\t\t\t}\n\t\t\t\tonChangeText={setName}\n\t\t\t/>\n\n\t\t\t<ToolInstructionsField\n\t\t\t\tdata-test=\"restapi-instructions\"\n\t\t\t\tlabel=\"Instructions\"\n\t\t\t\tvalue={instructions}\n\t\t\t\tonChange={setInstructions}\n\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\tplaceholder=\"Describe how should the LLM generate the rest API\"\n\t\t\t\tonImprove={onImprove}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t/>\n\n\t\t\t<FieldBlock>\n\t\t\t\t<VariableInlineField\n\t\t\t\t\tdata-test=\"restapi-url\"\n\t\t\t\t\tlabel=\"Request URL\"\n\t\t\t\t\tplaceholder=\"https://\"\n\t\t\t\t\tvalue={url}\n\t\t\t\t\tonChange={setUrl}\n\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t/>\n\t\t\t\t{/* VariableInlineField has no invalid state of its own — surface the\n\t\t\t\t URL validation (from main) as a caption below the field. */}\n\t\t\t\t{isUrlInvalid && (\n\t\t\t\t\t<BodyCaption color={COLORS.content.negative}>\n\t\t\t\t\t\tEnter a valid URL (including https://)\n\t\t\t\t\t</BodyCaption>\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<HeaderRow\n\t\t\t\t\t\tkey={headerIdsRef.current[i]}\n\t\t\t\t\t\tdata-test={`restapi-header-${i}`}\n\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 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<VariableInlineField\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\tonChange={(v) => patchHeader(i, { value: v })}\n\t\t\t\t\t\t\tvariablesData={variablesData}\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{/* Variables intentionally NOT wired here (yet) — the JSON editors are\n\t\t\t plain code fields; @ types a literal @. */}\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\n// Fixed tracks (name / value / delete): minmax(0, …) lets the fields shrink\n// below their content width, so a long value scrolls inside its field and the\n// delete button can never be pushed off the row.\nconst HeaderRow = styled.div`\n\tdisplay: grid;\n\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) 32px;\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","host","RestApiToolPanel","onClose","onSave","initial","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","existingNames","variablesData","element","footerDirection","name","setName","useState","instructions","setInstructions","url","setUrl","method","setMethod","headers","setHeaders","requestBody","setRequestBody","responseSample","setResponseSample","saving","setSaving","headerIdsRef","useRef","_h","i","nextHeaderIdRef","patchHeader","patch","prev","idx","addHeader","removeHeader","_","nameTrimmed","isDuplicateName","n","urlTrimmed","urlOk","isUrlInvalid","canSave","jsxs","SideModal","jsx","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","config","h","result","Input","ToolInstructionsField","FieldBlock","VariableInlineField","BodyCaption","COLORS","TitleSmall","Dropdown","opt","v","unwrapDropdownValue","HeaderRow","IconBtn","DeleteIcon","AddHeaderRow","Button","PlusIcon","BikEditor","JsonFieldBox","c","styled"],"mappings":";;;;;;;;;;;;;;;;;;AA+DA,MAAMA,KAA2B,CAAC,OAAO,QAAQ,OAAO,SAAS,QAAQ,GACnEC,KAAiCD,GAAQ,IAAI,CAACE,OAAO;AAAA,EAC1D,OAAOA;AAAA,EACP,OAAOA;AACR,EAAE,GAOIC,KAAiB,CAACC,MAA2B;AAClD,MAAI,CAAC,gBAAgB,KAAKA,CAAK;AAC9B,WAAO;AAER,MAAIC;AACJ,MAAI;AACH,IAAAA,IAAO,IAAI,IAAID,CAAK,EAAE;AAAA,EACvB,QAAQ;AACP,WAAO;AAAA,EACR;AACA,SAAOC,EAAK,SAAS,GAAG,KAAK,CAACA,EAAK,WAAW,GAAG,KAAK,CAACA,EAAK,SAAS,GAAG;AACzE,GAQaC,KAAoD,CAAC;AAAA,EACjE,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,YAAAC,IAAaC;AAAA,EACb,QAAAC;AAAA,EACA,eAAAC,IAAgB,CAAA;AAAA,EAChB,eAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC;AACD,MAAM;AACL,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAASX,GAAS,QAAQ,EAAE,GAC9C,CAACY,GAAcC,CAAe,IAAIF,EAASX,GAAS,gBAAgB,EAAE,GAEtE,CAACc,GAAKC,CAAM,IAAIJ,EAASX,GAAS,OAAO,UAAU,GACnD,CAACgB,GAAQC,CAAS,IAAIN;AAAA,IAC3BX,GAAS,UAAU;AAAA,EAAA,GAEd,CAACkB,GAASC,CAAU,IAAIR;AAAA,IAC7BX,GAAS,WAAW,CAAC,EAAE,KAAK,IAAI,OAAO,IAAI;AAAA,EAAA,GAEtC,CAACoB,GAAaC,CAAc,IAAIV,EAASX,GAAS,eAAe,EAAE,GACnE,CAACsB,GAAgBC,CAAiB,IAAIZ;AAAA,IAC3CX,GAAS,kBAAkB;AAAA,EAAA,GAEtB,CAACwB,GAAQC,CAAS,IAAId,EAAS,EAAK,GAMpCe,IAAeC;AAAA,KACnB3B,GAAS,WAAW,CAAC,EAAE,KAAK,IAAI,OAAO,GAAA,CAAI,GAAG;AAAA,MAC9C,CAAC4B,GAAmBC,MAAcA;AAAA,IAAA;AAAA,EACnC,GAEKC,IAAkBH,EAAOD,EAAa,QAAQ,MAAM,GAEpDK,IAAc,CAACF,GAAWG,MAC/Bb;AAAA,IAAW,CAACc,MACXA,EAAK,IAAI,CAAC,GAAGC,MAASA,MAAQL,IAAI,EAAE,GAAG,GAAG,GAAGG,EAAA,IAAU,CAAE;AAAA,EAAA,GAErDG,IAAY,MAAM;AACvB,IAAAT,EAAa,UAAU,CAAC,GAAGA,EAAa,SAASI,EAAgB,OAAO,GACxEA,EAAgB,WAAW,GAC3BX,EAAW,CAACc,MAAS,CAAC,GAAGA,GAAM,EAAE,KAAK,IAAI,OAAO,GAAA,CAAI,CAAC;AAAA,EACvD,GACMG,IAAe,CAACP,MAAc;AACnC,IAAAH,EAAa,UAAUA,EAAa,QAAQ,OAAO,CAACW,GAAGH,MAAQA,MAAQL,CAAC,GACxEV,EAAW,CAACc,MAASA,EAAK,OAAO,CAACI,GAAGH,MAAQA,MAAQL,CAAC,CAAC;AAAA,EACxD,GAEMS,IAAc7B,EAAK,KAAA,GAEnB8B,IACLD,EAAY,SAAS,KACrBjC,EAAc;AAAA,IACb,CAACmC,MAAMA,EAAE,KAAA,EAAO,YAAA,MAAkBF,EAAY,YAAA;AAAA,EAAY,GAEtDG,IAAa3B,EAAI,KAAA,GAOjB4B,IADmBD,EAAW,SAAS,aAAa,IAEvD,gBAAgB,KAAKA,CAAU,IAC/B/C,GAAe+C,CAAU,GACtBE,IACLF,EAAW,SAAS,KAAKA,MAAe,cAAc,CAACC,GAClDE,IACLN,EAAY,SAAS,KACrBI,KACA,CAACH;AAAA;AAAA,EAGD3B,EAAa,UAAUV,EAAW;AA4BnC,SACC,gBAAA2C;AAAA,IAACC;AAAA,IAAA;AAAA,MACA,QAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,QAAA1C;AAAA,MACA,SAAAG;AAAA,MACA,iBAAAC;AAAA,MACA,uBACC,gBAAAuC;AAAA,QAACC;AAAA,QAAA;AAAA,UACA,OAAM;AAAA,UACN,UAAS;AAAA,QAAA;AAAA,MAAA;AAAA,MAGX,OAAM;AAAA,MACN,aAAaC;AAAA,MACb,WAAWC;AAAA,MACX,SAAApD;AAAA,MACA,iBAAiB;AAAA,QAChB,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,UAAU,CAAC8C;AAAA,QACX,WAAWpB;AAAA,QACX,SAlDgB,YAAY;AAC9B,cAAI,CAACoB,KAAWpB;AACf;AAED,gBAAM2B,IAA4B;AAAA,YACjC,IAAInD,GAAS,MAAM,WAAW,KAAK,MAAM,SAAS,EAAE,CAAC;AAAA,YACrD,MAAMS,EAAK,KAAA;AAAA,YACX,cAAAG;AAAA,YACA,KAAKE,EAAI,KAAA;AAAA,YACT,QAAAE;AAAA;AAAA,YAEA,SAASE,EAAQ,OAAO,CAACkC,MAAMA,EAAE,IAAI,UAAUA,EAAE,MAAM,KAAA,CAAM;AAAA,YAC7D,aAAAhC;AAAA,YACA,gBAAAE;AAAA,UAAA,GAEK+B,IAAStD,EAAOoD,CAAM;AAC5B,cAAIE,KAAU,OAAQA,EAAyB,QAAS,YAAY;AACnE,YAAA5B,EAAU,EAAI;AACd,gBAAI;AACH,oBAAM4B;AAAA,YACP,UAAA;AACC,cAAA5B,EAAU,EAAK;AAAA,YAChB;AAAA,UACD;AAAA,QACD;AAAA,MA0BY;AAAA,MAEV,mBAAmB;AAAA,QAClB,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,SAAS3B;AAAA,MAAA;AAAA,MAGV,UAAA;AAAA,QAAA,gBAAAiD;AAAA,UAACO;AAAA,UAAA;AAAA,YACA,aAAU;AAAA,YACV,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,eAAa;AAAA,YACb,aAAY;AAAA,YACZ,OAAO7C;AAAA,YACP,cAAcP,EAAW;AAAA,YACzB,OAAOqC,IAAkB,YAAY;AAAA,YACrC,cACCA,IAAkB,yCAAyC;AAAA,YAE5D,cAAc7B;AAAA,UAAA;AAAA,QAAA;AAAA,QAGf,gBAAAqC;AAAA,UAACQ;AAAA,UAAA;AAAA,YACA,aAAU;AAAA,YACV,OAAM;AAAA,YACN,OAAO3C;AAAA,YACP,UAAUC;AAAA,YACV,WAAWX,EAAW;AAAA,YACtB,aAAY;AAAA,YACZ,WAAAD;AAAA,YACA,eAAAK;AAAA,UAAA;AAAA,QAAA;AAAA,0BAGAkD,GAAA,EACA,UAAA;AAAA,UAAA,gBAAAT;AAAA,YAACU;AAAA,YAAA;AAAA,cACA,aAAU;AAAA,cACV,OAAM;AAAA,cACN,aAAY;AAAA,cACZ,OAAO3C;AAAA,cACP,UAAUC;AAAA,cACV,eAAAT;AAAA,YAAA;AAAA,UAAA;AAAA,UAIAqC,KACA,gBAAAI,EAACW,IAAA,EAAY,OAAOC,EAAO,QAAQ,UAAU,UAAA,yCAAA,CAE7C;AAAA,QAAA,GAEF;AAAA,0BAECH,GAAA,EACA,UAAA;AAAA,UAAA,gBAAAT,EAACa,GAAA,EAAW,OAAOD,EAAO,QAAQ,SAAS,UAAA,eAAW;AAAA,UACtD,gBAAAZ;AAAA,YAACc;AAAA,YAAA;AAAA,cACA,aAAU;AAAA,cACV,MAAK;AAAA,cACL,OAAM;AAAA,cACN,eAAc;AAAA,cACd,SAASrE;AAAA,cACT,gBAAgB,CAAC,EAAE,OAAOwB,GAAQ,OAAOA,GAAQ;AAAA,cACjD,UAAU,CAAC8C,MAAQ;AAClB,sBAAMC,IAAIC,GAAoBF,CAAG;AACjC,gBAAIC,KACH9C,EAAU8C,CAAkB;AAAA,cAE9B;AAAA,YAAA;AAAA,UAAA;AAAA,QACD,GACD;AAAA,0BAECP,GAAA,EACA,UAAA;AAAA,UAAA,gBAAAT,EAACa,GAAA,EAAW,OAAOD,EAAO,QAAQ,SAAS,UAAA,WAAO;AAAA,UACjDzC,EAAQ,IAAI,CAACkC,GAAGvB,MAChB,gBAAAgB;AAAA,YAACoB;AAAA,YAAA;AAAA,cAEA,aAAW,kBAAkBpC,CAAC;AAAA,cAE9B,UAAA;AAAA,gBAAA,gBAAAkB;AAAA,kBAACO;AAAA,kBAAA;AAAA,oBACA,SAAQ;AAAA,oBACR,iBAAe;AAAA,oBACf,aAAY;AAAA,oBACZ,OAAOF,EAAE;AAAA,oBACT,cAAc,CAACW,MAAMhC,EAAYF,GAAG,EAAE,KAAKkC,GAAG;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAE/C,gBAAAhB;AAAA,kBAACU;AAAA,kBAAA;AAAA,oBACA,aAAY;AAAA,oBACZ,OAAOL,EAAE;AAAA,oBACT,UAAU,CAACW,MAAMhC,EAAYF,GAAG,EAAE,OAAOkC,GAAG;AAAA,oBAC5C,eAAAzD;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAED,gBAAAyC;AAAA,kBAACmB;AAAA,kBAAA;AAAA,oBACA,MAAK;AAAA,oBACL,cAAW;AAAA,oBACX,aAAW,yBAAyBrC,CAAC;AAAA,oBACrC,SAAS,MAAMO,EAAaP,CAAC;AAAA,oBAE7B,UAAA,gBAAAkB;AAAA,sBAACoB;AAAAA,sBAAA;AAAA,wBACA,OAAO;AAAA,wBACP,QAAQ;AAAA,wBACR,OAAOR,EAAO,QAAQ;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACvB;AAAA,gBAAA;AAAA,cACD;AAAA,YAAA;AAAA,YA3BKjC,EAAa,QAAQG,CAAC;AAAA,UAAA,CA6B5B;AAAA,4BACAuC,IAAA,EACA,UAAA,gBAAArB;AAAA,YAACsB;AAAA,YAAA;AAAA,cACA,aAAU;AAAA,cACV,YAAW;AAAA,cACX,MAAK;AAAA,cACL,aAAaC;AAAAA,cACb,YAAW;AAAA,cACX,SAASnC;AAAA,YAAA;AAAA,UAAA,EACV,CACD;AAAA,QAAA,GACD;AAAA,0BAICqB,GAAA,EACA,UAAA;AAAA,UAAA,gBAAAT,EAACa,GAAA,EAAW,OAAOD,EAAO,QAAQ,SAAS,UAAA,YAAQ;AAAA,UACnD,gBAAAZ;AAAA,YAACwB;AAAA,YAAA;AAAA,cACA,UAAU,EAAE,UAAU,GAAA;AAAA,cACtB,gBAAgBnD;AAAA,cAChB,OAAOoD;AAAA,cACP,aAAY;AAAA,cACZ,UAAU,CAACC,MAAMpD,EAAeoD,EAAE,IAAI;AAAA,cACtC,WAAU;AAAA,cACV,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACX,GACD;AAAA,0BAECjB,GAAA,EACA,UAAA;AAAA,UAAA,gBAAAT,EAACa,GAAA,EAAW,OAAOD,EAAO,QAAQ,SAAS,UAAA,aAAS;AAAA,UACpD,gBAAAZ;AAAA,YAACwB;AAAA,YAAA;AAAA,cACA,UAAU,EAAE,UAAU,GAAA;AAAA,cACtB,OAAOC;AAAA,cACP,gBAAgBlD;AAAA,cAChB,aAAY;AAAA,cACZ,UAAU,CAACmD,MAAMlD,EAAkBkD,EAAE,IAAI;AAAA,cACzC,WAAU;AAAA,cACV,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACX,EAAA,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGH,GAKMR,KAAYS,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,GAOnBN,KAAeM,EAAO;AAAA;AAAA,GAItBR,KAAUQ,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAOFf,EAAO,OAAO,OAAO;AAAA;AAAA,eAE3BA,EAAO,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA,kBAIpBA,EAAO,QAAQ,SAAS;AAAA;AAAA,GAI7Ba,IAAe;AAAA,EAC3B,cAAc;AAAA,EACd,UAAU;AACX;"}
|