const normalizeLine = line => {
  if (line.startsWith('Error: ')) {
    return line.slice('Error: '.length);
  }
  if (line.startsWith('VError: ')) {
    return line.slice('VError: '.length);
  }
  return line;
};
const getCombinedMessage = (error, message) => {
  const stringifiedError = normalizeLine(`${error}`);
  if (message) {
    return `${message}: ${stringifiedError}`;
  }
  return stringifiedError;
};
const NewLine$2 = '\n';
const getNewLineIndex$1 = (string, startIndex = undefined) => {
  return string.indexOf(NewLine$2, startIndex);
};
const mergeStacks = (parent, child) => {
  if (!child) {
    return parent;
  }
  const parentNewLineIndex = getNewLineIndex$1(parent);
  const childNewLineIndex = getNewLineIndex$1(child);
  if (childNewLineIndex === -1) {
    return parent;
  }
  const parentFirstLine = parent.slice(0, parentNewLineIndex);
  const childRest = child.slice(childNewLineIndex);
  const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
  if (parentFirstLine.includes(childFirstLine)) {
    return parentFirstLine + childRest;
  }
  return child;
};
class VError extends Error {
  constructor(error, message) {
    const combinedMessage = getCombinedMessage(error, message);
    super(combinedMessage);
    this.name = 'VError';
    if (error instanceof Error) {
      this.stack = mergeStacks(this.stack, error.stack);
    }
    if (error.codeFrame) {
      // @ts-ignore
      this.codeFrame = error.codeFrame;
    }
    if (error.code) {
      // @ts-ignore
      this.code = error.code;
    }
  }
}

const isMessagePort = value => {
  return value && value instanceof MessagePort;
};
const isMessagePortMain = value => {
  return value && value.constructor && value.constructor.name === 'MessagePortMain';
};
const isOffscreenCanvas = value => {
  return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
};
const isInstanceOf = (value, constructorName) => {
  return value?.constructor?.name === constructorName;
};
const isSocket = value => {
  return isInstanceOf(value, 'Socket');
};
const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
const isTransferrable = value => {
  for (const fn of transferrables) {
    if (fn(value)) {
      return true;
    }
  }
  return false;
};
const walkValue = (value, transferrables, isTransferrable) => {
  if (!value) {
    return;
  }
  if (isTransferrable(value)) {
    transferrables.push(value);
    return;
  }
  if (Array.isArray(value)) {
    for (const item of value) {
      walkValue(item, transferrables, isTransferrable);
    }
    return;
  }
  if (typeof value === 'object') {
    for (const property of Object.values(value)) {
      walkValue(property, transferrables, isTransferrable);
    }
    return;
  }
};
const getTransferrables = value => {
  const transferrables = [];
  walkValue(value, transferrables, isTransferrable);
  return transferrables;
};
const attachEvents = that => {
  const handleMessage = (...args) => {
    const data = that.getData(...args);
    that.dispatchEvent(new MessageEvent('message', {
      data
    }));
  };
  that.onMessage(handleMessage);
  const handleClose = event => {
    that.dispatchEvent(new Event('close'));
  };
  that.onClose(handleClose);
};
class Ipc extends EventTarget {
  constructor(rawIpc) {
    super();
    this._rawIpc = rawIpc;
    attachEvents(this);
  }
}
const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
const NewLine$1 = '\n';
const joinLines$1 = lines => {
  return lines.join(NewLine$1);
};
const RE_AT = /^\s+at/;
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
const isNormalStackLine = line => {
  return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
};
const getDetails = lines => {
  const index = lines.findIndex(isNormalStackLine);
  if (index === -1) {
    return {
      actualMessage: joinLines$1(lines),
      rest: []
    };
  }
  let lastIndex = index - 1;
  while (++lastIndex < lines.length) {
    if (!isNormalStackLine(lines[lastIndex])) {
      break;
    }
  }
  return {
    actualMessage: lines[index - 1],
    rest: lines.slice(index, lastIndex)
  };
};
const splitLines$1 = lines => {
  return lines.split(NewLine$1);
};
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
const isMessageCodeBlockStartIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_START.test(line);
};
const isMessageCodeBlockEndIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_END.test(line);
};
const getMessageCodeBlock = stderr => {
  const lines = splitLines$1(stderr);
  const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
  const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
  const relevantLines = lines.slice(startIndex, endIndex);
  const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
  return relevantMessage;
};
const isModuleNotFoundMessage = line => {
  return line.includes('[ERR_MODULE_NOT_FOUND]');
};
const getModuleNotFoundError = stderr => {
  const lines = splitLines$1(stderr);
  const messageIndex = lines.findIndex(isModuleNotFoundMessage);
  const message = lines[messageIndex];
  return {
    code: ERR_MODULE_NOT_FOUND,
    message
  };
};
const isModuleNotFoundError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('ERR_MODULE_NOT_FOUND');
};
const isModulesSyntaxError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('SyntaxError: Cannot use import statement outside a module');
};
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
const isUnhelpfulNativeModuleError = stderr => {
  return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
};
const getNativeModuleErrorMessage = stderr => {
  const message = getMessageCodeBlock(stderr);
  return {
    code: E_INCOMPATIBLE_NATIVE_MODULE,
    message: `Incompatible native node module: ${message}`
  };
};
const getModuleSyntaxError = () => {
  return {
    code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON,
    message: `ES Modules are not supported in electron`
  };
};
const getHelpfulChildProcessError = (stdout, stderr) => {
  if (isUnhelpfulNativeModuleError(stderr)) {
    return getNativeModuleErrorMessage(stderr);
  }
  if (isModulesSyntaxError(stderr)) {
    return getModuleSyntaxError();
  }
  if (isModuleNotFoundError(stderr)) {
    return getModuleNotFoundError(stderr);
  }
  const lines = splitLines$1(stderr);
  const {
    actualMessage,
    rest
  } = getDetails(lines);
  return {
    code: '',
    message: actualMessage,
    stack: rest
  };
};
class IpcError extends VError {
  // @ts-ignore
  constructor(betterMessage, stdout = '', stderr = '') {
    if (stdout || stderr) {
      // @ts-ignore
      const {
        code,
        message,
        stack
      } = getHelpfulChildProcessError(stdout, stderr);
      const cause = new Error(message);
      // @ts-ignore
      cause.code = code;
      cause.stack = stack;
      super(cause, betterMessage);
    } else {
      super(betterMessage);
    }
    // @ts-ignore
    this.name = 'IpcError';
    // @ts-ignore
    this.stdout = stdout;
    // @ts-ignore
    this.stderr = stderr;
  }
}
const readyMessage = 'ready';
const getData$2 = event => {
  return event.data;
};
const listen$7 = () => {
  // @ts-ignore
  if (typeof WorkerGlobalScope === 'undefined') {
    throw new TypeError('module is not in web worker scope');
  }
  return globalThis;
};
const signal$8 = global => {
  global.postMessage(readyMessage);
};
class IpcChildWithModuleWorker extends Ipc {
  getData(event) {
    return getData$2(event);
  }
  send(message) {
    // @ts-ignore
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    // @ts-ignore
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    // ignore
  }
  onClose(callback) {
    // ignore
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
  }
}
const wrap$f = global => {
  return new IpcChildWithModuleWorker(global);
};
const waitForFirstMessage = async port => {
  const {
    promise,
    resolve
  } = Promise.withResolvers();
  port.addEventListener('message', resolve, {
    once: true
  });
  const event = await promise;
  // @ts-ignore
  return event.data;
};
const listen$6 = async () => {
  const parentIpcRaw = listen$7();
  signal$8(parentIpcRaw);
  const parentIpc = wrap$f(parentIpcRaw);
  const firstMessage = await waitForFirstMessage(parentIpc);
  if (firstMessage.method !== 'initialize') {
    throw new IpcError('unexpected first message');
  }
  const type = firstMessage.params[0];
  if (type === 'message-port') {
    parentIpc.send({
      id: firstMessage.id,
      jsonrpc: '2.0',
      result: null
    });
    parentIpc.dispose();
    const port = firstMessage.params[1];
    return port;
  }
  return globalThis;
};
class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
  getData(event) {
    return getData$2(event);
  }
  send(message) {
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    if (this._rawIpc.close) {
      this._rawIpc.close();
    }
  }
  onClose(callback) {
    // ignore
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
    this._rawIpc.start();
  }
}
const wrap$e = port => {
  return new IpcChildWithModuleWorkerAndMessagePort(port);
};
const IpcChildWithModuleWorkerAndMessagePort$1 = {
  __proto__: null,
  listen: listen$6,
  wrap: wrap$e
};
const addListener = (emitter, type, callback) => {
  if ('addEventListener' in emitter) {
    emitter.addEventListener(type, callback);
  } else {
    emitter.on(type, callback);
  }
};
const removeListener = (emitter, type, callback) => {
  if ('removeEventListener' in emitter) {
    emitter.removeEventListener(type, callback);
  } else {
    emitter.off(type, callback);
  }
};
const getFirstEvent = (eventEmitter, eventMap) => {
  const {
    promise,
    resolve
  } = Promise.withResolvers();
  const listenerMap = Object.create(null);
  const cleanup = value => {
    for (const event of Object.keys(eventMap)) {
      removeListener(eventEmitter, event, listenerMap[event]);
    }
    resolve(value);
  };
  for (const [event, type] of Object.entries(eventMap)) {
    const listener = event => {
      cleanup({
        event,
        type
      });
    };
    addListener(eventEmitter, event, listener);
    listenerMap[event] = listener;
  }
  return promise;
};
const Message$1 = 3;
const create$5$1 = async ({
  isMessagePortOpen,
  messagePort
}) => {
  if (!isMessagePort(messagePort)) {
    throw new IpcError('port must be of type MessagePort');
  }
  if (isMessagePortOpen) {
    return messagePort;
  }
  const eventPromise = getFirstEvent(messagePort, {
    message: Message$1
  });
  messagePort.start();
  const {
    event,
    type
  } = await eventPromise;
  if (type !== Message$1) {
    throw new IpcError('Failed to wait for ipc message');
  }
  if (event.data !== readyMessage) {
    throw new IpcError('unexpected first message');
  }
  return messagePort;
};
const signal$1 = messagePort => {
  messagePort.start();
};
class IpcParentWithMessagePort extends Ipc {
  getData = getData$2;
  send(message) {
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    this._rawIpc.close();
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
  }
  onClose(callback) {}
}
const wrap$5 = messagePort => {
  return new IpcParentWithMessagePort(messagePort);
};
const IpcParentWithMessagePort$1 = {
  __proto__: null,
  create: create$5$1,
  signal: signal$1,
  wrap: wrap$5
};

