diff --git a/.env.example b/.env.example index a2f07f1480..0d808f655b 100644 --- a/.env.example +++ b/.env.example @@ -225,6 +225,12 @@ WALLET_SECRET_SALT= # ONLY DEFINE IF YOU WANT TO USE TEE Plugin, otherwise it wi # Galadriel Configuration GALADRIEL_API_KEY=gal-* # Get from https://dashboard.galadriel.com/ +# Venice Configuration +VENICE_API_KEY= # generate from venice settings +SMALL_VENICE_MODEL= # Default: llama-3.3-70b +MEDIUM_VENICE_MODEL= # Default: llama-3.3-70b +LARGE_VENICE_MODEL= # Default: llama-3.1-405b + # fal.ai Configuration FAL_API_KEY= FAL_AI_LORA_PATH= @@ -264,3 +270,7 @@ AWS_SECRET_ACCESS_KEY= AWS_REGION= AWS_S3_BUCKET= AWS_S3_UPLOAD_PATH= + + +# Deepgram +DEEPGRAM_API_KEY= diff --git a/.github/workflows/integrationTests.yaml b/.github/workflows/integrationTests.yaml index cd9441507d..86f1b6f20e 100644 --- a/.github/workflows/integrationTests.yaml +++ b/.github/workflows/integrationTests.yaml @@ -3,7 +3,7 @@ on: push: branches: - "*" - pull_request: + pull_request_target: branches: - "*" jobs: diff --git a/agent/src/index.ts b/agent/src/index.ts index bb631a8136..cd92b6005d 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -286,6 +286,11 @@ export function getTokenForProvider( character.settings?.secrets?.HYPERBOLIC_API_KEY || settings.HYPERBOLIC_API_KEY ); + case ModelProviderName.VENICE: + return ( + character.settings?.secrets?.VENICE_API_KEY || + settings.VENICE_API_KEY + ); } } @@ -318,42 +323,53 @@ function initializeDatabase(dataDir: string) { } } +// also adds plugins from character file into the runtime export async function initializeClients( character: Character, runtime: IAgentRuntime ) { - const clients = []; - const clientTypes = + // each client can only register once + // and if we want two we can explicitly support it + const clients: Record = {}; + const clientTypes:string[] = character.clients?.map((str) => str.toLowerCase()) || []; + elizaLogger.log('initializeClients', clientTypes, 'for', character.name) if (clientTypes.includes("auto")) { const autoClient = await AutoClientInterface.start(runtime); - if (autoClient) clients.push(autoClient); + if (autoClient) clients.auto = autoClient; } if (clientTypes.includes("discord")) { - clients.push(await DiscordClientInterface.start(runtime)); + const discordClient = await DiscordClientInterface.start(runtime); + if (discordClient) clients.discord = discordClient; } if (clientTypes.includes("telegram")) { const telegramClient = await TelegramClientInterface.start(runtime); - if (telegramClient) clients.push(telegramClient); + if (telegramClient) clients.telegram = telegramClient; } if (clientTypes.includes("twitter")) { TwitterClientInterface.enableSearch = !isFalsish(getSecret(character, "TWITTER_SEARCH_ENABLE")); - const twitterClients = await TwitterClientInterface.start(runtime); - clients.push(twitterClients); + const twitterClient = await TwitterClientInterface.start(runtime); + if (twitterClient) clients.twitter = twitterClient; } if (clientTypes.includes("farcaster")) { - const farcasterClients = new FarcasterAgentClient(runtime); - farcasterClients.start(); - clients.push(farcasterClients); + // why is this one different :( + const farcasterClient = new FarcasterAgentClient(runtime); + if (farcasterClient) { + farcasterClient.start(); + clients.farcaster = farcasterClient; + } } + elizaLogger.log('client keys', Object.keys(clients)); + if (character.plugins?.length > 0) { for (const plugin of character.plugins) { + // if plugin has clients, add those.. if (plugin.clients) { for (const client of plugin.clients) { clients.push(await client.start(runtime)); @@ -382,7 +398,7 @@ function isFalsish(input: any): boolean { } function getSecret(character: Character, secret: string) { - return character.settings.secrets?.[secret] || process.env[secret]; + return character.settings?.secrets?.[secret] || process.env[secret]; } let nodePlugin: any | undefined; @@ -392,7 +408,7 @@ export async function createAgent( db: IDatabaseAdapter, cache: ICacheManager, token: string -) { +):AgentRuntime { elizaLogger.success( elizaLogger.successesTitle, "Creating runtime for character", @@ -425,6 +441,7 @@ export async function createAgent( modelProvider: character.modelProvider, evaluators: [], character, + // character.plugins are handled when clients are added plugins: [ bootstrapPlugin, getSecret(character, "CONFLUX_CORE_PRIVATE_KEY") @@ -495,7 +512,7 @@ function initializeDbCache(character: Character, db: IDatabaseCacheAdapter) { return cache; } -async function startAgent(character: Character, directClient) { +async function startAgent(character: Character, directClient):AgentRuntime { let db: IDatabaseAdapter & IDatabaseCacheAdapter; try { character.id ??= stringToUuid(character.name); @@ -514,15 +531,21 @@ async function startAgent(character: Character, directClient) { await db.init(); const cache = initializeDbCache(character, db); - const runtime = await createAgent(character, db, cache, token); + const runtime:AgentRuntime = await createAgent(character, db, cache, token); + // start services/plugins/process knowledge await runtime.initialize(); - const clients = await initializeClients(character, runtime); + // start assigned clients + runtime.clients = await initializeClients(character, runtime); + // add to container directClient.registerAgent(runtime); - return clients; + // report to console + elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`) + + return runtime; } catch (error) { elizaLogger.error( `Error starting agent for character ${character.name}:`, @@ -566,8 +589,8 @@ const startAgents = async () => { }); } - elizaLogger.log("Chat started. Type 'exit' to quit."); if (!args["non-interactive"]) { + elizaLogger.log("Chat started. Type 'exit' to quit."); chat(); } }; diff --git a/docs/docs/core/characterfile.md b/docs/docs/core/characterfile.md index 8662a54871..37adc65224 100644 --- a/docs/docs/core/characterfile.md +++ b/docs/docs/core/characterfile.md @@ -22,7 +22,7 @@ A `characterfile` implements the [Character](/api/type-aliases/character) type a ```json { "name": "trump", - "clients": ["DISCORD", "DIRECT"], + "clients": ["discord", "direct"], "settings": { "voice": { "model": "en_US-male-medium" } }, @@ -92,11 +92,11 @@ The character's display name for identification and in conversations. #### `modelProvider` (required) -Specifies the AI model provider. Supported options from [ModelProviderName](/api/enumerations/modelprovidername) include `ANTHROPIC`, `LLAMALOCAL`, `OPENAI`, and others. +Specifies the AI model provider. Supported options from [ModelProviderName](/api/enumerations/modelprovidername) include `anthropic`, `llama_local`, `openai`, and others. #### `clients` (required) -Array of supported client types from [Clients](/api/enumerations/clients) e.g., `DISCORD`, `DIRECT`, `TWITTER`, `TELEGRAM`. +Array of supported client types from [Clients](/api/enumerations/clients) e.g., `discord`, `direct`, `twitter`, `telegram`, `farcaster`. #### `bio` @@ -261,8 +261,8 @@ Your response should not contain any questions. Brief, concise statements only. ```json { "name": "TechAI", - "modelProvider": "ANTHROPIC", - "clients": ["DISCORD", "DIRECT"], + "modelProvider": "anthropic", + "clients": ["discord", "direct"], "bio": "AI researcher and educator focused on practical applications", "lore": [ "Pioneer in open-source AI development", diff --git a/lerna.json b/lerna.json index 8ce6c7af19..e8390a9625 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "version": "0.1.5-alpha.5", - "packages": ["packages/*", "docs", "agent", "client"], + "packages": ["packages/*", "docs", "agent", "client", "!packages/_examples"], "npmClient": "pnpm" } diff --git a/package.json b/package.json index ac6da05dad..55021a62d3 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,10 @@ "dependencies": { "@0glabs/0g-ts-sdk": "0.2.1", "@coinbase/coinbase-sdk": "0.10.0", + "@deepgram/sdk": "^3.9.0", + "@vitest/eslint-plugin": "1.0.1", "amqplib": "0.10.5", "csv-parse": "5.6.0", - "@vitest/eslint-plugin": "1.0.1", "ollama-ai-provider": "0.16.1", "optional": "0.1.4", "pnpm": "9.14.4", diff --git a/packages/_examples/plugin/.npmignore b/packages/_examples/plugin/.npmignore new file mode 100644 index 0000000000..078562ecea --- /dev/null +++ b/packages/_examples/plugin/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/** +!package.json +!readme.md +!tsup.config.ts \ No newline at end of file diff --git a/packages/_examples/plugin/README.md b/packages/_examples/plugin/README.md new file mode 100644 index 0000000000..12b04e1dda --- /dev/null +++ b/packages/_examples/plugin/README.md @@ -0,0 +1,32 @@ +# Sample Plugin for Eliza + +The Sample Plugin for Eliza extends the functionality of the Eliza platform by providing additional actions, providers, evaluators, and more. This plugin is designed to be easily extendable and customizable to fit various use cases. + +## Description +The Sample Plugin offers a set of features that can be integrated into the Eliza platform to enhance its capabilities. Below is a high-level overview of the different components available in this plugin. + +## Actions +- **createResourceAction**: This action enables the creation and management of generic resources. It can be customized to handle different types of resources and integrate with various data sources. + +## Providers +- **sampleProvider**: This provider offers a mechanism to supply data or services to the plugin. It can be extended to include additional providers as needed. + +## Evaluators +- **sampleEvaluator**: This evaluator provides a way to assess or analyze data within the plugin. It can be extended to include additional evaluators as needed. + +## Services +- **[ServiceName]**: Description of the service and its functionality. This can be extended to include additional services as needed. + +## Clients +- **[ClientName]**: Description of the client and its functionality. This can be extended to include additional clients as needed. + +## How to Extend +To extend the Sample Plugin, you can add new actions, providers, evaluators, services, and clients by following the structure provided in the plugin. Each component can be customized to fit your specific requirements. + +1. **Actions**: Add new actions by defining them in the `actions` array. +2. **Providers**: Add new providers by defining them in the `providers` array. +3. **Evaluators**: Add new evaluators by defining them in the `evaluators` array. +4. **Services**: Add new services by defining them in the `services` array. +5. **Clients**: Add new clients by defining them in the `clients` array. + +For more detailed information on how to extend the plugin, refer to the documentation provided in the Eliza platform. diff --git a/packages/_examples/plugin/eslint.config.mjs b/packages/_examples/plugin/eslint.config.mjs new file mode 100644 index 0000000000..92fe5bbebe --- /dev/null +++ b/packages/_examples/plugin/eslint.config.mjs @@ -0,0 +1,3 @@ +import eslintGlobalConfig from "../../eslint.config.mjs"; + +export default [...eslintGlobalConfig]; diff --git a/packages/_examples/plugin/package.json b/packages/_examples/plugin/package.json new file mode 100644 index 0000000000..a9d8ab03e0 --- /dev/null +++ b/packages/_examples/plugin/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ai16z/plugin-sample", + "version": "0.1.5-alpha.5", + "main": "dist/index.js", + "type": "module", + "types": "dist/index.d.ts", + "dependencies": { + "@ai16z/eliza": "workspace:*" + }, + "devDependencies": { + "tsup": "8.3.5", + "@types/node": "^20.0.0" + }, + "scripts": { + "build": "tsup --format esm --dts", + "dev": "tsup --format esm --dts --watch", + "lint": "eslint . --fix" + } +} diff --git a/packages/_examples/plugin/src/actions/sampleAction.ts b/packages/_examples/plugin/src/actions/sampleAction.ts new file mode 100644 index 0000000000..33ed90e87e --- /dev/null +++ b/packages/_examples/plugin/src/actions/sampleAction.ts @@ -0,0 +1,117 @@ +import { + Action, + IAgentRuntime, + Memory, + HandlerCallback, + State, + composeContext, + generateObjectV2, + ModelClass, + elizaLogger, +} from "@ai16z/eliza"; + +import { + CreateResourceSchema, + isCreateResourceContent, +} from "../types"; + +import { createResourceTemplate } from "../templates"; + +export const createResourceAction: Action = { + name: "CREATE_RESOURCE", + description: "Create a new resource with the specified details", + validate: async (runtime: IAgentRuntime, _message: Memory) => { + return !!(runtime.character.settings.secrets?.API_KEY); + }, + handler: async ( + runtime: IAgentRuntime, + _message: Memory, + state: State, + _options: any, + callback: HandlerCallback + ) => { + try { + const context = composeContext({ + state, + template: createResourceTemplate, + }); + + const resourceDetails = await generateObjectV2({ + runtime, + context, + modelClass: ModelClass.SMALL, + schema: CreateResourceSchema, + }); + + if (!isCreateResourceContent(resourceDetails.object)) { + callback( + { text: "Invalid resource details provided." }, + [] + ); + return; + } + + // persist relevant data if needed to memory/knowledge + // const memory = { + // type: "resource", + // content: resourceDetails.object, + // timestamp: new Date().toISOString() + // }; + + // await runtime.storeMemory(memory); + + callback( + { + text: `Resource created successfully: +- Name: ${resourceDetails.object.name} +- Type: ${resourceDetails.object.type} +- Description: ${resourceDetails.object.description} +- Tags: ${resourceDetails.object.tags.join(", ")} + +Resource has been stored in memory.` + }, + [] + ); + } catch (error) { + elizaLogger.error("Error creating resource:", error); + callback( + { text: "Failed to create resource. Please check the logs." }, + [] + ); + } + }, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Create a new resource with the name 'Resource1' and type 'TypeA'", + }, + }, + { + user: "{{agentName}}", + content: { + text: `Resource created successfully: +- Name: Resource1 +- Type: TypeA`, + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Create a new resource with the name 'Resource2' and type 'TypeB'", + }, + }, + { + user: "{{agentName}}", + content: { + text: `Resource created successfully: +- Name: Resource2 +- Type: TypeB`, + }, + }, + ], + ], +}; \ No newline at end of file diff --git a/packages/_examples/plugin/src/evaluators/sampleEvalutor.ts b/packages/_examples/plugin/src/evaluators/sampleEvalutor.ts new file mode 100644 index 0000000000..06ad6d454c --- /dev/null +++ b/packages/_examples/plugin/src/evaluators/sampleEvalutor.ts @@ -0,0 +1,47 @@ +import { Evaluator, IAgentRuntime, Memory, State, elizaLogger } from "@ai16z/eliza"; + +export const sampleEvaluator: Evaluator = { + alwaysRun: false, + description: "Sample evaluator for checking important content in memory", + similes: ["content checker", "memory evaluator"], + examples: [ + { + context: "Checking if memory contains important content", + messages: [ + { + action: "evaluate", + input: "This is an important message", + output: { + score: 1, + reason: "Memory contains important content." + } + } + ], + outcome: "Memory should be evaluated as important" + } + ], + handler: async (runtime: IAgentRuntime, memory: Memory, state: State) => { + // Evaluation logic for the evaluator + elizaLogger.log("Evaluating data in sampleEvaluator..."); + + // Example evaluation logic + if (memory.content && memory.content.includes("important")) { + elizaLogger.log("Important content found in memory."); + return { + score: 1, + reason: "Memory contains important content." + }; + } else { + elizaLogger.log("No important content found in memory."); + return { + score: 0, + reason: "Memory does not contain important content." + }; + } + }, + name: "sampleEvaluator", + validate: async (runtime: IAgentRuntime, memory: Memory, state: State) => { + // Validation logic for the evaluator + return true; + } +}; diff --git a/packages/_examples/plugin/src/index.ts b/packages/_examples/plugin/src/index.ts new file mode 100644 index 0000000000..e05078abd8 --- /dev/null +++ b/packages/_examples/plugin/src/index.ts @@ -0,0 +1,8 @@ +import { samplePlugin } from './plugins/samplePlugin'; + + + +export * from './plugins/samplePlugin'; + + +export default samplePlugin; \ No newline at end of file diff --git a/packages/_examples/plugin/src/plugins/samplePlugin.ts b/packages/_examples/plugin/src/plugins/samplePlugin.ts new file mode 100644 index 0000000000..dc72976409 --- /dev/null +++ b/packages/_examples/plugin/src/plugins/samplePlugin.ts @@ -0,0 +1,17 @@ +import { + Plugin, +} from "@ai16z/eliza"; +import { createResourceAction } from "../actions/sampleAction"; +import { sampleProvider } from "../providers/sampleProvider"; +import { sampleEvaluator } from "../evaluators/sampleEvalutor"; + +export const samplePlugin: Plugin = { + name: "sample", + description: "Enables creation and management of generic resources", + actions: [createResourceAction], + providers: [sampleProvider], + evaluators: [sampleEvaluator], + // separate examples will be added for services and clients + services: [], + clients: [], +}; diff --git a/packages/_examples/plugin/src/providers/sampleProvider.ts b/packages/_examples/plugin/src/providers/sampleProvider.ts new file mode 100644 index 0000000000..5e4b3c2b5b --- /dev/null +++ b/packages/_examples/plugin/src/providers/sampleProvider.ts @@ -0,0 +1,14 @@ +import { + Provider, + IAgentRuntime, + Memory, + State, + elizaLogger +} from "@ai16z/eliza"; + +export const sampleProvider: Provider = { + get: async (runtime: IAgentRuntime, message: Memory, state: State) => { + // Data retrieval logic for the provider + elizaLogger.log("Retrieving data in sampleProvider..."); + }, +}; diff --git a/packages/_examples/plugin/src/templates.ts b/packages/_examples/plugin/src/templates.ts new file mode 100644 index 0000000000..f9c0d96591 --- /dev/null +++ b/packages/_examples/plugin/src/templates.ts @@ -0,0 +1,60 @@ +export const createResourceTemplate = ` +Extract the following details to create a new resource: +- **name** (string): Name of the resource +- **type** (string): Type of resource (document, image, video) +- **description** (string): Description of the resource +- **tags** (array): Array of tags to categorize the resource + +Provide the values in the following JSON format: + +\`\`\`json +{ + "name": "", + "type": "", + "description": "", + "tags": ["", ""] +} +\`\`\` + +Here are the recent user messages for context: +{{recentMessages}} +`; + +export const readResourceTemplate = ` +Extract the following details to read a resource: +- **id** (string): Unique identifier of the resource +- **fields** (array): Specific fields to retrieve (optional) + +Provide the values in the following JSON format: + +\`\`\`json +{ + "id": "", + "fields": ["", ""] +} +\`\`\` + +Here are the recent user messages for context: +{{recentMessages}} +`; + +export const updateResourceTemplate = ` +Extract the following details to update a resource: +- **id** (string): Unique identifier of the resource +- **updates** (object): Key-value pairs of fields to update + +Provide the values in the following JSON format: + +\`\`\`json +{ + "id": "", + "updates": { + "": "", + "": "" + } +} +\`\`\` + +Here are the recent user messages for context: +{{recentMessages}} +`; diff --git a/packages/_examples/plugin/src/types.ts b/packages/_examples/plugin/src/types.ts new file mode 100644 index 0000000000..e0d03cf173 --- /dev/null +++ b/packages/_examples/plugin/src/types.ts @@ -0,0 +1,51 @@ +import { z } from "zod"; + +// Base resource schema +export const ResourceSchema = z.object({ + id: z.string().optional(), + name: z.string().min(1), + type: z.enum(["document", "image", "video"]), + description: z.string(), + tags: z.array(z.string()) +}); + +// Create resource schema +export const CreateResourceSchema = ResourceSchema.omit({ id: true }); + +// Read resource schema +export const ReadResourceSchema = z.object({ + id: z.string(), + fields: z.array(z.string()).optional() +}); + +// Update resource schema +export const UpdateResourceSchema = z.object({ + id: z.string(), + updates: z.record(z.string(), z.any()) +}); + +// Type definitions +export type Resource = z.infer; +export type CreateResourceContent = z.infer; +export type ReadResourceContent = z.infer; +export type UpdateResourceContent = z.infer; + +// Type guards +export const isCreateResourceContent = (obj: any): obj is CreateResourceContent => { + return CreateResourceSchema.safeParse(obj).success; +}; + +export const isReadResourceContent = (obj: any): obj is ReadResourceContent => { + return ReadResourceSchema.safeParse(obj).success; +}; + +export const isUpdateResourceContent = (obj: any): obj is UpdateResourceContent => { + return UpdateResourceSchema.safeParse(obj).success; +}; + +// Plugin configuration type +export interface ExamplePluginConfig { + apiKey: string; + apiSecret: string; + endpoint?: string; +} \ No newline at end of file diff --git a/packages/_examples/plugin/tsconfig.json b/packages/_examples/plugin/tsconfig.json new file mode 100644 index 0000000000..99dbaa3d81 --- /dev/null +++ b/packages/_examples/plugin/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../core/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "types": [ + "node" + ] + }, + "include": [ + "src/**/*.ts", + ] +} \ No newline at end of file diff --git a/packages/_examples/plugin/tsup.config.ts b/packages/_examples/plugin/tsup.config.ts new file mode 100644 index 0000000000..1a96f24afa --- /dev/null +++ b/packages/_examples/plugin/tsup.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + sourcemap: true, + clean: true, + format: ["esm"], // Ensure you're targeting CommonJS + external: [ + "dotenv", // Externalize dotenv to prevent bundling + "fs", // Externalize fs to use Node.js built-in module + "path", // Externalize other built-ins if necessary + "@reflink/reflink", + "@node-llama-cpp", + "https", + "http", + "agentkeepalive", + "safe-buffer", + // Add other modules you want to externalize + ], +}); diff --git a/packages/client-discord/src/constants.ts b/packages/client-discord/src/constants.ts new file mode 100644 index 0000000000..2bc2346410 --- /dev/null +++ b/packages/client-discord/src/constants.ts @@ -0,0 +1,85 @@ +export const TEAM_COORDINATION = { + KEYWORDS: [ + 'team', + 'everyone', + 'all agents', + 'team update', + 'gm team', + 'hello team', + 'hey team', + 'hi team', + 'morning team', + 'evening team', + 'night team', + 'update team', + ] +} as const; + +export const MESSAGE_CONSTANTS = { + MAX_MESSAGES: 10, + RECENT_MESSAGE_COUNT: 3, + CHAT_HISTORY_COUNT: 5, + INTEREST_DECAY_TIME: 5 * 60 * 1000, // 5 minutes + PARTIAL_INTEREST_DECAY: 3 * 60 * 1000, // 3 minutes + DEFAULT_SIMILARITY_THRESHOLD: 0.3, + DEFAULT_SIMILARITY_THRESHOLD_FOLLOW_UPS: 0.20, +} as const; + +export const MESSAGE_LENGTH_THRESHOLDS = { + LOSE_INTEREST: 100, + SHORT_MESSAGE: 10, + VERY_SHORT_MESSAGE: 2, + IGNORE_RESPONSE: 4, +} as const; + +export const TIMING_CONSTANTS = { + LEADER_RESPONSE_TIMEOUT: 3000, + TEAM_MEMBER_DELAY: 1500, + LEADER_DELAY_MIN: 3000, + LEADER_DELAY_MAX: 4000, + TEAM_MEMBER_DELAY_MIN: 1000, + TEAM_MEMBER_DELAY_MAX: 3000, +} as const; + +export const RESPONSE_CHANCES = { + AFTER_LEADER: 0.5, // 50% chance + FREQUENT_CHATTER: 0.5, // Base chance for frequent responders +} as const; + +export const LOSE_INTEREST_WORDS = [ + "shut up", + "stop", + "please shut up", + "shut up please", + "dont talk", + "silence", + "stop talking", + "be quiet", + "hush", + "wtf", + "chill", + "stfu", + "stupid bot", + "dumb bot", + "stop responding", + "god damn it", + "god damn", + "goddamnit", + "can you not", + "can you stop", + "be quiet", + "hate you", + "hate this", + "fuck up", +] as const; + +export const IGNORE_RESPONSE_WORDS = [ + "lol", + "nm", + "uh", + "wtf", + "stfu", + "dumb", + "jfc", + "omg", +] as const; \ No newline at end of file diff --git a/packages/client-discord/src/index.ts b/packages/client-discord/src/index.ts index 849465f9f8..5e3621762e 100644 --- a/packages/client-discord/src/index.ts +++ b/packages/client-discord/src/index.ts @@ -1,7 +1,11 @@ -import { getEmbeddingZeroVector } from "@ai16z/eliza"; -import { Character, Client as ElizaClient, IAgentRuntime } from "@ai16z/eliza"; -import { stringToUuid } from "@ai16z/eliza"; -import { elizaLogger } from "@ai16z/eliza"; +import { + getEmbeddingZeroVector, + stringToUuid, + elizaLogger, + Character, + Client as ElizaClient, + IAgentRuntime, +} from "@ai16z/eliza"; import { Client, Events, @@ -111,6 +115,16 @@ export class DiscordClient extends EventEmitter { ); } + async stop() { + try { + // disconnect websocket + // this unbinds all the listeners + await this.client.destroy(); + } catch(e) { + elizaLogger.error('client-discord instance stop err', e); + } + } + private async onClientReady(readyClient: { user: { tag: any; id: any } }) { elizaLogger.success(`Logged in as ${readyClient.user?.tag}`); @@ -388,7 +402,13 @@ export function startDiscord(runtime: IAgentRuntime) { export const DiscordClientInterface: ElizaClient = { start: async (runtime: IAgentRuntime) => new DiscordClient(runtime), - stop: async (_runtime: IAgentRuntime) => { - console.warn("Discord client does not support stopping yet"); + stop: async (runtime: IAgentRuntime) => { + try { + // stop it + elizaLogger.log('Stopping discord client', runtime.agentId) + await runtime.clients.discord.stop() + } catch(e) { + elizaLogger.error('client-discord interface stop error', e); + } }, }; diff --git a/packages/client-discord/src/messages.ts b/packages/client-discord/src/messages.ts index 9c5bf3f21c..735979b243 100644 --- a/packages/client-discord/src/messages.ts +++ b/packages/client-discord/src/messages.ts @@ -28,12 +28,21 @@ import { discordShouldRespondTemplate, discordMessageHandlerTemplate, } from "./templates.ts"; -import { sendMessageInChunks, canSendMessage } from "./utils.ts"; +import { IGNORE_RESPONSE_WORDS, LOSE_INTEREST_WORDS, MESSAGE_CONSTANTS, MESSAGE_LENGTH_THRESHOLDS, RESPONSE_CHANCES, TEAM_COORDINATION, TIMING_CONSTANTS } from './constants'; +import { sendMessageInChunks, canSendMessage, cosineSimilarity } from "./utils.ts"; + +interface MessageContext { + content: string; + timestamp: number; +} export type InterestChannels = { [key: string]: { + currentHandler: string | undefined; lastMessageSent: number; messages: { userId: UUID; userName: string; content: Content }[]; + previousContext?: MessageContext; + contextSimilarityThreshold?: number; }; }; @@ -58,8 +67,9 @@ export class MessageManager { message.interaction || message.author.id === this.client.user?.id /* || message.author?.bot*/ - ) + ) { return; + } if ( this.runtime.character.clientConfig?.discord @@ -69,6 +79,13 @@ export class MessageManager { return; } + // Check for mentions-only mode setting + if (this.runtime.character.clientConfig?.discord?.shouldRespondOnlyToMentions) { + if(!this._isMessageForMe(message)) { + return; + } + } + if ( this.runtime.character.clientConfig?.discord ?.shouldIgnoreDirectMessages && @@ -81,6 +98,108 @@ export class MessageManager { const userName = message.author.username; const name = message.author.displayName; const channelId = message.channel.id; + const isDirectlyMentioned = this._isMessageForMe(message); + const hasInterest = this._checkInterest(message.channelId); + + // Team handling + if (this.runtime.character.clientConfig?.discord?.isPartOfTeam && !this.runtime.character.clientConfig?.discord?.shouldRespondOnlyToMentions) { + const authorId = this._getNormalizedUserId(message.author.id); + + if (!this._isTeamLeader() && this._isRelevantToTeamMember(message.content, channelId)) { + this.interestChannels[message.channelId] = { + currentHandler: this.client.user?.id, + lastMessageSent: Date.now(), + messages: [] + }; + } + + const isTeamRequest = this._isTeamCoordinationRequest(message.content); + const isLeader = this._isTeamLeader(); + + // After team-wide responses, check if we should maintain interest + if (hasInterest && !isDirectlyMentioned) { + const lastSelfMemories = await this.runtime.messageManager.getMemories({ + roomId: stringToUuid(channelId + "-" + this.runtime.agentId), + unique: false, + count: 5 + }); + + const lastSelfSortedMemories = lastSelfMemories?.filter(m => m.userId === this.runtime.agentId).sort((a, b) => + (b.createdAt || 0) - (a.createdAt || 0) + ); + + const isRelevant = this._isRelevantToTeamMember(message.content, channelId, lastSelfSortedMemories?.[0]); + + if (!isRelevant) { + // Clearing interest - conversation not relevant to team member + delete this.interestChannels[message.channelId]; + return; + } + } + + if (isTeamRequest) { + if (isLeader) { + this.interestChannels[message.channelId] = { + currentHandler: this.client.user?.id, + lastMessageSent: Date.now(), + messages: [] + }; + } else { + // Set temporary interest for this response + this.interestChannels[message.channelId] = { + currentHandler: this.client.user?.id, + lastMessageSent: Date.now(), + messages: [] + }; + + // Clear interest after this cycle unless directly mentioned + if (!isDirectlyMentioned) { + // Use existing message cycle to clear interest + this.interestChannels[message.channelId].lastMessageSent = 0; + } + } + } + + // Check for other team member mentions + const otherTeamMembers = this.runtime.character.clientConfig.discord.teamAgentIds.filter( + id => id !== this.client.user?.id + ); + const mentionedTeamMember = otherTeamMembers.find(id => + message.content.includes(`<@${id}>`) + ); + + // If another team member is mentioned, clear our interest + if (mentionedTeamMember) { + if (hasInterest || this.interestChannels[message.channelId]?.currentHandler === this.client.user?.id) { + delete this.interestChannels[message.channelId]; + + // Only return if we're not the mentioned member + if (!isDirectlyMentioned) { + return; + } + } + } + + // Set/maintain interest only if we're mentioned or already have interest + if (isDirectlyMentioned) { + this.interestChannels[message.channelId] = { + currentHandler: this.client.user?.id, + lastMessageSent: Date.now(), + messages: [] + }; + } else if (!isTeamRequest && !hasInterest) { + return; + } + + // Bot-specific checks + if (message.author.bot) { + if (this._isTeamMember(authorId) && !isDirectlyMentioned) { + return; + } else if (this.runtime.character.clientConfig.discord.shouldIgnoreBotMessages) { + return; + } + } + } try { const { processedContent, attachments } = @@ -149,6 +268,21 @@ export class MessageManager { if (content.text) { await this.runtime.messageManager.addEmbeddingToMemory(memory); await this.runtime.messageManager.createMemory(memory); + + if (this.interestChannels[message.channelId]) { + // Add new message + this.interestChannels[message.channelId].messages.push({ + userId: userIdUUID, + userName: userName, + content: content + }); + + // Trim to keep only recent messages + if (this.interestChannels[message.channelId].messages.length > MESSAGE_CONSTANTS.MAX_MESSAGES) { + this.interestChannels[message.channelId].messages = + this.interestChannels[message.channelId].messages.slice(-MESSAGE_CONSTANTS.MAX_MESSAGES); + } + } } let state = await this.runtime.composeState(userMessage, { @@ -174,7 +308,6 @@ export class MessageManager { if (shouldIgnore) { return; } - const hasInterest = this._checkInterest(channelId); const agentUserState = await this.runtime.databaseAdapter.getParticipantUserState( @@ -422,13 +555,270 @@ export class MessageManager { return { processedContent, attachments }; } + private _getNormalizedUserId(id: string): string { + return id.toString().replace(/[^0-9]/g, ''); + } + + private _isTeamMember(userId: string): boolean { + const teamConfig = this.runtime.character.clientConfig?.discord; + if (!teamConfig?.isPartOfTeam || !teamConfig.teamAgentIds) return false; + + const normalizedUserId = this._getNormalizedUserId(userId); + + const isTeamMember = teamConfig.teamAgentIds.some(teamId => + this._getNormalizedUserId(teamId) === normalizedUserId + ); + + return isTeamMember; + } + + private _isTeamLeader(): boolean { + return this.client.user?.id === this.runtime.character.clientConfig?.discord?.teamLeaderId; + } + + private _isTeamCoordinationRequest(content: string): boolean { + const contentLower = content.toLowerCase(); + return TEAM_COORDINATION.KEYWORDS?.some(keyword => + contentLower.includes(keyword.toLowerCase()) + ); + } + + private _isRelevantToTeamMember(content: string, channelId: string, lastAgentMemory: Memory | null = null): boolean { + const teamConfig = this.runtime.character.clientConfig?.discord; + + if (this._isTeamLeader() && lastAgentMemory?.content.text) { + const timeSinceLastMessage = Date.now() - lastAgentMemory.createdAt; + if (timeSinceLastMessage > MESSAGE_CONSTANTS.INTEREST_DECAY_TIME) { + return false; // Memory too old, not relevant + } + + const similarity = cosineSimilarity( + content.toLowerCase(), + lastAgentMemory.content.text.toLowerCase() + ); + + return similarity >= MESSAGE_CONSTANTS.DEFAULT_SIMILARITY_THRESHOLD_FOLLOW_UPS; + } + + // If no keywords defined, only leader maintains conversation + if (!teamConfig?.teamMemberInterestKeywords) { + return false; + } + + return teamConfig.teamMemberInterestKeywords.some(keyword => + content.toLowerCase().includes(keyword.toLowerCase()) + ); + } + + private _isMessageForMe(message: DiscordMessage): boolean { + const isMentioned = message.mentions.users?.has(this.client.user?.id as string); + const guild = message.guild; + const member = guild?.members.cache.get(this.client.user?.id as string); + const nickname = member?.nickname; + const memberId = member?.id; + + // Don't consider role mentions as direct mentions + const hasRoleMentionOnly = message.mentions.roles.size > 0 && !isMentioned; + + // If it's only a role mention and we're in team mode, let team logic handle it + if (hasRoleMentionOnly && this.runtime.character.clientConfig?.discord?.isPartOfTeam) { + return false; + } + + return isMentioned || (!this.runtime.character.clientConfig?.discord?.shouldRespondOnlyToMentions && ( + message.content.toLowerCase().includes(this.client.user?.username.toLowerCase() as string) || + message.content.toLowerCase().includes(this.client.user?.tag.toLowerCase() as string) || + (nickname && message.content.toLowerCase().includes(nickname.toLowerCase())))); + } + + private async _analyzeContextSimilarity(currentMessage: string, previousContext?: MessageContext, agentLastMessage?: string): Promise { + if (!previousContext) return 1; // No previous context to compare against + + // If more than 5 minutes have passed, reduce similarity weight + const timeDiff = Date.now() - previousContext.timestamp; + const timeWeight = Math.max(0, 1 - (timeDiff / (5 * 60 * 1000))); // 5 minutes threshold + + // Calculate content similarity + const similarity = cosineSimilarity( + currentMessage.toLowerCase(), + previousContext.content.toLowerCase(), + agentLastMessage?.toLowerCase() + ); + + // Weight the similarity by time factor + const weightedSimilarity = similarity * timeWeight; + + return weightedSimilarity; + } + + private async _shouldRespondBasedOnContext(message: DiscordMessage, channelState: InterestChannels[string]): Promise { + // Always respond if directly mentioned + if (this._isMessageForMe(message)) return true; + + // If we're not the current handler, don't respond + if (channelState?.currentHandler !== this.client.user?.id) return false; + + // Check if we have messages to compare + if (!channelState.messages?.length) return false; + + // Get last user message (not from the bot) + const lastUserMessage = [...channelState.messages] + .reverse() + .find((m, index) => + index > 0 && // Skip first message (current) + m.userId !== this.runtime.agentId + ); + + if (!lastUserMessage) return false; + + const lastSelfMemories = await this.runtime.messageManager.getMemories({ + roomId: stringToUuid(message.channel.id + "-" + this.runtime.agentId), + unique: false, + count: 5 + }); + + const lastSelfSortedMemories = lastSelfMemories?.filter(m => m.userId === this.runtime.agentId).sort((a, b) => + (b.createdAt || 0) - (a.createdAt || 0) + ); + + // Calculate context similarity + const contextSimilarity = await this._analyzeContextSimilarity( + message.content, + { + content: lastUserMessage.content.text || '', + timestamp: Date.now() + }, + lastSelfSortedMemories?.[0]?.content?.text + ); + + const similarityThreshold = + this.runtime.character.clientConfig?.discord?.messageSimilarityThreshold || + channelState.contextSimilarityThreshold || + MESSAGE_CONSTANTS.DEFAULT_SIMILARITY_THRESHOLD; + + return contextSimilarity >= similarityThreshold; + } + private _checkInterest(channelId: string): boolean { - return !!this.interestChannels[channelId]; + const channelState = this.interestChannels[channelId]; + if (!channelState) return false; + + const lastMessage = channelState.messages[channelState.messages.length - 1]; + // If it's been more than 5 minutes since last message, reduce interest + const timeSinceLastMessage = Date.now() - channelState.lastMessageSent; + + if (timeSinceLastMessage > MESSAGE_CONSTANTS.INTEREST_DECAY_TIME) { + delete this.interestChannels[channelId]; + return false; + } else if (timeSinceLastMessage > MESSAGE_CONSTANTS.PARTIAL_INTEREST_DECAY) { + // Require stronger relevance for continued interest + return this._isRelevantToTeamMember(lastMessage.content.text || '', channelId) + } + + // If team leader and messages exist, check for topic changes and team member responses + if (this._isTeamLeader() && channelState.messages.length > 0) { + // If leader's keywords don't match and another team member has responded, drop interest + if (!this._isRelevantToTeamMember(lastMessage.content.text || '', channelId)) { + const recentTeamResponses = channelState.messages.slice(-3).some(m => + m.userId !== this.client.user?.id && + this._isTeamMember(m.userId) + ); + + if (recentTeamResponses) { + delete this.interestChannels[channelId]; + return false; + } + } + } + + // Check if conversation has shifted to a new topic + if (channelState.messages.length > 0) { + const recentMessages = channelState.messages.slice(-MESSAGE_CONSTANTS.RECENT_MESSAGE_COUNT); + const differentUsers = new Set(recentMessages.map(m => m.userId)).size; + + // If multiple users are talking and we're not involved, reduce interest + if (differentUsers > 1 && !recentMessages.some(m => m.userId === this.client.user?.id)) { + delete this.interestChannels[channelId]; + return false; + } + } + + return true; } private async _shouldIgnore(message: DiscordMessage): Promise { // if the message is from us, ignore if (message.author.id === this.client.user?.id) return true; + + // Honor mentions-only mode + if (this.runtime.character.clientConfig?.discord?.shouldRespondOnlyToMentions) { + return !this._isMessageForMe(message); + } + + // Team-based ignore logic + if (this.runtime.character.clientConfig?.discord?.isPartOfTeam) { + const authorId = this._getNormalizedUserId(message.author.id); + + if (this._isTeamLeader()) { + if(this._isTeamCoordinationRequest(message.content)) { + return false; + } + // Ignore if message is only about team member interests and not directed to leader + if (!this._isMessageForMe(message)) { + const otherMemberInterests = this.runtime.character.clientConfig?.discord?.teamMemberInterestKeywords || []; + const hasOtherInterests = otherMemberInterests.some(keyword => + message.content.toLowerCase().includes(keyword.toLowerCase()) + ); + if (hasOtherInterests) { + return true; + } + } + } else if (this._isTeamCoordinationRequest(message.content)) { + const randomDelay = Math.floor(Math.random() * (TIMING_CONSTANTS.TEAM_MEMBER_DELAY_MAX - TIMING_CONSTANTS.TEAM_MEMBER_DELAY_MIN)) + + TIMING_CONSTANTS.TEAM_MEMBER_DELAY_MIN; // 1-3 second random delay + await new Promise(resolve => setTimeout(resolve, randomDelay)); + return false; + } + + if (this._isTeamMember(authorId)) { + if (!this._isMessageForMe(message)) { + // If message contains our interests, don't ignore + if (this._isRelevantToTeamMember(message.content, message.channelId)) { + return false; + } + return true; + } + } + + // Check if we're in an active conversation based on context + const channelState = this.interestChannels[message.channelId]; + + if (channelState?.currentHandler) { + + // If we're the current handler, check context + if (channelState.currentHandler === this.client.user?.id) { + //If it's our keywords, bypass context check + if (this._isRelevantToTeamMember(message.content, message.channelId)) { + return false; + } + + const shouldRespondContext = await this._shouldRespondBasedOnContext( + message, + channelState + ); + + // If context is different, ignore. If similar, don't ignore + return !shouldRespondContext; + } + + // If another team member is handling and we're not mentioned or coordinating + else if (!this._isMessageForMe(message) && + !this._isTeamCoordinationRequest(message.content)) { + return true; + } + } + } + let messageContent = message.content.toLowerCase(); // Replace the bot's @ping with the character name @@ -448,36 +838,10 @@ export class MessageManager { // strip all special characters messageContent = messageContent.replace(/[^a-zA-Z0-9\s]/g, ""); - // short responses where ruby should stop talking and disengage unless mentioned again - const loseInterestWords = [ - "shut up", - "stop", - "please shut up", - "shut up please", - "dont talk", - "silence", - "stop talking", - "be quiet", - "hush", - "wtf", - "chill", - "stfu", - "stupid bot", - "dumb bot", - "stop responding", - "god damn it", - "god damn", - "goddamnit", - "can you not", - "can you stop", - "be quiet", - "hate you", - "hate this", - "fuck up", - ]; + // short responses where eliza should stop talking and disengage unless mentioned again if ( - messageContent.length < 100 && - loseInterestWords.some((word) => messageContent.includes(word)) + messageContent.length < MESSAGE_LENGTH_THRESHOLDS.LOSE_INTEREST && + LOSE_INTEREST_WORDS.some((word) => messageContent.includes(word)) ) { delete this.interestChannels[message.channelId]; return true; @@ -485,7 +849,7 @@ export class MessageManager { // If we're not interested in the channel and it's a short message, ignore it if ( - messageContent.length < 10 && + messageContent.length < MESSAGE_LENGTH_THRESHOLDS.SHORT_MESSAGE && !this.interestChannels[message.channelId] ) { return true; @@ -515,24 +879,14 @@ export class MessageManager { // if the message is short, ignore but maintain interest if ( !this.interestChannels[message.channelId] && - messageContent.length < 2 + messageContent.length < MESSAGE_LENGTH_THRESHOLDS.VERY_SHORT_MESSAGE ) { return true; } - const ignoreResponseWords = [ - "lol", - "nm", - "uh", - "wtf", - "stfu", - "dumb", - "jfc", - "omg", - ]; if ( - message.content.length < 4 && - ignoreResponseWords.some((word) => + message.content.length < MESSAGE_LENGTH_THRESHOLDS.IGNORE_RESPONSE && + IGNORE_RESPONSE_WORDS.some((word) => message.content.toLowerCase().includes(word) ) ) { @@ -547,6 +901,130 @@ export class MessageManager { ): Promise { if (message.author.id === this.client.user?.id) return false; // if (message.author.bot) return false; + + // Honor mentions-only mode + if (this.runtime.character.clientConfig?.discord?.shouldRespondOnlyToMentions) { + return this._isMessageForMe(message); + } + + const channelState = this.interestChannels[message.channelId]; + + // Check if team member has direct interest first + if (this.runtime.character.clientConfig?.discord?.isPartOfTeam && + !this._isTeamLeader() && + this._isRelevantToTeamMember(message.content, message.channelId)) { + return true; + } + + try { + // Team-based response logic + if (this.runtime.character.clientConfig?.discord?.isPartOfTeam) { + const authorId = this._getNormalizedUserId(message.author.id); + + // Team leader coordination + if (this._isTeamLeader() && this._isTeamCoordinationRequest(message.content)) { + return true; + } + + if (!this._isTeamLeader() && this._isRelevantToTeamMember(message.content, message.channelId)) { + // Add small delay for non-leader responses + await new Promise(resolve => setTimeout(resolve, TIMING_CONSTANTS.TEAM_MEMBER_DELAY)); //1.5 second delay + + // If leader has responded in last few seconds, reduce chance of responding + + if (channelState?.messages?.length) { + const recentMessages = channelState.messages.slice(-MESSAGE_CONSTANTS.RECENT_MESSAGE_COUNT); + const leaderResponded = recentMessages.some(m => + m.userId === this.runtime.character.clientConfig?.discord?.teamLeaderId && + Date.now() - channelState.lastMessageSent < 3000 + ); + + if (leaderResponded) { + // 50% chance to respond if leader just did + return Math.random() > RESPONSE_CHANCES.AFTER_LEADER; + } + } + + return true; + } + + // If I'm the leader but message doesn't match my keywords, add delay and check for team responses + if (this._isTeamLeader() && !this._isRelevantToTeamMember(message.content, message.channelId)) { + const randomDelay = Math.floor(Math.random() * (TIMING_CONSTANTS.LEADER_DELAY_MAX - TIMING_CONSTANTS.LEADER_DELAY_MIN)) + + TIMING_CONSTANTS.LEADER_DELAY_MIN; // 2-4 second random delay + await new Promise(resolve => setTimeout(resolve, randomDelay)); + + // After delay, check if another team member has already responded + if (channelState?.messages?.length) { + const recentResponses = channelState.messages.slice(-MESSAGE_CONSTANTS.RECENT_MESSAGE_COUNT); + const otherTeamMemberResponded = recentResponses.some(m => + m.userId !== this.client.user?.id && + this._isTeamMember(m.userId) + ); + + if (otherTeamMemberResponded) { + return false; + } + } + } + + // Update current handler if we're mentioned + if (this._isMessageForMe(message)) { + const channelState = this.interestChannels[message.channelId]; + if (channelState) { + channelState.currentHandler = this.client.user?.id; + channelState.lastMessageSent = Date.now(); + } + return true; + } + + // Don't respond if another teammate is handling the conversation + if (channelState?.currentHandler) { + if (channelState.currentHandler !== this.client.user?.id && + this._isTeamMember(channelState.currentHandler)) { + return false; + } + } + + // Natural conversation cadence + if (!this._isMessageForMe(message) && channelState) { + // Count our recent messages + const recentMessages = channelState.messages.slice(-MESSAGE_CONSTANTS.CHAT_HISTORY_COUNT); + const ourMessageCount = recentMessages.filter(m => + m.userId === this.client.user?.id + ).length; + + // Reduce responses if we've been talking a lot + if (ourMessageCount > 2) { + // Exponentially decrease chance to respond + const responseChance = Math.pow(0.5, ourMessageCount - 2); + if (Math.random() > responseChance) { + return false; + } + } + } + } + + } catch (error) { + elizaLogger.error('Error in _shouldRespond team processing:', { + error, + agentId: this.runtime.agentId, + channelId: message.channelId + }); + } + + // Otherwise do context check + if (channelState?.previousContext) { + const shouldRespondContext = await this._shouldRespondBasedOnContext( + message, + channelState + ); + if (!shouldRespondContext) { + delete this.interestChannels[message.channelId]; + return false; + } + } + if (message.mentions.has(this.client.user?.id as string)) return true; const guild = message.guild; @@ -587,6 +1065,13 @@ export class MessageManager { }); if (response === "RESPOND") { + if (channelState) { + channelState.previousContext = { + content: message.content, + timestamp: Date.now() + }; + } + return true; } else if (response === "IGNORE") { return false; @@ -649,4 +1134,4 @@ export class MessageManager { const data = await response.json(); return data.username; } -} +} \ No newline at end of file diff --git a/packages/client-discord/src/utils.ts b/packages/client-discord/src/utils.ts index 053c3d4ccb..6ee1e98871 100644 --- a/packages/client-discord/src/utils.ts +++ b/packages/client-discord/src/utils.ts @@ -50,11 +50,11 @@ export async function generateSummary( text = trimTokens(text, 100000, "gpt-4o-mini"); // TODO: clean this up const prompt = `Please generate a concise summary for the following text: - + Text: """ ${text} """ - + Respond with a JSON object in the following format: \`\`\`json { @@ -221,3 +221,80 @@ export function canSendMessage(channel) { : null, }; } + +export function cosineSimilarity(text1: string, text2: string, text3?: string): number { + const preprocessText = (text: string) => text + .toLowerCase() + .replace(/[^\w\s'_-]/g, ' ') + .replace(/\s+/g, ' ') + .trim(); + + const getWords = (text: string) => { + return text.split(' ').filter(word => word.length > 1); + }; + + const words1 = getWords(preprocessText(text1)); + const words2 = getWords(preprocessText(text2)); + const words3 = text3 ? getWords(preprocessText(text3)) : []; + + const freq1: { [key: string]: number } = {}; + const freq2: { [key: string]: number } = {}; + const freq3: { [key: string]: number } = {}; + + words1.forEach(word => freq1[word] = (freq1[word] || 0) + 1); + words2.forEach(word => freq2[word] = (freq2[word] || 0) + 1); + if (words3.length) { + words3.forEach(word => freq3[word] = (freq3[word] || 0) + 1); + } + + const uniqueWords = new Set([...Object.keys(freq1), ...Object.keys(freq2), ...(words3.length ? Object.keys(freq3) : [])]); + + let dotProduct = 0; + let magnitude1 = 0; + let magnitude2 = 0; + let magnitude3 = 0; + + uniqueWords.forEach(word => { + const val1 = freq1[word] || 0; + const val2 = freq2[word] || 0; + const val3 = freq3[word] || 0; + + if (words3.length) { + // For three-way, calculate pairwise similarities + const sim12 = val1 * val2; + const sim23 = val2 * val3; + const sim13 = val1 * val3; + + // Take maximum similarity between any pair + dotProduct += Math.max(sim12, sim23, sim13); + } else { + dotProduct += val1 * val2; + } + + magnitude1 += val1 * val1; + magnitude2 += val2 * val2; + if (words3.length) { + magnitude3 += val3 * val3; + } + }); + + magnitude1 = Math.sqrt(magnitude1); + magnitude2 = Math.sqrt(magnitude2); + magnitude3 = words3.length ? Math.sqrt(magnitude3) : 1; + + if (magnitude1 === 0 || magnitude2 === 0 || (words3.length && magnitude3 === 0)) return 0; + + // For two texts, use original calculation + if (!words3.length) { + return dotProduct / (magnitude1 * magnitude2); + } + + // For three texts, use max magnitude pair to maintain scale + const maxMagnitude = Math.max( + magnitude1 * magnitude2, + magnitude2 * magnitude3, + magnitude1 * magnitude3 + ); + + return dotProduct / maxMagnitude; +} \ No newline at end of file diff --git a/packages/client-discord/src/voice.ts b/packages/client-discord/src/voice.ts index c8b2bb5447..97f2a81b6e 100644 --- a/packages/client-discord/src/voice.ts +++ b/packages/client-discord/src/voice.ts @@ -46,14 +46,12 @@ import { discordShouldRespondTemplate, discordVoiceHandlerTemplate, } from "./templates.ts"; -import debounce from "lodash/debounce.js"; import { getWavHeader } from "./utils.ts"; // These values are chosen for compatibility with picovoice components const DECODE_FRAME_SIZE = 1024; const DECODE_SAMPLE_RATE = 16000; -// Buffers all audio export class AudioMonitor { private readable: Readable; private buffers: Buffer[] = []; @@ -64,6 +62,7 @@ export class AudioMonitor { constructor( readable: Readable, maxSize: number, + onStart: () => void, callback: (buffer: Buffer) => void ) { this.readable = readable; @@ -98,6 +97,7 @@ export class AudioMonitor { }); this.readable.on("speakingStarted", () => { if (this.ended) return; + onStart(); elizaLogger.log("Speaking started"); this.reset(); }); @@ -138,6 +138,8 @@ export class AudioMonitor { } export class VoiceManager extends EventEmitter { + private processingVoice: boolean = false; + private transcriptionTimeout: NodeJS.Timeout | null = null; private userStates: Map< string, { @@ -373,6 +375,7 @@ export class VoiceManager extends EventEmitter { if (avgVolume > SPEAKING_THRESHOLD) { volumeBuffer.length = 0; this.cleanupAudioPlayer(this.activeAudioPlayer); + this.processingVoice = false; } } }); @@ -453,6 +456,52 @@ export class VoiceManager extends EventEmitter { // this.scanGuild(guild); } + async debouncedProcessTranscription( + userId: UUID, + name: string, + userName: string, + channel: BaseGuildVoiceChannel + ) { + const DEBOUNCE_TRANSCRIPTION_THRESHOLD = 1500; // wait for 1.5 seconds of silence + + if (this.activeAudioPlayer?.state?.status === "idle") { + elizaLogger.log("Cleaning up idle audio player."); + this.cleanupAudioPlayer(this.activeAudioPlayer); + } + + if (this.activeAudioPlayer || this.processingVoice) { + const state = this.userStates.get(userId); + state.buffers.length = 0; + state.totalLength = 0; + return; + } + + if (this.transcriptionTimeout) { + clearTimeout(this.transcriptionTimeout); + } + + this.transcriptionTimeout = setTimeout(async () => { + this.processingVoice = true; + try { + await this.processTranscription( + userId, + channel.id, + channel, + name, + userName + ); + + // Clean all users' previous buffers + this.userStates.forEach((state, id) => { + state.buffers.length = 0; + state.totalLength = 0; + }); + } finally { + this.processingVoice = false; + } + }, DEBOUNCE_TRANSCRIPTION_THRESHOLD); + } + async handleUserStream( userId: UUID, name: string, @@ -461,7 +510,6 @@ export class VoiceManager extends EventEmitter { audioStream: Readable ) { console.log(`Starting audio monitor for user: ${userId}`); - const channelId = channel.id; if (!this.userStates.has(userId)) { this.userStates.set(userId, { buffers: [], @@ -473,25 +521,17 @@ export class VoiceManager extends EventEmitter { const state = this.userStates.get(userId); - const DEBOUNCE_TRANSCRIPTION_THRESHOLD = 2500; // wait for 1.5 seconds of silence - - const debouncedProcessTranscription = debounce(async () => { - await this.processTranscription( - userId, - channelId, - channel, - name, - userName - ); - }, DEBOUNCE_TRANSCRIPTION_THRESHOLD); - const processBuffer = async (buffer: Buffer) => { try { state!.buffers.push(buffer); state!.totalLength += buffer.length; state!.lastActive = Date.now(); - - debouncedProcessTranscription(); + this.debouncedProcessTranscription( + userId, + name, + userName, + channel + ); } catch (error) { console.error( `Error processing buffer for user ${userId}:`, @@ -500,13 +540,22 @@ export class VoiceManager extends EventEmitter { } }; - new AudioMonitor(audioStream, 10000000, async (buffer) => { - if (!buffer) { - console.error("Received empty buffer"); - return; + new AudioMonitor( + audioStream, + 10000000, + () => { + if (this.transcriptionTimeout) { + clearTimeout(this.transcriptionTimeout); + } + }, + async (buffer) => { + if (!buffer) { + console.error("Received empty buffer"); + return; + } + await processBuffer(buffer); } - await processBuffer(buffer); - }); + ); } private async processTranscription( @@ -520,12 +569,11 @@ export class VoiceManager extends EventEmitter { if (!state || state.buffers.length === 0) return; try { const inputBuffer = Buffer.concat(state.buffers, state.totalLength); + state.buffers.length = 0; // Clear the buffers state.totalLength = 0; - // Convert Opus to WAV const wavBuffer = await this.convertOpusToWav(inputBuffer); - console.log("Starting transcription..."); const transcriptionText = await this.runtime diff --git a/packages/client-twitter/src/post.ts b/packages/client-twitter/src/post.ts index 51737e8cfe..1cae50bc8f 100644 --- a/packages/client-twitter/src/post.ts +++ b/packages/client-twitter/src/post.ts @@ -137,7 +137,6 @@ export class TwitterPostClient { }; - const processActionsLoop = async () => { const actionInterval = parseInt( this.runtime.getSetting("ACTION_INTERVAL") @@ -172,6 +171,7 @@ export class TwitterPostClient { if (postImmediately) { await this.generateNewTweet(); } + generateNewTweetLoop(); // Add check for ENABLE_ACTION_PROCESSING before starting the loop const enableActionProcessing = parseBooleanFromText( @@ -250,6 +250,7 @@ export class TwitterPostClient { cleanedContent = parsedResponse; } } catch (error) { + error.linted = true; // make linter happy since catch needs a variable // If not JSON, clean the raw content cleanedContent = newTweetContent .replace(/^\s*{?\s*"text":\s*"|"\s*}?\s*$/g, '') // Remove JSON-like wrapper @@ -374,7 +375,7 @@ export class TwitterPostClient { console.log("generate tweet content response:\n" + response); // First clean up any markdown and newlines - let cleanedResponse = response + const cleanedResponse = response .replace(/```json\s*/g, '') // Remove ```json .replace(/```\s*/g, '') // Remove any remaining ``` .replaceAll(/\\n/g, "\n") @@ -393,6 +394,8 @@ export class TwitterPostClient { } } } catch (error) { + error.linted = true; // make linter happy since catch needs a variable + // If JSON parsing fails, treat as plain text elizaLogger.debug('Response is not JSON, treating as plain text'); } diff --git a/packages/core/src/generation.ts b/packages/core/src/generation.ts index fefb24845a..61744cb3e4 100644 --- a/packages/core/src/generation.ts +++ b/packages/core/src/generation.ts @@ -533,6 +533,29 @@ export async function generateText({ break; } + case ModelProviderName.VENICE: { + elizaLogger.debug("Initializing Venice model."); + const venice = createOpenAI({ + apiKey: apiKey, + baseURL: endpoint + }); + + const { text: veniceResponse } = await aiGenerateText({ + model: venice.languageModel(model), + prompt: context, + system: + runtime.character.system ?? + settings.SYSTEM_PROMPT ?? + undefined, + temperature: temperature, + maxTokens: max_response_length, + }); + + response = veniceResponse; + elizaLogger.debug("Received response from Venice model."); + break; + } + default: { const errorMessage = `Unsupported provider: ${provider}`; elizaLogger.error(errorMessage); diff --git a/packages/core/src/models.ts b/packages/core/src/models.ts index a705f4f204..06c7e564d3 100644 --- a/packages/core/src/models.ts +++ b/packages/core/src/models.ts @@ -451,6 +451,20 @@ export const models: Models = { [ModelClass.IMAGE]: settings.IMAGE_HYPERBOLIC_MODEL || "FLUX.1-dev", }, }, + [ModelProviderName.VENICE]: { + endpoint: "https://api.venice.ai/api/v1", + settings: { + stop: [], + maxInputTokens: 128000, + maxOutputTokens: 8192, + temperature: 0.6, + }, + model: { + [ModelClass.SMALL]: settings.SMALL_VENICE_MODEL || "llama-3.3-70b", + [ModelClass.MEDIUM]: settings.MEDIUM_VENICE_MODEL || "llama-3.3-70b", + [ModelClass.LARGE]: settings.LARGE_VENICE_MODEL || "llama-3.1-405b", + }, + }, }; export function getModel(provider: ModelProviderName, type: ModelClass) { diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts index ca6c0b18ab..7d37f1ee35 100644 --- a/packages/core/src/runtime.ts +++ b/packages/core/src/runtime.ts @@ -142,6 +142,7 @@ export class AgentRuntime implements IAgentRuntime { services: Map = new Map(); memoryManagers: Map = new Map(); cacheManager: ICacheManager; + clients: Record; registerMemoryManager(manager: IMemoryManager): void { if (!manager.tableName) { @@ -405,6 +406,25 @@ export class AgentRuntime implements IAgentRuntime { } } + async stop() { + elizaLogger.debug('runtime::stop - character', this.character) + // stop services, they don't have a stop function + // just initialize + + // plugins + // have actions, providers, evaluators (no start/stop) + // services (just initialized), clients + + // client have a start + for(const cStr in this.clients) { + const c = this.clients[cStr] + elizaLogger.log('runtime::stop - requesting', cStr, 'client stop for', this.character.name) + c.stop() + } + // we don't need to unregister with directClient + // don't need to worry about knowledge + } + /** * Processes character knowledge by creating document memories and fragment memories. * This function takes an array of knowledge items, creates a document memory for each item if it doesn't exist, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index b9790e98f7..860e68a6d0 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -207,6 +207,7 @@ export type Models = { [ModelProviderName.VOLENGINE]: Model; [ModelProviderName.NANOGPT]: Model; [ModelProviderName.HYPERBOLIC]: Model; + [ModelProviderName.VENICE]: Model; }; /** @@ -234,6 +235,7 @@ export enum ModelProviderName { VOLENGINE = "volengine", NANOGPT = "nanogpt", HYPERBOLIC = "hyperbolic", + VENICE = "venice", } /** @@ -603,7 +605,9 @@ export type Plugin = { */ export enum Clients { DISCORD = "discord", - DIRECT = "direct", +// you can't specify this in characters +// all characters are registered with this +// DIRECT = "direct", TWITTER = "twitter", TELEGRAM = "telegram", FARCASTER = "farcaster", @@ -713,6 +717,11 @@ export type Character = { discord?: { shouldIgnoreBotMessages?: boolean; shouldIgnoreDirectMessages?: boolean; + messageSimilarityThreshold?: number; + isPartOfTeam?: boolean; + teamAgentIds?: string[]; + teamLeaderId?: string; + teamMemberInterestKeywords?: string[]; }; telegram?: { shouldIgnoreBotMessages?: boolean; @@ -1003,6 +1012,9 @@ export interface IAgentRuntime { cacheManager: ICacheManager; services: Map; + // any could be EventEmitter + // but I think the real solution is forthcoming as a base client interface + clients: Record; initialize(): Promise; diff --git a/packages/plugin-node/src/services/transcription.ts b/packages/plugin-node/src/services/transcription.ts index 43bbf37360..35c8546a76 100644 --- a/packages/plugin-node/src/services/transcription.ts +++ b/packages/plugin-node/src/services/transcription.ts @@ -14,6 +14,7 @@ import os from "os"; import path from "path"; import { fileURLToPath } from "url"; import { promisify } from "util"; +import { createClient, DeepgramClient } from "@deepgram/sdk"; // const __dirname = path.dirname(new URL(import.meta.url).pathname); #compatibility issues with windows const __filename = fileURLToPath(import.meta.url); @@ -25,17 +26,23 @@ export class TranscriptionService extends Service implements ITranscriptionService { + private runtime: IAgentRuntime | null = null; static serviceType: ServiceType = ServiceType.TRANSCRIPTION; private CONTENT_CACHE_DIR: string; private DEBUG_AUDIO_DIR: string; private TARGET_SAMPLE_RATE = 16000; // Common sample rate for speech recognition private isCudaAvailable: boolean = false; private openai: OpenAI | null = null; + private deepgram?: DeepgramClient; private queue: { audioBuffer: ArrayBuffer; resolve: Function }[] = []; private processing: boolean = false; - async initialize(_runtime: IAgentRuntime): Promise {} + async initialize(_runtime: IAgentRuntime): Promise { + this.runtime = _runtime; + const deepgramKey = this.runtime.getSetting("DEEPGRAM_API_KEY"); + this.deepgram = deepgramKey ? createClient(deepgramKey) : null; + } constructor() { super(); @@ -194,8 +201,9 @@ export class TranscriptionService while (this.queue.length > 0) { const { audioBuffer, resolve } = this.queue.shift()!; let result: string | null = null; - - if (this.openai) { + if (this.deepgram) { + result = await this.transcribeWithDeepgram(audioBuffer); + } else if (this.openai) { result = await this.transcribeWithOpenAI(audioBuffer); } else { result = await this.transcribeLocally(audioBuffer); @@ -207,6 +215,23 @@ export class TranscriptionService this.processing = false; } + private async transcribeWithDeepgram( + audioBuffer: ArrayBuffer + ): Promise { + const buffer = Buffer.from(audioBuffer); + const response = await this.deepgram.listen.prerecorded.transcribeFile( + buffer, + { + model: "nova-2", + language: "en-US", + smart_format: true, + } + ); + const result = + response.result.results.channels[0].alternatives[0].transcript; + return result; + } + private async transcribeWithOpenAI( audioBuffer: ArrayBuffer ): Promise { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 92f3c9d09f..1332136fa1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -298,7 +298,7 @@ importers: version: 3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/preset-classic': specifier: 3.6.3 - version: 3.6.3(@algolia/client-search@5.17.0)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10) + version: 3.6.3(@algolia/client-search@5.17.1)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/theme-mermaid': specifier: 3.6.3 version: 3.6.3(@docusaurus/plugin-content-docs@3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10))(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) @@ -531,7 +531,7 @@ importers: version: link:../core '@neynar/nodejs-sdk': specifier: ^2.0.3 - version: 2.2.0(bufferutil@4.0.8)(class-transformer@0.5.1)(encoding@0.1.13)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.2.3(bufferutil@4.0.8)(class-transformer@0.5.1)(encoding@0.1.13)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: tsup: specifier: ^8.3.5 @@ -662,7 +662,7 @@ importers: version: 10.0.0 ai: specifier: 3.4.33 - version: 3.4.33(openai@4.73.0(encoding@0.1.13)(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.11.0))(svelte@5.11.0)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + version: 3.4.33(openai@4.73.0(encoding@0.1.13)(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.12.0))(svelte@5.12.0)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) anthropic-vertex-ai: specifier: 1.0.2 version: 1.0.2(encoding@0.1.13)(zod@3.23.8) @@ -1631,8 +1631,8 @@ packages: '@algolia/cache-in-memory@4.24.0': resolution: {integrity: sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==} - '@algolia/client-abtesting@5.17.0': - resolution: {integrity: sha512-6+7hPdOEPfJqjWNYPRaVcttLLAtVqQyp1U7xBA1e1uSya1ivIr9FtS/GBr31mfvwk2N2yxV4W7itxuBtST8SWg==} + '@algolia/client-abtesting@5.17.1': + resolution: {integrity: sha512-Os/xkQbDp5A5RdGYq1yS3fF69GoBJH5FIfrkVh+fXxCSe714i1Xdl9XoXhS4xG76DGKm6EFMlUqP024qjps8cg==} engines: {node: '>= 14.0.0'} '@algolia/client-account@4.24.0': @@ -1641,44 +1641,44 @@ packages: '@algolia/client-analytics@4.24.0': resolution: {integrity: sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==} - '@algolia/client-analytics@5.17.0': - resolution: {integrity: sha512-nhJ+elL8h0Fts3xD9261zE2NvTs7nPMe9/SfAgMnWnbvxmuhJn7ZymnBsfm2VkTDb4Dy810ZAdBfzYEk7PjlAw==} + '@algolia/client-analytics@5.17.1': + resolution: {integrity: sha512-WKpGC+cUhmdm3wndIlTh8RJXoVabUH+4HrvZHC4hXtvCYojEXYeep8RZstatwSZ7Ocg6Y2u67bLw90NEINuYEw==} engines: {node: '>= 14.0.0'} '@algolia/client-common@4.24.0': resolution: {integrity: sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==} - '@algolia/client-common@5.17.0': - resolution: {integrity: sha512-9eC8i41/4xcQ/wI6fVM4LwC/ZGcDl3mToqjM0wTZzePWhXgRrdzOzqy/XgP+L1yYCDfkMFBZZsruNL5U8aEOag==} + '@algolia/client-common@5.17.1': + resolution: {integrity: sha512-5rb5+yPIie6912riAypTSyzbE23a7UM1UpESvD8GEPI4CcWQvA9DBlkRNx9qbq/nJ5pvv8VjZjUxJj7rFkzEAA==} engines: {node: '>= 14.0.0'} - '@algolia/client-insights@5.17.0': - resolution: {integrity: sha512-JL/vWNPUIuScsJubyC4aPHkpMftlK2qGqMiR2gy0rGvrh8v0w+ec6Ebq+efoFgE8wO55HJPTxiKeerE1DaQgvA==} + '@algolia/client-insights@5.17.1': + resolution: {integrity: sha512-nb/tfwBMn209TzFv1DDTprBKt/wl5btHVKoAww9fdEVdoKK02R2KAqxe5tuXLdEzAsS+LevRyOM/YjXuLmPtjQ==} engines: {node: '>= 14.0.0'} '@algolia/client-personalization@4.24.0': resolution: {integrity: sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==} - '@algolia/client-personalization@5.17.0': - resolution: {integrity: sha512-PkMUfww8QiRpyLkW4kzmc7IJDcW90sfUpnTgUOVlug5zEE2iv1ruHrJxdcNRTXkA0fgVpHu3oxXmCQL/ie2p7A==} + '@algolia/client-personalization@5.17.1': + resolution: {integrity: sha512-JuNlZe1SdW9KbV0gcgdsiVkFfXt0mmPassdS3cBSGvZGbPB9JsHthD719k5Y6YOY4dGvw1JmC1i9CwCQHAS8hg==} engines: {node: '>= 14.0.0'} - '@algolia/client-query-suggestions@5.17.0': - resolution: {integrity: sha512-bokfgPN2whetLuiX9NB6C6d7Eke+dvHuASOPiB+jdI8Z6hacLHkcJjYeZY4Mppj0/oJ1KlyNivj+8WNpZeGhYA==} + '@algolia/client-query-suggestions@5.17.1': + resolution: {integrity: sha512-RBIFIv1QE3IlAikJKWTOpd6pwE4d2dY6t02iXH7r/SLXWn0HzJtsAPPeFg/OKkFvWAXt0H7In2/Mp7a1/Dy2pw==} engines: {node: '>= 14.0.0'} '@algolia/client-search@4.24.0': resolution: {integrity: sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==} - '@algolia/client-search@5.17.0': - resolution: {integrity: sha512-alY3U79fiEvlR/0optgt1LZp9MfthXFnuEA4GYS81svozDOF61gdvxgBjt6SYtmskmTQQZDWVgakvUvvHrDzMw==} + '@algolia/client-search@5.17.1': + resolution: {integrity: sha512-bd5JBUOP71kPsxwDcvOxqtqXXVo/706NFifZ/O5Rx5GB8ZNVAhg4l7aGoT6jBvEfgmrp2fqPbkdIZ6JnuOpGcw==} engines: {node: '>= 14.0.0'} '@algolia/events@4.0.1': resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==} - '@algolia/ingestion@1.17.0': - resolution: {integrity: sha512-9+mO+FbIpWz6izh1lXzON9BcenBKx4K3qVjSWiFFmL8nv+7b7zpGq++LXWr/Lxv/bZ9+D71Go6QVL6AZQhFOmg==} + '@algolia/ingestion@1.17.1': + resolution: {integrity: sha512-T18tvePi1rjRYcIKhd82oRukrPWHxG/Iy1qFGaxCplgRm9Im5z96qnYOq75MSKGOUHkFxaBKJOLmtn8xDR+Mcw==} engines: {node: '>= 14.0.0'} '@algolia/logger-common@4.24.0': @@ -1687,36 +1687,36 @@ packages: '@algolia/logger-console@4.24.0': resolution: {integrity: sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==} - '@algolia/monitoring@1.17.0': - resolution: {integrity: sha512-Db7Qh51zVchmHa8d9nQFzTz2Ta6H2D4dpCnPj1giC/LE6UG/6e3iOnRxUzV+9ZR7etHKIrri2hbnkyNrvbqA9A==} + '@algolia/monitoring@1.17.1': + resolution: {integrity: sha512-gDtow+AUywTehRP8S1tWKx2IvhcJOxldAoqBxzN3asuQobF7er5n72auBeL++HY4ImEuzMi7PDOA/Iuwxs2IcA==} engines: {node: '>= 14.0.0'} '@algolia/recommend@4.24.0': resolution: {integrity: sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==} - '@algolia/recommend@5.17.0': - resolution: {integrity: sha512-7vM4+mfuLYbslj8+RNsP/ISwY7izu5HcQqQhA0l+q3EZRHF+PBeRaJXc3S1N0fTRxj8ystvwXWZPmjssB/xMLw==} + '@algolia/recommend@5.17.1': + resolution: {integrity: sha512-2992tTHkRe18qmf5SP57N78kN1D3e5t4PO1rt10sJncWtXBZWiNOK6K/UcvWsFbNSGAogFcIcvIMAl5mNp6RWA==} engines: {node: '>= 14.0.0'} '@algolia/requester-browser-xhr@4.24.0': resolution: {integrity: sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==} - '@algolia/requester-browser-xhr@5.17.0': - resolution: {integrity: sha512-bXSiPL2R08s4e9qvNZsJA0bXZeyWH2A5D4shS8kRT22b8GgjtnGTuoZmi6MxtKOEaN0lpHPbjvjXAO7UIOhDog==} + '@algolia/requester-browser-xhr@5.17.1': + resolution: {integrity: sha512-XpKgBfyczVesKgr7DOShNyPPu5kqlboimRRPjdqAw5grSyHhCmb8yoTIKy0TCqBABZeXRPMYT13SMruUVRXvHA==} engines: {node: '>= 14.0.0'} '@algolia/requester-common@4.24.0': resolution: {integrity: sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==} - '@algolia/requester-fetch@5.17.0': - resolution: {integrity: sha512-mjJ6Xv7TlDDoZ6RLKrEzH1ved3g2GAq3YJjb94bA639INfxK1HM8A/wCAFSZ8ye+QM/jppwauDXe1PENkuareQ==} + '@algolia/requester-fetch@5.17.1': + resolution: {integrity: sha512-EhUomH+DZP5vb6DnEjT0GvXaXBSwzZnuU6hPGNU1EYKRXDouRjII/bIWpVjt7ycMgL2D2oQruqDh6rAWUhQwRw==} engines: {node: '>= 14.0.0'} '@algolia/requester-node-http@4.24.0': resolution: {integrity: sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==} - '@algolia/requester-node-http@5.17.0': - resolution: {integrity: sha512-Z2BXTR7BctlGPNig21k2wf/5nlH+96lU2UElzXTKiptyn2iM8lDU8zdO+dRll0AxQUxUGWEnkBysst9xL3S2cg==} + '@algolia/requester-node-http@5.17.1': + resolution: {integrity: sha512-PSnENJtl4/wBWXlGyOODbLYm6lSiFqrtww7UpQRCJdsHXlJKF8XAP6AME8NxvbE0Qo/RJUxK0mvyEh9sQcx6bg==} engines: {node: '>= 14.0.0'} '@algolia/transporter@4.24.0': @@ -3088,7 +3088,6 @@ packages: resolution: {integrity: sha512-hArn9FF5ZYi1IkxdJEVnJi+OxlwLV0NJYWpKXsmNOojtGtAZHxmsELA+MZlu2KW1F/K1/nt7lFOfcMXNYweq9w==} version: 0.17.0 engines: {node: '>=16.11.0'} - deprecated: This version uses deprecated encryption modes. Please use a newer version. '@discordjs/ws@1.1.1': resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==} @@ -4345,8 +4344,8 @@ packages: '@nestjs/websockets': optional: true - '@neynar/nodejs-sdk@2.2.0': - resolution: {integrity: sha512-+vCC4hNWJwhsj0JmhhomgbW+wul1XyVQiceFGXE6weW//vpIfVSm8TwcYk8FWHsEPZyyry0IHctIW0Y8qjLx4w==} + '@neynar/nodejs-sdk@2.2.3': + resolution: {integrity: sha512-9CW2j64yFJEg70A0D6qc3EE5x8NnMzHMRNdA9VuLYZQA1GzoOWsi6/BKxPX/vfgSvnNeveCIPtUzEXRSTbGarQ==} engines: {node: '>=19.9.0'} '@noble/curves@1.2.0': @@ -7344,8 +7343,8 @@ packages: algoliasearch@4.24.0: resolution: {integrity: sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==} - algoliasearch@5.17.0: - resolution: {integrity: sha512-BpuFprDFc3Pe9a1ZXLzLeqZ+l8Ur37AfzBswkOB4LwikqnRPbIGdluT/nFc/Xk+u/QMxMzUlTN+izqQJVb5vYA==} + algoliasearch@5.17.1: + resolution: {integrity: sha512-3CcbT5yTWJDIcBe9ZHgsPi184SkT1kyZi3GWlQU5EFgvq1V73X2sqHRkPCQMe0RA/uvZbB+1sFeAk73eWygeLg==} engines: {node: '>= 14.0.0'} amp-message@0.1.2: @@ -7653,8 +7652,8 @@ packages: bare-path@2.1.3: resolution: {integrity: sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==} - bare-stream@2.5.2: - resolution: {integrity: sha512-QK6bePvszntxgPKdVXciYzjlWv2Ry1mQuUqyUUzd27G7eLupl6d0K5AGJfnfyFAdgy5tRolHP/zbaUMslLceOg==} + bare-stream@2.6.1: + resolution: {integrity: sha512-eVZbtKM+4uehzrsj49KtCy3Pbg7kO1pJ3SKZ1SFrIH/0pnj9scuGGgUlNDf/7qS8WKtGdiJY5Kyhs/ivYPTB/g==} base-x@3.0.10: resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} @@ -7814,8 +7813,8 @@ packages: browser-headers@0.4.1: resolution: {integrity: sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==} - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + browserslist@4.24.3: + resolution: {integrity: sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -7983,8 +7982,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001687: - resolution: {integrity: sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==} + caniuse-lite@1.0.30001688: + resolution: {integrity: sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==} canvas@2.11.2: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} @@ -8581,8 +8580,8 @@ packages: peerDependencies: postcss: ^8.0.9 - css-has-pseudo@7.0.1: - resolution: {integrity: sha512-EOcoyJt+OsuKfCADgLT7gADZI5jMzIe/AeI6MeAYKiFBDmNmM7kk46DtSfMj5AohUJisqVzopBpnQTlvbyaBWg==} + css-has-pseudo@7.0.2: + resolution: {integrity: sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ==} engines: {node: '>=18'} peerDependencies: postcss: ^8.4 @@ -9314,8 +9313,8 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.72: - resolution: {integrity: sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==} + electron-to-chromium@1.5.73: + resolution: {integrity: sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==} elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} @@ -9421,6 +9420,10 @@ packages: es-module-lexer@1.5.4: resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + es5-ext@0.10.64: resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} engines: {node: '>=0.10'} @@ -10093,8 +10096,8 @@ packages: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} - get-intrinsic@1.2.5: - resolution: {integrity: sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==} + get-intrinsic@1.2.6: + resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==} engines: {node: '>= 0.4'} get-nonce@1.0.1: @@ -10421,8 +10424,8 @@ packages: hast-util-to-estree@3.1.0: resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} - hast-util-to-html@9.0.3: - resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} + hast-util-to-html@9.0.4: + resolution: {integrity: sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==} hast-util-to-jsx-runtime@2.3.2: resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==} @@ -11499,8 +11502,8 @@ packages: resolution: {integrity: sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==} engines: {node: '>=16.0.0'} - langsmith@0.2.12: - resolution: {integrity: sha512-FP1eMcM/ckocagtzKsD6WEjkSOZKImOmKK83hOgULa3pNGnc3nWRvCRIniZVLjCaXw9SOFR3K2ah0o3FvQhM5A==} + langsmith@0.2.13: + resolution: {integrity: sha512-16EOM5nhU6GlMCKGm5sgBIAKOKzS2d30qcDZmF21kSLZJiUhUNTROwvYdqgZLrGfIIzmSMJHCKA7RFd5qf50uw==} peerDependencies: openai: '*' peerDependenciesMeta: @@ -11871,6 +11874,10 @@ packages: engines: {node: '>= 18'} hasBin: true + math-intrinsics@1.0.0: + resolution: {integrity: sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==} + engines: {node: '>= 0.4'} + md4w@0.2.6: resolution: {integrity: sha512-CBLQ2PxVe9WA+/nndZCx/Y+1C3DtmtSeubmXTPhMIgsXtq9gVGleikREko5FYnV6Dz4cHDWm0Ea+YMLpIjP4Kw==} @@ -12965,8 +12972,8 @@ packages: parse-data-uri@0.2.0: resolution: {integrity: sha512-uOtts8NqDcaCt1rIsO3VFDRsAfgE4c6osG4d9z3l4dCBlxYFzni6Di/oNU270SDrjkfZuUvLZx1rxMyqh46Y9w==} - parse-entities@4.0.1: - resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} parse-json@4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} @@ -13805,8 +13812,8 @@ packages: peerDependencies: postcss: ^8.4 - postcss-preset-env@10.1.1: - resolution: {integrity: sha512-wqqsnBFD6VIwcHHRbhjTOcOi4qRVlB26RwSr0ordPj7OubRRxdWebv/aLjKLRR8zkZrbxZyuus03nOIgC5elMQ==} + postcss-preset-env@10.1.2: + resolution: {integrity: sha512-OqUBZ9ByVfngWhMNuBEMy52Izj07oIFA6K/EOGBlaSv+P12MiE1+S2cqXtS1VuW82demQ/Tzc7typYk3uHunkA==} engines: {node: '>=18'} peerDependencies: postcss: ^8.4 @@ -13950,8 +13957,8 @@ packages: postgres-range@1.1.4: resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} - preact@10.25.1: - resolution: {integrity: sha512-frxeZV2vhQSohQwJ7FvlqC40ze89+8friponWUFeVEkaCfhC6Eu4V0iND5C9CXz8JLndV07QRDeXzH1+Anz5Og==} + preact@10.25.2: + resolution: {integrity: sha512-GEts1EH3oMnqdOIeXhlbBSddZ9nrINd070WBOiPO2ous1orrKGUM4SMDbwyjSWD1iMS2dBvaDjAa5qUhz3TXqw==} prebuild-install@7.1.2: resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} @@ -15238,8 +15245,8 @@ packages: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} - streamx@2.21.0: - resolution: {integrity: sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==} + streamx@2.21.1: + resolution: {integrity: sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==} strict-uri-encode@2.0.0: resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} @@ -15389,8 +15396,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte@5.11.0: - resolution: {integrity: sha512-w4FYvEY1eKbgBZo8RY2iegaOe9sZu9yhDa70cAyW9gkPJc87w6/1rrfNI4uu985s/7U+4CggQDE7CPIbrPsnXw==} + svelte@5.12.0: + resolution: {integrity: sha512-nOd7uj0D/4A3IrHnltaFYndVPGViYSs0s+Zi3N4uQg3owJt9RoiUdwxYx8qjorj5CtaGsx8dNYsFVbH6czrGNg==} engines: {node: '>=18'} svg-parser@2.0.4: @@ -15478,8 +15485,8 @@ packages: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} engines: {node: '>=4'} - terser-webpack-plugin@5.3.10: - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + terser-webpack-plugin@5.3.11: + resolution: {integrity: sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -15601,14 +15608,14 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} - tldts-core@6.1.66: - resolution: {integrity: sha512-s07jJruSwndD2X8bVjwioPfqpIc1pDTzszPe9pL1Skbh4bjytL85KNQ3tolqLbCvpQHawIsGfFi9dgerWjqW4g==} + tldts-core@6.1.67: + resolution: {integrity: sha512-12K5O4m3uUW6YM5v45Z7wc6NTSmAYj4Tq3de7eXghZkp879IlfPJrUWeWFwu1FS94U5t2vwETgJ1asu8UGNKVQ==} - tldts-experimental@6.1.66: - resolution: {integrity: sha512-hAgdTxaOC1QP2WoB4HKH1R6Df7MDusIFtljZ9XB3bndsQPKeUxHyAuOmvXxzdF7MrgfJmMtfusavNlX/ateEow==} + tldts-experimental@6.1.67: + resolution: {integrity: sha512-M5HZFMmtfxXcTQSTHu4Pn51CJdOK4hFw+y9KCj6bRRNaJRffNJIpTqSLixol+P+0v3NkXYxb1Mm90goJksCSrw==} - tldts@6.1.66: - resolution: {integrity: sha512-l3ciXsYFel/jSRfESbyKYud1nOw7WfhrBEF9I3UiarYk/qEaOOwu3qXNECHw4fHGHGTEOuhf/VdKgoDX5M/dhQ==} + tldts@6.1.67: + resolution: {integrity: sha512-714VbegxoZ9WF5/IsVCy9rWXKUpPkJq87ebWLXQzNawce96l5oRrRf2eHzB4pT2g/4HQU1dYbu+sdXClYxlDKQ==} hasBin: true tmp@0.0.33: @@ -16993,13 +17000,13 @@ snapshots: transitivePeerDependencies: - zod - '@ai-sdk/svelte@0.0.57(svelte@5.11.0)(zod@3.23.8)': + '@ai-sdk/svelte@0.0.57(svelte@5.12.0)(zod@3.23.8)': dependencies: '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - sswr: 2.1.0(svelte@5.11.0) + sswr: 2.1.0(svelte@5.12.0) optionalDependencies: - svelte: 5.11.0 + svelte: 5.12.0 transitivePeerDependencies: - zod @@ -17023,33 +17030,33 @@ snapshots: transitivePeerDependencies: - zod - '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0)(search-insights@2.17.3)': + '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0)(search-insights@2.17.3) - '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0) + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)(search-insights@2.17.3) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1) transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - search-insights - '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0)(search-insights@2.17.3)': + '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1) search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0)': + '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)': dependencies: - '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0) - '@algolia/client-search': 5.17.0 - algoliasearch: 5.17.0 + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1) + '@algolia/client-search': 5.17.1 + algoliasearch: 5.17.1 - '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0)': + '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)': dependencies: - '@algolia/client-search': 5.17.0 - algoliasearch: 5.17.0 + '@algolia/client-search': 5.17.1 + algoliasearch: 5.17.1 '@algolia/cache-browser-local-storage@4.24.0': dependencies: @@ -17061,12 +17068,12 @@ snapshots: dependencies: '@algolia/cache-common': 4.24.0 - '@algolia/client-abtesting@5.17.0': + '@algolia/client-abtesting@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/client-account@4.24.0': dependencies: @@ -17081,26 +17088,26 @@ snapshots: '@algolia/requester-common': 4.24.0 '@algolia/transporter': 4.24.0 - '@algolia/client-analytics@5.17.0': + '@algolia/client-analytics@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/client-common@4.24.0': dependencies: '@algolia/requester-common': 4.24.0 '@algolia/transporter': 4.24.0 - '@algolia/client-common@5.17.0': {} + '@algolia/client-common@5.17.1': {} - '@algolia/client-insights@5.17.0': + '@algolia/client-insights@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/client-personalization@4.24.0': dependencies: @@ -17108,19 +17115,19 @@ snapshots: '@algolia/requester-common': 4.24.0 '@algolia/transporter': 4.24.0 - '@algolia/client-personalization@5.17.0': + '@algolia/client-personalization@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 - '@algolia/client-query-suggestions@5.17.0': + '@algolia/client-query-suggestions@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/client-search@4.24.0': dependencies: @@ -17128,21 +17135,21 @@ snapshots: '@algolia/requester-common': 4.24.0 '@algolia/transporter': 4.24.0 - '@algolia/client-search@5.17.0': + '@algolia/client-search@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/events@4.0.1': {} - '@algolia/ingestion@1.17.0': + '@algolia/ingestion@1.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/logger-common@4.24.0': {} @@ -17150,12 +17157,12 @@ snapshots: dependencies: '@algolia/logger-common': 4.24.0 - '@algolia/monitoring@1.17.0': + '@algolia/monitoring@1.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/recommend@4.24.0': dependencies: @@ -17171,34 +17178,34 @@ snapshots: '@algolia/requester-node-http': 4.24.0 '@algolia/transporter': 4.24.0 - '@algolia/recommend@5.17.0': + '@algolia/recommend@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + '@algolia/client-common': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 '@algolia/requester-browser-xhr@4.24.0': dependencies: '@algolia/requester-common': 4.24.0 - '@algolia/requester-browser-xhr@5.17.0': + '@algolia/requester-browser-xhr@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 + '@algolia/client-common': 5.17.1 '@algolia/requester-common@4.24.0': {} - '@algolia/requester-fetch@5.17.0': + '@algolia/requester-fetch@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 + '@algolia/client-common': 5.17.1 '@algolia/requester-node-http@4.24.0': dependencies: '@algolia/requester-common': 4.24.0 - '@algolia/requester-node-http@5.17.0': + '@algolia/requester-node-http@5.17.1': dependencies: - '@algolia/client-common': 5.17.0 + '@algolia/client-common': 5.17.1 '@algolia/transporter@4.24.0': dependencies: @@ -17998,7 +18005,7 @@ snapshots: dependencies: '@babel/compat-data': 7.26.3 '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 + browserslist: 4.24.3 lru-cache: 5.1.1 semver: 6.3.1 @@ -18817,7 +18824,7 @@ snapshots: '@cliqz/adblocker': 1.34.0 '@cliqz/adblocker-content': 1.34.0 playwright: 1.48.2 - tldts-experimental: 6.1.66 + tldts-experimental: 6.1.67 '@cliqz/adblocker@1.34.0': dependencies: @@ -18828,7 +18835,7 @@ snapshots: '@remusao/smaz': 1.10.0 '@types/chrome': 0.0.278 '@types/firefox-webext-browser': 120.0.4 - tldts-experimental: 6.1.66 + tldts-experimental: 6.1.67 '@coinbase-samples/advanced-sdk-ts@file:packages/plugin-coinbase/advanced-sdk-ts(encoding@0.1.13)': dependencies: @@ -19385,12 +19392,12 @@ snapshots: '@docsearch/css@3.8.0': {} - '@docsearch/react@3.8.0(@algolia/client-search@5.17.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': + '@docsearch/react@3.8.0(@algolia/client-search@5.17.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0)(search-insights@2.17.3) - '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.17.0)(algoliasearch@5.17.0) + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)(search-insights@2.17.3) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1) '@docsearch/css': 3.8.0 - algoliasearch: 5.17.0 + algoliasearch: 5.17.1 optionalDependencies: '@types/react': 18.3.12 react: 18.3.1 @@ -19447,9 +19454,9 @@ snapshots: null-loader: 4.0.1(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) postcss: 8.4.49 postcss-loader: 7.3.4(postcss@8.4.49)(typescript@5.6.3)(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) - postcss-preset-env: 10.1.1(postcss@8.4.49) + postcss-preset-env: 10.1.2(postcss@8.4.49) react-dev-utils: 12.0.1(eslint@9.16.0(jiti@2.4.0))(typescript@5.6.3)(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) - terser-webpack-plugin: 5.3.10(@swc/core@1.10.1(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.1(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) tslib: 2.8.1 url-loader: 4.1.1(file-loader@6.2.0(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) @@ -19927,7 +19934,7 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/preset-classic@3.6.3(@algolia/client-search@5.17.0)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10)': + '@docusaurus/preset-classic@3.6.3(@algolia/client-search@5.17.1)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10)': dependencies: '@docusaurus/core': 3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/plugin-content-blog': 3.6.3(@docusaurus/plugin-content-docs@3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10))(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) @@ -19940,7 +19947,7 @@ snapshots: '@docusaurus/plugin-sitemap': 3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/theme-classic': 3.6.3(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/theme-common': 3.6.3(@docusaurus/plugin-content-docs@3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) - '@docusaurus/theme-search-algolia': 3.6.3(@algolia/client-search@5.17.0)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10) + '@docusaurus/theme-search-algolia': 3.6.3(@algolia/client-search@5.17.1)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/types': 3.6.3(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -20089,9 +20096,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-search-algolia@3.6.3(@algolia/client-search@5.17.0)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10)': + '@docusaurus/theme-search-algolia@3.6.3(@algolia/client-search@5.17.1)(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/react@18.3.12)(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)(utf-8-validate@5.0.10)': dependencies: - '@docsearch/react': 3.8.0(@algolia/client-search@5.17.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) + '@docsearch/react': 3.8.0(@algolia/client-search@5.17.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) '@docusaurus/core': 3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) '@docusaurus/logger': 3.6.3 '@docusaurus/plugin-content-docs': 3.6.3(@mdx-js/react@3.0.1(@types/react@18.3.12)(react@18.3.1))(@swc/core@1.10.1(@swc/helpers@0.5.15))(acorn@8.14.0)(bufferutil@4.0.8)(eslint@9.16.0(jiti@2.4.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)(utf-8-validate@5.0.10) @@ -21119,7 +21126,7 @@ snapshots: camelcase: 6.3.0 decamelize: 1.2.0 js-tiktoken: 1.0.15 - langsmith: 0.2.12(openai@4.73.0(encoding@0.1.13)(zod@3.23.8)) + langsmith: 0.2.13(openai@4.73.0(encoding@0.1.13)(zod@3.23.8)) mustache: 4.2.0 p-queue: 6.6.2 p-retry: 4.6.2 @@ -21397,7 +21404,7 @@ snapshots: transitivePeerDependencies: - encoding - '@neynar/nodejs-sdk@2.2.0(bufferutil@4.0.8)(class-transformer@0.5.1)(encoding@0.1.13)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)': + '@neynar/nodejs-sdk@2.2.3(bufferutil@4.0.8)(class-transformer@0.5.1)(encoding@0.1.13)(typescript@5.6.3)(utf-8-validate@5.0.10)(zod@3.23.8)': dependencies: '@openapitools/openapi-generator-cli': 2.15.3(class-transformer@0.5.1)(encoding@0.1.13) semver: 7.6.3 @@ -22027,7 +22034,7 @@ snapshots: '@walletconnect/types': 2.17.2 '@walletconnect/utils': 2.17.2 postcss-cli: 11.0.0(jiti@2.4.0)(postcss@8.4.49) - preact: 10.25.1 + preact: 10.25.2 tailwindcss: 3.4.15(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.8.4)(typescript@5.6.3)) transitivePeerDependencies: - '@azure/app-configuration' @@ -22947,7 +22954,7 @@ snapshots: '@shikijs/types': 1.24.2 '@shikijs/vscode-textmate': 9.3.1 '@types/hast': 3.0.4 - hast-util-to-html: 9.0.3 + hast-util-to-html: 9.0.4 '@shikijs/engine-javascript@1.24.2': dependencies: @@ -25304,13 +25311,13 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@3.4.33(openai@4.73.0(encoding@0.1.13)(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.11.0))(svelte@5.11.0)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8): + ai@3.4.33(openai@4.73.0(encoding@0.1.13)(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.12.0))(svelte@5.12.0)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8): dependencies: '@ai-sdk/provider': 0.0.26 '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) '@ai-sdk/react': 0.0.70(react@18.3.1)(zod@3.23.8) '@ai-sdk/solid': 0.0.54(zod@3.23.8) - '@ai-sdk/svelte': 0.0.57(svelte@5.11.0)(zod@3.23.8) + '@ai-sdk/svelte': 0.0.57(svelte@5.12.0)(zod@3.23.8) '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) '@ai-sdk/vue': 0.0.59(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) '@opentelemetry/api': 1.9.0 @@ -25322,8 +25329,8 @@ snapshots: optionalDependencies: openai: 4.73.0(encoding@0.1.13)(zod@3.23.8) react: 18.3.1 - sswr: 2.1.0(svelte@5.11.0) - svelte: 5.11.0 + sswr: 2.1.0(svelte@5.12.0) + svelte: 5.12.0 zod: 3.23.8 transitivePeerDependencies: - solid-js @@ -25381,21 +25388,21 @@ snapshots: '@algolia/requester-node-http': 4.24.0 '@algolia/transporter': 4.24.0 - algoliasearch@5.17.0: - dependencies: - '@algolia/client-abtesting': 5.17.0 - '@algolia/client-analytics': 5.17.0 - '@algolia/client-common': 5.17.0 - '@algolia/client-insights': 5.17.0 - '@algolia/client-personalization': 5.17.0 - '@algolia/client-query-suggestions': 5.17.0 - '@algolia/client-search': 5.17.0 - '@algolia/ingestion': 1.17.0 - '@algolia/monitoring': 1.17.0 - '@algolia/recommend': 5.17.0 - '@algolia/requester-browser-xhr': 5.17.0 - '@algolia/requester-fetch': 5.17.0 - '@algolia/requester-node-http': 5.17.0 + algoliasearch@5.17.1: + dependencies: + '@algolia/client-abtesting': 5.17.1 + '@algolia/client-analytics': 5.17.1 + '@algolia/client-common': 5.17.1 + '@algolia/client-insights': 5.17.1 + '@algolia/client-personalization': 5.17.1 + '@algolia/client-query-suggestions': 5.17.1 + '@algolia/client-search': 5.17.1 + '@algolia/ingestion': 1.17.1 + '@algolia/monitoring': 1.17.1 + '@algolia/recommend': 5.17.1 + '@algolia/requester-browser-xhr': 5.17.1 + '@algolia/requester-fetch': 5.17.1 + '@algolia/requester-node-http': 5.17.1 amp-message@0.1.2: dependencies: @@ -25575,8 +25582,8 @@ snapshots: autoprefixer@10.4.20(postcss@8.4.49): dependencies: - browserslist: 4.24.2 - caniuse-lite: 1.0.30001687 + browserslist: 4.24.3 + caniuse-lite: 1.0.30001688 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -25736,7 +25743,7 @@ snapshots: dependencies: bare-events: 2.5.0 bare-path: 2.1.3 - bare-stream: 2.5.2 + bare-stream: 2.6.1 optional: true bare-os@2.4.4: @@ -25747,9 +25754,9 @@ snapshots: bare-os: 2.4.4 optional: true - bare-stream@2.5.2: + bare-stream@2.6.1: dependencies: - streamx: 2.21.0 + streamx: 2.21.1 optional: true base-x@3.0.10: @@ -25950,12 +25957,12 @@ snapshots: browser-headers@0.4.1: {} - browserslist@4.24.2: + browserslist@4.24.3: dependencies: - caniuse-lite: 1.0.30001687 - electron-to-chromium: 1.5.72 + caniuse-lite: 1.0.30001688 + electron-to-chromium: 1.5.73 node-releases: 2.0.19 - update-browserslist-db: 1.1.1(browserslist@4.24.2) + update-browserslist-db: 1.1.1(browserslist@4.24.3) bs-logger@0.2.6: dependencies: @@ -26113,13 +26120,13 @@ snapshots: dependencies: call-bind-apply-helpers: 1.0.1 es-define-property: 1.0.1 - get-intrinsic: 1.2.5 + get-intrinsic: 1.2.6 set-function-length: 1.2.2 call-bound@1.0.2: dependencies: call-bind: 1.0.8 - get-intrinsic: 1.2.5 + get-intrinsic: 1.2.6 callsites@3.1.0: {} @@ -26151,12 +26158,12 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.24.2 - caniuse-lite: 1.0.30001687 + browserslist: 4.24.3 + caniuse-lite: 1.0.30001688 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001687: {} + caniuse-lite@1.0.30001688: {} canvas@2.11.2(encoding@0.1.13): dependencies: @@ -26711,7 +26718,7 @@ snapshots: core-js-compat@3.39.0: dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 core-js-pure@3.39.0: {} @@ -26854,7 +26861,7 @@ snapshots: dependencies: postcss: 8.4.49 - css-has-pseudo@7.0.1(postcss@8.4.49): + css-has-pseudo@7.0.2(postcss@8.4.49): dependencies: '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.0.0) postcss: 8.4.49 @@ -26927,7 +26934,7 @@ snapshots: cssnano-preset-advanced@6.1.2(postcss@8.4.49): dependencies: autoprefixer: 10.4.20(postcss@8.4.49) - browserslist: 4.24.2 + browserslist: 4.24.3 cssnano-preset-default: 6.1.2(postcss@8.4.49) postcss: 8.4.49 postcss-discard-unused: 6.0.5(postcss@8.4.49) @@ -26937,7 +26944,7 @@ snapshots: cssnano-preset-default@6.1.2(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 css-declaration-sorter: 7.2.0(postcss@8.4.49) cssnano-utils: 4.0.2(postcss@8.4.49) postcss: 8.4.49 @@ -26971,7 +26978,7 @@ snapshots: cssnano-preset-default@7.0.6(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 css-declaration-sorter: 7.2.0(postcss@8.4.49) cssnano-utils: 5.0.0(postcss@8.4.49) postcss: 8.4.49 @@ -27673,7 +27680,7 @@ snapshots: dependencies: jake: 10.9.2 - electron-to-chromium@1.5.72: {} + electron-to-chromium@1.5.73: {} elliptic@6.5.4: dependencies: @@ -27771,6 +27778,10 @@ snapshots: es-module-lexer@1.5.4: {} + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + es5-ext@0.10.64: dependencies: es6-iterator: 2.0.3 @@ -28283,7 +28294,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.3.4 + debug: 4.4.0(supports-color@5.5.0) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -28669,16 +28680,18 @@ snapshots: get-east-asian-width@1.3.0: {} - get-intrinsic@1.2.5: + get-intrinsic@1.2.6: dependencies: call-bind-apply-helpers: 1.0.1 dunder-proto: 1.0.0 es-define-property: 1.0.1 es-errors: 1.3.0 + es-object-atoms: 1.0.0 function-bind: 1.1.2 gopd: 1.2.0 has-symbols: 1.1.0 hasown: 2.0.2 + math-intrinsics: 1.0.0 get-nonce@1.0.1: {} @@ -29132,7 +29145,7 @@ snapshots: transitivePeerDependencies: - supports-color - hast-util-to-html@9.0.3: + hast-util-to-html@9.0.4: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.3 @@ -30508,7 +30521,7 @@ snapshots: js-tiktoken: 1.0.15 js-yaml: 4.1.0 jsonpointer: 5.0.1 - langsmith: 0.2.12(openai@4.73.0(encoding@0.1.13)(zod@3.23.8)) + langsmith: 0.2.13(openai@4.73.0(encoding@0.1.13)(zod@3.23.8)) openapi-types: 12.1.3 p-retry: 4.6.2 uuid: 10.0.0 @@ -30530,7 +30543,7 @@ snapshots: vscode-languageserver-textdocument: 1.0.12 vscode-uri: 3.0.8 - langsmith@0.2.12(openai@4.73.0(encoding@0.1.13)(zod@3.23.8)): + langsmith@0.2.13(openai@4.73.0(encoding@0.1.13)(zod@3.23.8)): dependencies: '@types/uuid': 10.0.0 commander: 10.0.1 @@ -30867,7 +30880,7 @@ snapshots: log-symbols@4.1.0: dependencies: - chalk: 4.1.0 + chalk: 4.1.2 is-unicode-supported: 0.1.0 log-symbols@6.0.0: @@ -31011,6 +31024,8 @@ snapshots: marked@13.0.3: {} + math-intrinsics@1.0.0: {} + md4w@0.2.6: {} md5.js@1.3.5: @@ -31026,7 +31041,7 @@ snapshots: devlop: 1.1.0 mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.1 + parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-visit-parents: 6.0.1 transitivePeerDependencies: @@ -31145,7 +31160,7 @@ snapshots: devlop: 1.1.0 mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.1 + parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 @@ -31334,7 +31349,7 @@ snapshots: micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.1 - parse-entities: 4.0.1 + parse-entities: 4.0.2 micromark-extension-frontmatter@2.0.0: dependencies: @@ -32607,10 +32622,9 @@ snapshots: dependencies: data-uri-to-buffer: 0.0.3 - parse-entities@4.0.1: + parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 - character-entities: 2.0.2 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 decode-named-character-reference: 1.0.2 @@ -33020,7 +33034,7 @@ snapshots: postcss-colormin@6.1.0(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.4.49 @@ -33028,7 +33042,7 @@ snapshots: postcss-colormin@7.0.2(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.4.49 @@ -33036,13 +33050,13 @@ snapshots: postcss-convert-values@6.1.0(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 postcss: 8.4.49 postcss-value-parser: 4.2.0 postcss-convert-values@7.0.4(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 postcss: 8.4.49 postcss-value-parser: 4.2.0 @@ -33225,7 +33239,7 @@ snapshots: postcss-merge-rules@6.1.1(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 caniuse-api: 3.0.0 cssnano-utils: 4.0.2(postcss@8.4.49) postcss: 8.4.49 @@ -33233,7 +33247,7 @@ snapshots: postcss-merge-rules@7.0.4(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 caniuse-api: 3.0.0 cssnano-utils: 5.0.0(postcss@8.4.49) postcss: 8.4.49 @@ -33265,14 +33279,14 @@ snapshots: postcss-minify-params@6.1.0(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 cssnano-utils: 4.0.2(postcss@8.4.49) postcss: 8.4.49 postcss-value-parser: 4.2.0 postcss-minify-params@7.0.2(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 cssnano-utils: 5.0.0(postcss@8.4.49) postcss: 8.4.49 postcss-value-parser: 4.2.0 @@ -33381,13 +33395,13 @@ snapshots: postcss-normalize-unicode@6.1.0(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 postcss: 8.4.49 postcss-value-parser: 4.2.0 postcss-normalize-unicode@7.0.2(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 postcss: 8.4.49 postcss-value-parser: 4.2.0 @@ -33441,7 +33455,7 @@ snapshots: postcss: 8.4.49 postcss-value-parser: 4.2.0 - postcss-preset-env@10.1.1(postcss@8.4.49): + postcss-preset-env@10.1.2(postcss@8.4.49): dependencies: '@csstools/postcss-cascade-layers': 5.0.1(postcss@8.4.49) '@csstools/postcss-color-function': 4.0.6(postcss@8.4.49) @@ -33476,9 +33490,9 @@ snapshots: '@csstools/postcss-trigonometric-functions': 4.0.5(postcss@8.4.49) '@csstools/postcss-unset-value': 4.0.0(postcss@8.4.49) autoprefixer: 10.4.20(postcss@8.4.49) - browserslist: 4.24.2 + browserslist: 4.24.3 css-blank-pseudo: 7.0.1(postcss@8.4.49) - css-has-pseudo: 7.0.1(postcss@8.4.49) + css-has-pseudo: 7.0.2(postcss@8.4.49) css-prefers-color-scheme: 10.0.0(postcss@8.4.49) cssdb: 8.2.3 postcss: 8.4.49 @@ -33520,13 +33534,13 @@ snapshots: postcss-reduce-initial@6.1.0(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 caniuse-api: 3.0.0 postcss: 8.4.49 postcss-reduce-initial@7.0.2(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 caniuse-api: 3.0.0 postcss: 8.4.49 @@ -33626,7 +33640,7 @@ snapshots: postgres-range@1.1.4: {} - preact@10.25.1: {} + preact@10.25.2: {} prebuild-install@7.1.2: dependencies: @@ -33982,7 +33996,7 @@ snapshots: dependencies: '@babel/code-frame': 7.26.2 address: 1.2.2 - browserslist: 4.24.2 + browserslist: 4.24.3 chalk: 4.1.2 cross-spawn: 7.0.6 detect-port-alt: 1.1.6 @@ -34814,7 +34828,7 @@ snapshots: define-data-property: 1.1.4 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.5 + get-intrinsic: 1.2.6 gopd: 1.2.0 has-property-descriptors: 1.0.2 @@ -34915,14 +34929,14 @@ snapshots: dependencies: call-bound: 1.0.2 es-errors: 1.3.0 - get-intrinsic: 1.2.5 + get-intrinsic: 1.2.6 object-inspect: 1.13.3 side-channel-weakmap@1.0.2: dependencies: call-bound: 1.0.2 es-errors: 1.3.0 - get-intrinsic: 1.2.5 + get-intrinsic: 1.2.6 object-inspect: 1.13.3 side-channel-map: 1.0.1 @@ -35184,9 +35198,9 @@ snapshots: dependencies: minipass: 7.1.2 - sswr@2.1.0(svelte@5.11.0): + sswr@2.1.0(svelte@5.12.0): dependencies: - svelte: 5.11.0 + svelte: 5.12.0 swrev: 4.0.0 stack-utils@2.0.6: @@ -35238,7 +35252,7 @@ snapshots: streamsearch@1.1.0: {} - streamx@2.21.0: + streamx@2.21.1: dependencies: fast-fifo: 1.3.2 queue-tick: 1.0.1 @@ -35342,13 +35356,13 @@ snapshots: stylehacks@6.1.1(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 postcss: 8.4.49 postcss-selector-parser: 6.1.2 stylehacks@7.0.4(postcss@8.4.49): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 postcss: 8.4.49 postcss-selector-parser: 6.1.2 @@ -35389,7 +35403,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte@5.11.0: + svelte@5.12.0: dependencies: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.5.0 @@ -35499,7 +35513,7 @@ snapshots: dependencies: b4a: 1.6.7 fast-fifo: 1.3.2 - streamx: 2.21.0 + streamx: 2.21.1 tar@6.2.1: dependencies: @@ -35535,11 +35549,11 @@ snapshots: temp-dir@1.0.0: {} - terser-webpack-plugin@5.3.10(@swc/core@1.10.1(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))): + terser-webpack-plugin@5.3.11(@swc/core@1.10.1(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 - schema-utils: 3.3.0 + schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 webpack: 5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15)) @@ -35640,15 +35654,15 @@ snapshots: tinyspy@3.0.2: {} - tldts-core@6.1.66: {} + tldts-core@6.1.67: {} - tldts-experimental@6.1.66: + tldts-experimental@6.1.67: dependencies: - tldts-core: 6.1.66 + tldts-core: 6.1.67 - tldts@6.1.66: + tldts@6.1.67: dependencies: - tldts-core: 6.1.66 + tldts-core: 6.1.67 tmp@0.0.33: dependencies: @@ -35705,7 +35719,7 @@ snapshots: tough-cookie@5.0.0: dependencies: - tldts: 6.1.66 + tldts: 6.1.67 tr46@0.0.3: {} @@ -36200,9 +36214,9 @@ snapshots: upath@2.0.1: {} - update-browserslist-db@1.1.1(browserslist@4.24.2): + update-browserslist-db@1.1.1(browserslist@4.24.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.3 escalade: 3.2.0 picocolors: 1.1.1 @@ -36700,7 +36714,7 @@ snapshots: '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.14.0 - browserslist: 4.24.2 + browserslist: 4.24.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.17.1 es-module-lexer: 1.5.4 @@ -36714,7 +36728,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.10.1(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.1(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.1(@swc/helpers@0.5.15))) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -37030,4 +37044,4 @@ snapshots: zx@8.2.4: optionalDependencies: '@types/fs-extra': 11.0.4 - '@types/node': 20.17.9 + '@types/node': 20.17.9 \ No newline at end of file