From 07f4b0fa565de1d7daa76229d869bd97e3a517e1 Mon Sep 17 00:00:00 2001 From: Benjamin Christopher Simmonds <44439583+benibenj@users.noreply.github.com> Date: Wed, 18 Mar 2026 18:32:26 +0100 Subject: [PATCH] Standardize run script UI terminology to use 'Task' (#302888) * fix - update action labels to use "Task" terminology instead of "Action" * fix - update terminology from "Action" to "Task" in run script components * fix - update run script widget to handle existing task state and adjust submit label accordingly * fix - update task mode handling in run script components to improve clarity and functionality --- .../contrib/chat/browser/runScriptAction.ts | 36 ++++++------ .../chat/browser/runScriptCustomTaskWidget.ts | 58 +++++++++++++++---- 2 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/vs/sessions/contrib/chat/browser/runScriptAction.ts b/src/vs/sessions/contrib/chat/browser/runScriptAction.ts index 6a3e15911b2..74cf99e76a4 100644 --- a/src/vs/sessions/contrib/chat/browser/runScriptAction.ts +++ b/src/vs/sessions/contrib/chat/browser/runScriptAction.ts @@ -219,7 +219,7 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr constructor() { super({ id: CONFIGURE_DEFAULT_RUN_ACTION_ID, - title: localize2('configureDefaultRunAction', "Add Action..."), + title: localize2('configureDefaultRunAction', "Add Task..."), category: SessionsCategories.Sessions, icon: Codicon.add, precondition: configureScriptPrecondition, @@ -243,7 +243,7 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr constructor() { super({ id: GENERATE_RUN_ACTION_ID, - title: localize2('generateRunAction', "Generate New Action..."), + title: localize2('generateRunAction', "Generate New Task..."), category: SessionsCategories.Sessions, precondition: IsActiveSessionBackgroundProviderContext, menu: [{ @@ -283,7 +283,7 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr items.push({ type: 'separator', label: localize('custom', "Custom") }); items.push({ - label: localize('enterCustomCommand', "Enter Custom Command..."), + label: localize('createNewTask', "Create new Task..."), description: localize('enterCustomCommandDesc', "Create a new shell task"), }); @@ -300,7 +300,7 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr } const picked = await this._quickInputService.pick(items, { - placeHolder: localize('pickRunAction', "Select a task or enter a custom command"), + placeHolder: localize('pickRunAction', "Select or create a task"), }); if (!picked) { @@ -382,12 +382,12 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr const quickWidget = disposables.add(this._quickInputService.createQuickWidget()); quickWidget.title = isConfigureMode - ? localize('configureActionWidgetTitle', "Configure Action...") + ? localize('configureActionWidgetTitle', "Configure Task...") : existingTask - ? localize('addExistingActionWidgetTitle', "Add Existing Action...") - : localize('addActionWidgetTitle', "Add Action..."); + ? localize('addExistingActionWidgetTitle', "Add Existing Task...") + : localize('addActionWidgetTitle', "Add Task..."); quickWidget.description = isConfigureMode - ? localize('configureActionWidgetDescription', "Update how this action is named, saved, and run") + ? localize('configureActionWidgetDescription', "Update how this task is named, saved, and run") : existingTask ? localize('addExistingActionWidgetDescription', "Enable an existing task for sessions and configure when it should run") : localize('addActionWidgetDescription', "Create a shell task and configure how it should be saved and run"); @@ -400,7 +400,7 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr target: existingTask?.target, targetDisabledReason: existingTask && !isConfigureMode ? localize('existingTaskTargetLocked', "This existing task cannot be moved between workspace and user storage.") : workspaceTargetDisabledReason, runOn: existingTask?.task.runOptions?.runOn === 'worktreeCreated' ? 'worktreeCreated' : undefined, - submitLabel: isConfigureMode ? localize('confirmConfigureAction', "Save Changes") : undefined, + mode: isConfigureMode ? 'configure' : existingTask ? 'add-existing' : 'add', })); quickWidget.widget = widget.domNode; @@ -479,7 +479,7 @@ class RunScriptActionViewItem extends BaseActionViewItem { })); // Dropdown with categorized actions and per-item toolbars - const dropdownAction = this._register(new Action('agentSessions.runScriptDropdown', localize('runDropdown', "More Run Actions..."))); + const dropdownAction = this._register(new Action('agentSessions.runScriptDropdown', localize('runDropdown', "More Tasks..."))); this._dropdown = this._register(new ChevronActionWidgetDropdown( dropdownAction, { @@ -633,16 +633,16 @@ class RunScriptActionViewItem extends BaseActionViewItem { }); } - // "Add Action..." action + // "Add Task..." action const canConfigure = !!(session.worktree ?? session.repository); actions.push({ id: 'runScript.addAction', - label: localize('configureDefaultRunAction', "Add Action..."), + label: localize('configureDefaultRunAction', "Add Task..."), tooltip: '', hover: { content: canConfigure - ? localize('addActionTooltip', "Add a new action") - : localize('addActionTooltipDisabled', "Cannot add actions to this session because workspace storage is unavailable"), + ? localize('addActionTooltip', "Add a new task") + : localize('addActionTooltipDisabled', "Cannot add tasks to this session because workspace storage is unavailable"), position: { hoverPosition: HoverPosition.LEFT } }, icon: Codicon.add, @@ -657,13 +657,13 @@ class RunScriptActionViewItem extends BaseActionViewItem { }, }); - // "Generate New Action..." action + // "Generate New Task..." action actions.push({ id: 'runScript.generateAction', - label: localize('generateRunAction', "Generate New Action..."), + label: localize('generateRunAction', "Generate New Task..."), tooltip: '', hover: { - content: localize('generateRunActionTooltip', "Generate a new workspace action"), + content: localize('generateRunActionTooltip', "Generate a new workspace task"), position: { hoverPosition: HoverPosition.LEFT }, }, icon: Codicon.sparkle, @@ -713,7 +713,7 @@ class RunScriptNotAvailableAction extends Action2 { super({ id: 'workbench.action.agentSessions.runScript.notAvailable', title: localize2('run', "Run"), - tooltip: localize('runScriptNotAvailableTooltip', "Run Script is not available for this session type"), + tooltip: localize('runScriptNotAvailableTooltip', "Run Task is not available for this session type"), icon: Codicon.play, precondition: ContextKeyExpr.false(), menu: [{ diff --git a/src/vs/sessions/contrib/chat/browser/runScriptCustomTaskWidget.ts b/src/vs/sessions/contrib/chat/browser/runScriptCustomTaskWidget.ts index d9cec03dc1e..5d40dfdef39 100644 --- a/src/vs/sessions/contrib/chat/browser/runScriptCustomTaskWidget.ts +++ b/src/vs/sessions/contrib/chat/browser/runScriptCustomTaskWidget.ts @@ -28,7 +28,7 @@ export interface IRunScriptCustomTaskWidgetState { readonly target?: TaskStorageTarget; readonly targetDisabledReason?: string; readonly runOn?: typeof WORKTREE_CREATED_RUN_ON; - readonly submitLabel?: string; + readonly mode?: 'add' | 'add-existing' | 'configure'; } export interface IRunScriptCustomTaskWidgetResult { @@ -51,6 +51,12 @@ export class RunScriptCustomTaskWidget extends Disposable { private readonly _labelLocked: boolean; private readonly _commandLocked: boolean; private readonly _targetLocked: boolean; + private readonly _isExistingTask: boolean; + private readonly _isAddExistingTask: boolean; + private readonly _initialLabel: string; + private readonly _initialCommand: string; + private readonly _initialRunOn: boolean; + private readonly _initialTarget: TaskStorageTarget; private _selectedTarget: TaskStorageTarget; private readonly _onDidSubmit = this._register(new Emitter()); @@ -65,7 +71,13 @@ export class RunScriptCustomTaskWidget extends Disposable { this._labelLocked = !!state.labelDisabledReason; this._commandLocked = !!state.commandDisabledReason; this._targetLocked = !!state.targetDisabledReason && state.target !== undefined; + this._isExistingTask = state.mode === 'configure'; + this._isAddExistingTask = state.mode === 'add-existing'; this._selectedTarget = state.target ?? (state.targetDisabledReason ? 'user' : 'workspace'); + this._initialLabel = state.label ?? ''; + this._initialCommand = state.command ?? ''; + this._initialRunOn = state.runOn === WORKTREE_CREATED_RUN_ON; + this._initialTarget = this._selectedTarget; this.domNode = dom.$('.run-script-action-widget'); @@ -73,7 +85,7 @@ export class RunScriptCustomTaskWidget extends Disposable { dom.append(labelSection, dom.$('label.run-script-action-label', undefined, localize('labelFieldLabel', "Name"))); const labelInputContainer = dom.append(labelSection, dom.$('.run-script-action-input')); this._labelInput = this._register(new InputBox(labelInputContainer, undefined, { - placeholder: localize('enterLabelPlaceholder', "Enter a name for this action (optional)"), + placeholder: localize('enterLabelPlaceholder', "Enter a name for this task (optional)"), tooltip: state.labelDisabledReason, ariaLabel: localize('enterLabelAriaLabel', "Task name"), inputBoxStyles: defaultInputBoxStyles, @@ -102,7 +114,7 @@ export class RunScriptCustomTaskWidget extends Disposable { const runOnRow = dom.append(runOnSection, dom.$('.run-script-action-option-row')); this._runOnCheckbox = this._register(new Checkbox(localize('runOnWorktreeCreated', "Run When Worktree Is Created"), state.runOn === WORKTREE_CREATED_RUN_ON, defaultCheckboxStyles)); runOnRow.appendChild(this._runOnCheckbox.domNode); - const runOnText = dom.append(runOnRow, dom.$('span.run-script-action-option-text', undefined, localize('runOnWorktreeCreatedDescription', "Automatically run this action when the session worktree is created"))); + const runOnText = dom.append(runOnRow, dom.$('span.run-script-action-option-text', undefined, localize('runOnWorktreeCreatedDescription', "Automatically run this task when the session worktree is created"))); this._register(dom.addDisposableListener(runOnText, dom.EventType.CLICK, () => this._runOnCheckbox.checked = !this._runOnCheckbox.checked)); const storageSection = dom.append(this.domNode, dom.$('.run-script-action-section')); @@ -113,13 +125,13 @@ export class RunScriptCustomTaskWidget extends Disposable { items: [ { text: localize('workspaceStorageLabel', "Workspace"), - tooltip: storageDisabledReason ?? localize('workspaceStorageTooltip', "Save this action in the current workspace"), + tooltip: storageDisabledReason ?? localize('workspaceStorageTooltip', "Save this task in the current workspace"), isActive: this._selectedTarget === 'workspace', disabled: workspaceTargetDisabled, }, { text: localize('userStorageLabel', "User"), - tooltip: this._targetLocked ? storageDisabledReason : localize('userStorageTooltip', "Save this action in your user tasks and make it available in all sessions"), + tooltip: this._targetLocked ? storageDisabledReason : localize('userStorageTooltip', "Save this task in your user tasks and make it available in all sessions"), isActive: this._selectedTarget === 'user', disabled: this._targetLocked, } @@ -135,13 +147,15 @@ export class RunScriptCustomTaskWidget extends Disposable { this._cancelButton = this._register(new Button(buttonRow, { ...defaultButtonStyles, secondary: true })); this._cancelButton.label = localize('cancelAddAction', "Cancel"); this._submitButton = this._register(new Button(buttonRow, defaultButtonStyles)); - this._submitButton.label = state.submitLabel ?? localize('confirmAddAction', "Add Action"); + this._submitButton.label = this._getSubmitLabel(); - this._register(this._labelInput.onDidChange(() => this._updateButtonEnablement())); - this._register(this._commandInput.onDidChange(() => this._updateButtonEnablement())); + this._register(this._labelInput.onDidChange(() => this._updateButtonState())); + this._register(this._commandInput.onDidChange(() => this._updateButtonState())); this._register(this._storageOptions.onDidSelect(index => { this._selectedTarget = index === 0 ? 'workspace' : 'user'; + this._updateButtonState(); })); + this._register(this._runOnCheckbox.onChange(() => this._updateButtonState())); this._register(this._submitButton.onDidClick(() => this._submit())); this._register(this._cancelButton.onDidClick(() => this._onDidCancel.fire())); this._register(dom.addDisposableListener(this._labelInput.inputElement, dom.EventType.KEY_DOWN, event => { @@ -169,7 +183,7 @@ export class RunScriptCustomTaskWidget extends Disposable { } })); - this._updateButtonEnablement(); + this._updateButtonState(); } focus(): void { @@ -199,7 +213,31 @@ export class RunScriptCustomTaskWidget extends Disposable { }); } - private _updateButtonEnablement(): void { + private _updateButtonState(): void { this._submitButton.enabled = this._commandInput.value.trim().length > 0; + this._submitButton.label = this._getSubmitLabel(); + } + + private _getSubmitLabel(): string { + if (this._isAddExistingTask) { + return localize('confirmAddToSessions', "Add to Sessions Window"); + } + if (!this._isExistingTask) { + return localize('confirmAddTask', "Add Task"); + } + + const targetChanged = this._selectedTarget !== this._initialTarget; + const labelChanged = this._labelInput.value !== this._initialLabel; + const commandChanged = this._commandInput.value !== this._initialCommand; + const runOnChanged = this._runOnCheckbox.checked !== this._initialRunOn; + const otherChanged = labelChanged || commandChanged || runOnChanged; + + if (targetChanged && otherChanged) { + return localize('confirmMoveAndUpdateTask', "Move and Update Task"); + } + if (targetChanged) { + return localize('confirmMoveTask', "Move Task"); + } + return localize('confirmUpdateTask', "Update Task"); } }