{
  "interval": {
    "intervalStart": "2025-05-23T00:00:00.000Z",
    "intervalEnd": "2025-05-24T00:00:00.000Z",
    "intervalType": "day"
  },
  "repository": "elizaos/eliza",
  "overview": "From 2025-05-23 to 2025-05-24, elizaos/eliza had 30 new PRs (28 merged), 2 new issues, and 17 active contributors.",
  "topIssues": [
    {
      "id": "I_kwDOMT5cIs6sPClh",
      "title": "RAG processFile attempts to embed entire files causing errors for large documents",
      "author": "omikolaj",
      "number": 3745,
      "repository": "elizaos/eliza",
      "body": "**Describe the bug**\n\n`ragknowledge.ts` file is running `embd` function on the entire content of the document, often causing errors with going over token limitations of the underlying model. The code attempts to embed the entire document, and then chunks it out.\n\n**To Reproduce**\n\n1. Create 'knowledge' directory in 'characters' directory.\n2. Add a large pdf to the directory\n3. Update *character.json file `knowledge` property to run embeddings on the file\n4. Update *character.json file `settings.ragKnowledge` property to 'true'\n5. Configure .env file to use `USE_OPENAI_EMBEDDING=true` and provide `OPENAI_API_KEY` and `EMBEDDING_OPENAI_MODEL=text-embedding-3-large` (or small)\n6. Start the server, notice errors: \n```\n[2025-03-02 15:14:48] ERROR: API Response: {\n  \"error\": {\n    \"message\": \"This model's maximum context length is 8192 tokens, however you requested 16376 tokens (16376 in your prompt; 0 for the completion). Please reduce your prompt; or completion length.\",\n    \"type\": \"invalid_request_error\",\n    \"param\": null,\n    \"code\": null\n  }\n}\n```\n\n**Expected behavior**\nAll supported documents embedded without errors\n\n**Screenshots**\n\n![Image](https://github.com/user-attachments/assets/c1d4f359-74b9-4fe5-a38d-c90012a52f27)\n\n**Additional context**\n\nThe code that does this was added on Jan5. It apppears to be in the latest release tag. Its possible Im setting something up wrong, but its not clear what.\n",
      "createdAt": "2025-03-02T15:42:28Z",
      "closedAt": "2025-05-23T02:31:18Z",
      "state": "CLOSED",
      "commentCount": 1
    },
    {
      "id": "I_kwDOMT5cIs6yy4Mz",
      "title": "Ensure USE_LOCAL_AI is always true",
      "author": "jmikedupont2",
      "number": 4303,
      "repository": "elizaos/eliza",
      "body": "Hi team,\nI am wondering about \" Ensure USE_LOCAL_AI is always true\" in v2,\nin my small version I don't want to have local ai loaded.\nIf the user sets it to false, we should respect that.\n\n",
      "createdAt": "2025-04-16T13:34:31Z",
      "closedAt": "2025-05-23T02:29:00Z",
      "state": "CLOSED",
      "commentCount": 1
    },
    {
      "id": "I_kwDOMT5cIs6yyqVg",
      "title": "Task.World is redundant",
      "author": "jmikedupont2",
      "number": 4302,
      "repository": "elizaos/eliza",
      "body": "The world already is referenced from room and task references room, so we dont need to have world in task.\npackages/plugin-sql/src/schema/tasks.ts\n```\n worldId: uuid('world_id').references(() => worldTable.id, {\n   onDelete: 'cascade',\n }),\n\n```",
      "createdAt": "2025-04-16T13:14:06Z",
      "closedAt": "2025-05-23T02:27:26Z",
      "state": "CLOSED",
      "commentCount": 1
    },
    {
      "id": "I_kwDOMT5cIs6yxIb9",
      "title": "How can i handle the content response from the modell?",
      "author": "transformer98",
      "number": 4299,
      "repository": "elizaos/eliza",
      "body": "i am getting the content from the prompt using llama_local model, but i don't want to use that content again in my future prompts based on {recentMessages}, e.g i said i want to swap 0.0001 Eth to USDT on Ethereum chain, the model give me content based on the swapTemplate but when i again prompt like just please swap it gives me the same content, from the recentMessages, how can i restrict the model so that it should not give content based on previous messages? here is the swapTemplate and action code:\n\n```\nexport const swapTemplate = `Respond with a JSON markdown block containing only the extracted values\n- Use default | null for any values that cannot be determined.\n\n{{recentMessages}}\n\n{{walletInfo}}\n\nGiven the recent messages and wallet info, extract the following information about the requested token swap in same chain:\n- Input token symbol.\n- Output token symbol.\n- Input token address. If the address is provided, it must be a valid Ethereum address starting with \"0x\" (the token being sold), default 0x0000000000000000000000000000000000000000.\n- Output token address. If the address is provided, it must be a valid Ethereum address starting with \"0x\" (the token being bought), default 0x0000000000000000000000000000000000000000.\n- Amount to swap: Must be a string representing the amount in ether (only number without coin symbol, e.g., \"0.1\")\n- Chain from chain to execute on swap\n- Slippage percentage value in numbers: default is 0.5\n\nRespond with a JSON markdown block containing only the extracted values. \nIf any field is not provided, use the default value. If no default value is specified, use null.\n \n\\`\\`\\`json\n{   \n    \"inputTokenSymbol\": string,\n    \"outputTokenSymbol\": string,\n    \"amount\": string,\n    \"chain\": \"ethereum\" | \"bsc\" | \"polygon\" | \"optimism\" | \"base\" | \"mode\" | \"zora\" | \"aurora\" | \"gnosis\" | \"mantle\" | \"avalanche\" | \"linea\" | \"blast\" | \"scroll\" | \"arbitrum\" | \"zksync era\" | \"polygon zkevm\" | \"moonriver\" | \"moonbeam\" | \"boba\" | \"fantom\" | \"metis\" | \"sei\" | \"taiko\" | \"fraxtal\" | \"celo\" | \"rootstock\" | \"gravity\" | \"klatyn\" | \"cronos\" | \"world chain\" | \"ink\" | \"lisk\" | \"abstract\" | \"unichain\" | \"b3\" | \"berachain\" | \"nirvana\" | \"sagaevm\" | \"maria chain\";\n    \"slippage\": number\n}\n\\`\\`\\`\n`;\n\n```\n\n```\nimport {\n    composeContext,\n    elizaLogger,\n    type HandlerCallback,\n    ModelClass,\n    type IAgentRuntime,\n    type Memory,\n    type State,\n    generateObjectDeprecated,\n} from \"@elizaos/core\";\nimport {\n    decodeFunctionData,\n    erc20Abi,\n    formatUnits,\n    parseUnits,\n    zeroAddress,\n    type Hex,\n} from \"viem\";\n\nimport {\n    evmWalletProvider,\n    initWalletProvider,\n    type WalletProvider,\n} from \"../providers/evmWallet\";\n\nimport { swapTemplate } from \"../templates\";\nimport { QuotePayload, RoutePayload, SupportedChain, SwapParams, SwapResponse } from \"../types\";\nimport { PonderAPIProvider } from \"../providers/ponder\";\nimport { swapExamplesSingleToken } from \"../utils/examples\";\nexport { swapTemplate };\n\nexport class SwapAction {\n    constructor(private walletProvider: WalletProvider) {}\n\n    async swapSingle(params: SwapParams): Promise<SwapResponse | string> {\n        elizaLogger.info(\"Single swap params same chain:\", params);\n        const fromAddress = this.walletProvider.getAddress();\n\n        const requiredFields = await this.checkRequiredParams(params);\n\n        if (requiredFields.length > 0) {\n            return requiredFields;\n        }\n\n        const requiredParams = await this.validateParams(params)\n\n        if (requiredParams.length > 0) {\n            return requiredParams;\n        }\n\n        const ponderProvider = new PonderAPIProvider();\n        const chains = await ponderProvider.getChains();\n\n        const blockExplorer = chains.find((chain) => chain.name.toLowerCase() === params.chain.toLowerCase())?.blockExplorer;\n\n        const inputChainId = String(await ponderProvider.getChainId(params.chain, chains));\n        const outputChainId = String(await ponderProvider.getChainId(params.chain, chains));\n\n        const resp: SwapResponse = {\n           fromChain: params.chain as SupportedChain,\n           toChain: params.chain as SupportedChain,\n           fromTokenSymbol: params.inputTokenSymbol,\n           toTokenSymbol: params.outputTokenSymbol,\n           fromToken: params.inputToken,\n           toToken: params.outputToken,\n           txHash: blockExplorer + \"tx/\",\n           recipient:fromAddress,\n           fromAmount: params.amount,\n           toAmount: \"\"\n        }\n\n        const publicClient = this.walletProvider.getPublicClient(\n            params.chain\n        );\n\n        let decimals;\n\n        if (params.inputToken === zeroAddress) {\n            decimals = 18;\n        } else {\n            decimals = await publicClient.readContract({\n                address: params.inputToken as `0x${string}`,\n                abi: erc20Abi,\n                functionName: \"decimals\",\n            });\n        }\n\n        params.amount = parseUnits(params.amount, decimals).toString();\n        \n        this.walletProvider.switchChain(params.chain);\n\n        const quotePayload: QuotePayload = {\n            fromChain: inputChainId,\n            toChain: outputChainId,\n            fromToken: [params.inputToken],\n            toToken: [params.outputToken],\n            fromAmount: [params.amount],\n            slippage: 0.5, //TODO: slippage fix now returning \"null\" in string form\n            fromAddress: fromAddress,\n            toAddress: fromAddress,\n            provider: \"\"\n        }\n\n        const quote = await ponderProvider.getQuote(quotePayload);\n        \n        if (!quote) {\n            throw new Error(\"No quote found for the given input\");\n        }\n\n        const routePayload: RoutePayload = {\n            fromChain: inputChainId,\n            toChain: outputChainId,\n            fromToken: [params.inputToken],\n            toToken: [params.outputToken],\n            fromAmount: [params.amount],\n            slippage: params.slippage,\n            fromAddress: fromAddress,\n            provider: quote.protocol,\n            routeId: quote.routeId\n        }\n\n        let route = await ponderProvider.getRoute(routePayload);\n\n        if (!route) {\n            throw new Error(\"No route found for the given quote\");\n        }\n\n        if (route.approvalTx) {\n            const approveAmount = BigInt(params.amount)\n            const token = await this.walletProvider.formatAddress(params.inputToken)\n\n            const { args } = decodeFunctionData({\n                abi: erc20Abi,\n                data: route.approvalTx[0].data\n              })\n\n            const spender = await this.walletProvider.formatAddress(args[0] as string)\n\n            const allowance = await this.walletProvider.checkERC20Allowance(\n                params.chain,\n                token,\n                fromAddress,\n                spender\n            );\n            if (allowance < approveAmount) {\n                elizaLogger.info(\n                    `Increasing ERC20 token ${params.inputTokenSymbol} allowance for ${route.protocol}. ${approveAmount - allowance} more needed`\n                );\n                const txHash = await this.walletProvider.approveERC20(\n                    params.chain,\n                    token,\n                    spender,\n                    approveAmount\n                );\n                await publicClient.waitForTransactionReceipt({\n                    hash: txHash,\n                });\n\n                elizaLogger.info(`successfully approved ${params.inputTokenSymbol} for swap`);\n            }\n        }\n\n        route = await ponderProvider.getRoute(routePayload);\n\n        if (!route.executionTx) {\n            throw new Error(\"No execution data found for the given route\");\n        }\n\n        const options: { gas?: bigint; gasPrice?: bigint; data?: Hex } = {}\n        \n        options.gas = BigInt(route.executionTx.gasLimit);\n        options.gasPrice = BigInt(route.executionTx.gasPrice);\n        options.data = route.executionTx.data;\n\n        const txHash = await this.walletProvider.swapToken(params.chain, route.executionTx.to, BigInt(route.executionTx.value), options)\n\n        if (!txHash || txHash === \"0x\") {\n            throw new Error(\"Get transaction hash failed\");\n        }\n\n        // wait for the transaction to be confirmed\n        await publicClient.waitForTransactionReceipt({\n            hash: txHash,\n        });\n\n        const toAmount = formatUnits(quote.transactionDetails[0].toToken[0].toAmount,  quote.transactionDetails[0].toToken[0].decimals);\n\n        resp.toAmount = toAmount.toString(); \n        resp.txHash = resp.txHash + txHash;\n\n        return resp;\n\n    }\n\n    async checkRequiredParams(params: SwapParams): Promise<string> {\n\n        let requiredFieldsText = \"\";\n\n        if (!params.inputTokenSymbol) {\n            requiredFieldsText += `- inputTokenSymbol: Symbol of the input token, like ETH\\n`\n        }\n\n        if (!params.outputTokenSymbol) {\n            requiredFieldsText += `- outputTokenSymbol: Symbol of the output token, like USDT\\n`\n        }\n\n        if (!params.inputToken) {\n            requiredFieldsText += `- inputToken: Address of the input token\\n`\n        }\n\n        if (!params.outputToken) {\n            requiredFieldsText += `- outputToken: Address of the output token\\n`\n        }\n\n        if (!params.amount) {\n            requiredFieldsText += `- amount: Amount of input token to swap\\n`\n        }\n\n        if (!params.chain) {\n            requiredFieldsText += `- chain: Chain to swap on\\n`\n        }\n\n        return requiredFieldsText;\n\n    }\n\n    async validateParams(params: SwapParams): Promise<string> {\n\n        let notValidParamsText = \"\"; \n\n        const nativeToken = this.walletProvider.chains[params.chain].nativeCurrency.symbol;\n\n        if (params.inputTokenSymbol.toLowerCase() === params.outputTokenSymbol.toLowerCase()) {\n            notValidParamsText = 'Cannot Swap Same Token, symbols are same'\n            return notValidParamsText;\n        }\n\n        if (params.inputTokenSymbol.toLowerCase() !== nativeToken.toLowerCase() && params.inputToken.toLowerCase() === zeroAddress) {\n            notValidParamsText = `- inputToken: Address of the input token\\n`\n            return notValidParamsText;\n        }\n\n        if (params.outputTokenSymbol.toLowerCase() !== nativeToken.toLowerCase() && params.outputToken.toLowerCase() === zeroAddress) {\n            notValidParamsText = `- outputToken: Address of the output token\\n`\n            return notValidParamsText;\n        }\n\n        return notValidParamsText;\n\n    }\n}\n\nexport const swapSingleAction = {\n    name: \"SWAP_SINGLE\",\n    description: \"Use this action when user swap from evm chain to evm chain, from chain and to chain should not be solana or movement chain.\",\n    handler: async (\n        runtime: IAgentRuntime,\n        message: Memory,\n        state: State,\n        _options: Record<string, unknown>,\n        callback?: HandlerCallback\n    ) => {\n        elizaLogger.info(\"Starting swap action...\");\n\n        if (message.content.source === \"direct\") {\n            // continue\n        } else {\n            callback?.({\n                text: \"i can't do that for you.\",\n                content: { error: \"Swap single not allowed\" },\n            });\n            return false;\n        }\n\n        \n        // Initialize or update state\n        let currentState = state;\n        if (!currentState) {\n            currentState = (await runtime.composeState(message)) as State;\n        } else {\n            currentState = await runtime.updateRecentMessageState(currentState);\n        }\n        state.walletInfo = await evmWalletProvider.get(\n            runtime,\n            message,\n            currentState\n        );\n\n        // Compose swap context\n        const swapContext = composeContext({\n            state: currentState,\n            template: swapTemplate,\n        });\n        const content = await generateObjectDeprecated({\n            runtime,\n            context: swapContext,\n            modelClass: ModelClass.LARGE,\n        });\n\n        elizaLogger.debug(\"Swap evm single token on same chain content:\", content);\n\n        const slippage = (!content?.slippage || content.slippage === null || content.slippage === \"null\") ? 0.5 : Number(content.slippage);\n\n        const walletProvider = initWalletProvider(runtime);\n        const action = new SwapAction(walletProvider);\n        const swapParams: SwapParams = {\n            inputTokenSymbol: content.inputTokenSymbol,\n            outputTokenSymbol: content.outputTokenSymbol,\n            inputToken: content.inputToken,\n            outputToken: content.outputToken,\n            amount: content.amount,\n            chain: content.chain,\n            slippage: slippage,\n        };\n        try {\n            const swapResp = await action.swapSingle(swapParams);\n\n            if (typeof swapResp === \"string\") {\n                callback?.({\n                    text: `You are trying to do token swap on same evm chain, but following fields are missing or not correct:\\n${swapResp}`,\n                    content: { error: swapResp }\n                });\n                return false;\n            }\n\n            callback?.({\n                text: `Successfully swapped ${swapResp.fromAmount} ${swapResp.fromTokenSymbol} to ${swapResp.toAmount} ${swapResp.toTokenSymbol} to receipent address ${swapResp.recipient} on ${swapResp.toChain} chain\\nTransaction Hash: ${swapResp.txHash}`,\n                content: { ...swapResp },\n            });\n\n            return true;\n        } catch (error) {\n            elizaLogger.error(\"Error during single token swap:\", error.message);\n            callback?.({\n                text: `Swap failed: ${error.message}`,\n                content: { error: error.message }\n            });\n            return false;\n        }\n    },\n    template: swapTemplate,\n    \n    validate: async (runtime: IAgentRuntime) => {\n        const privateKey = runtime.getSetting(\"WALLET_PRIVATE_KEY\");\n        return typeof privateKey === \"string\" && privateKey.startsWith(\"0x\");\n    },\n    examples: swapExamplesSingleToken,\n    similes: [\"SWAP\", \"TOKEN_SWAP\", \"SWAP_TOKEN\", \"SWAP_FUND\", \"CONVERT\", \"EXCHANGE_TOKEN\", \"TOKEN_CONVERSION\"]\n\n};\n\n\n```",
      "createdAt": "2025-04-16T10:37:20Z",
      "closedAt": "2025-05-23T02:28:26Z",
      "state": "CLOSED",
      "commentCount": 1
    },
    {
      "id": "I_kwDOMT5cIs60vfHb",
      "title": "RAG document Knowledge error (getCachedEmbeddings)",
      "author": "retdude",
      "number": 4408,
      "repository": "elizaos/eliza",
      "body": "**Describe the bug**\n\nThe application encounters multiple errors during knowledge processing:\n1. Circuit breaker errors causing knowledge processing failures\n2. UTF-8 encoding issues with PDF files\n3. Database operation failures due to invalid byte sequences\n\nThe errors occur during the initialization phase when processing character knowledge, particularly when handling PDF files and text content.\n\n\n**To Reproduce**\n\n1. Put PDF knowledge in 'eliza/characters/knowledge/<your agent>'\n2. Set ragKnowledge to 'true' in your character file.\n3. Edit your character file to add the knowlege like so:\n```\n \"knowledge\": [\n    {\n      \"directory\": \"tech_guides\",\n      \"shared\": true\n    }\n  ], \n```\n4. Start the application using `pnpm start`\n5. The errors appear during the knowledge processing phase\n6. Specific errors include:\n   - \"invalid byte sequence for encoding \"UTF8\": 0x00\"\n   - \"Circuit breaker is OPEN\"\n   - \"unsupported Unicode escape sequence\"\n\n\n**Expected behavior**\n\n- PDF files should be properly processed without encoding errors\n- Knowledge processing should complete successfully\n- Circuit breaker should handle failures gracefully without blocking all operations\n\n\n**Screenshots**\n<img width=\"952\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/39d789b4-3fee-4a0e-b078-044101051388\" />\n\n<img width=\"1087\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/50b881b0-b3f0-43f4-8500-16f947e333fb\" />\n\n<img width=\"1097\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/90bed2aa-23db-4c89-95fe-44bb5459a0ff\" />\n\n<img width=\"1095\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/6c4db528-f2d2-40b7-9f15-96b1144303ac\" />\n\n**Additional context**\n\n-Using PGVector for RAG\n- Environment: macOS 23.6.0\n- The errors occur during the RAG (Retrieval-Augmented Generation) knowledge processing phase\n- The circuit breaker appears to be tripping due to database operation failures\n\n",
      "createdAt": "2025-04-30T19:53:01Z",
      "closedAt": "2025-05-23T02:30:04Z",
      "state": "CLOSED",
      "commentCount": 1
    }
  ],
  "topPRs": [
    {
      "id": "PR_kwDOMT5cIs6R1jEI",
      "title": "resolved hapi shot error.",
      "author": "nitzansaar",
      "number": 4232,
      "body": "can build an run eliza chatbot only\r\n\r\n<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review and merge. -->\r\n\r\n# Risks\r\n\r\n<!--\r\nLow, medium, large. List what kind of risks and what could be affected.\r\n-->\r\n\r\n# Background\r\n\r\n## What does this PR do?\r\n\r\n## What kind of change is this?\r\n\r\n<!--\r\nBug fixes (non-breaking change which fixes an issue)\r\nImprovements (misc. changes to existing features)\r\nFeatures (non-breaking change which adds functionality)\r\nUpdates (new versions of included code)\r\n-->\r\n\r\n<!-- This \"Why\" section is most relevant if there are no linked issues explaining why. If there is a related issue, it might make sense to skip this why section. -->\r\n<!--\r\n## Why are we doing this? Any context or related work?\r\n-->\r\n\r\n# Documentation changes needed?\r\n\r\n<!--\r\nMy changes do not require a change to the project documentation.\r\nMy changes require a change to the project documentation.\r\nIf documentation change is needed: I have updated the documentation accordingly.\r\n-->\r\n\r\n<!-- Please show how you tested the PR. This will really help if the PR needs to be retested and probably help the PR get merged quicker. -->\r\n\r\n# Testing\r\n\r\n## Where should a reviewer start?\r\n\r\n## Detailed testing steps\r\n\r\n<!--\r\nNone: Automated tests are acceptable.\r\n-->\r\n\r\n<!--\r\n- As [anon/admin], go to [link]\r\n  - [do action]\r\n  - verify [result]\r\n-->\r\n\r\n<!-- If there is a UI change, please include before and after screenshots or videos. This will speed up PRs being merged. It is extra nice to annotate screenshots with arrows or boxes pointing out the differences. -->\r\n<!--\r\n## Screenshots\r\n### Before\r\n### After\r\n-->\r\n\r\n<!-- If there is anything about the deployment, please make a note. -->\r\n<!--\r\n# Deploy Notes\r\n-->\r\n\r\n<!--  Copy and paste command line output. -->\r\n<!--\r\n## Database changes\r\n-->\r\n\r\n<!--  Please specify deploy instructions if there is something more than the automated steps. -->\r\n<!--\r\n## Deployment instructions\r\n-->\r\n\r\n<!-- If you are on Discord, please join https://discord.gg/elizaOS and state your Discord username here for the contributor role and join us in #development-feed -->\r\n<!--\r\n## Discord username\r\n\r\n-->\r\n",
      "repository": "elizaos/eliza",
      "createdAt": "2025-04-08T19:00:40Z",
      "mergedAt": null,
      "additions": 54046,
      "deletions": 3338
    },
    {
      "id": "PR_kwDOMT5cIs6Wk-z3",
      "title": "V2 Spartan",
      "author": "lalalune",
      "number": 4630,
      "body": "V2 Spartan Changes (WIP)",
      "repository": "elizaos/eliza",
      "createdAt": "2025-05-17T19:07:00Z",
      "mergedAt": null,
      "additions": 23639,
      "deletions": 5547
    },
    {
      "id": "PR_kwDOMT5cIs6Wh29n",
      "title": "feat: add plugin-rag",
      "author": "0xbbjoker",
      "number": 4614,
      "body": "\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n- **New Features**\n  - Introduced a Retrieval-Augmented Generation (RAG) plugin, enabling advanced document ingestion and retrieval capabilities.\n  - Added support for uploading and processing various document types, including PDFs and DOCX, with asynchronous handling and per-file status reporting.\n  - Integrated AI-powered text embedding and completion features using OpenAI and Anthropic models.\n\n- **Bug Fixes**\n  - Improved handling of nullable fields in agent and task data to ensure consistent string values.\n\n- **Documentation**\n  - Added comprehensive documentation for the RAG plugin, including usage instructions, image requirements, and publishing guidelines.\n\n- **Chores**\n  - Updated dependencies and configuration files to support the new plugin.\n  - Enhanced logging and error reporting for document processing and plugin operations.\n\n<!-- end of auto-generated comment: release notes by coderabbit.ai -->",
      "repository": "elizaos/eliza",
      "createdAt": "2025-05-16T23:32:49Z",
      "mergedAt": "2025-05-23T00:52:11Z",
      "additions": 4420,
      "deletions": 750
    },
    {
      "id": "PR_kwDOMT5cIs6XK_-J",
      "title": "feat: Knowledge Plugin",
      "author": "lalalune",
      "number": 4701,
      "body": "This PR moves the code for knowledge into the RAG plugin and renames that to the knowledge plugin\r\n\r\nSo now the agent will be able to process knowledge optionally with the plugin installed, completely removing it from the runtime",
      "repository": "elizaos/eliza",
      "createdAt": "2025-05-22T07:09:22Z",
      "mergedAt": "2025-05-23T00:52:11Z",
      "additions": 3873,
      "deletions": 1357
    },
    {
      "id": "PR_kwDOMT5cIs6XY5J-",
      "title": "Updated polygon plugin",
      "author": "Samarthsinghal28",
      "number": 4745,
      "body": "<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review and merge. -->\r\n\r\n# Risks\r\n\r\n<!--\r\nLow, medium, large. List what kind of risks and what could be affected.\r\n-->\r\n\r\n# Background\r\n\r\n## What does this PR do?\r\n\r\n## What kind of change is this?\r\n\r\n<!--\r\nBug fixes (non-breaking change which fixes an issue)\r\nImprovements (misc. changes to existing features)\r\nFeatures (non-breaking change which adds functionality)\r\nUpdates (new versions of included code)\r\n-->\r\n\r\n<!-- This \"Why\" section is most relevant if there are no linked issues explaining why. If there is a related issue, it might make sense to skip this why section. -->\r\n<!--\r\n## Why are we doing this? Any context or related work?\r\n-->\r\n\r\n# Documentation changes needed?\r\n\r\n<!--\r\nMy changes do not require a change to the project documentation.\r\nMy changes require a change to the project documentation.\r\nIf documentation change is needed: I have updated the documentation accordingly.\r\n-->\r\n\r\n<!-- Please show how you tested the PR. This will really help if the PR needs to be retested and probably help the PR get merged quicker. -->\r\n\r\n# Testing\r\n\r\n## Where should a reviewer start?\r\n\r\n## Detailed testing steps\r\n\r\n<!--\r\nNone: Automated tests are acceptable.\r\n-->\r\n\r\n<!--\r\n- As [anon/admin], go to [link]\r\n  - [do action]\r\n  - verify [result]\r\n-->\r\n\r\n<!-- If there is a UI change, please include before and after screenshots or videos. This will speed up PRs being merged. It is extra nice to annotate screenshots with arrows or boxes pointing out the differences. -->\r\n<!--\r\n## Screenshots\r\n### Before\r\n### After\r\n-->\r\n\r\n<!-- If there is anything about the deployment, please make a note. -->\r\n<!--\r\n# Deploy Notes\r\n-->\r\n\r\n<!--  Copy and paste command line output. -->\r\n<!--\r\n## Database changes\r\n-->\r\n\r\n<!--  Please specify deploy instructions if there is something more than the automated steps. -->\r\n<!--\r\n## Deployment instructions\r\n-->\r\n\r\n<!-- If you are on Discord, please join https://discord.gg/elizaOS and state your Discord username here for the contributor role and join us in #development-feed -->\r\n<!--\r\n## Discord username\r\n\r\n-->\r\n",
      "repository": "elizaos/eliza",
      "createdAt": "2025-05-23T13:32:31Z",
      "mergedAt": "2025-05-24T20:46:39Z",
      "additions": 3850,
      "deletions": 1642
    }
  ],
  "codeChanges": {
    "additions": 16854,
    "deletions": 5862,
    "files": 99,
    "commitCount": 71
  },
  "completedItems": [
    {
      "title": "feat: improve db api",
      "prNumber": 4556,
      "type": "feature",
      "body": "# Risks\r\n\r\nLow\r\n\r\n# Background\r\n\r\n## What does this PR do?\r\n\r\n- getEntityById becomes getEntitesByIds (runtime still has a getEntityById helper/wrapper)\r\n- getRoom becomes getRoomsByIds (runtime still has a getRoom helper/wrapper)\r\n- batch "
    },
    {
      "title": "chore(deps): bump undici from 7.4.0 to 7.5.0 in the npm_and_yarn group across 1 directory",
      "prNumber": 4598,
      "type": "other",
      "body": "Bumps the npm_and_yarn group with 1 update in the / directory: [undici](https://github.com/nodejs/undici).\n\nUpdates `undici` from 7.4.0 to 7.5.0\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/node"
    },
    {
      "title": "feat: add support for PDF rag",
      "prNumber": 4611,
      "type": "feature",
      "body": "\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n- **New Features**\n  - Added support for extracting and uploading text content from PDF files, enabling users to upload PDFs as knowledg"
    },
    {
      "title": "feat: add plugin-rag",
      "prNumber": 4614,
      "type": "feature",
      "body": "\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n- **New Features**\n  - Introduced a Retrieval-Augmented Generation (RAG) plugin, enabling advanced document ingestion and retrieval capa"
    },
    {
      "title": "Add file TRANSLATION",
      "prNumber": 4704,
      "type": "feature",
      "body": "<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review "
    },
    {
      "title": "Delete README_IDN.md",
      "prNumber": 4702,
      "type": "other",
      "body": "the file is already there\r\n\r\n(i18n/readme/README_IND.md)\r\n\r\n<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- Th"
    },
    {
      "title": "feat: Knowledge Plugin",
      "prNumber": 4701,
      "type": "feature",
      "body": "This PR moves the code for knowledge into the RAG plugin and renames that to the knowledge plugin\r\n\r\nSo now the agent will be able to process knowledge optionally with the plugin installed, completely removing it from the runtime"
    },
    {
      "title": "fix: use findNearestEnvFile(), etc to lookup github creds, before was…",
      "prNumber": 4700,
      "type": "bugfix",
      "body": "elizaos publish -t was failing with:\r\n\r\n✔ Enter your GitHub username: … yungalgo\r\n✔ Enter your GitHub Personal Access Token (with repo, read:org, and workflow scopes): … ****************************************\r\n[2025-05-22 03:52:59] WARN: "
    },
    {
      "title": "fix: env files, .73 release",
      "prNumber": 4751,
      "type": "bugfix",
      "body": ""
    },
    {
      "title": "chore: improve message handler template",
      "prNumber": 4748,
      "type": "other",
      "body": "\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n- **New Features**\n  - Enhanced provider selection rules for message handling, ensuring more accurate responses based on message content"
    },
    {
      "title": "unpeg CLI plugin / core deps, version .71 deploy CLI",
      "prNumber": 4747,
      "type": "other",
      "body": ""
    },
    {
      "title": "fix: make starter low prior",
      "prNumber": 4743,
      "type": "bugfix",
      "body": "\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n- **New Features**\n  - Updated plugin behavior to ensure it is given lower priority compared to other plugins.\n\n<!-- end of auto-generat"
    },
    {
      "title": "chore: update twitter setup blog",
      "prNumber": 4742,
      "type": "other",
      "body": "Update Twitter agent blog post."
    },
    {
      "title": "fix: postgres bypass + double init of server",
      "prNumber": 4741,
      "type": "bugfix",
      "body": ""
    },
    {
      "title": "fix: remove unused PDF.js imports causing CLI DOMMatrix runtime error",
      "prNumber": 4740,
      "type": "bugfix",
      "body": "**## Problem**\r\nCLI commands fail with `ReferenceError: Can't find variable: DOMMatrix` when running in environments without DOM support (like Node.js/Bun).\r\n\r\n**## Root Cause**  \r\n`packages/core/src/utils.ts` imports `pdfjs-dist` at the to"
    },
    {
      "title": "Add supplemental unit tests for core utilities",
      "prNumber": 4739,
      "type": "feature",
      "body": "## Summary\n- add utility tests verifying template upgrades, header addition, random name replacement, XML parsing, circular reference handling, and UUID validation\n- implement settings tests covering encryption/decryption and value salting "
    },
    {
      "title": "Fix Build Error: Missing findNearestEnvFile Import",
      "prNumber": 4732,
      "type": "bugfix",
      "body": "**Problem**\r\n\r\n- CLI build was failing with missing import error\r\n- `packages/cli/src/utils/registry/index.ts` was importing `findNearestEnvFile` which doesn't exist\r\n- Error: `No matching export in \"src/utils/index.ts\" for import \"findNear"
    },
    {
      "title": "feat: enhance plugin publishing with NPM authentication and validation",
      "prNumber": 4731,
      "type": "feature",
      "body": "**Key Features Added**\r\n\r\n1. NPM Authentication Integration (getNpmUsername())\r\n- Added required NPM authentication for registry compliance\r\n- Interactive prompts to use existing NPM login or switch accounts\r\n- Automatic fallback to npm log"
    },
    {
      "title": "refactor: simplify template path resolution in copy-template.ts",
      "prNumber": 4730,
      "type": "refactor",
      "body": "**Summary of changes:**\r\n\r\nRemoved UserEnvironment dependency - eliminated import and usage of UserEnvironment.getInstance()\r\nSimplified development mode logic - removed complex monorepo root detection and fallback logic\r\nStreamlined templa"
    },
    {
      "title": "update name handling in publisher.ts so it doesnt expect \"elizaos\" anymore",
      "prNumber": 4729,
      "type": "other",
      "body": "**Problem:**\r\n\r\npublisher.ts was hardcoded to only handle @elizaos/ scoped packages, but it needed to work with any npm scope (like @yungalgo/, @username/, etc.).\r\n\r\n**Specific Changes Made:**\r\n\r\nRepository Name Extraction (Line ~298)\r\nTest"
    },
    {
      "title": "fix: Fix response handling",
      "prNumber": 4728,
      "type": "bugfix",
      "body": "This PR fixes response handling, which is not working\r\n\r\nSo the agent actually responds and the message is correctly parsed without errors"
    },
    {
      "title": "update plugin prefix check/add function to also validate \"plugin-alpanumeric\" naming conv",
      "prNumber": 4727,
      "type": "feature",
      "body": "this is a small pr to change a codeblock that checks for \"plugin-\" prefix and adds it if its not there. i am also adding some alphanumeric validation to the part that comes after \"plugin-\" so it's like this:\r\n\r\nallowed:\r\nplugin-abc\r\nplugic-"
    },
    {
      "title": "chore: Update opentelemetry version and API usage",
      "prNumber": 4726,
      "type": "other",
      "body": "This PR updates the telemetry stack to consistent versions, since we were having some deprecation and version mismatch issues"
    },
    {
      "title": "Fix/linter issues and tests",
      "prNumber": 4725,
      "type": "bugfix",
      "body": ""
    },
    {
      "title": "fix: revert project starter character",
      "prNumber": 4724,
      "type": "bugfix",
      "body": ""
    },
    {
      "title": "fix: add libvips-dev to integration test CI",
      "prNumber": 4723,
      "type": "feature",
      "body": "fixes integration CI complaining in bun install because of Sharp deps"
    },
    {
      "title": "feat: write .env example, cleanup get-config functions",
      "prNumber": 4721,
      "type": "feature",
      "body": "`.env` file is empty on creation, this writes example envs for users to config better.\n\nAlso cleans up some functions and improves type safety and file handling."
    },
    {
      "title": "Factor Knowledge Out to Plugin and Add Service Registry Types",
      "prNumber": 4719,
      "type": "feature",
      "body": "This PR moves all knowledge functionality out of the runtime and into the plugin-knowledge\r\n\r\nIn additional, adds a service registry pattern so that external plugins can have typed Services referenced elsewhere"
    }
  ],
  "topContributors": [
    {
      "username": "lalalune",
      "avatarUrl": "https://avatars.githubusercontent.com/u/18633264?u=e2e906c3712c2506ebfa98df01c2cfdc50050b30&v=4",
      "totalScore": 215.17379079423236,
      "prScore": 212.73579079423237,
      "issueScore": 2,
      "reviewScore": 0,
      "commentScore": 0.43799999999999994,
      "summary": null
    },
    {
      "username": "yungalgo",
      "avatarUrl": "https://avatars.githubusercontent.com/u/113615973?u=92e0f29f7e2fbb8ce46ed13c51f692ca803de02d&v=4",
      "totalScore": 185.46570602040174,
      "prScore": 185.46570602040174,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": null
    },
    {
      "username": "ChristopherTrimboli",
      "avatarUrl": "https://avatars.githubusercontent.com/u/27584221?u=0d816ce1dcdea8f925aba18bb710153d4a87a719&v=4",
      "totalScore": 150.22846683233692,
      "prScore": 145.22846683233692,
      "issueScore": 0,
      "reviewScore": 5,
      "commentScore": 0,
      "summary": null
    },
    {
      "username": "0xbbjoker",
      "avatarUrl": "https://avatars.githubusercontent.com/u/54844437?u=90fe1762420de6ad493a1c1582f1f70c0d87d8e2&v=4",
      "totalScore": 132.96837765642732,
      "prScore": 132.62837765642732,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.33999999999999997,
      "summary": null
    },
    {
      "username": "wtfsayo",
      "avatarUrl": "https://avatars.githubusercontent.com/u/82053242?u=98209a1f10456f42d4d2fa71db4d5bf4a672cbc3&v=4",
      "totalScore": 78.14731797392504,
      "prScore": 77.70931797392504,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.43799999999999994,
      "summary": null
    },
    {
      "username": "Samarthsinghal28",
      "avatarUrl": "https://avatars.githubusercontent.com/u/120447590?v=4",
      "totalScore": 40.4317738965761,
      "prScore": 40.4317738965761,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": null
    },
    {
      "username": "samarth30",
      "avatarUrl": "https://avatars.githubusercontent.com/u/48334430?u=1fc119a6c2deb8cf60448b4c8961cb21dc69baeb&v=4",
      "totalScore": 17.83887795833288,
      "prScore": 17.83887795833288,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": null
    },
    {
      "username": "monilpat",
      "avatarUrl": "https://avatars.githubusercontent.com/u/15067321?v=4",
      "totalScore": 6,
      "prScore": 0,
      "issueScore": 0,
      "reviewScore": 6,
      "commentScore": 0,
      "summary": null
    },
    {
      "username": "Icarus-Community",
      "avatarUrl": "https://avatars.githubusercontent.com/u/174098848?u=e1b5a7fe3b0a3bda521bb26fc2e5bc3fa21393c2&v=4",
      "totalScore": 2.2,
      "prScore": 0,
      "issueScore": 2,
      "reviewScore": 0,
      "commentScore": 0.2,
      "summary": null
    }
  ],
  "newPRs": 30,
  "mergedPRs": 28,
  "newIssues": 2,
  "closedIssues": 9,
  "activeContributors": 17
}