diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 7163c3c..0000000
--- a/.eslintignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.cursorrules
-.cursorrules
diff --git a/.prettierignore b/.prettierignore
index d2ad7e5..f602757 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,3 +1,3 @@
 CODEOWNERS
 .yarn
-
+.changeset/**/*.md
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index b732917..0000000
--- a/.prettierrc
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "arrowParens": "always",
-  "bracketSameLine": true,
-  "bracketSpacing": true,
-  "embeddedLanguageFormatting": "auto",
-  "endOfLine": "lf",
-  "htmlWhitespaceSensitivity": "css",
-  "jsxSingleQuote": false,
-  "printWidth": 80,
-  "proseWrap": "preserve",
-  "quoteProps": "as-needed",
-  "semi": true,
-  "singleAttributePerLine": false,
-  "singleQuote": false,
-  "tabWidth": 2,
-  "trailingComma": "all",
-  "useTabs": false,
-  "plugins": ["prettier-plugin-packagejson"]
-}
diff --git a/.prettierrc.cjs b/.prettierrc.cjs
new file mode 100644
index 0000000..d20f3fe
--- /dev/null
+++ b/.prettierrc.cjs
@@ -0,0 +1,31 @@
+module.exports = {
+  arrowParens: "always",
+  bracketSameLine: true,
+  bracketSpacing: true,
+  embeddedLanguageFormatting: "auto",
+  endOfLine: "lf",
+  htmlWhitespaceSensitivity: "css",
+  jsxSingleQuote: false,
+  printWidth: 80,
+  proseWrap: "preserve",
+  quoteProps: "as-needed",
+  semi: true,
+  singleAttributePerLine: false,
+  singleQuote: false,
+  tabWidth: 2,
+  trailingComma: "all",
+  useTabs: false,
+  plugins: [
+    "prettier-plugin-packagejson",
+    "@ianvs/prettier-plugin-sort-imports",
+  ],
+  importOrder: [
+    "<BUILTIN_MODULES>",
+    "<THIRD_PARTY_MODULES>",
+    "^@(/.*)$",
+    "^@test(/.*)$",
+    "^@bench(/.*)$",
+    "^[.]",
+  ],
+  importOrderTypeScriptVersion: "5.6.3",
+};
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..f905bdb
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,78 @@
+import path from "node:path";
+import process from "node:process";
+import { fileURLToPath } from "node:url";
+import { includeIgnoreFile } from "@eslint/compat";
+import eslint from "@eslint/js";
+import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
+import globals from "globals";
+import tseslint from "typescript-eslint";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const gitignorePath = path.resolve(__dirname, ".gitignore");
+
+export default tseslint.config(
+  includeIgnoreFile(gitignorePath),
+  {
+    ignores: [".yarn/**/*"],
+  },
+  eslint.configs.recommended,
+  ...tseslint.configs.strictTypeChecked,
+  {
+    languageOptions: {
+      parserOptions: {
+        projectService: {
+          defaultProject: "tsconfig.json",
+        },
+        tsconfigRootDir: process.cwd(),
+      },
+    },
+  },
+  {
+    rules: {
+      "@typescript-eslint/consistent-type-exports": [
+        "error",
+        {
+          fixMixedExportsWithInlineTypeSpecifier: false,
+        },
+      ],
+      "@typescript-eslint/consistent-type-imports": "error",
+      "@typescript-eslint/no-deprecated": "warn",
+      "@typescript-eslint/no-explicit-any": "warn",
+      "@typescript-eslint/no-unused-vars": [
+        "error",
+        {
+          argsIgnorePattern: "^_",
+          destructuredArrayIgnorePattern: "^_",
+          ignoreRestSiblings: true,
+          varsIgnorePattern: "^_",
+        },
+      ],
+      "@typescript-eslint/restrict-template-expressions": [
+        "error",
+        {
+          allowNumber: true,
+        },
+      ],
+    },
+  },
+  {
+    files: ["**/*.cjs", "**/*.js"],
+    extends: [tseslint.configs.disableTypeChecked],
+    languageOptions: {
+      globals: {
+        ...globals.node,
+      },
+    },
+    rules: {
+      "@typescript-eslint/no-require-imports": "off",
+    },
+  },
+  {
+    files: ["**/*.test.ts"],
+    rules: {
+      "@typescript-eslint/no-non-null-assertion": "off",
+    },
+  },
+  eslintPluginPrettierRecommended,
+);
diff --git a/examples/express/package.json b/examples/express/package.json
index cbdfc9e..cdec32a 100644
--- a/examples/express/package.json
+++ b/examples/express/package.json
@@ -11,10 +11,10 @@
   "dependencies": {
     "@xmtp/agent-starter": "workspace:*",
     "axios": "^1.7.9",
-    "express": "^4.21.2"
+    "express": "^5.0.1"
   },
   "devDependencies": {
-    "@types/express": "^4.17.21",
+    "@types/express": "^5.0.0",
     "@types/node": "^22.10.9",
     "typescript": "^5.7.3"
   },
diff --git a/examples/express/src/index.ts b/examples/express/src/index.ts
index 7c17a62..7cc79dc 100644
--- a/examples/express/src/index.ts
+++ b/examples/express/src/index.ts
@@ -1,27 +1,28 @@
-import express from "express";
+import { xmtpClient, type XMTP } from "@xmtp/agent-starter";
+import express, { type Request, type Response } from "express";
 import fetch from "node-fetch";
