Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
04147f7
fix(chat): stop losing sends aborted during mount-settling
j15z Aug 11, 2026
b840a3a
fix(chat): detect aborts by signal state, not error identity
j15z Aug 11, 2026
cd23af8
fix(chat): hand an aborted chatless send to the next mount
j15z Aug 11, 2026
ed4ea7c
fix(chat): deliver an aborted chatless send to the live replacement s…
j15z Aug 11, 2026
d078e82
refactor(chat): thread the recoverable-abort outcome through the send…
j15z Aug 11, 2026
81716ff
fix(chat): carry attachments through the cross-mount send handoff
j15z Aug 11, 2026
45357cb
fix(panel): forward event attachments to the copilot send
j15z Aug 11, 2026
3e67769
fix(chat): carry attachments through the stored handoff lane too
j15z Aug 11, 2026
fc881bf
feat(search): improve command palette results
j15z Aug 4, 2026
a4625ab
feat(search): sharpen command palette discovery
j15z Aug 5, 2026
1ce85ca
feat(search): unify cmd+k into one page-aware section model
j15z Aug 8, 2026
1091783
feat(search): ask-Sim tab mode, canvas sections, and palette refinements
j15z Aug 10, 2026
00dceb4
fix(search): order module results below Sim actions
j15z Aug 10, 2026
ecb6ade
fix(review): make command palette fast and focused
j15z Aug 10, 2026
9139781
fix(search): restore Ask Sim prefill and refine palette ranking
j15z Aug 11, 2026
160d500
chore(sidebar): drop unused getSettingsHref destructure
j15z Aug 11, 2026
16a6787
fix(deploy): gate every deploy invoker on full eligibility
j15z Aug 11, 2026
c1bd985
fix(search): port the palette to post-#6458 staging
j15z Aug 11, 2026
852f700
feat(search): auto-send Ask Sim queries via the chat handoff
j15z Aug 11, 2026
08128f1
revert(search): return Ask Sim to prefill, storing raw prose
j15z Aug 11, 2026
a77ce2a
feat(search): auto-send Ask Sim queries via the chat handoff
j15z Aug 11, 2026
62971be
fix(deploy): include registry loading in the deploy invoker gate
j15z Aug 11, 2026
5a8ac0d
improvement(search): label the ask row New Chat
j15z Aug 11, 2026
c4b2728
refactor(search): apply simplify-pass cleanups
j15z Aug 11, 2026
b0ecf22
fix(search): paint the palette fog with the dialog's own surface
j15z Aug 11, 2026
9b82ef4
fix(search): the palette fog matches the inner --bg panel, not the di…
j15z Aug 11, 2026
693e245
fix(search): review-round parity and consistency fixes
j15z Aug 11, 2026
b39bb97
fix(deploy): use the emcn toast input shape
j15z Aug 11, 2026
61a2559
fix(search): rename logs view toggles to "Switch to Logs/Dashboard"
j15z Aug 11, 2026
9ad2d36
Merge remote-tracking branch 'origin/staging' into feat-enhance-cmd-k
j15z Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/files/files.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import {
isUntitledName,
uniqueMarkdownName,
} from '@/app/workspace/[workspaceId]/files/untitled-title'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { useContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/hooks'
import { usePinItem, usePinnedIds, useUnpinItem } from '@/hooks/queries/pinned-items'
Expand Down Expand Up @@ -1681,6 +1682,16 @@ export function Files() {
fileInputRef.current?.click()
}, [canEdit, uploading])

useRegisterGlobalCommands(() => [
{ id: 'files-upload', handler: () => handleUploadClick() },
{ id: 'files-new-file', handler: () => void handleCreateFile() },
{ id: 'files-new-folder', handler: () => void handleCreateFolder() },
{ id: 'file-download', handler: () => handleDownloadSelected() },
{ id: 'file-rename', handler: () => handleStartHeaderRename() },
{ id: 'file-share', handler: () => handleShareSelected() },
{ id: 'file-delete', handler: () => handleDeleteSelected() },
])

