@agent-native/core 0.7.20 → 0.7.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  2. package/dist/agent/engine/ai-sdk-engine.js +43 -1
  3. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  4. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  5. package/dist/agent/engine/anthropic-engine.js +8 -0
  6. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  7. package/dist/agent/engine/builder-engine.d.ts +1 -1
  8. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  9. package/dist/agent/engine/builder-engine.js +9 -4
  10. package/dist/agent/engine/builder-engine.js.map +1 -1
  11. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  12. package/dist/agent/engine/translate-ai-sdk.js +31 -1
  13. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  14. package/dist/agent/engine/translate-anthropic.d.ts.map +1 -1
  15. package/dist/agent/engine/translate-anthropic.js +16 -0
  16. package/dist/agent/engine/translate-anthropic.js.map +1 -1
  17. package/dist/agent/engine/types.d.ts +16 -1
  18. package/dist/agent/engine/types.d.ts.map +1 -1
  19. package/dist/agent/engine/types.js.map +1 -1
  20. package/dist/agent/production-agent.d.ts +4 -0
  21. package/dist/agent/production-agent.d.ts.map +1 -1
  22. package/dist/agent/production-agent.js +96 -4
  23. package/dist/agent/production-agent.js.map +1 -1
  24. package/dist/agent/types.d.ts +3 -0
  25. package/dist/agent/types.d.ts.map +1 -1
  26. package/dist/agent/types.js.map +1 -1
  27. package/dist/client/AgentPanel.d.ts.map +1 -1
  28. package/dist/client/AgentPanel.js +5 -5
  29. package/dist/client/AgentPanel.js.map +1 -1
  30. package/dist/client/AssistantChat.d.ts +5 -0
  31. package/dist/client/AssistantChat.d.ts.map +1 -1
  32. package/dist/client/AssistantChat.js +54 -2
  33. package/dist/client/AssistantChat.js.map +1 -1
  34. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  35. package/dist/client/MultiTabAssistantChat.js +33 -2
  36. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  37. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  38. package/dist/client/NewWorkspaceAppFlow.js +15 -8
  39. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  40. package/dist/client/agent-chat-adapter.d.ts +4 -0
  41. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  42. package/dist/client/agent-chat-adapter.js +5 -1
  43. package/dist/client/agent-chat-adapter.js.map +1 -1
  44. package/dist/client/composer/TiptapComposer.d.ts +6 -1
  45. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  46. package/dist/client/composer/TiptapComposer.js +25 -17
  47. package/dist/client/composer/TiptapComposer.js.map +1 -1
  48. package/dist/client/composer/useVoiceDictation.d.ts +6 -5
  49. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  50. package/dist/client/composer/useVoiceDictation.js +54 -21
  51. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  52. package/dist/client/notifications/NotificationsBell.d.ts.map +1 -1
  53. package/dist/client/notifications/NotificationsBell.js +28 -1
  54. package/dist/client/notifications/NotificationsBell.js.map +1 -1
  55. package/dist/client/org/OrgSwitcher.d.ts +3 -1
  56. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  57. package/dist/client/org/OrgSwitcher.js +12 -7
  58. package/dist/client/org/OrgSwitcher.js.map +1 -1
  59. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  60. package/dist/client/settings/AutomationsSection.js +2 -2
  61. package/dist/client/settings/AutomationsSection.js.map +1 -1
  62. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  63. package/dist/client/settings/VoiceTranscriptionSection.js +46 -15
  64. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  65. package/dist/client/tools/ToolViewer.d.ts.map +1 -1
  66. package/dist/client/tools/ToolViewer.js +2 -2
  67. package/dist/client/tools/ToolViewer.js.map +1 -1
  68. package/dist/client/tools/ToolsListPage.d.ts.map +1 -1
  69. package/dist/client/tools/ToolsListPage.js +4 -4
  70. package/dist/client/tools/ToolsListPage.js.map +1 -1
  71. package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -1
  72. package/dist/client/tools/ToolsSidebarSection.js +2 -2
  73. package/dist/client/tools/ToolsSidebarSection.js.map +1 -1
  74. package/dist/client/transcription/use-live-transcription.d.ts +1 -0
  75. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  76. package/dist/client/transcription/use-live-transcription.js +41 -0
  77. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  78. package/dist/integrations/adapters/email.js +81 -5
  79. package/dist/integrations/adapters/email.js.map +1 -1
  80. package/dist/integrations/plugin.d.ts.map +1 -1
  81. package/dist/integrations/plugin.js +2 -1
  82. package/dist/integrations/plugin.js.map +1 -1
  83. package/dist/integrations/types.d.ts +2 -0
  84. package/dist/integrations/types.d.ts.map +1 -1
  85. package/dist/integrations/types.js.map +1 -1
  86. package/dist/integrations/webhook-handler.js +12 -2
  87. package/dist/integrations/webhook-handler.js.map +1 -1
  88. package/dist/oauth-tokens/store.d.ts.map +1 -1
  89. package/dist/oauth-tokens/store.js +34 -16
  90. package/dist/oauth-tokens/store.js.map +1 -1
  91. package/dist/scripts/db/exec.d.ts.map +1 -1
  92. package/dist/scripts/db/exec.js +32 -23
  93. package/dist/scripts/db/exec.js.map +1 -1
  94. package/dist/scripts/db/patch.d.ts.map +1 -1
  95. package/dist/scripts/db/patch.js +48 -35
  96. package/dist/scripts/db/patch.js.map +1 -1
  97. package/dist/scripts/db/query.d.ts.map +1 -1
  98. package/dist/scripts/db/query.js +22 -13
  99. package/dist/scripts/db/query.js.map +1 -1
  100. package/dist/scripts/db/safety.d.ts +2 -0
  101. package/dist/scripts/db/safety.d.ts.map +1 -0
  102. package/dist/scripts/db/safety.js +67 -0
  103. package/dist/scripts/db/safety.js.map +1 -0
  104. package/dist/scripts/db/scoping.js +4 -4
  105. package/dist/scripts/db/scoping.js.map +1 -1
  106. package/dist/server/email-template.d.ts +5 -0
  107. package/dist/server/email-template.d.ts.map +1 -1
  108. package/dist/server/email-template.js +7 -4
  109. package/dist/server/email-template.js.map +1 -1
  110. package/dist/server/google-auth-plugin.d.ts.map +1 -1
  111. package/dist/server/google-auth-plugin.js +1 -8
  112. package/dist/server/google-auth-plugin.js.map +1 -1
  113. package/dist/server/index.d.ts +3 -2
  114. package/dist/server/index.d.ts.map +1 -1
  115. package/dist/server/index.js +3 -2
  116. package/dist/server/index.js.map +1 -1
  117. package/dist/server/onboarding-html.d.ts.map +1 -1
  118. package/dist/server/onboarding-html.js +3 -10
  119. package/dist/server/onboarding-html.js.map +1 -1
  120. package/dist/server/ssr-handler.d.ts.map +1 -1
  121. package/dist/server/ssr-handler.js +7 -2
  122. package/dist/server/ssr-handler.js.map +1 -1
  123. package/dist/server/transcribe-voice.d.ts +9 -9
  124. package/dist/server/transcribe-voice.d.ts.map +1 -1
  125. package/dist/server/transcribe-voice.js +405 -51
  126. package/dist/server/transcribe-voice.js.map +1 -1
  127. package/dist/server/voice-providers-status.d.ts.map +1 -1
  128. package/dist/server/voice-providers-status.js +13 -1
  129. package/dist/server/voice-providers-status.js.map +1 -1
  130. package/dist/settings/store.d.ts.map +1 -1
  131. package/dist/settings/store.js +14 -6
  132. package/dist/settings/store.js.map +1 -1
  133. package/dist/shared/reasoning-effort.d.ts +8 -0
  134. package/dist/shared/reasoning-effort.d.ts.map +1 -0
  135. package/dist/shared/reasoning-effort.js +94 -0
  136. package/dist/shared/reasoning-effort.js.map +1 -0
  137. package/dist/templates/default/public/favicon.svg +1 -13
  138. package/dist/templates/default/public/icon-180.svg +1 -13
  139. package/dist/templates/default/public/icon-192.svg +1 -13
  140. package/dist/templates/default/public/icon-512.svg +1 -13
  141. package/dist/templates/workspace-root/scripts/workspace-dev.ts +5 -38
  142. package/dist/transcription/builder-transcription.d.ts +2 -0
  143. package/dist/transcription/builder-transcription.d.ts.map +1 -1
  144. package/dist/transcription/builder-transcription.js +4 -0
  145. package/dist/transcription/builder-transcription.js.map +1 -1
  146. package/dist/vite/client.d.ts.map +1 -1
  147. package/dist/vite/client.js +1 -5
  148. package/dist/vite/client.js.map +1 -1
  149. package/docs/content/voice-input.md +14 -13
  150. package/package.json +1 -1
  151. package/src/templates/default/public/favicon.svg +1 -13
  152. package/src/templates/default/public/icon-180.svg +1 -13
  153. package/src/templates/default/public/icon-192.svg +1 -13
  154. package/src/templates/default/public/icon-512.svg +1 -13
  155. package/src/templates/workspace-root/scripts/workspace-dev.ts +5 -38
