diff --git a/.gitignore b/.gitignore index 5c84119..73bf4af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ dist/ node_modules/ -.env \ No newline at end of file +.env +*.env +elizadb +elizaos +elizaos.db +elizaos.db-journal +elizaos.db-shm +elizaos.db-wal +.windsurf/rules/ +.qodo/ \ No newline at end of file diff --git a/.windsurf/rules/polymarket-plugin.md b/.windsurf/rules/polymarket-plugin.md new file mode 100644 index 0000000..28465c2 --- /dev/null +++ b/.windsurf/rules/polymarket-plugin.md @@ -0,0 +1,119 @@ +--- +trigger: manual +--- + +**3.1 Required Functionalities** + +The plugin must support the following core interactions with Polymarket: + +1. **Read Markets:** Fetch lists of available markets, retrieve details for specific markets (e.g., question, resolution criteria, current odds/prices, volume, liquidity, status). +2. **Buy Shares:** Place orders to purchase shares representing a specific outcome of a market. This requires specifying the market, outcome, quantity, and price (or placing a market order). +3. **Sell Shares:** Place orders to sell previously acquired shares. Similar parameters to buying are required. +4. **Redeem Winnings:** Claim payouts for shares held in markets that have resolved favorably. +5. **(Optional) Read Portfolio/Balances:** Fetch the agent's current positions, open orders, and available balance on Polymarket. + +## **4\. Plugin Specification: Polymarket Plugin for ElizaOS** + +This section details the proposed design for the @elizaos-plugins/plugin-polymarket. + +**4.1 Plugin Name** + +The standard naming convention suggests: @elizaos-plugins/plugin-polymarket + +**4.2 Core Components** + +* **Actions:** These define the capabilities the agent can perform based on natural language commands. Each action includes a name, description, example interactions (examples), validation logic (validate), and the core execution logic (handler).5 Similes (similes) allow the agent to recognize variations in user requests.11 + * **Table 1: Core Plugin Actions** + +| Action Name | Similes | Description | Input Parameters (Example) | Output (Example) | +| :---- | :---- | :---- | :---- | :---- | +| POLYMARKET\_READ\_MARKET | find market, get market info, lookup market | Retrieves details about a specific Polymarket market or searches for markets. | market\_id or search\_query | Market details (question, outcomes, prices, etc.) | +| POLYMARKET\_BUY\_SHARES | buy, invest in, purchase shares | Places an order to buy shares for a specific outcome in a market. | market\_id, outcome, amount, price | Confirmation message, Order ID | +| POLYMARKET\_SELL\_SHARES | sell, divest, close position | Places an order to sell shares held for a specific outcome in a market. | market\_id, outcome, amount, price | Confirmation message, Order ID | +| POLYMARKET\_REDEEM\_WINNINGS | redeem, claim winnings, collect payout | Redeems winnings from resolved markets where the agent held winning shares. | market\_id (optional) | Confirmation of redemption, Amount redeemed | +| POLYMARKET\_GET\_PORTFOLIO (Opt) | portfolio, balance, positions | Retrieves the agent's current balance, open orders, and positions. | None | Portfolio details | + +* **Services:** A dedicated service is recommended for managing interactions with the Polymarket APIs. + * PolymarketApiService: This class will encapsulate all HTTP requests (using libraries like axios or node-fetch) to the Polymarket CLOB and Gamma APIs. Its responsibilities include: + * Handling authentication (API key injection or transaction signing logic). + * Constructing API requests based on input parameters. + * Parsing API responses. + * Implementing error handling and potentially rate limit management. + * Loading configuration (API endpoints, keys) during initialization. +* **Providers:** A provider can optionally be implemented to proactively fetch and update the agent's state with relevant Polymarket data. + * PolymarketPortfolioProvider (Optional): This provider could periodically poll the Polymarket API (using PolymarketApiService) to fetch the agent's current balance and positions, making this information readily available in the agent's context without requiring an explicit action.5 This helps keep the agent's understanding of its financial state more current but requires careful consideration of API rate limits. + +**4.3 Configuration** + +The plugin will require configuration parameters, managed via environment variables or character.json settings.5 + +* **Table 2: Configuration Parameters** + +| Parameter Name | Type | Location | Description | Required | Example Value | +| :---- | :---- | :---- | :---- | :---- | :---- | +| POLYMARKET\_API\_KEY | string | .env/Settings | API Key for accessing Polymarket APIs (if using key-based auth). | Maybe | pk\_live\_xxxxxxxxxxxxxxxx | +| POLYMARKET\_API\_SECRET | string | .env/Settings | API Secret associated with the API Key (if applicable). | Maybe | sk\_live\_xxxxxxxxxxxxxxxx | +| POLYMARKET\_PRIVATE\_KEY | string | .env/Settings | User's private key for signing transactions (if required by API). **Handle with extreme care.** | Maybe | 0xabcde... | +| POLYMARKET\_NETWORK | string | .env/Settings | Target Polymarket environment ('mainnet' or 'testnet'). Defaults to 'mainnet'. | No | testnet | +| POLYMARKET\_CLOB\_API\_ENDPOINT | string | .env/Settings | Base URL for the Polymarket CLOB API. Defaults can be provided. | No | https://clob-api.polymarket.com/ | +| POLYMARKET\_GAMMA\_API\_ENDPOINT | string | .env/Settings | Base URL for the Polymarket Gamma API. Defaults can be provided. | No | https://gamma-api.polymarket.com/ | + +The decision of whether POLYMARKET\_API\_KEY/SECRET or POLYMARKET\_PRIVATE\_KEY is required depends entirely on the Polymarket API's authentication mechanism. Storing POLYMARKET\_PRIVATE\_KEY demands the highest level of security; using secure environment variable management outside of version control is strongly recommended.12 Placing user-specific keys in character.json settings allows different agents to use different Polymarket accounts. + +**4.4 Data Handling and Validation** + +* **TypeScript Types:** Define clear TypeScript interfaces or types for all Polymarket data structures (Market, Order, Position, Trade, API Responses) within the plugin (src/types/). +* **Input Validation:** Use a library like zod 11 within action handlers to validate incoming parameters (e.g., ensuring amount is a valid number, market\_id has the correct format) before sending requests to the PolymarketApiService. This prevents invalid API calls and provides immediate feedback for malformed requests. + +**4.5 Error Handling** + +* The PolymarketApiService should catch errors from API calls (network issues, HTTP status codes) and translate Polymarket-specific error responses into standardized errors. +* Action handlers should catch errors from the service and validation steps, formatting them into user-understandable messages for the agent to relay. Logging should capture detailed error information for debugging. + +This specification provides a blueprint for a modular and configurable plugin. The separation of API logic into a dedicated service enhances testability and maintainability. The explicit definition of actions and configuration parameters clarifies the plugin's capabilities and requirements. However, the significant uncertainty around the API authentication mechanism remains a key area requiring investigation once API documentation is available. + +## **5\. Proposed Project Structure** + +A well-organized project structure is essential for maintainability and aligns with conventions observed in the ElizaOS ecosystem.2 The following structure, based on the eliza-plugin-starter 8 and other existing plugins 7, is recommended for the @elizaos-plugins/plugin-polymarket: + +plugin-polymarket/ +├── src/ +│ ├── actions/ \# Implementation of plugin actions +│ │ ├── readMarket.ts +│ │ ├── buyShares.ts +│ │ ├── sellShares.ts +│ │ ├── redeemWinnings.ts +│ │ └── index.ts \# Exports all actions +│ ├── services/ \# Core service logic +│ │ └── polymarketApiService.ts +│ ├── providers/ \# Optional: Data providers +│ │ └── polymarketPortfolioProvider.ts +│ ├── types/ \# TypeScript interfaces and types +│ │ └── index.ts \# (or specific files like marketTypes.ts, orderTypes.ts) +│ ├── utils/ +│ │ └── index.ts \# (Helper functions, constants) +│ └── index.ts \# (Plugin entry point, exports actions, providers, services) +├── test/ \# Unit and integration tests +│ ├── actions/ +│ └── services/ +├── assets/ \# Branding assets for registry \[5\] +│ ├── logo.png \# (400x400px) +│ ├── banner.png \# (1280x640px) +│ └── screenshots/ +│ └── screenshot1.png \# Demo screenshot +├── characters/ \# Example character configuration +│ └── polymarket-agent.character.json.example +├──.env.example \# Example environment variables \[13\] +├── package.json \# Project metadata and dependencies +├── tsconfig.json \# TypeScript compiler options +├── README.md \# Plugin documentation +└──... \# (other config files like.gitignore,.prettierrc) + +**5.1 Key Module Definitions** + +* src/index.ts: The main entry point for the plugin. It exports the plugin definition object, including arrays of implemented actions, providers, and services, making them discoverable by the ElizaOS runtime. This follows patterns seen in examples like.10 +* src/actions/\*.ts: Each file implements a specific action, adhering to the Action interface (defining name, similes, description, validate, handler, examples).11 The handler function within each action will typically instantiate or utilize the PolymarketApiService to perform the required API calls. +* src/services/polymarketApiService.ts: Contains the PolymarketApiService class. This class is responsible for all communication with the Polymarket CLOB and Gamma APIs. It handles loading configuration (API keys/endpoints), building requests, managing authentication (API key headers or transaction signing), parsing responses, and handling API-level errors and rate limits. It will likely use an HTTP client library like axios or node-fetch. +* src/providers/\*.ts: If implemented, files here define Provider classes (e.g., PolymarketPortfolioProvider) that periodically fetch data using the PolymarketApiService and update the agent's state or context. +* src/types/index.ts: Centralizes all TypeScript interfaces and type definitions specific to Polymarket data (e.g., Market, Order, Position, API response structures). Using Zod schemas 16 for validation within these types can enhance robustness. +* src/utils/index.ts: Contains shared constants (e.g., default API endpoint URLs, error codes, configuration keys) and utility functions (e.g., data formatting, number precision handling). diff --git a/Polymarket Plugin Development Specification_.md b/Polymarket Plugin Development Specification_.md new file mode 100644 index 0000000..e2066dd --- /dev/null +++ b/Polymarket Plugin Development Specification_.md @@ -0,0 +1,356 @@ +# **Specification and Development Plan: ElizaOS Polymarket Plugin** + +## **1\. Introduction** + +This document outlines the specification, project structure, and development plan for creating a plugin for the ElizaOS AI agent framework. The primary goal of this plugin is to empower Eliza agents with the capability to interact with the Polymarket prediction market platform. Specifically, the plugin will enable agents to perform core functions such as reading market information, executing buy and sell orders for market shares, and redeeming winnings from resolved markets. + +ElizaOS is a TypeScript-based framework designed for building autonomous AI agents, featuring a robust plugin system for extending agent capabilities.1 Polymarket is a decentralized information markets platform where users trade on the outcomes of future events. Integrating Polymarket access into ElizaOS allows for the creation of agents capable of participating in prediction markets, potentially for automated trading strategies, information gathering, or other autonomous tasks.3 + +This specification assumes the availability and functionality of Polymarket's CLOB (Central Limit Order Book) and Gamma APIs as described in the initial request, providing endpoints for market data retrieval, order placement, and position management. The target audience for this document includes software developers involved in building or integrating ElizaOS plugins. + +## **2\. Understanding the ElizaOS Plugin Architecture** + +Developing a plugin for ElizaOS requires understanding its core architectural principles and development workflow. The framework is designed with extensibility in mind, treating nearly all functional components as plugins.5 + +**2.1 Core Concepts** + +* **Unified Plugin System:** ElizaOS employs a unified architecture where components like clients (e.g., Discord, Twitter integrations), adapters (e.g., database connectors), services (background processes), providers (data suppliers), evaluators (decision logic), and actions (agent capabilities) are all implemented as plugins.2 This ensures consistency and modularity. +* **Plugin Types:** A single plugin package can provide one or more of these component types.5 For the Polymarket plugin, the primary focus will be on implementing Actions (buy, sell, read, redeem) and potentially a Service (for API interaction) and a Provider (for portfolio updates). +* **TypeScript Foundation:** ElizaOS and its plugins are primarily developed using TypeScript, leveraging its strong typing and modern JavaScript features. Development requires Node.js (v23+ recommended) and pnpm (v9+ recommended).1 Git is used for version control.6 Windows users typically require WSL 2\.3 +* **Dependency Injection:** Some plugin templates and examples utilize dependency injection patterns (e.g., @elizaos-plugins/plugin-di), allowing for class-based implementation of components and facilitating testing.6 However, simpler object-based structures are also common.6 + +**2.2 Development Workflow** + +The standard workflow for creating an ElizaOS plugin generally involves the following steps: + +1. **Initialization:** Create a new plugin repository, often starting from the official eliza-plugin-starter template 8 or by adapting an existing plugin example.6 The starter template provides a basic structure, example implementations (e.g., search plugins), and scripts for local testing with a mocked client.8 +2. **Integration:** Add the plugin repository as a submodule or local workspace package to the main Eliza agent project.6 Update the agent's package.json to include the new plugin as a dependency, typically using a workspace:\* protocol.3 +3. **Building:** Compile the TypeScript code into JavaScript using pnpm build, often configured via tsup or tsc.6 +4. **Configuration:** Add the plugin's package name (e.g., @elizaos-plugins/plugin-polymarket) to the plugins array within the target agent's character.json file.5 Configure plugin-specific settings either via environment variables (.env) or within the settings object in character.json.1 +5. **Running & Testing:** Start the Eliza agent, ensuring it loads the new plugin. Interact with the agent using a client (like the 'direct' client for local testing or web/Discord clients) to test the plugin's functionality.3 + +**2.3 Configuration Mechanisms** + +Effective configuration is vital for plugin operation, especially when dealing with external APIs and sensitive credentials. + +* **package.json (agentConfig):** Plugins must define an agentConfig section in their package.json. This specifies the pluginType (e.g., "elizaos:plugin:1.0.0") and lists expected pluginParameters, including their type and description. These parameters often correspond to required environment variables or settings.5 +* **character.json:** This file defines an agent's personality, capabilities, and configuration. Plugins are enabled by adding their package name to the plugins array. User-specific or agent-specific settings, including secrets, can be provided within the settings object, keyed by the plugin name.1 +* **Environment Variables (.env):** A common pattern is to load configuration values, particularly secrets like API keys or private keys, from a .env file at the root of the agent project.1 Plugins can access these variables during initialization. Examples include API keys 12, private keys 10, and RPC URLs.1 + +The choice between .env and character.json for settings involves trade-offs. .env is suitable for instance-wide secrets shared by all agents running in that environment. character.json allows for agent-specific configurations, which is essential if different agents need distinct API keys or credentials.3 Storing sensitive data like private keys requires careful consideration, favoring secure environment variable management over embedding them directly in potentially version-controlled configuration files.12 + +This established architecture provides a flexible yet structured foundation for extending ElizaOS. Adhering to these conventions ensures better integration, maintainability, and compatibility within the ecosystem.2 The separation of concerns (actions, services, configuration) promotes modularity, making plugins easier to develop, test, and reuse.6 + +## **3\. Polymarket API Overview** + +Integration with Polymarket necessitates interaction with its Application Programming Interfaces (APIs). Based on the provided information, Polymarket offers at least two relevant APIs: the CLOB API and the Gamma API. While the specific documentation for these APIs was not provided, this section outlines the assumed functionalities and potential technical considerations based on common practices for prediction market and trading APIs. + +**3.1 Required Functionalities** + +The plugin must support the following core interactions with Polymarket: + +1. **Read Markets:** Fetch lists of available markets, retrieve details for specific markets (e.g., question, resolution criteria, current odds/prices, volume, liquidity, status). +2. **Buy Shares:** Place orders to purchase shares representing a specific outcome of a market. This requires specifying the market, outcome, quantity, and price (or placing a market order). +3. **Sell Shares:** Place orders to sell previously acquired shares. Similar parameters to buying are required. +4. **Redeem Winnings:** Claim payouts for shares held in markets that have resolved favorably. +5. **(Optional) Read Portfolio/Balances:** Fetch the agent's current positions, open orders, and available balance on Polymarket. + +**3.2 Potential API Complexities** + +Interacting with financial or quasi-financial APIs like Polymarket's often involves several complexities: + +* **Authentication:** Access to trading functions typically requires authentication. This could be via: + * **API Keys:** A common method where the platform issues keys (public/secret) for programmatic access.5 This is generally simpler to implement but requires secure key management. + * **Signed Transactions:** Particularly in decentralized or blockchain-adjacent platforms, actions might require signing transactions with a user's private key.10 This enhances security by keeping the key local but significantly increases implementation complexity within the plugin, requiring integration with cryptographic libraries (e.g., ethers, viem) and secure key handling.1 The specific mechanism used by Polymarket's APIs is critical to determine. +* **Rate Limiting:** APIs enforce limits on the number of requests per time period to prevent abuse and ensure stability. The plugin must respect these limits, potentially implementing retry logic with backoff or request queuing. +* **Error Handling:** Robust error handling is crucial. The plugin must interpret various API error codes (e.g., invalid parameters, insufficient funds, market closed, authentication failure) and provide meaningful feedback to the agent or user. +* **Data Formats:** APIs will return data in specific formats (likely JSON). The plugin needs to parse these responses correctly and potentially transform them into internal data structures. Prices and amounts might require handling specific decimal precisions. +* **CLOB vs. Gamma:** The distinction between the CLOB and Gamma APIs needs clarification from the official documentation. They might serve different purposes (e.g., one for order book data, another for higher-level actions or specific market types) or represent different versions or tiers of access. + +The method of authentication stands out as a primary technical hurdle. If private key signing is required for trading actions, it imposes significant security responsibilities on the plugin and the agent's configuration, demanding careful implementation to avoid key exposure.12 An API-key-based approach would be preferable from an implementation simplicity standpoint but still necessitates secure handling of those keys. + +## **4\. Plugin Specification: Polymarket Plugin for ElizaOS** + +This section details the proposed design for the @elizaos-plugins/plugin-polymarket. + +**4.1 Plugin Name** + +The standard naming convention suggests: @elizaos-plugins/plugin-polymarket + +**4.2 Core Components** + +* **Actions:** These define the capabilities the agent can perform based on natural language commands. Each action includes a name, description, example interactions (examples), validation logic (validate), and the core execution logic (handler).5 Similes (similes) allow the agent to recognize variations in user requests.11 + * **Table 1: Core Plugin Actions** + +| Action Name | Similes | Description | Input Parameters (Example) | Output (Example) | +| :---- | :---- | :---- | :---- | :---- | +| POLYMARKET\_READ\_MARKET | find market, get market info, lookup market | Retrieves details about a specific Polymarket market or searches for markets. | market\_id or search\_query | Market details (question, outcomes, prices, etc.) | +| POLYMARKET\_BUY\_SHARES | buy, invest in, purchase shares | Places an order to buy shares for a specific outcome in a market. | market\_id, outcome, amount, price | Confirmation message, Order ID | +| POLYMARKET\_SELL\_SHARES | sell, divest, close position | Places an order to sell shares held for a specific outcome in a market. | market\_id, outcome, amount, price | Confirmation message, Order ID | +| POLYMARKET\_REDEEM\_WINNINGS | redeem, claim winnings, collect payout | Redeems winnings from resolved markets where the agent held winning shares. | market\_id (optional) | Confirmation of redemption, Amount redeemed | +| POLYMARKET\_GET\_PORTFOLIO (Opt) | portfolio, balance, positions | Retrieves the agent's current balance, open orders, and positions. | None | Portfolio details | + +* **Services:** A dedicated service is recommended for managing interactions with the Polymarket APIs. + * PolymarketApiService: This class will encapsulate all HTTP requests (using libraries like axios or node-fetch) to the Polymarket CLOB and Gamma APIs. Its responsibilities include: + * Handling authentication (API key injection or transaction signing logic). + * Constructing API requests based on input parameters. + * Parsing API responses. + * Implementing error handling and potentially rate limit management. + * Loading configuration (API endpoints, keys) during initialization. +* **Providers:** A provider can optionally be implemented to proactively fetch and update the agent's state with relevant Polymarket data. + * PolymarketPortfolioProvider (Optional): This provider could periodically poll the Polymarket API (using PolymarketApiService) to fetch the agent's current balance and positions, making this information readily available in the agent's context without requiring an explicit action.5 This helps keep the agent's understanding of its financial state more current but requires careful consideration of API rate limits. + +**4.3 Configuration** + +The plugin will require configuration parameters, managed via environment variables or character.json settings.5 + +* **Table 2: Configuration Parameters** + +| Parameter Name | Type | Location | Description | Required | Example Value | +| :---- | :---- | :---- | :---- | :---- | :---- | +| POLYMARKET\_API\_KEY | string | .env/Settings | API Key for accessing Polymarket APIs (if using key-based auth). | Maybe | pk\_live\_xxxxxxxxxxxxxxxx | +| POLYMARKET\_API\_SECRET | string | .env/Settings | API Secret associated with the API Key (if applicable). | Maybe | sk\_live\_xxxxxxxxxxxxxxxx | +| POLYMARKET\_PRIVATE\_KEY | string | .env/Settings | User's private key for signing transactions (if required by API). **Handle with extreme care.** | Maybe | 0xabcde... | +| POLYMARKET\_NETWORK | string | .env/Settings | Target Polymarket environment ('mainnet' or 'testnet'). Defaults to 'mainnet'. | No | testnet | +| POLYMARKET\_CLOB\_API\_ENDPOINT | string | .env/Settings | Base URL for the Polymarket CLOB API. Defaults can be provided. | No | https://clob-api.polymarket.com/ | +| POLYMARKET\_GAMMA\_API\_ENDPOINT | string | .env/Settings | Base URL for the Polymarket Gamma API. Defaults can be provided. | No | https://gamma-api.polymarket.com/ | + +The decision of whether POLYMARKET\_API\_KEY/SECRET or POLYMARKET\_PRIVATE\_KEY is required depends entirely on the Polymarket API's authentication mechanism. Storing POLYMARKET\_PRIVATE\_KEY demands the highest level of security; using secure environment variable management outside of version control is strongly recommended.12 Placing user-specific keys in character.json settings allows different agents to use different Polymarket accounts.5 + +**4.4 Data Handling and Validation** + +* **TypeScript Types:** Define clear TypeScript interfaces or types for all Polymarket data structures (Market, Order, Position, Trade, API Responses) within the plugin (src/types/). +* **Input Validation:** Use a library like zod 11 within action handlers to validate incoming parameters (e.g., ensuring amount is a valid number, market\_id has the correct format) before sending requests to the PolymarketApiService. This prevents invalid API calls and provides immediate feedback for malformed requests. + +**4.5 Error Handling** + +* The PolymarketApiService should catch errors from API calls (network issues, HTTP status codes) and translate Polymarket-specific error responses into standardized errors. +* Action handlers should catch errors from the service and validation steps, formatting them into user-understandable messages for the agent to relay. Logging should capture detailed error information for debugging. + +This specification provides a blueprint for a modular and configurable plugin. The separation of API logic into a dedicated service enhances testability and maintainability. The explicit definition of actions and configuration parameters clarifies the plugin's capabilities and requirements. However, the significant uncertainty around the API authentication mechanism remains a key area requiring investigation once API documentation is available. + +## **5\. Proposed Project Structure** + +A well-organized project structure is essential for maintainability and aligns with conventions observed in the ElizaOS ecosystem.2 The following structure, based on the eliza-plugin-starter 8 and other existing plugins 7, is recommended for the @elizaos-plugins/plugin-polymarket: + +plugin-polymarket/ +├── src/ +│ ├── actions/ \# Implementation of plugin actions +│ │ ├── readMarket.ts +│ │ ├── buyShares.ts +│ │ ├── sellShares.ts +│ │ ├── redeemWinnings.ts +│ │ └── index.ts \# Exports all actions +│ ├── services/ \# Core service logic +│ │ └── polymarketApiService.ts +│ ├── providers/ \# Optional: Data providers +│ │ └── polymarketPortfolioProvider.ts +│ ├── types/ \# TypeScript interfaces and types +│ │ └── index.ts \# (or specific files like marketTypes.ts, orderTypes.ts) +│ ├── utils/ +│ │ └── index.ts \# (Helper functions, constants) +│ └── index.ts \# (Plugin entry point, exports actions, providers, services) +├── test/ \# Unit and integration tests +│ ├── actions/ +│ └── services/ +├── assets/ \# Branding assets for registry \[5\] +│ ├── logo.png \# (400x400px) +│ ├── banner.png \# (1280x640px) +│ └── screenshots/ +│ └── screenshot1.png \# Demo screenshot +├── characters/ \# Example character configuration +│ └── polymarket-agent.character.json.example +├──.env.example \# Example environment variables \[13\] +├── package.json \# Project metadata and dependencies +├── tsconfig.json \# TypeScript compiler options +├── README.md \# Plugin documentation +└──... \# (other config files like.gitignore,.prettierrc) + +**5.1 Key Module Definitions** + +* src/index.ts: The main entry point for the plugin. It exports the plugin definition object, including arrays of implemented actions, providers, and services, making them discoverable by the ElizaOS runtime. This follows patterns seen in examples like.10 +* src/actions/\*.ts: Each file implements a specific action, adhering to the Action interface (defining name, similes, description, validate, handler, examples).11 The handler function within each action will typically instantiate or utilize the PolymarketApiService to perform the required API calls. +* src/services/polymarketApiService.ts: Contains the PolymarketApiService class. This class is responsible for all communication with the Polymarket CLOB and Gamma APIs. It handles loading configuration (API keys/endpoints), building requests, managing authentication (API key headers or transaction signing), parsing responses, and handling API-level errors and rate limits. It will likely use an HTTP client library like axios or node-fetch. +* src/providers/\*.ts: If implemented, files here define Provider classes (e.g., PolymarketPortfolioProvider) that periodically fetch data using the PolymarketApiService and update the agent's state or context. +* src/types/index.ts: Centralizes all TypeScript interfaces and type definitions specific to Polymarket data (e.g., Market, Order, Position, API response structures). Using Zod schemas 16 for validation within these types can enhance robustness. +* src/utils/index.ts: Contains shared constants (e.g., default API endpoint URLs, error codes, configuration keys) and utility functions (e.g., data formatting, number precision handling). + +**5.2 package.json Configuration** + +The package.json file defines the plugin's metadata and dependencies: + +* name: @elizaos-plugins/plugin-polymarket +* version: 0.1.0 (or semantic version) +* main: dist/index.js (points to the compiled JavaScript output) +* types: dist/index.d.ts (points to the generated TypeScript declaration file) +* scripts: Standard scripts for build (e.g., tsup src/index.ts \--format esm,cjs \--dts), test, dev, lint. 11 +* dependencies: + * @elizaos/core: Essential dependency for ElizaOS types and interfaces.11 + * axios or node-fetch: For making HTTP requests to the Polymarket API. + * zod: For data validation.11 + * ethers or viem: Potentially required if transaction signing with a private key is necessary.1 + * js-tiktoken: Optional, if needed for calculating token counts for LLM context limits, similar to the web search plugin.11 +* devDependencies: + * typescript: TypeScript compiler. + * tsup 11 or tsc: Build tool. + * @types/node: Node.js type definitions. + * Testing framework (e.g., jest, vitest). + * eslint, prettier: Linters and formatters. +* agentConfig: Defines the plugin for ElizaOS discovery.5 + JSON + "agentConfig": { + "pluginType": "elizaos:plugin:1.0.0", + "pluginParameters": { + "POLYMARKET\_API\_KEY": { "type": "string", "description": "Polymarket API Key (optional)" }, + "POLYMARKET\_API\_SECRET": { "type": "string", "description": "Polymarket API Secret (optional)" }, + "POLYMARKET\_PRIVATE\_KEY": { "type": "string", "description": "Private key for signing (optional, handle securely)" }, + "POLYMARKET\_NETWORK": { "type": "string", "description": "Network (mainnet/testnet)" }, + "POLYMARKET\_CLOB\_API\_ENDPOINT": { "type": "string", "description": "CLOB API endpoint URL" }, + "POLYMARKET\_GAMMA\_API\_ENDPOINT": { "type": "string", "description": "Gamma API endpoint URL" } + } + } + +**5.3 tsconfig.json Setup** + +A standard tsconfig.json for a Node.js TypeScript project should be used. Key settings include: + +* target: A modern ECMAScript version (e.g., ES2022 or ESNext). +* module: NodeNext or ESNext to support modern module systems, aligning with Node.js 23+ requirements.3 +* outDir: ./dist (or similar build output directory). +* rootDir: ./src. +* strict: true (highly recommended for type safety). +* esModuleInterop: true. +* declaration: true (to generate .d.ts files). +* sourceMap: true (for debugging). + +This structure promotes a clear separation of concerns. Actions define *what* the agent can do, the service handles *how* to interact with the external API, and types define the *data* involved. This modularity is crucial for testing, as the PolymarketApiService can be easily mocked during unit tests of the actions, allowing verification of action logic without making actual API calls. Managing dependencies like @elizaos/core and external libraries for HTTP, validation, and potential blockchain interactions is critical for stability and compatibility.11 + +## **6\. Holistic Project Plan & Roadmap** + +A phased approach is recommended for developing the Polymarket plugin, allowing for incremental progress, testing, and risk management, particularly given the potential financial implications of trading actions. + +**6.1 Development Phases** + +* **Phase 1: Setup & Foundation (Estimated Duration: \~1 week)** + * **Activities:** + * Initialize project repository using eliza-plugin-starter 8 or by cloning/adapting a similar plugin structure. + * Configure package.json (dependencies, agentConfig 5), tsconfig.json, linters (eslint), formatters (prettier). + * Implement the basic structure for PolymarketApiService in src/services/. + * Implement configuration loading logic within the service to read API keys/endpoints/private keys from environment variables or character settings. + * Set up basic logging infrastructure. + * Define core TypeScript types/interfaces for basic Polymarket structures (e.g., Market) in src/types/. + * Write initial unit tests for configuration loading and basic service instantiation. + * **Milestone:** Project repository created and configured. Basic PolymarketApiService structure exists and can load configuration correctly. Core types defined. +* **Phase 2: Read Functionality Implementation (Estimated Duration: \~1-2 weeks)** + * **Activities:** + * Implement API call methods within PolymarketApiService for fetching market lists and specific market details (using endpoints assumed from CLOB/Gamma APIs). + * Implement the POLYMARKET\_READ\_MARKET action in src/actions/, utilizing the service methods. Include natural language similes.11 + * Implement input validation (e.g., using Zod 16) for the action's parameters. + * Write comprehensive unit tests for the new service methods and the action handler (mocking the service). + * Perform integration testing by running the plugin within a local Eliza instance (pnpm start \--characters=... 3) and interacting via a client (pnpm start:client 6) to query market data. + * **Milestone:** The agent can successfully query and retrieve information about Polymarket markets via natural language commands. +* **Phase 3: Trading Functionality (Buy/Sell) Implementation (Estimated Duration: \~2-3 weeks)** + * **Activities:** + * Determine the exact API authentication mechanism (API key vs. signed transaction) from Polymarket documentation. + * Implement API call methods in PolymarketApiService for placing Buy and Sell orders. If signing is required, integrate necessary libraries (e.g., viem, ethers 16) and implement secure private key handling. + * Implement the POLYMARKET\_BUY\_SHARES and POLYMARKET\_SELL\_SHARES actions, utilizing the service. + * Implement robust input validation (market ID format, outcome validity, numeric amounts/prices) and comprehensive error handling (insufficient funds, invalid order parameters, market not open, API errors). + * Write extensive unit tests covering various scenarios, including edge cases and error conditions. + * Conduct thorough integration testing, **critically using Polymarket's testnet environment if available**, or with minimal amounts on mainnet if unavoidable and accepted risk. Verify order placement and handling of potential failures. + * **Milestone:** The agent can successfully execute buy and sell orders on Polymarket (ideally on a testnet) via API calls triggered by natural language. +* **Phase 4: Redeem & Portfolio Implementation (Estimated Duration: \~1-2 weeks)** + * **Activities:** + * Implement API call methods in PolymarketApiService for redeeming winnings from resolved markets and fetching user portfolio/balances. + * Implement the POLYMARKET\_REDEEM\_WINNINGS action. + * Optionally implement the POLYMARKET\_GET\_PORTFOLIO action and/or the PolymarketPortfolioProvider 5 for proactive state updates. + * Add unit and integration tests for redemption and portfolio functionalities. + * **Milestone:** The agent can redeem winnings and query its Polymarket portfolio and balance. +* **Phase 5: Testing, Refinement & Documentation (Estimated Duration: \~1-2 weeks)** + * **Activities:** + * Conduct end-to-end testing using various conversational flows and edge cases. + * Refine error messages relayed to the user for clarity. Enhance logging based on testing feedback. + * Review and optimize API usage (e.g., check for redundant calls, ensure rate limits are respected). Consider caching for non-volatile data if applicable. + * Write a comprehensive README.md detailing plugin setup, configuration options (including security warnings for private keys), usage examples for each action, and any known limitations. + * Prepare branding assets (logo.png, banner.png, screenshots/) according to Eliza Plugin Registry guidelines if submission is intended.5 + * Ensure all tests pass consistently. + * **Milestone:** Plugin is robust, well-tested, thoroughly documented, and potentially ready for wider use or registry submission. + +**6.2 Testing Strategy** + +A multi-layered testing approach is essential: + +* **Unit Testing:** Use a framework like Vitest or Jest to test individual functions, classes, and modules in isolation. Mock the PolymarketApiService when testing action handlers to isolate action logic. Test utility functions, validation schemas, and service methods (potentially mocking the underlying HTTP client). +* **Integration Testing:** Run the complete plugin within a local ElizaOS environment.3 Use the direct client 8 or other clients (pnpm start:client 3) to send commands to the agent and verify the end-to-end flow: natural language \-\> action recognition \-\> validation \-\> service call \-\> API interaction \-\> response to user. Crucially, perform trading tests against a Polymarket testnet if possible. +* **Manual Testing:** Interact conversationally with the agent using various phrasings and scenarios to ensure natural interaction and correct behavior. Test error conditions and recovery paths. + +**6.3 Deployment Considerations** + +1. **Build:** Ensure the plugin is compiled (pnpm build). +2. **Dependency:** Add the plugin package as a dependency to the target Eliza agent's package.json (e.g., using pnpm add @elizaos-plugins/plugin-polymarket@workspace:\* if in a monorepo, or referencing the built package).6 +3. **Character Config:** Include @elizaos-plugins/plugin-polymarket in the plugins array of the agent's character.json file.5 +4. **Environment/Settings:** Configure the necessary parameters (API keys, private key, network) in the deployment environment's .env file or the agent's character.json settings object.3 Ensure secure management of sensitive credentials. + +**6.4 Development Roadmap Summary** + +* **Table 3: Development Roadmap** + +| Phase | Key Activities | Major Milestones | Estimated Duration | +| :---- | :---- | :---- | :---- | +| **Phase 1: Setup & Foundation** | Init repo, configure build tools & deps, basic service structure, config loading, core types, initial tests. | Project bootstrapped, config loads, basic service structure in place. | \~1 week | +| **Phase 2: Read Functionality** | Implement read API calls (service), POLYMARKET\_READ\_MARKET action, validation, unit & integration tests for reading. | Agent can query Polymarket market data. | \~1-2 weeks | +| **Phase 3: Trading Functionality (Buy/Sell)** | Implement trading API calls (service, handle auth/signing), BUY/SELL actions, validation, error handling, extensive unit & integration tests (testnet). | Agent can execute buy/sell orders (on testnet). | \~2-3 weeks | +| **Phase 4: Redeem & Portfolio** | Implement redeem/portfolio API calls (service), REDEEM action, optional GET\_PORTFOLIO action/provider, tests. | Agent can redeem winnings and query portfolio. | \~1-2 weeks | +| **Phase 5: Testing, Refinement & Docs** | End-to-end testing, error handling refinement, optimization, comprehensive README.md, branding assets 5, final test suite execution. | Plugin is robust, well-tested, documented, potentially registry-ready.5 | \~1-2 weeks | + +This iterative plan allows for focused development and testing on specific functionalities before moving to more complex or sensitive operations like trading. The emphasis on testing, particularly using a testnet environment for financial transactions, is paramount to minimize risk. Furthermore, planning for documentation and potential registry submission from the outset encourages adherence to quality standards beneficial for any user of the plugin.5 + +## **7\. Key Considerations & Recommendations** + +Several critical factors require careful attention during the development and deployment of the Polymarket plugin. + +* **API Nuances:** Thoroughly understanding the specifics of both the CLOB and Gamma APIs is essential once documentation is available. Pay close attention to: + * Rate limits for different endpoints and implement appropriate handling (e.g., delays, backoff). + * Detailed error codes and their meanings to provide accurate feedback. + * Specific data formats, especially for prices, amounts, and market identifiers. + * Any differences in functionality or requirements between the two APIs. +* **Transaction Signing & Security:** This is arguably the most critical consideration if the API requires private key signing for trading or redemption actions. + * **Confirmation:** Verify definitively if private key signing is required versus API key authentication. + * **Security:** If private keys are necessary, implement robust security measures. Avoid storing raw keys directly in code or insecure configuration files. Utilize secure environment variable management systems (like Docker secrets, Kubernetes secrets, or cloud provider secret managers) in deployment. Minimize the scope and duration for which the key is held in memory. + * **Alternatives:** Investigate if Polymarket offers alternative, less sensitive methods for authenticated actions, such as session tokens obtained via a more secure initial authentication, or integration with browser extensions/wallet connectors (though this might be complex for a backend agent). + * **User Consent:** Ensure the agent interaction model includes clear user consent before executing any action involving fund movement or key usage. +* **State Synchronization:** Maintaining an accurate representation of the agent's Polymarket portfolio (balances, positions) within the agent's state can be challenging due to API latency, potential network issues, or delays in order fulfillment. + * **Strategy:** Decide between fetching state on-demand before critical actions (e.g., check balance before buying) or using a background provider (PolymarketPortfolioProvider) to poll periodically. Polling provides fresher data but consumes API rate limits and might still not be perfectly real-time. +* **Idempotency:** For actions that modify state or move funds (Buy, Sell, Redeem), strive to make API calls idempotent if the Polymarket API supports it (e.g., using unique order identifiers). This prevents accidental duplicate transactions if a request is retried due to network timeouts or temporary errors. +* **Gas Fees / Transaction Costs:** If any interactions directly result in on-chain transactions (needs confirmation from API docs, especially if interacting with smart contracts directly rather than via an off-chain API), the plugin must account for potential gas fees or transaction costs. This might involve fetching estimated costs and confirming sufficient balance exists in the appropriate currency (e.g., USDC, ETH). +* **Testing Environment:** **Strongly recommend** performing all development and testing of trading and redemption functionalities against Polymarket's official testnet or staging environment, if available. Testing with real funds on mainnet carries significant financial risk. +* **Configuration Management:** Adhere to best practices: use .env for instance-wide, non-user-specific settings (like default API endpoints) and prefer character.json settings for agent-specific credentials (like individual API keys or the sensitive private key, if unavoidable, while acknowledging the security risks).3 +* **Code Quality and Maintainability:** Follow TypeScript best practices, enforce code style with linters (ESLint) and formatters (Prettier), write clear comments for complex logic, and aim for high unit test coverage. Adhering to the observed structural patterns of other ElizaOS plugins facilitates easier understanding and maintenance.2 + +## **8\. Conclusion** + +Developing an ElizaOS plugin to interact with Polymarket is feasible and offers compelling possibilities for creating AI agents capable of participating in prediction markets. The ElizaOS framework provides the necessary architecture and tools for building such an extension.1 + +The proposed specification outlines a modular plugin structure centered around distinct actions (POLYMARKET\_READ\_MARKET, BUY, SELL, REDEEM) and a dedicated service (PolymarketApiService) to handle API communication. A phased development plan with rigorous testing at each stage is recommended to manage complexity and risk. + +Key challenges revolve around the specifics of the Polymarket CLOB and Gamma APIs, particularly the authentication mechanism. If private key signing is required for trading functions, implementing secure key handling is paramount and represents the most significant technical and security hurdle. Thoroughly understanding API rate limits, error conditions, and data formats is also crucial. + +By following the outlined structure, development plan, and key considerations, a robust and functional Polymarket plugin can be created, significantly expanding the capabilities of ElizaOS agents in the domain of information markets. Careful attention to security, error handling, and testing will be essential for success. + +#### **Works cited** + +1. How to Build Web3-Enabled AI Agents with Eliza | QuickNode Guides, accessed May 5, 2025, [https://www.quicknode.com/guides/ai/how-to-setup-an-ai-agent-with-eliza-ai16z-framework](https://www.quicknode.com/guides/ai/how-to-setup-an-ai-agent-with-eliza-ai16z-framework) +2. 0x3Matt/eliza-guide: A guide for Eliza OS \- GitHub, accessed May 5, 2025, [https://github.com/0x3Matt/eliza-guide](https://github.com/0x3Matt/eliza-guide) +3. elizaOS/eliza: Autonomous agents for everyone \- GitHub, accessed May 5, 2025, [https://github.com/elizaOS/eliza](https://github.com/elizaOS/eliza) +4. elizaos-plugins/eliza \- GitHub, accessed May 5, 2025, [https://github.com/elizaos-plugins/eliza](https://github.com/elizaos-plugins/eliza) +5. JSON Registry for all the plugins in the elizaOS ecosystem \- GitHub, accessed May 5, 2025, [https://github.com/elizaos-plugins/registry](https://github.com/elizaos-plugins/registry) +6. Eliza Plugin Development Guide \- Flow Developer Portal, accessed May 5, 2025, [https://developers.flow.com/tutorials/ai-plus-flow/eliza/build-plugin](https://developers.flow.com/tutorials/ai-plus-flow/eliza/build-plugin) +7. okto-hq/okto-sdk-eliza-agent-template: AI agent example using eliza plugin \- GitHub, accessed May 5, 2025, [https://github.com/okto-hq/okto-sdk-eliza-agent-template](https://github.com/okto-hq/okto-sdk-eliza-agent-template) +8. elizaOS/eliza-plugin-starter: A starter plugin repo for the Solana hackathon \- GitHub, accessed May 5, 2025, [https://github.com/elizaOS/eliza-plugin-starter](https://github.com/elizaOS/eliza-plugin-starter) +9. storacha/elizaos-plugin \- GitHub, accessed May 5, 2025, [https://github.com/storacha/elizaos-plugin](https://github.com/storacha/elizaos-plugin) +10. elizaos-plugins/plugin-sei: Enables Eliza agents to perform actions on the Sei blockchain, including transferring SEI tokens and querying wallet balances. \- GitHub, accessed May 5, 2025, [https://github.com/elizaos-plugins/plugin-sei](https://github.com/elizaos-plugins/plugin-sei) +11. elizaos-plugins/plugin-web-search: A plugin for powerful web search capabilities, enabling efficient search query handling and result processing through a customizable API interface. \- GitHub, accessed May 5, 2025, [https://github.com/elizaos-plugins/plugin-web-search](https://github.com/elizaos-plugins/plugin-web-search) +12. ElizaOS DKG agent | OriginTrail, accessed May 5, 2025, [https://docs.origintrail.io/build-with-dkg/ai-agents/elizaos-dkg-agent](https://docs.origintrail.io/build-with-dkg/ai-agents/elizaos-dkg-agent) +13. eliza-plugin-starter/.env.example at master \- GitHub, accessed May 5, 2025, [https://github.com/elizaOS/eliza-plugin-starter/blob/master/.env.example](https://github.com/elizaOS/eliza-plugin-starter/blob/master/.env.example) +14. storacha/elizaos-plugin, accessed May 5, 2025, [https://docs.storacha.network/ai/elizaos/](https://docs.storacha.network/ai/elizaos/) +15. @elizaos/plugin-0g \- npm, accessed May 5, 2025, [https://www.npmjs.com/package/@elizaos/plugin-0g](https://www.npmjs.com/package/@elizaos/plugin-0g) +16. Building a Neon EVM plugin for ElizaOS: A Developer's Tutorial, accessed May 5, 2025, [https://neonevm.org/blog/building-a-neon-evm-plugin-for-elizaos:-a-developer's-tutorial](https://neonevm.org/blog/building-a-neon-evm-plugin-for-elizaos:-a-developer's-tutorial) \ No newline at end of file diff --git a/README-TESTS.md b/README-TESTS.md index add7165..bc8746b 100644 --- a/README-TESTS.md +++ b/README-TESTS.md @@ -1,6 +1,6 @@ -# Project Starter Tests +# Plugin Polymarket Tests -This document provides information about the testing approach for the Project Starter plugin. +This document provides specific information about the testing approach for the Polymarket plugin. ## Test Structure @@ -8,11 +8,9 @@ The project uses a standardized testing approach that leverages core test utilit ### Core Test Utilities -The tests reuse core testing functionality from `@elizaos/core` through a set of utilities in the `__tests__/utils/core-test-utils.ts` file: +The tests reuse core testing functionality from `@elizaos/core` through a set of utility functions: - `runCoreActionTests` - Validates action structure and functionality -- `runCoreModelTests` - Tests model behavior with various parameters -- `documentTestResult` - Records test results for debugging and documentation - `createMockRuntime` - Creates a standardized runtime for testing - `createMockMessage` - Creates test messages for action testing - `createMockState` - Creates test state objects @@ -21,13 +19,13 @@ The tests reuse core testing functionality from `@elizaos/core` through a set of The test suite covers: -1. **Actions** - Testing the HELLO_WORLD action and action utilities -2. **Models** - Testing TEXT_SMALL and TEXT_LARGE model implementations -3. **Plugin Structure** - Validating the overall plugin structure -4. **Routes** - Testing API routes -5. **Integration** - End-to-end plugin functionality -6. **File Structure** - Ensuring proper package organization -7. **Configuration** - Testing configuration handling +1. **Actions Tests** - Testing all Polymarket actions: + - Market data: `READ_POLYMARKET_MARKETS` and `GET_POLYMARKET_MARKET_BY_ID` + - Trading: `POLYMARKET_BUY_SHARES`, `POLYMARKET_SELL_SHARES`, and `POLYMARKET_REDEEM_WINNINGS` +2. **Service Tests** - Testing the service functionality: + - `GammaService` for market data API interactions + - `ClobService` for trading operations API interactions +3. **Plugin Structure** - Validating the overall plugin configuration ## Running Tests @@ -45,91 +43,249 @@ npm test -- actions.test.ts npm test -- --watch ``` -## Test Implementation +## Polymarket-Specific Tests ### Action Tests -The action tests use the core action test utilities to validate: +#### Market Data Action Tests -- Action structure compliance -- Action validation functionality -- Action handler behavior -- Action formatting utilities +Tests for the Polymarket market data actions validate: -Example from `actions.test.ts`: +- Market list retrieval with various filter parameters +- Single market retrieval by ID +- Error handling for invalid inputs or API failures +- Response formatting for both actions + +Example test case structure: ```typescript -// Run core tests on all plugin actions -it('should pass core action tests', () => { - if (plugin.actions) { - const coreTestResults = runCoreActionTests(plugin.actions); - expect(coreTestResults).toBeDefined(); - // ... - } +describe('readMarketsAction', () => { + it('should validate action structure', () => { + expect(readMarketsAction.name).toBe('READ_POLYMARKET_MARKETS'); + expect(readMarketsAction.handler).toBeDefined(); + expect(readMarketsAction.validate).toBeDefined(); + }); + + it('should retrieve and format active markets', async () => { + const mockRuntime = createMockRuntime(); + const mockMessage = createMockMessage({ + text: 'Show me prediction markets' + }); + const mockState = createMockState(); + + const result = await readMarketsAction.handler( + mockRuntime, + mockMessage, + mockState, + {}, + mockCallback, + [] + ); + + expect(result).toContain('Here are the top'); + }); }); ``` -### Model Tests +#### Trading Action Tests -The model tests validate: +Tests for the trading actions validate: -- Model interface compliance -- Handling of various parameters -- Response formatting -- Error handling +- Proper parameter extraction from user messages +- Market validation before placing orders +- API interactions for buy and sell orders +- Winnings redemption logic +- Error handling without try-catch blocks +- Response formatting for trade confirmations -Example from `models.test.ts`: +Example test case structure: ```typescript -it('should run core tests for TEXT_SMALL model', async () => { - if (plugin.models && plugin.models[ModelType.TEXT_SMALL]) { - const results = await runCoreModelTests( - ModelType.TEXT_SMALL, - plugin.models[ModelType.TEXT_SMALL] +describe('buySharesAction', () => { + it('should validate action structure', () => { + expect(buySharesAction.name).toBe('POLYMARKET_BUY_SHARES'); + expect(buySharesAction.handler).toBeDefined(); + expect(buySharesAction.validate).toBeDefined(); + }); + + it('should extract parameters and place buy order', async () => { + const mockRuntime = createMockRuntime(); + const mockMessage = createMockMessage({ + text: 'Buy 50 USD of YES shares in market 138462 at price 0.70' + }); + const mockState = createMockState(); + + // Mock GammaService and ClobService calls + jest.spyOn(GammaService, 'fetchMarketById').mockResolvedValue({ + success: true, + market: { /* mock market data */ } + }); + + jest.spyOn(ClobService, 'placeOrder').mockResolvedValue({ + success: true, + orderId: 'mock-order-id', + message: 'Order placed successfully' + }); + + const result = await buySharesAction.handler( + mockRuntime, + mockMessage, + mockState, + {}, + mockCallback, + [] ); - // ... - } + + expect(result).toContain('Order placed successfully'); + expect(GammaService.fetchMarketById).toHaveBeenCalledWith('138462'); + expect(ClobService.placeOrder).toHaveBeenCalledWith({ + marketId: '138462', + outcomeId: 'YES', + side: 'BUY', + amount: '50', + price: '0.70', + orderType: 'LIMIT' + }); + }); }); ``` -## Writing New Tests +### GammaService Tests -When adding new features, follow these guidelines: +Tests for the GammaService cover: -1. Use the core test utilities where possible -2. Structure tests in a consistent manner -3. Document test results using `documentTestResult` -4. Use the `createMockRuntime` for standardized testing +- API URL construction with various parameters +- Market data transformation +- Pagination handling +- Error handling for API failures -Example: +Example test case structure: ```typescript -it('should test my new feature', async () => { - const runtime = createMockRuntime(); - const message = createMockMessage('Test message'); - const state = createMockState(); - - const result = await myFeature(runtime, message, state); - - expect(result).toBeTruthy(); - documentTestResult('My feature test', result); +describe('GammaService', () => { + it('should correctly build API URLs', () => { + const url = GammaService._buildApiUrl({ + active: true, + limit: 10, + offset: 0 + }); + expect(url).toContain('active=true'); + expect(url).toContain('limit=10'); + }); + + it('should transform raw market data', () => { + const rawData = { /* mock data */ }; + const transformed = GammaService._transformMarketData(rawData); + expect(transformed.id).toBeDefined(); + expect(transformed.question).toBeDefined(); + expect(transformed.outcomes).toBeInstanceOf(Array); + }); }); ``` -## Logs and Documentation +### ClobService Tests + +Tests for the ClobService cover: -All tests use the Eliza logger for consistent reporting: +- Order placement (buy/sell) functionality +- Order cancellation +- Winnings redemption +- Error handling without try-catch blocks +- API key validation +- API response handling + +Example test case structure: ```typescript -logger.info(`TEST: ${testName}`); -logger.error(`ERROR: ${error.message}`); +describe('ClobService', () => { + beforeEach(() => { + // Mock environment variables + process.env.POLYMARKET_API_KEY = 'test-api-key'; + + // Mock global fetch + global.fetch = jest.fn(); + }); + + it('should place orders correctly', async () => { + // Mock successful API response + (global.fetch as jest.Mock).mockResolvedValue({ + ok: true, + json: async () => ({ orderId: 'test-order-id' }) + }); + + const result = await ClobService.placeOrder({ + marketId: '138462', + outcomeId: 'YES', + side: 'BUY', + amount: '50', + price: '0.70', + orderType: 'LIMIT' + }); + + expect(result.success).toBe(true); + expect(result.orderId).toBe('test-order-id'); + expect(global.fetch).toHaveBeenCalledWith( + expect.stringContaining('/orders'), + expect.objectContaining({ + method: 'POST', + headers: expect.objectContaining({ + 'Authorization': 'Bearer test-api-key' + }) + }) + ); + }); + + it('should handle missing API key', async () => { + delete process.env.POLYMARKET_API_KEY; + + const result = await ClobService.redeemWinnings({ + marketId: '138462' + }); + + expect(result.success).toBe(false); + expect(result.error).toContain('API key not configured'); + expect(global.fetch).not.toHaveBeenCalled(); + }); +}); ``` -## Debugging +## Mocking Strategy -To view detailed logs during test runs: +When testing the Polymarket plugin, the following mocking approaches are used: -```bash -# Run with detailed logging -DEBUG=eliza:* npm test -``` +1. **API Responses** - Mock responses from both Polymarket Gamma API and CLOB API +2. **Runtime Services** - Mock ElizaOS runtime for action testing +3. **User Inputs** - Simulated user messages with various queries and trading parameters +4. **Environment Variables** - Mock API keys for testing authentication + +## Testing Trading Actions + +For testing the trading functionality, follow these steps: + +1. **Mock Dependencies**: + - Mock the `GammaService.fetchMarketById` method to return a valid market + - Mock the `ClobService.placeOrder` and `ClobService.redeemWinnings` methods to simulate successful or failed API responses + +2. **Test Parameter Extraction**: + - Test that action can correctly extract market ID, outcome, amount, and price from user messages + - Test different message formats and phrasings to ensure robustness + +3. **Test API Interactions**: + - Verify the correct parameters are passed to the ClobService methods + - Test error handling logic when API calls fail + +4. **Test Without Try-Catch**: + - Ensure error handling works properly without try-catch blocks + - Verify conditional checks are properly implemented + +## Writing New Tests + +When adding new features to the Polymarket plugin, follow these guidelines: + +1. Create dedicated tests for new actions or services +2. Mock any external API calls +3. Test both successful and error scenarios +4. Verify correct market data formatting +5. Ensure proper handling of user queries with different search terms +6. For trading actions, test with various parameter combinations +7. Verify proper API key handling and authentication diff --git a/README.md b/README.md index d62b0df..2946608 100644 --- a/README.md +++ b/README.md @@ -1 +1,124 @@ -# Plugin Starter +# Plugin Polymarket + +A plugin for ElizaOS that provides integration with Polymarket prediction markets data. This plugin enables AI agents to fetch and present real-time market data from Polymarket and execute trading operations. + +## Overview + +The Polymarket plugin provides actions to: +- Retrieve a list of active prediction markets from Polymarket +- Fetch specific market details by ID +- Filter markets by various criteria including search terms +- Buy shares in specific market outcomes +- Sell shares in specific market outcomes +- Redeem winnings from resolved markets + +## Installation + +```bash +# Add the plugin to your ElizaOS project +npm install plugin-polymarket +``` + +## Configuration + +Create a `.env` file based on the provided `.env.example` template. + +### API Keys + +For trading operations, you need to obtain a Polymarket API key: + +``` +# Required for trading operations (buy/sell/redeem) +POLYMARKET_API_KEY=your_polymarket_api_key_here +``` + +No API key is required for basic market data access (read-only operations). + +## Usage + +### In ElizaOS + +Import and register the plugin in your ElizaOS project: + +```typescript +import pluginPolymarket from 'plugin-polymarket'; + +export const projectAgent: ProjectAgent = { + character, + init: async (runtime: IAgentRuntime) => await initCharacter({ runtime }), + plugins: [pluginPolymarket], +}; +``` + +### Available Actions + +#### READ_POLYMARKET_MARKETS + +Retrieves a list of active prediction markets, optionally filtered by search terms. + +Example prompts: +- "Show me prediction markets" +- "Find prediction markets about crypto" +- "What are the top 5 markets on Polymarket?" + +#### GET_POLYMARKET_MARKET_BY_ID + +Fetches detailed information about a specific market by its ID. + +Example prompts: +- "Show me details for Polymarket market 138462" +- "Get Polymarket data for market 138462" + +#### POLYMARKET_BUY_SHARES + +Places an order to buy shares in a specific market outcome. + +Example prompts: +- "Buy 50 USD of YES shares in market 138462 at price 0.70" +- "Place a buy order for 100 USD of NO shares in market 138462 at 0.30" + +#### POLYMARKET_SELL_SHARES + +Places an order to sell shares in a specific market outcome. + +Example prompts: +- "Sell 50 USD of YES shares in market 138462 at price 0.75" +- "Close my position in market 138462 by selling 30 USD of NO at 0.40" + +#### POLYMARKET_REDEEM_WINNINGS + +Redeems winnings from resolved markets. + +Example prompts: +- "Redeem my winnings from market 138462" +- "Claim all my winnings from resolved markets" + +## Development + +```bash +# Install dependencies +npm install + +# Run in development mode +npm run dev + +# Build the plugin +npm run build + +# Run tests +npm test +``` + +## API Reference + +This plugin uses the following Polymarket APIs: +- Gamma API: https://gamma-api.polymarket.com/markets (for market data) +- CLOB API: https://clob-api.polymarket.com (for trading operations) + +### Documentation Links +- Gamma API: https://docs.polymarket.com/developers/gamma-markets-api/gamma-structure +- CLOB API: https://docs.polymarket.com/developers/CLOB/introduction + +## License + +This project is licensed under the terms specified in the package.json file. diff --git a/package-lock.json b/package-lock.json index 7507b00..ab08808 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@elizaos/cli": "beta", "@elizaos/core": "beta", + "@elizaos/plugin-anthropic": "^1.0.0-beta.54", "@elizaos/plugin-bootstrap": "^1.0.0-beta.49", "@elizaos/plugin-openai": "beta", "@elizaos/plugin-sql": "beta", @@ -22,6 +23,22 @@ "vitest": "2.1.5" } }, + "node_modules/@ai-sdk/anthropic": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-1.2.12.tgz", + "integrity": "sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "1.1.3", + "@ai-sdk/provider-utils": "2.2.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.0.0" + } + }, "node_modules/@ai-sdk/openai": { "version": "1.3.22", "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.3.22.tgz", @@ -217,16 +234,12 @@ } }, "node_modules/@elizaos/core": { - "version": "1.0.0-beta.49", - "resolved": "https://registry.npmjs.org/@elizaos/core/-/core-1.0.0-beta.49.tgz", - "integrity": "sha512-WFafa/ptT0Tspk+CKaoqjKH/5qJ3yZgSQBLMUvrQdi+vsuKZcJ0wousbhtMHqW9vP5KfQrNJYQplH0gMtg6Ksw==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@elizaos/core/-/core-1.0.9.tgz", + "integrity": "sha512-AhJ4ENdD33o13YCunpd+QYLQT+W9H5qgGPIA44IojRHVrJzBM/SCzxGWevl3o3gZvlNeAQNfsIMFa/Qmwybtdg==", "license": "MIT", "dependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.53.0", - "@opentelemetry/instrumentation-pg": "^0.52.0", - "@opentelemetry/sdk-metrics": "^1.26.0", - "@opentelemetry/sdk-node": "^0.53.0", + "@sentry/browser": "^9.22.0", "buffer": "^6.0.3", "crypto-browserify": "^3.12.1", "dotenv": "16.4.5", @@ -235,11 +248,261 @@ "handlebars": "^4.7.8", "js-sha1": "0.7.0", "langchain": "^0.3.15", + "pdfjs-dist": "^5.2.133", "pino": "^9.6.0", "pino-pretty": "^13.0.0", "stream-browserify": "^3.0.0", "unique-names-generator": "4.7.1", - "uuid": "11.0.3" + "uuid": "11.0.3", + "vitest": "^3.1.4", + "zod": "^3.24.4" + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/@elizaos/core/node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@elizaos/core/node_modules/tinyspy": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", + "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@elizaos/core/node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@elizaos/core/node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/@elizaos/core/node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@elizaos/plugin-anthropic": { + "version": "1.0.0-beta.54", + "resolved": "https://registry.npmjs.org/@elizaos/plugin-anthropic/-/plugin-anthropic-1.0.0-beta.54.tgz", + "integrity": "sha512-nhTw7ri0TNitKE+GVVZbeYBAf9SQj96EeWtcr7ekn12HVZDeb8oI9/4f8Uwd39jGDc3MD54lXVxoMdlqsTXeKQ==", + "dependencies": { + "@ai-sdk/anthropic": "^1.2.11", + "@ai-sdk/ui-utils": "^1.2.11", + "@elizaos/core": "^1.0.0-beta.52", + "ai": "4.3.15", + "jsonrepair": "^3.12.0" } }, "node_modules/@elizaos/plugin-bootstrap": { @@ -1095,37 +1358,6 @@ "node": ">=12" } }, - "node_modules/@grpc/grpc-js": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.3.tgz", - "integrity": "sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1201,16 +1433,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/@langchain/core": { "version": "0.3.55", "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.55.tgz", @@ -1282,717 +1504,195 @@ "@langchain/core": ">=0.2.21 <0.4.0" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", + "node_modules/@napi-rs/canvas": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.71.tgz", + "integrity": "sha512-92ybDocKl6JM48ZpYbj+A7Qt45IaTABDk0y3sDecEQfgdhfNzJtEityqNHoCZ4Vty2dldPkJhxgvOnbrQMXTTA==", + "license": "MIT", + "optional": true, "engines": { - "node": ">=8.0.0" + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.71", + "@napi-rs/canvas-darwin-arm64": "0.1.71", + "@napi-rs/canvas-darwin-x64": "0.1.71", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.71", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.71", + "@napi-rs/canvas-linux-arm64-musl": "0.1.71", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.71", + "@napi-rs/canvas-linux-x64-gnu": "0.1.71", + "@napi-rs/canvas-linux-x64-musl": "0.1.71", + "@napi-rs/canvas-win32-x64-msvc": "0.1.71" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.71.tgz", + "integrity": "sha512-cxi3VCotIOS9kNFQI7dcysbVJi106pxryVY1Hi85pX+ZeqahRyeqc/NsLaZ998Ae99+F3HI5X/39G1Y/Byrf0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.200.0.tgz", - "integrity": "sha512-IKJBQxh91qJ+3ssRly5hYEJ8NDHu9oY/B1PXVSCWf7zytmYO9RNLB0Ox9XQ/fJ8m6gY6Q6NtBWlmXfaXt5Uc4Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.71.tgz", + "integrity": "sha512-7Y4D/6vIuMLYsVNtRM/w2j0+fB1GyqeOxc7I0BTx8eLP1S6BZE2Rj6zJfdG+zmLEOW0IlHa+VQq1q2MUAjW84w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.26.0.tgz", - "integrity": "sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==", - "license": "Apache-2.0", + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.71.tgz", + "integrity": "sha512-Z0IUqxclrYdfVt/SK9nKCzUHTOXKTWiygtO71YCzs0OtxKdNI7GJRJdYG48wXZEDQ/pqTF4F7Ifgtidfc2tYpg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/core": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.26.0.tgz", - "integrity": "sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.71.tgz", + "integrity": "sha512-KlpqqCASak5ruY+UIolJgmhMZ9Pa2o1QyaNu648L8sz4WNBbNa+aOT60XCLCL1VIKLv11B3MlNgiOHoYNmDhXQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.53.0.tgz", - "integrity": "sha512-x5ygAQgWAQOI+UOhyV3z9eW7QU2dCfnfOuIBiyYmC2AWr74f6x/3JBnP27IAcEx6aihpqBYWKnpoUTztkVPAZw==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/sdk-logs": "0.53.0" - }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.71.tgz", + "integrity": "sha512-bdGZCGu8YQNAiu3nkIVVUp6nIn6fPd36IuZsLXTG027E52KyIuZ3obCxehSwjDIUNkFWvmff5D6JYfWwAoioEw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.53.0.tgz", - "integrity": "sha512-cSRKgD/n8rb+Yd+Cif6EnHEL/VZg1o8lEcEwFji1lwene6BdH51Zh3feAD9p2TyVoBKrl6Q9Zm2WltSp2k9gWQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/sdk-logs": "0.53.0" - }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.71.tgz", + "integrity": "sha512-1R5sMWe9ur8uM+hAeylBwG0b6UHDR+iWQNgzXmF9vbBYRooQvmDWqpcgytKLJAC0vnWhIkKwqd7yExn7cwczmg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz", - "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.53.0.tgz", - "integrity": "sha512-m6KSh6OBDwfDjpzPVbuJbMgMbkoZfpxYH2r262KckgX9cMYvooWXEKzlJYsNDC6ADr28A1rtRoUVRwNfIN4tUg==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.53.0.tgz", - "integrity": "sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.53.0.tgz", - "integrity": "sha512-T/bdXslwRKj23S96qbvGtaYOdfyew3TjPEKOk5mHjkCmkVl1O9C/YMdejwSsdLdOq2YW30KjR9kVi0YMxZushQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.26.0.tgz", - "integrity": "sha512-PW5R34n3SJHO4t0UetyHKiXL6LixIqWN6lWncg3eRXhKuT30x+b7m5sDJS0kEWRfHeS+kG7uCw2vBzmB2lk3Dw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.200.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.200.0.tgz", - "integrity": "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.200.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "shimmer": "^1.2.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.52.0.tgz", - "integrity": "sha512-OBpqlxTqmFkZGHaHV4Pzd95HkyKVS+vf0N5wVX3BSb8uqsvOrW62I1qt+2jNsZ13dtG5eOzvcsQTMGND76wizA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.200.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.41.0", - "@types/pg": "8.6.1", - "@types/pg-pool": "2.0.6" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", - "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.33.0.tgz", - "integrity": "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@types/pg": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", - "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.53.0.tgz", - "integrity": "sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-transformer": "0.53.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.53.0.tgz", - "integrity": "sha512-F7RCN8VN+lzSa4fGjewit8Z5fEUpY/lmMVy5EWn2ZpbAabg3EE3sCLuTNfOiooNGnmvzimUPruoeqeko/5/TzQ==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.53.0.tgz", - "integrity": "sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-metrics": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.26.0.tgz", - "integrity": "sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-b3": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.26.0.tgz", - "integrity": "sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.26.0.tgz", - "integrity": "sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.53.0.tgz", - "integrity": "sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", - "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", - "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-node": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.53.0.tgz", - "integrity": "sha512-0hsxfq3BKy05xGktwG8YdGdxV978++x40EAKyKr1CaHZRh8uqVlXnclnl7OMi9xLMJEcXUw7lGhiRlArFcovyg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/exporter-logs-otlp-grpc": "0.53.0", - "@opentelemetry/exporter-logs-otlp-http": "0.53.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.53.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.53.0", - "@opentelemetry/exporter-trace-otlp-http": "0.53.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.53.0", - "@opentelemetry/exporter-zipkin": "1.26.0", - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-metrics": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "@opentelemetry/sdk-trace-node": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-metrics": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.26.0.tgz", - "integrity": "sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.26.0.tgz", - "integrity": "sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/context-async-hooks": "1.26.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/propagator-b3": "1.26.0", - "@opentelemetry/propagator-jaeger": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "semver": "^7.5.2" - }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.71.tgz", + "integrity": "sha512-xjjKsipueuG+LdKIk6/uAlqdo+rzGcmNpTZPXdakIT1sHX4NNSnQTzjRaj9Gh96Czjd9G89UWR0KIlE7fwOgFA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.71.tgz", + "integrity": "sha512-3s6YpklXDB4OeeULG1XTRyKrKAOo7c3HHEqM9A6N4STSjMaJtzmpp7tB/JTvAFeOeFte6gWN8IwC+7AjGJ6MpQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10" } }, - "node_modules/@opentelemetry/sql-common": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.0.tgz", - "integrity": "sha512-pmzXctVbEERbqSfiAgdes9Y63xjoOyXcD7B6IXBkVb+vbM7M9U98mn33nGXxPf4dfYR0M+vhcKRZmbSJ7HfqFA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0" - }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.71.tgz", + "integrity": "sha512-5v9aCLzCXw7u10ray5juQMdl7TykZSn1X5AIGYwBvTAcKSgrqaR9QkRxp1Lqk3njQmFekOW1SFN9bZ/i/6y6kA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/sql-common/node_modules/@opentelemetry/core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.0.tgz", - "integrity": "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.71.tgz", + "integrity": "sha512-oJughk6xjsRIr0Rd9EqjmZmhIMkvcPuXgr3MNn2QexTqn+YFOizrwHS5ha0BDfFl7TEGRvwaDUXBQtu8JKXb8A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/sql-common/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.33.0.tgz", - "integrity": "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w==", + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", "engines": { - "node": ">=14" + "node": ">=8.0.0" } }, "node_modules/@oven/bun-darwin-aarch64": { @@ -2154,70 +1854,6 @@ "node": ">=14" } }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.40.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", @@ -2478,12 +2114,96 @@ "win32" ] }, + "node_modules/@sentry-internal/browser-utils": { + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.30.0.tgz", + "integrity": "sha512-e6ZlN8oWheCB0YJSGlBNUlh6UPnY5Ecj1P+/cgeKBhNm7c3bIx4J50485hB8LQsu+b7Q11L2o/wucZ//Pb6FCg==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.30.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.30.0.tgz", + "integrity": "sha512-qAZ7xxLqZM7GlEvmSUmTHnoueg+fc7esMQD4vH8pS7HI3n9C5MjGn3HHlndRpD8lL7iUUQ0TPZQgU6McbzMDyw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.30.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.30.0.tgz", + "integrity": "sha512-+6wkqQGLJuFUzvGRzbh3iIhFGyxQx/Oxc0ODDKmz9ag2xYRjCYb3UUQXmQX9navAF0HXUsq8ajoJPm2L1ZyWVg==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.30.0", + "@sentry/core": "9.30.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.30.0.tgz", + "integrity": "sha512-I4MxS27rfV7vnOU29L80y4baZ4I1XqpnYvC/yLN7C17nA8eDCufQ8WVomli41y8JETnfcxlm68z7CS0sO4RCSA==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "9.30.0", + "@sentry/core": "9.30.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser": { + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.30.0.tgz", + "integrity": "sha512-sRyW6A9nIieTTI26MYXk1DmWEhmphTjZevusNWla+vvUigCmSjuH+xZw19w43OyvF3bu261Skypnm/mAalOTwg==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.30.0", + "@sentry-internal/feedback": "9.30.0", + "@sentry-internal/replay": "9.30.0", + "@sentry-internal/replay-canvas": "9.30.0", + "@sentry/core": "9.30.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/core": { + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.30.0.tgz", + "integrity": "sha512-JfEpeQ8a1qVJEb9DxpFTFy1J1gkNdlgKAPiqYGNnm4yQbnfl2Kb/iEo1if70FkiHc52H8fJwISEF90pzMm6lPg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "license": "MIT" }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, "node_modules/@types/cors": { "version": "2.8.18", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.18.tgz", @@ -2493,6 +2213,12 @@ "@types/node": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "license": "MIT" + }, "node_modules/@types/diff-match-patch": { "version": "1.0.36", "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", @@ -2535,27 +2261,12 @@ "pg-types": "^4.0.1" } }, - "node_modules/@types/pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", - "license": "MIT", - "dependencies": { - "@types/pg": "*" - } - }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "license": "MIT" }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", - "license": "MIT" - }, "node_modules/@types/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", @@ -2759,27 +2470,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/agentkeepalive": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", @@ -2876,7 +2566,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3149,7 +2838,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dev": true, "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", @@ -3162,147 +2850,53 @@ "node": ">=12" } }, - "node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 16" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/cipher-base": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 0.10" } }, "node_modules/color-convert": { @@ -3510,9 +3104,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3540,7 +3134,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3899,7 +3492,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { @@ -3979,20 +3571,10 @@ "esbuild": ">=0.12 <1" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -4036,7 +3618,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" @@ -4170,15 +3751,6 @@ "node": ">= 18.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -4408,39 +3980,12 @@ ], "license": "BSD-3-Clause" }, - "node_modules/import-in-the-middle": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.1.tgz", - "integrity": "sha512-k2V9wNm9B+ysuelDTHjI9d5KPc4l8zAZTGqj+pcynvWkypZd857ryzN8jNC7Pg2YZXNMJcHRPpaDyCBbNyVRpA==", - "license": "Apache-2.0", - "dependencies": { - "acorn": "^8.14.0", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -4558,6 +4103,12 @@ "base64-js": "^1.5.1" } }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4602,6 +4153,15 @@ "node": ">=0.10.0" } }, + "node_modules/jsonrepair": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.12.0.tgz", + "integrity": "sha512-SWfjz8SuQ0wZjwsxtSJ3Zy8vvLg6aO/kxcp9TWNPGwJKgTZVfhNEQBMk/vPOpYCDFWRxD6QWuI6IHR1t615f0w==", + "license": "ISC", + "bin": { + "jsonrepair": "bin/cli.js" + } + }, "node_modules/langchain": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.3.24.tgz", @@ -4805,29 +4365,16 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", "license": "MIT" }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "dev": true, + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", + "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", "license": "MIT" }, "node_modules/lru-cache": { @@ -4843,7 +4390,6 @@ "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -4982,12 +4528,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5276,12 +4816,6 @@ "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, "node_modules/path-scurry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", @@ -5318,7 +4852,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 14.16" @@ -5340,6 +4873,18 @@ "node": ">=0.12" } }, + "node_modules/pdfjs-dist": { + "version": "5.3.31", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.3.31.tgz", + "integrity": "sha512-EhPdIjNX0fcdwYQO+e3BAAJPXt+XI29TZWC7COhIXs/K0JHcUt1Gdz1ITpebTwVMFiLsukdUZ3u0oTO7jij+VA==", + "license": "Apache-2.0", + "engines": { + "node": ">=20.16.0 || >=22.3.0" + }, + "optionalDependencies": { + "@napi-rs/canvas": "^0.1.67" + } + }, "node_modules/pg": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.0.tgz", @@ -5587,7 +5132,6 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "devOptional": true, "funding": [ { "type": "opencollective", @@ -5737,30 +5281,6 @@ ], "license": "MIT" }, - "node_modules/protobufjs": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.1.tgz", - "integrity": "sha512-3qx3IRjR9WPQKagdwrKjO3Gu8RgQR2qqw+1KnigWhoVjFqegIj1K3bP11sGqhxrO46/XL7lekuG4jmjL+4cLsw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -5878,49 +5398,6 @@ "node": ">= 12.13.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -6090,17 +5567,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, "license": "ISC" }, "node_modules/signal-exit": { @@ -6256,7 +5726,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6285,14 +5754,12 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, "license": "MIT" }, "node_modules/std-env": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", - "dev": true, "license": "MIT" }, "node_modules/stream-browserify": { @@ -6442,6 +5909,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -6548,18 +6027,6 @@ "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/swr": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.3.tgz", @@ -6711,7 +6178,6 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, "license": "MIT" }, "node_modules/tinyexec": { @@ -6721,9 +6187,9 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -6737,10 +6203,9 @@ } }, "node_modules/tinypool": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" @@ -7353,7 +6818,6 @@ "version": "5.4.19", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -7439,7 +6903,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7456,7 +6919,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7473,7 +6935,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7490,7 +6951,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7507,7 +6967,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7524,7 +6983,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7541,7 +6999,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7558,7 +7015,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7575,7 +7031,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7592,7 +7047,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7609,7 +7063,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7626,7 +7079,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7643,7 +7095,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7660,7 +7111,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7677,7 +7127,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7694,7 +7143,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7711,7 +7159,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7728,7 +7175,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7745,7 +7191,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7762,7 +7207,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7779,7 +7223,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7796,7 +7239,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7813,7 +7255,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7827,7 +7268,6 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -7973,7 +7413,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, "license": "MIT", "dependencies": { "siginfo": "^2.0.0", @@ -8133,15 +7572,6 @@ "node": ">=0.4" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/yaml": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", @@ -8154,74 +7584,6 @@ "node": ">= 14" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/zod": { "version": "3.24.2", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", diff --git a/package.json b/package.json index 84475cf..efd8e22 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "dependencies": { "@elizaos/cli": "beta", "@elizaos/core": "beta", + "@elizaos/plugin-anthropic": "^1.0.0-beta.54", "@elizaos/plugin-bootstrap": "^1.0.0-beta.49", "@elizaos/plugin-openai": "beta", "@elizaos/plugin-sql": "beta", @@ -65,4 +66,4 @@ } }, "platform": "node" -} \ No newline at end of file +} diff --git a/src/actions/buyShares.ts b/src/actions/buyShares.ts new file mode 100644 index 0000000..ace2945 --- /dev/null +++ b/src/actions/buyShares.ts @@ -0,0 +1,149 @@ +import { + type Action, + type IAgentRuntime, + type Memory, + type State, + type Content, + elizaLogger, + HandlerCallback, + logger +} from "@elizaos/core"; +import { ClobService } from "../services/clobService"; +import { BuySharesActionContent } from "../types"; +import { GammaService } from "../services/gammaService"; + +export const buySharesAction: Action = { + name: "POLYMARKET_BUY_SHARES", + similes: [ + "buy shares", + "invest in market", + "purchase outcome", + "place buy order" + ], + description: "Places an order to buy shares in a specific Polymarket outcome", + examples: [ + [ + { + name: "{{user1}}", + content: { text: 'Buy 50 USD worth of YES shares in market 138462 at price 0.65' }, + }, + { + name: "{{agent}}", + content: { text: 'Order placed successfully! You have bought 50 USD worth of YES shares in "Will event X happen?" market at price $0.65 per share. Order ID: POLY-12345' }, + }, + ], + [ + { + name: "{{user1}}", + content: { text: 'Purchase NO shares in market 138462' }, + }, + { + name: "{{agent}}", + content: { text: 'I need a few more details to place your order. Could you specify the amount you want to invest and the price at which you want to buy?' }, + }, + ], + ], + + validate: async ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + ): Promise => { + const content = message.content as BuySharesActionContent; + if (!content || !content.text) { + return false; + } + + const text = content.text.toLowerCase(); + + const hasBuyKeywords = + text.includes("buy") || + text.includes("purchase") || + text.includes("invest"); + + const hasMarketKeywords = + text.includes("market") || + text.includes("shares") || + text.includes("outcome") || + /\d{6}/.test(text); // Checks for market ID pattern + + return hasBuyKeywords && hasMarketKeywords; + }, + + handler: async ( + _runtime: IAgentRuntime, + message: Memory, + _state: State, + _options: any, + callback: HandlerCallback, + _responses: Memory[] + ): Promise => { + const content = message.content as BuySharesActionContent; + const text = content.text.trim(); + + // Extract market ID + const marketIdPattern = /\b\d{6}\b/; + const marketIdMatch = text.match(marketIdPattern); + const marketId = marketIdMatch ? marketIdMatch[0] : content.marketId; + + if (!marketId) { + return "Sorry, I couldn't identify a market ID in your request. Please specify a market ID."; + } + + // First fetch market details to verify market exists and to display details later + const marketResult = await GammaService.fetchMarketById(marketId); + if (!marketResult.success || !marketResult.market) { + return `Sorry, I couldn't find a market with ID ${marketId}. ${marketResult.error || ''}`; + } + + // Extract outcome (YES/NO) + const outcomePattern = /\b(yes|no)\b/i; + const outcomeMatch = text.match(outcomePattern); + const outcome = outcomeMatch ? outcomeMatch[0].toUpperCase() : content.outcomeId; + + if (!outcome) { + return `Please specify which outcome you want to buy (YES or NO) for market "${marketResult.market.question}".`; + } + + // Extract amount + const amountPattern = /\b(\d+(?:\.\d+)?)\s*(?:USD|USDC|dollars|$)?\b/; + const amountMatch = text.match(amountPattern); + const amount = amountMatch ? amountMatch[1] : content.amount; + + if (!amount) { + return `Please specify the amount you want to invest in ${outcome} shares for market "${marketResult.market.question}".`; + } + + // Extract price + const pricePattern = /(?:price|at)\s*(?:\$)?(\d+(?:\.\d+)?)/i; + const priceMatch = text.match(pricePattern); + const price = priceMatch ? priceMatch[1] : content.price; + + if (!price) { + return `Please specify the price at which you want to buy ${outcome} shares for market "${marketResult.market.question}".`; + } + + // Log the extracted parameters for debugging + logger.info(`Buying ${amount} USD of ${outcome} in market ${marketId} at price ${price}`); + + // Place the order through the CLOB API + const result = await ClobService.placeOrder({ + marketId, + outcomeId: outcome, + side: 'BUY', + amount, + price, + orderType: 'LIMIT' + }); + + const responseContent: Content = { + text: result.success + ? `Order placed successfully! You have bought ${amount} USD worth of ${outcome} shares in market "${marketResult.market.question}" (ID: ${marketId}) at price $${price} per share. ${result.message || ''}` + : `Sorry, there was an error placing your order: ${result.error}` + }; + + await callback(responseContent); + + return responseContent.text; + } +}; diff --git a/src/actions/redeemWinnings.ts b/src/actions/redeemWinnings.ts new file mode 100644 index 0000000..aa35213 --- /dev/null +++ b/src/actions/redeemWinnings.ts @@ -0,0 +1,115 @@ +import { + type Action, + type IAgentRuntime, + type Memory, + type State, + type Content, + elizaLogger, + HandlerCallback, + logger +} from "@elizaos/core"; +import { ClobService } from "../services/clobService"; +import { RedeemWinningsActionContent } from "../types"; +import { GammaService } from "../services/gammaService"; + +export const redeemWinningsAction: Action = { + name: "POLYMARKET_REDEEM_WINNINGS", + similes: [ + "claim winnings", + "redeem payout", + "collect earnings", + "collect rewards" + ], + description: "Redeems winnings from resolved Polymarket markets", + examples: [ + [ + { + name: "{{user1}}", + content: { text: 'Redeem my winnings from market 138462' }, + }, + { + name: "{{agent}}", + content: { text: 'Successfully redeemed your winnings from market "Will event X happen?". You received 75 USDC.' }, + }, + ], + [ + { + name: "{{user1}}", + content: { text: 'Claim all my winnings from resolved markets' }, + }, + { + name: "{{agent}}", + content: { text: 'Successfully redeemed your winnings from all resolved markets. You received a total of 120 USDC.' }, + }, + ], + ], + + validate: async ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + ): Promise => { + const content = message.content as RedeemWinningsActionContent; + if (!content || !content.text) { + return false; + } + + const text = content.text.toLowerCase(); + + const hasRedeemKeywords = + text.includes("redeem") || + text.includes("claim") || + text.includes("collect") || + text.includes("winnings") || + text.includes("rewards") || + text.includes("payout") || + text.includes("earnings"); + + return hasRedeemKeywords; + }, + + handler: async ( + _runtime: IAgentRuntime, + message: Memory, + _state: State, + _options: any, + callback: HandlerCallback, + _responses: Memory[] + ): Promise => { + const content = message.content as RedeemWinningsActionContent; + const text = content.text.trim(); + + // Check if a specific market ID is provided + const marketIdPattern = /\b\d{6}\b/; + const marketIdMatch = text.match(marketIdPattern); + const marketId = marketIdMatch ? marketIdMatch[0] : content.marketId; + + // If market ID is provided, verify it exists + let marketName = "all resolved markets"; + if (marketId) { + const marketResult = await GammaService.fetchMarketById(marketId); + if (!marketResult.success || !marketResult.market) { + return `Sorry, I couldn't find a market with ID ${marketId} to redeem winnings from. ${marketResult.error || ''}`; + } + marketName = `"${marketResult.market.question}"`; + } + + // Log the redemption attempt + logger.info(`Attempting to redeem winnings${marketId ? ` from market ${marketId}` : ' from all resolved markets'}`); + + // Call the CLOB API to redeem winnings + const result = await ClobService.redeemWinnings({ + marketId: marketId + }); + + const responseContent: Content = { + text: result.success + ? `Successfully redeemed your winnings from ${marketName}. You received ${result.amount} USDC.` + : `Sorry, there was an error redeeming your winnings: ${result.error}` + }; + + await callback(responseContent); + + return responseContent.text; + } +}; diff --git a/src/actions/sellShares.ts b/src/actions/sellShares.ts new file mode 100644 index 0000000..bba8443 --- /dev/null +++ b/src/actions/sellShares.ts @@ -0,0 +1,149 @@ +import { + type Action, + type IAgentRuntime, + type Memory, + type State, + type Content, + elizaLogger, + HandlerCallback, + logger +} from "@elizaos/core"; +import { ClobService } from "../services/clobService"; +import { SellSharesActionContent } from "../types"; +import { GammaService } from "../services/gammaService"; + +export const sellSharesAction: Action = { + name: "POLYMARKET_SELL_SHARES", + similes: [ + "sell shares", + "close position", + "exit market", + "place sell order" + ], + description: "Places an order to sell shares in a specific Polymarket outcome", + examples: [ + [ + { + name: "{{user1}}", + content: { text: 'Sell 50 USD worth of YES shares in market 138462 at price 0.70' }, + }, + { + name: "{{agent}}", + content: { text: 'Order placed successfully! You have sold 50 USD worth of YES shares in "Will event X happen?" market at price $0.70 per share. Order ID: POLY-12345' }, + }, + ], + [ + { + name: "{{user1}}", + content: { text: 'Close my position in market 138462' }, + }, + { + name: "{{agent}}", + content: { text: 'I need a few more details to place your sell order. Could you specify the outcome (YES/NO), amount you want to sell, and the price?' }, + }, + ], + ], + + validate: async ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + ): Promise => { + const content = message.content as SellSharesActionContent; + if (!content || !content.text) { + return false; + } + + const text = content.text.toLowerCase(); + + const hasSellKeywords = + text.includes("sell") || + text.includes("exit") || + text.includes("close position"); + + const hasMarketKeywords = + text.includes("market") || + text.includes("shares") || + text.includes("position") || + /\d{6}/.test(text); // Checks for market ID pattern + + return hasSellKeywords && hasMarketKeywords; + }, + + handler: async ( + _runtime: IAgentRuntime, + message: Memory, + _state: State, + _options: any, + callback: HandlerCallback, + _responses: Memory[] + ): Promise => { + const content = message.content as SellSharesActionContent; + const text = content.text.trim(); + + // Extract market ID + const marketIdPattern = /\b\d{6}\b/; + const marketIdMatch = text.match(marketIdPattern); + const marketId = marketIdMatch ? marketIdMatch[0] : content.marketId; + + if (!marketId) { + return "Sorry, I couldn't identify a market ID in your request. Please specify a market ID."; + } + + // First fetch market details to verify market exists and to display details later + const marketResult = await GammaService.fetchMarketById(marketId); + if (!marketResult.success || !marketResult.market) { + return `Sorry, I couldn't find a market with ID ${marketId}. ${marketResult.error || ''}`; + } + + // Extract outcome (YES/NO) + const outcomePattern = /\b(yes|no)\b/i; + const outcomeMatch = text.match(outcomePattern); + const outcome = outcomeMatch ? outcomeMatch[0].toUpperCase() : content.outcomeId; + + if (!outcome) { + return `Please specify which outcome you want to sell (YES or NO) for market "${marketResult.market.question}".`; + } + + // Extract amount + const amountPattern = /\b(\d+(?:\.\d+)?)\s*(?:USD|USDC|dollars|$)?\b/; + const amountMatch = text.match(amountPattern); + const amount = amountMatch ? amountMatch[1] : content.amount; + + if (!amount) { + return `Please specify the amount you want to sell of ${outcome} shares for market "${marketResult.market.question}".`; + } + + // Extract price + const pricePattern = /(?:price|at)\s*(?:\$)?(\d+(?:\.\d+)?)/i; + const priceMatch = text.match(pricePattern); + const price = priceMatch ? priceMatch[1] : content.price; + + if (!price) { + return `Please specify the price at which you want to sell ${outcome} shares for market "${marketResult.market.question}".`; + } + + // Log the extracted parameters for debugging + logger.info(`Selling ${amount} USD of ${outcome} in market ${marketId} at price ${price}`); + + // Place the order through the CLOB API + const result = await ClobService.placeOrder({ + marketId, + outcomeId: outcome, + side: 'SELL', + amount, + price, + orderType: 'LIMIT' + }); + + const responseContent: Content = { + text: result.success + ? `Order placed successfully! You have sold ${amount} USD worth of ${outcome} shares in market "${marketResult.market.question}" (ID: ${marketId}) at price $${price} per share. ${result.message || ''}` + : `Sorry, there was an error placing your sell order: ${result.error}` + }; + + await callback(responseContent); + + return responseContent.text; + } +}; diff --git a/src/plugin.ts b/src/plugin.ts index 45e42e8..83ee709 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,12 +1,23 @@ import { type Plugin } from '@elizaos/core'; import { GammaService } from './services/gammaService'; +import { ClobService } from './services/clobService'; import { readMarketsAction } from './actions/readMarkets'; import { readMarketAction } from './actions/readMarket'; +import { buySharesAction } from './actions/buyShares'; +import { sellSharesAction } from './actions/sellShares'; +import { redeemWinningsAction } from './actions/redeemWinnings'; const pluginPolymarket: Plugin = { name: 'plugin-polymarket', description: 'Plugin for Polymarket integration', - actions: [readMarketsAction, readMarketAction], + actions: [ + readMarketsAction, + readMarketAction, + buySharesAction, + sellSharesAction, + redeemWinningsAction + ], + services: [GammaService, ClobService], }; export default pluginPolymarket; \ No newline at end of file diff --git a/src/services/clobService.ts b/src/services/clobService.ts new file mode 100644 index 0000000..d7e7625 --- /dev/null +++ b/src/services/clobService.ts @@ -0,0 +1,220 @@ +import { Service, IAgentRuntime, logger } from '@elizaos/core'; +import { + OrderParams, + OrderResult, + RedeemParams, + RedeemResult +} from '../types'; + +/** + * Service for interacting with Polymarket's Central Limit Order Book (CLOB) API + * Handles trading operations like buying, selling and redeeming winnings + */ +export class ClobService extends Service { + static serviceType = 'ClobService'; + static apiUrl = "https://clob-api.polymarket.com"; // Base URL for CLOB API + + static register(runtime: IAgentRuntime): IAgentRuntime { + return runtime; + } + + capabilityDescription = "Enables the agent to trade on Polymarket's CLOB API"; + + constructor(protected runtime: IAgentRuntime) { + super(runtime); + } + + static async start(runtime: IAgentRuntime): Promise { + const service = new ClobService(runtime); + return service; + } + + static async stop(runtime: IAgentRuntime): Promise { + const service = runtime.getService(ClobService.serviceType); + if (!service) { + throw new Error('CLOB service not found'); + } + service.stop(); + } + + async stop() {} + + /** + * Places an order to buy or sell shares + * @param params - Parameters for the order + * @returns Order result with success status and details + */ + static async placeOrder(params: OrderParams): Promise { + // Get API key from environment variables + const apiKey = process.env.POLYMARKET_API_KEY; + + if (!apiKey) { + return { + success: false, + error: "API key not configured. Please set POLYMARKET_API_KEY in your environment." + }; + } + + // Construct the order payload + const payload = { + marketId: params.marketId, + outcomeId: params.outcomeId, + side: params.side, // 'BUY' or 'SELL' + size: params.amount, + price: params.price, + type: params.orderType || 'LIMIT' // Default to limit order + }; + + // Send the request + let response; + let data; + + response = await fetch(`${this.apiUrl}/orders`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }, + body: JSON.stringify(payload) + }).catch(error => { + logger.error("Network error in placeOrder:", error); + return null; + }); + + if (!response) { + return { + success: false, + error: "Network error while connecting to Polymarket API" + }; + } + + if (!response.ok) { + const errorText = await response.text().catch(() => "Unknown error"); + return { + success: false, + error: `Order placement failed: ${response.status} ${errorText}` + }; + } + + data = await response.json().catch(() => null); + if (!data) { + return { + success: false, + error: "Failed to parse API response" + }; + } + + return { + success: true, + orderId: data.orderId, + message: `Successfully placed ${params.side.toLowerCase()} order for ${params.amount} shares at $${params.price}` + }; + } + + /** + * Cancels an existing order + * @param orderId - ID of the order to cancel + * @returns Order cancellation result + */ + static async cancelOrder(orderId: string): Promise { + const apiKey = process.env.POLYMARKET_API_KEY; + + if (!apiKey) { + return { + success: false, + error: "API key not configured. Please set POLYMARKET_API_KEY in your environment." + }; + } + + let response = await fetch(`${this.apiUrl}/orders/${orderId}`, { + method: 'DELETE', + headers: { + 'Authorization': `Bearer ${apiKey}` + } + }).catch(error => { + logger.error("Network error in cancelOrder:", error); + return null; + }); + + if (!response) { + return { + success: false, + error: "Network error while connecting to Polymarket API" + }; + } + + if (!response.ok) { + const errorText = await response.text().catch(() => "Unknown error"); + return { + success: false, + error: `Order cancellation failed: ${response.status} ${errorText}` + }; + } + + return { + success: true, + orderId: orderId, + message: `Successfully cancelled order ${orderId}` + }; + } + + /** + * Redeems winnings from resolved markets + * @param params - Parameters for redemption + * @returns Redemption result + */ + static async redeemWinnings(params: RedeemParams): Promise { + const apiKey = process.env.POLYMARKET_API_KEY; + + if (!apiKey) { + return { + success: false, + error: "API key not configured. Please set POLYMARKET_API_KEY in your environment." + }; + } + + // Construct the redeem payload + const payload = params.marketId ? { marketId: params.marketId } : {}; + + let response = await fetch(`${this.apiUrl}/redeem`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }, + body: JSON.stringify(payload) + }).catch(error => { + logger.error("Network error in redeemWinnings:", error); + return null; + }); + + if (!response) { + return { + success: false, + error: "Network error while connecting to Polymarket API" + }; + } + + if (!response.ok) { + const errorText = await response.text().catch(() => "Unknown error"); + return { + success: false, + error: `Redemption failed: ${response.status} ${errorText}` + }; + } + + const data = await response.json().catch(() => null); + if (!data) { + return { + success: false, + error: "Failed to parse API response" + }; + } + + return { + success: true, + amount: data.amount, + message: `Successfully redeemed winnings: ${data.amount} USDC` + }; + } +}