diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f188ab..f5adb70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.1] - 2026-06-20 + +### Added + +- ๐Ÿ” **Firecrawl web search.** Added Firecrawl as a web search provider. Configure your API key from Settings > Web, or set `FIRECRAWL_API_KEY` as an environment variable. Firecrawl slots in between Brave and DuckDuckGo in the automatic provider order, and also works with a custom self-hosted endpoint. + +### Changed + +- ๐Ÿ“‚ **Workspace paths are normalized.** Paths like `~/Projects/myapp` and `/Users/you/Projects/myapp` now resolve to the same workspace instead of creating duplicates. Existing duplicates are cleaned up automatically when you open or save a workspace. +- ๐Ÿ”” **Clicking a browser notification opens the chat.** Desktop notifications for completed tasks now take you straight to the conversation when you click them, instead of just bringing the window to the front. +- ๐Ÿท๏ธ **Workspace names display consistently.** Folder names shown in the sidebar, search results, automation list, and notifications now all use the same logic, so you see the same label everywhere. +- ๐Ÿงน **Pending messages follow the right branch.** When queued messages or background sub-agent results come in, they now attach to the correct point in the conversation instead of occasionally landing on the wrong branch. + ## [0.6.0] - 2026-06-20 ### Added diff --git a/cptr/frontend/src/lib/components/Admin/CreateBotModal.svelte b/cptr/frontend/src/lib/components/Admin/CreateBotModal.svelte index 209c07a..e9af940 100644 --- a/cptr/frontend/src/lib/components/Admin/CreateBotModal.svelte +++ b/cptr/frontend/src/lib/components/Admin/CreateBotModal.svelte @@ -8,6 +8,7 @@ import DropdownMenu from '../DropdownMenu.svelte'; import ModelSelector from '../common/ModelSelector.svelte'; import { selectedModelId, workspaceList } from '$lib/stores'; + import { getPathDisplayName } from '$lib/utils/paths'; import { createBot, updateBot, verifyBotToken, type BotData, type BotForm } from '$lib/apis/bots'; import { toast } from 'svelte-sonner'; import { t } from '$lib/i18n'; @@ -35,7 +36,7 @@ // Workspace dropdown let showWsMenu = $state(false); - let wsBtnEl: HTMLButtonElement | undefined = $state(); + let workspaceButtonEl: HTMLButtonElement | undefined = $state(); $effect(() => { if (!workspace && $workspaceList.length > 0) { @@ -43,18 +44,22 @@ } }); - let wsMenuItems = $derived( - $workspaceList.map((ws) => ({ - label: ws.name, + let workspaceMenuItems = $derived( + $workspaceList.map((workspaceOption) => ({ + label: workspaceOption.name, icon: 'folder', - active: ws.path === workspace, + active: workspaceOption.path === workspace, check: true, - onclick: () => { workspace = ws.path; } + onclick: () => { + workspace = workspaceOption.path; + } })) ); - let selectedWsName = $derived( - $workspaceList.find((w) => w.path === workspace)?.name || workspace.split('/').pop() || $t('automationModal.selectWorkspace') + let selectedWorkspaceName = $derived( + $workspaceList.find((w) => w.path === workspace)?.name || + getPathDisplayName(workspace) || + $t('automationModal.selectWorkspace') ); const platformHints: Record = $derived({ @@ -89,7 +94,11 @@ name: name.trim(), model_id: modelId, workspace, - allowed_senders: allowedSenders.split(',').map((s) => s.trim()).filter(Boolean) || undefined + allowed_senders: + allowedSenders + .split(',') + .map((s) => s.trim()) + .filter(Boolean) || undefined }; if (token.trim()) update.token = token.trim(); await updateBot(bot.id, update); @@ -100,7 +109,11 @@ token: token.trim(), model_id: modelId, workspace, - allowed_senders: allowedSenders.split(',').map((s) => s.trim()).filter(Boolean) || undefined + allowed_senders: + allowedSenders + .split(',') + .map((s) => s.trim()) + .filter(Boolean) || undefined }); } onsave(); @@ -141,10 +154,14 @@ />
- + @@ -200,7 +219,9 @@ {#if verifyResult}

{#if verifyResult.ok} - โœ“ {verifyResult.info?.username ? `@${verifyResult.info.username}` : `ID: ${verifyResult.info?.id}`} + โœ“ {verifyResult.info?.username + ? `@${verifyResult.info.username}` + : `ID: ${verifyResult.info?.id}`} {:else} โœ— {verifyResult.error} {/if} @@ -208,8 +229,12 @@ {/if} - -

{$t('messaging.allowedSendersHint')}

+ +

+ {$t('messaging.allowedSendersHint')} +

@@ -256,10 +289,10 @@
-{#if showWsMenu && wsBtnEl} +{#if showWsMenu && workspaceButtonEl} (showWsMenu = false)} preferAbove={true} maxHeight="15rem" diff --git a/cptr/frontend/src/lib/components/Admin/Web.svelte b/cptr/frontend/src/lib/components/Admin/Web.svelte index 030bba3..5b14981 100644 --- a/cptr/frontend/src/lib/components/Admin/Web.svelte +++ b/cptr/frontend/src/lib/components/Admin/Web.svelte @@ -19,6 +19,8 @@ let braveKey = $state(''); let perplexityKey = $state(''); let perplexityBaseUrl = $state(''); + let firecrawlSearchKey = $state(''); + let firecrawlSearchBaseUrl = $state('https://api.firecrawl.dev'); let ccKey = $state(''); let ccBaseUrl = $state(''); let ccModel = $state(''); @@ -46,6 +48,8 @@ braveKey = (config['web.brave_api_key'] as string) || ''; perplexityKey = (config['web.perplexity_api_key'] as string) || ''; perplexityBaseUrl = (config['web.perplexity_base_url'] as string) || ''; + firecrawlSearchKey = (config['web.firecrawl_api_key'] as string) || ''; + firecrawlSearchBaseUrl = (config['web.firecrawl_base_url'] as string) || 'https://api.firecrawl.dev'; ccKey = (config['web.chat_completions_api_key'] as string) || ''; ccBaseUrl = (config['web.chat_completions_base_url'] as string) || ''; ccModel = (config['web.chat_completions_model'] as string) || ''; @@ -77,6 +81,8 @@ 'web.brave_api_key': braveKey, 'web.perplexity_api_key': perplexityKey, 'web.perplexity_base_url': perplexityBaseUrl, + 'web.firecrawl_api_key': firecrawlSearchKey, + 'web.firecrawl_base_url': firecrawlSearchBaseUrl, 'web.chat_completions_api_key': ccKey, 'web.chat_completions_base_url': ccBaseUrl, 'web.chat_completions_model': ccModel, @@ -147,6 +153,7 @@ + @@ -181,6 +188,19 @@ class="w-full mt-1 h-7 px-2 rounded-lg text-xs bg-gray-100 dark:bg-white/6 text-gray-700 dark:text-gray-300 border border-gray-200 dark:border-white/8 outline-none focus:border-blue-400 dark:focus:border-blue-500 transition-colors" />

{$t('admin.webBraveHint')}

+ {:else if searchProvider === 'firecrawl'} +
+ + +

{$t('admin.webFirecrawlHint')}

+
+
+ + +

{$t('admin.browserFirecrawlBaseUrlHint')}

+
{:else if searchProvider === 'perplexity'}
diff --git a/cptr/frontend/src/lib/components/SearchModal.svelte b/cptr/frontend/src/lib/components/SearchModal.svelte index d15c9f1..c7c3080 100644 --- a/cptr/frontend/src/lib/components/SearchModal.svelte +++ b/cptr/frontend/src/lib/components/SearchModal.svelte @@ -1,5 +1,6 @@