-import { xmtpClient, XMTP } from "@xmtp/agent-starter";
 
 async function createServer(port: number, agent: XMTP) {
   const app = express();
   app.use(express.json());
 
   // Endpoint to RECEIVE encrypted messages
-  app.post("/receive", async (req, res) => {
-    try {
-      const { nonce, ciphertext, fromAddress } = req.body;
-      const decryptedMessage = await agent.decrypt(
-        nonce,
-        ciphertext,
-        fromAddress,
-      );
-
-      console.log(`Server on port ${port} decrypted:`, decryptedMessage);
-      return res.json({ success: true, decryptedMessage });
-    } catch (error) {
-      console.error("Error in /receive:", error);
-      return res.status(500).json({ error: (error as Error).message });
-    }
+  app.post("/receive", (req: Request, res: Response) => {
+    const { nonce, ciphertext, fromAddress } = req.body as {
+      nonce: string;
+      ciphertext: string;
+      fromAddress: string;
+    };
+    agent
+      .decrypt(nonce, ciphertext, fromAddress)
+      .then((decryptedMessage) => {
+        console.log(`Server on port ${port} decrypted:`, decryptedMessage);
+        res.json({ success: true, decryptedMessage });
+      })
+      .catch((error: unknown) => {
+        console.error("Error in /receive:", error);
+        res.status(500).json({ error: (error as Error).message });
+      });
   });
 
   return new Promise((resolve) => {
@@ -66,8 +67,8 @@ async function main() {
       method: "POST",
       headers: { "Content-Type": "application/json" },
       body: JSON.stringify({
-        nonce: nonce as string,
-        ciphertext: ciphertext as string,
+        nonce: nonce,
+        ciphertext: ciphertext,
         fromAddress: agentA.address as string, // the "sender"
       }),
     });
diff --git a/examples/gated-group/src/index.ts b/examples/gated-group/src/index.ts
index c9d4c41..cc6eb42 100644
--- a/examples/gated-group/src/index.ts
+++ b/examples/gated-group/src/index.ts
@@ -1,6 +1,6 @@
-import { Client, Message, XMTP, xmtpClient } from "@xmtp/agent-starter";
-import express from "express";
+import { xmtpClient, type Client, type Message } from "@xmtp/agent-starter";
 import { Alchemy, Network } from "alchemy-sdk";
+import express, { type Request, type Response } from "express";
 
 const settings = {
   apiKey: process.env.ALCHEMY_API_KEY, // Replace with your Alchemy API key
@@ -13,17 +13,18 @@ async function main() {
     onMessage: async (message: Message) => {
       if (message.typeId !== "text") return;
 
-      if (message?.content.text === "/create") {
+      if (message.content.text === "/create") {
         console.log("Creating group");
         const group = await createGroup(
-          agent?.client,
-          message?.sender?.address as string,
-          agent?.address as string,
+          agent.client,
+          message.sender.address,
+          agent.address as string,
         );
         console.log("Group created", group?.id);
         await agent.send({
           message: `Group created!\n- ID: ${group?.id}\n- Group URL: https://converse.xyz/group/${group?.id}: \n- This url will deelink to the group inside Converse\n- Once in the other group you can share the invite with your friends.`,
           originalMessage: message,
+          metadata: {},
         });
         return;
       } else {
@@ -31,6 +32,7 @@ async function main() {
           message:
             "👋 Welcome to the Gated Bot Group!\nTo get started, type /create to set up a new group. 🚀\nThis example will check if the user has a particular nft and add them to the group if they do.\nOnce your group is created, you'll receive a unique Group ID and URL.\nShare the URL with friends to invite them to join your group!",
           originalMessage: message,
+          metadata: {},
         });
       }
     },
@@ -39,20 +41,23 @@ async function main() {
   // Endpoint to add wallet address to a group from an external source
   const app = express();
   app.use(express.json());
-  app.post("/add-wallet", async (req, res) => {
-    try {
-      const { walletAddress, groupId } = req.body;
-      const verified = true; // (await checkNft(walletAddress, "XMTPeople"));
-      if (!verified) {
-        console.log("User cant be added to the group");
-        return;
-      } else {
-        await addToGroup(groupId, agent?.client as Client, walletAddress, true);
+  app.post("/add-wallet", (req: Request, res: Response) => {
+    const { walletAddress, groupId } = req.body as {
+      walletAddress: string;
+      groupId: string;
+    };
+    // const verified = true; // (await checkNft(walletAddress, "XMTPeople"));
+    // if (!verified) {
+    //   console.log("User cant be added to the group");
+    //   return;
+    // } else {
+    addToGroup(groupId, agent.client as Client, walletAddress, true)
+      .then(() => {
         res.status(200).send("success");
-      }
-    } catch (error: any) {
-      res.status(400).send(error.message);
-    }
+      })
+      .catch((error: unknown) => {
+        res.status(400).send((error as Error).message);
+      });
   });
   // Start the servfalcheer
   const PORT = process.env.PORT || 3000;
@@ -63,7 +68,7 @@ async function main() {
     );
   });
   console.log(
-    `XMTP agent initialized on ${agent?.address}\nSend a message on https://xmtp.chat or https://converse.xyz/dm/${agent?.address}`,
+    `XMTP agent initialized on ${agent.address}\nSend a message on https://xmtp.chat or https://converse.xyz/dm/${agent.address}`,
   );
 }
 
@@ -80,15 +85,15 @@ export async function createGroup(
   try {
     let senderInboxId = "";
     await client.conversations.sync();
-    const conversations = await client.conversations.list();
+    const conversations = client.conversations.list();
     console.log("Conversations", conversations.length);
-    const group = await client?.conversations.newGroup([
+    const group = await client.conversations.newGroup([
       senderAddress,
       clientAddress,
     ]);
-    console.log("Group created", group?.id);
+    console.log("Group created", group.id);
     const members = await group.members();
-    const senderMember = members.find((member: any) =>
+    const senderMember = members.find((member) =>
       member.accountAddresses.includes(senderAddress.toLowerCase()),
     );
     if (senderMember) {
@@ -98,10 +103,7 @@ export async function createGroup(
       console.log("Sender not found in members list");
     }
     await group.addSuperAdmin(senderInboxId);
-    console.log(
-      "Sender is superAdmin",
-      await group.isSuperAdmin(senderInboxId),
-    );
+    console.log("Sender is superAdmin", group.isSuperAdmin(senderInboxId));
     await group.send(`Welcome to the new group!`);
     await group.send(`You are now the admin of this group as well as the bot`);
     return group;
@@ -117,15 +119,14 @@ export async function removeFromGroup(
   senderAddress: string,
 ): Promise<void> {
   try {
-    let lowerAddress = senderAddress.toLowerCase();
+    const lowerAddress = senderAddress.toLowerCase();
     const isOnXMTP = await client.canMessage([lowerAddress]);
     console.warn("Checking if on XMTP: ", isOnXMTP);
-    if (!isOnXMTP) {
+    if (!isOnXMTP.get(lowerAddress)) {
       console.error("You don't seem to have a v3 identity ");
       return;
     }
-    const conversation =
-      await client.conversations.getConversationById(groupId);
+    const conversation = client.conversations.getConversationById(groupId);
     console.warn("removing from group", conversation?.id);
     await conversation?.sync();
     await conversation?.removeMembers([lowerAddress]);
@@ -137,7 +138,7 @@ export async function removeFromGroup(
     let wasRemoved = true;
     if (members) {
       for (const member of members) {
-        let lowerMemberAddress = member.accountAddresses[0].toLowerCase();
+        const lowerMemberAddress = member.accountAddresses[0].toLowerCase();
         if (lowerMemberAddress === lowerAddress) {
           wasRemoved = false;
           break;
@@ -162,13 +163,13 @@ export async function addToGroup(
   asAdmin: boolean = false,
 ): Promise<void> {
   try {
-    let lowerAddress = address.toLowerCase();
+    const lowerAddress = address.toLowerCase();
     const isOnXMTP = await client.canMessage([lowerAddress]);
-    if (!isOnXMTP) {
+    if (!isOnXMTP.get(lowerAddress)) {
       console.error("You don't seem to have a v3 identity ");
       return;
     }
-    const group = await client.conversations.getConversationById(groupId);
+    const group = client.conversations.getConversationById(groupId);
     console.warn("Adding to group", group?.id);
     await group?.sync();
     await group?.addMembers([lowerAddress]);
@@ -182,7 +183,7 @@ export async function addToGroup(
 
     if (members) {
       for (const member of members) {
-        let lowerMemberAddress = member.accountAddresses[0].toLowerCase();
+        const lowerMemberAddress = member.accountAddresses[0].toLowerCase();
         if (lowerMemberAddress === lowerAddress) {
           console.warn("Member exists", lowerMemberAddress);
           return;
@@ -204,11 +205,11 @@ export async function checkNft(
     const nfts = await alchemy.nft.getNftsForOwner(walletAddress);
 
     const ownsNft = nfts.ownedNfts.some(
-      (nft: any) =>
-        nft.contract.name.toLowerCase() === collectionSlug.toLowerCase(),
+      (nft) =>
+        nft.contract.name?.toLowerCase() === collectionSlug.toLowerCase(),
     );
     console.log("is the nft owned: ", ownsNft);
-    return ownsNft as boolean;
+    return ownsNft;
   } catch (error) {
     console.error("Error fetching NFTs from Alchemy:", error);
   }
diff --git a/examples/gm/src/index.ts b/examples/gm/src/index.ts
index 13d2ede..1df1932 100644
--- a/examples/gm/src/index.ts
+++ b/examples/gm/src/index.ts
@@ -1,21 +1,22 @@
-import { Message, xmtpClient } from "@xmtp/agent-starter";
+import { xmtpClient, type Message } from "@xmtp/agent-starter";
 
 async function main() {
   const agent = await xmtpClient({
     encryptionKey: process.env.ENCRYPTION_KEY as string,
     onMessage: async (message: Message) => {
       console.log(
-        `Decoded message: ${message?.content.text} by ${message.sender.address}`,
+        `Decoded message: ${message.content.text} by ${message.sender.address}`,
       );
       await agent.send({
         message: "gm",
         originalMessage: message,
+        metadata: {},
       });
     },
   });
 
   console.log(
-    `XMTP agent initialized on ${agent?.address}\nSend a message on https://xmtp.chat or https://converse.xyz/dm/${agent?.address}`,
+    `XMTP agent initialized on ${agent.address}\nSend a message on https://xmtp.chat or https://converse.xyz/dm/${agent.address}`,
   );
 }
 
diff --git a/examples/gpt/src/index.ts b/examples/gpt/src/index.ts
index bd67f96..0d147d1 100644
--- a/examples/gpt/src/index.ts
+++ b/examples/gpt/src/index.ts
@@ -1,4 +1,4 @@
-import { Message, xmtpClient } from "@xmtp/agent-starter";
+import { xmtpClient, type Message } from "@xmtp/agent-starter";
 import OpenAI from "openai";
 
 // Initialize OpenAI API
@@ -9,7 +9,7 @@ async function main() {
     encryptionKey: process.env.ENCRYPTION_KEY as string,
     onMessage: async (message: Message) => {
       console.log(
-        `Decoded message: ${message?.content.text} by ${message.sender.address}`,
+        `Decoded message: ${message.content.text} by ${message.sender.address}`,
       );
 
       // Send message content to GPT API
@@ -19,7 +19,7 @@ async function main() {
           { role: "developer", content: "You are a helpful assistant." },
           {
             role: "user",
-            content: message?.content.text ?? "",
+            content: message.content.text ?? "",
           },
         ],
       });
@@ -30,12 +30,13 @@ async function main() {
       await agent.send({
         message: gptMessage ?? "",
         originalMessage: message,
+        metadata: {},
       });
     },
   });
 
   console.log(
-    `XMTP agent initialized on ${agent?.address}\nSend a message on https://xmtp.chat or https://converse.xyz/dm/${agent?.address}`,
+    `XMTP agent initialized on ${agent.address}\nSend a message on https://xmtp.chat or https://converse.xyz/dm/${agent.address}`,
   );
 }
 
diff --git a/package.json b/package.json
index a00592b..3ce7090 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,9 @@
     "clean": "turbo run clean && yarn cache clean && find examples -name '.data' -type d -exec rm -rf {} +",
     "dev": "cd packages/agent-starter && yarn build:watch",
     "examples": "node scripts/examples.js",
-    "format": "turbo run format",
+    "format": "prettier -w .",
+    "format:check": "prettier -c .",
+    "lint": "yarn build && eslint .",
     "publish": "yarn build && changeset publish",
     "test": "FORCE_COLOR=1 turbo run test",
     "typecheck": "FORCE_COLOR=1 turbo run typecheck"
@@ -26,10 +28,19 @@
     "readline-sync": "^1.4.10"
   },
   "devDependencies": {
+    "@eslint/compat": "^1.2.5",
+    "@eslint/js": "^9.18.0",
+    "@ianvs/prettier-plugin-sort-imports": "^4.4.1",
+    "@types/eslint__js": "^8.42.3",
+    "eslint": "^9.18.0",
+    "eslint-config-prettier": "^10.0.1",
+    "eslint-plugin-prettier": "^5.2.3",
+    "globals": "^15.14.0",
     "prettier": "^3.4.2",
     "prettier-plugin-packagejson": "^2.5.8",
     "turbo": "^2.3.4",
-    "typescript": "^5.7.3"
+    "typescript": "^5.7.3",
+    "typescript-eslint": "^8.21.0"
   },
   "packageManager": "yarn@4.6.0",
   "engines": {
diff --git a/packages/agent-starter/package.json b/packages/agent-starter/package.json
index 84ae78b..43b01b1 100644
--- a/packages/agent-starter/package.json
+++ b/packages/agent-starter/package.json
@@ -40,7 +40,6 @@
     "@vitest/coverage-v8": "^2.1.8",
     "dotenv": "^16.4.7",
     "node-fetch": "^3.3.2",
-    "prettier": "^3.4.2",
     "rollup": "^4.31.0",
     "rollup-plugin-dts": "^6.1.1",
     "ts-node": "^10.9.2",
diff --git a/packages/agent-starter/rollup.config.js b/packages/agent-starter/rollup.config.js
index e36e761..a828b32 100644
--- a/packages/agent-starter/rollup.config.js
+++ b/packages/agent-starter/rollup.config.js
@@ -14,13 +14,13 @@ const external = [
   "@xmtp/node-bindings",
   "cross-fetch",
   "node-fetch",
-  "path",
-  "crypto",
+  "node:path",
+  "node:crypto",
   "viem",
   "dotenv",
   "viem/accounts",
-  "fs/promises",
-  "fs",
+  "node:fs/promises",
+  "node:fs",
   "viem/chains",
   "dotenv/config",
 ];
diff --git a/packages/agent-starter/src/content-types/agent-message.ts b/packages/agent-starter/src/content-types/agent-message.ts
index c0ae9ec..93f25c8 100644
--- a/packages/agent-starter/src/content-types/agent-message.ts
+++ b/packages/agent-starter/src/content-types/agent-message.ts
@@ -1,8 +1,9 @@
-import { ContentTypeId } from "@xmtp/content-type-primitives";
-import type {
-  ContentCodec,
-  EncodedContent,
+import {
+  ContentTypeId,
+  type ContentCodec,
+  type EncodedContent,
 } from "@xmtp/content-type-primitives";
+import type { Metadata } from "../lib/types";
 
 // Create a unique identifier for your content type
 export const ContentTypeAgentMessage = new ContentTypeId({
@@ -15,14 +16,11 @@ export const ContentTypeAgentMessage = new ContentTypeId({
 // Define the message structure with metadata
 export class AgentMessage {
   public text: string;
-  public metadata: {
-    [key: string]: any; // Allow for flexible metadata
-  };
+  public metadata: Metadata;
 
-  constructor(text: string, metadata: any) {
+  constructor(text: string, metadata: Metadata) {
     this.text = text;
     this.metadata = {
-      timestamp: Date.now(),
       isAgent: true,
       ...metadata,
     };
@@ -45,7 +43,10 @@ export class AgentMessageCodec implements ContentCodec<AgentMessage> {
 
   decode(encodedContent: EncodedContent): AgentMessage {
     const decoded = new TextDecoder().decode(encodedContent.content);
-    const { text, metadata } = JSON.parse(decoded);
+    const { text, metadata } = JSON.parse(decoded) as {
+      text: string;
+      metadata: Metadata;
+    };
     return new AgentMessage(text, metadata);
   }
 
diff --git a/packages/agent-starter/src/index.ts b/packages/agent-starter/src/index.ts
index 5b54c41..1c36ce9 100644
--- a/packages/agent-starter/src/index.ts
+++ b/packages/agent-starter/src/index.ts
@@ -1,3 +1,3 @@
 export * from "./lib/xmtp.js";
-export * from "./lib/types.js";
+export type * from "./lib/types.js";
 export * from "./content-types/agent-message.js";
diff --git a/packages/agent-starter/src/lib/types.ts b/packages/agent-starter/src/lib/types.ts
index 0bc85dc..c590a90 100644
--- a/packages/agent-starter/src/lib/types.ts
+++ b/packages/agent-starter/src/lib/types.ts
@@ -1,13 +1,19 @@
-import { privateKeyToAccount } from "viem/accounts";
-import { createWalletClient } from "viem";
-import { ClientOptions, Client } from "@xmtp/node-sdk";
+import type { Client, ClientOptions } from "@xmtp/node-sdk";
+import type { createWalletClient } from "viem";
+import type { privateKeyToAccount } from "viem/accounts";
+
 export type { Client };
 export type { ClientOptions };
 
+export type Metadata = {
+  isAgent?: boolean;
+  [key: string]: any;
+};
+
 export type agentMessage = {
   message: string;
   originalMessage?: Message;
-  metadata?: any;
+  metadata: Metadata;
   receivers?: string[];
   typeId?:
     | "text"
@@ -53,23 +59,23 @@ export type Message = {
   sent: Date; // Date when the message was sent
   isDM: boolean; // Whether the message is a direct message
   content: {
-    text?: string | undefined; // Text content of the message
-    reply?: string | undefined; // Reply content if the message is a reply
-    previousMsg?: string | undefined; // Reference to the previous message
-    attachment?: string | undefined; // Attachment content if the message is an attachment
-    react?: string | undefined; // Reaction content if the message is a reaction
-    content?: any | undefined; // Any other content
-    metadata?: any | undefined; // Metadata for the message
-    remoteAttachment?: any | undefined; // Remote attachment content if the message is a remote attachment
-    readReceipt?: any | undefined; // Read receipt content if the message is a read receipt
-    agentMessage?: any | undefined; // Agent message content if the message is an agent message
-    reaction?: any | undefined; // Reaction content if the message is a reaction
-    params?: any | undefined; // Parameters for the message
-    reference?: string | undefined; // Reference ID for the message
-    skill?: string | undefined; // Skill associated with the message
+    text?: string; // Text content of the message
+    reply?: string; // Reply content if the message is a reply
+    previousMsg?: string; // Reference to the previous message
+    attachment?: string; // Attachment content if the message is an attachment
+    react?: string; // Reaction content if the message is a reaction
+    content: any; // Any other content
+    metadata?: any; // Metadata for the message
+    remoteAttachment?: any; // Remote attachment content if the message is a remote attachment
+    readReceipt?: any; // Read receipt content if the message is a read receipt
+    agentMessage?: any; // Agent message content if the message is an agent message
+    reaction?: any; // Reaction content if the message is a reaction
+    params?: any; // Parameters for the message
+    reference?: string; // Reference ID for the message
+    skill?: string; // Skill associated with the message
     any?: any; // Any other content
   };
-  group?: Conversation | undefined; // Group the message belongs to
+  group?: Conversation; // Group the message belongs to
   sender: User; // Sender of the message
   typeId: string; // Type identifier for the message
   client: {
diff --git a/packages/agent-starter/src/lib/xmtp.ts b/packages/agent-starter/src/lib/xmtp.ts
index a9974c6..2a65202 100644
--- a/packages/agent-starter/src/lib/xmtp.ts
+++ b/packages/agent-starter/src/lib/xmtp.ts
@@ -1,45 +1,51 @@
-import dotenv from "dotenv";
-dotenv.config();
-import {
-  DecodedMessage,
-  Client,
-  ClientOptions,
-  XmtpEnv,
-  Conversation,
-} from "@xmtp/node-sdk";
-import { ContentTypeReply, Reply, ReplyCodec } from "@xmtp/content-type-reply";
+import crypto, { getRandomValues } from "node:crypto";
+import * as fs from "node:fs";
+import { readFile } from "node:fs/promises";
+import path from "node:path";
 import {
   ContentTypeReaction,
-  Reaction,
   ReactionCodec,
+  type Reaction,
 } from "@xmtp/content-type-reaction";
-import { ContentTypeText, TextCodec } from "@xmtp/content-type-text";
+import { ReadReceiptCodec } from "@xmtp/content-type-read-receipt";
 import {
-  Attachment,
   AttachmentCodec,
   ContentTypeRemoteAttachment,
   RemoteAttachmentCodec,
+  type Attachment,
+  type RemoteAttachment,
 } from "@xmtp/content-type-remote-attachment";
 import {
-  ContentTypeReadReceipt,
-  ReadReceiptCodec,
-} from "@xmtp/content-type-read-receipt";
+  ContentTypeReply,
+  ReplyCodec,
+  type Reply,
+} from "@xmtp/content-type-reply";
+import { ContentTypeText, TextCodec } from "@xmtp/content-type-text";
+import {
+  Client,
+  type ClientOptions,
+  type Conversation,
+  type DecodedMessage,
+} from "@xmtp/node-sdk";
+import dotenv from "dotenv";
+import fetch from "node-fetch";
+import { createWalletClient, http, isAddress, toBytes, toHex } from "viem";
+import { privateKeyToAccount } from "viem/accounts";
+import { mainnet } from "viem/chains";
 import {
   AgentMessage,
   AgentMessageCodec,
   ContentTypeAgentMessage,
 } from "../content-types/agent-message.js";
-import { createWalletClient, http, isAddress, toBytes, toHex } from "viem";
-import { privateKeyToAccount } from "viem/accounts";
-import { mainnet } from "viem/chains";
+import type {
+  Agent,
+  agentMessage,
+  Message,
+  User,
+  UserReturnType,
+} from "./types.js";
 
-import { getRandomValues } from "crypto";
-import path from "path";
-import { Message, agentMessage, UserReturnType, User, Agent } from "./types.js";
-import { readFile } from "fs/promises";
-import * as fs from "fs";
-import fetch from "node-fetch";
-import crypto from "crypto";
+dotenv.config();
 
 export async function xmtpClient(agent?: Agent): Promise<XMTP> {
   let xmtp: XMTP | null = null; // Ensure a single instance
@@ -61,7 +67,7 @@ export class XMTP {
   }
 
   async init(): Promise<XMTP> {
-    let suffix = this.agent?.name ? "_" + this.agent?.name : "";
+    const suffix = this.agent?.name ? "_" + this.agent.name : "";
     let fixedKey =
       this.agent?.fixedKey ??
       process.env["FIXED_KEY" + suffix] ??
@@ -81,21 +87,21 @@ export class XMTP {
 
     const user = createUser(encryptionKey);
 
-    let env = this.agent?.config?.env as XmtpEnv;
-    if (!env) env = "production" as XmtpEnv;
+    let env = this.agent?.config?.env;
+    if (!env) env = "production";
 
-    let volumePath =
+    const volumePath =
       process.env.RAILWAY_VOLUME_MOUNT_PATH ??
       this.agent?.config?.path ??
       ".data/xmtp";
 
-    if (fs && !fs.existsSync(volumePath)) {
+    if (!fs.existsSync(volumePath)) {
       fs.mkdirSync(volumePath, { recursive: true });
     }
 
     const defaultConfig: ClientOptions = {
       env: env,
-      dbPath: `${volumePath}/${user.account?.address.toLowerCase()}-${env}`,
+      dbPath: `${volumePath}/${user.account.address.toLowerCase()}-${env}`,
       codecs: [
         new TextCodec(),
         new ReactionCodec(),
@@ -119,7 +125,7 @@ export class XMTP {
     this.client = client;
     this.inboxId = client.inboxId;
     this.address = client.accountAddress;
-    Promise.all([streamMessages(this.onMessage, client, this)]);
+    void streamMessages(this.onMessage, client, this);
     this.saveKeys(suffix, fixedKey, encryptionKey);
     return this;
   }
@@ -187,10 +193,6 @@ export class XMTP {
       } else {
         // Handle file path
         const file = await readFile(source);
-        if (!file) {
-          console.error("File operations not supported in this environment");
-          return undefined;
-        }
 
         // Check file size
         if (file.length > MAX_SIZE) {
@@ -216,13 +218,7 @@ export class XMTP {
   }
 
   async send(agentMessage: agentMessage) {
-    let contentType:
-      | typeof ContentTypeReaction
-      | typeof ContentTypeText
-      | typeof ContentTypeRemoteAttachment
-      | typeof ContentTypeAgentMessage
-      | typeof ContentTypeReadReceipt
-      | typeof ContentTypeReply = ContentTypeText;
+    let contentType: typeof ContentTypeReaction = ContentTypeText;
 
     let message: any;
     if (!agentMessage.typeId || agentMessage.typeId === "text") {
@@ -247,10 +243,7 @@ export class XMTP {
         reference: agentMessage.originalMessage?.id,
       } as Reply;
     } else if (agentMessage.typeId === "agent_message") {
-      message = new AgentMessage(
-        agentMessage.message,
-        agentMessage.metadata,
-      ) as AgentMessage;
+      message = new AgentMessage(agentMessage.message, agentMessage.metadata);
       contentType = ContentTypeAgentMessage;
     }
     if (!agentMessage.receivers || agentMessage.receivers.length == 0) {
@@ -258,15 +251,14 @@ export class XMTP {
         agentMessage.originalMessage?.sender.inboxId as string,
       ];
     }
-    for (let receiverAddress of agentMessage.receivers) {
-      let inboxId = !isAddress(receiverAddress)
+    for (const receiverAddress of agentMessage.receivers) {
+      const inboxId = !isAddress(receiverAddress)
         ? receiverAddress
         : await this.client?.getInboxIdByAddress(receiverAddress);
       if (!inboxId) {
         throw new Error("Invalid receiver address");
       }
-      let conversation =
-        await this.client?.conversations.getDmByInboxId(inboxId);
+      let conversation = this.client?.conversations.getDmByInboxId(inboxId);
       if (!conversation) {
         conversation = await this.client?.conversations.newDm(receiverAddress);
       }
@@ -274,29 +266,23 @@ export class XMTP {
     }
   }
 
-  async getConversationFromMessage(
-    message: DecodedMessage | null | undefined,
-  ): Promise<Conversation | null | undefined> {
-    return await this.client?.conversations.getConversationById(
-      (message as DecodedMessage)?.conversationId as string,
+  getConversationFromMessage(message: DecodedMessage | null | undefined) {
+    return this.client?.conversations.getConversationById(
+      (message as DecodedMessage).conversationId,
     );
   }
 
-  isConversation(conversation: Conversation): conversation is Conversation {
-    return conversation?.id !== undefined;
-  }
-
   getConversationKey(message: Message) {
-    return `${message?.group?.id}`;
+    return `${message.group?.id}`;
   }
 
   getUserConversationKey(message: Message) {
-    return `${message?.group?.id}`;
+    return `${message.group?.id}`;
   }
 
-  async getMessageById(reference: string) {
-    return this.client?.conversations?.getMessageById?.bind(
-      this.client?.conversations,
+  getMessageById(reference: string) {
+    return this.client?.conversations.getMessageById.bind(
+      this.client.conversations,
     )(reference);
   }
 
@@ -318,14 +304,14 @@ export class XMTP {
       }
 
       // List all direct message conversations
-      const conversations = await this.client?.conversations.listDms();
+      const conversations = this.client?.conversations.listDms();
       if (!conversations) {
         console.error(`No conversations found ${inboxId}`);
         return undefined;
       }
 
       // Find the conversation with the matching inbox ID
-      const conversation = conversations?.find(
+      const conversation = conversations.find(
         (c: Conversation) => c.dmPeerInboxId === inboxId,
       );
 
@@ -335,8 +321,8 @@ export class XMTP {
       }
 
       // Retrieve all messages from the conversation
-      const messages = await conversation?.messages();
-      if (!messages) {
+      const messages = await conversation.messages();
+      if (!messages.length) {
         console.error(`No messages found ${conversation.id}`);
         return undefined;
       }
@@ -347,7 +333,7 @@ export class XMTP {
         .find(
           (msg: DecodedMessage) =>
             msg.contentType?.typeId === "agent_message" &&
-            msg.content.metadata.sharedSecret,
+            (msg.content as AgentMessage).metadata.sharedSecret,
         );
       if (!lastAgentMessageSharedSecret) {
         console.error(`No shared secret found ${conversation.id}`);
@@ -355,10 +341,12 @@ export class XMTP {
       }
 
       // Return the shared secret
-      return lastAgentMessageSharedSecret?.content?.metadata
+      return (lastAgentMessageSharedSecret.content as AgentMessage).metadata
         .sharedSecret as string;
     } catch (error) {
-      console.error(`Error getting last agent message shared secret: ${error}`);
+      console.error(
+        `Error getting last agent message shared secret: ${(error as Error).message}`,
+      );
       return undefined;
     }
   }
@@ -377,7 +365,7 @@ export class XMTP {
           "No shared secret found on encrypt, generating new one through a handshake",
         );
         sharedSecret = crypto.randomBytes(32).toString("hex");
-        let agentMessage: agentMessage = {
+        const agentMessage: agentMessage = {
           message: "",
           metadata: {
             sharedSecret,
@@ -387,15 +375,12 @@ export class XMTP {
         };
 
         // Send a handshake message with the new shared secret
-        await this.send(agentMessage as agentMessage);
+        await this.send(agentMessage);
         console.log("Sent handshake message");
       }
 
       // Convert the shared secret to a buffer
-      const bufferFromSharedSecret = Buffer.from(sharedSecret as string, "hex");
-      if (!bufferFromSharedSecret) {
-        throw new Error("encrypt: No buffer secret found");
-      }
+      const bufferFromSharedSecret = Buffer.from(sharedSecret, "hex");
 
       // Generate a nonce and create a cipher for encryption
       const nonce = crypto.randomBytes(12);
@@ -451,7 +436,7 @@ export class XMTP {
       }
 
       // Convert the shared secret to a buffer
-      const bufferFromSharedSecret = Buffer.from(sharedSecret as string, "hex");
+      const bufferFromSharedSecret = Buffer.from(sharedSecret, "hex");
 
       // Create a decipher for decryption
       const decipher = crypto.createDecipheriv(
@@ -482,43 +467,37 @@ async function streamMessages(
   client: Client | undefined,
   xmtp: XMTP,
 ) {
-  while (true) {
-    try {
-      await client?.conversations.sync();
-      await client?.conversations.list();
-      const stream = await client?.conversations.streamAllMessages();
-      if (stream) {
-        if (xmtp.agent?.config?.hideInitLogMessage !== true) {
-        }
-        for await (const message of stream) {
-          let conversation = await xmtp.getConversationFromMessage(message);
-          if (message && conversation) {
-            try {
-              const { senderInboxId, kind } = message as DecodedMessage;
-
-              if (
-                // Filter out membership_change messages and sent by one
-                senderInboxId?.toLowerCase() ===
-                  client?.inboxId.toLowerCase() &&
-                kind !== "membership_change"
-              ) {
-                continue;
-              }
-              const parsedMessage = await parseMessage(
-                message,
-                conversation,
-                client as Client,
-              );
-              await onMessage(parsedMessage as Message);
-            } catch (e) {
-              console.log(`error`, e);
+  try {
+    await client?.conversations.sync();
+    const stream = await client?.conversations.streamAllMessages();
+    if (stream) {
+      for await (const message of stream) {
+        const conversation = xmtp.getConversationFromMessage(message);
+        if (message && conversation) {
+          try {
+            const { senderInboxId, kind } = message;
+
+            if (
+              // Filter out membership_change messages and sent by one
+              senderInboxId.toLowerCase() === client?.inboxId.toLowerCase() &&
+              kind !== "membership_change"
+            ) {
+              continue;
             }
+            const parsedMessage = await parseMessage(
+              message,
+              conversation,
+              client as Client,
+            );
+            await onMessage(parsedMessage as Message);
+          } catch (e) {
+            console.log(`error`, e);
           }
         }
       }
-    } catch (err) {
-      console.error(`Stream encountered an error:`, err);
     }
+  } catch (err) {
+    console.error(`Stream encountered an error:`, err);
   }
 }
 
@@ -553,46 +532,53 @@ export async function parseMessage(
   conversation: Conversation | undefined,
   client: Client,
 ): Promise<Message | undefined> {
-  if (message == null) return undefined;
-  let typeId = message.contentType?.typeId ?? "text";
-  let content = message.content;
+  if (message === null || message === undefined) return undefined;
+  const typeId = message.contentType?.typeId ?? "text";
+  let content: any;
   if (typeId == "text") {
     content = {
-      text: content,
+      text: message.content as string,
     };
   } else if (typeId == "reply") {
-    let previousMsg = await client.conversations.getMessageById(
-      message.content?.reference as string,
+    const previousMsg = client.conversations.getMessageById(
+      (message.content as Reply).reference,
     );
+    const messageContent = message.content as Reply;
     content = {
-      previousMsg: previousMsg,
-      reply: content.content,
-      text: content.content,
-      reference: content.reference,
+      previousMsg,
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+      reply: messageContent.content,
+      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+      text: messageContent.content,
+      reference: messageContent.reference,
     };
   } else if (typeId == "reaction") {
+    const messageContent = message.content as Reaction;
     content = {
-      reaction: content.content,
-      reference: content.reference,
+      reaction: messageContent.content,
+      reference: messageContent.reference,
     };
   } else if (message.contentType?.typeId == "remote_attachment") {
-    const attachment = await RemoteAttachmentCodec.load(
-      message.content,
+    const messageContent = message.content as RemoteAttachment;
+    const attachment = await RemoteAttachmentCodec.load<string>(
+      messageContent,
       client,
     );
     content = {
-      attachment: attachment as string,
+      attachment: attachment,
     };
   } else if (typeId == "read_receipt") {
     //Log read receipt
   } else if (typeId == "agent_message") {
+    const messageContent = message.content as AgentMessage;
     content = {
-      text: message.content.text,
-      metadata: message.content.metadata,
+      text: messageContent.text,
+      metadata: messageContent.metadata,
     };
   } else if (typeId == "attachment") {
-    const blobdecoded = new Blob([message.content.data], {
-      type: message.content.mimeType,
+    const messageContent = message.content as Attachment;
+    const blobdecoded = new Blob([messageContent.data], {
+      type: messageContent.mimeType,
     });
     const url = URL.createObjectURL(blobdecoded);
 
@@ -600,21 +586,20 @@ export async function parseMessage(
       attachment: url,
     };
   }
-  let date = message.sentAt;
+  const date = message.sentAt;
   let sender: User | undefined = undefined;
 
   await conversation?.sync();
   const members = await conversation?.members();
-  let membersArray = members?.map((member: any) => ({
+  const membersArray = members?.map((member) => ({
     inboxId: member.inboxId,
     address: member.accountAddresses[0],
     accountAddresses: member.accountAddresses,
     installationIds: member.installationIds,
   })) as User[];
 
-  sender = membersArray?.find(
-    (member: User) =>
-      member.inboxId === (message as DecodedMessage).senderInboxId,
+  sender = membersArray.find(
+    (member: User) => member.inboxId === message.senderInboxId,
   );
   return {
     id: message.id,
@@ -627,7 +612,8 @@ export async function parseMessage(
       admins: conversation?.admins,
       superAdmins: conversation?.superAdmins,
     },
-    sent: date as Date,
+    sent: date,
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     content,
     typeId,
     client: {
diff --git a/packages/agent-starter/tests/Client.test.ts b/packages/agent-starter/tests/Client.test.ts
index 1d43096..cc897e5 100644
--- a/packages/agent-starter/tests/Client.test.ts
+++ b/packages/agent-starter/tests/Client.test.ts
@@ -1,12 +1,12 @@
-import { describe, test, expect } from "vitest";
+import { createUser, XMTP, xmtpClient } from "@xmtp/agent-starter";
 import { generatePrivateKey } from "viem/accounts";
-import { XMTP, createUser, xmtpClient } from "@xmtp/agent-starter";
+import { describe, expect, test } from "vitest";
 
 describe("Client Private Key Configuration Tests", () => {
   test("creates a client with a random generated key", async () => {
     const xmtp = new XMTP();
     await xmtp.init();
-    expect(xmtp?.inboxId).toBeDefined();
+    expect(xmtp.inboxId).toBeDefined();
   }, 25000); // Added 15 second timeout
 
   test("creates a client with a provided private key", async () => {
@@ -16,7 +16,7 @@ describe("Client Private Key Configuration Tests", () => {
       onMessage: async () => {},
     });
     await xmtp.init();
-    expect(xmtp?.inboxId).toBeDefined();
+    expect(xmtp.inboxId).toBeDefined();
   }, 15000); // Added 15 second timeout
 
   test("creates user with valid private key", () => {
@@ -33,7 +33,7 @@ describe("Client Private Key Configuration Tests", () => {
     const xmtp = await xmtpClient({
       name: agentName,
     });
-    expect(xmtp?.inboxId).toBeDefined();
+    expect(xmtp.inboxId).toBeDefined();
   });
 
   test("fails gracefully with invalid private key format", async () => {
@@ -49,7 +49,7 @@ describe("Client Private Key Configuration Tests", () => {
       throw new Error("Expected error was not thrown");
     } catch (error) {
       // Check if the error is the expected one
-      expect(error.message).toContain("invalid private key");
+      expect((error as Error).message).toContain("invalid private key");
     }
   }, 15000); // Added 15 second timeout
 });
diff --git a/packages/agent-starter/tests/Encryption.test.ts b/packages/agent-starter/tests/Encryption.test.ts
index e463b48..afff889 100644
--- a/packages/agent-starter/tests/Encryption.test.ts
+++ b/packages/agent-starter/tests/Encryption.test.ts
@@ -1,4 +1,4 @@
-import { describe, test, expect } from "vitest";
+import { describe, expect, test } from "vitest";
 import { xmtpClient } from "../src/lib/xmtp";
 
 describe("Encryption Tests", () => {
diff --git a/packages/agent-starter/tsconfig.json b/packages/agent-starter/tsconfig.json
index 07faedb..04248f9 100644
--- a/packages/agent-starter/tsconfig.json
+++ b/packages/agent-starter/tsconfig.json
@@ -1,4 +1,4 @@
 {
-  "include": ["src/**/*", "rollup.config.js"],
+  "include": ["src/**/*", "tests/**/*", "rollup.config.js"],
   "extends": "@xmtp/tsconfig/base.json"
 }
diff --git a/packages/lookup/package.json b/packages/lookup/package.json
index 0b9bb53..8e74da6 100644
--- a/packages/lookup/package.json
+++ b/packages/lookup/package.json
@@ -32,7 +32,6 @@
     "@types/node": "^22.10.9",
     "@vitest/coverage-v8": "^2.1.8",
     "dotenv": "^16.4.7",
-    "prettier": "^3.4.2",
     "rollup": "^4.31.0",
     "rollup-plugin-dts": "^6.1.1",
     "ts-node": "^10.9.2",
diff --git a/packages/lookup/src/index.ts b/packages/lookup/src/index.ts
index d72b64e..d5bcdaf 100644
--- a/packages/lookup/src/index.ts
+++ b/packages/lookup/src/index.ts
@@ -1,5 +1,6 @@
-import { isAddress } from "viem";
 import dns from "dns";
+import { isAddress } from "viem";
+
 export const converseEndpointURL = "https://converse.xyz/profile/";
 
 export type InfoCache = Map<string, UserInfo>;
@@ -42,7 +43,7 @@ export interface EnsData {
 }
 
 class UserInfoCache {
-  private static instance: UserInfoCache;
+  private static instance: UserInfoCache | undefined;
   private cache: InfoCache = new Map();
 
   private constructor() {}
@@ -78,7 +79,7 @@ export const lookup = async (
   key: string | undefined,
   clientAddress?: string,
 ): Promise<UserInfo | undefined> => {
-  let data: UserInfo = {
+  const data: UserInfo = {
     ensDomain: undefined,
     address: undefined,
     converseUsername: undefined,
@@ -96,7 +97,7 @@ export const lookup = async (
   const cachedData = cache.get(key);
   if (cachedData) return cachedData;
 
-  key = key?.toLowerCase();
+  key = key.toLowerCase();
   clientAddress = clientAddress?.toLowerCase();
 
   // Determine user information based on provided key
@@ -145,7 +146,7 @@ export const lookup = async (
         if (process.env.MSG_LOG === "true")
           console.log("- ENS data request failed for", keyToUse);
       } else {
-        const ensData = (await response.json()) as EnsData;
+        const ensData = (await response.json()) as EnsData | undefined;
         if (ensData) {
           data.ensInfo = ensData;
           data.ensDomain = ensData.ens || data.ensDomain;
@@ -154,7 +155,7 @@ export const lookup = async (
           data.avatar = ensData.avatar_url || data.avatar;
         }
       }
-    } catch (error) {
+    } catch {
       console.error(`Failed to fetch ENS data for ${keyToUse}`);
     }
 
@@ -177,7 +178,9 @@ export const lookup = async (
           `Converse profile request failed with status ${response?.status}`,
         );
       }
-      const converseData = (await response?.json()) as ConverseProfile;
+      const converseData = (await response?.json()) as
+        | ConverseProfile
+        | undefined;
       if (converseData) {
         data.converseUsername =
           converseData.formattedName ||
@@ -204,7 +207,9 @@ const fetchWithTimeout = async (
   timeout = 5000,
 ) => {
   const controller = new AbortController();
-  const id = setTimeout(() => controller.abort(), timeout);
+  const id = setTimeout(() => {
+    controller.abort();
+  }, timeout);
   try {
     const response = await fetch(url, {
       ...options,
@@ -212,7 +217,7 @@ const fetchWithTimeout = async (
     });
     clearTimeout(id);
     return response;
-  } catch (error) {
+  } catch {
     clearTimeout(id);
     console.error("fetching");
   }
@@ -223,11 +228,12 @@ export async function getEvmAddressFromDns(
 ): Promise<string | undefined> {
   try {
     try {
-      const records = await new Promise((resolve, reject) => {
+      const records = await new Promise<string[][]>((resolve, reject) => {
         dns.resolveTxt(domain, (err, records) => {
           if (err) {
             console.error("Failed to resolve TXT records:", err);
-            return reject(err);
+            reject(err);
+            return;
           }
           resolve(records);
         });
diff --git a/packages/lookup/tests/Lookup.test.ts b/packages/lookup/tests/Lookup.test.ts
index d28be1f..35a7a9f 100644
--- a/packages/lookup/tests/Lookup.test.ts
+++ b/packages/lookup/tests/Lookup.test.ts
@@ -1,4 +1,4 @@
-import { describe, test, expect } from "vitest";
+import { describe, expect, test } from "vitest";
 import { lookup } from "../src/index";
 
 describe("Client Private Key Configuration Tests", () => {
diff --git a/packages/lookup/tsconfig.json b/packages/lookup/tsconfig.json
index 07faedb..04248f9 100644
--- a/packages/lookup/tsconfig.json
+++ b/packages/lookup/tsconfig.json
@@ -1,4 +1,4 @@
 {
-  "include": ["src/**/*", "rollup.config.js"],
+  "include": ["src/**/*", "tests/**/*", "rollup.config.js"],
   "extends": "@xmtp/tsconfig/base.json"
 }
diff --git a/scripts/examples.js b/scripts/examples.js
index 6c4d9c2..56e1653 100644
--- a/scripts/examples.js
+++ b/scripts/examples.js
@@ -1,7 +1,7 @@
 import { execSync } from "child_process";
+import fs from "fs";
 import path from "node:path";
 import { fileURLToPath } from "node:url";
-import fs from "fs";
 import { select } from "@clack/prompts";
 
 const __filename = fileURLToPath(import.meta.url);
diff --git a/shared/tsconfig/node.json b/shared/tsconfig/node.json
new file mode 100644
index 0000000..a249ea1
--- /dev/null
+++ b/shared/tsconfig/node.json
@@ -0,0 +1,8 @@
+{
+  "$schema": "https://json.schemastore.org/tsconfig",
+  "display": "Node",
+  "extends": ["./base.json"],
+  "compilerOptions": {
+    "types": ["node"]
+  }
+}
diff --git a/shared/tsconfig/package.json b/shared/tsconfig/package.json
index 960d0d2..4730ba1 100644
--- a/shared/tsconfig/package.json
+++ b/shared/tsconfig/package.json
@@ -5,13 +5,7 @@
     "base.json"
   ],
   "scripts": {
-    "clean": "rm -rf .turbo && rm -rf node_modules",
-    "format": "yarn format:base -w .",
-    "format:base": "prettier --ignore-path ../../.gitignore",
-    "format:check": "yarn format:base -c ."
-  },
-  "devDependencies": {
-    "prettier": "^3.4.2"
+    "clean": "rm -rf .turbo && rm -rf node_modules"
   },
   "engines": {
     "node": ">=22"
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..4fb9c5b
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": ["@xmtp/tsconfig/node.json"]
+}
diff --git a/turbo.json b/turbo.json
index ac91766..a030435 100644
--- a/turbo.json
+++ b/turbo.json
@@ -1,16 +1,10 @@
 {
   "$schema": "https://turbo.build/schema.json",
-  "globalEnv": [
-    "\\*\\*/.env.\\*local"
-  ],
+  "globalEnv": ["\\*\\*/.env.\\*local"],
   "tasks": {
     "build": {
-      "dependsOn": [
-        "^build"
-      ],
-      "outputs": [
-        "dist/**"
-      ]
+      "dependsOn": ["^build"],
+      "outputs": ["dist/**"]
     },
     "clean": {
       "outputs": []
@@ -20,14 +14,10 @@
     },
     "test": {
       "outputs": [],
-      "dependsOn": [
-        "^build"
-      ]
+      "dependsOn": ["^build"]
     },
     "typecheck": {
-      "dependsOn": [
-        "^build"
-      ],
+      "dependsOn": ["^build"],
       "outputs": []
     }
   }
diff --git a/yarn.lock b/yarn.lock
index a271d9e..1ca982d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -22,7 +22,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/code-frame@npm:^7.24.2":
+"@babel/code-frame@npm:^7.24.2, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.2":
   version: 7.26.2
   resolution: "@babel/code-frame@npm:7.26.2"
   dependencies:
@@ -33,6 +33,19 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@babel/generator@npm:^7.26.2, @babel/generator@npm:^7.26.5":
+  version: 7.26.5
+  resolution: "@babel/generator@npm:7.26.5"
+  dependencies:
+    "@babel/parser": "npm:^7.26.5"
+    "@babel/types": "npm:^7.26.5"
+    "@jridgewell/gen-mapping": "npm:^0.3.5"
+    "@jridgewell/trace-mapping": "npm:^0.3.25"
+    jsesc: "npm:^3.0.2"
+  checksum: 10/aa5f176155431d1fb541ca11a7deddec0fc021f20992ced17dc2f688a0a9584e4ff4280f92e8a39302627345cd325762f70f032764806c579c6fd69432542bcb
+  languageName: node
+  linkType: hard
+
 "@babel/helper-string-parser@npm:^7.25.9":
   version: 7.25.9
   resolution: "@babel/helper-string-parser@npm:7.25.9"
@@ -47,7 +60,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/parser@npm:^7.25.4":
+"@babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.2, @babel/parser@npm:^7.26.5":
   version: 7.26.5
   resolution: "@babel/parser@npm:7.26.5"
   dependencies:
@@ -67,7 +80,33 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@babel/types@npm:^7.25.4, @babel/types@npm:^7.26.5":
+"@babel/template@npm:^7.25.9":
+  version: 7.25.9
+  resolution: "@babel/template@npm:7.25.9"
+  dependencies:
+    "@babel/code-frame": "npm:^7.25.9"
+    "@babel/parser": "npm:^7.25.9"
+    "@babel/types": "npm:^7.25.9"
+  checksum: 10/e861180881507210150c1335ad94aff80fd9e9be6202e1efa752059c93224e2d5310186ddcdd4c0f0b0fc658ce48cb47823f15142b5c00c8456dde54f5de80b2
+  languageName: node
+  linkType: hard
+
+"@babel/traverse@npm:^7.25.9":
+  version: 7.26.5
+  resolution: "@babel/traverse@npm:7.26.5"
+  dependencies:
+    "@babel/code-frame": "npm:^7.26.2"
+    "@babel/generator": "npm:^7.26.5"
+    "@babel/parser": "npm:^7.26.5"
+    "@babel/template": "npm:^7.25.9"
+    "@babel/types": "npm:^7.26.5"
+    debug: "npm:^4.3.1"
+    globals: "npm:^11.1.0"
+  checksum: 10/b0131159450e3cd4208354cdea57e832e1a344fcc284b6ac84d1e13567a10501c4747bfd0ce637d2bd02277526b49372cfca71edd5c825cea74dcc9f52bb9225
+  languageName: node
+  linkType: hard
+
+"@babel/types@npm:^7.25.4, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.5":
   version: 7.26.5
   resolution: "@babel/types@npm:7.26.5"
   dependencies:
@@ -509,6 +548,97 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0":
+  version: 4.4.1
+  resolution: "@eslint-community/eslint-utils@npm:4.4.1"
+  dependencies:
+    eslint-visitor-keys: "npm:^3.4.3"
+  peerDependencies:
+    eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+  checksum: 10/ae92a11412674329b4bd38422518601ec9ceae28e251104d1cad83715da9d38e321f68c817c39b64e66d0af7d98df6f9a10ad2dc638911254b47fb8932df00ef
+  languageName: node
+  linkType: hard
+
+"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1":
+  version: 4.12.1
+  resolution: "@eslint-community/regexpp@npm:4.12.1"
+  checksum: 10/c08f1dd7dd18fbb60bdd0d85820656d1374dd898af9be7f82cb00451313402a22d5e30569c150315b4385907cdbca78c22389b2a72ab78883b3173be317620cc
+  languageName: node
+  linkType: hard
+
+"@eslint/compat@npm:^1.2.5":
+  version: 1.2.5
+  resolution: "@eslint/compat@npm:1.2.5"
+  peerDependencies:
+    eslint: ^9.10.0
+  peerDependenciesMeta:
+    eslint:
+      optional: true
+  checksum: 10/bb4370ca995fcc69d7a657cd478ff0cf2b0d3efe78e45818509917e3a6e73bdc706d3830ccda6aa46c3968e99170feb44fe8eb4314b6c9fa9bcb76d4a2fd4f8c
+  languageName: node
+  linkType: hard
+
+"@eslint/config-array@npm:^0.19.0":
+  version: 0.19.1
+  resolution: "@eslint/config-array@npm:0.19.1"
+  dependencies:
+    "@eslint/object-schema": "npm:^2.1.5"
+    debug: "npm:^4.3.1"
+    minimatch: "npm:^3.1.2"
+  checksum: 10/1243b01f463de85c970c18f0994f9d1850dafe8cc8c910edb64105d845edd3cacaa0bbf028bf35a6daaf5a179021140b6a8b1dc7a2f915b42c2d35f022a9c201
+  languageName: node
+  linkType: hard
+
+"@eslint/core@npm:^0.10.0":
+  version: 0.10.0
+  resolution: "@eslint/core@npm:0.10.0"
+  dependencies:
+    "@types/json-schema": "npm:^7.0.15"
+  checksum: 10/de41d7fa5dc468b70fb15c72829096939fc0217c41b8519af4620bc1089cb42539a15325c4c3ee3832facac1836c8c944c4a0c4d0cc8b33ffd8e95962278ae14
+  languageName: node
+  linkType: hard
+
+"@eslint/eslintrc@npm:^3.2.0":
+  version: 3.2.0
+  resolution: "@eslint/eslintrc@npm:3.2.0"
+  dependencies:
+    ajv: "npm:^6.12.4"
+    debug: "npm:^4.3.2"
+    espree: "npm:^10.0.1"
+    globals: "npm:^14.0.0"
+    ignore: "npm:^5.2.0"
+    import-fresh: "npm:^3.2.1"
+    js-yaml: "npm:^4.1.0"
+    minimatch: "npm:^3.1.2"
+    strip-json-comments: "npm:^3.1.1"
+  checksum: 10/b32dd90ce7da68e89b88cd729db46b27aac79a2e6cb1fa75d25a6b766d586b443bfbf59622489efbd3c6f696f147b51111e81ec7cd23d70f215c5d474cad0261
+  languageName: node
+  linkType: hard
+
+"@eslint/js@npm:9.18.0, @eslint/js@npm:^9.18.0":
+  version: 9.18.0
+  resolution: "@eslint/js@npm:9.18.0"
+  checksum: 10/364a7d030dad9dbda1458d8dbcea0199fe7d48bcfefe4b49389df6c45cdc5a2449f70e5d8a794e46ed9fb34af3fe5a3f53e30020d306b6ee791e2a1b2b9fa25f
+  languageName: node
+  linkType: hard
+
+"@eslint/object-schema@npm:^2.1.5":
+  version: 2.1.5
+  resolution: "@eslint/object-schema@npm:2.1.5"
+  checksum: 10/bb07ec53357047f20de923bcd61f0306d9eee83ef41daa32e633e154a44796b5bd94670169eccb8fd8cb4ff42228a43b86953a6321f789f98194baba8207b640
+  languageName: node
+  linkType: hard
+
+"@eslint/plugin-kit@npm:^0.2.5":
+  version: 0.2.5
+  resolution: "@eslint/plugin-kit@npm:0.2.5"
+  dependencies:
+    "@eslint/core": "npm:^0.10.0"
+    levn: "npm:^0.4.1"
+  checksum: 10/82d0142bc7054587bde4f75c2c517f477df7c320e4bdb47a4d5f766899a313ce65e9ce5d59428178d0be473a95292065053f69637042546b811ad89079781cbc
+  languageName: node
+  linkType: hard
+
 "@ethersproject/abi@npm:^5.7.0":
   version: 5.7.0
   resolution: "@ethersproject/abi@npm:5.7.0"
@@ -936,11 +1066,11 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@example/multi-agent-express@workspace:examples/express"
   dependencies:
-    "@types/express": "npm:^4.17.21"
+    "@types/express": "npm:^5.0.0"
     "@types/node": "npm:^22.10.9"
     "@xmtp/agent-starter": "workspace:*"
     axios: "npm:^1.7.9"
-    express: "npm:^4.21.2"
+    express: "npm:^5.0.1"
     typescript: "npm:^5.7.3"
   languageName: unknown
   linkType: soft
@@ -952,6 +1082,63 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@humanfs/core@npm:^0.19.1":
+  version: 0.19.1
+  resolution: "@humanfs/core@npm:0.19.1"
+  checksum: 10/270d936be483ab5921702623bc74ce394bf12abbf57d9145a69e8a0d1c87eb1c768bd2d93af16c5705041e257e6d9cc7529311f63a1349f3678abc776fc28523
+  languageName: node
+  linkType: hard
+
+"@humanfs/node@npm:^0.16.6":
+  version: 0.16.6
+  resolution: "@humanfs/node@npm:0.16.6"
+  dependencies:
+    "@humanfs/core": "npm:^0.19.1"
+    "@humanwhocodes/retry": "npm:^0.3.0"
+  checksum: 10/6d43c6727463772d05610aa05c83dab2bfbe78291022ee7a92cb50999910b8c720c76cc312822e2dea2b497aa1b3fef5fe9f68803fc45c9d4ed105874a65e339
+  languageName: node
+  linkType: hard
+
+"@humanwhocodes/module-importer@npm:^1.0.1":
+  version: 1.0.1
+  resolution: "@humanwhocodes/module-importer@npm:1.0.1"
+  checksum: 10/e993950e346331e5a32eefb27948ecdee2a2c4ab3f072b8f566cd213ef485dd50a3ca497050608db91006f5479e43f91a439aef68d2a313bd3ded06909c7c5b3
+  languageName: node
+  linkType: hard
+
+"@humanwhocodes/retry@npm:^0.3.0":
+  version: 0.3.1
+  resolution: "@humanwhocodes/retry@npm:0.3.1"
+  checksum: 10/eb457f699529de7f07649679ec9e0353055eebe443c2efe71c6dd950258892475a038e13c6a8c5e13ed1fb538cdd0a8794faa96b24b6ffc4c87fb1fc9f70ad7f
+  languageName: node
+  linkType: hard
+
+"@humanwhocodes/retry@npm:^0.4.1":
+  version: 0.4.1
+  resolution: "@humanwhocodes/retry@npm:0.4.1"
+  checksum: 10/39fafc7319e88f61befebd5e1b4f0136534ea6a9bd10d74366698187bd63544210ec5d79a87ed4d91297f1cc64c4c53d45fb0077a2abfdce212cf0d3862d5f04
+  languageName: node
+  linkType: hard
+
+"@ianvs/prettier-plugin-sort-imports@npm:^4.4.1":
+  version: 4.4.1
+  resolution: "@ianvs/prettier-plugin-sort-imports@npm:4.4.1"
+  dependencies:
+    "@babel/generator": "npm:^7.26.2"
+    "@babel/parser": "npm:^7.26.2"
+    "@babel/traverse": "npm:^7.25.9"
+    "@babel/types": "npm:^7.26.0"
+    semver: "npm:^7.5.2"
+  peerDependencies:
+    "@vue/compiler-sfc": 2.7.x || 3.x
+    prettier: 2 || 3
+  peerDependenciesMeta:
+    "@vue/compiler-sfc":
+      optional: true
+  checksum: 10/4d4666bdbc30ab579b8d39e1ae68c2088bdc8e9d50ac356f85ca64ef614c09b05cab5a908f7c4ab3e1b5d7f235994e877f5af67561e3f967ba9ec5011625ceca
+  languageName: node
+  linkType: hard
+
 "@isaacs/cliui@npm:^8.0.2":
   version: 8.0.2
   resolution: "@isaacs/cliui@npm:8.0.2"
@@ -1024,7 +1211,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24":
+"@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25":
   version: 0.3.25
   resolution: "@jridgewell/trace-mapping@npm:0.3.25"
   dependencies:
@@ -1639,7 +1826,26 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/estree@npm:1.0.6, @types/estree@npm:^1.0.0":
+"@types/eslint@npm:*":
+  version: 9.6.1
+  resolution: "@types/eslint@npm:9.6.1"
+  dependencies:
+    "@types/estree": "npm:*"
+    "@types/json-schema": "npm:*"
+  checksum: 10/719fcd255760168a43d0e306ef87548e1e15bffe361d5f4022b0f266575637acc0ecb85604ac97879ee8ae83c6a6d0613b0ed31d0209ddf22a0fe6d608fc56fe
+  languageName: node
+  linkType: hard
+
+"@types/eslint__js@npm:^8.42.3":
+  version: 8.42.3
+  resolution: "@types/eslint__js@npm:8.42.3"
+  dependencies:
+    "@types/eslint": "npm:*"
+  checksum: 10/e31f19de642d35a664695d0cab873ce6de19b8a3506755835b91f8a49a8c41099dcace449df49f1a486de6fa6565d21ceb1fa33be6004fc7adef9226e5d256a1
+  languageName: node
+  linkType: hard
+
+"@types/estree@npm:*, @types/estree@npm:1.0.6, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6":
   version: 1.0.6
   resolution: "@types/estree@npm:1.0.6"
   checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d
@@ -1658,6 +1864,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/express-serve-static-core@npm:^5.0.0":
+  version: 5.0.5
+  resolution: "@types/express-serve-static-core@npm:5.0.5"
+  dependencies:
+    "@types/node": "npm:*"
+    "@types/qs": "npm:*"
+    "@types/range-parser": "npm:*"
+    "@types/send": "npm:*"
+  checksum: 10/186b275cd9110c7153ffd6f2c52e0e4242b0f2769873ea034c75885a96346b42535875012732e0866ccdfc7d5132bb32a725a297182e929427cb95aba62f9801
+  languageName: node
+  linkType: hard
+
 "@types/express@npm:^4.17.21":
   version: 4.17.21
   resolution: "@types/express@npm:4.17.21"
@@ -1670,6 +1888,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/express@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "@types/express@npm:5.0.0"
+  dependencies:
+    "@types/body-parser": "npm:*"
+    "@types/express-serve-static-core": "npm:^5.0.0"
+    "@types/qs": "npm:*"
+    "@types/serve-static": "npm:*"
+  checksum: 10/45b199ab669caa33e6badafeebf078e277ea95042309d325a04b1ec498f33d33fd5a4ae9c8e358342367b178fe454d7323c5dfc8002bf27070b210a2c6cc11f0
+  languageName: node
+  linkType: hard
+
 "@types/http-errors@npm:*":
   version: 2.0.4
   resolution: "@types/http-errors@npm:2.0.4"
@@ -1677,6 +1907,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15":
+  version: 7.0.15
+  resolution: "@types/json-schema@npm:7.0.15"
+  checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7
+  languageName: node
+  linkType: hard
+
 "@types/mime@npm:^1":
   version: 1.3.5
   resolution: "@types/mime@npm:1.3.5"
@@ -1763,6 +2000,118 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@typescript-eslint/eslint-plugin@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/eslint-plugin@npm:8.21.0"
+  dependencies:
+    "@eslint-community/regexpp": "npm:^4.10.0"
+    "@typescript-eslint/scope-manager": "npm:8.21.0"
+    "@typescript-eslint/type-utils": "npm:8.21.0"
+    "@typescript-eslint/utils": "npm:8.21.0"
+    "@typescript-eslint/visitor-keys": "npm:8.21.0"
+    graphemer: "npm:^1.4.0"
+    ignore: "npm:^5.3.1"
+    natural-compare: "npm:^1.4.0"
+    ts-api-utils: "npm:^2.0.0"
+  peerDependencies:
+    "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.8.0"
+  checksum: 10/4c7c274bd0f7d8ee2097278d9fb0829b883c28783b9a1c41e5f4e74dee0412c53063978db3590ad7609d538a38058e43f832895746e6af677da7558a8b16fbdd
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/parser@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/parser@npm:8.21.0"
+  dependencies:
+    "@typescript-eslint/scope-manager": "npm:8.21.0"
+    "@typescript-eslint/types": "npm:8.21.0"
+    "@typescript-eslint/typescript-estree": "npm:8.21.0"
+    "@typescript-eslint/visitor-keys": "npm:8.21.0"
+    debug: "npm:^4.3.4"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.8.0"
+  checksum: 10/c403f56b0a856ad25ffc0d78d4f0ede64d622edb279ace8bc7554c82518c0462f608a1e06d62111633a57b9ffcc37e063378c3980fba138f93d14a7aad5d0db1
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/scope-manager@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/scope-manager@npm:8.21.0"
+  dependencies:
+    "@typescript-eslint/types": "npm:8.21.0"
+    "@typescript-eslint/visitor-keys": "npm:8.21.0"
+  checksum: 10/99aa8257c758546c8c4905bd34381be446adea7642dbc279269039308dc33b8dbcf3d7b7d12da7bec8f8d8760b813a5852dc53d75e953cbe327fac05d3f18fc4
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/type-utils@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/type-utils@npm:8.21.0"
+  dependencies:
+    "@typescript-eslint/typescript-estree": "npm:8.21.0"
+    "@typescript-eslint/utils": "npm:8.21.0"
+    debug: "npm:^4.3.4"
+    ts-api-utils: "npm:^2.0.0"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.8.0"
+  checksum: 10/b4bce1325a2e5e1a74b6919b3187356b7246475ac4d62898134ed68572e39e52fe5daa89d0bb66d78aef7b2057612cccc00400c0b81f9d5b75acec3174114c8d
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/types@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/types@npm:8.21.0"
+  checksum: 10/a22c99f5687358c7343789b942c9885bc1b49eb239562b792f22e2ac4f0d3f04102f204cd2d749202d6888767566fba86f54447894955310890ec307fec8ed8d
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/typescript-estree@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/typescript-estree@npm:8.21.0"
+  dependencies:
+    "@typescript-eslint/types": "npm:8.21.0"
+    "@typescript-eslint/visitor-keys": "npm:8.21.0"
+    debug: "npm:^4.3.4"
+    fast-glob: "npm:^3.3.2"
+    is-glob: "npm:^4.0.3"
+    minimatch: "npm:^9.0.4"
+    semver: "npm:^7.6.0"
+    ts-api-utils: "npm:^2.0.0"
+  peerDependencies:
+    typescript: ">=4.8.4 <5.8.0"
+  checksum: 10/1a8bcd2968490dcf047273a36e1d2cd51725e893ad874e554e4b81e62bf54e4ff2b7ee2af206208a2ae9ac2cc5c8b50e2244dd4fe9c42ef34122df4360e9f9c2
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/utils@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/utils@npm:8.21.0"
+  dependencies:
+    "@eslint-community/eslint-utils": "npm:^4.4.0"
+    "@typescript-eslint/scope-manager": "npm:8.21.0"
+    "@typescript-eslint/types": "npm:8.21.0"
+    "@typescript-eslint/typescript-estree": "npm:8.21.0"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.8.0"
+  checksum: 10/e44b4e87b8227f7524b4cd16e833ea37fbb73d3829caf484e7ca737060908817788755b9481d053bc4371bbcc99d2477e32b7ad43a421a3e61ce46c2c48c0bd7
+  languageName: node
+  linkType: hard
+
+"@typescript-eslint/visitor-keys@npm:8.21.0":
+  version: 8.21.0
+  resolution: "@typescript-eslint/visitor-keys@npm:8.21.0"
+  dependencies:
+    "@typescript-eslint/types": "npm:8.21.0"
+    eslint-visitor-keys: "npm:^4.2.0"
+  checksum: 10/781cafa354177de4e864511435dbe61d896a7d1331bca76dd0a151295cc27b9677412444d47e1d5c6d2e7de5fee29b7bef0489d76c494fa59139e421f860506a
+  languageName: node
+  linkType: hard
+
 "@vitest/coverage-v8@npm:^2.1.8":
   version: 2.1.8
   resolution: "@vitest/coverage-v8@npm:2.1.8"
@@ -1888,7 +2237,6 @@ __metadata:
     "@xmtp/node-sdk": "npm:^0.0.40"
     dotenv: "npm:^16.4.7"
     node-fetch: "npm:^3.3.2"
-    prettier: "npm:^3.4.2"
     rollup: "npm:^4.31.0"
     rollup-plugin-dts: "npm:^6.1.1"
     ts-node: "npm:^10.9.2"
@@ -1975,7 +2323,6 @@ __metadata:
     "@types/node": "npm:^22.10.9"
     "@vitest/coverage-v8": "npm:^2.1.8"
     dotenv: "npm:^16.4.7"
-    prettier: "npm:^3.4.2"
     rollup: "npm:^4.31.0"
     rollup-plugin-dts: "npm:^6.1.1"
     ts-node: "npm:^10.9.2"
@@ -2020,8 +2367,6 @@ __metadata:
 "@xmtp/tsconfig@workspace:shared/tsconfig":
   version: 0.0.0-use.local
   resolution: "@xmtp/tsconfig@workspace:shared/tsconfig"
-  dependencies:
-    prettier: "npm:^3.4.2"
   languageName: unknown
   linkType: soft
 
@@ -2071,6 +2416,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"accepts@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "accepts@npm:2.0.0"
+  dependencies:
+    mime-types: "npm:^3.0.0"
+    negotiator: "npm:^1.0.0"
+  checksum: 10/ea1343992b40b2bfb3a3113fa9c3c2f918ba0f9197ae565c48d3f84d44b174f6b1d5cd9989decd7655963eb03a272abc36968cc439c2907f999bd5ef8653d5a7
+  languageName: node
+  linkType: hard
+
 "accepts@npm:~1.3.8":
   version: 1.3.8
   resolution: "accepts@npm:1.3.8"
@@ -2081,6 +2436,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"acorn-jsx@npm:^5.3.2":
+  version: 5.3.2
+  resolution: "acorn-jsx@npm:5.3.2"
+  peerDependencies:
+    acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+  checksum: 10/d4371eaef7995530b5b5ca4183ff6f062ca17901a6d3f673c9ac011b01ede37e7a1f7f61f8f5cfe709e88054757bb8f3277dc4061087cdf4f2a1f90ccbcdb977
+  languageName: node
+  linkType: hard
+
 "acorn-walk@npm:^8.1.1":
   version: 8.3.4
   resolution: "acorn-walk@npm:8.3.4"
@@ -2090,7 +2454,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"acorn@npm:^8.11.0, acorn@npm:^8.4.1":
+"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.4.1":
   version: 8.14.0
   resolution: "acorn@npm:8.14.0"
   bin:
@@ -2122,6 +2486,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"ajv@npm:^6.12.4":
+  version: 6.12.6
+  resolution: "ajv@npm:6.12.6"
+  dependencies:
+    fast-deep-equal: "npm:^3.1.1"
+    fast-json-stable-stringify: "npm:^2.0.0"
+    json-schema-traverse: "npm:^0.4.1"
+    uri-js: "npm:^4.2.2"
+  checksum: 10/48d6ad21138d12eb4d16d878d630079a2bda25a04e745c07846a4ad768319533031e28872a9b3c5790fa1ec41aabdf2abed30a56e5a03ebc2cf92184b8ee306c
+  languageName: node
+  linkType: hard
+
 "alchemy-sdk@npm:^3.5.1":
   version: 3.5.1
   resolution: "alchemy-sdk@npm:3.5.1"
@@ -2165,7 +2541,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ansi-styles@npm:^4.0.0":
+"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0":
   version: 4.3.0
   resolution: "ansi-styles@npm:4.3.0"
   dependencies:
@@ -2197,6 +2573,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"argparse@npm:^2.0.1":
+  version: 2.0.1
+  resolution: "argparse@npm:2.0.1"
+  checksum: 10/18640244e641a417ec75a9bd38b0b2b6b95af5199aa241b131d4b2fb206f334d7ecc600bd194861610a5579084978bfcbb02baa399dbe442d56d0ae5e60dbaef
+  languageName: node
+  linkType: hard
+
 "array-flatten@npm:1.1.1":
   version: 1.1.1
   resolution: "array-flatten@npm:1.1.1"
@@ -2204,6 +2587,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"array-flatten@npm:3.0.0":
+  version: 3.0.0
+  resolution: "array-flatten@npm:3.0.0"
+  checksum: 10/e1b11b51c0e0f0b1315ddab1d8e1760bbc76b4387290f73232d71195aa93e3f55179c434cac48f2c1446c614758b073b059bb0b2b545b8f0ec4af0cae9dc4371
+  languageName: node
+  linkType: hard
+
 "array-union@npm:^2.1.0":
   version: 2.1.0
   resolution: "array-union@npm:2.1.0"
@@ -2293,6 +2683,34 @@ __metadata:
   languageName: node
   linkType: hard
 
+"body-parser@npm:^2.0.1":
+  version: 2.0.2
+  resolution: "body-parser@npm:2.0.2"
+  dependencies:
+    bytes: "npm:3.1.2"
+    content-type: "npm:~1.0.5"
+    debug: "npm:3.1.0"
+    destroy: "npm:1.2.0"
+    http-errors: "npm:2.0.0"
+    iconv-lite: "npm:0.5.2"
+    on-finished: "npm:2.4.1"
+    qs: "npm:6.13.0"
+    raw-body: "npm:^3.0.0"
+    type-is: "npm:~1.6.18"
+  checksum: 10/3b381210daa9bbe90b6dc21fa9d4580b6842f7620437ec89c2522461150ceea11701ed6d7b23876d61056e9d64ee66a29ce00c0ef252a810edf4d7d45aa94455
+  languageName: node
+  linkType: hard
+
+"brace-expansion@npm:^1.1.7":
+  version: 1.1.11
+  resolution: "brace-expansion@npm:1.1.11"
+  dependencies:
+    balanced-match: "npm:^1.0.0"
+    concat-map: "npm:0.0.1"
+  checksum: 10/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07
+  languageName: node
+  linkType: hard
+
 "brace-expansion@npm:^2.0.1":
   version: 2.0.1
   resolution: "brace-expansion@npm:2.0.1"
@@ -2382,6 +2800,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"callsites@npm:^3.0.0":
+  version: 3.1.0
+  resolution: "callsites@npm:3.1.0"
+  checksum: 10/072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3
+  languageName: node
+  linkType: hard
+
 "chai@npm:^5.1.2":
   version: 5.1.2
   resolution: "chai@npm:5.1.2"
@@ -2395,6 +2820,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"chalk@npm:^4.0.0":
+  version: 4.1.2
+  resolution: "chalk@npm:4.1.2"
+  dependencies:
+    ansi-styles: "npm:^4.1.0"
+    supports-color: "npm:^7.1.0"
+  checksum: 10/cb3f3e594913d63b1814d7ca7c9bafbf895f75fbf93b92991980610dfd7b48500af4e3a5d4e3a8f337990a96b168d7eb84ee55efdce965e2ee8efc20f8c8f139
+  languageName: node
+  linkType: hard
+
 "chardet@npm:^0.7.0":
   version: 0.7.0
   resolution: "chardet@npm:0.7.0"
@@ -2448,6 +2883,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"concat-map@npm:0.0.1":
+  version: 0.0.1
+  resolution: "concat-map@npm:0.0.1"
+  checksum: 10/9680699c8e2b3af0ae22592cb764acaf973f292a7b71b8a06720233011853a58e256c89216a10cbe889727532fd77f8bcd49a760cedfde271b8e006c20e079f2
+  languageName: node
+  linkType: hard
+
 "content-disposition@npm:0.5.4":
   version: 0.5.4
   resolution: "content-disposition@npm:0.5.4"
@@ -2457,7 +2899,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"content-type@npm:~1.0.4, content-type@npm:~1.0.5":
+"content-disposition@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "content-disposition@npm:1.0.0"
+  dependencies:
+    safe-buffer: "npm:5.2.1"
+  checksum: 10/0dcc1a2d7874526b0072df3011b134857b49d97a3bc135bb464a299525d4972de6f5f464fd64da6c4d8406d26a1ffb976f62afaffef7723b1021a44498d10e08
+  languageName: node
+  linkType: hard
+
+"content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5":
   version: 1.0.5
   resolution: "content-type@npm:1.0.5"
   checksum: 10/585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662
@@ -2471,6 +2922,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"cookie-signature@npm:^1.2.1":
+  version: 1.2.2
+  resolution: "cookie-signature@npm:1.2.2"
+  checksum: 10/be44a3c9a56f3771aea3a8bd8ad8f0a8e2679bcb967478267f41a510b4eb5ec55085386ba79c706c4ac21605ca76f4251973444b90283e0eb3eeafe8a92c7708
+  languageName: node
+  linkType: hard
+
 "cookie@npm:0.7.1":
   version: 0.7.1
   resolution: "cookie@npm:0.7.1"
@@ -2485,7 +2943,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.5":
+"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6":
   version: 7.0.6
   resolution: "cross-spawn@npm:7.0.6"
   dependencies:
@@ -2522,7 +2980,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.4, debug@npm:^4.3.7":
+"debug@npm:3.1.0":
+  version: 3.1.0
+  resolution: "debug@npm:3.1.0"
+  dependencies:
+    ms: "npm:2.0.0"
+  checksum: 10/f5fd4b1390dd3b03a78aa30133a4b4db62acc3e6cd86af49f114bf7f7bd57c41a5c5c2eced2ad2c8190d70c60309f2dd5782feeaa0704dbaa5697890e3c5ad07
+  languageName: node
+  linkType: hard
+
+"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.7":
   version: 4.4.0
   resolution: "debug@npm:4.4.0"
   dependencies:
@@ -2534,6 +3001,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"debug@npm:4.3.6":
+  version: 4.3.6
+  resolution: "debug@npm:4.3.6"
+  dependencies:
+    ms: "npm:2.1.2"
+  peerDependenciesMeta:
+    supports-color:
+      optional: true
+  checksum: 10/d3adb9af7d57a9e809a68f404490cf776122acca16e6359a2702c0f462e510e91f9765c07f707b8ab0d91e03bad57328f3256f5082631cefb5393d0394d50fb7
+  languageName: node
+  linkType: hard
+
 "deep-eql@npm:^5.0.1":
   version: 5.0.2
   resolution: "deep-eql@npm:5.0.2"
@@ -2541,6 +3020,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"deep-is@npm:^0.1.3":
+  version: 0.1.4
+  resolution: "deep-is@npm:0.1.4"
+  checksum: 10/ec12d074aef5ae5e81fa470b9317c313142c9e8e2afe3f8efa124db309720db96d1d222b82b84c834e5f87e7a614b44a4684b6683583118b87c833b3be40d4d8
+  languageName: node
+  linkType: hard
+
 "delayed-stream@npm:~1.0.0":
   version: 1.0.0
   resolution: "delayed-stream@npm:1.0.0"
@@ -2555,7 +3041,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"destroy@npm:1.2.0":
+"destroy@npm:1.2.0, destroy@npm:^1.2.0":
   version: 1.2.0
   resolution: "destroy@npm:1.2.0"
   checksum: 10/0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38
@@ -2660,6 +3146,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"encodeurl@npm:^2.0.0, encodeurl@npm:~2.0.0":
+  version: 2.0.0
+  resolution: "encodeurl@npm:2.0.0"
+  checksum: 10/abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe
+  languageName: node
+  linkType: hard
+
 "encodeurl@npm:~1.0.2":
   version: 1.0.2
   resolution: "encodeurl@npm:1.0.2"
@@ -2667,13 +3160,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"encodeurl@npm:~2.0.0":
-  version: 2.0.0
-  resolution: "encodeurl@npm:2.0.0"
-  checksum: 10/abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe
-  languageName: node
-  linkType: hard
-
 "encoding@npm:^0.1.13":
   version: 0.1.13
   resolution: "encoding@npm:0.1.13"
@@ -2850,25 +3336,147 @@ __metadata:
   languageName: node
   linkType: hard
 
-"escape-html@npm:~1.0.3":
+"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3":
   version: 1.0.3
   resolution: "escape-html@npm:1.0.3"
   checksum: 10/6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24
   languageName: node
   linkType: hard
 
-"esniff@npm:^2.0.1":
-  version: 2.0.1
-  resolution: "esniff@npm:2.0.1"
-  dependencies:
-    d: "npm:^1.0.1"
-    es5-ext: "npm:^0.10.62"
-    event-emitter: "npm:^0.3.5"
+"escape-string-regexp@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "escape-string-regexp@npm:4.0.0"
+  checksum: 10/98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5
+  languageName: node
+  linkType: hard
+
+"eslint-config-prettier@npm:^10.0.1":
+  version: 10.0.1
+  resolution: "eslint-config-prettier@npm:10.0.1"
+  peerDependencies:
+    eslint: ">=7.0.0"
+  bin:
+    eslint-config-prettier: build/bin/cli.js
+  checksum: 10/ba6875df0fc4fd3c7c6e2ec9c2e6a224462f7afc662f4cf849775c598a3571c1be136a9b683b12971653b3dcf3f31472aaede3076524b46ec9a77582630158e5
+  languageName: node
+  linkType: hard
+
+"eslint-plugin-prettier@npm:^5.2.3":
+  version: 5.2.3
+  resolution: "eslint-plugin-prettier@npm:5.2.3"
+  dependencies:
+    prettier-linter-helpers: "npm:^1.0.0"
+    synckit: "npm:^0.9.1"
+  peerDependencies:
+    "@types/eslint": ">=8.0.0"
+    eslint: ">=8.0.0"
+    eslint-config-prettier: "*"
+    prettier: ">=3.0.0"
+  peerDependenciesMeta:
+    "@types/eslint":
+      optional: true
+    eslint-config-prettier:
+      optional: true
+  checksum: 10/6444a0b89f3e2a6b38adce69761133f8539487d797f1655b3fa24f93a398be132c4f68f87041a14740b79202368d5782aa1dffd2bd7a3ea659f263d6796acf15
+  languageName: node
+  linkType: hard
+
+"eslint-scope@npm:^8.2.0":
+  version: 8.2.0
+  resolution: "eslint-scope@npm:8.2.0"
+  dependencies:
+    esrecurse: "npm:^4.3.0"
+    estraverse: "npm:^5.2.0"
+  checksum: 10/cd9ab60d5a68f3a0fcac04d1cff5a7383d0f331964d5f1c446259123caec5b3ccc542284d07846e4f4d1389da77750821cc9a6e1ce18558c674977351666f9a6
+  languageName: node
+  linkType: hard
+
+"eslint-visitor-keys@npm:^3.4.3":
+  version: 3.4.3
+  resolution: "eslint-visitor-keys@npm:3.4.3"
+  checksum: 10/3f357c554a9ea794b094a09bd4187e5eacd1bc0d0653c3adeb87962c548e6a1ab8f982b86963ae1337f5d976004146536dcee5d0e2806665b193fbfbf1a9231b
+  languageName: node
+  linkType: hard
+
+"eslint-visitor-keys@npm:^4.2.0":
+  version: 4.2.0
+  resolution: "eslint-visitor-keys@npm:4.2.0"
+  checksum: 10/9651b3356b01760e586b4c631c5268c0e1a85236e3292bf754f0472f465bf9a856c0ddc261fceace155334118c0151778effafbab981413dbf9288349343fa25
+  languageName: node
+  linkType: hard
+
+"eslint@npm:^9.18.0":
+  version: 9.18.0
+  resolution: "eslint@npm:9.18.0"
+  dependencies:
+    "@eslint-community/eslint-utils": "npm:^4.2.0"
+    "@eslint-community/regexpp": "npm:^4.12.1"
+    "@eslint/config-array": "npm:^0.19.0"
+    "@eslint/core": "npm:^0.10.0"
+    "@eslint/eslintrc": "npm:^3.2.0"
+    "@eslint/js": "npm:9.18.0"
+    "@eslint/plugin-kit": "npm:^0.2.5"
+    "@humanfs/node": "npm:^0.16.6"
+    "@humanwhocodes/module-importer": "npm:^1.0.1"
+    "@humanwhocodes/retry": "npm:^0.4.1"
+    "@types/estree": "npm:^1.0.6"
+    "@types/json-schema": "npm:^7.0.15"
+    ajv: "npm:^6.12.4"
+    chalk: "npm:^4.0.0"
+    cross-spawn: "npm:^7.0.6"
+    debug: "npm:^4.3.2"
+    escape-string-regexp: "npm:^4.0.0"
+    eslint-scope: "npm:^8.2.0"
+    eslint-visitor-keys: "npm:^4.2.0"
+    espree: "npm:^10.3.0"
+    esquery: "npm:^1.5.0"
+    esutils: "npm:^2.0.2"
+    fast-deep-equal: "npm:^3.1.3"
+    file-entry-cache: "npm:^8.0.0"
+    find-up: "npm:^5.0.0"
+    glob-parent: "npm:^6.0.2"
+    ignore: "npm:^5.2.0"
+    imurmurhash: "npm:^0.1.4"
+    is-glob: "npm:^4.0.0"
+    json-stable-stringify-without-jsonify: "npm:^1.0.1"
+    lodash.merge: "npm:^4.6.2"
+    minimatch: "npm:^3.1.2"
+    natural-compare: "npm:^1.4.0"
+    optionator: "npm:^0.9.3"
+  peerDependencies:
+    jiti: "*"
+  peerDependenciesMeta:
+    jiti:
+      optional: true
+  bin:
+    eslint: bin/eslint.js
+  checksum: 10/85f22991aab4b0809fdfc557ec2bd309062e7211b631674e71827a73c45e44febaa80dedda35150154e331a2d372c3a25e8e5dd4a99dc8a982fe8f7d645d859f
+  languageName: node
+  linkType: hard
+
+"esniff@npm:^2.0.1":
+  version: 2.0.1
+  resolution: "esniff@npm:2.0.1"
+  dependencies:
+    d: "npm:^1.0.1"
+    es5-ext: "npm:^0.10.62"
+    event-emitter: "npm:^0.3.5"
     type: "npm:^2.7.2"
   checksum: 10/f6a2abd2f8c5fe57c5fcf53e5407c278023313d0f6c3a92688e7122ab9ac233029fd424508a196ae5bc561aa1f67d23f4e2435b1a0d378030f476596129056ac
   languageName: node
   linkType: hard
 
+"espree@npm:^10.0.1, espree@npm:^10.3.0":
+  version: 10.3.0
+  resolution: "espree@npm:10.3.0"
+  dependencies:
+    acorn: "npm:^8.14.0"
+    acorn-jsx: "npm:^5.3.2"
+    eslint-visitor-keys: "npm:^4.2.0"
+  checksum: 10/3412d44d4204c9e29d6b5dd0277400cfa0cd68495dc09eae1b9ce79d0c8985c1c5cc09cb9ba32a1cd963f48a49b0c46bdb7736afe395a300aa6bb1c0d86837e8
+  languageName: node
+  linkType: hard
+
 "esprima@npm:^4.0.0":
   version: 4.0.1
   resolution: "esprima@npm:4.0.1"
@@ -2879,6 +3487,31 @@ __metadata:
   languageName: node
   linkType: hard
 
+"esquery@npm:^1.5.0":
+  version: 1.6.0
+  resolution: "esquery@npm:1.6.0"
+  dependencies:
+    estraverse: "npm:^5.1.0"
+  checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a
+  languageName: node
+  linkType: hard
+
+"esrecurse@npm:^4.3.0":
+  version: 4.3.0
+  resolution: "esrecurse@npm:4.3.0"
+  dependencies:
+    estraverse: "npm:^5.2.0"
+  checksum: 10/44ffcd89e714ea6b30143e7f119b104fc4d75e77ee913f34d59076b40ef2d21967f84e019f84e1fd0465b42cdbf725db449f232b5e47f29df29ed76194db8e16
+  languageName: node
+  linkType: hard
+
+"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0":
+  version: 5.3.0
+  resolution: "estraverse@npm:5.3.0"
+  checksum: 10/37cbe6e9a68014d34dbdc039f90d0baf72436809d02edffcc06ba3c2a12eb298048f877511353b130153e532aac8d68ba78430c0dd2f44806ebc7c014b01585e
+  languageName: node
+  linkType: hard
+
 "estree-walker@npm:^2.0.2":
   version: 2.0.2
   resolution: "estree-walker@npm:2.0.2"
@@ -2895,7 +3528,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"etag@npm:~1.8.1":
+"esutils@npm:^2.0.2":
+  version: 2.0.3
+  resolution: "esutils@npm:2.0.3"
+  checksum: 10/b23acd24791db11d8f65be5ea58fd9a6ce2df5120ae2da65c16cfc5331ff59d5ac4ef50af66cd4bde238881503ec839928a0135b99a036a9cdfa22d17fd56cdb
+  languageName: node
+  linkType: hard
+
+"etag@npm:^1.8.1, etag@npm:~1.8.1":
   version: 1.8.1
   resolution: "etag@npm:1.8.1"
   checksum: 10/571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff
@@ -2979,6 +3619,46 @@ __metadata:
   languageName: node
   linkType: hard
 
+"express@npm:^5.0.1":
+  version: 5.0.1
+  resolution: "express@npm:5.0.1"
+  dependencies:
+    accepts: "npm:^2.0.0"
+    body-parser: "npm:^2.0.1"
+    content-disposition: "npm:^1.0.0"
+    content-type: "npm:~1.0.4"
+    cookie: "npm:0.7.1"
+    cookie-signature: "npm:^1.2.1"
+    debug: "npm:4.3.6"
+    depd: "npm:2.0.0"
+    encodeurl: "npm:~2.0.0"
+    escape-html: "npm:~1.0.3"
+    etag: "npm:~1.8.1"
+    finalhandler: "npm:^2.0.0"
+    fresh: "npm:2.0.0"
+    http-errors: "npm:2.0.0"
+    merge-descriptors: "npm:^2.0.0"
+    methods: "npm:~1.1.2"
+    mime-types: "npm:^3.0.0"
+    on-finished: "npm:2.4.1"
+    once: "npm:1.4.0"
+    parseurl: "npm:~1.3.3"
+    proxy-addr: "npm:~2.0.7"
+    qs: "npm:6.13.0"
+    range-parser: "npm:~1.2.1"
+    router: "npm:^2.0.0"
+    safe-buffer: "npm:5.2.1"
+    send: "npm:^1.1.0"
+    serve-static: "npm:^2.1.0"
+    setprototypeof: "npm:1.2.0"
+    statuses: "npm:2.0.1"
+    type-is: "npm:^2.0.0"
+    utils-merge: "npm:1.0.1"
+    vary: "npm:~1.1.2"
+  checksum: 10/b6afed019b6c22cb697a658d4dd70966e34f117ad6c83a2d32080c3ec4541443b15be770b4f7ac58bc6c07451a9bd0788121c5c4583c930beea48d8a17ee5c60
+  languageName: node
+  linkType: hard
+
 "ext@npm:^1.7.0":
   version: 1.7.0
   resolution: "ext@npm:1.7.0"
@@ -3006,7 +3686,21 @@ __metadata:
   languageName: node
   linkType: hard
 
-"fast-glob@npm:^3.2.9":
+"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
+  version: 3.1.3
+  resolution: "fast-deep-equal@npm:3.1.3"
+  checksum: 10/e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d
+  languageName: node
+  linkType: hard
+
+"fast-diff@npm:^1.1.2":
+  version: 1.3.0
+  resolution: "fast-diff@npm:1.3.0"
+  checksum: 10/9e57415bc69cd6efcc720b3b8fe9fdaf42dcfc06f86f0f45378b1fa512598a8aac48aa3928c8751d58e2f01bb4ba4f07e4f3d9bc0d57586d45f1bd1e872c6cde
+  languageName: node
+  linkType: hard
+
+"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2":
   version: 3.3.3
   resolution: "fast-glob@npm:3.3.3"
   dependencies:
@@ -3019,6 +3713,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"fast-json-stable-stringify@npm:^2.0.0":
+  version: 2.1.0
+  resolution: "fast-json-stable-stringify@npm:2.1.0"
+  checksum: 10/2c20055c1fa43c922428f16ca8bb29f2807de63e5c851f665f7ac9790176c01c3b40335257736b299764a8d383388dabc73c8083b8e1bc3d99f0a941444ec60e
+  languageName: node
+  linkType: hard
+
+"fast-levenshtein@npm:^2.0.6":
+  version: 2.0.6
+  resolution: "fast-levenshtein@npm:2.0.6"
+  checksum: 10/eb7e220ecf2bab5159d157350b81d01f75726a4382f5a9266f42b9150c4523b9795f7f5d9fbbbeaeac09a441b2369f05ee02db48ea938584205530fe5693cfe1
+  languageName: node
+  linkType: hard
+
 "fastq@npm:^1.6.0":
   version: 1.18.0
   resolution: "fastq@npm:1.18.0"
@@ -3050,6 +3758,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"file-entry-cache@npm:^8.0.0":
+  version: 8.0.0
+  resolution: "file-entry-cache@npm:8.0.0"
+  dependencies:
+    flat-cache: "npm:^4.0.0"
+  checksum: 10/afe55c4de4e0d226a23c1eae62a7219aafb390859122608a89fa4df6addf55c7fd3f1a2da6f5b41e7cdff496e4cf28bbd215d53eab5c817afa96d2b40c81bfb0
+  languageName: node
+  linkType: hard
+
 "fill-range@npm:^7.1.1":
   version: 7.1.1
   resolution: "fill-range@npm:7.1.1"
@@ -3074,6 +3791,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"finalhandler@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "finalhandler@npm:2.0.0"
+  dependencies:
+    debug: "npm:2.6.9"
+    encodeurl: "npm:~1.0.2"
+    escape-html: "npm:~1.0.3"
+    on-finished: "npm:2.4.1"
+    parseurl: "npm:~1.3.3"
+    statuses: "npm:2.0.1"
+    unpipe: "npm:~1.0.0"
+  checksum: 10/59b941fd40fcd2e173c858a47cccd493abf9709df54d5e06ef51be910957b6de7518af79110851f721e826dc246ce4456290d8dfe24a58b13488264690f76ed8
+  languageName: node
+  linkType: hard
+
 "find-up@npm:^4.1.0":
   version: 4.1.0
   resolution: "find-up@npm:4.1.0"
@@ -3084,6 +3816,33 @@ __metadata:
   languageName: node
   linkType: hard
 
+"find-up@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "find-up@npm:5.0.0"
+  dependencies:
+    locate-path: "npm:^6.0.0"
+    path-exists: "npm:^4.0.0"
+  checksum: 10/07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095
+  languageName: node
+  linkType: hard
+
+"flat-cache@npm:^4.0.0":
+  version: 4.0.1
+  resolution: "flat-cache@npm:4.0.1"
+  dependencies:
+    flatted: "npm:^3.2.9"
+    keyv: "npm:^4.5.4"
+  checksum: 10/58ce851d9045fffc7871ce2bd718bc485ad7e777bf748c054904b87c351ff1080c2c11da00788d78738bfb51b71e4d5ea12d13b98eb36e3358851ffe495b62dc
+  languageName: node
+  linkType: hard
+
+"flatted@npm:^3.2.9":
+  version: 3.3.2
+  resolution: "flatted@npm:3.3.2"
+  checksum: 10/ac3c159742e01d0e860a861164bcfd35bb567ccbebb8a0dd041e61cf3c64a435b917dd1e7ed1c380c2ebca85735fb16644485ec33665bc6aafc3b316aa1eed44
+  languageName: node
+  linkType: hard
+
 "follow-redirects@npm:^1.15.6":
   version: 1.15.9
   resolution: "follow-redirects@npm:1.15.9"
@@ -3148,13 +3907,20 @@ __metadata:
   languageName: node
   linkType: hard
 
-"fresh@npm:0.5.2":
+"fresh@npm:0.5.2, fresh@npm:^0.5.2":
   version: 0.5.2
   resolution: "fresh@npm:0.5.2"
   checksum: 10/64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1
   languageName: node
   linkType: hard
 
+"fresh@npm:2.0.0":
+  version: 2.0.0
+  resolution: "fresh@npm:2.0.0"
+  checksum: 10/44e1468488363074641991c1340d2a10c5a6f6d7c353d89fd161c49d120c58ebf9890720f7584f509058385836e3ce50ddb60e9f017315a4ba8c6c3461813bfc
+  languageName: node
+  linkType: hard
+
 "fs-extra@npm:^7.0.1":
   version: 7.0.1
   resolution: "fs-extra@npm:7.0.1"
@@ -3263,6 +4029,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"glob-parent@npm:^6.0.2":
+  version: 6.0.2
+  resolution: "glob-parent@npm:6.0.2"
+  dependencies:
+    is-glob: "npm:^4.0.3"
+  checksum: 10/c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8
+  languageName: node
+  linkType: hard
+
 "glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.1":
   version: 10.4.5
   resolution: "glob@npm:10.4.5"
@@ -3279,6 +4054,27 @@ __metadata:
   languageName: node
   linkType: hard
 
+"globals@npm:^11.1.0":
+  version: 11.12.0
+  resolution: "globals@npm:11.12.0"
+  checksum: 10/9f054fa38ff8de8fa356502eb9d2dae0c928217b8b5c8de1f09f5c9b6c8a96d8b9bd3afc49acbcd384a98a81fea713c859e1b09e214c60509517bb8fc2bc13c2
+  languageName: node
+  linkType: hard
+
+"globals@npm:^14.0.0":
+  version: 14.0.0
+  resolution: "globals@npm:14.0.0"
+  checksum: 10/03939c8af95c6df5014b137cac83aa909090c3a3985caef06ee9a5a669790877af8698ab38007e4c0186873adc14c0b13764acc754b16a754c216cc56aa5f021
+  languageName: node
+  linkType: hard
+
+"globals@npm:^15.14.0":
+  version: 15.14.0
+  resolution: "globals@npm:15.14.0"
+  checksum: 10/e35ffbdbc024d6381efca906f67211a7bbf935db2af8c14a65155785479e28b3e475950e5933bb6b296eed54b6dcd924e25b26dbc8579b1bde9d5d25916e1c5f
+  languageName: node
+  linkType: hard
+
 "globby@npm:^11.0.0":
   version: 11.1.0
   resolution: "globby@npm:11.1.0"
@@ -3307,6 +4103,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"graphemer@npm:^1.4.0":
+  version: 1.4.0
+  resolution: "graphemer@npm:1.4.0"
+  checksum: 10/6dd60dba97007b21e3a829fab3f771803cc1292977fe610e240ea72afd67e5690ac9eeaafc4a99710e78962e5936ab5a460787c2a1180f1cb0ccfac37d29f897
+  languageName: node
+  linkType: hard
+
 "has-flag@npm:^4.0.0":
   version: 4.0.0
   resolution: "has-flag@npm:4.0.0"
@@ -3365,7 +4168,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"http-errors@npm:2.0.0":
+"http-errors@npm:2.0.0, http-errors@npm:^2.0.0":
   version: 2.0.0
   resolution: "http-errors@npm:2.0.0"
   dependencies:
@@ -3423,7 +4226,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"iconv-lite@npm:^0.6.2":
+"iconv-lite@npm:0.5.2":
+  version: 0.5.2
+  resolution: "iconv-lite@npm:0.5.2"
+  dependencies:
+    safer-buffer: "npm:>= 2.1.2 < 3"
+  checksum: 10/b48a1c8a173b638cb3d9a21674acbfed1c1fd8e81f6dc52e63cf44d3b56f37fd48f8ff81d93a71c8b60b4dfb464d3e87f606df5f8a0f0247c21737665059565c
+  languageName: node
+  linkType: hard
+
+"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
   version: 0.6.3
   resolution: "iconv-lite@npm:0.6.3"
   dependencies:
@@ -3432,13 +4244,23 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ignore@npm:^5.2.0":
+"ignore@npm:^5.2.0, ignore@npm:^5.3.1":
   version: 5.3.2
   resolution: "ignore@npm:5.3.2"
   checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98
   languageName: node
   linkType: hard
 
+"import-fresh@npm:^3.2.1":
+  version: 3.3.0
+  resolution: "import-fresh@npm:3.3.0"
+  dependencies:
+    parent-module: "npm:^1.0.0"
+    resolve-from: "npm:^4.0.0"
+  checksum: 10/2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa
+  languageName: node
+  linkType: hard
+
 "imurmurhash@npm:^0.1.4":
   version: 0.1.4
   resolution: "imurmurhash@npm:0.1.4"
@@ -3493,7 +4315,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"is-glob@npm:^4.0.1":
+"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3":
   version: 4.0.3
   resolution: "is-glob@npm:4.0.3"
   dependencies:
@@ -3516,6 +4338,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"is-promise@npm:4.0.0":
+  version: 4.0.0
+  resolution: "is-promise@npm:4.0.0"
+  checksum: 10/0b46517ad47b00b6358fd6553c83ec1f6ba9acd7ffb3d30a0bf519c5c69e7147c132430452351b8a9fc198f8dd6c4f76f8e6f5a7f100f8c77d57d9e0f4261a8a
+  languageName: node
+  linkType: hard
+
 "is-subdir@npm:^1.1.1":
   version: 1.2.0
   resolution: "is-subdir@npm:1.2.0"
@@ -3640,6 +4469,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"js-yaml@npm:^4.1.0":
+  version: 4.1.0
+  resolution: "js-yaml@npm:4.1.0"
+  dependencies:
+    argparse: "npm:^2.0.1"
+  bin:
+    js-yaml: bin/js-yaml.js
+  checksum: 10/c138a34a3fd0d08ebaf71273ad4465569a483b8a639e0b118ff65698d257c2791d3199e3f303631f2cb98213fa7b5f5d6a4621fd0fff819421b990d30d967140
+  languageName: node
+  linkType: hard
+
 "jsbn@npm:1.1.0":
   version: 1.1.0
   resolution: "jsbn@npm:1.1.0"
@@ -3647,6 +4487,36 @@ __metadata:
   languageName: node
   linkType: hard
 
+"jsesc@npm:^3.0.2":
+  version: 3.1.0
+  resolution: "jsesc@npm:3.1.0"
+  bin:
+    jsesc: bin/jsesc
+  checksum: 10/20bd37a142eca5d1794f354db8f1c9aeb54d85e1f5c247b371de05d23a9751ecd7bd3a9c4fc5298ea6fa09a100dafb4190fa5c98c6610b75952c3487f3ce7967
+  languageName: node
+  linkType: hard
+
+"json-buffer@npm:3.0.1":
+  version: 3.0.1
+  resolution: "json-buffer@npm:3.0.1"
+  checksum: 10/82876154521b7b68ba71c4f969b91572d1beabadd87bd3a6b236f85fbc7dc4695089191ed60bb59f9340993c51b33d479f45b6ba9f3548beb519705281c32c3c
+  languageName: node
+  linkType: hard
+
+"json-schema-traverse@npm:^0.4.1":
+  version: 0.4.1
+  resolution: "json-schema-traverse@npm:0.4.1"
+  checksum: 10/7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b
+  languageName: node
+  linkType: hard
+
+"json-stable-stringify-without-jsonify@npm:^1.0.1":
+  version: 1.0.1
+  resolution: "json-stable-stringify-without-jsonify@npm:1.0.1"
+  checksum: 10/12786c2e2f22c27439e6db0532ba321f1d0617c27ad8cb1c352a0e9249a50182fd1ba8b52a18899291604b0c32eafa8afd09e51203f19109a0537f68db2b652d
+  languageName: node
+  linkType: hard
+
 "jsonfile@npm:^4.0.0":
   version: 4.0.0
   resolution: "jsonfile@npm:4.0.0"
@@ -3659,6 +4529,25 @@ __metadata:
   languageName: node
   linkType: hard
 
+"keyv@npm:^4.5.4":
+  version: 4.5.4
+  resolution: "keyv@npm:4.5.4"
+  dependencies:
+    json-buffer: "npm:3.0.1"
+  checksum: 10/167eb6ef64cc84b6fa0780ee50c9de456b422a1e18802209234f7c2cf7eae648c7741f32e50d7e24ccb22b24c13154070b01563d642755b156c357431a191e75
+  languageName: node
+  linkType: hard
+
+"levn@npm:^0.4.1":
+  version: 0.4.1
+  resolution: "levn@npm:0.4.1"
+  dependencies:
+    prelude-ls: "npm:^1.2.1"
+    type-check: "npm:~0.4.0"
+  checksum: 10/2e4720ff79f21ae08d42374b0a5c2f664c5be8b6c8f565bb4e1315c96ed3a8acaa9de788ffed82d7f2378cf36958573de07ef92336cb5255ed74d08b8318c9ee
+  languageName: node
+  linkType: hard
+
 "locate-path@npm:^5.0.0":
   version: 5.0.0
   resolution: "locate-path@npm:5.0.0"
@@ -3668,6 +4557,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"locate-path@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "locate-path@npm:6.0.0"
+  dependencies:
+    p-locate: "npm:^5.0.0"
+  checksum: 10/72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a
+  languageName: node
+  linkType: hard
+
+"lodash.merge@npm:^4.6.2":
+  version: 4.6.2
+  resolution: "lodash.merge@npm:4.6.2"
+  checksum: 10/d0ea2dd0097e6201be083865d50c3fb54fbfbdb247d9cc5950e086c991f448b7ab0cdab0d57eacccb43473d3f2acd21e134db39f22dac2d6c9ba6bf26978e3d6
+  languageName: node
+  linkType: hard
+
 "lodash.startcase@npm:^4.4.0":
   version: 4.4.0
   resolution: "lodash.startcase@npm:4.4.0"
@@ -3765,6 +4670,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"media-typer@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "media-typer@npm:1.1.0"
+  checksum: 10/a58dd60804df73c672942a7253ccc06815612326dc1c0827984b1a21704466d7cde351394f47649e56cf7415e6ee2e26e000e81b51b3eebb5a93540e8bf93cbd
+  languageName: node
+  linkType: hard
+
 "merge-descriptors@npm:1.0.3":
   version: 1.0.3
   resolution: "merge-descriptors@npm:1.0.3"
@@ -3772,6 +4684,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"merge-descriptors@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "merge-descriptors@npm:2.0.0"
+  checksum: 10/e383332e700a94682d0125a36c8be761142a1320fc9feeb18e6e36647c9edf064271645f5669b2c21cf352116e561914fd8aa831b651f34db15ef4038c86696a
+  languageName: node
+  linkType: hard
+
 "merge2@npm:^1.3.0, merge2@npm:^1.4.1":
   version: 1.4.1
   resolution: "merge2@npm:1.4.1"
@@ -3803,7 +4722,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
+"mime-db@npm:^1.53.0":
+  version: 1.53.0
+  resolution: "mime-db@npm:1.53.0"
+  checksum: 10/82409c568a20254cc67a763a25e581d2213e1ef5d070a0af805239634f8a655f5d8a15138200f5f81c5b06fc6623d27f6168c612d447642d59e37eb7f20f7412
+  languageName: node
+  linkType: hard
+
+"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
   version: 2.1.35
   resolution: "mime-types@npm:2.1.35"
   dependencies:
@@ -3812,6 +4738,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"mime-types@npm:^3.0.0":
+  version: 3.0.0
+  resolution: "mime-types@npm:3.0.0"
+  dependencies:
+    mime-db: "npm:^1.53.0"
+  checksum: 10/819584a951124b1cdee21e0c5515d174e1df018407b837297cef0da0620e4c0551336909fc3704166fca3a3fc141d19976bcc34e94eb720af04bbf4b50b43545
+  languageName: node
+  linkType: hard
+
 "mime@npm:1.6.0":
   version: 1.6.0
   resolution: "mime@npm:1.6.0"
@@ -3835,6 +4770,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"minimatch@npm:^3.1.2":
+  version: 3.1.2
+  resolution: "minimatch@npm:3.1.2"
+  dependencies:
+    brace-expansion: "npm:^1.1.7"
+  checksum: 10/e0b25b04cd4ec6732830344e5739b13f8690f8a012d73445a4a19fbc623f5dd481ef7a5827fde25954cd6026fede7574cc54dc4643c99d6c6b653d6203f94634
+  languageName: node
+  linkType: hard
+
 "minimatch@npm:^9.0.4":
   version: 9.0.5
   resolution: "minimatch@npm:9.0.5"
@@ -3944,6 +4888,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"ms@npm:2.1.2":
+  version: 2.1.2
+  resolution: "ms@npm:2.1.2"
+  checksum: 10/673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f
+  languageName: node
+  linkType: hard
+
 "ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.3":
   version: 2.1.3
   resolution: "ms@npm:2.1.3"
@@ -3960,6 +4911,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"natural-compare@npm:^1.4.0":
+  version: 1.4.0
+  resolution: "natural-compare@npm:1.4.0"
+  checksum: 10/23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d
+  languageName: node
+  linkType: hard
+
 "negotiator@npm:0.6.3":
   version: 0.6.3
   resolution: "negotiator@npm:0.6.3"
@@ -4062,7 +5020,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"on-finished@npm:2.4.1":
+"on-finished@npm:2.4.1, on-finished@npm:^2.4.1":
   version: 2.4.1
   resolution: "on-finished@npm:2.4.1"
   dependencies:
@@ -4071,6 +5029,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"once@npm:1.4.0":
+  version: 1.4.0
+  resolution: "once@npm:1.4.0"
+  dependencies:
+    wrappy: "npm:1"
+  checksum: 10/cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68
+  languageName: node
+  linkType: hard
+
 "openai@npm:latest":
   version: 4.79.1
   resolution: "openai@npm:4.79.1"
@@ -4096,6 +5063,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"optionator@npm:^0.9.3":
+  version: 0.9.4
+  resolution: "optionator@npm:0.9.4"
+  dependencies:
+    deep-is: "npm:^0.1.3"
+    fast-levenshtein: "npm:^2.0.6"
+    levn: "npm:^0.4.1"
+    prelude-ls: "npm:^1.2.1"
+    type-check: "npm:^0.4.0"
+    word-wrap: "npm:^1.2.5"
+  checksum: 10/a8398559c60aef88d7f353a4f98dcdff6090a4e70f874c827302bf1213d9106a1c4d5fcb68dacb1feb3c30a04c4102f41047aa55d4c576b863d6fc876e001af6
+  languageName: node
+  linkType: hard
+
 "os-tmpdir@npm:~1.0.2":
   version: 1.0.2
   resolution: "os-tmpdir@npm:1.0.2"
@@ -4148,6 +5129,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"p-limit@npm:^3.0.2":
+  version: 3.1.0
+  resolution: "p-limit@npm:3.1.0"
+  dependencies:
+    yocto-queue: "npm:^0.1.0"
+  checksum: 10/7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360
+  languageName: node
+  linkType: hard
+
 "p-locate@npm:^4.1.0":
   version: 4.1.0
   resolution: "p-locate@npm:4.1.0"
@@ -4157,6 +5147,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"p-locate@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "p-locate@npm:5.0.0"
+  dependencies:
+    p-limit: "npm:^3.0.2"
+  checksum: 10/1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3
+  languageName: node
+  linkType: hard
+
 "p-map@npm:^2.0.0":
   version: 2.1.0
   resolution: "p-map@npm:2.1.0"
@@ -4192,7 +5191,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"parseurl@npm:~1.3.3":
+"parent-module@npm:^1.0.0":
+  version: 1.0.1
+  resolution: "parent-module@npm:1.0.1"
+  dependencies:
+    callsites: "npm:^3.0.0"
+  checksum: 10/6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff
+  languageName: node
+  linkType: hard
+
+"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3":
   version: 1.3.3
   resolution: "parseurl@npm:1.3.3"
   checksum: 10/407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2
@@ -4237,6 +5245,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"path-to-regexp@npm:^8.0.0":
+  version: 8.2.0
+  resolution: "path-to-regexp@npm:8.2.0"
+  checksum: 10/23378276a172b8ba5f5fb824475d1818ca5ccee7bbdb4674701616470f23a14e536c1db11da9c9e6d82b82c556a817bbf4eee6e41b9ed20090ef9427cbb38e13
+  languageName: node
+  linkType: hard
+
 "path-type@npm:^4.0.0":
   version: 4.0.0
   resolution: "path-type@npm:4.0.0"
@@ -4297,6 +5312,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"prelude-ls@npm:^1.2.1":
+  version: 1.2.1
+  resolution: "prelude-ls@npm:1.2.1"
+  checksum: 10/0b9d2c76801ca652a7f64892dd37b7e3fab149a37d2424920099bf894acccc62abb4424af2155ab36dea8744843060a2d8ddc983518d0b1e22265a22324b72ed
+  languageName: node
+  linkType: hard
+
+"prettier-linter-helpers@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "prettier-linter-helpers@npm:1.0.0"
+  dependencies:
+    fast-diff: "npm:^1.1.2"
+  checksum: 10/00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392
+  languageName: node
+  linkType: hard
+
 "prettier-plugin-packagejson@npm:^2.5.8":
   version: 2.5.8
   resolution: "prettier-plugin-packagejson@npm:2.5.8"
@@ -4384,7 +5415,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"punycode@npm:^2.3.1":
+"punycode@npm:^2.1.0, punycode@npm:^2.3.1":
   version: 2.3.1
   resolution: "punycode@npm:2.3.1"
   checksum: 10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059
@@ -4407,7 +5438,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"range-parser@npm:~1.2.1":
+"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1":
   version: 1.2.1
   resolution: "range-parser@npm:1.2.1"
   checksum: 10/ce21ef2a2dd40506893157970dc76e835c78cf56437e26e19189c48d5291e7279314477b06ac38abd6a401b661a6840f7b03bd0b1249da9b691deeaa15872c26
@@ -4426,6 +5457,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"raw-body@npm:^3.0.0":
+  version: 3.0.0
+  resolution: "raw-body@npm:3.0.0"
+  dependencies:
+    bytes: "npm:3.1.2"
+    http-errors: "npm:2.0.0"
+    iconv-lite: "npm:0.6.3"
+    unpipe: "npm:1.0.0"
+  checksum: 10/2443429bbb2f9ae5c50d3d2a6c342533dfbde6b3173740b70fa0302b30914ff400c6d31a46b3ceacbe7d0925dc07d4413928278b494b04a65736fc17ca33e30c
+  languageName: node
+  linkType: hard
+
 "read-yaml-file@npm:^1.1.0":
   version: 1.1.0
   resolution: "read-yaml-file@npm:1.1.0"
@@ -4452,6 +5495,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"resolve-from@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "resolve-from@npm:4.0.0"
+  checksum: 10/91eb76ce83621eea7bbdd9b55121a5c1c4a39e54a9ce04a9ad4517f102f8b5131c2cf07622c738a6683991bf54f2ce178f5a42803ecbd527ddc5105f362cc9e3
+  languageName: node
+  linkType: hard
+
 "resolve-from@npm:^5.0.0":
   version: 5.0.0
   resolution: "resolve-from@npm:5.0.0"
@@ -4670,6 +5720,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"router@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "router@npm:2.0.0"
+  dependencies:
+    array-flatten: "npm:3.0.0"
+    is-promise: "npm:4.0.0"
+    methods: "npm:~1.1.2"
+    parseurl: "npm:~1.3.3"
+    path-to-regexp: "npm:^8.0.0"
+    setprototypeof: "npm:1.2.0"
+    utils-merge: "npm:1.0.1"
+  checksum: 10/cb0b044f0672eca104239680ac16d2629809df41a886a07a5ec319c683ef3c09c4ac0c88a91de2cea3da7d314ea6054d9c35840851ab55a3c2230e9ba690a885
+  languageName: node
+  linkType: hard
+
 "run-parallel@npm:^1.1.9":
   version: 1.2.0
   resolution: "run-parallel@npm:1.2.0"
@@ -4709,7 +5774,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.6.0":
+"semver@npm:^7.3.5, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.6.0":
   version: 7.6.3
   resolution: "semver@npm:7.6.3"
   bin:
@@ -4739,6 +5804,26 @@ __metadata:
   languageName: node
   linkType: hard
 
+"send@npm:^1.0.0, send@npm:^1.1.0":
+  version: 1.1.0
+  resolution: "send@npm:1.1.0"
+  dependencies:
+    debug: "npm:^4.3.5"
+    destroy: "npm:^1.2.0"
+    encodeurl: "npm:^2.0.0"
+    escape-html: "npm:^1.0.3"
+    etag: "npm:^1.8.1"
+    fresh: "npm:^0.5.2"
+    http-errors: "npm:^2.0.0"
+    mime-types: "npm:^2.1.35"
+    ms: "npm:^2.1.3"
+    on-finished: "npm:^2.4.1"
+    range-parser: "npm:^1.2.1"
+    statuses: "npm:^2.0.1"
+  checksum: 10/5040d4d1e52a2a4634a3381a0c21be8115543be3ac0345b99c16d2510af2391968e1c4031ac3e1620cca6948f5ff888f39fa6515c4b6005c6c792c56300ea997
+  languageName: node
+  linkType: hard
+
 "serve-static@npm:1.16.2":
   version: 1.16.2
   resolution: "serve-static@npm:1.16.2"
@@ -4751,6 +5836,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"serve-static@npm:^2.1.0":
+  version: 2.1.0
+  resolution: "serve-static@npm:2.1.0"
+  dependencies:
+    encodeurl: "npm:^2.0.0"
+    escape-html: "npm:^1.0.3"
+    parseurl: "npm:^1.3.3"
+    send: "npm:^1.0.0"
+  checksum: 10/ecb5969b66520e6546721454e72ee3fbe827fee16224a563d258d71ab68d9316991c81910b94bd2a7b75112669ef887068ab0ef66a4bf524ed8ed9c919a01de0
+  languageName: node
+  linkType: hard
+
 "setprototypeof@npm:1.2.0":
   version: 1.2.0
   resolution: "setprototypeof@npm:1.2.0"
@@ -4950,7 +6047,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"statuses@npm:2.0.1":
+"statuses@npm:2.0.1, statuses@npm:^2.0.1":
   version: 2.0.1
   resolution: "statuses@npm:2.0.1"
   checksum: 10/18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb
@@ -5011,6 +6108,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"strip-json-comments@npm:^3.1.1":
+  version: 3.1.1
+  resolution: "strip-json-comments@npm:3.1.1"
+  checksum: 10/492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443
+  languageName: node
+  linkType: hard
+
 "sturdy-websocket@npm:^0.2.1":
   version: 0.2.1
   resolution: "sturdy-websocket@npm:0.2.1"
@@ -5034,7 +6138,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"synckit@npm:0.9.2":
+"synckit@npm:0.9.2, synckit@npm:^0.9.1":
   version: 0.9.2
   resolution: "synckit@npm:0.9.2"
   dependencies:
@@ -5153,6 +6257,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"ts-api-utils@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "ts-api-utils@npm:2.0.0"
+  peerDependencies:
+    typescript: ">=4.8.4"
+  checksum: 10/485bdf8bbba98d58712243d958f4fd44742bbe49e559cd77882fb426d866eec6dd05c67ef91935dc4f8a3c776f235859735e1f05be399e4dc9e7ffd580120974
+  languageName: node
+  linkType: hard
+
 "ts-node@npm:^10.9.2":
   version: 10.9.2
   resolution: "ts-node@npm:10.9.2"
@@ -5269,6 +6382,26 @@ __metadata:
   languageName: node
   linkType: hard
 
+"type-check@npm:^0.4.0, type-check@npm:~0.4.0":
+  version: 0.4.0
+  resolution: "type-check@npm:0.4.0"
+  dependencies:
+    prelude-ls: "npm:^1.2.1"
+  checksum: 10/14687776479d048e3c1dbfe58a2409e00367810d6960c0f619b33793271ff2a27f81b52461f14a162f1f89a9b1d8da1b237fc7c99b0e1fdcec28ec63a86b1fec
+  languageName: node
+  linkType: hard
+
+"type-is@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "type-is@npm:2.0.0"
+  dependencies:
+    content-type: "npm:^1.0.5"
+    media-typer: "npm:^1.1.0"
+    mime-types: "npm:^3.0.0"
+  checksum: 10/056ae0e94fc7e01209f001d2b4506e39908d95e454aef6eefec7f8f252a00b15c6c0a9707fa3d4d6a83be8ea3ea95fe1d6cfd5bfe7ef90831b61875f5512f441
+  languageName: node
+  linkType: hard
+
 "type-is@npm:~1.6.18":
   version: 1.6.18
   resolution: "type-is@npm:1.6.18"
@@ -5295,6 +6428,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"typescript-eslint@npm:^8.21.0":
+  version: 8.21.0
+  resolution: "typescript-eslint@npm:8.21.0"
+  dependencies:
+    "@typescript-eslint/eslint-plugin": "npm:8.21.0"
+    "@typescript-eslint/parser": "npm:8.21.0"
+    "@typescript-eslint/utils": "npm:8.21.0"
+  peerDependencies:
+    eslint: ^8.57.0 || ^9.0.0
+    typescript: ">=4.8.4 <5.8.0"
+  checksum: 10/8bb7dce0084ea380b1f55046bead0adbaf57d1f5cdfa7b82a89eec18377fa2cd4e0e9746b4c5e8193899cf4de09c659032bbad19e2a8e9db54d53a596e176c5f
+  languageName: node
+  linkType: hard
+
 "typescript@npm:^5.7.3":
   version: 5.7.3
   resolution: "typescript@npm:5.7.3"
@@ -5370,6 +6517,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"uri-js@npm:^4.2.2":
+  version: 4.4.1
+  resolution: "uri-js@npm:4.4.1"
+  dependencies:
+    punycode: "npm:^2.1.0"
+  checksum: 10/b271ca7e3d46b7160222e3afa3e531505161c9a4e097febae9664e4b59912f4cbe94861361a4175edac3a03fee99d91e44b6a58c17a634bc5a664b19fc76fbcb
+  languageName: node
+  linkType: hard
+
 "utf-8-validate@npm:^5.0.2":
   version: 5.0.10
   resolution: "utf-8-validate@npm:5.0.10"
@@ -5609,6 +6765,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"word-wrap@npm:^1.2.5":
+  version: 1.2.5
+  resolution: "word-wrap@npm:1.2.5"
+  checksum: 10/1ec6f6089f205f83037be10d0c4b34c9183b0b63fca0834a5b3cee55dd321429d73d40bb44c8fc8471b5203d6e8f8275717f49a8ff4b2b0ab41d7e1b563e0854
+  languageName: node
+  linkType: hard
+
 "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version: 7.0.0
   resolution: "wrap-ansi@npm:7.0.0"
@@ -5631,6 +6794,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"wrappy@npm:1":
+  version: 1.0.2
+  resolution: "wrappy@npm:1.0.2"
+  checksum: 10/159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5
+  languageName: node
+  linkType: hard
+
 "ws@npm:7.4.6":
   version: 7.4.6
   resolution: "ws@npm:7.4.6"
@@ -5668,12 +6838,21 @@ __metadata:
     "@changesets/changelog-git": "npm:^0.2.0"
     "@changesets/cli": "npm:^2.27.11"
     "@clack/prompts": "npm:^0.9.1"
+    "@eslint/compat": "npm:^1.2.5"
+    "@eslint/js": "npm:^9.18.0"
+    "@ianvs/prettier-plugin-sort-imports": "npm:^4.4.1"
+    "@types/eslint__js": "npm:^8.42.3"
+    eslint: "npm:^9.18.0"
+    eslint-config-prettier: "npm:^10.0.1"
+    eslint-plugin-prettier: "npm:^5.2.3"
+    globals: "npm:^15.14.0"
     prettier: "npm:^3.4.2"
     prettier-plugin-packagejson: "npm:^2.5.8"
     punycode: "npm:^2.3.1"
     readline-sync: "npm:^1.4.10"
     turbo: "npm:^2.3.4"
     typescript: "npm:^5.7.3"
+    typescript-eslint: "npm:^8.21.0"
   languageName: unknown
   linkType: soft
 
@@ -5704,3 +6883,10 @@ __metadata:
   checksum: 10/2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6
   languageName: node
   linkType: hard
+
+"yocto-queue@npm:^0.1.0":
+  version: 0.1.0
+  resolution: "yocto-queue@npm:0.1.0"
+  checksum: 10/f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700
+  languageName: node
+  linkType: hard