Repository: Opentrons/opentrons
Pull request #18045: feature(app): get command text for flex stacker commands
Author: login: TamarZanzouri
Created: 2025-04-11T16:03:21Z | Merged: 2025-04-17T16:47:50Z

# Overview

closes https://opentrons.atlassian.net/browse/EXEC-1135.
add flex stacker commands to command text

## Test Plan and Hands on Testing

upload the following protocol and make sure all commands appear with the correct text:
```
requirements = {"robotType": "Flex", "apiLevel": "2.23"}


def run(protocol):
    stacker_c = protocol.load_module("flexStackerModuleV1", "C4")
    stacker_d = protocol.load_module("flexStackerModuleV1", "D4")
    stacker_c.set_stored_labware(load_name="opentrons_flex_96_tiprack_1000ul", count=5)

    tiprack = stacker_c.retrieve()
    stacker_c.store()
    stacker_c.empty(message="hell")
    stacker_c.fill(message="whatttt")

```

## Changelog

added command text logic for flex stacker commands and added tests.
![Screenshot 2025-04-16 at 1 28 44 PM](https://github.com/user-attachments/assets/7a443f13-20f4-46ed-966b-660e4dad5da9)



## Review requests

changes make sesense? am I missing something?

## Risk assessment

Medium. affects command text rendering, need to smoke test



Diff:
diff --git a/app/src/assets/localization/en/anonymous.json b/app/src/assets/localization/en/anonymous.json
index 56d21c84f726..56cd7252b996 100644
--- a/app/src/assets/localization/en/anonymous.json
+++ b/app/src/assets/localization/en/anonymous.json
@@ -22,6 +22,14 @@
   "estop_pressed_description": "First, safely clear the deck of any labware or spills. Then, twist the E-stop button clockwise. Finally, have the robot move the gantry to its home position.",
   "find_your_robot": "Find your robot in the Devices section of the app to install software updates.",
   "firmware_update_download_logs": "Contact support for assistance.",
+  "flex_stacker_empty": "Manually empty all labware from robot Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from robot {{stackerColumn}}",
+  "flex_stacker_fill": "Fill robot Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_retrieve": "Retrieve from robot Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in robot Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Configure robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_store": "Store into robot Stacker",
   "general_error_message": "If you keep getting this message, try restarting your app and robot. If this does not resolve the issue, contact support.",
   "gripper": "Gripper",
   "gripper_still_attached": "Gripper still attached",
@@ -55,6 +63,7 @@
   "previous_releases": "View previous releases",
   "receive_alert": "Receive an alert when a software update is available.",
   "restore_description": "Reverting to previous software versions is not recommended, but you can access previous releases below. For best results, uninstall the existing app and remove its configuration files before installing the previous version.",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from robot Stacker to {{slotName}}",
   "robot_server_version_ot3_description": "The robot software includes the robot server and the touchscreen display interface.",
   "robot_software_update_required": "A robot software update is required to run protocols with this version of the app.",
   "run_failed_modal_description_desktop": "Contact support for assistance.",
@@ -70,6 +79,7 @@
   "show_labware_offset_snippets_description": "Only for users who need to apply labware offset data outside of the app. When enabled, code snippets for Jupyter Notebook and SSH are available during protocol setup after configuring all required offsets.",
   "something_seems_wrong": "There may be a problem with your pipette. Exit setup and contact support for assistance.",
   "storage_limit_reached_description": "Your robot has reached the limit of quick transfers that it can store. You must delete an existing quick transfer before creating a new one.",
+  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} to robot Stacker",
   "system_language_preferences_update_description": "Your system’s language was recently updated. Would you like to use the updated language as the default for the app?",
   "these_are_advanced_settings": "<block>These are advanced settings. Please do not attempt to adjust without assistance from support. Changing these settings may affect the lifespan of your pipette.</block><block>These settings do not override any pipette settings defined in protocols.</block>",
   "u2e_driver_description": "The OT-2 uses this adapter for its USB connection to the desktop app.",
diff --git a/app/src/assets/localization/en/branded.json b/app/src/assets/localization/en/branded.json
index 66286467be3c..48d6bce2b481 100644
--- a/app/src/assets/localization/en/branded.json
+++ b/app/src/assets/localization/en/branded.json
@@ -22,6 +22,14 @@
   "estop_pressed_description": "First, safely clear the deck of any labware or spills. Then, twist the E-stop button clockwise. Finally, have Flex move the gantry to its home position.",
   "find_your_robot": "Find your robot in the Opentrons App to install software updates.",
   "firmware_update_download_logs": "Download the robot logs from the Opentrons App and send them to support@opentrons.com for assistance.",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex {{stackerColumn}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Configure Flex {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_store": "Store into Flex Stacker",
   "general_error_message": "If you keep getting this message, try restarting your app and robot. If this does not resolve the issue, contact Opentrons Support.",
   "gripper": "Flex Gripper",
   "gripper_still_attached": "Flex Gripper still attached",
@@ -55,6 +63,7 @@
   "previous_releases": "View previous Opentrons releases",
   "receive_alert": "Receive an alert when an Opentrons software update is available.",
   "restore_description": "Opentrons does not recommend reverting to previous software versions, but you can access previous releases below. For best results, uninstall the existing app and remove its configuration files before installing the previous version.",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from Flex Stacker to {{slotName}}",
   "robot_server_version_ot3_description": "The Opentrons Flex software includes the robot server and the touchscreen display interface.",
   "robot_software_update_required": "A robot software update is required to run protocols with this version of the Opentrons App.",
   "run_failed_modal_description_desktop": "Download the run log and send it to support@opentrons.com for assistance.",
@@ -70,6 +79,7 @@
   "show_labware_offset_snippets_description": "Only for users who need to apply labware offset data outside of the Opentrons App. When enabled, code snippets for Jupyter Notebook and SSH are available during protocol setup after configuring all required offsets.",
   "something_seems_wrong": "There may be a problem with your pipette. Exit setup and contact Opentrons Support for assistance.",
   "storage_limit_reached_description": "Your Opentrons Flex has reached the limit of quick transfers that it can store. You must delete an existing quick transfer before creating a new one.",
+  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} to Flex Stacker",
   "system_language_preferences_update_description": "Your system’s language was recently updated. Would you like to use the updated language as the default for the Opentrons App?",
   "these_are_advanced_settings": "<block>These are advanced settings. Please do not attempt to adjust without assistance from Opentrons Support. Changing these settings may affect the lifespan of your pipette.</block><block>These settings do not override any pipette settings defined in protocols.</block>",
   "u2e_driver_description": "The OT-2 uses this adapter for its USB connection to the Opentrons App.",
diff --git a/app/src/assets/localization/en/protocol_command_text.json b/app/src/assets/localization/en/protocol_command_text.json
index 613dfe6e98a7..7f7ba4f103cb 100644
--- a/app/src/assets/localization/en/protocol_command_text.json
+++ b/app/src/assets/localization/en/protocol_command_text.json
@@ -88,6 +88,7 @@
   "single_nozzle_layout": "single nozzle layout",
   "slot": "Slot {{slot_name}}",
   "stacker_display_name": "Stacker {{stacker_slot}}",
+  "stacker_column_display_name": "Stacker in Column {{stacker_slot}}",
   "target_temperature": "target temperature",
   "tc_awaiting_for_duration": "Waiting for Thermocycler profile to complete",
   "tc_run_profile_steps": "Temperature: {{celsius}}°C, hold time: {{duration}}",
@@ -108,5 +109,6 @@
   "waiting_for_tc_lid_to_reach": "Waiting for Thermocycler lid to reach target temperature",
   "waiting_to_reach_temp_module": "Waiting for Temperature Module to reach {{temp}}",
   "waste_chute": "Waste Chute",
-  "with_reference_of": "with reference of {{wavelength}} nm"
+  "with_reference_of": "with reference of {{wavelength}} nm",
+  "with_lid_name": " with {{lidDisplayName}}"
 }
