diff --git a/packages/plugin-depin/README.md b/packages/plugin-depin/README.md index c73e90ab25..f1262f5a8d 100644 --- a/packages/plugin-depin/README.md +++ b/packages/plugin-depin/README.md @@ -30,8 +30,7 @@ Leverage **`@elizaos/plugin-depin`** to seamlessly integrate AI agents with the Add the following to your `.env` file: ```env -MAPBOX_API_KEY=your-mapbox-api-key -NUBILA_API_KEY=your-nubila-api-key +SENTAI_API_KEY=your-sentai-api-key ``` ### Character Configuration @@ -76,14 +75,13 @@ The **DEPIN_PROJECTS** action empowers Eliza agents to interact with and analyze - **Device and Revenue Analysis:** Explore statistics such as device deployment, operational costs, and revenue generation. - **In-depth Queries:** Answer detailed questions about specific DePIN projects by leveraging the rich dataset provided by the DePINScan API. -### Current Weather and Weather Forecast +### Sentient AI -The **CURRENT_WEATHER** action integrates Nubila APIs to provide Eliza agents with weather-related capabilities. Key functionalities include: +The **SENTIENT_AI** action integrates Sentient AI APIs to provide Eliza agents with weather-related capabilities. Key functionalities include: -- **Real-Time Weather Updates:** Deliver current temperature, humidity, and general conditions for specified locations. -- **Forecast Analysis:** Generate short- and long-term forecasts to assist in planning and decision-making. -- **Pattern Recognition:** Analyze weather trends and identify emerging patterns or anomalies. -- **Interactive Content:** Create weather-related insights, summaries, or user-facing content such as memes and visuals. +- **Real-Time Weather Updates:** Deliver current temperature, humidity, and general conditions for specified locations. (supported by Nubila) +- **Forecast Analysis:** Generate short- and long-term forecasts to assist in planning and decision-making. (supported by Nubila) +- **Other Actions** Sentient AI will continue to improve and add more actions based on DePIN data. --- diff --git a/packages/plugin-depin/src/actions/currentWeather.ts b/packages/plugin-depin/src/actions/currentWeather.ts deleted file mode 100644 index 553409666b..0000000000 --- a/packages/plugin-depin/src/actions/currentWeather.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { - Action, - IAgentRuntime, - Memory, - State, - HandlerCallback, - ModelClass, - composeContext, - generateText, - elizaLogger, -} from "@elizaos/core"; - -import { currentWeatherTemplate } from "../template"; -import { parseWeatherAnalysis } from "../parsers"; -import { getWeather } from "../services/weather"; -import { extractLocationAndCoordinates } from "../services/map" - -export const currentWeather: Action = { - name: "CURRENT_WEATHER", - similes: [ - "WEATHER", - "WEATHER_REPORT", - "WEATHER_UPDATE", - ], - description: "Get the current weather for a given location", - validate: async (runtime: IAgentRuntime) => { - const nubilaKey = runtime.getSetting("NUBILA_API_KEY"); - const mapboxKey = runtime.getSetting("MAPBOX_API_KEY"); - if (!nubilaKey || !mapboxKey) { - return false; - } - return true; - }, - examples: [ - [ - { - user: "user", - content: { - text: "What is the weather in Tokyo?", - }, - }, - { - user: "assistant", - content: { - text: "The current weather in Tokyo is 20°C with clear skies.", - action: "CURRENT_WEATHER", - }, - }, - ], - [ - { - user: "user", - content: { - text: "How's the weather looking in New York right now?", - }, - }, - { - user: "assistant", - content: { - text: "In New York City, it's currently 15°C (feels like 13°C) with 65% humidity. Wind speed is 12 km/h and conditions are partly cloudy with a UV index of 3.", - action: "CURRENT_WEATHER", - }, - }, - ], - [ - { - user: "user", - content: { - text: "Tell me about the weather in London", - }, - }, - { - user: "assistant", - content: { - text: "London is experiencing light rain with a temperature of 12°C (feels like 10°C). The pressure is 1015 hPa with 78% humidity and wind speeds of 15 km/h.", - action: "CURRENT_WEATHER", - }, - }, - ], - [ - { - user: "user", - content: { - text: "What are the current conditions in Dubai?", - }, - }, - { - user: "assistant", - content: { - text: "Dubai is hot at 35°C (feels like 38°C) with clear skies. Humidity is at 45%, UV index is 8, and there's a light breeze at 8 km/h.", - action: "CURRENT_WEATHER", - }, - }, - ], - [ - { - user: "user", - content: { - text: "What's the temperature range today in Moscow?", - }, - }, - { - user: "assistant", - content: { - text: "In Moscow, the current temperature is -5°C with a range of -8°C to -3°C today. Light snowfall conditions with 85% humidity and wind speed at 20 km/h.", - action: "CURRENT_WEATHER", - }, - }, - ], - [ - { - user: "user", - content: { - text: "What's the detailed weather report for Sydney?", - }, - }, - { - user: "assistant", - content: { - text: "Sydney's current temperature is 26°C (feels like 28°C), ranging from 22°C to 29°C. Clear sky conditions with 60% humidity, UV index of 9, and coastal winds at 15 km/h.", - action: "CURRENT_WEATHER", - }, - }, - ], - ], - handler: async ( - runtime: IAgentRuntime, - message: Memory, - state: State, - _options: { [key: string]: unknown }, - callback?: HandlerCallback - ): Promise => { - if (!state) { - state = (await runtime.composeState(message)) as State; - } else { - state = await runtime.updateRecentMessageState(state); - } - - try { - const coordinates = await extractLocationAndCoordinates( - state, - runtime - ); - if (!coordinates) { - if (callback) { - callback({ - text: `Coordinates are not available for the given location, please try again`, - content: { error: "No valid location found" }, - }); - } - return false; - } - - const weatherAnalysis = await getAndAnalyzeWeather( - state, - runtime, - coordinates - ); - if (callback) { - callback({ - text: weatherAnalysis, - inReplyTo: message.id, - }); - } - - return true; - } catch (error) { - console.error("Error in current weather plugin:", error); - if (callback) { - callback({ - text: `Error processing request, try again`, - content: { error: error.message }, - }); - } - return false; - } - }, -}; - -async function getAndAnalyzeWeather( - state: State, - runtime: IAgentRuntime, - coordinates: { lat: number; lon: number } -) { - elizaLogger.log("Looking up the weather for coordinates: ", coordinates); - - const weather = await getWeather(runtime, coordinates); - - state.weatherData = JSON.stringify(weather); - - const weatherContext = composeContext({ - state, - template: - // @ts-ignore - runtime.character.templates?.currentWeatherTemplate || - currentWeatherTemplate, - }); - - const weatherText = await generateText({ - runtime, - context: weatherContext, - modelClass: ModelClass.LARGE, - }); - - return parseWeatherAnalysis(weatherText); -} diff --git a/packages/plugin-depin/src/actions/sentientai.ts b/packages/plugin-depin/src/actions/sentientai.ts new file mode 100644 index 0000000000..aee97b0fce --- /dev/null +++ b/packages/plugin-depin/src/actions/sentientai.ts @@ -0,0 +1,107 @@ +import { + Action, + HandlerCallback, + IAgentRuntime, + Memory, + State +} from "@elizaos/core"; + +export const sentientAI: Action = { + name: "SENTIENT_AI", + similes: [ + "SENTIENT", + "NEWS", + "WEATHER" + ], + description: "Provde realtime information for Weather, News.", + examples: [ + [ + { + user: "user", + content: { + text: "What's the weather forecast for Tokyo?", + }, + }, + { + user: "assistant", + content: { + text: "Here's the weather forecast for Tokyo: Tomorrow will be 22°C with partly cloudy skies. The next few days will see temperatures ranging from 18-24°C with a chance of rain on Thursday.", + action: "WEATHER", + }, + }, + ], + [ + { + user: "user", + content: { + text: "Will it rain in London this week?", + }, + }, + { + user: "assistant", + content: { + text: "Looking at London's forecast: There's a 60% chance of rain on Wednesday with temperatures around 15°C. The rest of the week should be mostly cloudy with occasional showers.", + action: "WEATHER", + }, + } + ], + [ + { + user: "user", + content: { + text: "What is the latest news about Trump?", + }, + }, + { + user: "assistant", + content: { + text: "Here are some of the latest news articles related to Trump: Trump invites House Republicans to Mar-a-Lago for strategy meetings.", + action: "NEWS", + }, + }, + ], + ], + validate: async (runtime: IAgentRuntime, message: Memory) => { + // no extra validation needed + return true; + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + options?: { [key: string]: unknown }, + callback?: HandlerCallback + ) => { + try { + const content = message.content; + + const response = await fetch("https://quicksilver.iotex.ai/ask", { + method: "POST", + headers: { + "Content-Type": "application/json", + "API-KEY": runtime.getSetting("SENTAI_API_KEY"), + }, + body: JSON.stringify({ + q: content.text, + }), + }); + + if (!response.ok) { + throw new Error(`API error: ${response.statusText}`); + } + + const res = await response.json(); + + callback({ + text: res.data, + }); + return true; + } catch (error) { + console.error("Error", error.message); + if (callback) { + callback({ text: `Error: ${error.message}` }); + } + return false; + } + }, +}; \ No newline at end of file diff --git a/packages/plugin-depin/src/actions/weatherForecast.ts b/packages/plugin-depin/src/actions/weatherForecast.ts deleted file mode 100644 index 34799c4dee..0000000000 --- a/packages/plugin-depin/src/actions/weatherForecast.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { - Action, - IAgentRuntime, - Memory, - State, - HandlerCallback, - ModelClass, - composeContext, - generateText, - elizaLogger, -} from "@elizaos/core"; - -import { weatherForecastTemplate } from "../template"; -import { parseWeatherForecast } from "../parsers"; -import { getWeatherForecast } from "../services/weather"; -import { extractLocationAndCoordinates } from "../services/map" - -export const weatherForecast: Action = { - name: "WEATHER_FORECAST", - similes: [ - "FORECAST", - "FUTURE_WEATHER", - "UPCOMING_WEATHER", - "WEATHER_PREDICTION", - ], - description: "Get the weather forecast for a given location", - validate: async (runtime: IAgentRuntime) => { - const nubilaKey = runtime.getSetting("NUBILA_API_KEY"); - const mapboxKey = runtime.getSetting("MAPBOX_API_KEY"); - if (!nubilaKey || !mapboxKey) { - return false; - } - return true; - }, - examples: [ - [ - { - user: "user", - content: { - text: "What's the weather forecast for Tokyo?", - }, - }, - { - user: "assistant", - content: { - text: "Here's the weather forecast for Tokyo: Tomorrow will be 22°C with partly cloudy skies. The next few days will see temperatures ranging from 18-24°C with a chance of rain on Thursday.", - action: "WEATHER_FORECAST", - }, - }, - ], - [ - { - user: "user", - content: { - text: "Will it rain in London this week?", - }, - }, - { - user: "assistant", - content: { - text: "Looking at London's forecast: There's a 60% chance of rain on Wednesday with temperatures around 15°C. The rest of the week should be mostly cloudy with occasional showers.", - action: "WEATHER_FORECAST", - }, - }, - ], - ], - handler: async ( - runtime: IAgentRuntime, - message: Memory, - state: State, - _options: { [key: string]: unknown }, - callback?: HandlerCallback - ): Promise => { - if (!state) { - state = (await runtime.composeState(message)) as State; - } else { - state = await runtime.updateRecentMessageState(state); - } - - try { - const coordinates = await extractLocationAndCoordinates( - state, - runtime - ); - - const forecastAnalysis = await getAndAnalyzeForecast( - state, - runtime, - coordinates - ); - - if (callback) { - callback({ - text: forecastAnalysis, - inReplyTo: message.id, - }); - } - - return true; - } catch (error) { - elizaLogger.error("Error in current weather plugin:", error); - if (callback) { - callback({ - text: `Error processing request, try again`, - content: { error: error.message }, - }); - } - return false; - } - }, -}; - -async function getAndAnalyzeForecast( - state: State, - runtime: IAgentRuntime, - coordinates: { lat: number; lon: number } -) { - elizaLogger.log("Looking up the weather for coordinates: ", coordinates); - - const weather = await getWeatherForecast(runtime, coordinates); - - state.weatherForecast = JSON.stringify(weather); - - const weatherContext = composeContext({ - state, - template: - // @ts-ignore - runtime.character.templates?.weatherForecastTemplate || - weatherForecastTemplate, - }); - - const weatherText = await generateText({ - runtime, - context: weatherContext, - modelClass: ModelClass.LARGE, - }); - - return parseWeatherForecast(weatherText); -} diff --git a/packages/plugin-depin/src/index.ts b/packages/plugin-depin/src/index.ts index f07eec5c1c..b0ea3f9bef 100644 --- a/packages/plugin-depin/src/index.ts +++ b/packages/plugin-depin/src/index.ts @@ -2,16 +2,15 @@ import type { Plugin } from "@elizaos/core"; import { depinDataProvider } from "./providers/depinData"; import { depinProjects } from "./actions/depinProjects"; -import { currentWeather } from "./actions/currentWeather"; -import { weatherForecast } from "./actions/weatherForecast"; +import { sentientAI } from "./actions/sentientai"; export const depinPlugin: Plugin = { name: "depin", - description: "DePIN plugin", + description: "DePIN plugin for Sentient AI", providers: [depinDataProvider], evaluators: [], services: [], - actions: [depinProjects, currentWeather, weatherForecast], + actions: [sentientAI, depinProjects], }; export default depinPlugin; diff --git a/packages/plugin-depin/src/parsers/index.ts b/packages/plugin-depin/src/parsers/index.ts deleted file mode 100644 index 3232a58f32..0000000000 --- a/packages/plugin-depin/src/parsers/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -function parseTagContent(text: string, tag: string) { - const pattern = new RegExp(`<${tag}>\\s*([\\s\\S]*?)\\s*<\\/${tag}>`); - const match = text.match(pattern); - if (match && match[1].trim()) { - return match[1].trim(); - } - return null; -} - -export function parseLocation(text: string) { - return parseTagContent(text, "extracted_location"); -} - -export function parseWeatherAnalysis(text: string) { - return parseTagContent(text, "weather_analysis"); -} - -export function parseWeatherForecast(text: string) { - return parseTagContent(text, "weather_forecast_analysis"); -} diff --git a/packages/plugin-depin/src/services/map.ts b/packages/plugin-depin/src/services/map.ts deleted file mode 100644 index 5fa297b2c4..0000000000 --- a/packages/plugin-depin/src/services/map.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - IAgentRuntime, - State, - ModelClass, - composeContext, - generateText, - elizaLogger, -} from "@elizaos/core"; -import axios from "axios"; - -import { locationExtractionTemplate } from "../template"; -import { parseLocation } from "../parsers"; - -export async function getLatLngMapbox( - runtime: IAgentRuntime, - location: string -) { - const apiKey = runtime.getSetting("MAPBOX_API_KEY"); - const apiUrl = `https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(location)}.json?access_token=${apiKey}`; - - try { - const response = await axios.get(apiUrl); - if (!response.data.features?.length) { - return null; // Location not found - } - const [lng, lat] = response.data.features[0].center; - return { lat, lon: lng }; - } catch (error) { - console.error( - "Error fetching coordinates:", - error instanceof Error ? error.message : "Unknown error" - ); - return null; - } -} - -export async function extractLocationAndCoordinates( - state: State, - runtime: IAgentRuntime -) { - const locationExtractionContext = composeContext({ - state, - template: - // @ts-ignore - runtime.character.templates?.locationExtractionTemplate || - locationExtractionTemplate, - }); - const location = await generateText({ - runtime, - context: locationExtractionContext, - modelClass: ModelClass.SMALL, - }); - - const parsedLocation = parseLocation(location); - - elizaLogger.log("Extracted location is: ", parsedLocation); - - return getLatLngMapbox(runtime, parsedLocation); -} diff --git a/packages/plugin-depin/src/services/weather.ts b/packages/plugin-depin/src/services/weather.ts deleted file mode 100644 index c11899f788..0000000000 --- a/packages/plugin-depin/src/services/weather.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { IAgentRuntime } from "@elizaos/core"; -import axios from "axios"; - -import { WeatherData, WeatherForecast, WeatherForcastDP } from "../types/depin"; - -export async function getWeather( - runtime: IAgentRuntime, - coordinates: { lat: number; lon: number } -): Promise { - const apiKey = runtime.getSetting("NUBILA_API_KEY"); - const apiUrl = `https://api.nubila.ai/api/v1/weather?lat=${coordinates.lat}&lon=${coordinates.lon}`; - const response = await axios.get(apiUrl, { - headers: { "x-api-key": apiKey }, - }); - if (response.data.ok) { - return { - ...response.data.data, - parsed_timestamp: new Date( - response.data.data.timestamp * 1000 - ).toISOString(), - }; - } else { - throw new Error("Failed to fetch weather data"); - } -} - -export async function getWeatherForecast( - runtime: IAgentRuntime, - coordinates: { lat: number; lon: number } -): Promise { - const apiKey = runtime.getSetting("NUBILA_API_KEY"); - const apiUrl = `https://api.nubila.ai/api/v1/forecast?lat=${coordinates.lat}&lon=${coordinates.lon}`; - const response = await axios.get(apiUrl, { - headers: { "x-api-key": apiKey }, - }); - if (response.data.ok) { - const forecast = response.data.data.map((item: WeatherForcastDP) => ({ - ...item, - parsed_timestamp: new Date(item.timestamp * 1000).toISOString(), - })); - return forecast; - } else { - throw new Error("Failed to fetch weather forecast data"); - } -} - - diff --git a/packages/plugin-depin/src/test/parsers.test.ts b/packages/plugin-depin/src/test/parsers.test.ts deleted file mode 100644 index 7b2f25695e..0000000000 --- a/packages/plugin-depin/src/test/parsers.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { parseLocation, parseWeatherAnalysis } from "../parsers"; - -describe.only("Parsers", () => { - describe("Location", () => { - it("should parse location", () => { - const location = parseLocation( - "New York" - ); - expect(location).toBe("New York"); - }); - it("should return null if invalid extracted location tag", () => { - const location = parseLocation( - "New York" - ); - expect(location).toBe(null); - }); - it("should return null if no extracted location tag", () => { - const location = parseLocation("New York"); - expect(location).toBe(null); - }); - it("should return null if no location in tags", () => { - const location = parseLocation( - "" - ); - expect(location).toBe(null); - }); - }); - describe("Weather", () => { - it("should parse weather analysis", () => { - const weather = parseWeatherAnalysis( - "Sunny" - ); - expect(weather).toBe("Sunny"); - }); - it("should return null if no weather analysis tag", () => { - const weather = parseWeatherAnalysis("Sunny"); - expect(weather).toBe(null); - }); - it("should return null if no weather analysis in tags", () => { - const weather = parseWeatherAnalysis( - "" - ); - expect(weather).toBe(null); - }); - it("should return null if invalid weather analysis tag", () => { - const weather = parseWeatherAnalysis( - "Sunny" - ); - expect(weather).toBe(null); - }); - }); -}); diff --git a/packages/plugin-depin/src/types/depin.ts b/packages/plugin-depin/src/types/depin.ts index d4a94a22d2..5c156b6339 100644 --- a/packages/plugin-depin/src/types/depin.ts +++ b/packages/plugin-depin/src/types/depin.ts @@ -21,63 +21,3 @@ export type DepinScanProject = { coingecko_id: string; fully_diluted_valuation: string; }; - -export type WeatherData = { - latitude: number; - longitude: number; - temperature: number; - condition: string; - condition_desc: string; - condition_code: number; - temperature_min: number; - temperature_max: number; - feels_like: number; - pressure: number; - humidity: number; - wind_speed: number; - wind_scale: number; - wind_direction: number; - uv: number; - luminance: number; - elevation: number; - rain: number; - wet_bulb: number; - timestamp: number; - parsed_timestamp: string; - timezone: number; - location_name: string; - address: string; - source: string; - tag: string; - is_online: boolean; - is_malfunction: boolean; -}; - -export type WeatherForecast = WeatherForcastDP[]; - -export type WeatherForcastDP = { - latitude: number; - longitude: number; - temperature: number; - condition: string; - condition_desc: string; - condition_code: number; - temperature_min: number; - temperature_max: number; - feels_like: number; - pressure: number; - humidity: number; - wind_speed: number; - wind_direction: number; - uv: number; - luminance: number; - sea_level: number; - rain: number; - wet_bulb: number; - timestamp: number; - parsed_timestamp: string; - timezone: number; - location_name: string; - source: string; - tag: string; -};