There was an error invoking the function - window is not defined at invoke

I am trying to create an admin page that has a form that stores two input fields in Jira key/value storage. I had this working with UI Kit 1 but have to switch to the new UI Kit and have been running into this error message.

adminForm.jsx:45 Uncaught (in promise) Error: There was an error invoking the function - window is not defined
    at invoke (https://jira-frontend-bifrost.prod-east.frontend.public.atl-paas.net/assets/async-forge-ui-full-page-extension.e927791e.js:39:78872)
    at async https://jira-frontend-bifrost.prod-east.frontend.public.atl-paas.net/assets/async-forge-ui-full-page-extension.e927791e.js:39:109927

Error: There was an error invoking the function - window is not defined
    at fe.error (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:74679)
    at Object.<anonymous> (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:82452)
    at JSON.parse (<anonymous>)
    at Ee.o (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:82311)
    at Ee (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:82464)
    at We.i.on (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:87124)
    at We (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:87261)
    at https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:93247
    at e.try (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:65731)
    at https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:93044

Here is my code, starting with the manifest.yml

permissions:
  scopes:
    - storage:app
modules:
  jira:adminPage:
    - key: bigeye-jira-admin-page
      resource: admin-page
      title: Bigeye
      render: native
      icon: resource:icons;bigeye_icon.png
      resolver:
        function: resolver
  function:
    - key: resolver
      handler: index.handler
resources:
  - key: admin-page
    path: src/frontend/adminForm.jsx
app:
  id: ari:cloud:ecosystem::app/xxxxxxxxx
  runtime:
    name: nodejs20.x

Here is my adminForm.jsx file

import ForgeReconciler, {
    Form,
    Textfield,
    Text,
    SectionMessage,
    FormHeader,
    FormSection,
    Stack,
    useForm,
    Label,
    ErrorMessage,
    Box,
    FormFooter,
    Button
} from "@forge/react";
import React, { Fragment, useState, useEffect } from "react";
import { invoke } from "@forge/bridge";

const WEBHOOK_STORAGE_KEY = 'bigeye-webhook-url'
const PROJECT_LIST_KEY = 'bigeye-project-keys'

function SavedMessage({isSaved}) {
  if (isSaved) {
    return <SectionMessage appearance="confirmation">
              <Text>Bigeye configuration has been updated!</Text>
            </SectionMessage>
  }
  else {
    return null
  }
}

const AdminForm = () => {
    const [webhookUrl, setWebhookUrl] = useState(null);
    const [projectKeys, setProjectKeys] = useState(null);
    const [isUpdated, setIsUpdated] = useState(false);

    const { handleSubmit, register, getFieldId, formState } = useForm();
    const { errors, touchedFields } = formState;

    useEffect(async() => {
        const currWebhook = await invoke("getStorageValue", { key: `${WEBHOOK_STORAGE_KEY}` });
        setWebhookUrl(currWebhook);
        const currProjectKeys = await invoke("getStorageValue", { key: `${PROJECT_LIST_KEY}` });
        setProjectKeys(currProjectKeys);
        }, [invoke, setWebhookUrl, setProjectKeys]
    );

    const onSubmit = (formData) => {
        console.log(formData);
        // Update the webhook url
        const wh = formData['webhook']
        console.log(`Setting the ${WEBHOOK_STORAGE_KEY} property to ${wh}`)
        invoke("setStorageValue", { key: `${WEBHOOK_STORAGE_KEY}`, value: wh }).then(setWebhookUrl);

        // Update the list of project keys
        const pks = formData['projectKeys']
        console.log(`Setting the ${PROJECT_LIST_KEY} property to ${pks}`)
        invoke("setStorageValue", { key: `${PROJECT_LIST_KEY}`, value: pks }).then(setProjectKeys);

        // Set to true so that success message shows
        setIsUpdated(true)
    };

    return (
      <Fragment>
        <SavedMessage isSaved={isUpdated} />
        <Form onSubmit={handleSubmit(onSubmit)}>
            <FormHeader title="Bigeye Integration Settings">
                All fields are required.
            </FormHeader>
            <FormSection>
                <Stack space="space.75">
                    <Box>
                        <Label labelFor={getFieldId("webhook")}>
                            Webhook Url
                        </Label>
                        <Textfield
                            {...register("webhook", {
                                required: true,
                                defaultValue: webhookUrl
                            })}
                        />
                        {errors["webhook"] && (
                            <ErrorMessage>Please enter a valid webhook URL</ErrorMessage>
                        )}
                    </Box>
                    <Box>
                        <Label labelFor={getFieldId("projectKeys")}>
                            Project Keys (Separate each key with a comma. i.e. BI,DO,DQ)
                        </Label>
                        <Textfield
                            {...register("projectKeys", {
                                required: true,
                                defaultValue: projectKeys
                            })}
                        />
                        {errors["projectKeys"] && (
                            <ErrorMessage>Please enter your desired Project keys</ErrorMessage>
                        )}
                    </Box>
                </Stack>
            </FormSection>
            <FormFooter>
                <Button appearance="primary" type="submit">
                  Submit
                </Button>
            </FormFooter>
        </Form>
      </Fragment>
    );
  };

ForgeReconciler.render(
    <React.StrictMode>
        <AdminForm/>
    </React.StrictMode>
)

Here is my resolvers/index.jsx file, inspired by this repo

import Resolver from "@forge/resolver";
import { storage } from "@forge/api";

const resolver = new Resolver();

async function getDefinition(key) {
  const value = await storage.get(key);
  return value ? value.definition : "";
}

resolver.define('getDefinition', async(req) => {
    const value = await getDefinition(req.payload.key);
    return await Promise.all(value);
})

resolver.define('setDefinition', async(req) => {
  const { key, value } = req.payload;
  await storage.set(key, value);
})

export const handler = resolver.getDefinitions();

Finally, here are my versions from package.json

  "dependencies": {
    "@forge/api": "^3.4.0",
    "@forge/bridge": "3.3.0",
    "@forge/react": "10.1.0",
    "@forge/resolver": "1.5.31",
    "react": "^18.2.0"
  }