class CommandNotFoundError extends Error {
  constructor(command) {
    super(`Command not found ${command}`);
    this.name = 'CommandNotFoundError';
  }
}
const commands = Object.create(null);
const register = commandMap => {
  Object.assign(commands, commandMap);
};
const getCommand = key => {
  return commands[key];
};
const execute = (command, ...args) => {
  const fn = getCommand(command);
  if (!fn) {
    throw new CommandNotFoundError(command);
  }
  return fn(...args);
};

const Two$1 = '2.0';
const callbacks = Object.create(null);
const get$1 = id => {
  return callbacks[id];
};
const remove$1 = id => {
  delete callbacks[id];
};
class JsonRpcError extends Error {
  constructor(message) {
    super(message);
    this.name = 'JsonRpcError';
  }
}
const NewLine = '\n';
const DomException = 'DOMException';
const ReferenceError$1 = 'ReferenceError';
const SyntaxError$1 = 'SyntaxError';
const TypeError$1 = 'TypeError';
const getErrorConstructor = (message, type) => {
  if (type) {
    switch (type) {
      case DomException:
        return DOMException;
      case ReferenceError$1:
        return ReferenceError;
      case SyntaxError$1:
        return SyntaxError;
      case TypeError$1:
        return TypeError;
      default:
        return Error;
    }
  }
  if (message.startsWith('TypeError: ')) {
    return TypeError;
  }
  if (message.startsWith('SyntaxError: ')) {
    return SyntaxError;
  }
  if (message.startsWith('ReferenceError: ')) {
    return ReferenceError;
  }
  return Error;
};
const constructError = (message, type, name) => {
  const ErrorConstructor = getErrorConstructor(message, type);
  if (ErrorConstructor === DOMException && name) {
    return new ErrorConstructor(message, name);
  }
  if (ErrorConstructor === Error) {
    const error = new Error(message);
    if (name && name !== 'VError') {
      error.name = name;
    }
    return error;
  }
  return new ErrorConstructor(message);
};
const joinLines = lines => {
  return lines.join(NewLine);
};
const splitLines = lines => {
  return lines.split(NewLine);
};
const getCurrentStack = () => {
  const stackLinesToSkip = 3;
  const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip));
  return currentStack;
};
const getNewLineIndex = (string, startIndex = undefined) => {
  return string.indexOf(NewLine, startIndex);
};
const getParentStack = error => {
  let parentStack = error.stack || error.data || error.message || '';
  if (parentStack.startsWith('    at')) {
    parentStack = error.message + NewLine + parentStack;
  }
  return parentStack;
};
const MethodNotFound = -32601;
const Custom = -32001;
const restoreJsonRpcError = error => {
  const currentStack = getCurrentStack();
  if (error && error instanceof Error) {
    if (typeof error.stack === 'string') {
      error.stack = error.stack + NewLine + currentStack;
    }
    return error;
  }
  if (error && error.code && error.code === MethodNotFound) {
    const restoredError = new JsonRpcError(error.message);
    const parentStack = getParentStack(error);
    restoredError.stack = parentStack + NewLine + currentStack;
    return restoredError;
  }
  if (error && error.message) {
    const restoredError = constructError(error.message, error.type, error.name);
    if (error.data) {
      if (error.data.stack && error.data.type && error.message) {
        restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
      } else if (error.data.stack) {
        restoredError.stack = error.data.stack;
      }
      if (error.data.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.data.codeFrame;
      }
      if (error.data.code) {
        // @ts-ignore
        restoredError.code = error.data.code;
      }
      if (error.data.type) {
        // @ts-ignore
        restoredError.name = error.data.type;
      }
    } else {
      if (error.stack) {
        const lowerStack = restoredError.stack || '';
        // @ts-ignore
        const indexNewLine = getNewLineIndex(lowerStack);
        const parentStack = getParentStack(error);
        // @ts-ignore
        restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
      }
      if (error.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.codeFrame;
      }
    }
    return restoredError;
  }
  if (typeof error === 'string') {
    return new Error(`JsonRpc Error: ${error}`);
  }
  return new Error(`JsonRpc Error: ${error}`);
};
const unwrapJsonRpcResult = responseMessage => {
  if ('error' in responseMessage) {
    const restoredError = restoreJsonRpcError(responseMessage.error);
    throw restoredError;
  }
  if ('result' in responseMessage) {
    return responseMessage.result;
  }
  throw new JsonRpcError('unexpected response message');
};
const warn = (...args) => {
  console.warn(...args);
};
const resolve = (id, response) => {
  const fn = get$1(id);
  if (!fn) {
    console.log(response);
    warn(`callback ${id} may already be disposed`);
    return;
  }
  fn(response);
  remove$1(id);
};
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
const getErrorType = prettyError => {
  if (prettyError && prettyError.type) {
    return prettyError.type;
  }
  if (prettyError && prettyError.constructor && prettyError.constructor.name) {
    return prettyError.constructor.name;
  }
  return undefined;
};
const isAlreadyStack = line => {
  return line.trim().startsWith('at ');
};
const getStack = prettyError => {
  const stackString = prettyError.stack || '';
  const newLineIndex = stackString.indexOf('\n');
  if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
    return stackString.slice(newLineIndex + 1);
  }
  return stackString;
};
const getErrorProperty = (error, prettyError) => {
  if (error && error.code === E_COMMAND_NOT_FOUND) {
    return {
      code: MethodNotFound,
      data: error.stack,
      message: error.message
    };
  }
  return {
    code: Custom,
    data: {
      code: prettyError.code,
      codeFrame: prettyError.codeFrame,
      name: prettyError.name,
      stack: getStack(prettyError),
      type: getErrorType(prettyError)
    },
    message: prettyError.message
  };
};
const create$1$1 = (id, error) => {
  return {
    error,
    id,
    jsonrpc: Two$1
  };
};
const getErrorResponse = (id, error, preparePrettyError, logError) => {
  const prettyError = preparePrettyError(error);
  logError(error, prettyError);
  const errorProperty = getErrorProperty(error, prettyError);
  return create$1$1(id, errorProperty);
};
const create$8 = (message, result) => {
  return {
    id: message.id,
    jsonrpc: Two$1,
    result: result ?? null
  };
};
const getSuccessResponse = (message, result) => {
  const resultProperty = result ?? null;
  return create$8(message, resultProperty);
};
const getErrorResponseSimple = (id, error) => {
  return {
    error: {
      code: Custom,
      data: error,
      // @ts-ignore
      message: error.message
    },
    id,
    jsonrpc: Two$1
  };
};
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
  try {
    const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
    return getSuccessResponse(message, result);
  } catch (error) {
    if (ipc.canUseSimpleErrorResponse) {
      return getErrorResponseSimple(message.id, error);
    }
    return getErrorResponse(message.id, error, preparePrettyError, logError);
  }
};
const defaultPreparePrettyError = error => {
  return error;
};
const defaultLogError = () => {
  // ignore
};
const defaultRequiresSocket = () => {
  return false;
};
const defaultResolve = resolve;

// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
const normalizeParams = args => {
  if (args.length === 1) {
    const options = args[0];
    return {
      execute: options.execute,
      ipc: options.ipc,
      logError: options.logError || defaultLogError,
      message: options.message,
      preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
      requiresSocket: options.requiresSocket || defaultRequiresSocket,
      resolve: options.resolve || defaultResolve
    };
  }
  return {
    execute: args[2],
    ipc: args[0],
    logError: args[5],
    message: args[1],
    preparePrettyError: args[4],
    requiresSocket: args[6],
    resolve: args[3]
  };
};
const handleJsonRpcMessage = async (...args) => {
  const options = normalizeParams(args);
  const {
    execute,
    ipc,
    logError,
    message,
    preparePrettyError,
    requiresSocket,
    resolve
  } = options;
  if ('id' in message) {
    if ('method' in message) {
      const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
      try {
        ipc.send(response);
      } catch (error) {
        const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
        ipc.send(errorResponse);
      }
      return;
    }
    resolve(message.id, message);
    return;
  }
  if ('method' in message) {
    await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
    return;
  }
  throw new JsonRpcError('unexpected message');
};

const Two = '2.0';

const create$7 = (method, params) => {
  return {
    jsonrpc: Two,
    method,
    params
  };
};

const create$6 = (id, method, params) => {
  const message = {
    id,
    jsonrpc: Two,
    method,
    params
  };
  return message;
};

let id = 0;
const create$5 = () => {
  return ++id;
};

const registerPromise = map => {
  const id = create$5();
  const {
    promise,
    resolve
  } = Promise.withResolvers();
  map[id] = resolve;
  return {
    id,
    promise
  };
};

const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => {
  const {
    id,
    promise
  } = registerPromise(callbacks);
  const message = create$6(id, method, params);
  if (useSendAndTransfer && ipc.sendAndTransfer) {
    ipc.sendAndTransfer(message);
  } else {
    ipc.send(message);
  }
  const responseMessage = await promise;
  return unwrapJsonRpcResult(responseMessage);
};
const createRpc = ipc => {
  const callbacks = Object.create(null);
  ipc._resolve = (id, response) => {
    const fn = callbacks[id];
    if (!fn) {
      console.warn(`callback ${id} may already be disposed`);
      return;
    }
    fn(response);
    delete callbacks[id];
  };
  const rpc = {
    async dispose() {
      await ipc?.dispose();
    },
    invoke(method, ...params) {
      return invokeHelper(callbacks, ipc, method, params, false);
    },
    invokeAndTransfer(method, ...params) {
      return invokeHelper(callbacks, ipc, method, params, true);
    },
    // @ts-ignore
    ipc,
    /**
     * @deprecated
     */
    send(method, ...params) {
      const message = create$7(method, params);
      ipc.send(message);
    }
  };
  return rpc;
};

const requiresSocket = () => {
  return false;
};
const preparePrettyError = error => {
  return error;
};
const logError = () => {
  // handled by renderer worker
};
const handleMessage = event => {
  const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
  const actualExecute = event?.target?.execute || execute;
  return handleJsonRpcMessage(event.target, event.data, actualExecute, event.target._resolve, preparePrettyError, logError, actualRequiresSocket);
};

const handleIpc = ipc => {
  if ('addEventListener' in ipc) {
    ipc.addEventListener('message', handleMessage);
  } else if ('on' in ipc) {
    // deprecated
    ipc.on('message', handleMessage);
  }
};

const listen$1 = async (module, options) => {
  const rawIpc = await module.listen(options);
  if (module.signal) {
    module.signal(rawIpc);
  }
  const ipc = module.wrap(rawIpc);
  return ipc;
};

const create$4 = async ({
  commandMap,
  isMessagePortOpen = true,
  messagePort
}) => {
  // TODO create a commandMap per rpc instance
  register(commandMap);
  const rawIpc = await IpcParentWithMessagePort$1.create({
    isMessagePortOpen,
    messagePort
  });
  const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
  handleIpc(ipc);
  const rpc = createRpc(ipc);
  messagePort.start();
  return rpc;
};

const create$3 = async ({
  commandMap,
  isMessagePortOpen,
  send
}) => {
  const {
    port1,
    port2
  } = new MessageChannel();
  await send(port1);
  return create$4({
    commandMap,
    isMessagePortOpen,
    messagePort: port2
  });
};

const createSharedLazyRpc = factory => {
  let rpcPromise;
  const getOrCreate = () => {
    if (!rpcPromise) {
      rpcPromise = factory();
    }
    return rpcPromise;
  };
  return {
    async dispose() {
      const rpc = await getOrCreate();
      await rpc.dispose();
    },
    async invoke(method, ...params) {
      const rpc = await getOrCreate();
      return rpc.invoke(method, ...params);
    },
    async invokeAndTransfer(method, ...params) {
      const rpc = await getOrCreate();
      return rpc.invokeAndTransfer(method, ...params);
    },
    async send(method, ...params) {
      const rpc = await getOrCreate();
      rpc.send(method, ...params);
    }
  };
};