diff --git a/components/src/organisms/CommandText/useCommandTextString/index.ts b/components/src/organisms/CommandText/useCommandTextString/index.ts
index 1cb464b6c720..209791d2efa9 100644
--- a/components/src/organisms/CommandText/useCommandTextString/index.ts
+++ b/components/src/organisms/CommandText/useCommandTextString/index.ts
@@ -53,7 +53,7 @@ export function useCommandTextString(
   params: UseCommandTextStringParams
 ): GetCommandTextResult {
   const { command } = params
-  const { t } = useTranslation('protocol_command_text')
+  const { t } = useTranslation(['protocol_command_text', 'branded'])
 
   const fullParams = { ...params, t }
 
@@ -147,6 +147,18 @@ export function useCommandTextString(
           command,
         }),
       }
+    case 'flexStacker/retrieve':
+    case 'flexStacker/store':
+    case 'flexStacker/setStoredLabware':
+    case 'flexStacker/empty':
+    case 'flexStacker/fill':
+      return {
+        kind: 'generic',
+        commandText: utils.getFlexStackerCommandText({
+          ...fullParams,
+          command,
+        }),
+      }
     case 'thermocycler/runProfile':
       return utils.getTCRunProfileCommandText({ ...fullParams, command })
 
diff --git a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/__tests__/getFlexStackerCommandText.test.tsx b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/__tests__/getFlexStackerCommandText.test.tsx
new file mode 100644
index 000000000000..20f0fcc5aa08
--- /dev/null
+++ b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/__tests__/getFlexStackerCommandText.test.tsx
@@ -0,0 +1,178 @@
+import { screen } from '@testing-library/react'
+import { vi, describe, it, beforeEach } from 'vitest'
+import { useTranslation } from 'react-i18next'
+
+import { renderWithProviders } from '../../../../../../testing/utils'
+import { i18n } from '../../../../../../i18n'
+import {
+  getFlexStackerCommandText,
+  KEYS_BY_COMMAND_TYPE,
+} from '../getFlexStackerCommandText'
+import { getLabwareDefURI } from '@opentrons/shared-data'
+import { getLabwareDisplayLocation } from '../../getLabwareDisplayLocation'
+
+vi.mock('@opentrons/shared-data')
+vi.mock('../../getLabwareDisplayLocation')
+
+const baseCommandData = {
+  allRunDefs: [
+    { metadata: { displayName: 'tip rack' } },
+    { metadata: { displayName: 'plate' } },
+  ],
+  robotType: 'OT-2',
+  commandTextData: {
+    commands: [],
+    labware: [],
+    modules: [],
+    pipettes: [{ id: 'pipette-1', pipetteName: 'p300_single' }],
+  },
+} as any
+
+function TestWrapper({ command }: { command: any }): JSX.Element {
+  const { t } = useTranslation(['protocol_command_text', 'branded'])
+  const text = getFlexStackerCommandText({
+    command,
+    ...baseCommandData,
+    t,
+  })
+
+  return <div>{text}</div>
+}
+
+const render = (command: any) => {
+  return renderWithProviders(<TestWrapper command={command} />, {
+    i18nInstance: i18n,
+  })
+}
+
+describe('getPipettingCommandText', () => {
+  beforeEach(() => {
+    vi.mocked(getLabwareDefURI).mockReturnValue('tiprack-uri')
+    vi.mocked(getLabwareDisplayLocation).mockReturnValue('Slot 1')
+  })
+
+  it('should render retrieve command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/retrieve',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+      },
+    }
+
+    render(command)
+    screen.getByText('retrieve_labware_from_stacker_to')
+  })
+
+  it('should render store command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/store',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+
+    render(command)
+    screen.getByText('store_labware_from_slot_to_stacker')
+  })
+
+  it('should render setStoredLabware command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/setStoredLabware',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryLabwareDefinition: {
+          metadata: {
+            displayName: 'dummy def',
+          },
+        },
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+
+    render(command)
+    screen.getByText(
+      'flex_stacker_set_stored_labware_with_quantity_and_location'
+    )
+  })
+
+  it('should render fill command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/fill',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryLabwareDefinition: {
+          metadata: {
+            displayName: 'dummy def',
+          },
+        },
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+
+    render(command)
+    screen.getByText('flex_stacker_fill_with_quantity_and_labware')
+  })
+
+  it('should render empty command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/empty',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryLabwareDefinition: {
+          metadata: {
+            displayName: 'dummy def',
+          },
+        },
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+    render(command)
+    screen.getByText('flex_stacker_empty_from_location')
+  })
+})
+
+describe.each(Object.entries(KEYS_BY_COMMAND_TYPE))(
+  'Default fallback for %s',
+  (commandType, expectedKey) => {
+    it(`should render default text for ${commandType} when result is missing`, () => {
+      const command = {
+        id: 'cmd-1',
+        commandType: commandType,
+        params: {
+          moduleId: 'module-id',
+        },
+      }
+      render(command)
+      screen.getByText(expectedKey)
+    })
+  }
+)
diff --git a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
index 85218c8d6639..a4bc9e5770e2 100644
--- a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
+++ b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
@@ -5,8 +5,12 @@ import type {
   FlexStackerFillRunTimeCommand,
   FlexStackerEmptyRunTimeCommand,
   RunTimeCommand,
+  LabwareDefinition3,
+  LabwareDefinition2,
 } from '@opentrons/shared-data'
