{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tool-call",
  "type": "registry:ui",
  "title": "Tool Call",
  "description": "A tool invocation as one quiet row that opens into its JSON, live timer included.",
  "categories": [
    "ai-agents"
  ],
  "dependencies": [
    "@base-ui/react",
    "@number-flow/react",
    "motion"
  ],
  "registryDependencies": [
    "https://www.stealth.pm/r/tokens.json",
    "https://www.stealth.pm/r/cn.json",
    "https://www.stealth.pm/r/motion.json",
    "https://www.stealth.pm/r/copy-button.json"
  ],
  "files": [
    {
      "path": "components/ui/tool-call.tsx",
      "content": "\"use client\";\nimport { Collapsible } from \"@base-ui/react/collapsible\";\nimport NumberFlow from \"@number-flow/react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport { createContext, useContext, useMemo, useSyncExternalStore } from \"react\";\nimport { CopyButton } from \"@/components/ui/copy-button\";\nimport { cn } from \"@/lib/cn\";\nimport { ease, spring } from \"@/lib/motion\";\n\nexport type ToolCallStatus = \"running\" | \"done\" | \"error\" | \"canceled\";\ntype Time = number | Date;\nconst toMs = (t: Time | undefined) => (t == null ? undefined : typeof t === \"number\" ? t : t.getTime());\n\n// One clock for every running call on the page, ticking on the second boundary\n// so all timers change together. It sleeps while the tab is hidden; elapsed time\n// is derived from Date.now, so nothing drifts.\nconst clock = (() => {\n  let now = 0;\n  let timer = 0;\n  const subs = new Set<() => void>();\n  const emit = () => {\n    now = Date.now();\n    subs.forEach((fn) => fn());\n  };\n  const schedule = () => {\n    window.clearTimeout(timer);\n    if (document.hidden) return;\n    timer = window.setTimeout(() => {\n      emit();\n      schedule();\n    }, 1000 - (Date.now() % 1000) + 4);\n  };\n  const onVisibility = () => {\n    if (!document.hidden) emit();\n    schedule();\n  };\n  return {\n    subscribe(fn: () => void) {\n      subs.add(fn);\n      if (subs.size === 1) {\n        now = Date.now();\n        schedule();\n        document.addEventListener(\"visibilitychange\", onVisibility);\n      }\n      return () => {\n        subs.delete(fn);\n        if (subs.size) return;\n        window.clearTimeout(timer);\n        document.removeEventListener(\"visibilitychange\", onVisibility);\n        now = 0;\n      };\n    },\n    get: () => (now ||= Date.now()),\n  };\n})();\nconst idle = () => () => {};\n\n/** Milliseconds a call has run: fixed once it ends, live (once a second) while it runs, null before hydration. */\nexport function useToolCallElapsed({ startedAt, endedAt, duration }: { startedAt?: Time; endedAt?: Time; duration?: number }) {\n  const start = toMs(startedAt);\n  const end = toMs(endedAt);\n  const live = duration == null && start != null && end == null;\n  const now = useSyncExternalStore(live ? clock.subscribe : idle, clock.get, () => null);\n  if (duration != null) return duration;\n  if (start == null) return null;\n  if (end != null) return Math.max(0, end - start);\n  return now == null ? null : Math.max(0, now - start);\n}\n\n/** 84ms · 1.4s · 12s · 2m 03s. Precise when short, calm when long. */\nexport function formatToolDuration(ms: number) {\n  if (ms < 1000) return `${Math.max(1, Math.round(ms))}ms`;\n  if (ms < 10_000) return `${(Math.floor(ms / 100) / 10).toFixed(1)}s`;\n  const s = Math.floor(ms / 1000);\n  if (s < 60) return `${s}s`;\n  return `${Math.floor(s / 60)}m ${String(s % 60).padStart(2, \"0\")}s`;\n}\n\nconst spoken: Record<ToolCallStatus, string> = { running: \"running\", done: \"done\", error: \"failed\", canceled: \"canceled\" };\n\n// Inside a group, calls drop their own frame and sit as rows of the group's card.\nconst Nested = createContext(false);\n\nexport type ToolCallProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  /** The tool, as a verb or its id: \"Search\", \"read_file\". */\n  name: string;\n  /** What it acted on: a path, a query, a URL. Monospaced and truncated from the end. */\n  target?: React.ReactNode;\n  status: ToolCallStatus;\n  /** A small glyph for the kind of tool, drawn at 16px in currentColor. */\n  icon?: React.ReactNode;\n  /** The arguments. Objects and arrays are shown as formatted JSON; strings as they are. */\n  input?: unknown;\n  /** The result, shown the same way. */\n  output?: unknown;\n  /** What went wrong, when the status is error. Shown in the row, and in full when expanded. */\n  error?: React.ReactNode;\n  /** One short result at the end of the row once done: \"3 hits\", \"200 OK\". */\n  summary?: React.ReactNode;\n  /** When the call started. With no endedAt and no duration, the timer runs. */\n  startedAt?: Time;\n  endedAt?: Time;\n  /** Milliseconds, when you already know it. Wins over startedAt/endedAt. */\n  duration?: number;\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n};\n\nexport function ToolCall({\n  name,\n  target,\n  status,\n  icon,\n  input,\n  output,\n  error,\n  summary,\n  startedAt,\n  endedAt,\n  duration,\n  open,\n  defaultOpen,\n  onOpenChange,\n  className,\n  ...rest\n}: ToolCallProps) {\n  const nested = useContext(Nested);\n  const elapsed = useToolCallElapsed({ startedAt, endedAt, duration });\n  const hasInput = input !== undefined;\n  const hasOutput = output !== undefined;\n  const failed = status === \"error\";\n  const expandable = hasInput || hasOutput || (failed && error != null);\n\n  const row = \"group/trigger relative flex h-9 w-full min-w-0 select-none items-center gap-2 pl-2 pr-2.5 text-left\";\n  const header = (\n    <>\n      <span className={cn(\"grid size-4 shrink-0 place-items-center text-fg-4 transition-colors duration-150 group-hover/trigger:text-fg-3 group-data-[panel-open]/trigger:text-fg-2\", !expandable && \"invisible\")}>\n        <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.4} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className=\"transition-[rotate] duration-[240ms] ease-in-out-quart motion-reduce:transition-none group-data-[panel-open]/trigger:rotate-90\">\n          <path d=\"m6.25 4.5 3.5 3.5-3.5 3.5\" />\n        </svg>\n      </span>\n\n      {icon != null && <span aria-hidden className=\"-ml-0.5 grid size-4 shrink-0 place-items-center text-fg-3 [&>svg]:size-4\">{icon}</span>}\n\n      <span className={cn(\"shrink-0 text-[13px] font-medium tracking-[-0.006em]\", status === \"canceled\" ? \"text-fg-3\" : \"text-fg\")}>\n        <Sheen active={status === \"running\"}>{name}</Sheen>\n      </span>\n\n      {target != null ? <span className=\"min-w-0 flex-1 truncate font-mono text-[12px] text-fg-2\">{target}</span> : <span className=\"flex-1\" />}\n\n      <Meta status={status} error={error} summary={summary} elapsed={elapsed} />\n\n      <span className=\"sr-only\">, {spoken[status]}</span>\n    </>\n  );\n\n  return (\n    <Collapsible.Root\n      open={open}\n      defaultOpen={defaultOpen}\n      onOpenChange={(next) => onOpenChange?.(next)}\n      data-status={status}\n      className={cn(\n        \"group/tool @container/tool relative min-w-0\",\n        !nested && \"rounded-lg border border-line bg-raised shadow-[var(--shadow)] transition-[border-color] duration-200 data-[status=error]:border-danger/30\",\n        className,\n      )}\n      {...rest}\n    >\n      {/* A call with nothing to show is a plain row, not a button that does nothing. */}\n      {expandable ? (\n        <Collapsible.Trigger\n          className={cn(\n            row,\n            \"touch-manipulation [-webkit-tap-highlight-color:transparent]\",\n            \"outline-none focus-visible:outline-solid focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-fg-3\",\n            \"transition-[background-color] duration-150 hover:bg-hover active:bg-fg/[0.06] active:duration-75\",\n            nested ? \"rounded-md\" : \"rounded-[7px] group-data-[open]/tool:rounded-b-none\",\n          )}\n        >\n          {header}\n        </Collapsible.Trigger>\n      ) : (\n        <div className={row}>{header}</div>\n      )}\n\n      {expandable && (\n        <Collapsible.Panel\n          className={cn(\n            \"group/panel h-(--collapsible-panel-height) overflow-hidden\",\n            \"transition-[height] duration-[260ms] ease-out-quart data-ending-style:duration-200 data-ending-style:ease-in-out-quart\",\n            \"data-starting-style:h-0 data-ending-style:h-0 motion-reduce:transition-none\",\n          )}\n        >\n          <div\n            className={cn(\n              \"flex flex-col gap-3 pb-3 pt-2.5\",\n              nested ? \"pl-8 pr-2\" : \"border-t border-line px-3\",\n              \"transition-[opacity,translate] delay-[50ms] duration-[280ms] ease-out-expo\",\n              \"group-data-[starting-style]/panel:-translate-y-1 group-data-[starting-style]/panel:opacity-0\",\n              \"group-data-[ending-style]/panel:opacity-0 group-data-[ending-style]/panel:delay-0 group-data-[ending-style]/panel:duration-[140ms]\",\n              \"motion-reduce:translate-y-0 motion-reduce:delay-0\",\n            )}\n          >\n            {hasInput && <Payload label=\"Input\" value={input} />}\n            {hasOutput ? (\n              <Payload label=\"Output\" value={output} />\n            ) : status === \"running\" ? (\n              <section className=\"flex flex-col gap-1.5\">\n                <h4 className=\"font-mono text-2xs uppercase tracking-[0.08em] text-fg-3\">Output</h4>\n                <p className=\"text-[12px] text-fg-3\">\n                  <Sheen active>Waiting for the result</Sheen>\n                </p>\n              </section>\n            ) : null}\n            {failed && error != null && (\n              <section className=\"flex flex-col gap-1.5\">\n                <h4 className=\"font-mono text-2xs uppercase tracking-[0.08em] text-danger\">Error</h4>\n                <div className=\"rounded-md border border-danger/20 bg-danger-soft px-2.5 py-2 font-mono text-[12px] leading-[18px] text-danger [overflow-wrap:anywhere]\">\n                  {error}\n                </div>\n              </section>\n            )}\n          </div>\n        </Collapsible.Panel>\n      )}\n    </Collapsible.Root>\n  );\n}\n\n/** The right end of the row: summary or error, then the duration, then the status glyph. */\nfunction Meta({ status, error, summary, elapsed }: { status: ToolCallStatus; error?: React.ReactNode; summary?: React.ReactNode; elapsed: number | null }) {\n  const reduce = useReducedMotion();\n  // A running timer only appears after a second, so fast calls never flash \"0s\".\n  const showTime = elapsed != null && (status !== \"running\" || elapsed >= 1000);\n  const note = status === \"error\" ? (error ?? \"Failed\") : status === \"canceled\" ? \"Canceled\" : status === \"done\" ? summary : null;\n  return (\n    <span className=\"ml-auto flex min-w-0 shrink items-center gap-2 pl-1\">\n      <AnimatePresence initial={false} mode=\"popLayout\">\n        {note != null && (\n          <motion.span\n            key={status}\n            className={cn(\n              \"min-w-0 truncate text-[12px]\",\n              // In a narrow column the target keeps the room; the error is one tap away in the panel.\n              status === \"error\" ? \"max-w-[22ch] text-danger @max-[26rem]/tool:hidden\" : \"max-w-[16ch] text-fg-3\",\n            )}\n            initial={reduce ? { opacity: 0 } : { opacity: 0, x: 4, filter: \"blur(2px)\" }}\n            animate={{ opacity: 1, x: 0, filter: \"blur(0px)\" }}\n            exit={{ opacity: 0, transition: { duration: 0.1 } }}\n            transition={{ duration: reduce ? 0.15 : 0.24, ease: ease.out }}\n          >\n            {note}\n          </motion.span>\n        )}\n      </AnimatePresence>\n      {showTime && (\n        <span className=\"shrink-0 text-[12px] tabular text-fg-3\">\n          {status === \"running\" ? <NumberFlow value={Math.floor(elapsed / 1000)} suffix=\"s\" /> : formatToolDuration(elapsed)}\n        </span>\n      )}\n      <span className=\"relative grid size-4 shrink-0 place-items-center\">\n        <AnimatePresence initial={false}>\n          <motion.span\n            key={status}\n            className=\"absolute inset-0 grid place-items-center\"\n            initial={reduce ? { opacity: 0 } : { opacity: 0, scale: 0.5, filter: \"blur(3px)\" }}\n            animate={{ opacity: 1, scale: 1, filter: \"blur(0px)\" }}\n            exit={reduce ? { opacity: 0, transition: { duration: 0.1 } } : { opacity: 0, scale: 0.5, filter: \"blur(3px)\", transition: { duration: 0.12, ease: ease.in } }}\n            transition={reduce ? { duration: 0.15 } : spring.pop}\n          >\n            <StatusGlyph status={status} reduce={!!reduce} />\n          </motion.span>\n        </AnimatePresence>\n      </span>\n    </span>\n  );\n}\n\nconst stroke = { width: 16, height: 16, viewBox: \"0 0 16 16\", fill: \"none\", stroke: \"currentColor\", strokeWidth: 1.5, strokeLinecap: \"round\" as const, strokeLinejoin: \"round\" as const, \"aria-hidden\": true };\n\nfunction StatusGlyph({ status, reduce }: { status: ToolCallStatus; reduce: boolean }) {\n  // The same attributes either way so server and client markup agree; reduced motion just doesn't draw.\n  const draw = (delay = 0.05) => ({\n    initial: { pathLength: reduce ? 1 : 0 },\n    animate: { pathLength: 1 },\n    transition: reduce ? { duration: 0 } : { duration: 0.3, ease: ease.out, delay },\n  });\n  if (status === \"running\")\n    return (\n      <svg {...stroke} className=\"animate-spin text-fg-2 [animation-duration:0.8s]\">\n        <circle cx=\"8\" cy=\"8\" r=\"5.5\" stroke=\"var(--line-2)\" />\n        <path d=\"M8 2.5a5.5 5.5 0 0 1 5.5 5.5\" />\n      </svg>\n    );\n  if (status === \"done\")\n    return (\n      <svg {...stroke} className=\"text-success\">\n        <motion.path d=\"M3.5 8.5 6.5 11.5 12.5 4.5\" {...draw()} />\n      </svg>\n    );\n  if (status === \"error\")\n    return (\n      <svg {...stroke} className=\"text-danger\">\n        <motion.path d=\"m4.5 4.5 7 7\" {...draw()} />\n        <motion.path d=\"m11.5 4.5-7 7\" {...draw(0.12)} />\n      </svg>\n    );\n  return (\n    <svg {...stroke} className=\"text-fg-4\">\n      <circle cx=\"8\" cy=\"8\" r=\"5.5\" />\n      <path d=\"M5.75 8h4.5\" />\n    </svg>\n  );\n}\n\n// A sheen crosses the words only while the call is actually working.\n// Reduced motion keeps the plain label.\nfunction Sheen({ active, children }: { active: boolean; children: React.ReactNode }) {\n  if (!active) return <>{children}</>;\n  return (\n    <span\n      className={cn(\n        \"bg-[linear-gradient(90deg,var(--fg-3)_0%,var(--fg-3)_40%,var(--fg)_50%,var(--fg-3)_60%,var(--fg-3)_100%)]\",\n        \"animate-shine bg-clip-text [background-size:250%_100%] [-webkit-text-fill-color:transparent] rtl:[animation-direction:reverse]\",\n        \"motion-reduce:animate-none motion-reduce:bg-none motion-reduce:[-webkit-text-fill-color:currentColor]\",\n      )}\n    >\n      {children}\n    </span>\n  );\n}\n\nexport type PayloadProps = { label: string; value: unknown };\n\n/** One labeled block of arguments or results, highlighted, scrollable and copyable. */\nfunction Payload({ label, value }: PayloadProps) {\n  const text = useMemo(() => stringify(value), [value]);\n  const isJson = typeof value !== \"string\";\n  return (\n    <section className=\"flex min-w-0 flex-col gap-1.5\">\n      <div className=\"flex h-5 items-center justify-between\">\n        <h4 className=\"font-mono text-2xs uppercase tracking-[0.08em] text-fg-3\">{label}</h4>\n        <CopyButton value={text} iconOnly variant=\"ghost\" size=\"sm\" label={`Copy ${label.toLowerCase()}`} className=\"-mr-1.5 size-6\" />\n      </div>\n      <div className=\"relative min-w-0 rounded-md border border-line bg-frame\">\n        <pre\n          tabIndex={0}\n          aria-label={label}\n          className={cn(\n            \"max-h-56 overflow-auto overscroll-contain px-2.5 py-2 font-mono text-[12px] leading-[18px] text-fg-2 outline-none\",\n            \"focus-visible:outline-solid focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-fg-3 rounded-[5px]\",\n          )}\n        >\n          <code className=\"block w-max min-w-full\">{isJson ? <Json text={text} /> : text}</code>\n        </pre>\n      </div>\n    </section>\n  );\n}\n\nfunction stringify(value: unknown) {\n  if (typeof value === \"string\") return value;\n  try {\n    return JSON.stringify(value, (_, v) => (typeof v === \"bigint\" ? v.toString() : v), 2) ?? String(value);\n  } catch {\n    return String(value);\n  }\n}\n\n// Keys, strings, numbers and literals, told apart by weight of ink rather than hue.\nconst token = /(\"(?:\\\\.|[^\"\\\\])*\")(\\s*:)?|\\b(true|false|null)\\b|(-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|([{}[\\],])/g;\n\nfunction Json({ text }: { text: string }) {\n  const parts: React.ReactNode[] = [];\n  let last = 0;\n  let i = 0;\n  for (const m of text.matchAll(token)) {\n    if (m.index > last) parts.push(text.slice(last, m.index));\n    const [whole, str, colon, literal, num, punct] = m;\n    if (str && colon) parts.push(<span key={i++} className=\"text-fg\">{str}</span>, <span key={i++} className=\"text-fg-4\">{colon}</span>);\n    else if (str) parts.push(<span key={i++} className=\"text-fg-2\">{str}</span>);\n    else if (literal) parts.push(<span key={i++} className=\"italic text-fg-3\">{literal}</span>);\n    else if (num) parts.push(<span key={i++} className=\"text-fg tabular\">{num}</span>);\n    else if (punct) parts.push(<span key={i++} className=\"text-fg-4\">{punct}</span>);\n    else parts.push(whole);\n    last = m.index + whole.length;\n  }\n  if (last < text.length) parts.push(text.slice(last));\n  return <>{parts}</>;\n}\n\nexport type ToolCallGroupProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  /** What the calls did together: \"Read 6 files\". */\n  label: React.ReactNode;\n  /** Overall status. Running while any call runs; error if one failed. */\n  status: ToolCallStatus;\n  /** Shown at the end of the header: a total duration, a count. */\n  summary?: React.ReactNode;\n  icon?: React.ReactNode;\n  children: React.ReactNode;\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n};\n\n/** Consecutive calls of one kind, collapsed into a single row that opens into the list. */\nexport function ToolCallGroup({ label, status, summary, icon, children, open, defaultOpen, onOpenChange, className, ...rest }: ToolCallGroupProps) {\n  return (\n    <Collapsible.Root\n      open={open}\n      defaultOpen={defaultOpen}\n      onOpenChange={(next) => onOpenChange?.(next)}\n      data-status={status}\n      className={cn(\"group/tool relative min-w-0 rounded-lg border border-line bg-raised shadow-[var(--shadow)] data-[status=error]:border-danger/30\", className)}\n      {...rest}\n    >\n      <Collapsible.Trigger\n        className={cn(\n          \"group/trigger relative flex h-9 w-full min-w-0 select-none items-center gap-2 rounded-[7px] pl-2 pr-2.5 text-left group-data-[open]/tool:rounded-b-none\",\n          \"touch-manipulation [-webkit-tap-highlight-color:transparent]\",\n          \"outline-none focus-visible:outline-solid focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-fg-3\",\n          \"transition-[background-color] duration-150 hover:bg-hover active:bg-fg/[0.06] active:duration-75\",\n        )}\n      >\n        <span className=\"grid size-4 shrink-0 place-items-center text-fg-4 transition-colors duration-150 group-hover/trigger:text-fg-3 group-data-[panel-open]/trigger:text-fg-2\">\n          <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.4} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className=\"transition-[rotate] duration-[240ms] ease-in-out-quart motion-reduce:transition-none group-data-[panel-open]/trigger:rotate-90\">\n            <path d=\"m6.25 4.5 3.5 3.5-3.5 3.5\" />\n          </svg>\n        </span>\n        {icon != null && <span aria-hidden className=\"-ml-0.5 grid size-4 shrink-0 place-items-center text-fg-3 [&>svg]:size-4\">{icon}</span>}\n        <span className=\"min-w-0 flex-1 truncate text-[13px] font-medium tracking-[-0.006em] text-fg\">\n          <Sheen active={status === \"running\"}>{label}</Sheen>\n        </span>\n        <GroupMeta status={status} summary={summary} />\n        <span className=\"sr-only\">, {spoken[status]}</span>\n      </Collapsible.Trigger>\n      <Collapsible.Panel\n        className={cn(\n          \"group/panel h-(--collapsible-panel-height) overflow-hidden\",\n          \"transition-[height] duration-[260ms] ease-out-quart data-ending-style:duration-200 data-ending-style:ease-in-out-quart\",\n          \"data-starting-style:h-0 data-ending-style:h-0 motion-reduce:transition-none\",\n        )}\n      >\n        <div\n          className={cn(\n            \"flex flex-col gap-px border-t border-line p-1\",\n            \"transition-[opacity,translate] delay-[50ms] duration-[280ms] ease-out-expo\",\n            \"group-data-[starting-style]/panel:-translate-y-1 group-data-[starting-style]/panel:opacity-0\",\n            \"group-data-[ending-style]/panel:opacity-0 group-data-[ending-style]/panel:delay-0 group-data-[ending-style]/panel:duration-[140ms]\",\n            \"motion-reduce:translate-y-0 motion-reduce:delay-0\",\n          )}\n        >\n          <Nested.Provider value={true}>{children}</Nested.Provider>\n        </div>\n      </Collapsible.Panel>\n    </Collapsible.Root>\n  );\n}\n\nfunction GroupMeta({ status, summary }: { status: ToolCallStatus; summary?: React.ReactNode }) {\n  const reduce = useReducedMotion();\n  return (\n    <span className=\"ml-auto flex shrink-0 items-center gap-2 pl-1\">\n      {summary != null && <span className=\"text-[12px] tabular text-fg-3\">{summary}</span>}\n      <span className=\"relative grid size-4 place-items-center\">\n        <AnimatePresence initial={false}>\n          <motion.span\n            key={status}\n            className=\"absolute inset-0 grid place-items-center\"\n            initial={reduce ? { opacity: 0 } : { opacity: 0, scale: 0.5, filter: \"blur(3px)\" }}\n            animate={{ opacity: 1, scale: 1, filter: \"blur(0px)\" }}\n            exit={{ opacity: 0, transition: { duration: 0.1 } }}\n            transition={reduce ? { duration: 0.15 } : spring.pop}\n          >\n            <StatusGlyph status={status} reduce={!!reduce} />\n          </motion.span>\n        </AnimatePresence>\n      </span>\n    </span>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "docs": "https://www.stealth.pm/ui/tool-call"
}