const create$2 = async ({
  commandMap,
  isMessagePortOpen,
  send
}) => {
  return createSharedLazyRpc(() => {
    return create$3({
      commandMap,
      isMessagePortOpen,
      send
    });
  });
};

const create$1 = async ({
  commandMap
}) => {
  // TODO create a commandMap per rpc instance
  register(commandMap);
  const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
  handleIpc(ipc);
  const rpc = createRpc(ipc);
  return rpc;
};

const handleMessagePort = async port => {
  await create$4({
    commandMap: commandMap,
    isMessagePortOpen: true,
    messagePort: port
  });
};

const initialize = async (_, port) => {
  await handleMessagePort(port);
};

const createMockRpc = ({
  commandMap
}) => {
  const invocations = [];
  const invoke = (method, ...params) => {
    invocations.push([method, ...params]);
    const command = commandMap[method];
    if (!command) {
      throw new Error(`command ${method} not found`);
    }
    return command(...params);
  };
  const mockRpc = {
    invocations,
    invoke,
    invokeAndTransfer: invoke
  };
  return mockRpc;
};

const rpcs = Object.create(null);
const set$1 = (id, rpc) => {
  rpcs[id] = rpc;
};
const get = id => {
  return rpcs[id];
};
const remove = id => {
  delete rpcs[id];
};

/* eslint-disable  @typescript-eslint/explicit-function-return-type */
const create = rpcId => {
  return {
    async dispose() {
      const rpc = get(rpcId);
      await rpc.dispose();
    },
    // @ts-ignore
    invoke(method, ...params) {
      const rpc = get(rpcId);
      // @ts-ignore
      return rpc.invoke(method, ...params);
    },
    // @ts-ignore
    invokeAndTransfer(method, ...params) {
      const rpc = get(rpcId);
      // @ts-ignore
      return rpc.invokeAndTransfer(method, ...params);
    },
    registerMockRpc(commandMap) {
      const mockRpc = createMockRpc({
        commandMap
      });
      set$1(rpcId, mockRpc);
      // @ts-ignore
      mockRpc[Symbol.dispose] = () => {
        remove(rpcId);
      };
      // @ts-ignore
      return mockRpc;
    },
    set(rpc) {
      set$1(rpcId, rpc);
    }
  };
};

const {
  invoke,
  set
} = create(6007);
const getMathBlockDom = async node => {
  return invoke('ChatMath.getMathBlockDom', node);
};
const getMathInlineDom = async node => {
  return invoke('ChatMath.getMathInlineDom', node);
};

const RendererWorker = 1;

const {
  invokeAndTransfer} = create(RendererWorker);
const sendMessagePortToChatMathWorker$1 = async (port, rpcId) => {
  const command = 'HandleMessagePort.handleMessagePort';
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatMathWorker', port, command, rpcId);
};

const parseMathInline = async children => {
  const nextChildren = [];
  for (const child of children) {
    if (child.type === 'math-inline') {
      const dom = await getMathInlineDom(child);
      nextChildren.push({
        dom,
        type: 'math-inline-dom'
      });
      continue;
    }
    if (child.type === 'bold') {
      nextChildren.push({
        ...child,
        children: await parseMathInline(child.children)
      });
      continue;
    }
    if (child.type === 'italic') {
      nextChildren.push({
        ...child,
        children: await parseMathInline(child.children)
      });
      continue;
    }
    if (child.type === 'strikethrough') {
      nextChildren.push({
        ...child,
        children: await parseMathInline(child.children)
      });
      continue;
    }
    nextChildren.push(child);
  }
  return nextChildren;
};
const parseMathListItem = async item => {
  const children = await parseMathInline(item.children);
  if (!item.nestedItems) {
    return {
      ...item,
      children
    };
  }
  const nestedItems = [];
  for (const nestedItem of item.nestedItems) {
    nestedItems.push(await parseMathListItem(nestedItem));
  }
  return {
    ...item,
    children,
    nestedItems
  };
};
const parseMathTableCell = async cell => {
  return {
    ...cell,
    children: await parseMathInline(cell.children)
  };
};
const parseMathNode = async node => {
  if (node.type === 'math-block') {
    const dom = await getMathBlockDom(node);
    return {
      dom,
      type: 'math-block-dom'
    };
  }
  if (node.type === 'text' || node.type === 'heading') {
    return {
      ...node,
      children: await parseMathInline(node.children)
    };
  }
  if (node.type === 'blockquote') {
    const children = [];
    for (const child of node.children) {
      children.push(await parseMathNode(child));
    }
    return {
      ...node,
      children
    };
  }
  if (node.type === 'ordered-list' || node.type === 'unordered-list') {
    const items = [];
    for (const item of node.items) {
      items.push(await parseMathListItem(item));
    }
    return {
      ...node,
      items
    };
  }
  if (node.type === 'table') {
    const headers = [];
    for (const header of node.headers) {
      headers.push(await parseMathTableCell(header));
    }
    const rows = [];
    for (const row of node.rows) {
      const cells = [];
      for (const cell of row.cells) {
        cells.push(await parseMathTableCell(cell));
      }
      rows.push({
        ...row,
        cells
      });
    }
    return {
      ...node,
      headers,
      rows
    };
  }
  return node;
};

const TokenAttribute = 'TokenAttribute';
const TokenComment = 'TokenComment';
const TokenKeyword = 'TokenKeyword';
const TokenNumber = 'TokenNumber';
const TokenProperty = 'TokenProperty';
const TokenString = 'TokenString';
const TokenTag = 'TokenTag';
const TokenValue = 'TokenValue';

