fix(#3562): automated AI fix (#3564)

Co-authored-by: netcatty-bot <308658023+netcatty-bot@users.noreply.github.com>
This commit is contained in:
Netcatty-Botandnetcatty-bot authored and GitHub committed 2026-09-29 19:47:06 +08:00
1 parent 04a63c653a
commit 50ca182e1e
7 files changed
+57

No files matched your search

+13
View File
@@ -53,6 +53,19 @@ test("scripts side panel offers run-on-all-tabs for every snippet, not only auto
assert.match(source, /openPackageDialog/);
});
test("scripts side panel snippet context menu offers copy command without running", () => {
// Copy must sit between the run actions and Edit, write snippet.command to
// the clipboard, and confirm with a toast — it never executes the command.
assert.match(source, /onCopyCommand=\{\(\) => handleCopySnippetCommand\(item\.snippet\)\}/);
assert.match(source, /onCopyCommand=\{\(\) => handleCopySnippetCommand\(item\.row\.snippet\)\}/);
assert.match(source, /scripts\.actions\.copyCommand'/);
const menu = source.match(/\{onRunParallel \? \([\s\S]*?<\/ContextMenu>/);
assert.ok(menu, "snippet row context menu should exist");
assert.match(menu[0], /onCopyCommand[\s\S]*?onClick=\{onEdit\}/);
assert.match(menu[0], /<Copy className="[\s\S]*?\{copyCommandLabel\}/);
assert.match(source, /handleCopySnippetCommand[\s\S]*?snippet\.command[\s\S]*?toast\.success/);
});
test("scripts side panel exposes create actions as inline toolbar icons", () => {
assert.match(source, /snippets\.action\.newSnippet/);
assert.match(source, /snippets\.action\.newPackage/);
+29
View File
@@ -10,6 +10,7 @@
import {
CheckSquare,
ChevronRight,
Copy,
Edit2,
Expand,
FolderPlus,
@@ -54,6 +55,7 @@ import { SnippetCommandTooltipContent } from './snippets/SnippetCommandTooltipCo
import { TERMINAL_SIDE_PANEL_INNER_HEADER_CLASS } from './terminalLayer/terminalSidePanelChrome';
import { isNonPrimaryPointer, primaryOnlyDragHandlers } from './ui/primaryOnlyDrag';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip';
import { toast } from './ui/toast';
const toolbarIconButtonClass =
'h-7 w-7 shrink-0 flex items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-muted/60 transition-colors disabled:opacity-40 disabled:pointer-events-none';
@@ -889,6 +891,20 @@ const ScriptsSidePanelInner: React.FC<ScriptsSidePanelProps> = ({
);
}, []);
const handleCopySnippetCommand = useCallback((snippet: Snippet) => {
if (!snippet.command) return;
navigator.clipboard.writeText(snippet.command).then(
() => {
toast.success(t('scripts.actions.copyCommand.copied'), {
title: snippet.label,
});
},
() => {
toast.error(t('scripts.actions.copyCommand.failed'));
},
);
}, [t]);
if (!isVisible) return null;
const hasAnyContent = snippets.length > 0 || packages.length > 0;
@@ -1129,6 +1145,8 @@ const ScriptsSidePanelInner: React.FC<ScriptsSidePanelProps> = ({
onClick={() => handleSnippetClick(item.snippet)}
onEdit={() => handleEditSnippet(item.snippet)}
onDelete={() => handleDeleteSnippet(item.snippet.id)}
onCopyCommand={() => handleCopySnippetCommand(item.snippet)}
copyCommandLabel={t('scripts.actions.copyCommand')}
onRunParallel={onRunScriptOnWorkspace
? () => onRunScriptOnWorkspace(item.snippet, 'parallel')
: undefined}
@@ -1182,6 +1200,8 @@ const ScriptsSidePanelInner: React.FC<ScriptsSidePanelProps> = ({
onClick={() => handleSnippetClick(item.row.snippet)}
onEdit={() => handleEditSnippet(item.row.snippet)}
onDelete={() => handleDeleteSnippet(item.row.snippet.id)}
onCopyCommand={() => handleCopySnippetCommand(item.row.snippet)}
copyCommandLabel={t('scripts.actions.copyCommand')}
onRunParallel={onRunScriptOnWorkspace
? () => onRunScriptOnWorkspace(item.row.snippet, 'parallel')
: undefined}
@@ -1505,6 +1525,8 @@ interface SnippetRowProps {
onDelete: () => void;
onRunParallel?: () => void;
onRunSequential?: () => void;
onCopyCommand?: () => void;
copyCommandLabel?: string;
runParallelLabel?: string;
runSequentialLabel?: string;
editLabel: string;
@@ -1527,6 +1549,8 @@ const SnippetRow = memo<SnippetRowProps>(({
onDelete,
onRunParallel,
onRunSequential,
onCopyCommand,
copyCommandLabel,
runParallelLabel,
runSequentialLabel,
editLabel,
@@ -1604,6 +1628,11 @@ const SnippetRow = memo<SnippetRowProps>(({
<Layers className="mr-2 h-4 w-4" /> {runSequentialLabel}
</ContextMenuItem>
) : null}
{onCopyCommand ? (
<ContextMenuItem onClick={onCopyCommand}>
<Copy className="mr-2 h-4 w-4" /> {copyCommandLabel}
</ContextMenuItem>
) : null}
<ContextMenuItem onClick={onEdit}>
<Edit2 className="mr-2 h-4 w-4" /> {editLabel}
</ContextMenuItem>