+import { getLabwareDefURI } from '@opentrons/shared-data'
 import type { HandlesCommands } from '../types'
+import { getLabwareDisplayLocation } from '../../utils/getLabwareDisplayLocation'
 
 export type FlexStackerCommand =
   | FlexStackerSetStoredLabwareRunTimeCommand
@@ -15,18 +19,148 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getLabwareDisplayName = (labwareUri: string, allRunDefs: any): string => {
+  const currentLabwareDef = allRunDefs.find(
+    (def: LabwareDefinition2 | LabwareDefinition3) =>
+      getLabwareDefURI(def) === labwareUri
+  )
+  return currentLabwareDef?.metadata.displayName ?? null
+}
+
 export const getFlexStackerCommandText = ({
   command,
+  allRunDefs,
+  commandTextData,
   t,
+  robotType,
 }: // stackerCommand,
 GetFlexStackerCommandText): string => {
-  return ''
+  const primaryDefinitionDisplayName =
+    command.result !== undefined && 'primaryLabwareURI' in command?.result
+      ? getLabwareDisplayName(
+          command?.result.primaryLabwareURI,
+          allRunDefs ?? []
+        )
+      : null
+  if (command.commandType === 'flexStacker/retrieve') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryLocationSequence,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:retrieve_labware_from_stacker_to', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/store') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryOriginLocationSequence ?? null,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:store_labware_from_slot_to_stacker', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/setStoredLabware') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId },
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (
+      command.result !== undefined &&
+      'primaryLabwareDefinition' in command.result &&
+      slotName != null
+    ) {
+      return (
+        t(
+          'branded:flex_stacker_set_stored_labware_with_quantity_and_location',
+          {
+            quantity: command.params.initialCount,
+            stackerColumn: slotName,
+            labwareAndLidDisplayNames:
+              command.result?.primaryLabwareDefinition.metadata.displayName,
+          }
+        ) +
+        (command.result?.lidLabwareDefinition != null
+          ? t('with_lid_name', {
+              lidDisplayName:
+                command.result?.lidLabwareDefinition.metadata.displayName,
+            })
+          : '')
+      )
+    }
+  } else if (command.commandType === 'flexStacker/fill') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId },
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null) {
+      return (
+        t('branded:flex_stacker_fill_with_quantity_and_labware', {
+          quantity: command.params.count,
+          stackerColumn: slotName,
+          labwareAndLidDisplayNames: primaryDefinitionDisplayName,
+        }) +
+        (command.result?.lidLabwareURI != null
+          ? t('with_lid_name', {
+              lidDisplayName: getLabwareDisplayName(
+                command.result?.lidLabwareURI,
+                allRunDefs ?? []
+              ),
+            })
+          : '')
+      )
+    }
+  } else if (command.commandType === 'flexStacker/empty') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId },
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:flex_stacker_empty_from_location', {
+        stackerColumn: slotName,
+      })
+    }
+  }
+  return t('branded:' + KEYS_BY_COMMAND_TYPE[command.commandType])
 }
diff --git a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/index.ts b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/index.ts
index c2926c880c62..3cb549e7086d 100644
--- a/components/src/organisms/CommandText/useCommandTextString/utils/commandText/index.ts
+++ b/components/src/organisms/CommandText/useCommandTextString/utils/commandText/index.ts
@@ -24,3 +24,4 @@ export * from './getPipettingCommandText'
 export * from './getLiquidProbeCommandText'
 export * from './getRailLightsCommandText'
 export * from './getAbsorbanceReaderCommandText'
+export * from './getFlexStackerCommandText'
diff --git a/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx b/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx
index 842536133d92..5bdf52a2ebd7 100644
--- a/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx
+++ b/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx
@@ -88,28 +88,30 @@ export function getLabwareDisplayLocation(
         case THERMOCYCLER_MODULE_V2:
           return t('slot', { slot_name: 'A1+B1' })
         case FLEX_STACKER_MODULE_V1:
-          if (slotName === 'D3') {
-            return t('stacker_display_name', { stacker_slot: 'A' })
-          } else if (slotName === 'C3') {
-            return t('stacker_display_name', { stacker_slot: 'B' })
-          } else if (slotName === 'B3') {
-            return t('stacker_display_name', { stacker_slot: 'C' })
-          } else return t('stacker_display_name', { stacker_slot: 'D' })
-
+          return t('stacker_display_name', {
+            stacker_slot: getSlotColumn(slotName),
+          })
         default:
           return t('slot', { slot_name: slotName })
       }
     } else {
-      return isOnDevice
-        ? `${getModuleDisplayName(moduleModel)}, ${slotName}`
-        : t('module_in_slot', {
-            count: getOccludedSlotCountForModule(
-              getModuleType(moduleModel),
-              params.robotType
-            ),
-            module: getModuleDisplayName(moduleModel),
-            slot_name: slotName,
+      switch (moduleModel) {
+        case FLEX_STACKER_MODULE_V1:
+          return t('stacker_column_display_name', {
+            stacker_slot: getSlotColumn(slotName),
           })
+        default:
+          return isOnDevice
+            ? `${getModuleDisplayName(moduleModel)}, ${slotName}`
+            : t('module_in_slot', {
+                count: getOccludedSlotCountForModule(
+                  getModuleType(moduleModel),
+                  params.robotType
+                ),
+                module: getModuleDisplayName(moduleModel),
+                slot_name: slotName,
+              })
+      }
     }
   }
   // Adapter locations
@@ -135,6 +137,10 @@ export function getLabwareDisplayLocation(
   }
 }
 