const jsRules = [{
  className: TokenComment,
  regex: /\/\/[^\n]*/
}, {
  className: TokenComment,
  regex: /\/\*[\s\S]*?\*\//
}, {
  className: TokenString,
  regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
}, {
  className: TokenString,
  regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
}, {
  className: TokenString,
  regex: /`[^`\\]*(?:\\.[^`\\]*)*`/
}, {
  className: TokenNumber,
  regex: /\b\d+\.?\d*\b/
}, {
  className: TokenKeyword,
  regex: /\b(?:const|let|var|function|return|if|else|for|while|class|new|typeof|instanceof|import|export|from|default|async|await|try|catch|finally|throw|this|true|false|null|undefined)\b/
}];
const tsRules = [{
  className: TokenComment,
  regex: /\/\/[^\n]*/
}, {
  className: TokenComment,
  regex: /\/\*[\s\S]*?\*\//
}, {
  className: TokenString,
  regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
}, {
  className: TokenString,
  regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
}, {
  className: TokenString,
  regex: /`[^`\\]*(?:\\.[^`\\]*)*`/
}, {
  className: TokenNumber,
  regex: /\b\d+\.?\d*\b/
}, {
  className: TokenKeyword,
  regex: /\b(?:abstract|any|as|asserts|async|await|boolean|class|const|constructor|declare|default|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|infer|instanceof|interface|is|keyof|let|module|namespace|never|new|null|number|object|override|private|protected|public|readonly|return|satisfies|set|static|string|super|switch|symbol|this|throw|true|try|type|typeof|undefined|unknown|var|void|while)\b/
}];
const htmlRules = [{
  className: TokenComment,
  regex: /<!--[\s\S]*?-->/
}, {
  className: TokenTag,
  regex: /<\/[a-zA-Z][a-zA-Z0-9-]*\s*>/
}, {
  className: TokenTag,
  regex: /<[a-zA-Z][a-zA-Z0-9-]*/
}, {
  className: TokenTag,
  regex: /\/?>/
}, {
  className: TokenString,
  regex: /"[^"]*"/
}, {
  className: TokenString,
  regex: /'[^']*'/
}, {
  className: TokenAttribute,
  regex: /[a-zA-Z-]+(?=\s*=)/
}];
const cssRules = [{
  className: TokenComment,
  regex: /\/\*[\s\S]*?\*\//
}, {
  className: TokenString,
  regex: /"[^"]*"/
}, {
  className: TokenString,
  regex: /'[^']*'/
}, {
  className: TokenValue,
  regex: /#[0-9a-fA-F]{3,8}/
}, {
  className: TokenValue,
  regex: /\b\d+(?:\.\d+)?(?:px|em|rem|%|vh|vw|pt|s|ms|fr)?\b/
}, {
  className: TokenProperty,
  regex: /[a-zA-Z-]+(?=\s*:)/
}];
const pythonRules = [{
  className: TokenComment,
  regex: /#[^\n]*/
}, {
  className: TokenString,
  regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
}, {
  className: TokenString,
  regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
}, {
  className: TokenNumber,
  regex: /\b\d+\.?\d*\b/
}, {
  className: TokenKeyword,
  regex: /\b(?:def|class|return|if|elif|else|for|while|in|import|from|as|with|try|except|finally|raise|lambda|yield|pass|break|continue|True|False|None|and|or|not|is)\b/
}];
const jsonRules = [{
  className: TokenProperty,
  regex: /"[^"\\]*(?:\\.[^"\\]*)*"(?=\s*:)/
}, {
  className: TokenString,
  regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
}, {
  className: TokenNumber,
  regex: /-?\b\d+\.?\d*(?:[eE][+-]?\d+)?\b/
}, {
  className: TokenKeyword,
  regex: /\b(?:true|false|null)\b/
}];
const tokenize = (code, rules) => {
  const tokens = [];
  let pos = 0;
  while (pos < code.length) {
    let matched = false;
    for (const rule of rules) {
      const match = rule.regex.exec(code.slice(pos));
      if (match && match.index === 0) {
        tokens.push({
          className: rule.className,
          text: match[0]
        });
        pos += match[0].length;
        matched = true;
        break;
      }
    }
    if (!matched) {
      const last = tokens.at(-1);
      if (last && last.className === '') {
        tokens.pop();
        tokens.push({
          className: '',
          text: last.text + code[pos]
        });
      } else {
        tokens.push({
          className: '',
          text: code[pos]
        });
      }
      pos++;
    }
  }
  return tokens;
};
const highlightCode = (code, language) => {
  if (!language) {
    return [{
      className: '',
      text: code
    }];
  }
  const normalized = language.toLowerCase();
  if (normalized === 'html') {
    return tokenize(code, htmlRules);
  }
  if (normalized === 'css') {
    return tokenize(code, cssRules);
  }
  if (normalized === 'js' || normalized === 'javascript') {
    return tokenize(code, jsRules);
  }
  if (normalized === 'ts' || normalized === 'typescript') {
    return tokenize(code, tsRules);
  }
  if (normalized === 'py' || normalized === 'python') {
    return tokenize(code, pythonRules);
  }
  if (normalized === 'json') {
    return tokenize(code, jsonRules);
  }
  return [{
    className: '',
    text: code
  }];
};

const windowsAbsolutePathRegex = /^[a-zA-Z]:[\\/]/;
const pathSeparatorRegex$1 = /[\\/]/;
const isPathTraversalAttempt = path => {
  if (!path) {
    return false;
  }
  if (path.startsWith('/') || path.startsWith('\\')) {
    return true;
  }
  if (path.startsWith('file://')) {
    return true;
  }
  if (windowsAbsolutePathRegex.test(path)) {
    return true;
  }
  const segments = path.split(pathSeparatorRegex$1);
  return segments.includes('..');
};

const pathSeparatorRegex = /[\\/]/;
const normalizeRelativePath = path => {
  const segments = path.split(pathSeparatorRegex).filter(segment => segment && segment !== '.');
  if (segments.length === 0) {
    return '.';
  }
  return segments.join('/');
};

const isAlphaNumeric = value => {
  if (!value) {
    return false;
  }
  const code = value.codePointAt(0) ?? 0;
  if (code >= 48 && code <= 57) {
    return true;
  }
  if (code >= 65 && code <= 90) {
    return true;
  }
  return code >= 97 && code <= 122;
};
const sanitizeLinkUrl = url => {
  const trimmedUrl = url.trim();
  const normalized = url.trim().toLowerCase();
  if (normalized.startsWith('http://') || normalized.startsWith('https://') || normalized.startsWith('file://') || normalized.startsWith('vscode-references://')) {
    return trimmedUrl;
  }
  if (!trimmedUrl || trimmedUrl.startsWith('#') || trimmedUrl.startsWith('?') || trimmedUrl.startsWith('/') || trimmedUrl.startsWith('\\')) {
    return '#';
  }
  if (trimmedUrl.includes('://') || trimmedUrl.includes(':')) {
    return '#';
  }
  if (isPathTraversalAttempt(trimmedUrl)) {
    return '#';
  }
  const normalizedPath = normalizeRelativePath(trimmedUrl);
  if (normalizedPath === '.') {
    return '#';
  }
  return `file:///workspace/${normalizedPath}`;
};
const sanitizeImageUrl = url => {
  const normalized = url.trim().toLowerCase();
  if (normalized.startsWith('http://') || normalized.startsWith('https://')) {
    return url;
  }
  return '#';
};
const isOpenBracket = value => {
  return value === '(' || value === '[' || value === '{';
};
const isCloseBracket = value => {
  return value === ')' || value === ']' || value === '}';
};
const findRawUrlEnd = (value, start) => {
  let index = start;
  while (index < value.length) {
    const current = value[index];
    if (current === ' ' || current === '\n' || current === '\r' || current === '\t' || current === '"' || current === "'" || current === '`' || current === '<' || current === '>') {
      break;
    }
    index++;
  }
  return index;
};
const trimRawUrlEnd = url => {
  let end = url.length;
  while (end > 0) {
    const current = url[end - 1];
    if (current === '.' || current === ',' || current === ':' || current === ';' || current === '!' || current === '?') {
      end--;
      continue;
    }
    if (isCloseBracket(current)) {
      const inner = url.slice(0, end - 1);
      let openCount = 0;
      let closeCount = 0;
      for (let i = 0; i < inner.length; i++) {
        if (isOpenBracket(inner[i])) {
          openCount++;
        } else if (isCloseBracket(inner[i])) {
          closeCount++;
        }
      }
      if (closeCount >= openCount) {
        end--;
        continue;
      }
    }
    break;
  }
  return url.slice(0, end);
};
const parseRawLinkToken = (value, start) => {
  if (!value.startsWith('https://', start) && !value.startsWith('http://', start)) {
    return undefined;
  }
  if (start >= 2 && value[start - 1] === '(' && value[start - 2] === ']') {
    return undefined;
  }
  const end = findRawUrlEnd(value, start);
  const rawUrl = value.slice(start, end);
  const href = trimRawUrlEnd(rawUrl);
  if (!href) {
    return undefined;
  }
  return {
    length: href.length,
    node: {
      href: sanitizeLinkUrl(href),
      text: href,
      type: 'link'
    }
  };
};
const parseLinkToken = (value, start) => {
  if (value[start] !== '[') {
    return undefined;
  }
  const textEnd = value.indexOf(']', start + 1);
  if (textEnd === -1) {
    return undefined;
  }
  if (value[textEnd + 1] !== '(') {
    return undefined;
  }
  let depth = 1;
  let index = textEnd + 2;
  while (index < value.length) {
    const current = value[index];
    if (current === '\n') {
      return undefined;
    }
    if (current === '(') {
      depth++;
    } else if (current === ')') {
      depth--;
      if (depth === 0) {
        const text = value.slice(start + 1, textEnd);
        const href = value.slice(textEnd + 2, index);
        if (!text || !href) {
          return undefined;
        }
        return {
          length: index - start + 1,
          node: {
            href: sanitizeLinkUrl(href),
            text,
            type: 'link'
          }
        };
      }
    }
    index++;
  }
  return undefined;
};
const parseImageToken = (value, start) => {
  if (value[start] !== '!' || value[start + 1] !== '[') {
    return undefined;
  }
  const textEnd = value.indexOf(']', start + 2);
  if (textEnd === -1) {
    return undefined;
  }
  if (value[textEnd + 1] !== '(') {
    return undefined;
  }
  let depth = 1;
  let index = textEnd + 2;
  while (index < value.length) {
    const current = value[index];
    if (current === '\n') {
      return undefined;
    }
    if (current === '(') {
      depth++;
    } else if (current === ')') {
      depth--;
      if (depth === 0) {
        const alt = value.slice(start + 2, textEnd);
        const src = value.slice(textEnd + 2, index);
        if (!src) {
          return undefined;
        }
        return {
          length: index - start + 1,
          node: {
            alt,
            src: sanitizeImageUrl(src),
            type: 'image'
          }
        };
      }
    }
    index++;
  }
  return undefined;
};
const parseBoldToken = (value, start) => {
  if (value[start] !== '*' || value[start + 1] !== '*') {
    return undefined;
  }
  const end = value.indexOf('**', start + 2);
  if (end === -1) {
    return undefined;
  }
  const text = value.slice(start + 2, end);
  if (!text || text.includes('\n')) {
    return undefined;
  }
  return {
    length: end - start + 2,
    node: {
      children: parseInlineNodes(text),
      type: 'bold'
    }
  };
};
const parseBoldItalicToken = (value, start) => {
  if (value[start] !== '*' || value[start + 1] !== '*' || value[start + 2] !== '*') {
    return undefined;
  }
  const end = value.indexOf('***', start + 3);
  if (end === -1) {
    return undefined;
  }
  const text = value.slice(start + 3, end);
  if (!text || text.includes('\n')) {
    return undefined;
  }
  return {
    length: end - start + 3,
    node: {
      children: [{
        children: parseInlineNodes(text),
        type: 'italic'
      }],
      type: 'bold'
    }
  };
};
const findItalicEnd = (value, start) => {
  let index = start + 1;
  while (index < value.length) {
    if (value[index] !== '*') {
      index++;
      continue;
    }
    if (value[index + 1] !== '*') {
      return index;
    }
    const boldEnd = value.indexOf('**', index + 2);
    if (boldEnd === -1) {
      return -1;
    }
    index = boldEnd + 2;
  }
  return -1;
};
const parseItalicToken = (value, start) => {
  if (value[start] !== '*' || value[start + 1] === '*') {
    return undefined;
  }
  const end = findItalicEnd(value, start);
  if (end === -1) {
    return undefined;
  }
  const text = value.slice(start + 1, end);
  if (!text) {
    return undefined;
  }
  return {
    length: end - start + 1,
    node: {
      children: parseInlineNodes(text),
      type: 'italic'
    }
  };
};
const parseStrikethroughToken = (value, start) => {
  if (value[start] !== '~' || value[start + 1] !== '~') {
    return undefined;
  }
  const end = value.indexOf('~~', start + 2);
  if (end === -1) {
    return undefined;
  }
  const text = value.slice(start + 2, end);
  if (!text || text.includes('\n')) {
    return undefined;
  }
  return {
    length: end - start + 2,
    node: {
      children: parseInlineNodes(text),
      type: 'strikethrough'
    }
  };
};
const parseInlineCodeToken = (value, start) => {
  if (value[start] !== '`') {
    return undefined;
  }
  const end = value.indexOf('`', start + 1);
  if (end === -1) {
    return undefined;
  }
  const codeText = value.slice(start + 1, end);
  if (!codeText || codeText.includes('\n')) {
    return undefined;
  }
  return {
    length: end - start + 1,
    node: {
      text: codeText,
      type: 'inline-code'
    }
  };
};
const parseMathToken = (value, start) => {
  if (value[start] !== '$') {
    return undefined;
  }
  const delimiterLength = value[start + 1] === '$' ? 2 : 1;
  const previous = value[start - 1];
  if (isAlphaNumeric(previous)) {
    return undefined;
  }
  const next = value[start + delimiterLength];
  if (!next || next === '.') {
    return undefined;
  }
  if (next === '(' && (value[start + delimiterLength + 1] === '"' || value[start + delimiterLength + 1] === "'")) {
    return undefined;
  }
  let index = start + delimiterLength;
  while (index < value.length) {
    if (value[index] === '\n') {
      return undefined;
    }
    const isClosed = delimiterLength === 2 ? value.startsWith('$$', index) : value[index] === '$';
    if (isClosed) {
      const body = value.slice(start + delimiterLength, index);
      const following = value[index + delimiterLength];
      if (!body || isAlphaNumeric(following)) {
        return undefined;
      }
      return {
        length: index - start + delimiterLength,
        node: {
          displayMode: delimiterLength === 2,
          text: body.trim(),
          type: 'math-inline'
        }
      };
    }
    if (value[index] === '\\') {
      index += 2;
      continue;
    }
    index++;
  }
  return undefined;
};
const parseInlineToken = (value, start) => {
  return parseImageToken(value, start) || parseLinkToken(value, start) || parseRawLinkToken(value, start) || parseBoldItalicToken(value, start) || parseBoldToken(value, start) || parseItalicToken(value, start) || parseLinkToken(value, start) || parseBoldItalicToken(value, start) || parseBoldToken(value, start) || parseItalicToken(value, start) || parseStrikethroughToken(value, start) || parseInlineCodeToken(value, start) || parseMathToken(value, start);
};
const parseInlineNodes = value => {
  const nodes = [];
  let textStart = 0;
  let index = 0;
  const pushText = end => {
    if (end <= textStart) {
      return;
    }
    nodes.push({
      text: value.slice(textStart, end),
      type: 'text'
    });
  };
  while (index < value.length) {
    const parsed = parseInlineToken(value, index);
    if (!parsed) {
      index++;
      continue;
    }
    pushText(index);
    nodes.push(parsed.node);
    index += parsed.length;
    textStart = index;
  }
  pushText(value.length);
  if (nodes.length === 0) {
    return [{
      text: value,
      type: 'text'
    }];
  }
  return nodes;
};

const markdownMathBlockDelimiter = '$$';
const escapedNewlineRegex = /\\r\\n|\\n/g;
const lineBreakRegex = /\r?\n/;
const tableDelimiterRegex = /\|\s*[-:]{3,}/;
const inlineTableCellRegex = /\|\s+\|/g;
const normalizeEscapedNewlines = value => {
  if (value.includes('\\n')) {
    return value.replaceAll(escapedNewlineRegex, '\n');
  }
  return value;
};
const normalizeInlineTables = value => {
  return value.split(lineBreakRegex).map(line => {
    if (!line.includes('|')) {
      return line;
    }
    if (!tableDelimiterRegex.test(line)) {
      return line;
    }
    return line.replaceAll(inlineTableCellRegex, '|\n|');
  }).join('\n');
};
const parseHeadingLine = line => {
  const trimmedStart = line.trimStart();
  let index = 0;
  while (index < trimmedStart.length && trimmedStart[index] === '#') {
    index++;
  }
  if (index === 0 || index > 6) {
    return undefined;
  }
  if (trimmedStart[index] !== ' ') {
    return undefined;
  }
  const text = trimmedStart.slice(index).trimStart();
  return {
    level: index,
    text
  };
};
const parseOrderedListItemLine = line => {
  let indentation = 0;
  while (indentation < line.length && line[indentation] === ' ') {
    indentation++;
  }
  let index = indentation;
  const firstDigit = index;
  while (index < line.length && line[index] >= '0' && line[index] <= '9') {
    index++;
  }
  if (index === firstDigit || line[index] !== '.') {
    return undefined;
  }
  index++;
  if (line[index] !== ' ') {
    return undefined;
  }
  while (index < line.length && line[index] === ' ') {
    index++;
  }
  return {
    indentation,
    text: line.slice(index)
  };
};
const parseUnorderedListItemLine = line => {
  let indentation = 0;
  while (indentation < line.length && line[indentation] === ' ') {
    indentation++;
  }
  const marker = line[indentation];
  if (marker !== '-' && marker !== '*') {
    return undefined;
  }
  let index = indentation + 1;
  if (line[index] !== ' ') {
    return undefined;
  }
  while (index < line.length && line[index] === ' ') {
    index++;
  }
  return {
    indentation,
    text: line.slice(index)
  };
};
const parseBlockQuoteLine = line => {
  const trimmedStart = line.trimStart();
  if (!trimmedStart.startsWith('>')) {
    return undefined;
  }
  const content = trimmedStart.slice(1);
  if (!content) {
    return '';
  }
  if (content.startsWith(' ')) {
    return content.slice(1);
  }
  return content;
};
const isThematicBreakLine = line => {
  const trimmedStart = line.trimStart();
  const leadingSpaces = line.length - trimmedStart.length;
  if (leadingSpaces > 3) {
    return false;
  }
  const trimmed = trimmedStart.trimEnd();
  if (!trimmed) {
    return false;
  }
  const marker = trimmed[0];
  if (marker !== '-' && marker !== '_' && marker !== '*') {
    return false;
  }
  let markerCount = 0;
  for (let i = 0; i < trimmed.length; i++) {
    const char = trimmed[i];
    if (char === marker) {
      markerCount++;
      continue;
    }
    if (char !== ' ') {
      return false;
    }
  }
  return markerCount >= 3;
};
const isTableRow = line => {
  const trimmed = line.trim();
  if (!trimmed.startsWith('|') || !trimmed.endsWith('|')) {
    return false;
  }
  return trimmed.length > 2;
};
const getTableCells = line => {
  const trimmed = line.trim();
  return trimmed.slice(1, -1).split('|').map(part => part.trim());
};
const scanBlockTokens = rawMessage => {
  const normalizedMessage = normalizeInlineTables(normalizeEscapedNewlines(rawMessage));
  const lines = normalizedMessage.split(lineBreakRegex);
  const tokens = [];
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    const trimmed = line.trim();
    if (!trimmed) {
      tokens.push({
        type: 'blank-line'
      });
      continue;
    }
    const blockQuoteLine = parseBlockQuoteLine(line);
    if (blockQuoteLine !== undefined) {
      tokens.push({
        text: blockQuoteLine,
        type: 'blockquote-line'
      });
      continue;
    }
    if (trimmed.startsWith('```')) {
      const language = trimmed.slice(3).trim();
      const codeLines = [];
      i++;
      while (i < lines.length && !lines[i].trim().startsWith('```')) {
        codeLines.push(lines[i]);
        i++;
      }
      if (language) {
        tokens.push({
          language,
          text: codeLines.join('\n'),
          type: 'code-block'
        });
      } else {
        tokens.push({
          text: codeLines.join('\n'),
          type: 'code-block'
        });
      }
      continue;
    }
    if (trimmed === markdownMathBlockDelimiter) {
      const endIndex = lines.findIndex((candidate, index) => {
        if (index <= i) {
          return false;
        }
        return candidate.trim() === markdownMathBlockDelimiter;
      });
      if (endIndex !== -1) {
        tokens.push({
          text: lines.slice(i + 1, endIndex).join('\n').trim(),
          type: 'math-block'
        });
        i = endIndex;
        continue;
      }
    }
    const heading = parseHeadingLine(line);
    if (heading) {
      tokens.push({
        level: heading.level,
        text: heading.text,
        type: 'heading-line'
      });
      continue;
    }
    if (isThematicBreakLine(line)) {
      tokens.push({
        type: 'thematic-break'
      });
      continue;
    }
    const ordered = parseOrderedListItemLine(line);
    if (ordered) {
      tokens.push({
        indentation: ordered.indentation,
        text: ordered.text,
        type: 'ordered-list-item-line'
      });
      continue;
    }
    const unordered = parseUnorderedListItemLine(line);
    if (unordered) {
      tokens.push({
        indentation: unordered.indentation,
        text: unordered.text,
        type: 'unordered-list-item-line'
      });
      continue;
    }
    if (isTableRow(line)) {
      tokens.push({
        cells: getTableCells(line),
        line,
        type: 'table-row-line'
      });
      continue;
    }
    tokens.push({
      text: line,
      type: 'paragraph-line'
    });
  }
  return tokens;
};