@@ -22,12 +22,12 @@ function CreateToolInput({ className, inputClassName, }) {
22
22
  });
23
23
  setPrompt("");
24
24
  };
25
- return (_jsxs("div", { className: cn("flex flex-col gap-2", className), children: [_jsx("textarea", { value: prompt, onChange: (e) => setPrompt(e.target.value), placeholder: "Describe what you'd like to build...\ne.g. a todo list, API dashboard, calculator", className: cn("flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y", inputClassName), onKeyDown: (e) => {
25
+ return (_jsxs("div", { className: cn("flex flex-col gap-2", className), children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "New tool" }), _jsx("textarea", { value: prompt, onChange: (e) => setPrompt(e.target.value), placeholder: "Describe what you'd like to build...\ne.g. a todo list, API dashboard, calculator", className: cn("flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y", inputClassName), onKeyDown: (e) => {
26
26
  if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
27
27
  e.preventDefault();
28
28
  handleCreate();
29
29
  }
30
- } }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter"] }), _jsx("button", { type: "button", onClick: handleCreate, disabled: !prompt.trim(), className: cn("rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 cursor-pointer", !prompt.trim() && "opacity-60"), children: "Create" })] })] }));
30
+ } }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter to submit"] }), _jsx("button", { type: "button", onClick: handleCreate, disabled: !prompt.trim(), className: cn("rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 cursor-pointer", !prompt.trim() && "opacity-60"), children: "Create" })] })] }));
31
31
  }
32
32
  export function ToolsListPage() {
33
33
  const [showCreate, setShowCreate] = useState(false);
@@ -78,11 +78,11 @@ export function ToolsListPage() {
78
78
  return (_jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsxs("header", { className: "flex h-12 items-center justify-between border-b px-4 shrink-0", children: [_jsx("h1", { className: "text-sm font-semibold", children: "Tools" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90", children: [_jsx(IconPlus, { className: "h-4 w-4" }), "New Tool"] }) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, className: "w-80 p-4", children: _jsxs("form", { onSubmit: (e) => {
79
79
  e.preventDefault();
80
80
  handleCreate();
81
- }, children: [_jsx("textarea", { autoFocus: true, value: createPrompt, onChange: (e) => setCreatePrompt(e.target.value), placeholder: "Describe what you'd like to build...", className: "flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[140px] resize-y", onKeyDown: (e) => {
81
+ }, className: "space-y-3", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "New tool" }), _jsx("textarea", { autoFocus: true, value: createPrompt, onChange: (e) => setCreatePrompt(e.target.value), placeholder: "Describe what you'd like to build...", className: "flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[140px] resize-y", onKeyDown: (e) => {
82
82
  if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
83
83
  e.preventDefault();
84
84
  handleCreate();
85
85
  }
86
- } }), _jsxs("div", { className: "flex items-center justify-end gap-2 mt-3", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter"] }), _jsx("button", { type: "submit", disabled: !createPrompt.trim(), className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer", children: "Create" })] })] }) })] }), _jsx(AgentToggleButton, { className: "h-8 w-8 rounded-md hover:bg-accent" })] })] }), _jsx("div", { className: "flex-1 overflow-auto p-6", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-lg border border-border bg-card p-5", children: [_jsx("div", { className: "mb-3 h-10 w-10 rounded-lg bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 h-4 w-2/3 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-3 w-4/5 rounded bg-muted animate-pulse" })] }, i))) })) : toolList.length === 0 ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 text-center", children: [_jsx(IconTool, { className: "h-10 w-10 text-muted-foreground/40" }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: "No tools yet" }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Describe what you'd like to build" })] }), _jsx(CreateToolInput, { className: "w-full max-w-sm" })] })) : (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: toolList.map((tool) => (_jsxs(Link, { to: `/tools/${tool.id}`, className: cn("group cursor-pointer rounded-lg border border-border bg-card p-5", "hover:border-primary/30 hover:shadow-sm"), children: [_jsx("div", { className: "mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary", children: _jsx(IconTool, { className: "h-5 w-5" }) }), _jsx("h3", { className: "mb-1 text-sm font-semibold text-foreground", children: tool.name }), tool.description && (_jsx("p", { className: "line-clamp-2 text-xs text-muted-foreground", children: tool.description }))] }, tool.id))) })) })] }));
86
+ } }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter to submit"] }), _jsx("button", { type: "submit", disabled: !createPrompt.trim(), className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer", children: "Create" })] })] }) })] }), _jsx(AgentToggleButton, { className: "h-8 w-8 rounded-md hover:bg-accent" })] })] }), _jsx("div", { className: "flex-1 overflow-auto p-6", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-lg border border-border bg-card p-5", children: [_jsx("div", { className: "mb-3 h-10 w-10 rounded-lg bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 h-4 w-2/3 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-3 w-4/5 rounded bg-muted animate-pulse" })] }, i))) })) : toolList.length === 0 ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 text-center", children: [_jsx(IconTool, { className: "h-10 w-10 text-muted-foreground/40" }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: "No tools yet" }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Describe what you'd like to build" })] }), _jsx(CreateToolInput, { className: "w-full max-w-sm" })] })) : (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: toolList.map((tool) => (_jsxs(Link, { to: `/tools/${tool.id}`, className: cn("group cursor-pointer rounded-lg border border-border bg-card p-5", "hover:border-primary/30 hover:shadow-sm"), children: [_jsx("div", { className: "mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary", children: _jsx(IconTool, { className: "h-5 w-5" }) }), _jsx("h3", { className: "mb-1 text-sm font-semibold text-foreground", children: tool.name }), tool.description && (_jsx("p", { className: "line-clamp-2 text-xs text-muted-foreground", children: tool.description }))] }, tool.id))) })) })] }));
87
87
  }
88
88
  //# sourceMappingURL=ToolsListPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolsListPage.js","sourceRoot":"","sources":["../../../src/client/tools/ToolsListPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Link } from \"react-router\";\nimport { IconPlus, IconTool } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { AgentToggleButton } from \"../AgentPanel.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n TOOLS_ORDER_CHANGE_EVENT,\n applyToolsOrder,\n getToolsOrder,\n} from \"./tool-order.js\";\n\ninterface Tool {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nfunction CreateToolInput({\n className,\n inputClassName,\n}: {\n className?: string;\n inputClassName?: string;\n}) {\n const [prompt, setPrompt] = useState(\"\");\n\n const handleCreate = () => {\n if (!prompt.trim()) return;\n sendToAgentChat({\n message: `Create a tool: ${prompt.trim()}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setPrompt(\"\");\n };\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n <textarea\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder={\n \"Describe what you'd like to build...\\ne.g. a todo list, API dashboard, calculator\"\n }\n className={cn(\n \"flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y\",\n inputClassName,\n )}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}+Enter\n </span>\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={!prompt.trim()}\n className={cn(\n \"rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 cursor-pointer\",\n !prompt.trim() && \"opacity-60\",\n )}\n >\n Create\n </button>\n </div>\n </div>\n );\n}\n\nexport function ToolsListPage() {\n const [showCreate, setShowCreate] = useState(false);\n const [createPrompt, setCreatePrompt] = useState(\"\");\n const [toolOrderState, setToolOrderState] = useState<string[]>(() =>\n typeof window !== \"undefined\" ? getToolsOrder() : [],\n );\n\n useEffect(() => {\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ value: { view: \"tools\" } }),\n }).catch(() => {});\n }, []);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const syncOrder = () => setToolOrderState(getToolsOrder());\n window.addEventListener(TOOLS_ORDER_CHANGE_EVENT, syncOrder);\n window.addEventListener(\"storage\", syncOrder);\n return () => {\n window.removeEventListener(TOOLS_ORDER_CHANGE_EVENT, syncOrder);\n window.removeEventListener(\"storage\", syncOrder);\n };\n }, []);\n\n const { data: tools, isLoading } = useQuery<Tool[]>({\n queryKey: [\"tools\"],\n queryFn: async () => {\n const res = await fetch(agentNativePath(\"/_agent-native/tools\"));\n if (!res.ok) return [];\n return res.json();\n },\n });\n\n const toolList =\n toolOrderState.length > 0\n ? applyToolsOrder(tools ?? [], toolOrderState)\n : (tools ?? []);\n\n const handleCreate = () => {\n if (!createPrompt.trim()) return;\n sendToAgentChat({\n message: `Create a tool: ${createPrompt.trim()}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setCreatePrompt(\"\");\n setShowCreate(false);\n };\n\n return (\n <div className=\"flex h-full w-full flex-col\">\n <header className=\"flex h-12 items-center justify-between border-b px-4 shrink-0\">\n <h1 className=\"text-sm font-semibold\">Tools</h1>\n <div className=\"flex items-center gap-2\">\n <Popover open={showCreate} onOpenChange={setShowCreate}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <IconPlus className=\"h-4 w-4\" />\n New Tool\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" sideOffset={6} className=\"w-80 p-4\">\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleCreate();\n }}\n >\n <textarea\n autoFocus\n value={createPrompt}\n onChange={(e) => setCreatePrompt(e.target.value)}\n placeholder=\"Describe what you'd like to build...\"\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[140px] resize-y\"\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center justify-end gap-2 mt-3\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}\n +Enter\n </span>\n <button\n type=\"submit\"\n disabled={!createPrompt.trim()}\n className=\"rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n >\n Create\n </button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n <AgentToggleButton className=\"h-8 w-8 rounded-md hover:bg-accent\" />\n </div>\n </header>\n\n <div className=\"flex-1 overflow-auto p-6\">\n {isLoading ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div\n key={i}\n className=\"rounded-lg border border-border bg-card p-5\"\n >\n <div className=\"mb-3 h-10 w-10 rounded-lg bg-muted animate-pulse\" />\n <div className=\"mb-2 h-4 w-2/3 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-4/5 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n ) : toolList.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-4 py-16 text-center\">\n <IconTool className=\"h-10 w-10 text-muted-foreground/40\" />\n <div>\n <p className=\"text-sm font-medium\">No tools yet</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Describe what you'd like to build\n </p>\n </div>\n <CreateToolInput className=\"w-full max-w-sm\" />\n </div>\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {toolList.map((tool) => (\n <Link\n key={tool.id}\n to={`/tools/${tool.id}`}\n className={cn(\n \"group cursor-pointer rounded-lg border border-border bg-card p-5\",\n \"hover:border-primary/30 hover:shadow-sm\",\n )}\n >\n <div className=\"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary\">\n <IconTool className=\"h-5 w-5\" />\n </div>\n <h3 className=\"mb-1 text-sm font-semibold text-foreground\">\n {tool.name}\n </h3>\n {tool.description && (\n <p className=\"line-clamp-2 text-xs text-muted-foreground\">\n {tool.description}\n </p>\n )}\n </Link>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"ToolsListPage.js","sourceRoot":"","sources":["../../../src/client/tools/ToolsListPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Link } from \"react-router\";\nimport { IconPlus, IconTool } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { AgentToggleButton } from \"../AgentPanel.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n TOOLS_ORDER_CHANGE_EVENT,\n applyToolsOrder,\n getToolsOrder,\n} from \"./tool-order.js\";\n\ninterface Tool {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nfunction CreateToolInput({\n className,\n inputClassName,\n}: {\n className?: string;\n inputClassName?: string;\n}) {\n const [prompt, setPrompt] = useState(\"\");\n\n const handleCreate = () => {\n if (!prompt.trim()) return;\n sendToAgentChat({\n message: `Create a tool: ${prompt.trim()}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setPrompt(\"\");\n };\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n <p className=\"text-sm font-semibold text-foreground\">New tool</p>\n <textarea\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder={\n \"Describe what you'd like to build...\\ne.g. a todo list, API dashboard, calculator\"\n }\n className={cn(\n \"flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y\",\n inputClassName,\n )}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}+Enter to\n submit\n </span>\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={!prompt.trim()}\n className={cn(\n \"rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 cursor-pointer\",\n !prompt.trim() && \"opacity-60\",\n )}\n >\n Create\n </button>\n </div>\n </div>\n );\n}\n\nexport function ToolsListPage() {\n const [showCreate, setShowCreate] = useState(false);\n const [createPrompt, setCreatePrompt] = useState(\"\");\n const [toolOrderState, setToolOrderState] = useState<string[]>(() =>\n typeof window !== \"undefined\" ? getToolsOrder() : [],\n );\n\n useEffect(() => {\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ value: { view: \"tools\" } }),\n }).catch(() => {});\n }, []);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const syncOrder = () => setToolOrderState(getToolsOrder());\n window.addEventListener(TOOLS_ORDER_CHANGE_EVENT, syncOrder);\n window.addEventListener(\"storage\", syncOrder);\n return () => {\n window.removeEventListener(TOOLS_ORDER_CHANGE_EVENT, syncOrder);\n window.removeEventListener(\"storage\", syncOrder);\n };\n }, []);\n\n const { data: tools, isLoading } = useQuery<Tool[]>({\n queryKey: [\"tools\"],\n queryFn: async () => {\n const res = await fetch(agentNativePath(\"/_agent-native/tools\"));\n if (!res.ok) return [];\n return res.json();\n },\n });\n\n const toolList =\n toolOrderState.length > 0\n ? applyToolsOrder(tools ?? [], toolOrderState)\n : (tools ?? []);\n\n const handleCreate = () => {\n if (!createPrompt.trim()) return;\n sendToAgentChat({\n message: `Create a tool: ${createPrompt.trim()}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setCreatePrompt(\"\");\n setShowCreate(false);\n };\n\n return (\n <div className=\"flex h-full w-full flex-col\">\n <header className=\"flex h-12 items-center justify-between border-b px-4 shrink-0\">\n <h1 className=\"text-sm font-semibold\">Tools</h1>\n <div className=\"flex items-center gap-2\">\n <Popover open={showCreate} onOpenChange={setShowCreate}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <IconPlus className=\"h-4 w-4\" />\n New Tool\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" sideOffset={6} className=\"w-80 p-4\">\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleCreate();\n }}\n className=\"space-y-3\"\n >\n <p className=\"text-sm font-semibold text-foreground\">\n New tool\n </p>\n <textarea\n autoFocus\n value={createPrompt}\n onChange={(e) => setCreatePrompt(e.target.value)}\n placeholder=\"Describe what you'd like to build...\"\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[140px] resize-y\"\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}\n +Enter to submit\n </span>\n <button\n type=\"submit\"\n disabled={!createPrompt.trim()}\n className=\"rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n >\n Create\n </button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n <AgentToggleButton className=\"h-8 w-8 rounded-md hover:bg-accent\" />\n </div>\n </header>\n\n <div className=\"flex-1 overflow-auto p-6\">\n {isLoading ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div\n key={i}\n className=\"rounded-lg border border-border bg-card p-5\"\n >\n <div className=\"mb-3 h-10 w-10 rounded-lg bg-muted animate-pulse\" />\n <div className=\"mb-2 h-4 w-2/3 rounded bg-muted animate-pulse\" />\n <div className=\"h-3 w-4/5 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n ) : toolList.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-4 py-16 text-center\">\n <IconTool className=\"h-10 w-10 text-muted-foreground/40\" />\n <div>\n <p className=\"text-sm font-medium\">No tools yet</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n Describe what you'd like to build\n </p>\n </div>\n <CreateToolInput className=\"w-full max-w-sm\" />\n </div>\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {toolList.map((tool) => (\n <Link\n key={tool.id}\n to={`/tools/${tool.id}`}\n className={cn(\n \"group cursor-pointer rounded-lg border border-border bg-card p-5\",\n \"hover:border-primary/30 hover:shadow-sm\",\n )}\n >\n <div className=\"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary\">\n <IconTool className=\"h-5 w-5\" />\n </div>\n <h3 className=\"mb-1 text-sm font-semibold text-foreground\">\n {tool.name}\n </h3>\n {tool.description && (\n <p className=\"line-clamp-2 text-xs text-muted-foreground\">\n {tool.description}\n </p>\n )}\n </Link>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ToolsSidebarSection.d.ts","sourceRoot":"","sources":["../../../src/client/tools/ToolsSidebarSection.tsx"],"names":[],"mappings":"AAoDA,wBAAgB,mBAAmB,4CA2ZlC"}
1
+ {"version":3,"file":"ToolsSidebarSection.d.ts","sourceRoot":"","sources":["../../../src/client/tools/ToolsSidebarSection.tsx"],"names":[],"mappings":"AAoDA,wBAAgB,mBAAmB,4CA6ZlC"}
@@ -182,12 +182,12 @@ export function ToolsSidebarSection() {
182
182
  return (_jsxs("div", { className: "group/help relative py-2", children: [_jsxs("div", { className: cn("flex items-center justify-between px-3", sortedTools.length > 0 && "mb-1"), children: [_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: [_jsx(IconTool, { className: "h-3.5 w-3.5 shrink-0" }), "Tools", _jsx("a", { href: "https://agent-native.com/docs/tools", target: "_blank", rel: "noopener noreferrer", className: "opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground", "aria-label": "Tools documentation", children: _jsx(IconHelpCircle, { className: "h-3 w-3" }) })] }), _jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground", "aria-label": "New tool", children: _jsx(IconPlus, { className: "h-3.5 w-3.5" }) }) }), _jsx(PopoverContent, { side: "right", align: "start", className: "w-80 p-4", children: _jsxs("form", { onSubmit: (e) => {
183
183
  e.preventDefault();
184
184
  handleCreate();
185
- }, children: [_jsx("textarea", { autoFocus: true, value: createPrompt, onChange: (e) => setCreatePrompt(e.target.value), placeholder: "Describe what you'd like to build...", className: "flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y", onKeyDown: (e) => {
185
+ }, className: "space-y-3", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "New tool" }), _jsx("textarea", { autoFocus: true, value: createPrompt, onChange: (e) => setCreatePrompt(e.target.value), placeholder: "Describe what you'd like to build...", className: "flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y", onKeyDown: (e) => {
186
186
  if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
187
187
  e.preventDefault();
188
188
  handleCreate();
189
189
  }
190
- } }), _jsxs("div", { className: "flex items-center justify-end gap-2 mt-3", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter"] }), _jsx("button", { type: "submit", disabled: !createPrompt.trim(), className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer", children: "Create" })] })] }) })] })] }), isLoading ? (_jsx("div", { className: "space-y-0.5 px-1", children: [1, 2, 3].map((i) => (_jsx("div", { className: "flex items-center rounded-md px-2 py-1.5", children: _jsx("div", { className: "h-3 rounded bg-muted animate-pulse", style: { width: `${60 + i * 20}px` } }) }, i))) })) : sortedTools.length === 0 ? null : (_jsx("div", { className: "space-y-0.5 px-1", children: sortedTools.map((tool) => {
190
+ } }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter to submit"] }), _jsx("button", { type: "submit", disabled: !createPrompt.trim(), className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer", children: "Create" })] })] }) })] })] }), isLoading ? (_jsx("div", { className: "space-y-0.5 px-1", children: [1, 2, 3].map((i) => (_jsx("div", { className: "flex items-center rounded-md px-2 py-1.5", children: _jsx("div", { className: "h-3 rounded bg-muted animate-pulse", style: { width: `${60 + i * 20}px` } }) }, i))) })) : sortedTools.length === 0 ? null : (_jsx("div", { className: "space-y-0.5 px-1", children: sortedTools.map((tool) => {
191
191
  const isActive = location.pathname === `/tools/${tool.id}` ||
192
192
  location.pathname === `/tools/${tool.id}/edit`;
193
193
  const isFav = favoriteIds.has(tool.id);
@@ -1 +1 @@
1
- {"version":3,"file":"ToolsSidebarSection.js","sourceRoot":"","sources":["../../../src/client/tools/ToolsSidebarSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useCallback, useMemo, useEffect } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconTool,\n IconPlus,\n IconStar,\n IconStarFilled,\n IconTrash,\n IconDots,\n IconHelpCircle,\n IconPencil,\n IconGripVertical,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { applyToolsOrder, getToolsOrder, setToolsOrder } from \"./tool-order.js\";\n\ninterface Tool {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nconst FAVORITES_KEY = \"tools-favorites\";\n\nfunction getFavorites(): Set<string> {\n try {\n const raw = localStorage.getItem(FAVORITES_KEY);\n if (!raw) return new Set();\n const parsed = JSON.parse(raw);\n return new Set(Array.isArray(parsed) ? parsed : []);\n } catch {\n return new Set();\n }\n}\n\nfunction saveFavorites(ids: Set<string>) {\n try {\n localStorage.setItem(FAVORITES_KEY, JSON.stringify(Array.from(ids)));\n } catch {\n // localStorage unavailable — ignore\n }\n}\n\nexport function ToolsSidebarSection() {\n const location = useLocation();\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const [favoriteIds, setFavoriteIds] = useState<Set<string>>(() =>\n typeof window !== \"undefined\" ? getFavorites() : new Set(),\n );\n const [menuOpenId, setMenuOpenId] = useState<string | null>(null);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState(\"\");\n const [showCreate, setShowCreate] = useState(false);\n const [createPrompt, setCreatePrompt] = useState(\"\");\n const [toolOrderState, setToolOrderState] = useState<string[]>(() =>\n typeof window !== \"undefined\" ? getToolsOrder() : [],\n );\n const [draggingId, setDraggingId] = useState<string | null>(null);\n const [dragOverId, setDragOverId] = useState<string | null>(null);\n\n const { data: tools, isLoading } = useQuery<Tool[]>({\n queryKey: [\"tools\"],\n queryFn: async () => {\n const res = await fetch(agentNativePath(\"/_agent-native/tools\"));\n if (!res.ok) return [];\n return res.json();\n },\n });\n\n const toggleFavorite = useCallback((id: string) => {\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n saveFavorites(next);\n return next;\n });\n }, []);\n\n const handleDelete = useCallback(\n async (toolId: string) => {\n setMenuOpenId(null);\n const prev = queryClient.getQueryData<Tool[]>([\"tools\"]);\n queryClient.setQueryData<Tool[]>([\"tools\"], (old) =>\n (old ?? []).filter((t) => t.id !== toolId),\n );\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/tools/${toolId}`),\n {\n method: \"DELETE\",\n },\n );\n if (!res.ok) throw new Error(\"Delete failed\");\n queryClient.removeQueries({ queryKey: [\"tool\", toolId] });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n next.delete(toolId);\n saveFavorites(next);\n return next;\n });\n setToolOrderState((prev) => {\n const next = prev.filter((id) => id !== toolId);\n if (next.length !== prev.length) setToolsOrder(next);\n return next;\n });\n if (\n location.pathname === `/tools/${toolId}` ||\n location.pathname === `/tools/${toolId}/edit`\n ) {\n navigate(\"/tools\");\n }\n } catch {\n if (prev) queryClient.setQueryData([\"tools\"], prev);\n }\n },\n [location.pathname, navigate, queryClient],\n );\n\n const startRename = useCallback((tool: Tool) => {\n setMenuOpenId(null);\n setRenameValue(tool.name);\n setRenamingId(tool.id);\n }, []);\n\n const submitRename = useCallback(\n async (toolId: string) => {\n const trimmed = renameValue.trim();\n setRenamingId(null);\n if (!trimmed) return;\n const prev = queryClient.getQueryData<Tool[]>([\"tools\"]);\n const existing = prev?.find((t) => t.id === toolId);\n if (!existing || trimmed === existing.name) return;\n queryClient.setQueryData<Tool[]>([\"tools\"], (old) =>\n (old ?? []).map((t) => (t.id === toolId ? { ...t, name: trimmed } : t)),\n );\n queryClient.setQueryData<Tool>([\"tool\", toolId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n try {\n await fetch(agentNativePath(`/_agent-native/tools/${toolId}`), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n queryClient.invalidateQueries({ queryKey: [\"tool\", toolId] });\n } catch {\n if (prev) queryClient.setQueryData([\"tools\"], prev);\n queryClient.invalidateQueries({ queryKey: [\"tool\", toolId] });\n }\n },\n [renameValue, queryClient],\n );\n\n // Close menu on click outside\n useEffect(() => {\n if (!menuOpenId) return;\n const handler = () => setMenuOpenId(null);\n document.addEventListener(\"click\", handler);\n return () => document.removeEventListener(\"click\", handler);\n }, [menuOpenId]);\n\n const sortedTools = useMemo(() => {\n if (!tools) return [];\n const defaultSorted = [...tools].sort((a, b) => {\n const aFav = favoriteIds.has(a.id) ? 0 : 1;\n const bFav = favoriteIds.has(b.id) ? 0 : 1;\n if (aFav !== bFav) return aFav - bFav;\n return a.name.localeCompare(b.name);\n });\n return toolOrderState.length > 0\n ? applyToolsOrder(defaultSorted, toolOrderState)\n : defaultSorted;\n }, [tools, favoriteIds, toolOrderState]);\n\n const reorderTool = useCallback(\n (activeId: string, overId: string) => {\n if (activeId === overId) return;\n const ids = sortedTools.map((tool) => tool.id);\n const oldIndex = ids.indexOf(activeId);\n const newIndex = ids.indexOf(overId);\n if (oldIndex === -1 || newIndex === -1) return;\n const next = [...ids];\n const [moved] = next.splice(oldIndex, 1);\n if (!moved) return;\n next.splice(newIndex, 0, moved);\n setToolsOrder(next);\n setToolOrderState(next);\n },\n [sortedTools],\n );\n\n const handleCreate = () => {\n if (!createPrompt.trim()) return;\n sendToAgentChat({\n message: `Create a tool: ${createPrompt.trim()}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setCreatePrompt(\"\");\n setShowCreate(false);\n };\n\n return (\n <div className=\"group/help relative py-2\">\n <div\n className={cn(\n \"flex items-center justify-between px-3\",\n sortedTools.length > 0 && \"mb-1\",\n )}\n >\n <span className=\"inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n <IconTool className=\"h-3.5 w-3.5 shrink-0\" />\n Tools\n <a\n href=\"https://agent-native.com/docs/tools\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground\"\n aria-label=\"Tools documentation\"\n >\n <IconHelpCircle className=\"h-3 w-3\" />\n </a>\n </span>\n <Popover open={showCreate} onOpenChange={setShowCreate}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"New tool\"\n >\n <IconPlus className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent side=\"right\" align=\"start\" className=\"w-80 p-4\">\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleCreate();\n }}\n >\n <textarea\n autoFocus\n value={createPrompt}\n onChange={(e) => setCreatePrompt(e.target.value)}\n placeholder=\"Describe what you'd like to build...\"\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y\"\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center justify-end gap-2 mt-3\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}\n +Enter\n </span>\n <button\n type=\"submit\"\n disabled={!createPrompt.trim()}\n className=\"rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n >\n Create\n </button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-0.5 px-1\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex items-center rounded-md px-2 py-1.5\">\n <div\n className=\"h-3 rounded bg-muted animate-pulse\"\n style={{ width: `${60 + i * 20}px` }}\n />\n </div>\n ))}\n </div>\n ) : sortedTools.length === 0 ? null : (\n <div className=\"space-y-0.5 px-1\">\n {sortedTools.map((tool) => {\n const isActive =\n location.pathname === `/tools/${tool.id}` ||\n location.pathname === `/tools/${tool.id}/edit`;\n const isFav = favoriteIds.has(tool.id);\n const isRenamingThis = renamingId === tool.id;\n const actionsVisible = menuOpenId === tool.id || isRenamingThis;\n\n return (\n <div\n key={tool.id}\n onDragOver={(e) => {\n if (!draggingId || draggingId === tool.id) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n setDragOverId(tool.id);\n }}\n onDragLeave={() => {\n setDragOverId((current) =>\n current === tool.id ? null : current,\n );\n }}\n onDrop={(e) => {\n e.preventDefault();\n const activeId =\n draggingId || e.dataTransfer.getData(\"text/plain\");\n setDraggingId(null);\n setDragOverId(null);\n if (activeId) reorderTool(activeId, tool.id);\n }}\n className={cn(\n \"group/tool relative flex items-center min-w-0 rounded-md\",\n draggingId === tool.id && \"opacity-50\",\n dragOverId === tool.id &&\n draggingId !== tool.id &&\n \"bg-accent/60\",\n )}\n >\n <button\n type=\"button\"\n draggable\n onDragStart={(e) => {\n setDraggingId(tool.id);\n setDragOverId(null);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", tool.id);\n }}\n onDragEnd={() => {\n setDraggingId(null);\n setDragOverId(null);\n }}\n className=\"-ml-2 cursor-grab rounded p-0.5 text-muted-foreground/30 opacity-0 transition-colors hover:text-muted-foreground/70 active:cursor-grabbing group-hover/tool:opacity-100 group-focus-within/tool:opacity-100\"\n aria-label={`Reorder ${tool.name}`}\n title=\"Drag to reorder\"\n >\n <IconGripVertical className=\"h-3 w-3\" />\n </button>\n <Link\n to={`/tools/${tool.id}`}\n className={cn(\n \"flex min-w-0 flex-1 items-center rounded-md px-2 py-1.5 pr-12 text-xs transition-[padding,color,background-color] md:pr-2 md:group-hover/tool:pr-12 md:group-focus-within/tool:pr-12\",\n actionsVisible && \"md:pr-12\",\n isActive\n ? \"bg-accent text-accent-foreground font-medium\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-accent-foreground\",\n )}\n >\n {isRenamingThis ? (\n <input\n autoFocus\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={() => submitRename(tool.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename(tool.id);\n if (e.key === \"Escape\") setRenamingId(null);\n }}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n className=\"min-w-0 flex-1 truncate border-b border-primary bg-transparent px-0 py-0 text-xs outline-none\"\n />\n ) : (\n <span className=\"block truncate\">{tool.name}</span>\n )}\n </Link>\n\n <div\n className={cn(\n \"pointer-events-none absolute right-1 top-1/2 flex -translate-y-1/2 items-center gap-0.5 opacity-100 transition-opacity md:opacity-0 md:group-hover/tool:opacity-100 md:group-focus-within/tool:opacity-100\",\n actionsVisible && \"md:opacity-100\",\n )}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n toggleFavorite(tool.id);\n }}\n className={cn(\n \"pointer-events-auto cursor-pointer rounded p-0.5 transition-colors\",\n isFav\n ? \"text-yellow-500\"\n : \"text-muted-foreground/40 hover:text-yellow-500\",\n )}\n aria-label={isFav ? \"Unfavorite\" : \"Favorite\"}\n >\n {isFav ? (\n <IconStarFilled className=\"h-3 w-3\" />\n ) : (\n <IconStar className=\"h-3 w-3\" />\n )}\n </button>\n\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setMenuOpenId(menuOpenId === tool.id ? null : tool.id);\n }}\n className=\"pointer-events-auto cursor-pointer rounded p-0.5 text-muted-foreground/40 transition-colors hover:text-foreground\"\n aria-label=\"Tool actions\"\n >\n <IconDots className=\"h-3 w-3\" />\n </button>\n\n {menuOpenId === tool.id && (\n <div\n className=\"absolute right-0 top-full z-50 mt-1 min-w-[120px] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n onClick={() => startRename(tool)}\n className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent\"\n >\n <IconPencil className=\"h-3.5 w-3.5\" />\n Rename\n </button>\n <button\n type=\"button\"\n onClick={() => handleDelete(tool.id)}\n className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive hover:bg-accent\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n Delete\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"ToolsSidebarSection.js","sourceRoot":"","sources":["../../../src/client/tools/ToolsSidebarSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useCallback, useMemo, useEffect } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconTool,\n IconPlus,\n IconStar,\n IconStarFilled,\n IconTrash,\n IconDots,\n IconHelpCircle,\n IconPencil,\n IconGripVertical,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { applyToolsOrder, getToolsOrder, setToolsOrder } from \"./tool-order.js\";\n\ninterface Tool {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nconst FAVORITES_KEY = \"tools-favorites\";\n\nfunction getFavorites(): Set<string> {\n try {\n const raw = localStorage.getItem(FAVORITES_KEY);\n if (!raw) return new Set();\n const parsed = JSON.parse(raw);\n return new Set(Array.isArray(parsed) ? parsed : []);\n } catch {\n return new Set();\n }\n}\n\nfunction saveFavorites(ids: Set<string>) {\n try {\n localStorage.setItem(FAVORITES_KEY, JSON.stringify(Array.from(ids)));\n } catch {\n // localStorage unavailable — ignore\n }\n}\n\nexport function ToolsSidebarSection() {\n const location = useLocation();\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const [favoriteIds, setFavoriteIds] = useState<Set<string>>(() =>\n typeof window !== \"undefined\" ? getFavorites() : new Set(),\n );\n const [menuOpenId, setMenuOpenId] = useState<string | null>(null);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState(\"\");\n const [showCreate, setShowCreate] = useState(false);\n const [createPrompt, setCreatePrompt] = useState(\"\");\n const [toolOrderState, setToolOrderState] = useState<string[]>(() =>\n typeof window !== \"undefined\" ? getToolsOrder() : [],\n );\n const [draggingId, setDraggingId] = useState<string | null>(null);\n const [dragOverId, setDragOverId] = useState<string | null>(null);\n\n const { data: tools, isLoading } = useQuery<Tool[]>({\n queryKey: [\"tools\"],\n queryFn: async () => {\n const res = await fetch(agentNativePath(\"/_agent-native/tools\"));\n if (!res.ok) return [];\n return res.json();\n },\n });\n\n const toggleFavorite = useCallback((id: string) => {\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n saveFavorites(next);\n return next;\n });\n }, []);\n\n const handleDelete = useCallback(\n async (toolId: string) => {\n setMenuOpenId(null);\n const prev = queryClient.getQueryData<Tool[]>([\"tools\"]);\n queryClient.setQueryData<Tool[]>([\"tools\"], (old) =>\n (old ?? []).filter((t) => t.id !== toolId),\n );\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/tools/${toolId}`),\n {\n method: \"DELETE\",\n },\n );\n if (!res.ok) throw new Error(\"Delete failed\");\n queryClient.removeQueries({ queryKey: [\"tool\", toolId] });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n next.delete(toolId);\n saveFavorites(next);\n return next;\n });\n setToolOrderState((prev) => {\n const next = prev.filter((id) => id !== toolId);\n if (next.length !== prev.length) setToolsOrder(next);\n return next;\n });\n if (\n location.pathname === `/tools/${toolId}` ||\n location.pathname === `/tools/${toolId}/edit`\n ) {\n navigate(\"/tools\");\n }\n } catch {\n if (prev) queryClient.setQueryData([\"tools\"], prev);\n }\n },\n [location.pathname, navigate, queryClient],\n );\n\n const startRename = useCallback((tool: Tool) => {\n setMenuOpenId(null);\n setRenameValue(tool.name);\n setRenamingId(tool.id);\n }, []);\n\n const submitRename = useCallback(\n async (toolId: string) => {\n const trimmed = renameValue.trim();\n setRenamingId(null);\n if (!trimmed) return;\n const prev = queryClient.getQueryData<Tool[]>([\"tools\"]);\n const existing = prev?.find((t) => t.id === toolId);\n if (!existing || trimmed === existing.name) return;\n queryClient.setQueryData<Tool[]>([\"tools\"], (old) =>\n (old ?? []).map((t) => (t.id === toolId ? { ...t, name: trimmed } : t)),\n );\n queryClient.setQueryData<Tool>([\"tool\", toolId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n try {\n await fetch(agentNativePath(`/_agent-native/tools/${toolId}`), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n queryClient.invalidateQueries({ queryKey: [\"tool\", toolId] });\n } catch {\n if (prev) queryClient.setQueryData([\"tools\"], prev);\n queryClient.invalidateQueries({ queryKey: [\"tool\", toolId] });\n }\n },\n [renameValue, queryClient],\n );\n\n // Close menu on click outside\n useEffect(() => {\n if (!menuOpenId) return;\n const handler = () => setMenuOpenId(null);\n document.addEventListener(\"click\", handler);\n return () => document.removeEventListener(\"click\", handler);\n }, [menuOpenId]);\n\n const sortedTools = useMemo(() => {\n if (!tools) return [];\n const defaultSorted = [...tools].sort((a, b) => {\n const aFav = favoriteIds.has(a.id) ? 0 : 1;\n const bFav = favoriteIds.has(b.id) ? 0 : 1;\n if (aFav !== bFav) return aFav - bFav;\n return a.name.localeCompare(b.name);\n });\n return toolOrderState.length > 0\n ? applyToolsOrder(defaultSorted, toolOrderState)\n : defaultSorted;\n }, [tools, favoriteIds, toolOrderState]);\n\n const reorderTool = useCallback(\n (activeId: string, overId: string) => {\n if (activeId === overId) return;\n const ids = sortedTools.map((tool) => tool.id);\n const oldIndex = ids.indexOf(activeId);\n const newIndex = ids.indexOf(overId);\n if (oldIndex === -1 || newIndex === -1) return;\n const next = [...ids];\n const [moved] = next.splice(oldIndex, 1);\n if (!moved) return;\n next.splice(newIndex, 0, moved);\n setToolsOrder(next);\n setToolOrderState(next);\n },\n [sortedTools],\n );\n\n const handleCreate = () => {\n if (!createPrompt.trim()) return;\n sendToAgentChat({\n message: `Create a tool: ${createPrompt.trim()}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setCreatePrompt(\"\");\n setShowCreate(false);\n };\n\n return (\n <div className=\"group/help relative py-2\">\n <div\n className={cn(\n \"flex items-center justify-between px-3\",\n sortedTools.length > 0 && \"mb-1\",\n )}\n >\n <span className=\"inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n <IconTool className=\"h-3.5 w-3.5 shrink-0\" />\n Tools\n <a\n href=\"https://agent-native.com/docs/tools\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground\"\n aria-label=\"Tools documentation\"\n >\n <IconHelpCircle className=\"h-3 w-3\" />\n </a>\n </span>\n <Popover open={showCreate} onOpenChange={setShowCreate}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"New tool\"\n >\n <IconPlus className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent side=\"right\" align=\"start\" className=\"w-80 p-4\">\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleCreate();\n }}\n className=\"space-y-3\"\n >\n <p className=\"text-sm font-semibold text-foreground\">New tool</p>\n <textarea\n autoFocus\n value={createPrompt}\n onChange={(e) => setCreatePrompt(e.target.value)}\n placeholder=\"Describe what you'd like to build...\"\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 min-h-[100px] resize-y\"\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}\n +Enter to submit\n </span>\n <button\n type=\"submit\"\n disabled={!createPrompt.trim()}\n className=\"rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n >\n Create\n </button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-0.5 px-1\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex items-center rounded-md px-2 py-1.5\">\n <div\n className=\"h-3 rounded bg-muted animate-pulse\"\n style={{ width: `${60 + i * 20}px` }}\n />\n </div>\n ))}\n </div>\n ) : sortedTools.length === 0 ? null : (\n <div className=\"space-y-0.5 px-1\">\n {sortedTools.map((tool) => {\n const isActive =\n location.pathname === `/tools/${tool.id}` ||\n location.pathname === `/tools/${tool.id}/edit`;\n const isFav = favoriteIds.has(tool.id);\n const isRenamingThis = renamingId === tool.id;\n const actionsVisible = menuOpenId === tool.id || isRenamingThis;\n\n return (\n <div\n key={tool.id}\n onDragOver={(e) => {\n if (!draggingId || draggingId === tool.id) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n setDragOverId(tool.id);\n }}\n onDragLeave={() => {\n setDragOverId((current) =>\n current === tool.id ? null : current,\n );\n }}\n onDrop={(e) => {\n e.preventDefault();\n const activeId =\n draggingId || e.dataTransfer.getData(\"text/plain\");\n setDraggingId(null);\n setDragOverId(null);\n if (activeId) reorderTool(activeId, tool.id);\n }}\n className={cn(\n \"group/tool relative flex items-center min-w-0 rounded-md\",\n draggingId === tool.id && \"opacity-50\",\n dragOverId === tool.id &&\n draggingId !== tool.id &&\n \"bg-accent/60\",\n )}\n >\n <button\n type=\"button\"\n draggable\n onDragStart={(e) => {\n setDraggingId(tool.id);\n setDragOverId(null);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", tool.id);\n }}\n onDragEnd={() => {\n setDraggingId(null);\n setDragOverId(null);\n }}\n className=\"-ml-2 cursor-grab rounded p-0.5 text-muted-foreground/30 opacity-0 transition-colors hover:text-muted-foreground/70 active:cursor-grabbing group-hover/tool:opacity-100 group-focus-within/tool:opacity-100\"\n aria-label={`Reorder ${tool.name}`}\n title=\"Drag to reorder\"\n >\n <IconGripVertical className=\"h-3 w-3\" />\n </button>\n <Link\n to={`/tools/${tool.id}`}\n className={cn(\n \"flex min-w-0 flex-1 items-center rounded-md px-2 py-1.5 pr-12 text-xs transition-[padding,color,background-color] md:pr-2 md:group-hover/tool:pr-12 md:group-focus-within/tool:pr-12\",\n actionsVisible && \"md:pr-12\",\n isActive\n ? \"bg-accent text-accent-foreground font-medium\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-accent-foreground\",\n )}\n >\n {isRenamingThis ? (\n <input\n autoFocus\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={() => submitRename(tool.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename(tool.id);\n if (e.key === \"Escape\") setRenamingId(null);\n }}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n className=\"min-w-0 flex-1 truncate border-b border-primary bg-transparent px-0 py-0 text-xs outline-none\"\n />\n ) : (\n <span className=\"block truncate\">{tool.name}</span>\n )}\n </Link>\n\n <div\n className={cn(\n \"pointer-events-none absolute right-1 top-1/2 flex -translate-y-1/2 items-center gap-0.5 opacity-100 transition-opacity md:opacity-0 md:group-hover/tool:opacity-100 md:group-focus-within/tool:opacity-100\",\n actionsVisible && \"md:opacity-100\",\n )}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n toggleFavorite(tool.id);\n }}\n className={cn(\n \"pointer-events-auto cursor-pointer rounded p-0.5 transition-colors\",\n isFav\n ? \"text-yellow-500\"\n : \"text-muted-foreground/40 hover:text-yellow-500\",\n )}\n aria-label={isFav ? \"Unfavorite\" : \"Favorite\"}\n >\n {isFav ? (\n <IconStarFilled className=\"h-3 w-3\" />\n ) : (\n <IconStar className=\"h-3 w-3\" />\n )}\n </button>\n\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setMenuOpenId(menuOpenId === tool.id ? null : tool.id);\n }}\n className=\"pointer-events-auto cursor-pointer rounded p-0.5 text-muted-foreground/40 transition-colors hover:text-foreground\"\n aria-label=\"Tool actions\"\n >\n <IconDots className=\"h-3 w-3\" />\n </button>\n\n {menuOpenId === tool.id && (\n <div\n className=\"absolute right-0 top-full z-50 mt-1 min-w-[120px] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n onClick={() => startRename(tool)}\n className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent\"\n >\n <IconPencil className=\"h-3.5 w-3.5\" />\n Rename\n </button>\n <button\n type=\"button\"\n onClick={() => handleDelete(tool.id)}\n className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive hover:bg-accent\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n Delete\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -22,6 +22,7 @@ export interface LiveTranscriptionApi {
22
22
  interimText: string;
