diff --git a/components/components.module.css b/components/components.module.css index f69f320f8..a25b42c5f 100644 --- a/components/components.module.css +++ b/components/components.module.css @@ -183,3 +183,17 @@ font-weight: 400; line-height: 20px; } + +.mainTitleHeading { + color: var(--Indigo-Indigo-900---Fetch-navy, #000d3d); + font-family: Lexend; + font-size: 24px; + font-style: normal; + font-weight: 400; + line-height: 140%; + letter-spacing: -0.24px; +} + +:is(html[class~="dark"] .mainTitleHeading) { + color: #e9e9ea; +} diff --git a/components/feature-guide-tabs.tsx b/components/feature-guide-tabs.tsx index ab03ec1a1..2af85154f 100644 --- a/components/feature-guide-tabs.tsx +++ b/components/feature-guide-tabs.tsx @@ -1,6 +1,7 @@ -import React, { useEffect, useState } from "react"; +import React, { useState, useEffect } from "react"; import styles from "./tab.module.css"; import { useRouter } from "next/router"; +import Link from "next/link"; export const GuideBox = ({ content, @@ -42,6 +43,50 @@ export const GuideBox = ({ ); }; +const FeaturedGuidesTab = ({ + item, +}: { + item: { type: string; title: string; path: string; label: string }; +}) => { + return ( +
+
+ {item.type} + {item.title} +
+
{item.label}
+
+ ); +}; + +export const FeaturedGuides = ({ + featuredGuidesData, +}: { + featuredGuidesData: { + type: string; + title: string; + path: string; + label: string; + }[]; +}) => { + return ( +
+
Featured guides
+
+ {featuredGuidesData?.map((item, index) => ( + + + + ))} +
+
+ ); +}; + export const FeatureGuideTabs = ({ centerMode }: { centerMode?: boolean }) => { const [activeTab, setActiveTab] = useState(0); const [isMobile, setIsMobile] = useState(false); diff --git a/components/guide-mdx.tsx b/components/guide-mdx.tsx index b343f5db9..0c46a495d 100644 --- a/components/guide-mdx.tsx +++ b/components/guide-mdx.tsx @@ -20,6 +20,10 @@ interface GuideCategory { interface GuidesData { content: GuideCategory[]; + components?: { + featuredGuides?: ReactNode; + }; + mainHeading?: string; } const pathLabels = new Map([ @@ -37,7 +41,7 @@ const getPathLabel = (path: string): string => { return ""; }; -const SectionHeading = ({ +export const SectionHeading = ({ heading, icon, }: { @@ -145,7 +149,7 @@ const SearchInput = ({ ); -const GuidesMdx = ({ content }: GuidesData) => { +const GuidesMdx = ({ content, components, mainHeading }: GuidesData) => { const [filterState, setFilterState] = useState({ value: "All Types", inputVal: "", @@ -214,7 +218,11 @@ const GuidesMdx = ({ content }: GuidesData) => { onInputChange={onInputChange} /> + {components && components.featuredGuides}
+ + {mainHeading && mainHeading} + {filteredContent.map((items, index) => (
bool: @@ -90,9 +118,10 @@ def in_service_region( return in_range + @cleaning_proto.on_message(model=ServiceRequest, replies=ServiceResponse) async def handle_query_request(ctx: Context, sender: str, msg: ServiceRequest): - provider = await Provider.filter(name=ctx.name).first() + provider = await Provider.filter(name=ctx.agent.name).first() availability = await Availability.get(provider=provider) services = [int(service.type) for service in await provider.services] markup = provider.markup @@ -102,11 +131,11 @@ async def handle_query_request(ctx: Context, sender: str, msg: ServiceRequest): ctx.logger.info(f"Received service request from user `{user.name}`") if ( - set(msg.services) <= set(services) - and in_service_region(msg.location, availability, provider) - and availability.time_start <= msg.time_start - and availability.time_end >= msg.time_start + msg.duration - and availability.min_hourly_price * msg_duration_hours < msg.max_price + set(msg.services) <= set(services) + and in_service_region(msg.location, availability, provider) + and availability.time_start <= msg.time_start + and availability.time_end >= msg.time_start + msg.duration + and availability.min_hourly_price * msg_duration_hours < msg.max_price ): accept = True price = markup * availability.min_hourly_price * msg_duration_hours @@ -118,9 +147,10 @@ async def handle_query_request(ctx: Context, sender: str, msg: ServiceRequest): await ctx.send(sender, ServiceResponse(accept=accept, price=price)) + @cleaning_proto.on_message(model=ServiceBooking, replies=BookingResponse) async def handle_book_request(ctx: Context, sender: str, msg: ServiceBooking): - provider = await Provider.filter(name=ctx.name).first() + provider = await Provider.filter(name=ctx.agent.name).first() availability = await Availability.get(provider=provider) services = [int(service.type) for service in await provider.services] @@ -129,10 +159,10 @@ async def handle_book_request(ctx: Context, sender: str, msg: ServiceBooking): ctx.logger.info(f"Received booking request from user `{user.name}`") success = ( - set(msg.services) <= set(services) - and availability.time_start <= msg.time_start - and availability.time_end >= msg.time_start + msg.duration - and msg.price <= availability.min_hourly_price * msg_duration_hours + set(msg.services) <= set(services) + and availability.time_start <= msg.time_start + and availability.time_end >= msg.time_start + msg.duration + and msg.price <= availability.min_hourly_price * msg_duration_hours ) if success: @@ -342,3 +372,49 @@ if __name__ == "__main__": ``` + +### Poetry Dependencies + +```pyproject.toml copy filename="pyproject.toml" +[tool.poetry.dependencies] +python = ">=3.9,<3.13" +uagents = "^0.17.1" +tortoise-orm = "^0.22.1" +geopy = "^2.4.1" +``` + +#### Instructions to execute the example. + +- Navigate to the root folder of the example. +- Install dependencies by running `poetry install`. +- Run the cleaner agent with `python cleaner.py`. +- Run the user agent with `python user.py`. + +### Expected Output + +- Cleaner Agent + +``` +INFO: [cleaner]: Registration on Almanac API successful +INFO: [cleaner]: Registering on almanac contract... +INFO: [cleaner]: Registering on almanac contract...complete +INFO: [cleaner]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8001&address=agent1qdfdx6952trs028fxyug7elgcktam9f896ays6u9art4uaf75hwy2j9m87w +INFO: [cleaner]: Starting server on http://0.0.0.0:8001 (Press CTRL+C to quit) +INFO: [cleaner]: Received service request from user `user` +INFO: [cleaner]: I am available! Proposing price: 22.0. +INFO: [cleaner]: Received booking request from user `user` +INFO: [cleaner]: Accepted task and updated availability. +``` + +- User Agent: + +``` +INFO: [ user]: Registration on Almanac API successful +INFO: [ user]: Registering on almanac contract... +INFO: [ user]: Registering on almanac contract...complete +INFO: [ user]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8000&address=agent1qvrskj36y7urk2j9g4gu5hjgwvgr8v6jegm5druawmrpztmjjnep6ssn45p +INFO: [ user]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit) +INFO: [ user]: Requesting cleaning service: user='user' location='London Kings Cross' time_start=datetime.datetime(2023, 4, 10, 16, 0, tzinfo=) duration=datetime.timedelta(seconds=14400) services=[, ] max_price=60.0 +INFO: [ user]: Cleaner is available, attempting to book now +INFO: [ user]: Booking was successful +``` \ No newline at end of file diff --git a/pages/examples/intermediate/table-booking-demo.mdx b/pages/examples/intermediate/table-booking-demo.mdx index b6616e1f9..a5e5aa225 100644 --- a/pages/examples/intermediate/table-booking-demo.mdx +++ b/pages/examples/intermediate/table-booking-demo.mdx @@ -7,7 +7,7 @@ import { CodeGroup, DocsCode } from "../../../components/code" This file can be run on any platform supporting Python, with the necessary install permissions. This example shows how to use Agents to create a table booking service at a restaurant. -### Supporting documentation +## Supporting documentation - [Creating an agent ↗️](/guides/agents/create-a-uagent) - [Creating an interval task ↗️](/guides/agents/interval-task) @@ -17,6 +17,22 @@ This example shows how to use Agents to create a table booking service at a rest - [Protocols ↗️](/references/uagents/uagents-protocols/agent-protocols) - [Agents address ↗️](/guides/agents/getting-started/getting-uagent-address) +## Project Structure + +Outline of basic structure of the project: + +``` +table-booking-demo/ +. +├── protocols/ +│ ├── query.py +│ └── book.py +│ +└── agents/ + ├── restaurant.py + └── user.py +``` + ### The Protocols #### Query table @@ -416,8 +432,10 @@ This example shows how to use Agents to create a table booking service at a rest - Restaurant: ``` + INFO: [restaurant]: Registration on Almanac API successful INFO: [restaurant]: Registering on almanac contract... INFO: [restaurant]: Registering on almanac contract...complete + INFO: [cleaner]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8001&address=agent1qdfdx6952trs028fxyug7elgcktam9f896ayu9art4uaf75hwy2j9m87w INFO: [restaurant]: Starting server on http://0.0.0.0:8001 (Press CTRL+C to quit) INFO: [restaurant]: Query: guests=3 time_start=19 duration=2. Available tables: [2]. ``` @@ -425,8 +443,10 @@ This example shows how to use Agents to create a table booking service at a rest - User: ``` + INFO: [ user]: Registration on Almanac API successful INFO: [ user]: Registering on almanac contract... INFO: [ user]: Registering on almanac contract...complete + INFO: [ user]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8000&address=agent1qvrskj36y7urk2j9g4gujgwvgr8v6jegm5druawmrpztmjjnep6ssn45p INFO: [ user]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: [ user]: There is a free table, attempting to book one now INFO: [ user]: Table reservation was successful diff --git a/pages/guides.mdx b/pages/guides.mdx index 31c4f9b91..b6f5159ab 100644 --- a/pages/guides.mdx +++ b/pages/guides.mdx @@ -5,9 +5,57 @@
import GuidesMdx from "../components/guide-mdx" +import {FeaturedGuides} from "../components/feature-guide-tabs" import { AgentsIcon, AgentverseIcon, CliIcon,FetchNetwork, AsiIcon, LedgerIcon } from "src/icons/main-page-icons"; - + } + } + mainHeading={"Explore all guides"} + content={ [ { type: "Agents", icon: AgentsIcon, diff --git a/styles/globals.css b/styles/globals.css index 53934a29a..2cb72715a 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -3120,7 +3120,7 @@ article details > summary::-webkit-details-marker { article details > summary:before { vertical-align: -4px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='w-5 h-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); width: 1.2em; height: 1.2em; }