+function getSlotColumn(slotName: string): string {
+  return slotName.charAt(0)
+}
+
 // Sometimes we don't want to show the actual slotName, so we special case the text here.
 function handleSpecialSlotNames(
   slotName: string,
diff --git a/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareLocation.tsx b/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareLocation.tsx
index 8d2356a1767c..d870e454ed29 100644
--- a/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareLocation.tsx
+++ b/components/src/organisms/CommandText/useCommandTextString/utils/getLabwareLocation.tsx
@@ -6,6 +6,7 @@ import {
   getModuleModelFromAddressableArea,
   MOVABLE_TRASH_ADDRESSABLE_AREAS,
   WASTE_CHUTE_ADDRESSABLE_AREAS,
+  FLEX_STACKER_MODULE_V1,
 } from '@opentrons/shared-data'
 import { getModuleDisplayLocation } from './getModuleDisplayLocation'
 import { getModuleModel } from './getModuleModel'
@@ -72,7 +73,6 @@ export function getLabwareLocationFromSequence(
     locationSequence,
     detailLevel = 'full',
   } = params
-
   return locationSequence.reduce<LocationResult>(
     (acc, sequenceItem, index) => {
       if (sequenceItem.kind === 'notOnDeck') {
@@ -111,7 +111,10 @@ export function getLabwareLocationFromSequence(
         return {
           ...acc,
           slotName,
-          moduleModel: moduleModel ?? undefined,
+          moduleModel:
+            moduleModel === FLEX_STACKER_MODULE_V1
+              ? undefined
+              : moduleModel ?? undefined,
         }
       } else if (sequenceItem.kind === 'onModule') {
         const moduleModel = getModuleModel(loadedModules, sequenceItem.moduleId)
@@ -120,10 +123,15 @@ export function getLabwareLocationFromSequence(
         } else {
           return {
             ...acc,
-            moduleModel,
+            moduleModel:
+              moduleModel === FLEX_STACKER_MODULE_V1
+                ? undefined
+                : moduleModel ?? undefined,
           }
         }
-      } else if (detailLevel === 'full') {
+      }
+      // TODO(tz, 4-16-25): add inHooperLocation when logic is merged
+      else if (detailLevel === 'full') {
         const { allRunDefs } = params as SequenceFullParams
         if (sequenceItem.kind === 'onLabware' && acc.adapterName == null) {
           if (!Array.isArray(loadedLabwares)) {
diff --git a/shared-data/command/types/module.ts b/shared-data/command/types/module.ts
index 7afb01a0e325..5a15a0c795f3 100644
--- a/shared-data/command/types/module.ts
+++ b/shared-data/command/types/module.ts
@@ -528,6 +528,7 @@ export interface FlexStackerFillRunTimeCommand
     CommonCommandRunTimeInfo {
   result?: {
     count: number
+    lidLabwareURI?: string
   }
 }
 


Reviews:
user: login: mjhuff
body: Lookin good. A couple clean up comments.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T16:59:37Z
user: login: mjhuff
body: lgtm with passing CI!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T18:04:22Z
user: login: ecormany
body: Just nitpicking some prepositions. Can you tell I used to teach freshman composition? 😇 
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T18:49:38Z
user: login: smb2268
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T15:01:20Z
user: login: smb2268
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T15:06:41Z
user: login: smb2268
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T15:18:57Z
user: login: smb2268
body: This looks good so far, but there's a little more work to do to get these strings and display locations in line with the product requirements - see above comments!
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T15:20:44Z
user: login: TamarZanzouri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T01:19:21Z
user: login: smb2268
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T14:51:30Z
user: login: smb2268
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T14:52:48Z
user: login: TamarZanzouri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T15:27:48Z
user: login: TamarZanzouri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T15:51:01Z
user: login: TamarZanzouri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T15:54:13Z
user: login: mjhuff
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T15:10:18Z
user: login: TamarZanzouri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T15:24:18Z
user: login: smb2268
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T17:36:18Z
user: login: TamarZanzouri
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T17:48:44Z
user: login: smb2268
body: A few last changes needed but looking great overall!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T18:00:59Z
user: login: smb2268
body: thanks for making those updates! looks great 🤩
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T18:24:30Z

Review comments:
diff_hunk: @@ -0,0 +1,177 @@
+import { screen } from '@testing-library/react'
+import { vi, describe, it, beforeEach } from 'vitest'
+import { useTranslation } from 'react-i18next'
+
+import { renderWithProviders } from '../../../../../../testing/utils'
+import { i18n } from '../../../../../../i18n'
+import { getFlexStackerCommandText } from '../getFlexStackerCommandText'
+import { getAllLabwareDefs } from '@opentrons/shared-data'
+import { getLabwareDisplayLocation } from '../../getLabwareDisplayLocation'
+
+vi.mock('@opentrons/shared-data')
+vi.mock('../../getLabwareDisplayLocation')
+
+const baseCommandData = {
+  allRunDefs: {},
+  robotType: 'OT-2',
+  commandTextData: {
+    commands: [],
+    labware: [],
+    modules: [],
+    pipettes: [{ id: 'pipette-1', pipetteName: 'p300_single' }],
+  },
+} as any
+
+function TestWrapper({ command }: { command: any }): JSX.Element {
+  const { t } = useTranslation('protocol_command_text')
+  const text = getFlexStackerCommandText({
+    command,
+    ...baseCommandData,
+    t,
+  })
+
+  return <div>{text}</div>
+}
+
+const render = (command: any) => {
+  return renderWithProviders(<TestWrapper command={command} />, {
+    i18nInstance: i18n,
+  })
+}
+
+describe('getPipettingCommandText', () => {
+  beforeEach(() => {
+    vi.mocked(getAllLabwareDefs).mockReturnValue({
+      'tiprack-uri': { metadata: { displayName: 'tip rack' } },
+      'plate-uri': { metadata: { displayName: 'plate' } },
+    } as any)
+    vi.mocked(getLabwareDisplayLocation).mockReturnValue('Slot 1')
+  })
+
+  it('should render retrieve command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/retrieve',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+      },
+    }
+
+    render(command)
+    screen.getByText('retrieve_labware_from_stacker_to')
+  })
+
+  it('should render store command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/store',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+
+    render(command)
+    screen.getByText('store_labware_from_slot_to_stacker')
+  })
+
+  it('should render setStoredLabware command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/setStoredLabware',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryLabwareDefinition: {
+          metadata: {
+            displayName: 'dummy def',
+          },
+        },
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+
+    render(command)
+    screen.getByText(
+      'flex_stacker_set_stored_labware_with_quantity_and_location'
+    )
+  })
+
+  it('should render fill command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/fill',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryLabwareDefinition: {
+          metadata: {
+            displayName: 'dummy def',
+          },
+        },
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+
+    render(command)
+    screen.getByText('flex_stacker_fill_with_quantity_and_labware')
+  })
+
+  it('should render empty command text correctly', () => {
+    const command = {
+      id: 'cmd-1',
+      commandType: 'flexStacker/empty',
+      params: {
+        moduleId: 'module-id',
+      },
+      result: {
+        primaryLabwareURI: 'tiprack-uri',
+        primaryLabwareDefinition: {
+          metadata: {
+            displayName: 'dummy def',
+          },
+        },
+        primaryOriginLocationSequence: [
+          { kind: 'onAddressableArea', addressableAreaName: 'A1' },
+        ],
+      },
+    }
+  })
+
+  it('should render defualt command text correctly', () => {
+    const COMMAND_TYPE_TRANSLATIONS = {
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/__tests__/getFlexStackerCommandText.test.tsx
user: login: mjhuff
body: Nit, I'd import the constant you have in the actual file, KEYS_BY_COMMAND_TYPE.
created_at: 2025-04-11T16:52:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,122 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
 export const getFlexStackerCommandText = ({
   command,
+  allRunDefs,
+  commandTextData,
   t,
+  robotType,
 }: // stackerCommand,
 GetFlexStackerCommandText): string => {
-  return ''
+  let primaryDefinitionDisplayName = null
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: mjhuff
body: I'd prefer if we'd move away from using `let` in general. These mutable variable assignments are harder to read and prone to bugs. A helper function would be good for this, either within the lexical scope of `getFlexStackerCommandText` or outside of it.
created_at: 2025-04-11T16:58:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,16 +34,24 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware out of Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware out of Stacker in {{slotName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: ecormany
body: "from" is more natural? and we appear to be using "Flex Stacker" everywhere in these.
```suggestion
  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
```
created_at: 2025-04-11T18:46:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -88,6 +97,7 @@
   "single_nozzle_layout": "single nozzle layout",
   "slot": "Slot {{slot_name}}",
   "stacker_display_name": "Stacker {{stacker_slot}}",
+  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} to Flex Stacker",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: ecormany
body: more natural, matches `flex_stacker_store`
```suggestion
  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} into Flex Stacker",
```
created_at: 2025-04-11T18:49:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,131 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getPrimaryLabwareUriIfExsists = (
+  command: FlexStackerCommand
+): string | null => {
+  if (command.result !== undefined && 'primaryLabwareURI' in command?.result) {
+    const currentLabwareDef = getAllLabwareDefs()[
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: This should be refactored to grab the definitions from `getLabwareDefinitionsByURIForProtocol` which I added because we aren't able to get definitions for custom labware in this way. You'll might need to grab this definition map at the top level of command text and drill it down here!
created_at: 2025-04-14T15:01:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: These strings don't match the ones Nick and I came up with that are listed in the ticket. Can you update them to ensure they're all written properly? I also don't think we should need a version with + without all of these variables. Only `setStoredLabware` and `fill` should have optional fields. 
created_at: 2025-04-14T15:06:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,131 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getPrimaryLabwareUriIfExsists = (
+  command: FlexStackerCommand
+): string | null => {
+  if (command.result !== undefined && 'primaryLabwareURI' in command?.result) {
+    const currentLabwareDef = getAllLabwareDefs()[
+      command.result?.primaryLabwareURI
+    ]
+    return currentLabwareDef?.metadata.displayName ?? null
+  }
+  return null
+}
+
 export const getFlexStackerCommandText = ({
   command,
+  allRunDefs,
+  commandTextData,
   t,
+  robotType,
 }: // stackerCommand,
 GetFlexStackerCommandText): string => {
-  return ''
+  const primaryDefinitionDisplayName = getPrimaryLabwareUriIfExsists(command)
+  if (command.commandType === 'flexStacker/retrieve') {
+    const slotName = getLabwareDisplayLocation({
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: We'll need to adjust this `getLabwareDisplayLocation` function for stacker. If we're trying to get the location of the stacker itself, we want to represent that as "Column A". For labware in the hopper it would be "Flex Stacker in Column A" and for the location shuttle location, we'll say "A4".
created_at: 2025-04-14T15:18:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: TamarZanzouri
body: these are the strings from the ticket, I just made sure + default in case there is no command found
created_at: 2025-04-15T01:19:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,131 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getPrimaryLabwareUriIfExsists = (
+  command: FlexStackerCommand
+): string | null => {
+  if (command.result !== undefined && 'primaryLabwareURI' in command?.result) {
+    const currentLabwareDef = getAllLabwareDefs()[
+      command.result?.primaryLabwareURI
+    ]
+    return currentLabwareDef?.metadata.displayName ?? null
+  }
+  return null
+}
+
 export const getFlexStackerCommandText = ({
   command,
+  allRunDefs,
+  commandTextData,
   t,
+  robotType,
 }: // stackerCommand,
 GetFlexStackerCommandText): string => {
-  return ''
+  const primaryDefinitionDisplayName = getPrimaryLabwareUriIfExsists(command)
+  if (command.commandType === 'flexStacker/retrieve') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId as string },
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('retrieve_labware_from_stacker_to', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/store') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryOriginLocationSequence ?? null,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('store_labware_from_slot_to_stacker', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/setStoredLabware') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId },
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (
+      command.result !== undefined &&
+      'primaryLabwareDefinition' in command?.result &&
+      slotName != null
+    ) {
+      return (
+        t('flex_stacker_set_stored_labware_with_quantity_and_location', {
+          quantity: command.params.initialCount,
+          slotName,
+          primaryDefinitionDisplayName:
+            command.result?.primaryLabwareDefinition.metadata.displayName,
+        }) +
+        (command.result?.lidLabwareDefinition != null
+          ? t('with_lid_name', {
+              lidDisplayName:
+                command.result?.lidLabwareDefinition.metadata.displayName,
+            })
+          : '')
+      )
+    }
+  } else if (command.commandType === 'flexStacker/fill') {
+    if (primaryDefinitionDisplayName != null) {
+      return (
+        t('flex_stacker_fill_with_quantity_and_labware', {
+          quantity: command.params.count,
+          primaryDefinitionDisplayName,
+        }) +
+        (command.result?.lidLabwareURI != null
+          ? t('with_lid_name', {
+              lidDisplayName: command.result?.lidLabwareURI,
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: We'll need to get the lid display name from the definition here!
created_at: 2025-04-15T01:35:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: Let's name this variable `stackerLocation` or `stackerColumn` so it's clear this shouldn't be the slot name that the stacker is loaded into
created_at: 2025-04-15T01:37:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: Let's rename this one to something like `labwareAndLidDisplayNames` for the same reason!
created_at: 2025-04-15T01:38:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -74,6 +82,7 @@
   "prepare_to_aspirate": "Preparing {{pipette}} to aspirate",
   "pressurizing_to_dispense": "Pressurize pipette to dispense {{volume}} µL from resin tip at {{flow_rate}} µL/sec",
   "reloading_labware": "Reloading {{labware}}",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from {{slotName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: This should have two locations -- `from Flex Stacker in {{stackerColumn}} to {{slotName}}`
created_at: 2025-04-15T01:44:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Set stored labware at {{slotName}} with {{quantity}} {{primaryDefinitionDisplayName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: This one should be "Configure Flex Stacker in {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}"
created_at: 2025-04-15T01:46:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: Also realized this one is missing a location in the ticket but should have one -- let's say "Fill Flex Stacker in {{stackerColumn}} with {{labwareAndLidDisplayNames}}"
created_at: 2025-04-15T01:49:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: There's a few small differences! Added a few more comments. Is it possible for there to be no command found here?
created_at: 2025-04-15T14:52:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: TamarZanzouri
body: @smb2268 probably not.. I just followed the other module commands. if there are small diffs that might be bc Ed gave me feedback?
created_at: 2025-04-15T15:27:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +34,14 @@
   "dropping_tip_in_trash": "Dropping tip in {{trash}}",
   "engaging_magnetic_module": "Engaging Magnetic Module",
   "fixed_trash": "Fixed Trash",
+  "flex_stacker_empty": "Manually empty all labware from Flex Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Flex Stacker in {{slotName}}",
+  "flex_stacker_fill": "Fill Flex Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Flex Stacker with {{quantity}} {{primaryDefinitionDisplayName}}",
+  "flex_stacker_retrieve": "Retrieve from Flex Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Flex Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Set stored labware at {{slotName}} with {{quantity}} {{primaryDefinitionDisplayName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: TamarZanzouri
body: I changed this bc we do not have a configure command but I can change the text back
created_at: 2025-04-15T15:51:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -74,6 +82,7 @@
   "prepare_to_aspirate": "Preparing {{pipette}} to aspirate",
   "pressurizing_to_dispense": "Pressurize pipette to dispense {{volume}} µL from resin tip at {{flow_rate}} µL/sec",
   "reloading_labware": "Reloading {{labware}}",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from {{slotName}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: TamarZanzouri
body: There is no "to" when retrieving. it stays on the shuttle
created_at: 2025-04-15T15:54:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -81,5 +81,15 @@
   "view_latest_release_notes_at": "Please contact support for release notes.",
   "want_to_help_out": "Want to help out?",
   "welcome_title": "Welcome!",
-  "why_use_lpc": "Labware Position Check is intended to correct for minor variances. Don't use Labware Position Check to compensate for large positional adjustments. Needing to set large labware offsets could indicate a problem with robot calibration."
+  "why_use_lpc": "Labware Position Check is intended to correct for minor variances. Don't use Labware Position Check to compensate for large positional adjustments. Needing to set large labware offsets could indicate a problem with robot calibration.",
+  "flex_stacker_empty": "Manually empty all labware from Robot Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Robot {{stackerColumn}}",
+  "flex_stacker_fill": "Fill Robot Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_retrieve": "Retrieve from Robot Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Robot Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Configure Robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_store": "Store into Robot Stacker",
+  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} to Robot Stacker",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from Robot Stacker to {{slotName}}"
path: app/src/assets/localization/en/anonymous.json
user: login: mjhuff
body: Is it intentional to treat "Robot Stacker" as a proper noun?
created_at: 2025-04-16T15:10:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,152 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
+// inStackerHopperLocation -> colum location
+// onModule -> slot name (C4)
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getLabwareDisplayName = (labwareUri: string): string => {
+  const currentLabwareDef = getAllLabwareDefs()[labwareUri]
+  return currentLabwareDef?.metadata.displayName ?? null
+}
+
 export const getFlexStackerCommandText = ({
   command,
+  allRunDefs,
+  commandTextData,
   t,
+  robotType,
 }: // stackerCommand,
 GetFlexStackerCommandText): string => {
-  return ''
+  const primaryDefinitionDisplayName =
+    command.result !== undefined && 'primaryLabwareURI' in command?.result
+      ? getLabwareDisplayName(command?.result.primaryLabwareURI)
+      : null
+  if (command.commandType === 'flexStacker/retrieve') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryLocationSequence,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:retrieve_labware_from_stacker_to', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/store') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryOriginLocationSequence ?? null,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:store_labware_from_slot_to_stacker', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/setStoredLabware') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId },
+      robotType,
+      detailLevel: 'slot-only',
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (
+      command.result !== undefined &&
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: ```suggestion
      command.result != undefined &&
      'primaryLabwareDefinition' in command.result &&
      slotName != null
```
created_at: 2025-04-16T15:16:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,152 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: We'll need to add branded to all of these if they're going to be used also!
```suggestion
  'flexStacker/retrieve': 'branded:flex_stacker_retrieve',
```
created_at: 2025-04-16T15:16:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,152 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
+// inStackerHopperLocation -> colum location
+// onModule -> slot name (C4)
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: Leftover comment 😄
created_at: 2025-04-16T15:17:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,6 +48,7 @@ export function getLabwareDisplayLocation(
   params: DisplayLocationParams
 ): string {
   const { t, isOnDevice = false, location } = params
+  console.log('location: ', location)
path: components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx
user: login: smb2268
body: Leftover log
created_at: 2025-04-16T15:17:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -60,6 +61,7 @@ export function getLabwareDisplayLocation(
   if (locationResult == null) {
     return ''
   }
+  console.log('locationResult: ', locationResult)
path: components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx
user: login: smb2268
body: Here also!
created_at: 2025-04-16T15:18:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -63,6 +63,7 @@ export type GetLabwareLocationFromSequenceParams =
   | SequenceSlotOnlyParams
   | SequenceFullParams
 
+// we need to add a inStackerHopperLocation kind and return a column only
path: components/src/organisms/CommandText/useCommandTextString/utils/getLabwareLocation.tsx
user: login: smb2268
body: A few more leftover logs in this file
created_at: 2025-04-16T15:20:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -81,5 +81,15 @@
   "view_latest_release_notes_at": "Please contact support for release notes.",
   "want_to_help_out": "Want to help out?",
   "welcome_title": "Welcome!",
-  "why_use_lpc": "Labware Position Check is intended to correct for minor variances. Don't use Labware Position Check to compensate for large positional adjustments. Needing to set large labware offsets could indicate a problem with robot calibration."
+  "why_use_lpc": "Labware Position Check is intended to correct for minor variances. Don't use Labware Position Check to compensate for large positional adjustments. Needing to set large labware offsets could indicate a problem with robot calibration.",
+  "flex_stacker_empty": "Manually empty all labware from Robot Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Robot {{stackerColumn}}",
+  "flex_stacker_fill": "Fill Robot Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_retrieve": "Retrieve from Robot Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Robot Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Configure Robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_store": "Store into Robot Stacker",
+  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} to Robot Stacker",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from Robot Stacker to {{slotName}}"
path: app/src/assets/localization/en/anonymous.json
user: login: TamarZanzouri
body: Nick asked to switch Flex Stacker with Robot Stacker :-) let me know what you think it should be instead 
created_at: 2025-04-16T15:24:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -81,5 +81,15 @@
   "view_latest_release_notes_at": "Please contact support for release notes.",
   "want_to_help_out": "Want to help out?",
   "welcome_title": "Welcome!",
-  "why_use_lpc": "Labware Position Check is intended to correct for minor variances. Don't use Labware Position Check to compensate for large positional adjustments. Needing to set large labware offsets could indicate a problem with robot calibration."
+  "why_use_lpc": "Labware Position Check is intended to correct for minor variances. Don't use Labware Position Check to compensate for large positional adjustments. Needing to set large labware offsets could indicate a problem with robot calibration.",
+  "flex_stacker_empty": "Manually empty all labware from Robot Stacker",
+  "flex_stacker_empty_from_location": "Manually empty all labware from Robot {{stackerColumn}}",
+  "flex_stacker_fill": "Fill Robot Stacker",
+  "flex_stacker_fill_with_quantity_and_labware": "Fill Robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_retrieve": "Retrieve from Robot Stacker",
+  "flex_stacker_set_stored_labware": "Set stored labware in Robot Stacker",
+  "flex_stacker_set_stored_labware_with_quantity_and_location": "Configure Robot {{stackerColumn}} with {{quantity}} {{labwareAndLidDisplayNames}}",
+  "flex_stacker_store": "Store into Robot Stacker",
+  "store_labware_from_slot_to_stacker": "Store {{primaryDefinitionDisplayName}} from {{slotName}} to Robot Stacker",
+  "retrieve_labware_from_stacker_to": "Retrieve {{primaryDefinitionDisplayName}} from Robot Stacker to {{slotName}}"
path: app/src/assets/localization/en/anonymous.json
user: login: smb2268
body: I think that's right but we shouldn't capitalize "robot"!
created_at: 2025-04-16T17:35:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +17,152 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: TamarZanzouri
body: added branded when rendering the string
created_at: 2025-04-16T17:48:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -88,6 +88,7 @@
   "single_nozzle_layout": "single nozzle layout",
   "slot": "Slot {{slot_name}}",
   "stacker_display_name": "Stacker {{stacker_slot}}",
+  "stacker_column_display_name": "Stacker In Column {{stacker_slot}}",
path: app/src/assets/localization/en/protocol_command_text.json
user: login: smb2268
body: nit, but we shouldn't capitalize "In" here
created_at: 2025-04-16T17:52:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +19,151 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getLabwareDisplayName = (labwareUri: string, allRunDefs: any): string => {
+  const currentLabwareDef = allRunDefs.find(
+    (def: LabwareDefinition2 | LabwareDefinition3) =>
+      getLabwareDefURI(def) === labwareUri
+  )
+  // const currentLabwareDef = getAllLabwareDefs()[labwareUri]
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: leftover comment here
created_at: 2025-04-16T17:53:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,18 +19,151 @@ export type FlexStackerCommand =
   | FlexStackerFillRunTimeCommand
   | FlexStackerEmptyRunTimeCommand
 
+export const KEYS_BY_COMMAND_TYPE: {
+  [commandType in FlexStackerCommand['commandType']]: string
+} = {
+  'flexStacker/retrieve': 'flex_stacker_retrieve',
+  'flexStacker/store': 'flex_stacker_store',
+  'flexStacker/setStoredLabware': 'flex_stacker_set_stored_labware',
+  'flexStacker/empty': 'flex_stacker_empty',
+  'flexStacker/fill': 'flex_stacker_fill',
+}
+
 type HandledCommands = Extract<
   RunTimeCommand,
-  { commandType: FlexStackerCommand }
+  { commandType: keyof typeof KEYS_BY_COMMAND_TYPE }
 >
 
 type GetFlexStackerCommandText = HandlesCommands<HandledCommands>
 
-// hold until Casey's work is implemented?
+const getLabwareDisplayName = (labwareUri: string, allRunDefs: any): string => {
+  const currentLabwareDef = allRunDefs.find(
+    (def: LabwareDefinition2 | LabwareDefinition3) =>
+      getLabwareDefURI(def) === labwareUri
+  )
+  // const currentLabwareDef = getAllLabwareDefs()[labwareUri]
+  return currentLabwareDef?.metadata.displayName ?? null
+}
+
 export const getFlexStackerCommandText = ({
   command,
+  allRunDefs,
+  commandTextData,
   t,
+  robotType,
 }: // stackerCommand,
 GetFlexStackerCommandText): string => {
-  return ''
+  const primaryDefinitionDisplayName =
+    command.result !== undefined && 'primaryLabwareURI' in command?.result
+      ? getLabwareDisplayName(
+          command?.result.primaryLabwareURI,
+          allRunDefs ?? []
+        )
+      : null
+  if (command.commandType === 'flexStacker/retrieve') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryLocationSequence,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:retrieve_labware_from_stacker_to', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/store') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: command.result?.primaryOriginLocationSequence ?? null,
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (primaryDefinitionDisplayName != null && slotName != null) {
+      return t('branded:store_labware_from_slot_to_stacker', {
+        primaryDefinitionDisplayName,
+        slotName,
+      })
+    }
+  } else if (command.commandType === 'flexStacker/setStoredLabware') {
+    const slotName = getLabwareDisplayLocation({
+      loadedLabwares: commandTextData?.labware ?? [],
+      location: { moduleId: command.params?.moduleId },
+      robotType,
+      allRunDefs,
+      loadedModules: commandTextData?.modules ?? [],
+      t,
+    })
+    if (
+      command.result != undefined &&
+      'primaryLabwareDefinition' in command.result &&
+      slotName != null
+      'primaryLabwareDefinition' in command?.result &&
path: components/src/organisms/CommandText/useCommandTextString/utils/commandText/getFlexStackerCommandText.ts
user: login: smb2268
body: Looks like the conditional got mixed up here, I think lines 106 + 107 should be removed
created_at: 2025-04-16T17:55:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +73,7 @@ export function getLabwareLocationFromSequence(
     locationSequence,
     detailLevel = 'full',
   } = params
-
+  console.log('locationSequence: ', locationSequence)
path: components/src/organisms/CommandText/useCommandTextString/utils/getLabwareLocation.tsx
user: login: smb2268
body: leftover log statement here
created_at: 2025-04-16T17:56:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -100,16 +100,27 @@ export function getLabwareDisplayLocation(
           return t('slot', { slot_name: slotName })
       }
     } else {
-      return isOnDevice
-        ? `${getModuleDisplayName(moduleModel)}, ${slotName}`
-        : t('module_in_slot', {
-            count: getOccludedSlotCountForModule(
-              getModuleType(moduleModel),
-              params.robotType
-            ),
-            module: getModuleDisplayName(moduleModel),
-            slot_name: slotName,
-          })
+      switch (moduleModel) {
+        case FLEX_STACKER_MODULE_V1:
+          if (slotName === 'D3') {
path: components/src/organisms/CommandText/useCommandTextString/utils/getLabwareDisplayLocation.tsx
user: login: smb2268
body: You have the columns mixed up here! you're checking for D3 first but printing "A", then checking C3 and printing "B", etc
created_at: 2025-04-16T17:59:24Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-04-11T16:07:15Z
body: ## [Codecov](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) Report
Attention: Patch coverage is `50.28902%` with `86 lines` in your changes missing coverage. Please review.
> Project coverage is 26.54%. Comparing base [(`b6a86c7`)](https://app.codecov.io/gh/Opentrons/opentrons/commit/b6a86c71bb22a4d9ebe7cceeb290d86448e93ec4?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) to head [(`6a17483`)](https://app.codecov.io/gh/Opentrons/opentrons/commit/6a17483f5c43f074832619f68479c46e1bc79a07?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons).
> Report is 5 commits behind head on edge.

| [Files with missing lines](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) | Patch % | Lines |
|---|---|---|
| [...ing/utils/commandText/getFlexStackerCommandText.ts](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FcommandText%2FgetFlexStackerCommandText.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2NvbW1hbmRUZXh0L2dldEZsZXhTdGFja2VyQ29tbWFuZFRleHQudHM=) | 59.05% | [52 Missing :warning: ](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) |
| [...rganisms/CommandText/useCommandTextString/index.ts](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Findex.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL2luZGV4LnRz) | 0.00% | [13 Missing :warning: ](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) |
| [...mandTextString/utils/getLabwareDisplayLocation.tsx](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FgetLabwareDisplayLocation.tsx&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2dldExhYndhcmVEaXNwbGF5TG9jYXRpb24udHN4) | 50.00% | [11 Missing :warning: ](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) |
| [.../useCommandTextString/utils/getLabwareLocation.tsx](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FgetLabwareLocation.tsx&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2dldExhYndhcmVMb2NhdGlvbi50c3g=) | 0.00% | [10 Missing :warning: ](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) |

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045/graphs/tree.svg?width=650&height=150&src=pr&token=DIJPWI1JiU&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons)](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons)

```diff
@@            Coverage Diff             @@
##             edge   #18045      +/-   ##
==========================================
+ Coverage   25.47%   26.54%   +1.06%     
==========================================
  Files        3008     2967      -41     
  Lines      233870   231533    -2337     
  Branches    20072    19954     -118     
==========================================
+ Hits        59584    61449    +1865     
+ Misses     174271   170062    -4209     
- Partials       15       22       +7     
```

| [Flag](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) | Coverage Δ | |
|---|---|---|
| [protocol-designer](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) | `18.80% <5.78%> (+0.07%)` | :arrow_up: |
| [step-generation](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) | `4.38% <0.00%> (-0.01%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Files with missing lines](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons) | Coverage Δ | |
|---|---|---|
| [...xt/useCommandTextString/utils/commandText/index.ts](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FcommandText%2Findex.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2NvbW1hbmRUZXh0L2luZGV4LnRz) | `100.00% <100.00%> (ø)` | |
| [.../useCommandTextString/utils/getLabwareLocation.tsx](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FgetLabwareLocation.tsx&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2dldExhYndhcmVMb2NhdGlvbi50c3g=) | `30.00% <0.00%> (+0.46%)` | :arrow_up: |
| [...mandTextString/utils/getLabwareDisplayLocation.tsx](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FgetLabwareDisplayLocation.tsx&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2dldExhYndhcmVEaXNwbGF5TG9jYXRpb24udHN4) | `68.22% <50.00%> (-1.09%)` | :arrow_down: |
| [...rganisms/CommandText/useCommandTextString/index.ts](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Findex.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL2luZGV4LnRz) | `77.20% <0.00%> (-4.32%)` | :arrow_down: |
| [...ing/utils/commandText/getFlexStackerCommandText.ts](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045?src=pr&el=tree&filepath=components%2Fsrc%2Forganisms%2FCommandText%2FuseCommandTextString%2Futils%2FcommandText%2FgetFlexStackerCommandText.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons#diff-Y29tcG9uZW50cy9zcmMvb3JnYW5pc21zL0NvbW1hbmRUZXh0L3VzZUNvbW1hbmRUZXh0U3RyaW5nL3V0aWxzL2NvbW1hbmRUZXh0L2dldEZsZXhTdGFja2VyQ29tbWFuZFRleHQudHM=) | `61.19% <59.05%> (+48.69%)` | :arrow_up: |

... and [222 files with indirect coverage changes](https://app.codecov.io/gh/Opentrons/opentrons/pull/18045/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Opentrons)

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: vegano1
created_at: 2025-04-14T13:38:53Z
body: @TamarZanzouri 
looks great, thank you
Can we also say the number of labware we are filling the stacker with for the' fill' command?
author_association: CONTRIBUTOR