23
23
  start: () => void;
24
24
  stop: () => string;
25
+ stopAndWait: (timeoutMs?: number) => Promise<string>;
25
26
  pause: () => void;
26
27
  resume: () => void;
27
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-live-transcription.d.ts","sourceRoot":"","sources":["../../../src/client/transcription/use-live-transcription.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,CAAC,EAAE,2BAA2B,GACpC,oBAAoB,CA2ItB"}
1
+ {"version":3,"file":"use-live-transcription.d.ts","sourceRoot":"","sources":["../../../src/client/transcription/use-live-transcription.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,CAAC,EAAE,2BAA2B,GACpC,oBAAoB,CAuLtB"}
@@ -29,6 +29,7 @@ export function useLiveTranscription(options) {
29
29
  const recognitionRef = useRef(null);
30
30
  const transcriptRef = useRef("");
31
31
  const stoppedManuallyRef = useRef(false);
32
+ const stopWaiterRef = useRef(null);
32
33
  const supported = !!getSpeechRecognitionCtor();
33
34
  const start = useCallback(() => {
34
35
  const Ctor = getSpeechRecognitionCtor();
@@ -85,6 +86,9 @@ export function useLiveTranscription(options) {
85
86
  return;
86
87
  }
87
88
  setIsActive(false);
89
+ if (stopWaiterRef.current) {
90
+ stopWaiterRef.current(transcriptRef.current);
91
+ }
88
92
  };
89
93
  try {
90
94
  recognition.start();
@@ -109,6 +113,42 @@ export function useLiveTranscription(options) {
109
113
  setIsActive(false);
110
114
  return transcriptRef.current;
111
115
  }, []);
116
+ const stopAndWait = useCallback((timeoutMs = 1200) => {
117
+ stoppedManuallyRef.current = true;
118
+ setInterimText("");
119
+ const recognition = recognitionRef.current;
120
+ if (!recognition) {
121
+ setIsActive(false);
122
+ return Promise.resolve(transcriptRef.current);
123
+ }
124
+ return new Promise((resolve) => {
125
+ let settled = false;
126
+ const finish = (text) => {
127
+ if (settled)
128
+ return;
129
+ settled = true;
130
+ window.clearTimeout(timeout);
131
+ if (stopWaiterRef.current === finish) {
132
+ stopWaiterRef.current = null;
133
+ }
134
+ if (recognitionRef.current === recognition) {
135
+ recognitionRef.current = null;
136
+ }
137
+ setIsActive(false);
138
+ resolve(text);
139
+ };
140
+ const timeout = window.setTimeout(() => {
141
+ finish(transcriptRef.current);
142
+ }, timeoutMs);
143
+ stopWaiterRef.current = finish;
144
+ try {
145
+ recognition.stop();
146
+ }
147
+ catch {
148
+ finish(transcriptRef.current);
149
+ }
150
+ });
151
+ }, []);
112
152
  const pause = useCallback(() => {
113
153
  if (!recognitionRef.current)
114
154
  return;
@@ -149,6 +189,7 @@ export function useLiveTranscription(options) {
149
189
  interimText,
150
190
  start,
151
191
  stop,
192
+ stopAndWait,
152
193
  pause,
153
194
  resume,
154
195
  };
@@ -1 +1 @@
1
- {"version":3,"file":"use-live-transcription.js","sourceRoot":"","sources":["../../../src/client/transcription/use-live-transcription.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Live transcription hook — runs the browser's Web Speech API alongside\n * any recording to produce an instant transcript with no API key required.\n *\n * Designed to pair with a MediaRecorder: start when recording begins,\n * stop when the user hits stop. The accumulated transcript is available\n * immediately — no round-trip to Whisper needed.\n *\n * Higher-quality backends (Groq Whisper, OpenAI Whisper, Deepgram) can\n * refine the result afterward, but this gives users something useful\n * from second zero even without an API key.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction getSpeechRecognitionCtor(): any {\n if (typeof window === \"undefined\") return null;\n return (\n (window as any).SpeechRecognition ||\n (window as any).webkitSpeechRecognition ||\n null\n );\n}\n\nexport interface UseLiveTranscriptionOptions {\n lang?: string;\n}\n\nexport interface LiveTranscriptionApi {\n supported: boolean;\n isActive: boolean;\n /** Accumulated final transcript text so far. */\n transcript: string;\n /** Current interim (unconfirmed) text being spoken. */\n interimText: string;\n start: () => void;\n stop: () => string;\n pause: () => void;\n resume: () => void;\n}\n\nexport function useLiveTranscription(\n options?: UseLiveTranscriptionOptions,\n): LiveTranscriptionApi {\n const lang =\n options?.lang ??\n (typeof navigator !== \"undefined\" ? navigator.language : \"en-US\");\n\n const [isActive, setIsActive] = useState(false);\n const [transcript, setTranscript] = useState(\"\");\n const [interimText, setInterimText] = useState(\"\");\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const recognitionRef = useRef<any>(null);\n const transcriptRef = useRef(\"\");\n const stoppedManuallyRef = useRef(false);\n\n const supported = !!getSpeechRecognitionCtor();\n\n const start = useCallback(() => {\n const Ctor = getSpeechRecognitionCtor();\n if (!Ctor) return;\n\n // Clean up any prior session.\n if (recognitionRef.current) {\n try {\n recognitionRef.current.abort();\n } catch {\n /* ignore */\n }\n }\n\n const recognition = new Ctor();\n recognition.continuous = true;\n recognition.interimResults = true;\n recognition.lang = lang;\n recognitionRef.current = recognition;\n transcriptRef.current = \"\";\n stoppedManuallyRef.current = false;\n setTranscript(\"\");\n setInterimText(\"\");\n\n recognition.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n transcriptRef.current += text;\n setTranscript(transcriptRef.current);\n } else {\n interim += text;\n }\n }\n setInterimText(interim);\n };\n\n recognition.onerror = (event: any) => {\n if (event.error === \"no-speech\" || event.error === \"aborted\") return;\n console.warn(\"[live-transcription] error:\", event.error);\n };\n\n recognition.onend = () => {\n // Web Speech sometimes stops on its own (silence timeout, network\n // hiccup). Restart automatically unless we stopped intentionally.\n if (!stoppedManuallyRef.current && recognitionRef.current) {\n try {\n recognition.start();\n } catch {\n setIsActive(false);\n }\n return;\n }\n setIsActive(false);\n };\n\n try {\n recognition.start();\n setIsActive(true);\n } catch {\n /* browser may block without user gesture */\n }\n }, [lang]);\n\n const stop = useCallback((): string => {\n stoppedManuallyRef.current = true;\n setInterimText(\"\");\n if (recognitionRef.current) {\n try {\n recognitionRef.current.stop();\n } catch {\n /* ignore */\n }\n recognitionRef.current = null;\n }\n setIsActive(false);\n return transcriptRef.current;\n }, []);\n\n const pause = useCallback(() => {\n if (!recognitionRef.current) return;\n stoppedManuallyRef.current = true;\n try {\n recognitionRef.current.stop();\n } catch {\n /* ignore */\n }\n }, []);\n\n const resume = useCallback(() => {\n if (!recognitionRef.current) return;\n stoppedManuallyRef.current = false;\n try {\n recognitionRef.current.start();\n setIsActive(true);\n } catch {\n /* ignore */\n }\n }, []);\n\n // Clean up on unmount\n const startRef = useRef(start);\n const stopRef = useRef(stop);\n startRef.current = start;\n stopRef.current = stop;\n\n useEffect(() => {\n return () => {\n stopRef.current();\n };\n }, []);\n\n return {\n supported,\n isActive,\n transcript,\n interimText,\n start,\n stop,\n pause,\n resume,\n };\n}\n"]}
1
+ {"version":3,"file":"use-live-transcription.js","sourceRoot":"","sources":["../../../src/client/transcription/use-live-transcription.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Live transcription hook — runs the browser's Web Speech API alongside\n * any recording to produce an instant transcript with no API key required.\n *\n * Designed to pair with a MediaRecorder: start when recording begins,\n * stop when the user hits stop. The accumulated transcript is available\n * immediately — no round-trip to Whisper needed.\n *\n * Higher-quality backends (Groq Whisper, OpenAI Whisper, Deepgram) can\n * refine the result afterward, but this gives users something useful\n * from second zero even without an API key.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction getSpeechRecognitionCtor(): any {\n if (typeof window === \"undefined\") return null;\n return (\n (window as any).SpeechRecognition ||\n (window as any).webkitSpeechRecognition ||\n null\n );\n}\n\nexport interface UseLiveTranscriptionOptions {\n lang?: string;\n}\n\nexport interface LiveTranscriptionApi {\n supported: boolean;\n isActive: boolean;\n /** Accumulated final transcript text so far. */\n transcript: string;\n /** Current interim (unconfirmed) text being spoken. */\n interimText: string;\n start: () => void;\n stop: () => string;\n stopAndWait: (timeoutMs?: number) => Promise<string>;\n pause: () => void;\n resume: () => void;\n}\n\nexport function useLiveTranscription(\n options?: UseLiveTranscriptionOptions,\n): LiveTranscriptionApi {\n const lang =\n options?.lang ??\n (typeof navigator !== \"undefined\" ? navigator.language : \"en-US\");\n\n const [isActive, setIsActive] = useState(false);\n const [transcript, setTranscript] = useState(\"\");\n const [interimText, setInterimText] = useState(\"\");\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const recognitionRef = useRef<any>(null);\n const transcriptRef = useRef(\"\");\n const stoppedManuallyRef = useRef(false);\n const stopWaiterRef = useRef<((text: string) => void) | null>(null);\n\n const supported = !!getSpeechRecognitionCtor();\n\n const start = useCallback(() => {\n const Ctor = getSpeechRecognitionCtor();\n if (!Ctor) return;\n\n // Clean up any prior session.\n if (recognitionRef.current) {\n try {\n recognitionRef.current.abort();\n } catch {\n /* ignore */\n }\n }\n\n const recognition = new Ctor();\n recognition.continuous = true;\n recognition.interimResults = true;\n recognition.lang = lang;\n recognitionRef.current = recognition;\n transcriptRef.current = \"\";\n stoppedManuallyRef.current = false;\n setTranscript(\"\");\n setInterimText(\"\");\n\n recognition.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n transcriptRef.current += text;\n setTranscript(transcriptRef.current);\n } else {\n interim += text;\n }\n }\n setInterimText(interim);\n };\n\n recognition.onerror = (event: any) => {\n if (event.error === \"no-speech\" || event.error === \"aborted\") return;\n console.warn(\"[live-transcription] error:\", event.error);\n };\n\n recognition.onend = () => {\n // Web Speech sometimes stops on its own (silence timeout, network\n // hiccup). Restart automatically unless we stopped intentionally.\n if (!stoppedManuallyRef.current && recognitionRef.current) {\n try {\n recognition.start();\n } catch {\n setIsActive(false);\n }\n return;\n }\n setIsActive(false);\n if (stopWaiterRef.current) {\n stopWaiterRef.current(transcriptRef.current);\n }\n };\n\n try {\n recognition.start();\n setIsActive(true);\n } catch {\n /* browser may block without user gesture */\n }\n }, [lang]);\n\n const stop = useCallback((): string => {\n stoppedManuallyRef.current = true;\n setInterimText(\"\");\n if (recognitionRef.current) {\n try {\n recognitionRef.current.stop();\n } catch {\n /* ignore */\n }\n recognitionRef.current = null;\n }\n setIsActive(false);\n return transcriptRef.current;\n }, []);\n\n const stopAndWait = useCallback((timeoutMs = 1200): Promise<string> => {\n stoppedManuallyRef.current = true;\n setInterimText(\"\");\n\n const recognition = recognitionRef.current;\n if (!recognition) {\n setIsActive(false);\n return Promise.resolve(transcriptRef.current);\n }\n\n return new Promise((resolve) => {\n let settled = false;\n const finish = (text: string) => {\n if (settled) return;\n settled = true;\n window.clearTimeout(timeout);\n if (stopWaiterRef.current === finish) {\n stopWaiterRef.current = null;\n }\n if (recognitionRef.current === recognition) {\n recognitionRef.current = null;\n }\n setIsActive(false);\n resolve(text);\n };\n\n const timeout = window.setTimeout(() => {\n finish(transcriptRef.current);\n }, timeoutMs);\n\n stopWaiterRef.current = finish;\n try {\n recognition.stop();\n } catch {\n finish(transcriptRef.current);\n }\n });\n }, []);\n\n const pause = useCallback(() => {\n if (!recognitionRef.current) return;\n stoppedManuallyRef.current = true;\n try {\n recognitionRef.current.stop();\n } catch {\n /* ignore */\n }\n }, []);\n\n const resume = useCallback(() => {\n if (!recognitionRef.current) return;\n stoppedManuallyRef.current = false;\n try {\n recognitionRef.current.start();\n setIsActive(true);\n } catch {\n /* ignore */\n }\n }, []);\n\n // Clean up on unmount\n const startRef = useRef(start);\n const stopRef = useRef(stop);\n startRef.current = start;\n stopRef.current = stop;\n\n useEffect(() => {\n return () => {\n stopRef.current();\n };\n }, []);\n\n return {\n supported,\n isActive,\n transcript,\n interimText,\n start,\n stop,\n stopAndWait,\n pause,\n resume,\n };\n}\n"]}
@@ -659,14 +659,83 @@ function stripHtmlForPlainText(html) {
659
659
  .replace(/\n{3,}/g, "\n\n")
660
660
  .trim();
661
661
  }
662
+ function escapeHtml(s) {
663
+ return s
664
+ .replace(/&/g, "&amp;")
665
+ .replace(/</g, "&lt;")
666
+ .replace(/>/g, "&gt;")
667
+ .replace(/"/g, "&quot;")
668
+ .replace(/'/g, "&#39;");
669
+ }
670
+ function decodeBasicHtmlEntities(s) {
671
+ return s
672
+ .replace(/&amp;/g, "&")
673
+ .replace(/&lt;/g, "<")
674
+ .replace(/&gt;/g, ">")
675
+ .replace(/&quot;/g, '"')
676
+ .replace(/&#39;/g, "'");
677
+ }
678
+ function splitTrailingUrlPunctuation(raw) {
679
+ let url = raw;
680
+ let trailing = "";
681
+ const trailingEntities = ["&quot;", "&#39;"];
682
+ for (;;) {
683
+ const entity = trailingEntities.find((candidate) => url.endsWith(candidate));
684
+ if (!entity)
685
+ break;
686
+ url = url.slice(0, -entity.length);
687
+ trailing = entity + trailing;
688
+ }
689
+ while (/[.,!?;:]$/.test(url)) {
690
+ trailing = url.slice(-1) + trailing;
691
+ url = url.slice(0, -1);
692
+ }
693
+ while (url.endsWith(")") && !url.includes("(")) {
694
+ trailing = ")" + trailing;
695
+ url = url.slice(0, -1);
696
+ }
697
+ return { url, trailing };
698
+ }
699
+ function labelForUrl(rawUrl) {
700
+ try {
701
+ const parsed = new URL(decodeBasicHtmlEntities(rawUrl));
702
+ const host = parsed.hostname.replace(/^www\./, "");
703
+ return host ? `Open ${host}` : "Open link";
704
+ }
705
+ catch {
706
+ return "Open link";
707
+ }
708
+ }
709
+ function linkifyTextSegment(segment) {
710
+ return segment.replace(/\bhttps?:\/\/[^\s<>"']+/gi, (raw) => {
711
+ const { url, trailing } = splitTrailingUrlPunctuation(raw);
712
+ const href = decodeBasicHtmlEntities(url);
713
+ return `<a href="${escapeHtml(href)}" style="color:#2563eb;text-decoration:underline;">${escapeHtml(labelForUrl(url))}</a>${trailing}`;
714
+ });
715
+ }
716
+ function linkifyBareUrlsInHtml(html) {
717
+ const parts = html.split(/(<\/?[^>]+>)/g);
718
+ let skipDepth = 0;
719
+ return parts
720
+ .map((part) => {
721
+ if (part.startsWith("<") && part.endsWith(">")) {
722
+ if (/^<\/\s*(a|code)\b/i.test(part)) {
723
+ skipDepth = Math.max(0, skipDepth - 1);
724
+ }
725
+ else if (/^<\s*(a|code)\b/i.test(part)) {
726
+ skipDepth += 1;
727
+ }
728
+ return part;
729
+ }
730
+ return skipDepth > 0 ? part : linkifyTextSegment(part);
731
+ })
732
+ .join("");
733
+ }
662
734
  /** Convert basic markdown to HTML for email rendering */
663
735
  function markdownToHtml(md) {
664
736
  let html = md;
665
737
  // Escape HTML entities in the source (but not our generated tags)
666
- html = html
667
- .replace(/&/g, "&amp;")
668
- .replace(/</g, "&lt;")
669
- .replace(/>/g, "&gt;");
738
+ html = escapeHtml(html);
670
739
  // Bold: **text** or __text__
671
740
  html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
672
741
  html = html.replace(/__(.+?)__/g, "<strong>$1</strong>");
@@ -674,9 +743,16 @@ function markdownToHtml(md) {
674
743
  html = html.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g, "<em>$1</em>");
675
744
  html = html.replace(/(?<!\w)_([^_]+?)_(?!\w)/g, "<em>$1</em>");
676
745
  // Links: [text](url)
677
- html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:#2563eb;text-decoration:underline;">$1</a>');
746
+ html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, label, url) => {
747
+ const visibleLabel = /^https?:\/\//i.test(decodeBasicHtmlEntities(label))
748
+ ? escapeHtml(labelForUrl(label))
749
+ : label;
750
+ return `<a href="${escapeHtml(decodeBasicHtmlEntities(url))}" style="color:#2563eb;text-decoration:underline;">${visibleLabel}</a>`;
751
+ });
678
752
  // Inline code: `code`
679
753
  html = html.replace(/`([^`]+)`/g, '<code style="background:#f1f5f9;padding:1px 4px;border-radius:3px;font-size:0.9em;">$1</code>');
754
+ // Bare URLs: keep the destination in href but avoid spelling long URLs out.
755
+ html = linkifyBareUrlsInHtml(html);
680
756
  // Unordered lists: lines starting with "- " or "* "
681
757
  html = html.replace(/^([*-]) (.+)$/gm, "<li>$2</li>");
682
758
  // Wrap consecutive <li> in <ul>