const searchConfig: SearchConfig = {
value: urlSearchTerm,
onChange: setSearchTerm,
Expand Down
9 changes: 9 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
pageUrlKeys,
} from '@/app/workspace/[workspaceId]/knowledge/[id]/search-params'
import { getDocumentIcon } from '@/app/workspace/[workspaceId]/knowledge/components'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { useContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/hooks'
import { CONNECTOR_META_REGISTRY } from '@/connectors/registry'
Expand Down Expand Up @@ -707,6 +708,14 @@ export function KnowledgeBase({
setShowAddDocumentsModal(true)
}

useRegisterGlobalCommands(() => [
{ id: 'knowledge-base-new-documents', handler: () => setShowAddDocumentsModal(true) },
{ id: 'knowledge-base-new-connector', handler: () => setShowAddConnectorModal(true) },
{ id: 'knowledge-base-rename', handler: () => kbRename.startRename(id, knowledgeBaseName) },
{ id: 'knowledge-base-tags', handler: () => setShowTagsModal(true) },
{ id: 'knowledge-base-delete', handler: () => setShowDeleteDialog(true) },
])

/**
* Handles bulk enabling of selected documents
*/
Expand Down
6 changes: 6 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/knowledge/knowledge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
knowledgeUrlKeys,
} from '@/app/workspace/[workspaceId]/knowledge/search-params'
import { filterKnowledgeBases } from '@/app/workspace/[workspaceId]/knowledge/utils/filter'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { useContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/hooks'
import { CONNECTOR_META_REGISTRY } from '@/connectors/registry'
Expand Down Expand Up @@ -726,6 +727,11 @@ export function Knowledge() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [workspaceId])

useRegisterGlobalCommands(() => [
{ id: 'knowledge-new-base', handler: () => handleOpenCreateModal() },
{ id: 'knowledge-new-folder', handler: () => void handleCreateFolder() },
])

const handleRenameFolder = useCallback(() => {
const folder = activeFolderRef.current
if (!folder) return
Expand Down
8 changes: 8 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/logs/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import {
logSortParams,
} from '@/app/workspace/[workspaceId]/logs/search-params'
import type { Suggestion } from '@/app/workspace/[workspaceId]/logs/types'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { getBlock } from '@/blocks/registry'
import { useFolderMap, useFolders } from '@/hooks/queries/folders'
Expand Down Expand Up @@ -698,6 +699,13 @@ export default function Logs() {
debouncedSearchQuery,
])

useRegisterGlobalCommands(() => [
{ id: 'logs-refresh', handler: () => handleRefresh() },
{ id: 'logs-export', handler: () => void handleExport() },
{ id: 'logs-show-dashboard', handler: () => setViewMode('dashboard') },
{ id: 'logs-show-logs', handler: () => setViewMode('logs') },
])

const loadMoreLogs = useCallback(() => {
const { isFetching, hasNextPage, fetchNextPage } = logsQueryRef.current
if (!isFetching && hasNextPage) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ export interface ParsedShortcut {

export interface GlobalCommand {
id?: string
shortcut: string
/** Keyboard binding. Omit for palette-only commands invoked by id. */
shortcut?: string
allowInEditable?: boolean
handler: (event: KeyboardEvent) => void
}

interface RegistryCommand extends GlobalCommand {
id: string
parsed: ParsedShortcut
parsed: ParsedShortcut | null
}

interface GlobalCommandsContextValue {
Expand Down Expand Up @@ -130,7 +131,7 @@ export function GlobalCommandsProvider({ children }: { children: ReactNode }) {
const createdIds: string[] = []
for (const cmd of commands) {
const id = cmd.id ?? generateId()
const parsed = parseShortcut(cmd.shortcut)
const parsed = cmd.shortcut ? parseShortcut(cmd.shortcut) : null
registryRef.current.set(id, {
...cmd,
id,
Expand All @@ -152,6 +153,7 @@ export function GlobalCommandsProvider({ children }: { children: ReactNode }) {
if (e.isComposing) return

for (const [, cmd] of registryRef.current) {
if (!cmd.parsed) continue
if (!cmd.allowInEditable && isEditableElement(document.activeElement)) continue

if (matchesShortcut(e, cmd.parsed)) {
Expand Down
29 changes: 29 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from '@/app/workspace/[workspaceId]/components/folders'
import { PresenceAvatars } from '@/app/workspace/[workspaceId]/components/presence/presence-avatars'
import { LogDetails } from '@/app/workspace/[workspaceId]/logs/components'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { ImportCsvDialog } from '@/app/workspace/[workspaceId]/tables/components/import-csv-dialog'
import { ImportProgressMenu } from '@/app/workspace/[workspaceId]/tables/components/import-progress-menu'
Expand Down Expand Up @@ -1068,6 +1069,34 @@ export function Table({
}
}, [tableData, workspaceId])

useRegisterGlobalCommands(() => [
{
id: 'table-new-column',
handler: () => {
if (!userPermissions.canEdit) return
if (tableDataRef.current?.locks.schemaLocked) {
showBlockedToast('add-column')
return
}
handleAddColumnOfType('string')
},
},
{
id: 'table-export-csv',
handler: () => {
if (!tableDataRef.current?.rowCount) return
void handleExportCsv()
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent empty CSV export

Low Severity

table-export-csv is always offered on table detail, but the handler no-ops when rowCount is 0. The header Export control is disabled for empty tables, so the palette path gives no indication why nothing happened—the same class of silent failure the deploy action was later fixed to toast for.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b39bb97. Configure here.

},
{
id: 'table-import-csv',
handler: () => {
if (!userPermissions.canEdit || tableDataRef.current?.locks.insertLocked) return
onRequestImportCsv()
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent locked CSV import

Medium Severity

table-import-csv still appears in the palette whenever canEdit is true, but the handler returns with no feedback when insertLocked is set. The header control is disabled for that lock, and the sibling table-new-column command already surfaces a blocked toast for schemaLocked, so a palette import on an insert-locked table looks selectable and then does nothing.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b39bb97. Configure here.

},
])

const columnOptions = useMemo<ColumnOption[]>(
() =>
columns.map((col) => ({
Expand Down
12 changes: 12 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/tables/tables.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
useFolderNavigation,
useFolderRowDragDrop,
} from '@/app/workspace/[workspaceId]/components/folders'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import {
ImportCsvDialog,
Expand Down Expand Up @@ -1033,6 +1034,17 @@ export function Tables() {
}
}, [workspaceId, folders, currentFolderId, createFolderAsync, setSearchTerm, startFolderRename])

useRegisterGlobalCommands(() => [
{ id: 'tables-new-table', handler: () => void handleCreateTable() },
{ id: 'tables-new-folder', handler: () => void handleCreateFolder() },
{
id: 'tables-import-csv',
handler: () => {
if (!uploading) csvInputRef.current?.click()
},
},
])
Comment thread
j15z marked this conversation as resolved.

const headerActions: ResourceAction[] = useMemo(
() => [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from 'react'
import { Button, cn } from '@sim/emcn'
import { Search, X } from '@sim/emcn/icons'
import { X } from '@sim/emcn/icons'
import { WorkflowBlockBorder, type WorkflowBorderPort } from '@sim/workflow-renderer'
import { Command } from 'cmdk'
import { useParams } from 'next/navigation'
import { usePostHog } from 'posthog-js/react'
import { Handle, type NodeProps, Position } from 'reactflow'
import { captureEvent } from '@/lib/posthog/client'
import {
CommandFadedList,
CommandSearch,
} from '@/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/components/command-chrome'
import { MemoizedCommandItem } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/components/command-items'
import {
BlocksGroup,
Expand Down Expand Up @@ -403,10 +407,11 @@ export function ConnectionBlockSelector({ id, data }: NodeProps<ConnectionBlockS
className='relative z-20 flex h-full flex-col overflow-hidden rounded-2xl [clip-path:inset(0_round_16px)]'
>
<div className='relative min-h-0 flex-1'>
<Command.List
<CommandFadedList
ref={listRef}
fade='canvas'
className={cn(
"nodrag nopan nowheel allow-scroll scrollbar-none [&_[cmdk-item][aria-selected='true']]:!border-transparent [&_[cmdk-item][aria-selected='true']]:!bg-[var(--surface-hover)] [&_[cmdk-item]_svg]:!scale-100 [&_[cmdk-item]_svg]:!transition-none h-full overflow-y-auto overflow-x-hidden px-1.5 pt-12 pb-1.5 [-webkit-mask-image:linear-gradient(to_bottom,transparent_0%,transparent_8%,black_18%,black_94%,transparent_100%)] [clip-path:inset(3px_round_13px)] [mask-image:linear-gradient(to_bottom,transparent_0%,transparent_8%,black_18%,black_94%,transparent_100%)] [&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col",
"nodrag nopan nowheel allow-scroll scrollbar-none [&_[cmdk-item][aria-selected='true']]:!border-transparent [&_[cmdk-item][aria-selected='true']]:!bg-[var(--surface-hover)] [&_[cmdk-item]_svg]:!scale-100 [&_[cmdk-item]_svg]:!transition-none h-full [clip-path:inset(3px_round_13px)]",
CMDK_ITEM_GAP_CLASS,
CMDK_SECTION_GAP_CLASS
)}
Expand Down Expand Up @@ -482,19 +487,16 @@ export function ConnectionBlockSelector({ id, data }: NodeProps<ConnectionBlockS
<ToolsGroup items={browseTools} onSelect={handleToolSelect} />
</>
)}
</Command.List>
<div className='nodrag nopan absolute inset-x-[3px] top-[3px] z-20 flex h-12 cursor-text items-center gap-2 rounded-t-[13px] bg-[linear-gradient(to_bottom,var(--surface-2)_0%,color-mix(in_srgb,var(--surface-2)_88%,transparent)_68%,transparent_100%)] px-2.5 pb-2'>
<Search className='size-[14px] flex-shrink-0 text-[var(--text-muted)]' />
<Command.Input
ref={inputRef}
autoFocus
aria-label='Search blocks'
value={search}
onValueChange={handleSearchChange}
placeholder='Search blocks...'
className='h-8 min-w-0 flex-1 cursor-text bg-transparent text-[var(--text-body)] text-sm outline-none placeholder:text-[var(--text-muted)] focus:outline-none'
/>
</div>
</CommandFadedList>
<CommandSearch
ref={inputRef}
surface='canvas'
autoFocus
aria-label='Search blocks'
value={search}
onValueChange={handleSearchChange}
placeholder='Search blocks...'
/>
</div>
</Command>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client'

import { useState } from 'react'
import { Chip, Tooltip } from '@sim/emcn'
import { Chip, Tooltip, toast } from '@sim/emcn'
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
import { DeployModal } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal'
import {
useChangeDetection,
Expand Down Expand Up @@ -62,7 +63,7 @@ export function Deploy({ activeWorkflowId, userPermissions, disabled = false }:
(!isDeployed && deployReadiness.isBlocked && !deployReadiness.isSyncing)

const onDeployClick = async () => {
if (disabled || !canDeploy || !activeWorkflowId) return
if (isRegistryLoading || isDisabled || !activeWorkflowId) return

if (isDeploymentSettling) {
setIsModalOpen(true)
Expand All @@ -75,6 +76,21 @@ export function Deploy({ activeWorkflowId, userPermissions, disabled = false }:
}
}

useRegisterGlobalCommands(() => [
{
id: 'deploy-workflow',
handler: () => {
/* The palette can't render a disabled state for this action yet, so a
gated invocation reports the same reason the button's tooltip shows. */
if (isRegistryLoading || isDisabled) {
toast({ message: isRegistryLoading ? 'Workflow is still loading' : getTooltipText() })
return
}
void onDeployClick()
},
},
])

const getTooltipText = () => {
if (isEmpty) {
return 'Cannot deploy an empty workflow'
Expand Down
Loading
Loading