const isTableSeparatorCell = value => {
  if (!value) {
    return false;
  }
  let index = 0;
  if (value[index] === ':') {
    index++;
  }
  let dashCount = 0;
  while (index < value.length && value[index] === '-') {
    dashCount++;
    index++;
  }
  if (dashCount < 3) {
    return false;
  }
  if (index < value.length && value[index] === ':') {
    index++;
  }
  return index === value.length;
};
const isTableSeparatorToken = (token, expectedColumns) => {
  if (!token || token.type !== 'table-row-line') {
    return false;
  }
  if (token.cells.length !== expectedColumns) {
    return false;
  }
  return token.cells.every(isTableSeparatorCell);
};
const toTableCell = value => {
  return {
    children: parseInlineNodes(value),
    type: 'table-cell'
  };
};
const toTableRow = token => {
  return {
    cells: token.cells.map(toTableCell),
    type: 'table-row'
  };
};
const getEmptyTextNode = () => {
  return [{
    children: [{
      text: '',
      type: 'text'
    }],
    type: 'text'
  }];
};
const parseBlockTokens = tokens => {
  if (tokens.length === 0) {
    return getEmptyTextNode();
  }
  const nodes = [];
  let paragraphLines = [];
  let listItems = [];
  let listType = '';
  let orderedListPathStack = [];
  let canContinueOrderedListItemParagraph = false;
  const createListItem = (text, index) => {
    return {
      children: parseInlineNodes(text),
      ...(index === undefined ? {} : {
        index
      }),
      type: 'list-item'
    };
  };
  const getListItemAtPath = (items, path) => {
    let currentItems = items;
    let currentItem;
    for (const index of path) {
      currentItem = currentItems[index];
      if (!currentItem) {
        return undefined;
      }
      currentItems = currentItem.nestedItems || [];
    }
    return currentItem;
  };
  const appendNestedItemAtPath = (items, path, item, nestedListType) => {
    if (path.length === 0) {
      return [...items, item];
    }
    const [index, ...rest] = path;
    const current = items[index];
    if (!current) {
      return [...items];
    }
    const nextNestedItems = rest.length > 0 ? appendNestedItemAtPath(current.nestedItems || [], rest, item, nestedListType) : [...(current.nestedItems || []), item];
    const nextItem = {
      ...current,
      nestedItems: nextNestedItems,
      nestedListType
    };
    return [...items.slice(0, index), nextItem, ...items.slice(index + 1)];
  };
  const appendInlineChildrenAtPath = (items, path, children) => {
    if (path.length === 0) {
      return [...items];
    }
    const [index, ...rest] = path;
    const current = items[index];
    if (!current) {
      return [...items];
    }
    const lineBreakNode = {
      text: '\n',
      type: 'text'
    };
    const nextChildren = [...current.children, lineBreakNode, ...children];
    const nextItem = rest.length > 0 ? {
      ...current,
      nestedItems: appendInlineChildrenAtPath(current.nestedItems || [], rest, children)
    } : {
      ...current,
      children: nextChildren
    };
    return [...items.slice(0, index), nextItem, ...items.slice(index + 1)];
  };
  const flushParagraph = () => {
    if (paragraphLines.length === 0) {
      return;
    }
    nodes.push({
      children: parseInlineNodes(paragraphLines.join('\n')),
      type: 'text'
    });
    paragraphLines = [];
  };
  const flushList = () => {
    if (listItems.length === 0) {
      return;
    }
    nodes.push({
      items: listItems,
      type: listType || 'ordered-list'
    });
    listItems = [];
    listType = '';
    orderedListPathStack = [];
    canContinueOrderedListItemParagraph = false;
  };
  for (let i = 0; i < tokens.length; i++) {
    const token = tokens[i];
    if (token.type === 'blank-line') {
      flushParagraph();
      canContinueOrderedListItemParagraph = false;
      continue;
    }
    if (token.type === 'code-block') {
      flushList();
      flushParagraph();
      if (token.language) {
        nodes.push({
          codeTokens: highlightCode(token.text, token.language),
          language: token.language,
          text: token.text,
          type: 'code-block'
        });
      } else {
        nodes.push({
          codeTokens: highlightCode(token.text, undefined),
          text: token.text,
          type: 'code-block'
        });
      }
      continue;
    }
    if (token.type === 'math-block') {
      flushList();
      flushParagraph();
      nodes.push({
        text: token.text,
        type: 'math-block'
      });
      continue;
    }
    if (token.type === 'thematic-break') {
      flushList();
      flushParagraph();
      nodes.push({
        type: 'thematic-break'
      });
      continue;
    }
    if (token.type === 'blockquote-line') {
      flushList();
      flushParagraph();
      const lines = [];
      while (i < tokens.length && tokens[i].type === 'blockquote-line') {
        const quoteToken = tokens[i];
        if (quoteToken.type === 'blockquote-line') {
          lines.push(quoteToken.text);
        }
        i++;
      }
      i--;
      nodes.push({
        children: parseBlockTokens(scanBlockTokens(lines.join('\n'))),
        type: 'blockquote'
      });
      continue;
    }
    if (token.type === 'table-row-line') {
      const expectedColumns = token.cells.length;
      if (isTableSeparatorToken(tokens[i + 1], expectedColumns)) {
        flushList();
        flushParagraph();
        const rows = [];
        i += 2;
        while (i < tokens.length && tokens[i].type === 'table-row-line') {
          const rowToken = tokens[i];
          if (rowToken.type !== 'table-row-line') {
            break;
          }
          if (rowToken.cells.length === expectedColumns) {
            rows.push(toTableRow(rowToken));
          }
          i++;
        }
        i--;
        nodes.push({
          headers: token.cells.map(toTableCell),
          rows,
          type: 'table'
        });
        continue;
      }
      flushList();
      paragraphLines.push(token.line);
      continue;
    }
    if (token.type === 'ordered-list-item-line') {
      if (listType === 'ordered-list' && listItems.length > 0 && token.indentation > 0 && orderedListPathStack.length > 0) {
        const parentEntry = orderedListPathStack.toReversed().find(entry => entry.indentation < token.indentation);
        if (parentEntry) {
          const parentItem = getListItemAtPath(listItems, parentEntry.path);
          if (parentItem) {
            const nextIndex = parentItem.nestedItems?.length || 0;
            const nextItem = createListItem(token.text, nextIndex + 1);
            listItems = appendNestedItemAtPath(listItems, parentEntry.path, nextItem, 'ordered-list');
            const nextPath = [...parentEntry.path, nextIndex];
            orderedListPathStack = [...orderedListPathStack.filter(entry => entry.indentation < token.indentation), {
              indentation: token.indentation,
              path: nextPath
            }];
            canContinueOrderedListItemParagraph = true;
            continue;
          }
        }
      }
      if (listType && listType !== 'ordered-list') {
        flushList();
      }
      flushParagraph();
      listType = 'ordered-list';
      const nextIndex = listItems.length;
      const nextItem = createListItem(token.text, nextIndex + 1);
      listItems.push(nextItem);
      orderedListPathStack = [...orderedListPathStack.filter(entry => entry.indentation < token.indentation), {
        indentation: token.indentation,
        path: [nextIndex]
      }];
      canContinueOrderedListItemParagraph = true;
      continue;
    }
    if (token.type === 'unordered-list-item-line') {
      if (listType === 'ordered-list' && listItems.length > 0 && token.indentation > 0 && orderedListPathStack.length > 0) {
        const parentEntry = orderedListPathStack.toReversed().find(entry => entry.indentation < token.indentation);
        if (parentEntry) {
          const nextItem = createListItem(token.text);
          listItems = appendNestedItemAtPath(listItems, parentEntry.path, nextItem, 'unordered-list');
          canContinueOrderedListItemParagraph = false;
          continue;
        }
      }
      if (listType && listType !== 'unordered-list') {
        flushList();
      }
      flushParagraph();
      listType = 'unordered-list';
      listItems.push(createListItem(token.text));
      canContinueOrderedListItemParagraph = false;
      continue;
    }
    if (token.type === 'heading-line') {
      flushList();
      flushParagraph();
      nodes.push({
        children: parseInlineNodes(token.text),
        level: token.level,
        type: 'heading'
      });
      continue;
    }
    if (token.type === 'paragraph-line' && listType === 'ordered-list' && listItems.length > 0 && canContinueOrderedListItemParagraph) {
      const currentPath = orderedListPathStack.at(-1)?.path;
      if (currentPath) {
        listItems = appendInlineChildrenAtPath(listItems, currentPath, parseInlineNodes(token.text));
        continue;
      }
    }
    flushList();
    paragraphLines.push(token.text);
    canContinueOrderedListItemParagraph = false;
  }
  flushList();
  flushParagraph();
  return nodes.length === 0 ? getEmptyTextNode() : nodes;
};

const parseMessageContent = rawMessage => {
  return parseBlockTokens(scanBlockTokens(rawMessage));
};

const parseMessage = async rawMessage => {
  const parsedContent = parseMessageContent(rawMessage);
  const nextParsedContent = [];
  for (const node of parsedContent) {
    nextParsedContent.push(await parseMathNode(node));
  }
  return nextParsedContent;
};

const parseMessageContents = rawMessages => {
  return rawMessages.map(parseMessageContent);
};

const commandMap = {
  'ChatMessageParsing.parseMessageContent': parseMessageContent,
  'ChatMessageParsing.parseMessageContents': parseMessageContents,
  'ChatParser.parseMessage': parseMessage,
  'ChatParser.parseMessageContent': parseMessageContent,
  'ChatParser.parseMessageContents': parseMessageContents,
  'HandleMessagePort.handleMessagePort': handleMessagePort,
  initialize: initialize
};

const sendMessagePortToChatMathWorker = async port => {
  await sendMessagePortToChatMathWorker$1(port, 0);
};
const initializeChatMathWorker = async () => {
  const rpc = await create$2({
    commandMap: {},
    send: sendMessagePortToChatMathWorker
  });
  set(rpc);
};

const listen = async () => {
  await create$1({
    commandMap: commandMap
  });
  await initializeChatMathWorker();
};

const main = async () => {
  await listen();
};

main();
