diff --git a/.devcontainer/074-AIWithConfluentOnAzure/devcontainer.json b/.devcontainer/074-AIWithConfluentOnAzure/devcontainer.json new file mode 100644 index 0000000000..33b15f57ff --- /dev/null +++ b/.devcontainer/074-AIWithConfluentOnAzure/devcontainer.json @@ -0,0 +1,33 @@ +{ + "image": "mcr.microsoft.com/devcontainers/python:3.12-bookworm", + "workspaceFolder": "/workspace/074-AIWithConfluentOnAzure/Student/Resources", + "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", + "hostRequirements": { + "cpus": 2, + "memory": "4gb" + }, + "waitFor": "onCreateCommand", + "updateContentCommand": "python3 -m pip install -r requirements.txt", + "postCreateCommand": "", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/azure-cli:1": {}, + "ghcr.io/devcontainers/features/terraform:1": {} + }, + "customizations": { + "codespaces": { + "openFiles": [] + }, + "vscode": { + "extensions": [ + "ms-toolsai.jupyter", + "ms-python.python", + "github.copilot", + "github.copilot-chat", + "HashiCorp.terraform", + "humao.rest-client", + "ms-azuretools.vscode-docker" + ] + } + } + } diff --git a/.gitignore b/.gitignore index c2fd5482d4..dac96335f9 100644 --- a/.gitignore +++ b/.gitignore @@ -333,4 +333,35 @@ ASALocalRun/ .mfractor/ .DS_Store -.env \ No newline at end of file +.env + + +shared_environment_variables.sh +shared_environment_variables.env + +.env.sh + +# Confluent Ignores +*confluent-environment* +*confluent-environment.sh + +# Terraform Stuff +terraform.tfstate.backup +.terraform +*.tfstate +.terraform* +azure_environment_variables.sh +main_variables.tf +microsoft_hackathon.plan + +# Othe files from Python and Node +.cosmos_permissions +DRAFT.txt +node_modules +.idea +.vscode +.project +__pycache__ +*.final.json + + diff --git a/074-AIWithConfluentOnAzure/.wordlist.txt b/074-AIWithConfluentOnAzure/.wordlist.txt new file mode 100644 index 0000000000..80ddf9d42b --- /dev/null +++ b/074-AIWithConfluentOnAzure/.wordlist.txt @@ -0,0 +1,8 @@ +Flink +DDL +DML +Confluent +Confluent's +ksqlDB +replenishments +upsert diff --git a/074-AIWithConfluentOnAzure/Coach/Lectures.pptx b/074-AIWithConfluentOnAzure/Coach/Lectures.pptx new file mode 100644 index 0000000000..34cfe52f45 Binary files /dev/null and b/074-AIWithConfluentOnAzure/Coach/Lectures.pptx differ diff --git a/074-AIWithConfluentOnAzure/Coach/README.md b/074-AIWithConfluentOnAzure/Coach/README.md new file mode 100644 index 0000000000..cb8ba79faa --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/README.md @@ -0,0 +1,71 @@ +# What The Hack - AI With Confluent On Azure - Coach Guide + +## Introduction + +Welcome to the coach's guide for the AI With Confluent On Azure What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. + +This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. + +**NOTE:** If you are a Hackathon participant, this is the answer guide. Don't cheat yourself by looking at these during the hack! Go learn something. :) + +## Coach's Guides + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** + - Prepare Azure and Confluent Cloud environments with required infrastructure +- Challenge 01: **[Build the Flink Data Pipeline](./Solution-01.md)** + - Create streaming data pipeline that merges multiple data streams using Apache Flink +- Challenge 02: **[Supplier Experience](./Solution-02.md)** + - Interact with the AI agent as a supplier to query and replenish inventory +- Challenge 03: **[Customer Experience](./Solution-03.md)** + - Simulate customer purchases and returns with real-time inventory updates +- Challenge 04: **[Employee Experience](./Solution-04.md)** + - Access comprehensive operational insights across all transactions + +## Coach Prerequisites + +This hack has pre-reqs that a coach is responsible for understanding and/or setting up BEFORE hosting an event. Please review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for information on how to host a hack event. + +The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. + +### Student Resources + +Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. + +Always refer students to the [What The Hack website](https://aka.ms/wth) for the student guide: [https://aka.ms/wth](https://aka.ms/wth) + +**NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. + +### Additional Coach Prerequisites + +- Ensure you have a Confluent Cloud account with permissions to create Kafka clusters, topics, and connectors. +- Pre-provision or verify access to the required Azure services: Azure OpenAI, Azure Cosmos DB, Azure AI Search, Azure Redis Cache, and Azure Storage Account. +- Test the Terraform modules in the `Student/Resources/terraform` folder to ensure they deploy successfully in your target environment. + +## Azure Requirements + +This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. + +- Azure subscription with Owner access +- Ability to create the following resources: Azure OpenAI, Azure Cosmos DB, Azure AI Search, Azure Redis Cache, Azure Storage Account +- Sufficient quota for Azure OpenAI model deployments + +## Suggested Hack Agenda + +- Challenge 00 (1 hour) - Prerequisites and infrastructure provisioning +- Challenge 01 (1.5 hours) - Build the Flink Data Pipeline +- Challenge 02 (1 hour) - Supplier Experience +- Challenge 03 (1 hour) - Customer Experience +- Challenge 04 (1 hour) - Employee Experience + +## Repository Contents + +- `./Coach` + - Coach's Guide and related files +- `./Coach/Solutions` + - Solution files with completed example answers to a challenge +- `./Coach/Lectures.pptx` + - Optional lecture presentations for each challenge +- `./Student` + - Student's Challenge Guide +- `./Student/Resources` + - Terraform modules, configuration scripts, AI agent application code, and connector configurations meant to be provided to students (must be packaged up by the coach and provided to students at start of event) diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-00.md b/074-AIWithConfluentOnAzure/Coach/Solution-00.md new file mode 100644 index 0000000000..1f358e3ef5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-00.md @@ -0,0 +1,18 @@ +# Challenge 00 - Prerequisites - Ready, Set, GO! - Coach's Guide + +**[Home](./README.md)** - [Next Solution >](./Solution-01.md) + +## Notes & Guidance + +Ensure students have all prerequisites installed before proceeding: + +- Verify students have Azure CLI, Terraform CLI, and Confluent CLI installed and authenticated +- Students should extract the Resources.zip file and navigate to the Terraform directory +- The Terraform modules require Azure subscription ID, principal IDs, and Confluent API keys to be set in the variables files +- Run `terraform init` followed by `terraform plan` and `terraform apply` to deploy all infrastructure +- Common issues: + - Insufficient Azure permissions or quota limits for Azure OpenAI + - Missing or incorrect Confluent Cloud API keys + - Terraform state lock issues if multiple students share a subscription +- After deployment, verify all connectors are in a "Running" state in Confluent Cloud +- Confirm the MCP-powered AI agent responds when prompted with its name and can list the eight grocery store departments diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-01.md b/074-AIWithConfluentOnAzure/Coach/Solution-01.md new file mode 100644 index 0000000000..19df90c6e3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-01.md @@ -0,0 +1,21 @@ +# Challenge 01 - Build the Flink Data Pipeline - Coach's Guide + +[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) + +## Notes & Guidance + +Students need to connect to the Apache Flink SQL editor in Confluent Cloud and create Flink tables mapped to existing Kafka topics. + +- Students must create Flink tables for all six topics: `product_sku`, `product_pricing`, `product_departments`, `purchases`, `returns`, and `replenishments` +- The merge logic for `net_sales` should: + - Add purchase amounts to the running total per SKU + - Subtract return amounts from the running total per SKU +- The merge logic for `net_inventory_count` should: + - Subtract purchase quantities from inventory per SKU + - Add replenishment quantities to inventory per SKU + - For returns: only add back to inventory if the product belongs to the appliance department; ignore returns from all other departments +- Reference Flink SQL solutions are available in the `Coach/Solutions/flink-sql` folder +- Common issues: + - Students may forget to handle the appliance department return logic + - Schema mismatches between Kafka topic schemas and Flink table definitions + - Flink SQL statements must be running continuously; verify they are active in the Confluent Cloud UI diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-02.md b/074-AIWithConfluentOnAzure/Coach/Solution-02.md new file mode 100644 index 0000000000..6ff9b4981c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-02.md @@ -0,0 +1,14 @@ +# Challenge 02 - Supplier Experience - Coach's Guide + +[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) + +## Notes & Guidance + +Students interact with the supplier agent to query and replenish inventory. + +- The supplier agent should display real-time inventory levels per SKU and per department +- When a student replenishes inventory, the change should be reflected in the `net_inventory_count` table and subsequently in Azure AI Search +- Verify students confirm that the AI agent retrieves updated values from MCP services after replenishment actions +- Common issues: + - Delays in data propagation from Kafka through Flink to Azure AI Search; allow a few seconds for updates + - If the agent returns stale data, check that the Flink SQL merge statements are running and the sink connector to Azure AI Search is active diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-03.md b/074-AIWithConfluentOnAzure/Coach/Solution-03.md new file mode 100644 index 0000000000..5813689152 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-03.md @@ -0,0 +1,15 @@ +# Challenge 03 - Customer Experience - Coach's Guide + +[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) + +## Notes & Guidance + +Students simulate customer purchases and returns and observe real-time inventory and sales updates. + +- Students should record inventory levels before and after purchases/returns to validate the pipeline +- After a purchase, inventory should decrease and net sales should increase +- After a return, net sales should decrease; inventory should only increase if the returned product belongs to the appliance department +- The three-second update window is a guideline; slight delays are acceptable but data should converge quickly +- Common issues: + - Students may not observe updates if the sink connector to Azure AI Search has fallen behind + - Remind students to check both the `net_sales` and `net_inventory_count` values after each action diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-04.md b/074-AIWithConfluentOnAzure/Coach/Solution-04.md new file mode 100644 index 0000000000..c1a11340c2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-04.md @@ -0,0 +1,16 @@ +# Challenge 04 - Employee Experience - Coach's Guide + +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** + +## Notes & Guidance + +Students use the employee agent to access comprehensive operational insights across all transactions. + +- This challenge requires students to use multiple personas simultaneously (customer, supplier, and employee) +- The employee agent should display inventory levels, cumulative purchase/return/replenishment units, and net sales for any SKU +- Students should trigger events from customer and supplier agents and then verify the employee agent reflects those changes +- All data shown by the employee agent should match what is observed in Azure AI Search and Flink output +- Common issues: + - Students may have difficulty managing multiple browser tabs or windows for different personas + - If cumulative values are incorrect, verify the Flink SQL merge logic from Challenge 01 is running correctly + - Ensure the sink connector is actively pushing updates to Azure AI Search diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep b/074-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md new file mode 100644 index 0000000000..758eab2454 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md @@ -0,0 +1,33 @@ + +## Data Pipeline Overview + +The goal of the pipeline is to ensure that +- the data from the source data stores (Cosmos DB) flows into Kafka topics +- the data from the topics are joined and merged into transient tables +- the data from the transient tables to finalized into the summary topics and tables +- the data from the summary tables and pushed out to Azure AI search for the AI agent to use via MCP + +### Steps to Follow + +You will need to run each DDL statement first to set up the Flink Tables. + +Note that each Flink table also maps to a Kafka Topic in Confluent cloud. You can browse these topics as well to see the raw data in the topics. + +You will then need to run the DML statements to pull data from various topics/tables and push them to the final tables that will go out to Azure AI Search via the sink connectors. + +### Location of SQL Statements + +The DDL statements are in this folder. Run them one at a time in the Flink SQL Workspace in Confluent Cloud. + +It would be nice to run these from the Confluent CLI. + +The DML statements that pull from single or multiple sources/topics into the final topics/tables are also available in this folder + +### AI Search Sink Configuration + +Make sure that the topics in the AI Search Sink connector matches the corresponding final topic/table. + +Make sure that the AI Search index name is also correct. The MCP service depends on this correctness to fetch the correct data. + + + diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql new file mode 100644 index 0000000000..f6ea244cb5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql @@ -0,0 +1,50 @@ + + +CREATE TABLE `product_inventory_depot` ( + `key` STRING NOT NULL, + `department` STRING NOT NULL, + `description` STRING NOT NULL, + `inventory_level` DOUBLE NOT NULL, + `name` STRING NOT NULL, + `sku_id` STRING NOT NULL, + `unit_price` DOUBLE NOT NULL, + PRIMARY KEY (`key`) NOT ENFORCED +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'upsert', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + + +CREATE TABLE `net_sales_depot` ( + `key` STRING NOT NULL, + `department` STRING NOT NULL COMMENT 'Department of the Product', + `name` STRING NOT NULL COMMENT 'Name of the Product', + `net_sales` DOUBLE NOT NULL COMMENT 'Net sales amount for the transaction.', + `sku_id` STRING NOT NULL COMMENT 'Unique identifier for the stock keeping unit (SKU).', + PRIMARY KEY (`key`) NOT ENFORCED +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'upsert', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql new file mode 100644 index 0000000000..3bffd6ff6f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql @@ -0,0 +1,97 @@ +--- Set State TTL +SET 'sql.state-ttl' = '2 d'; + +INSERT INTO `departments_flat` +SELECT `department` AS `row_key`, `department`, `description` FROM `departments`; + + +INSERT INTO `purchases_flat` +SELECT + CAST(CAST(i.sku_id AS STRING) AS VARBINARY(2147483647)) AS key_column, + p.customer_id, + i.discounts, + p.receipt_id, + i.sku_id, + p.transaction_date, + i.unit_price, + i.units +FROM `purchases` AS p +CROSS JOIN UNNEST(p.items) AS i (discounts, sku_id, unit_price, units); + +INSERT INTO `returns_flat` +SELECT + CAST(CAST(i.sku_id AS STRING) AS VARBINARY(2147483647)) AS key_column, + r.customer_id, + r.receipt_id, + i.sku_id, + r.transaction_date, + i.unit_price, + i.units +FROM `returns` AS r +CROSS JOIN UNNEST(r.items) AS i (sku_id, unit_price, units); + +INSERT INTO `replenishments_flat` +SELECT + CAST(CAST(r.sku_id AS STRING) AS VARBINARY(2147483647)) AS key_column, + r.replenishment_id, + r.sku_id, + r.transaction_date, + r.units, + r.vendor_id +FROM `replenishments` AS r; + +--- Available Units Computed from Cummulative replenishments, purchases and returns +INSERT INTO `product_inventory_depot` +SELECT + ps.sku_id AS key_column, + ps.department, + ps.description, + -- Available Units = Cummulative (Replenishments + Returns) - Purchases + (IFNULL(SUM(rp.units), 0.00) + IFNULL(SUM(rt.units),0.00) - IFNULL(SUM(pc.units),0.00)) AS inventory_level, + ps.name, + ps.sku_id, + pp.unit_price +FROM product_skus AS ps +INNER JOIN product_pricing AS pp + ON ps.sku_id = pp.sku_id +INNER JOIN departments AS d + ON ps.department = d.department +LEFT JOIN purchases_flat AS pc + ON ps.sku_id = pc.sku_id +LEFT JOIN replenishments_flat AS rp + ON ps.sku_id = rp.sku_id +LEFT JOIN returns_flat AS rt + -- other departments besides the 'appliance' dept cannot be restocked into available inventory + ON ps.sku_id = rt.sku_id AND ps.department = 'appliance' +GROUP BY + ps.sku_id, + ps.name, + pp.unit_price, + ps.description, + ps.department; + + +--- NET_SALES numbers computed from Cummulative Purchases minus Returns +INSERT INTO `net_sales_depot` +SELECT + ps.sku_id AS key_column, + ps.department, + ps.name, + -- Net Sales = (Purchases - Returns) + (IFNULL(SUM(pc.units * pc.unit_price),0.00) - IFNULL(SUM(rt.units * rt.unit_price),0.00)) AS net_sales, + ps.sku_id +FROM product_skus AS ps +INNER JOIN product_pricing AS pp + ON ps.sku_id = pp.sku_id +INNER JOIN departments AS d + ON ps.department = d.department +LEFT JOIN purchases_flat AS pc + ON ps.sku_id = pc.sku_id +LEFT JOIN returns_flat AS rt + ON ps.sku_id = rt.sku_id +GROUP BY + ps.sku_id, + ps.name, + pp.unit_price, + ps.description, + ps.department; \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql new file mode 100644 index 0000000000..6518e8ef98 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql @@ -0,0 +1,18 @@ +CREATE TABLE `departments_source` ( + `department` STRING NOT NULL, + `description` STRING NOT NULL +) +DISTRIBUTED BY HASH(`key`) INTO 6 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'topic' = 'departments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql new file mode 100644 index 0000000000..552747ed6b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql @@ -0,0 +1,19 @@ +CREATE TABLE `departments` ( + `key` STRING NOT NULL, + `department` STRING NOT NULL, + `description` STRING NOT NULL +) +DISTRIBUTED BY HASH(`key`) INTO 6 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'topic' = 'departments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql new file mode 100644 index 0000000000..cf17ea3b57 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql @@ -0,0 +1,4 @@ + +INSERT INTO `departments_flat` +SELECT `department` AS `row_key`, `department`, `description` FROM `departments` + diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql new file mode 100644 index 0000000000..91c67b8063 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql @@ -0,0 +1,109 @@ + +-- Flat table definitions for purchases, returns, and replenishments +CREATE TABLE `purchases_flat` ( + `key` VARBINARY(2147483647), + `customer_id` VARCHAR(2147483647) NOT NULL COMMENT 'Unique identifier for the customer making the purchase.', + `discounts` DOUBLE NOT NULL COMMENT 'Total discounts applied to the item.', + `receipt_id` VARCHAR(2147483647) NOT NULL COMMENT 'Identifier associated with the transaction receipt.', + `sku_id` VARCHAR(2147483647) NOT NULL COMMENT 'SKU identifier for the purchased item.', + `transaction_date` VARCHAR(2147483647) NOT NULL COMMENT 'Date and time of the transaction in ''YYYY-MM-DD HH:MM:SS'' format.', + `unit_price` DOUBLE NOT NULL COMMENT 'Price per unit of the item.', + `units` DOUBLE NOT NULL COMMENT 'Number of units purchased.' +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'raw', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE `returns_flat` ( + `key` VARBINARY(2147483647), + `customer_id` VARCHAR(2147483647) NOT NULL COMMENT 'Unique identifier for the customer making the return.', + `receipt_id` VARCHAR(2147483647) NOT NULL COMMENT 'Identifier associated with the transaction receipt.', + `sku_id` VARCHAR(2147483647) NOT NULL COMMENT 'SKU identifier for the returned item.', + `transaction_date` VARCHAR(2147483647) NOT NULL COMMENT 'Date and time of the transaction in ''YYYY-MM-DD HH:MM:SS'' format.', + `unit_price` DOUBLE NOT NULL COMMENT 'Price per unit of the item.', + `units` DOUBLE NOT NULL COMMENT 'Number of units returns.' +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'raw', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE `replenishments_flat` ( + `key` VARBINARY(2147483647), + `replenishment_id` VARCHAR(2147483647) NOT NULL COMMENT 'Identifier associated with the transaction receipt.', + `sku_id` VARCHAR(2147483647) NOT NULL COMMENT 'SKU identifier for the returned item.', + `transaction_date` VARCHAR(2147483647) NOT NULL COMMENT 'Date and time of the transaction in ''YYYY-MM-DD HH:MM:SS'' format.', + `units` DOUBLE NOT NULL COMMENT 'Number of units returns.', + `vendor_id` VARCHAR(2147483647) NOT NULL COMMENT 'Unique identifier for the customer making the return.' +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'raw', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +INSERT INTO `replenishments_flat` +SELECT + r.sku_id AS `key`, + r.replenishment_id, + r.sku_id, + r.transaction_date, + r.units, + r.vendor_id +FROM `replenishments` AS r; + +INSERT INTO `purchases_flat` +SELECT + i.sku_id, AS `key`, + p.customer_id, + i.discounts, + p.receipt_id, + i.sku_id, + p.transaction_date, + i.unit_price, + i.units +FROM `purchases` AS p +CROSS JOIN UNNEST(p.items) AS i (sku_id, units, unit_price, discounts); + +INSERT INTO `returns_flat` +SELECT + i.sku_id, AS `key`, + r.customer_id, + r.receipt_id, + i.sku_id, + r.transaction_date, + i.unit_price, + i.units +FROM `returns` AS r +CROSS JOIN UNNEST(r.items) AS i (sku_id, units, unit_price); + diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql new file mode 100644 index 0000000000..c81dc2c835 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql @@ -0,0 +1,10 @@ +CREATE TABLE product_skus ( + id STRING, + sku_id STRING, + name STRING, + description STRING, + department STRING +) WITH ( + 'changelog.mode' = 'append', + 'scan.startup.mode' = 'earliest-offset' +); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql new file mode 100644 index 0000000000..cca613833a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql @@ -0,0 +1,36 @@ +-- Create a flattened view of the purchases + +CREATE TABLE `purchases_flat` ( + customer_id STRING, + receipt_id STRING, + transaction_date VARCHAR(2147483647), + sku_id STRING, + units DOUBLE NOT NULL, + unit_price DOUBLE, + discounts DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +-- Insert into the purchases_flat table + +INSERT INTO `purchases_flat` +SELECT + p.customer_id, + p.receipt_id, + p.transaction_date, + i.sku_id, + i.units, + i.unit_price, + i.discounts +FROM purchases AS p +CROSS JOIN UNNEST(p.items) AS i (sku_id, units, unit_price, discounts); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql new file mode 100644 index 0000000000..8e1b21907e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql @@ -0,0 +1,29 @@ +-- Create a flattened view of the replenishments +CREATE TABLE `replenishments_flat` ( + replenishment_id STRING, + vendor_id STRING, + transaction_date VARCHAR(2147483647), + sku_id STRING, + units DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +-- Insert into the replenishments_flat table +INSERT INTO `replenishments_flat` +SELECT + r.replenishment_id, + r.vendor_id, + r.transaction_date, + r.sku_id, + r.units +FROM `replenishments` AS r; \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql new file mode 100644 index 0000000000..59474f500c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql @@ -0,0 +1,125 @@ +CREATE TABLE departments ( + `department` STRING, + `description` STRING +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'departments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE product_skus ( + id STRING, + sku_id STRING, + name STRING, + description STRING, + department STRING +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'product_skus', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE product_pricing ( + id STRING, + sku_id STRING, + unit_price DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'product_pricing', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE purchases ( + id STRING, + receipt_id STRING, + transaction_date STRING, + customer_id STRING, + items ARRAY> +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'purchases', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE returns ( + id STRING, + return_id STRING, + receipt_id STRING, + transaction_date STRING, + customer_id STRING, + items ARRAY> +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'returns', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE replenishments ( + id STRING, + replenishment_id STRING, + transaction_date STRING, + sku_id STRING, + units DOUBLE, + vendor_id STRING +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'replenishments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql new file mode 100644 index 0000000000..5563c7fc37 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql @@ -0,0 +1,32 @@ +-- Create a flattened view of the returns +CREATE TABLE `returns_flat` ( + customer_id STRING, + receipt_id STRING, + transaction_date VARCHAR(2147483647), + sku_id STRING, + units DOUBLE, + unit_price DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +-- Insert into the returns_flat table +INSERT INTO `returns_flat` +SELECT + r.customer_id, + r.receipt_id, + r.transaction_date, + i.sku_id, + i.units, + i.unit_price +FROM `returns` AS r +CROSS JOIN UNNEST(r.items) AS i (sku_id, units, unit_price); \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh new file mode 100644 index 0000000000..da2cdbe8f9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +source ./environment-azure.sh + + +print_lines() { + echo "" + echo "" +} + +print_lines +echo "Checking Azure Cosmos DB Account Local Auth Disabled..." +COSMOS_DB_DISABLE_LOCAL_AUTH=$(az cosmosdb show -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --query "disableLocalAuth" --output tsv) +echo "Cosmos DB Local Auth Disabled: ${COSMOS_DB_DISABLE_LOCAL_AUTH}" +echo "This should be 'false'" + +print_lines +echo "Checking Azure Cosmos DB Account Public Network Access..." +COSMOS_DB_PUBLIC_NETWORK_ACCESS=$(az cosmosdb show -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --query "publicNetworkAccess" --output tsv) +echo "Cosmos DB Public Network Access: ${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" +echo "This should be 'Enabled'" + +echo "" +echo "" + +printf "%-45s %-12s %-12s %-10s\n" "Service Setting/Configuration" "Expected" "Actual" "Result" + +# Cosmos DB Public Network Access +if [ "${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" == "Enabled" ]; then + result="Pass" +else + result="Fail" +fi +printf "%-45s %-12s %-12s %-10s\n" "Cosmos DB Public Network Access Enabled" "Enabled" "${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" "${result}" + +# Cosmos DB Local Auth Disabled +if [ "${COSMOS_DB_DISABLE_LOCAL_AUTH}" == "false" ]; then + result="Pass" +else + result="Fail" +fi +printf "%-45s %-12s %-12s %-10s\n" "Cosmos DB Local Auth Disabled" "false" "${COSMOS_DB_DISABLE_LOCAL_AUTH}" "${result}" + diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh new file mode 100644 index 0000000000..02ad7b1682 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +export AZURE_RESOURCE_GROUP="confluent-hackathon" + +export COSMOS_DB_ACCOUNT="cfltizzya04qga" diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh new file mode 100644 index 0000000000..3690490763 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh @@ -0,0 +1,8 @@ + +#!/bin/bash + +# export CONFLUENT_ORGANIZATION_ID="1b2a7da3-709a-4562-9553-3cd6397c7388" + +export CONFLUENT_ORGANIZATION_ID="ca4d5cac-8257-49fd-af5b-1d1692f5f125" +export CONFLUENT_ENVIRONMENT_ID="env-6ggk2q" +export CONFLUENT_KAFKA_CLUSTER_ID="lkc-jyw7j2" diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh new file mode 100644 index 0000000000..2da754ccd7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +source ./environment-azure.sh + +# Enable Public Network Access +az cosmosdb update -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --public-network-access Enabled --debug + +# Enable Local Authentication with Keys +az resource update -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --resource-type "Microsoft.DocumentDB/databaseAccounts" --set properties.disableLocalAuth=false --debug + diff --git a/074-AIWithConfluentOnAzure/README.md b/074-AIWithConfluentOnAzure/README.md new file mode 100644 index 0000000000..4f32864eb2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/README.md @@ -0,0 +1,60 @@ +# What The Hack - AI With Confluent On Azure + +## Introduction + +This hackathon immerses you in building a real-time AI agent using **Confluent Cloud on Microsoft Azure**. You’ll learn how Confluent’s data streaming platform—based on Apache Kafka—can connect and process retail data in real time, enabling AI-driven insights that keep pace with constantly changing business conditions. Whether it’s ingesting product SKUs or synchronizing inventory levels, Confluent Cloud on Azure offers a unified, scalable, and secure platform to design near real-time pipelines and deliver accurate, intelligent solutions. + +Throughout this hack, you’ll capture data from diverse sources—such as transaction logs, returns, and purchase records—and then transform or enrich that data using Apache Flink or ksqlDB. The result is an always up-to-date data backbone, ready to power AI-driven applications that swiftly respond to customer needs, supplier demands, and dynamic inventory scenarios. + + +## Learning Objectives + +By completing this hack, you will: + +- **Set up a real-time streaming environment** on Confluent Cloud in Azure, incorporating best practices for scalability, reliability, and security. +- **Ingest and process diverse data sources** using Apache Kafka, exploring how pre-built Confluent connectors facilitate end-to-end data pipelines. +- **Apply basic stream processing** through ksqlDB or Apache Flink to merge, filter, or aggregate event data in real time. +- **Sync transformed data to Azure services** like Cosmos DB or Azure AI Search, ensuring your AI agent always has a near real-time view of retail operations. +- **Lay the groundwork for AI-driven decision-making**, demonstrating how real-time data improves accuracy and responsiveness for both customers and internal stakeholders. + +## Challenges + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** + - Prepare your Azure and Confluent Cloud environments with required infrastructure +- Challenge 01: **[Build the Flink Data Pipeline](Student/Challenge-01.md)** + - Create streaming data pipeline that merges multiple data streams using Apache Flink +- Challenge 02: **[Supplier Experience](Student/Challenge-02.md)** + - Interact with the AI agent as a supplier to query and replenish inventory +- Challenge 03: **[Customer Experience](Student/Challenge-03.md)** + - Simulate customer purchases and returns with real-time inventory updates +- Challenge 04: **[Employee Experience](Student/Challenge-04.md)** + - Access comprehensive operational insights across all transactions + +## Prerequisites + +- Your own Azure subscription with Owner access +- Visual Studio Code +- Azure CLI + +## Learning Resources +- [Apache Kafka vs Confluent](https://www.confluent.io/apache-kafka-vs-confluent/) +- [What is Apache Kafka & Confluent Cloud on Azure?](https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/overview) +- [Create an Apache Kafka & Confluent Cloud resource](https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create) +- [Confluent Hub](https://www.confluent.io/hub/) + +## Repository Contents + +- `./Coach` + - Coach's Guide and related files +- `./Coach/Solutions` + - Solution files with completed example answers to a challenge +- `./Student` + - Student's Challenge Guide +- `./Student/Resources` + - Terraform modules, configuration scripts, AI agent application code, and connector configurations (packaged by coach as Resources.zip) + +## Contributors + +- Andy Huang +- Israel Ekpo +- Juan Llovet de Casso diff --git a/074-AIWithConfluentOnAzure/Student/Challenge-00.md b/074-AIWithConfluentOnAzure/Student/Challenge-00.md new file mode 100644 index 0000000000..1a2163b26d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -0,0 +1,100 @@ +# Challenge 00 - Prerequisites - Ready, Set, GO! + +**[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) + +## Introduction + +In this challenge, you will provision all required infrastructure for the hackathon—both in Azure and Confluent Cloud—using automated Terraform modules. The focus of this challenge is to set up the cloud resources needed for data ingestion, streaming, schema validation, and AI search. + +By the end of this challenge, you should have: + +- Confluent Cloud configured with Kafka topics, Schema Registry, and Source/Sink Connectors +- Azure resources deployed, including Cosmos DB, Azure Storage, Azure OpenAI, Redis Cache, and Azure AI Search +- MCP-powered AI agents running and able to communicate with the deployed infrastructure. + +## Common Prerequisites + +We have compiled a list of common tools and software that you will need to complete this hack and deploy the Terraform-based infrastructure to Azure and Confluent Cloud. + +You may not need all of them outside this challenge. However, if you work with Azure or Confluent Cloud on a regular basis, these are essential components for your development toolkit. + +- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) +- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) + - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) + - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) + - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) +- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) +- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) + +In addition to the common prerequisites above, you will need the following tools specific to this hack: + +* **[Terraform CLI](https://developer.hashicorp.com/terraform/downloads)** + - Required to deploy infrastructure modules for Azure and Confluent Cloud + - After installation, verify by running: `terraform init` + +* **[Confluent Cloud CLI](https://docs.confluent.io/confluent-cli/current/install.html)** + - Required to authenticate to Confluent Cloud and interact with Kafka topics and connectors + - After installation, verify by running: `confluent --help` + + +## Description + +Your coach will provide you with a Resources.zip file (or access to a Codespaces environment) that contains the Terraform modules and configuration files needed to complete this challenge. If you plan to work locally, unpack the Resources.zip file on your workstation. If using Codespaces, the devcontainer will have the necessary dependencies pre-installed. + +In this challenge, you will: + +1. **Locate the Terraform modules** in the Resources folder (provided via Resources.zip or Codespaces) +2. **Update Terraform variables** with your Azure subscription ID, principal IDs, and Confluent API keys +3. **Run Terraform** to provision the infrastructure +4. **Confirm data flows through connectors** + +### What the Terraform automation will create + +| Platform | Resource Provisioned | +| ------------------- | ---------------------------------------------------------------------------------------------------------- | +| **Azure** | Azure OpenAI, Cosmos DB, Azure AI Search, Azure Redis Cache | +| **Confluent Cloud** | Kafka Cluster, Schema Registry, Kafka topics, Cosmos DB Source connectors, AI Search Sink connector | +| **AI Agents / MCP** | Deployment of microservices + MCP servers that expose capabilities to agents | + +## Success Criteria + +To complete this challenge successfully, you should be able to: + +- Verify Terraform deploys successfully and resources appear in Azure Portal and Confluent Cloud +- Verify source connectors are live and pushing data from Cosmos DB into Kafka topics +- Verify sink connector is pushing data into Azure AI Search (net sales + net inventory count topics) +- Demonstrate the MCP-powered AI agent can: + - Respond when prompted + - State its name + - List all eight departments in the grocery store + +## Learning Resources + + +* **Install Azure CLI:** + [Azure CLI Installation Guide](https://learn.microsoft.com/cli/azure/install-azure-cli) + +* **Install Terraform CLI:** + [Terraform CLI Downloads](https://developer.hashicorp.com/terraform/downloads) + +* **Install Confluent CLI:** + [Confluent CLI Installation Guide](https://docs.confluent.io/confluent-cli/current/install.html) + +* **Azure Service Principal authentication:** + [Azure Service Principal Setup](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal) + +* **Confluent Cloud getting started:** + [Confluent Cloud on Azure](https://docs.confluent.io/cloud/current/get-started/index.html) + +* **Confluent Connector Hub:** + [Azure Connectors for Confluent](https://www.confluent.io/hub/plugins?query=azure) + +* **Confluent Source & Sink Connectors:** + [Kafka Connectors from Confluent](https://docs.confluent.io/cloud/current/connectors/index.html) + +* **Azure AI Search documentation:** + [Azure AI Search Docs](https://learn.microsoft.com/azure/search/search-what-is-azure-search) + +* **Azure Cosmos DB documentation:** + [Azure Cosmos DB Docs](https://learn.microsoft.com/azure/cosmos-db/introduction) + diff --git a/074-AIWithConfluentOnAzure/Student/Challenge-01.md b/074-AIWithConfluentOnAzure/Student/Challenge-01.md new file mode 100644 index 0000000000..cf89f19c72 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -0,0 +1,66 @@ +# Challenge 01 - Build the Flink Data Pipeline (Merge Streaming Data) + +[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) + +## Introduction + +Welcome to the command center of a modern online grocery store. Every second, customers are buying, returning, and restocking items. Our goal is to build a real-time streaming pipeline that tracks every penny earned and every item in stock as it happens. + +Using Apache Flink on Confluent Cloud, you'll merge multiple data streams (purchases, returns, pricing, departments, and replenishments) into two critical business metrics: + +* `net_sales` - Real-time revenue tracking +* `net_inventory_count` - Live inventory levels + +Every event streaming into Kafka will instantly update your business metrics in real-time. + +## Description + +During this challenge, you will: + +- Connect to the Apache Flink SQL editor in Confluent Cloud +- Create Flink tables mapped to existing Kafka topics: `product_sku`, `product_pricing`, `product_departments`, `purchases`, `returns`, and `replenishments` +- Write Flink SQL merge logic that continuously updates the `net_sales` table and the `net_inventory_count` table + +### Required Merging Logic + +* Net Sales + + * Purchases add to the net sales total for each SKU. + * Returns subtract from the net sales total for each SKU. + +* Net Inventory Count + + * Purchases subtract from the inventory count. + * Replenishments add to the inventory count. + * Returns: + + * If the product belongs to the appliance department, returns add back to inventory. + * Returns from all other departments are ignored (treated as perishable or damaged). + + +After your SQL statements are running, every new message streaming into Kafka should update: + +* Net sales for the SKU +* Net inventory count for the SKU + +in real time. + +## Success Criteria + +To complete this challenge successfully, you should be able to: + +- Verify all Kafka topics listed above are mapped to Flink tables +- Verify Flink SQL merge statements for `net_sales` and `net_inventory_count` are created and running +- Verify sales and inventory values update continuously as new messages stream in +- Demonstrate logic behaves correctly: + - Purchases increase net sales and decrease inventory + - Replenishments increase inventory + - Returns decrease net sales + - Only appliance returns increase inventory count; all others are ignored + +## Learning Resources + +- [Apache Flink SQL documentation](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/overview/) +- [Confluent Cloud Flink quickstart](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Flink SQL merge and upsert concepts](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) + diff --git a/074-AIWithConfluentOnAzure/Student/Challenge-02.md b/074-AIWithConfluentOnAzure/Student/Challenge-02.md new file mode 100644 index 0000000000..2ab96e7184 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -0,0 +1,40 @@ +# Challenge 02 - Supplier Experience + +[< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) + + +## Pre-requisites + +You must complete **Challenge 01** before starting this challenge. The data pipeline with Flink SQL is necessary for this experience to function properly. + +## Introduction + +In this challenge, you will assume the role of a supplier interacting with the AI agent experience. The purpose of this challenge is to demonstrate how the data pipeline created in previous challenges provides real-time, accurate inventory information to the agent through MCP services backed by Apache Flink. As inventory levels change, Flink continuously merges data streams and updates the net inventory count table, ensuring that the supplier receives the most up-to-date information at all times. + +## Description + +During this challenge, you will: + +- Log into the supplier agent experience and explore its capabilities +- View inventory levels for product SKUs within specific departments +- View inventory levels for individual product SKUs +- Replenish inventory for specific SKUs or entire departments through the agent +- Verify that inventory changes are reflected in Azure AI Search +- Confirm that the AI agent responds with accurate, real-time inventory values from the streaming data pipeline + +## Success Criteria + +To complete this challenge successfully, you should be able to: + +- Verify the supplier agent can display real-time inventory levels for any SKU +- Verify the supplier agent can display real-time inventory levels per department +- Demonstrate replenishment actions result in updated inventory values in the net inventory count table +- Verify Azure AI Search reflects the updated inventory counts for specific SKUs +- Verify the agent retrieves updated values from MCP services and responds accurately after inventory changes + +## Learning Resources + +- [Working with Apache Flink SQL in Confluent Cloud](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Using Azure AI Search as a real-time index](https://learn.microsoft.com/azure/search/search-what-is-azure-search) +- [Schema Registry and data contracts](https://docs.confluent.io/platform/current/schema-registry/index.html) +- [Kafka Connect Source and Sink Connectors](https://docs.confluent.io/cloud/current/connectors/index.html) diff --git a/074-AIWithConfluentOnAzure/Student/Challenge-03.md b/074-AIWithConfluentOnAzure/Student/Challenge-03.md new file mode 100644 index 0000000000..d50cf672d5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -0,0 +1,41 @@ +# Challenge 03 - Customer Experience + +[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) + + +## Pre-requisites + +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The data pipeline with Flink SQL is necessary for this experience to function properly. + + +## Introduction + +In this challenge, you will assume the role of a customer interacting with the customer agent experience. The purpose of this challenge is to demonstrate real-time event processing as purchase and return actions affect inventory levels. When a customer makes a purchase or return, Apache Flink processes the streaming events and updates the net sales and net inventory count tables, which are then indexed into Azure AI Search and made available to the agent. + +## Description + +During this challenge, you will: + +- Log into the customer agent experience and explore its capabilities +- View inventory levels for specific product SKUs before making purchases +- Purchase product SKUs from different departments and record the quantities purchased +- Return product SKUs from each department and record the quantities returned +- Validate that inventory and sales data update in real time after each action +- Ensure that all inventory updates are visible within a three-second window + +## Success Criteria + +To complete this challenge successfully, you should be able to: + +- Verify the customer agent displays the inventory level of a SKU before a purchase +- Verify after a purchase, inventory is reduced and net sales are updated +- Verify after a return, inventory and net sales are updated following the business rules defined in the Flink merge logic +- Verify all inventory updates are visible within three seconds of the action being completed +- Verify the agent retrieves accurate, real-time values via MCP services backed by Azure AI Search + +## Learning Resources + +- [Confluent Cloud Flink quickstart](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Event processing and upsert patterns in Apache Flink](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) +- [Azure AI Search indexing concepts](https://learn.microsoft.com/azure/search/search-what-is-azure-search) +- [Kafka event streaming fundamentals](https://kafka.apache.org/documentation/) \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Challenge-04.md b/074-AIWithConfluentOnAzure/Student/Challenge-04.md new file mode 100644 index 0000000000..1284ccde5d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -0,0 +1,44 @@ +# Challenge 04 - Employee Experience + +[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** + + +## Pre-requisites + +You must complete **Challenge 02** and **Challenge 03** before starting this challenge. The data pipeline from the replenishments, returns and purchases is necessary for this experience to be complete and successful. + + +## Introduction + +In this challenge, you will assume the role of an employee interacting with the employee agent experience. The objective is to demonstrate the employee's ability to access comprehensive operational insights, including inventory, cumulative metrics, and net sales for each product SKU. The employee agent uses the same MCP service and data pipeline powered by Apache Flink, with data originating from real-time events such as purchases, returns, and replenishments. + +This challenge requires interaction across multiple personas. You will switch between customer, supplier, and employee tabs or windows to simulate real-world concurrent activity. Each action triggers updates to the net inventory count and net sales tables, and the employee agent should always return accurate, real-time data. + +## Description + +During this challenge, you will: + +- Log into the employee agent experience and explore its comprehensive capabilities +- Query real-time inventory and cumulative transaction metrics for any product SKU +- View inventory levels for individual SKUs and entire departments +- Use other personas (customer and supplier) to trigger purchase, return, and replenishment events +- Retrieve cumulative purchase, return, and replenishment units for any SKU after events occur +- Confirm that the employee agent responds with accurate net inventory counts and net sales values +- Verify that all data matches what is observed in Azure AI Search and Flink output + +## Success Criteria + +To complete this challenge successfully, you should be able to: + +- Verify the employee agent can display inventory levels for individual SKUs +- Verify the employee agent can display inventory levels for all SKUs in a department +- Verify cumulative purchase, return, and replenishment values for any SKU are retrieved accurately +- Verify the agent provides accurate net inventory counts and net sales values after transactions +- Verify inventory and sales values shown by the agent match what is observed in Azure AI Search and Flink output + +## Learning Resources + +- [Confluent Cloud Flink quickstart](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Flink SQL upsert and aggregate patterns](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) +- [Azure AI Search indexing concepts](https://learn.microsoft.com/azure/search/search-what-is-azure-search) +- [Kafka event streaming fundamentals](https://kafka.apache.org/documentation/) \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/.gitkeep b/074-AIWithConfluentOnAzure/Student/Resources/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore new file mode 100644 index 0000000000..aadd0f3246 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore @@ -0,0 +1,7 @@ + +Dockerfile.* +.env.sh +.env.sh.* +.venv +__pycache__ + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example new file mode 100644 index 0000000000..d79c2c25cc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example @@ -0,0 +1,50 @@ +#!/bin/bash + +# This is for the service principal in Azure +export AZURE_SUBSCRIPTION_ID="enter-your-subscription-id-here" +export AZURE_CLIENT_ID="enter-your-client-id-here" +export AZURE_CLIENT_SECRET="enter-your-client-secret-here" +export AZURE_TENANT_ID="enter-your-tenant-id-here" + +# Azure AI Search Credentials +export AZURE_AI_SEARCH_API_VERSION="2025-03-01-preview" # keep or change as needed +export AZURE_AI_SEARCH_ENDPOINT="https://your-search-service.search.windows.net" +export AZURE_AI_SEARCH_API_KEY="enter-your-ai-search-api-key-here" + +# Azure Cosmos DB Credentials +export COSMOS_CONNECTION_STRING="AccountEndpoint=https://your-cosmos-account.documents.azure.com:443/;AccountKey=enter-your-cosmos-key-here;" +export COSMOS_ENDPOINT="https://your-cosmos-account.documents.azure.com:443/" +export COSMOS_DATABASE_NAME="enter-your-database-name-here" + +# This is from Azure Redis Cache +export REDIS_HOST="your-redis-cache-name.redis.cache.windows.net" +export REDIS_PORT="6380" +export REDIS_PASSWORD="enter-your-redis-password-here" + +# This is from AI Foundry (Azure OpenAI) +export AZURE_OPENAI_ENDPOINT="https://your-openai-resource.openai.azure.com/" +export AZURE_OPENAI_API_KEY="enter-your-openai-api-key-here" +export AZURE_OPENAI_MODEL_NAME="gpt-4o-mini" +export OPENAI_API_VERSION="2025-01-01-preview" + +# MCP Services +export MCP_SERVICE_ENDPOINT_INVENTORY="http://localhost:8080/mcp" +export MCP_SERVICE_ENDPOINT_REPLENISHMENT="http://localhost:8081/mcp" +export MCP_SERVICE_ENDPOINT_SHOPPING="http://localhost:8082/mcp" + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# source ~/Microsoft/Confluent-WTH/.confluent-environment.sh +# confluent kafka topic produce ${topic_name} --parse-key --delimiter "::" --keyformat + + +# MCP Services \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md new file mode 100644 index 0000000000..ca502357ce --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md @@ -0,0 +1,82 @@ +## How to Build the Docker Images + +Navigate to the agentic_application directory and run the following commands to build each Docker image + + +```bash +# Navigate to the agent application directory +cd agentic_application + +# Create the base Docker image +docker build -t izzyacademy/confluent-hackathon:3.2.1 -t izzyacademy/confluent-hackathon:latest -f Dockerfile.base . + +# Build the Docker image for the Inventory MCP service +docker build -t izzyacademy/inventory:3.2.1 -t izzyacademy/inventory:latest -f Dockerfile.inventory . + +# Build the Docker image for the Replenishment MCP service +docker build -t izzyacademy/replenishment:3.2.1 -t izzyacademy/replenishment:latest -f Dockerfile.replenishment . + +# Build the Docker image for the Employee Agent Experience +docker build -t izzyacademy/employee:3.2.1 -t izzyacademy/employee:latest -f Dockerfile.employee . + +# Build the Docker image for the Supplier Agent Experience +docker build -t izzyacademy/supplier:3.2.1 -t izzyacademy/supplier:latest -f Dockerfile.supplier . + + +``` + +## How to Run the Dockers Containers with Docker Compose + +These are the steps: + +- Navigate to the compose directory +- ensure that the environment variables in the `shared_environment_variables.env` file are accurate +- make sure the `shared_environment_variables.env` file is in the current directory +- kick off the docker compose collection +- shut it down when you are done with you test/demo + +```bash + +# Navigate to the agent application directory +cd compose + +# Run the compose file as follows +docker-compose up + +# Tear down when you are done +docker-compose down --remove-orphans + +``` + +### How to Log on to the Containers + +```bash +# List all the active containers +docker ps + + +# Log into the employee container +docker exec -it compose-employee-1 /bin/bash + +# Log into the supplier container +docker exec -it compose-supplier-1 /bin/bash + +# Log into the customer container +docker exec -it compose-customer-1 /bin/bash + +``` + +Once you are in the container, you can execute each agent as follows: + +```bash + +# this is the employee experience +uv run agent_employee_experience.py + +# this is the supplier or vendor experience +uv run agent_supplier_experience.py + +# this is for the customer experience to search SKUs, make purchases, return previous purchases +uv run agent_customer_experience.py + +``` \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base new file mode 100644 index 0000000000..4a48a376e8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base @@ -0,0 +1,15 @@ +# Ubuntu 24.04 base +FROM ubuntu:24.04 + +# Install curl + certs (needed to fetch uv); keep image slim +RUN apt-get update \ + && apt-get install -y --no-install-recommends coreutils \ + curl ca-certificates vim \ + iputils-ping telnet netcat-openbsd \ + && rm -rf /var/lib/apt/lists/* + +# Install uv (to /root/.local/bin/uv by default) and make it globally available +RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ + && ln -s /root/.local/bin/uv /usr/local/bin/uv \ + && uv --version + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer new file mode 100644 index 0000000000..77aa635b65 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer @@ -0,0 +1,16 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.agent-customer.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee new file mode 100644 index 0000000000..a78fe24cd1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee @@ -0,0 +1,17 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder "agentic_application" into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.agent-employee.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory new file mode 100644 index 0000000000..ae9a2c1596 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory @@ -0,0 +1,18 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.mcp-inventory.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +EXPOSE 8080 + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment new file mode 100644 index 0000000000..3026c9315f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment @@ -0,0 +1,18 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.mcp-replenishment.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +EXPOSE 8081 + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping new file mode 100644 index 0000000000..c1d98e5199 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping @@ -0,0 +1,18 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.mcp-shopping.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +EXPOSE 8082 + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier new file mode 100644 index 0000000000..e62da83f92 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier @@ -0,0 +1,16 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.agent-supplier.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE new file mode 100644 index 0000000000..30d2ba5f4d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Israel Ekpo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md new file mode 100644 index 0000000000..d5b470279b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md @@ -0,0 +1,85 @@ + +We need to do the following +- define Pydantic Objects for all the schemas +- Department +- Product +- ShoppingCartItem +- ShoppingCart + + + +- we need to set up AI Search INDEX for departments and products (SKU and PRICING) + + +### Customers +Customers of the grocery company +- angela@contosocustomers.ai +- patrick@contosocustomers.ai +- darcy@contosovendors.ai +- mikhail@contosogroceries.ai +- jacob@contosogroceries.ai + +### Employees +Employees of the Grocery company +- james@contosogroceries.ai +- charlotte@contosogroceries.ai +- andy@contosogroceries.ai +- juan@contosogroceries.ai +- jason@contosogroceries.ai +- devanshi@contosogroceries.ai + +### Vendors +Global can supply anything but the rest only focus on one department +- kroger@contosovendors.ai +- costco@contosovendors.ai +- global@contosovendors.ai + +## Activate the Virtual Environment + +```bash +source .env.sh +source .venv/bin/activate +``` + +# Run the MCP Services + +````bash +uv run mcp_service.py --service inventory --port 8080 + +uv run mcp_service.py --service replenishment --port 8081 + +uv run mcp_service.py --service shopping --port 8082 +```` + + +# Run the Agents + +````bash + +uv run agent_employee_experience.py + +uv run agent_supplier_experience.py + +uv run agent_customer_experience.py + +```` + +### Run the MCP Inspector + +npx @modelcontextprotocol/inspector + + +### Network Debugging Tools + +```bash + +apt-get install -y iputils-ping telnet vim + +``` + + + +### Testing Nodes + +- Customer ID: jacob@contosogroceries.ai +- Receipt ID: 100001 \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md new file mode 100644 index 0000000000..c193286e15 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md @@ -0,0 +1,3 @@ + +# Contoso Retail Application + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md new file mode 100644 index 0000000000..3add4b2941 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md @@ -0,0 +1,142 @@ +## Setting up the Virtual Environment + +Run the following command from the `agentic_application` folder to create the virtual environment: + +```bash + +uv venv + +``` + +## Activating the Virtual Environment + +You can run these commands to activate the virtual environment + +### On Mac OS X or Linux + +```bash + +source .venv/bin/activate + +``` + +### On Windows + +```bash + +# If you are using Powershell +.venv\Scripts\Activate.ps1 + +# If you are using the Command Pallete +.venv\Scripts\activate.bat + +``` + +## Loading your Environment Variables + +Run the following command to load the environment variables before running the agents + +```bash + +source .env.sh + +``` + +## Running the MCP Servers + +You can run these commands to start up the MCP servers for the applications + +Make sure to `use a dedicated tab` for each service + +```bash +uv run mcp_service.py --service inventory --port 8080 + +uv run mcp_service.py --service replenishment --port 8081 + +uv run mcp_service.py --service shopping --port 8082 + +``` + +### Debugging the MCP Servers + +If you are having trouble or need to validate the MCP servers before running the agents you can use this tool below + +```bash +npx @modelcontextprotocol/inspector +``` + +### Running the Agent Experiences + +You can run these commands after the MCP servers have booted up: + +Make sure you use `a dedicated tab` for each experience + +````bash + +# this is the employee experience +uv run agent_employee_experience.py + +# this is the supplier or vendor experience +uv run agent_supplier_experience.py + +# this is for the customer experience to search SKUs, make purchases, return previous purchases +uv run agent_customer_experience.py + +```` + + +## How to Run the Dockers Containers with Docker Compose + +These are the steps: + +- Navigate to the compose directory +- ensure that the environment variables in the `shared_environment_variables.env` file are accurate +- make sure the `shared_environment_variables.env` file is in the current directory +- kick off the docker compose collection +- shut it down when you are done with you test/demo + +```bash + +# Navigate to the agent application directory +cd compose + +# Run the compose file as follows +docker-compose up + +# Tear down when you are done +docker-compose down --remove-orphans + +``` + +### How to Log on to the Containers + +```bash +# List all the active containers +docker ps + + +# Log into the employee container +docker exec -it compose-employee-1 /bin/bash + +# Log into the supplier container +docker exec -it compose-supplier-1 /bin/bash + +# Log into the customer container +docker exec -it compose-customer-1 /bin/bash + +``` + +Once you are in the container, you can execute each agent as follows: + +```bash + +# this is the employee experience +uv run agent_employee_experience.py + +# this is the supplier or vendor experience +uv run agent_supplier_experience.py + +# this is for the customer experience to search SKUs, make purchases, return previous purchases +uv run agent_customer_experience.py + +``` diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py new file mode 100644 index 0000000000..8a0eb485c3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from pydantic_graph import End, Graph + +from contoso_retail_application import ReturnsDao, PurchasesDao, CustomerDependency, CustomerTransactionState, \ + StartNode, MainMenu, FinishNode, ShopInventory, ReturnPriorPurchase, BrowseInventory, FinalizeShopping, \ + FinalizeReturns + + +async def main(): + r_dao = ReturnsDao() + p_dao = PurchasesDao() + + # Setting up the initial state and graph dependencies + transaction_dependency = CustomerDependency(purchases_dao=p_dao, returns_dao=r_dao) + transaction_state = CustomerTransactionState() + + # Listing all possible nodes within our state machine + graph_nodes = (StartNode, MainMenu, FinishNode, ReturnPriorPurchase, ShopInventory, BrowseInventory, FinalizeShopping, FinalizeReturns) + + # Constructing the Graph object with all the nodes + customer_experience_graph = Graph(nodes=graph_nodes, name="Customer Experience", state_type=CustomerTransactionState) + + # Setting the start node, initial state and graph dependencies + async with customer_experience_graph.iter(start_node=StartNode(), state=transaction_state, deps=transaction_dependency) as run: + current_node = run.next_node + while not isinstance(current_node, End): + print('Node', current_node) + current_node = await run.next(current_node) + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py new file mode 100644 index 0000000000..9b3836803e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py @@ -0,0 +1,68 @@ +import os + +from pydantic_ai import Agent +from pydantic_ai.mcp import MCPServerStreamableHTTP +from pydantic_ai.messages import ModelRequest, ModelResponse +from rich.prompt import Prompt + +from contoso_retail_application import ai_foundry_model + +instructions = """ +You are an agent called Mikhail and you help employees of Contoso Groceries (an online grocery store) to get information about the following: + + - Names of departments available in the grocery store + - The prices for different product SKUs in the grocery store + - Inventory levels for different product SKUs in the grocery store + - Net sales reports for different product SKUs in the grocery store + + Please use the data from tools provided and do not make up any information. + + If you cannot answer a question, please let the user know that you cannot answer the question. + +Whenever the response is a list of items, always convert it into a clean, readable Markdown table. + +Formatting rules for Markdown table dataset: +- Always include a header row with clear column names. +- Auto-detect the best column names based on the data (e.g., "Item", "Description", "Value", "Date"). +- Keep the table compact, aligned, and visually appealing. +- If there are more than 5 items, add alternating row shading (if the environment supports it). +- If some items have missing fields, leave the cell blank. +- Never return the list as plain text — always return a table. +- Use Markdown tables by default unless explicitly asked for HTML, CSV, or another format. +""" + +async def thank_you_message(): + print("\n\nThank you for using the Employee Experience Agent. Have a wonderful day\n\n") + +async def main(): + + inventory_service_endpoint = os.getenv('MCP_SERVICE_ENDPOINT_INVENTORY') + inventory_service_definition = MCPServerStreamableHTTP(url=inventory_service_endpoint) + mcp_servers: list[MCPServerStreamableHTTP] = [inventory_service_definition] + + # Keeping track of the Message history + message_history: list[ModelRequest | ModelResponse] = [] + + # initial prompt to get started + current_prompt = "\nHow can I help you?" + + + while True: + + user_prompt = Prompt.ask(current_prompt) + employee_experience_agent = Agent(ai_foundry_model, instructions=instructions, toolsets=mcp_servers) + results = await employee_experience_agent.run(user_prompt, message_history=message_history) + print(results.output) + message_history = results.all_messages() + + exit_or_not = Prompt.ask("\nIs there anything else you would like me to assist you with?", choices=['y','n']) + + if exit_or_not == 'n': + await thank_you_message() + break + current_prompt = "\nWhat else would you like me to help you with?" + + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py new file mode 100644 index 0000000000..3ab775b960 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py @@ -0,0 +1,74 @@ +import os + +from pydantic_ai import Agent +from pydantic_ai.mcp import MCPServerStreamableHTTP +from pydantic_ai.messages import ModelRequest, ModelResponse +from rich.prompt import Prompt + +from contoso_retail_application import ai_foundry_model, StaticDataset + +instructions = """ +You are an agent called Andrew and you help suppliers of Contoso Groceries (an online grocery store) to do the following tasks: + + - Check the inventory levels of product SKUs for the "appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood" departments. + - Check inventory levels for all SKUs for a specific department + - Replenish inventory for specific product SKUs + - Replenish inventory for all product SKUs for a specific department + + Please use the data from tools provided and do not make up any information. + + If you cannot answer a question, please let the user know that you cannot answer the question. + +Whenever the response is a list of items, always convert it into a clean, readable Markdown table. + +Formatting rules for Markdown table dataset: +- Always include a header row with clear column names. +- Auto-detect the best column names based on the data (e.g., "Item", "Description", "Value", "Date"). +- Keep the table compact, aligned, and visually appealing. +- If there are more than 5 items, add alternating row shading (if the environment supports it). +- If some items have missing fields, leave the cell blank. +- Never return the list as plain text — always return a table. +- Use Markdown tables by default unless explicitly asked for HTML, CSV, or another format. +""" + +valid_suppliers = StaticDataset.get_vendor_identifiers() + +async def thank_you_message(): + print("\n\nThank you for using the Supplier Experience Agent. Have a wonderful day\n\n") + +async def main(): + + replenishment_service_endpoint = os.getenv('MCP_SERVICE_ENDPOINT_REPLENISHMENT') + replenishment_service_definition = MCPServerStreamableHTTP(url=replenishment_service_endpoint) + mcp_services = [replenishment_service_definition] + + # Keeping track of the Message history + message_history: list[ModelRequest | ModelResponse] = [] + + # initial prompt to get started + current_prompt = "\nHow can I help you?" + + vendor_id: str = Prompt.ask("What is your vendor id?", choices=valid_suppliers, show_choices=False) + agent_system_prompt = f"My vendor id is {vendor_id}" + + while True: + + user_prompt = Prompt.ask(current_prompt) + supplier_experience_agent = Agent(ai_foundry_model, instructions=instructions, system_prompt=agent_system_prompt, toolsets=mcp_services) + + results = await supplier_experience_agent.run(user_prompt, message_history=message_history) + + print(results.output) + message_history = results.all_messages() + + exit_or_not = Prompt.ask("\nIs there anything else you would like me to assist you with?", choices=['y','n']) + + if exit_or_not == 'n': + await thank_you_message() + break + current_prompt = "\nWhat else would you like me to help you with?" + + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py new file mode 100644 index 0000000000..d31671e05d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py @@ -0,0 +1,45 @@ +from .ai_foundry_setup import ai_foundry_model +from .agent_graphs import CustomerDependency, CustomerTransactionState, FinalizeReturns, FinalizeShopping, \ + BrowseInventory, ShopInventory, ReturnPriorPurchase, StartNode, FinishNode, MainMenu +from .data_access_objects import SearchDataAccessObject, ReturnsDao, PurchasesDao, CartManager +from .models import Departments, Department, NetSales, ProductInventory, PurchaseCart, ReturnCart, ReplenishmentLevel, \ + SkuId, PurchaseItem, ReturnItem, Purchase, ReturnTransaction, ReplenishmentItem, DepartmentInventoryConfig +from .service_configuration_inventory import inventory_service +from .service_configuration_replenishment import replenishment_service +from .service_configuration_shopping import shopping_service +from .static_dataset import StaticDataset +from .utils import base64_encode + +__all__ = ( + 'ai_foundry_model', + 'StaticDataset', + 'ReturnsDao', + 'PurchasesDao', + 'CartManager', + 'Departments', + "Department", + 'inventory_service', + 'replenishment_service', + 'shopping_service', + 'SearchDataAccessObject', + 'NetSales', + 'ProductInventory', + 'PurchaseCart', + 'ReturnCart', + 'DepartmentInventoryConfig', + 'base64_encode', + "ReplenishmentLevel", + "SkuId", "PurchaseItem", "ReturnItem", "Purchase", "ReturnTransaction", "ReplenishmentItem", + "CustomerDependency", + "CustomerTransactionState", + "FinalizeReturns", + "FinalizeShopping", + "BrowseInventory", + "ShopInventory", + "ReturnPriorPurchase", + "FinishNode", + "StartNode", + "MainMenu", +) + + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py new file mode 100644 index 0000000000..69401ec1cb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +from dataclasses import dataclass + +from pydantic_graph import BaseNode, GraphRunContext, End +from rich.prompt import Prompt, IntPrompt + +from .models import SkuId +from .data_access_objects import ReturnsDao, PurchasesDao +from .static_dataset import StaticDataset + + +@dataclass +class CustomerDependency: + returns_dao: ReturnsDao + purchases_dao: PurchasesDao + +@dataclass +class CustomerTransactionState: + customer_id: str | None = None + active_return_cart: bool = False + active_shopping_cart: bool = False + shopping_cart_id: str | None = None + receipt_id: str | None = None + return_cart_id: str | None = None + +@dataclass +class FinalizeReturns(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> FinishNode | ReturnPriorPurchase: + pass + +@dataclass +class FinalizeShopping(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> FinishNode | ShopInventory: + pass + +@dataclass +class BrowseInventory(BaseNode[CustomerTransactionState, CustomerDependency]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState, CustomerDependency]) -> MainMenu | ShopInventory: + pass + + +@dataclass +class ShopInventory(BaseNode[CustomerTransactionState, CustomerDependency]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState, CustomerDependency]) -> MainMenu | BrowseInventory | FinalizeShopping: + pass + + +@dataclass +class ReturnPriorPurchase(BaseNode[CustomerTransactionState, CustomerDependency]): + returns_dao: ReturnsDao = None + purchases_dao: PurchasesDao = None + + async def run(self, ctx: GraphRunContext[CustomerTransactionState, CustomerDependency]) -> MainMenu | FinalizeReturns: + self.returns_dao = ctx.deps.returns_dao + self.purchases_dao = ctx.deps.purchases_dao + + prompt_string = """ + Welcome to Customer Returns: + Enter 1 to Start the Return Process + Enter 7 to Return to the Main Menu + """ + menu_options: list[str] = ["1", "7"] + selected_option: int = IntPrompt.ask(prompt=prompt_string, choices=menu_options, show_choices=False) + + if selected_option == 7: + return MainMenu() + else: + return await self.handle_returns(state=ctx.state) + + async def init_returns(self, state: CustomerTransactionState): + + if not state.active_return_cart: + cart = self.returns_dao.generate_new_cart(receipt_id=state.receipt_id, customer_id=state.customer_id) + state.active_return_cart = True + state.return_cart_id = cart.cart_id + + async def keep_processing_returns(self, state: CustomerTransactionState) -> int: + + print("Thank you for entering your receipt id") + valid_options = ["1", "2", "3", "4", "5"] + prompt_message = """ + What would you like to do next: + 1: Review items from the previous purchase + 2: Review current items you are about to return + 3: Add an item to the return cart. This will add all the units for that SKU + 4: Remove an item from the return cart. This will remove all the units for that SKU + 5: Finalize your returns + """ + + await self.init_returns(state) + + selected_option = IntPrompt.ask(prompt_message, choices=valid_options, show_choices=False) + current_receipt_id = state.receipt_id + current_customer_id = state.customer_id + return_cart_id = state.return_cart_id + + if selected_option == 1: + previous_purchase = self.purchases_dao.get_existing_purchase(receipt_id=current_receipt_id, customer_id=state.customer_id) + # TODO: display this using Rich Tables + print("Here is your previous purchase", previous_purchase) + return selected_option + elif selected_option == 2: + # TODO: display this using Rich Tables + current_return_cart = self.returns_dao.get_cart(cart_identifier=state.return_cart_id) + print("Here are the contents of your return cart", current_return_cart) + return selected_option + elif selected_option == 3: + valid_skus = self.purchases_dao.get_existing_purchase_skus(receipt_id=current_receipt_id, customer_id=current_customer_id) + current_prompt = f"Please enter the SKU you would like to add to the return cart {valid_skus}" + selected_sku: SkuId = Prompt.ask(current_prompt, choices=valid_skus) + units_returned = self.purchases_dao.get_existing_purchase_sku_quentity(receipt_id=current_receipt_id, customer_id=current_customer_id, sku_id=selected_sku) + update_confirmation = self.returns_dao.add_item(cart_identifier=return_cart_id, sku_id=selected_sku, quantity=units_returned) + print(f"Return cart updated, {update_confirmation}") + return selected_option + elif selected_option == 4: + valid_return_skus = self.returns_dao.get_active_return_skus(cart_id=return_cart_id) + if len(valid_return_skus) == 0: + print("There are no items in your return cart, yet. Review your previous purchase and select some items to return") + else: + current_prompt = f"Please enter the SKU you would like to remove from the return cart {valid_return_skus}" + selected_sku: SkuId = Prompt.ask(current_prompt, choices=valid_return_skus, show_choices=False) + removal_confirmation = self.returns_dao.remove_item(cart_identifier=return_cart_id, sku_id=selected_sku) + print(f"Return cart updated, {removal_confirmation}") + return selected_option + else: # option 5 was selected + return selected_option + + + async def handle_returns(self, state: CustomerTransactionState) -> FinalizeReturns: + has_valid_receipt_id: bool = False + customer_id = state.customer_id + + while not has_valid_receipt_id: + receipt_id = Prompt.ask("Please enter a valid receipt id") + receipt_lookup = self.purchases_dao.get_existing_purchase(receipt_id=receipt_id, customer_id=customer_id) + if receipt_lookup is None: + print(f"Receipt id {receipt_id} was NOT FOUND!") + continue + + if receipt_lookup.customer_id != customer_id: + print(f"Customer ID on Receipt Id {receipt_id} does not match your customer ID") + continue + + else: + has_valid_receipt_id = True + state.receipt_id = receipt_id + + + continue_returns = await self.keep_processing_returns(state) + while continue_returns != 5: + continue_returns = await self.keep_processing_returns(state) + + return FinalizeReturns() + + + + + +@dataclass +class FinishNode(BaseNode[CustomerTransactionState, None, str]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> End[str]: + print("Thank you for using the Customer Experience at Contoso Groceries where shopping is always a pleasure. Have a nice day") + return End(ctx.state.customer_id) + + +@dataclass +class StartNode(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> MainMenu: + print("Welcome to the Customer Experience at Contoso Groceries where shopping is always a pleasure.") + print("An agent will be with you shortly. Before we get started, let's have your customer identifier so that we can look up your account information to better assist you.") + valid_customer_ids = StaticDataset.get_customer_identifiers() + customer_id: str = Prompt.ask(prompt="Please enter a valid customer id", choices=valid_customer_ids, show_choices=False) + + # Set the customer id property on the shared state + ctx.state.customer_id = customer_id + return MainMenu() + + +@dataclass +class MainMenu(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> BrowseInventory | ShopInventory | ReturnPriorPurchase | FinishNode: + prompt_string = """ + Welcome to the Main Menu: + Enter 2 to Browse Inventory + Enter 3 to Start or Continue Shopping + Enter 4 to Start or Continue your Returns + Enter 5 to Exit the Customer Experience + """ + menu_options: list[str] = ["2", "3", "4", "5"] + selected_option: int = IntPrompt.ask(prompt=prompt_string, choices=menu_options, show_choices=False) + + if selected_option == 2: + return BrowseInventory() + elif selected_option == 3: + return ShopInventory() + elif selected_option == 4: + return ReturnPriorPurchase() + else: + return FinishNode() diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py new file mode 100644 index 0000000000..ca0b2dcc1e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py @@ -0,0 +1,9 @@ +import os + +from pydantic_ai.models.openai import OpenAIModelName, OpenAIChatModel + +ai_foundry_model_name = os.getenv('AZURE_OPENAI_MODEL_NAME', 'gpt-4o-mini') + +model_name: OpenAIModelName = ai_foundry_model_name + +ai_foundry_model = OpenAIChatModel(model_name=model_name, provider='azure') \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py new file mode 100644 index 0000000000..961113c4a9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py @@ -0,0 +1,568 @@ +import os +from datetime import datetime +from typing import Any +from zoneinfo import ZoneInfo + +from azure_datastore_utils import SearchClientDao, RedisUtil, CosmosDBUtils + +from .models import NetSales, Departments, Department, ProductInventory, ReplenishmentLevel, DepartmentInventoryConfig +from .models import PurchaseCart, SkuId, PurchaseItem, ReturnCart, ReturnItem, Purchase +from .models import ReturnTransaction, ReplenishmentItem + + +class SearchDataAccessObject: + """Data Access Object (DAO) for querying Azure Cognitive Search indexes. + + This class provides methods to interact with different indexes + such as net sales, product inventory, and departments. It uses + `SearchClientDao` to query Azure Cognitive Search indexes and + maps the results into domain models (e.g., `NetSales`, + `Department`, `ProductInventory`). + """ + + def __init__(self): + """Initialize the DAO with index names for sales, inventory, and departments.""" + self.sales_index = "net_sales" + self.inventory_index = "product_inventory" + self.department_index = "departments_flat" + + def get_departments(self): + """Retrieve all departments from the search index. + + Returns: + list[Department]: A list of `Department` objects. + """ + search_client = SearchClientDao(self.department_index) + + search_text = "*" + sort_order: list[str] = ["department asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order) + + search_results: list[Department] = [] + + for search_item in query_results: + current_item = Department.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_net_sales(self, max_count: int = 250): + """Retrieves the net sales records from the data store. + + Args: + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[NetSales]: A list of `NetSales` objects sorted by department and SKU. + """ + # set up search client + search_client = SearchClientDao(self.sales_index) + + search_text = "*" + sort_order: list[str] = ["department asc", "sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, top=max_count) + + search_results: list[NetSales] = [] + + for search_item in query_results: + current_item = NetSales.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_net_sales_by_sku(self, sku_id: str): + """Retrieve a single net sales record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + NetSales | None: A `NetSales` object if found, otherwise None. + """ + # set up search client + search_client = SearchClientDao(self.sales_index) + + search_text = "*" + query_filter = f"sku_id eq '{sku_id}'" + + query_results = search_client.query_index(search_text=search_text, query_filter=query_filter, + include_total_count=True) + + for search_item in query_results: + current_item = NetSales.from_dict(search_item) + return current_item + + return None + + def get_net_sales_by_department(self, department: Departments, max_count: int = 250): + """Retrieve net sales records filtered by department. + + Args: + department (Departments): The department to filter by. + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[NetSales]: A list of `NetSales` objects for the given department. + """ + search_client = SearchClientDao(self.sales_index) + + search_text = "*" + query_filter = f"department eq '{department}'" + sort_order: list[str] = ["sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, + query_filter=query_filter, top=max_count) + + search_results: list[NetSales] = [] + + for search_item in query_results: + current_item = NetSales.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_inventory_levels(self, max_count: int = 250): + """Retrieve product inventory levels from the search index. + + Args: + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects. + """ + search_client = SearchClientDao(self.inventory_index) + + search_text = "*" + sort_order: list[str] = ["department asc", "sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, top=max_count) + + search_results: list[ProductInventory] = [] + + for search_item in query_results: + current_item = ProductInventory.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_inventory_levels_by_department(self, department: Departments, max_count: int = 250): + """Retrieve product inventory levels filtered by department. + + Args: + department (Departments): The department to filter by. + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects for the given department. + """ + search_client = SearchClientDao(self.inventory_index) + + search_text = "*" + query_filter = f"department eq '{department}'" + sort_order: list[str] = ["sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, + query_filter=query_filter, top=max_count) + + search_results: list[ProductInventory] = [] + + for search_item in query_results: + current_item = ProductInventory.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_inventory_levels_by_sku(self, sku_id: str): + """Retrieve a single product inventory record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ProductInventory | None: A `ProductInventory` object if found, otherwise None. + """ + search_client = SearchClientDao(self.inventory_index) + + search_text = "*" + query_filter = f"sku_id eq '{sku_id}'" + + query_results = search_client.query_index(search_text=search_text, query_filter=query_filter) + + for search_item in query_results: + current_item = ProductInventory.from_dict(search_item) + return current_item + + return None + + def get_replenishment_levels(self, max_count: int = 250): + """Retrieve product replenishment levels for all SKUs. + + Args: + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects. + """ + + config_db = DepartmentInventoryConfig() + items = self.get_inventory_levels(max_count=max_count) + + results: list[ReplenishmentLevel] = [] + for current_sku in items: + current_sku_level = ReplenishmentLevel.from_product_inventory(current_sku, config_database=config_db) + results.append(current_sku_level) + + return results + + def get_replenishment_levels_by_department(self, department: Departments, max_count: int = 250): + """Retrieve product replenishment levels filtered by department. + + Args: + department (Departments): The department to filter by. + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects for the given department. + """ + + config_db = DepartmentInventoryConfig() + items = self.get_inventory_levels_by_department(department=department, max_count=max_count) + + results: list[ReplenishmentLevel] = [] + for current_sku in items: + current_sku_level = ReplenishmentLevel.from_product_inventory(current_sku, config_database=config_db) + results.append(current_sku_level) + + return results + + def get_replenishment_level_by_sku(self, sku_id: str): + """Retrieve a single product replenishment level by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ReplenishmentLevel | None: A `ReplenishmentLevel` object if found, otherwise None. + """ + + config_db = DepartmentInventoryConfig() + item = self.get_inventory_levels_by_sku(sku_id=sku_id) + + if item is not None: + return ReplenishmentLevel.from_product_inventory(item, config_database=config_db) + + return None + + +class CartManager: + CART_KEY_PURCHASES = "purchase_cart_" + CART_KEY_RETURNS = "return_cart_" + CART_KEY_REPLENISHMENTS = "replenishment_cart_" + + INITIAL_CART_ID_PURCHASES = 600000 + INITIAL_CART_ID_RETURNS = 700000 + INITIAL_CART_ID_REPLENISHMENTS = 800000 + + def __init__(self): + self.redis_client = RedisUtil() + + @staticmethod + def get_lookup_key(prefix: str, look_up_key: str): + return f"{prefix}{look_up_key}" + + @staticmethod + def get_lookup_key_purchases(look_up_key: str): + return CartManager.get_lookup_key(CartManager.CART_KEY_PURCHASES, look_up_key) + + @staticmethod + def get_lookup_key_returns(look_up_key: str): + return CartManager.get_lookup_key(CartManager.CART_KEY_RETURNS, look_up_key) + + @staticmethod + def get_lookup_key_replenishments(look_up_key: str): + return CartManager.get_lookup_key(CartManager.CART_KEY_REPLENISHMENTS, look_up_key) + + def __get_cart_id(self, lookup_key: str, initial_value: int): + id_exists: bool = self.redis_client.exists(lookup_key) + if not id_exists: + return self.redis_client.increment(lookup_key, initial_value) + return self.redis_client.increment(lookup_key, 1) + + def get_cart_id_purchases(self): + return self.__get_cart_id(CartManager.CART_KEY_PURCHASES, CartManager.INITIAL_CART_ID_PURCHASES) + + def get_cart_id_returns(self): + return self.__get_cart_id(CartManager.CART_KEY_RETURNS, CartManager.INITIAL_CART_ID_RETURNS) + + def get_cart_id_replenishments(self): + return self.__get_cart_id(CartManager.CART_KEY_REPLENISHMENTS, CartManager.INITIAL_CART_ID_REPLENISHMENTS) + + def generate_new_cart_purchases(self, customer_id: str)->PurchaseCart: + purchase_cart_id:int = self.get_cart_id_purchases() + return self.create_cart_purchases(cart_identifier=str(purchase_cart_id), customer_id=customer_id) + + def create_cart_purchases(self, cart_identifier: str, customer_id: str) -> PurchaseCart: + cart = PurchaseCart(cart_id=cart_identifier, customer_id=customer_id, items={}) + cart_entry = cart.model_dump() + + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + self.redis_client.set_json(look_up_key, cart_entry) + return cart + + def get_cart_purchases(self, cart_identifier: str): + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + item = self.redis_client.get_json(look_up_key) + cart = PurchaseCart.from_dict(item) + return cart + + def add_cart_item_purchases(self, cart_identifier: str, sku_id: SkuId, quantity: float): + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + purchase_item = PurchaseItem(sku_id=sku_id, units=quantity, unit_price=0.00, discounts=0.00) + cart = PurchaseCart.from_dict(item) + + cart.add_item(purchase_item) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def remove_cart_item_purchases(self, cart_identifier: str, sku_id: SkuId): + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + cart = PurchaseCart.from_dict(item) + cart.remove_item(sku_id=sku_id) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def generate_new_cart_returns(self, receipt_id: str, customer_id: str) -> ReturnCart: + return_cart_id:int = self.get_cart_id_returns() + return self.create_cart_returns(cart_identifier=str(return_cart_id), receipt_id=receipt_id, customer_id=customer_id) + + def create_cart_returns(self, cart_identifier: str, receipt_id: str, customer_id: str) -> ReturnCart: + cart = ReturnCart(cart_id=cart_identifier, receipt_id=receipt_id, customer_id=customer_id, items={}) + cart_entry = cart.model_dump() + + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + self.redis_client.set_json(look_up_key, cart_entry) + return cart + + def add_cart_item_returns(self, cart_identifier: str, sku_id: SkuId, quantity: float): + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + return_item = ReturnItem(sku_id=sku_id, units=quantity, unit_price=0.00) + cart = ReturnCart.from_dict(item) + + cart.add_item(return_item) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def remove_cart_item_returns(self, cart_identifier: str, sku_id: SkuId): + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + cart = ReturnCart.from_dict(item) + cart.remove_item(sku_id=sku_id) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def get_cart_returns(self, cart_identifier: str): + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + item = self.redis_client.get_json(look_up_key) + cart = ReturnCart.from_dict(item) + return cart + + +class ReturnsDao: + + def __init__(self): + database_name = os.environ.get("COSMOS_DATABASE_NAME") + collection = "returns" + self.client = CosmosDBUtils(database_name=database_name, collection=collection) + self.search_client = SearchDataAccessObject() + self.cart_manager = CartManager() + + def is_receipt_previously_processed(self, receipt_id: str) -> bool: + + retrieval_sql = "SELECT * FROM c WHERE c.receipt_id = @receipt_id" + query_parameters = [{"name": "@receipt_id", "value": receipt_id}] + items = self.client.query_container(query=retrieval_sql, parameters=query_parameters, enable_cross_partition_query=True) + for retrieved_item in items: + if retrieved_item is not None: + return True + return False + + def get_active_return_skus(self, cart_id: str): + active_return = self.get_cart(cart_identifier=cart_id) + existing_skus: list[SkuId] = [] + for cart_item in active_return.items: + existing_skus.append(cart_item.sku_id) + return existing_skus + + def get_existing_return(self, return_id: str, customer_id: str) -> ReturnTransaction | None: + record_id = return_id + retrieved_record: dict[str, Any] = self.client.get_single_item(item_id=record_id, partition_key=customer_id) + if retrieved_record is not None: + return_record: ReturnTransaction = ReturnTransaction.from_dict(retrieved_record) + return return_record + return None + + def generate_new_cart(self, receipt_id: str, customer_id: str): + return self.cart_manager.generate_new_cart_returns(receipt_id=receipt_id, customer_id=customer_id) + + def create_cart(self, cart_identifier: str, receipt_id: str, customer_id: str): + return self.cart_manager.create_cart_returns(cart_identifier, receipt_id=receipt_id, customer_id=customer_id) + + def add_item(self, cart_identifier: str, sku_id: SkuId, quantity: float): + return self.cart_manager.add_cart_item_returns(cart_identifier=cart_identifier, sku_id=sku_id, quantity=quantity) + + def remove_item(self, cart_identifier: str, sku_id: SkuId): + return self.cart_manager.remove_cart_item_returns(cart_identifier=cart_identifier, sku_id=sku_id) + + def get_cart(self, cart_identifier: str): + cart = self.cart_manager.get_cart_returns(cart_identifier=cart_identifier) + + current_datetime_original: datetime = datetime.now(ZoneInfo("America/New_York")) + current_datetime: str = current_datetime_original.isoformat(timespec="seconds").replace("T", " ") + + return_record = ReturnTransaction(id=cart_identifier, return_id=cart_identifier, receipt_id=cart_identifier, transaction_date=current_datetime, customer_id=cart.customer_id, items=[]) + + for key, value in cart.items.items(): + sku_id: SkuId = key + cart_item: ReturnItem = value + v = self.search_client.get_inventory_levels_by_sku(sku_id=sku_id) + return_item = ReturnItem(sku_id=sku_id, units=cart_item.units, unit_price=v.unit_price) + return_record.items.append(return_item) + + return return_record + + def submit_cart(self, cart_identifier: str): + return_record = self.get_cart(cart_identifier=cart_identifier) + record = return_record.model_dump() + + self.client.upsert_item(record) + return return_record + + +class PurchasesDao: + + def __init__(self): + database_name = os.environ.get("COSMOS_DATABASE_NAME") + collection = "purchases" + self.client = CosmosDBUtils(database_name=database_name, collection=collection) + self.search_client = SearchDataAccessObject() + self.cart_manager = CartManager() + + def get_existing_purchase_sku_quentity(self, receipt_id: str, customer_id: str, sku_id: SkuId) -> float: + existing_purchase = self.get_existing_purchase(receipt_id=receipt_id, customer_id=customer_id) + if existing_purchase is None: + return 0.00 + for purchase_item in existing_purchase.items: + if purchase_item.sku_id == sku_id: + return purchase_item.units + return 0.00 + + def get_existing_purchase_skus(self, receipt_id: str, customer_id: str): + existing_purchase = self.get_existing_purchase(receipt_id=receipt_id, customer_id=customer_id) + existing_skus: list[SkuId] = [] + + if existing_purchase is None: + return existing_skus + + for purchase_item in existing_purchase.items: + existing_skus.append(purchase_item.sku_id) + return existing_skus + + def get_existing_purchase(self, receipt_id: str, customer_id: str) -> Purchase | None: + record_id = receipt_id + retrieved_record: dict[str, Any] = self.client.get_single_item(item_id=record_id, partition_key=customer_id) + if retrieved_record is not None: + purchase: Purchase = Purchase.from_dict(retrieved_record) + return purchase + return None + + def generate_new_cart(self, customer_id: str): + return self.cart_manager.generate_new_cart_purchases(customer_id=customer_id) + + def create_cart(self, cart_identifier: str, customer_id: str): + return self.cart_manager.create_cart_purchases(cart_identifier, customer_id=customer_id) + + def add_item(self, cart_identifier: str, sku_id: SkuId, quantity: float): + self.cart_manager.add_cart_item_purchases(cart_identifier=cart_identifier, sku_id=sku_id, quantity=quantity) + + def remove_item(self, cart_identifier: str, sku_id: SkuId): + self.cart_manager.remove_cart_item_purchases(cart_identifier=cart_identifier, sku_id=sku_id) + + def get_cart(self, cart_identifier: str): + cart = self.cart_manager.get_cart_purchases(cart_identifier=cart_identifier) + + current_datetime_original: datetime = datetime.now(ZoneInfo("America/New_York")) + current_datetime: str = current_datetime_original.isoformat(timespec="seconds").replace("T", " ") + + purchase = Purchase(id=cart_identifier, receipt_id=cart_identifier, + transaction_date=current_datetime, customer_id=cart.customer_id, items=[]) + for key, value in cart.items.items(): + sku_id: SkuId = key + cart_item: PurchaseItem = value + v = self.search_client.get_inventory_levels_by_sku(sku_id=sku_id) + purchase_item = PurchaseItem(sku_id=sku_id, units=cart_item.units, unit_price=v.unit_price, discounts=0) + purchase.items.append(purchase_item) + + return purchase + + def submit_cart(self, cart_identifier: str): + purchase: Purchase = self.get_cart(cart_identifier=cart_identifier) + record = purchase.model_dump() + + self.client.upsert_item(record) + return purchase + + +class ReplenishmentDao: + + def __init__(self): + database_name = os.environ.get("COSMOS_DATABASE_NAME") + collection = "replenishments" + self.client = CosmosDBUtils(database_name=database_name, collection=collection) + self.search_client = SearchDataAccessObject() + self.cart_manager = CartManager() + + def replenish_sku(self, vendor_id: str, sku_id: SkuId, units: float) -> ReplenishmentItem: + current_datetime_original: datetime = datetime.now(ZoneInfo("America/New_York")) + current_datetime: str = current_datetime_original.isoformat(timespec="seconds").replace("T", " ") + + cart_id: int = self.cart_manager.get_cart_id_replenishments() + cart_identifier: str = str(cart_id) + + replenishment_item = ReplenishmentItem(id=cart_identifier, replenishment_id=cart_identifier, + transaction_date=current_datetime, sku_id=sku_id, + units=units, vendor_id=vendor_id) + record = replenishment_item.model_dump() + + self.client.upsert_item(record) + return replenishment_item + + def replenish_department(self, department_id: Departments, vendor_id: str): + + replenishment_results: list[ReplenishmentItem] = [] + dept_replenishment_levels: list[ReplenishmentLevel] = self.search_client.get_replenishment_levels_by_department( + department=department_id) + + for sku_replenishment_level in dept_replenishment_levels: + # This is the current SKU + current_sku_id: SkuId = sku_replenishment_level.sku_id + # This is the Maximum Inventory Level for the SKU + maximum_inventory_level: float = sku_replenishment_level.sku_mil + # The current inventory level for the SKU + current_inventory_level: float = sku_replenishment_level.inventory_level + # How many units we need for replenishment + replenishment_units: float = maximum_inventory_level - current_inventory_level + + if sku_replenishment_level.needs_replenishment: + repl_item = self.replenish_sku(vendor_id=vendor_id, sku_id=current_sku_id, units=replenishment_units) + replenishment_results.append(repl_item) + + return replenishment_results diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py new file mode 100644 index 0000000000..c3e163dc3c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py @@ -0,0 +1,228 @@ +import json +from typing import Mapping, Any, Self, Literal, Union, List + +from pydantic import BaseModel, Field +from .utils import base64_encode + +Departments = Literal["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + +ApplianceId = Literal[ + "101", "102", "103", "104", "105", + "106", "107", "108", "109", "110", + "111", "112", "113", "114", "115", + "116", "117", "118", "119", "120", + "121", "122", "123", "124", "125", +] + +CleaningId = Literal[ + "201", "202", "203", "204", "205", + "206", "207", "208", "209", "210", + "211", "212", "213", "214", "215", + "216", "217", "218", "219", "220", + "221", "222", "223", "224", "225", +] + +DairyId = Literal[ + "301", "302", "303", "304", "305", + "306", "307", "308", "309", "310", + "311", "312", "313", "314", "315", + "316", "317", "318", "319", "320", + "321", "322", "323", "324", "325", +] + +DeliId = Literal[ + "401", "402", "403", "404", "405", + "406", "407", "408", "409", "410", + "411", "412", "413", "414", "415", + "416", "417", "418", "419", "420", + "421", "422", "423", "424", "425", +] + +MeatId = Literal[ + "501", "502", "503", "504", "505", + "506", "507", "508", "509", "510", + "511", "512", "513", "514", "515", + "516", "517", "518", "519", "520", + "521", "522", "523", "524", "525", +] + +PharmacyId = Literal[ + "601", "602", "603", "604", "605", + "606", "607", "608", "609", "610", + "611", "612", "613", "614", "615", + "616", "617", "618", "619", "620", + "621", "622", "623", "624", "625", +] + +ProduceId = Literal[ + "701", "702", "703", "704", "705", + "706", "707", "708", "709", "710", + "711", "712", "713", "714", "715", + "716", "717", "718", "719", "720", + "721", "722", "723", "724", "725", +] + +SeafoodId = Literal[ + "801", "802", "803", "804", "805", + "806", "807", "808", "809", "810", + "811", "812", "813", "814", "815", + "816", "817", "818", "819", "820", + "821", "822", "823", "824", "825", +] + +SkuId = Union[ApplianceId, CleaningId, DairyId, DeliId, MeatId, PharmacyId, ProduceId, SeafoodId] + +class DepartmentInventoryConfig: + + def __init__(self): + + # This is the percentage below which the inventory needs to be replenished + self.replenishment_threshold: float = 0.30 + + # These are maximum inventory levels for each SKU by department + self.mil_config: dict[str, float] = { + "appliance": 200.00, + "cleaning": 200.00, + "dairy": 200.00, + "deli": 50.00, + "meat": 10000.00, + "pharmacy": 50.00, + "produce": 10000.00, + "seafood": 10000.00, + } + + def get_replenishment_threshold(self): + return self.replenishment_threshold + + def get_department_maximum_inventory_level(self, department: Departments) -> float: + return self.mil_config[department] + +class ContosoDataModel(BaseModel): + """Base model that adds a typed `from_dict` constructor for all subclasses.""" + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> Self: + """Converts a python dictionary to a Pydantic object""" + return cls.model_validate(data) + + +class ProductInventory(ContosoDataModel): + sku_id: SkuId = Field(..., description="Unique identifier for the product SKU") + inventory_level: float = Field(..., description="Available inventory quantity for the SKU") + unit_price: float = Field(..., description="Unit price of the product") + name: str = Field(..., description="Name of the product") + description: str = Field(..., description="Detailed description of the product") + department: Departments = Field(..., description="Department where the product belongs") + + def get_lookup_id(self) -> str: + lookup_id = {"sku_id": self.sku_id} + return base64_encode(json.dumps(lookup_id)) + + +class ReplenishmentItem(ContosoDataModel): + id: str = Field(..., description="Unique identifier for the replenishment record") + replenishment_id: str = Field(..., description="Replenishment transaction identifier") + transaction_date: str = Field(..., description="Date and time when stock was replenished") + sku_id: SkuId = Field(..., description="SKU identifier being replenished") + units: float = Field(..., description="Quantity of units replenished") + vendor_id: str = Field(..., description="Unique identifier of the vendor supplying the replenishment") + + +class ReplenishmentLevel(ContosoDataModel): + sku_id: SkuId = Field(..., description="Unique identifier for the product SKU") + sku_mil: float = Field(..., description="The Maximum Inventory Level for the SKU") + inventory_level: float = Field(..., description="Available inventory quantity for the SKU") + needs_replenishment: bool = Field(..., description="Whether or not the SKU needs to be replenished") + name: str = Field(..., description="Name of the product") + description: str = Field(..., description="Detailed description of the product") + department: str = Field(..., description="Department where the product belongs") + + @staticmethod + def from_product_inventory(sku: ProductInventory, config_database: DepartmentInventoryConfig): + sku_mil: float = config_database.get_department_maximum_inventory_level(sku.department) + needs_to_be_replenished: bool = (sku.inventory_level / sku_mil) < config_database.get_replenishment_threshold() + + replenishment_level = ReplenishmentLevel(sku_id=sku.sku_id, sku_mil=sku_mil, + inventory_level=sku.inventory_level, + needs_replenishment=needs_to_be_replenished, + name=sku.name, + description=sku.description, + department=sku.department) + return replenishment_level + + +class NetSales(ContosoDataModel): + sku_id: SkuId = Field(..., description="Unique identifier for the product SKU") + net_sales: float = Field(..., description="Net sales amount for the SKU") + name: str = Field(..., description="Name of the product") + department: str = Field(..., description="Department to which the product belongs") + + def get_lookup_id(self) -> str: + lookup_id = {"sku_id": self.sku_id} + return base64_encode(json.dumps(lookup_id)) + + +class Department(ContosoDataModel): + department: str = Field(..., description="Name of the department") + description: str = Field(..., description="Description of the department's focus or contents") + + def get_lookup_id(self) -> str: + lookup_id = {"department": self.department} + return base64_encode(json.dumps(lookup_id)) + + +class PurchaseItem(ContosoDataModel): + sku_id: SkuId = Field(..., description="Stock Keeping Unit identifier for the product") + units: float = Field(..., description="Number of units purchased") + unit_price: float = Field(..., description="Price per unit at time of transaction") + discounts: float = Field(..., description="Discount applied on the item") + + +class Purchase(ContosoDataModel): + id: str = Field(..., description="Unique transaction identifier") + receipt_id: str = Field(..., description="Receipt identifier") + transaction_date: str = Field(..., description="Date and time of the purchase") + customer_id: str = Field(..., description="Unique customer identifier") + items: List[PurchaseItem] = Field(..., description="List of purchased items") + + +class PurchaseCart(ContosoDataModel): + cart_id: str = Field(..., description="Unique Cart identifier") + customer_id: str = Field(..., description="Unique customer identifier") + items: dict[SkuId, PurchaseItem] = Field(..., description="Map of cart items for each SKU") + + def add_item(self, item: PurchaseItem): + sku_id = item.sku_id + self.items[sku_id] = item + + def remove_item(self, sku_id: SkuId): + return self.items.pop(sku_id, None) + + +class ReturnItem(ContosoDataModel): + sku_id: SkuId = Field(..., description="Stock Keeping Unit identifier") + units: float = Field(..., description="Number of units returned") + unit_price: float = Field(..., description="Original unit price at time of purchase") + + +class ReturnTransaction(ContosoDataModel): + id: str = Field(..., description="Unique transaction identifier for the return record") + return_id: str = Field(..., description="Unique return identifier") + receipt_id: str = Field(..., description="Reference to original purchase receipt") + transaction_date: str = Field(..., description="Date and time of the return") + customer_id: str = Field(..., description="Unique customer identifier") + items: List[ReturnItem] = Field(..., description="List of returned items") + + +class ReturnCart(ContosoDataModel): + cart_id: str = Field(..., description="Unique Cart identifier") + receipt_id: str = Field(..., description="Reference to original purchase receipt") + customer_id: str = Field(..., description="Unique customer identifier") + items: dict[str, ReturnItem] = Field(..., description="Map of cart items for each SKU") + + def add_item(self, item: ReturnItem): + sku_id = item.sku_id + self.items[sku_id] = item + + def remove_item(self, sku_id: SkuId): + return self.items.pop(sku_id, None) diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py new file mode 100644 index 0000000000..79937debf1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py @@ -0,0 +1,97 @@ +from mcp.server import FastMCP + +from . import Department +from . import SearchDataAccessObject +from . import NetSales, ProductInventory, Departments + + +def inventory_service(host: str = "0.0.0.0", port: int = 8080): + + # Declare the MCP service + product_mcp = FastMCP(name="Inventory Service", host=host, port=port) + + @product_mcp.tool(description="Returns a list of all the departments") + async def get_departments() -> list[Department]: + """Retrieve all departments from the database. + + Returns: + list[Department]: A list of `Department` objects. + """ + dao = SearchDataAccessObject() + return dao.get_departments() + + @product_mcp.tool(description="Retrieves the net sales for all the product SKUs") + async def get_net_sales() -> list[NetSales]: + """Retrieves the net sales records from the database. + + Returns: + list[NetSales]: A list of `NetSales` objects sorted by department and SKU. + """ + dao = SearchDataAccessObject() + return dao.get_net_sales() + + @product_mcp.tool(description="Retrieves the net sales amount for a specific SKU") + async def get_net_sales_by_sku(sku_id: str) -> NetSales: + """Retrieve a single net sales record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + NetSales | None: A `NetSales` object if found, otherwise None. + """ + dao = SearchDataAccessObject() + return dao.get_net_sales_by_sku(sku_id=sku_id) + + @product_mcp.tool(description="Retrieves net sales for all the SKUs for the specified department") + async def get_net_sales_by_department(department: Departments): + """Retrieve net sales records filtered by department. + + Args: + department (Departments): The department to filter by. + + Returns: + list[NetSales]: A list of `NetSales` objects for the given department. + """ + dao = SearchDataAccessObject() + return dao.get_net_sales_by_department(department=department) + + @product_mcp.tool(description="Retrieves the inventory level for all the product SKUs") + async def get_inventory_levels() -> list[ProductInventory]: + """Retrieve product inventory levels from the database. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects. + """ + dao = SearchDataAccessObject() + return dao.get_inventory_levels() + + @product_mcp.tool(description="Retrieves the inventory level for product SKUs in the specified department") + async def get_inventory_levels_by_department(department: Departments): + """Retrieve product inventory levels filtered by department. + + Args: + department (Departments): The department to filter by. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects for the given department. + """ + dao = SearchDataAccessObject() + return dao.get_inventory_levels_by_department(department=department) + + @product_mcp.tool(description="Retrieves the inventory level for the specific product SKU") + async def get_inventory_level_by_sku(sku_id: str): + """Retrieve a single product inventory record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ProductInventory | None: A `ProductInventory` object if found, otherwise None. + """ + dao = SearchDataAccessObject() + return dao.get_inventory_levels_by_sku(sku_id=sku_id) + + + + return product_mcp \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py new file mode 100644 index 0000000000..ce987cefec --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py @@ -0,0 +1,79 @@ +from mcp.server import FastMCP + +from contoso_retail_application import SearchDataAccessObject, Departments +from contoso_retail_application.data_access_objects import ReplenishmentDao +from contoso_retail_application.models import SkuId, ReplenishmentItem + + +def replenishment_service(host: str = "0.0.0.0", port: int = 8081): + + # Declare the MCP service + replenishment_mcp = FastMCP(name="Replenishment Service", host=host, port=port) + + @replenishment_mcp.tool(description="Returns the replenishment levels for all SKUs") + async def get_replenishment_levels(): + """Retrieve product replenishment levels for all SKUs. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects. + """ + dao = SearchDataAccessObject() + return dao.get_replenishment_levels() + + @replenishment_mcp.tool(description="Returns the replenishment levels for all SKUs for the specified department") + async def get_replenishment_levels_by_department(department: Departments): + """Retrieve product replenishment levels filtered by department. + + Args: + department (Departments): The department to filter by. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects for the given department. + """ + dao = SearchDataAccessObject() + return dao.get_replenishment_levels_by_department(department=department) + + @replenishment_mcp.tool(description="Returns the replenishment level for the specified SKU identifier") + async def get_replenishment_level_by_sku(sku_id: str): + """Retrieve a single product replenishment level by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ReplenishmentLevel | None: A `ReplenishmentLevel` object if found, otherwise None. + """ + dao = SearchDataAccessObject() + return dao.get_replenishment_level_by_sku(sku_id=sku_id) + + @replenishment_mcp.tool(description="Replenish the specified SKU identifier") + async def replenish_sku(vendor_id: str, sku_id: SkuId, units: float) -> ReplenishmentItem: + """Replenishes the SKU. + + Args: + vendor_id (str): The vendor identifier. + sku_id (SkuId): The SKU identifier to filter on. + units (float): The number of units of the SKU to replenish. + + Returns: + ReplenishmentItem | None: A `ReplenishmentItem` object if successful, otherwise None. + """ + dao = ReplenishmentDao() + return dao.replenish_sku(vendor_id=vendor_id, sku_id=sku_id, units=units) + + @replenishment_mcp.tool(description="Replenish all the SKUs for the specified department") + async def replenish_department(vendor_id: str, department_id: Departments) ->list[ReplenishmentItem]: + """Replenishes all the SKUs for the department. + + Args: + vendor_id (str): The vendor identifier. + department_id (Departments): The department to replenish + + Returns: + list[ReplenishmentItem]: The items that have been replenished. + """ + dao = ReplenishmentDao() + return dao.replenish_department(vendor_id=vendor_id, department_id=department_id) + + + return replenishment_mcp \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py new file mode 100644 index 0000000000..78d083fbe5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py @@ -0,0 +1,13 @@ +from mcp.server import FastMCP + + +def shopping_service(host: str = "0.0.0.0", port: int = 8082): + + # Declare the MCP service + product_mcp = FastMCP(name="Shopping Service", host=host, port=port) + + @product_mcp.tool(description="Says Hello") + async def say_hello(): + return "Hello" + + return product_mcp \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py new file mode 100644 index 0000000000..b10abb8de9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py @@ -0,0 +1,35 @@ + +class StaticDataset: + + @staticmethod + def get_employee_identifiers() -> list[str]: + employee_ids: list[str] = [ + "james@contosogroceries.ai", + "charlotte@contosogroceries.ai", + "andy@contosogroceries.ai", + "juan@contosogroceries.ai", + "jason@contosogroceries.ai", + "devanshi@contosogroceries.ai" + ] + return employee_ids + + @staticmethod + def get_customer_identifiers() -> list[str]: + customer_ids: list[str] = [ + "angela@contosocustomers.ai", + "patrick@contosocustomers.ai", + "darcy@contosovendors.ai", + "mikhail@contosogroceries.ai", + "jacob@contosogroceries.ai" + ] + return customer_ids + + @staticmethod + def get_vendor_identifiers() -> list[str]: + vendor_ids: list[str] = [ + "seafood@contosovendors.ai", + "meat@contosovendors.ai", + "dairy@contosovendors.ai", + "global@contosovendors.ai" + ] + return vendor_ids diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py new file mode 100644 index 0000000000..f5f9637bdc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py @@ -0,0 +1,9 @@ +import base64 + +def base64_encode(input_value: str) -> str: + encoded_bytes: str = base64.b64encode(input_value.encode("utf-8")).decode("utf-8") + return encoded_bytes + +def base64_decode(encoded_text: str) -> str: + decoded_bytes: str = base64.b64decode(encoded_text.encode("utf-8")).decode('utf-8') + return decoded_bytes diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh new file mode 100644 index 0000000000..5e8e2f96ff --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully +sleep 48h \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh new file mode 100644 index 0000000000..5e8e2f96ff --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully +sleep 48h \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh new file mode 100644 index 0000000000..5e8e2f96ff --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully +sleep 48h \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh new file mode 100644 index 0000000000..a7f7defd34 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully + +# MCP Services for Data CRUD operations +uv run mcp_service.py --service inventory --port 8080 diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh new file mode 100644 index 0000000000..bb713d5ab7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully + +# MCP Services for Data CRUD operations +uv run mcp_service.py --service replenishment --port 8081 diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh new file mode 100644 index 0000000000..a32802eb01 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully + +# MCP Services for Data CRUD operations +uv run mcp_service.py --service shopping --port 8082 diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py new file mode 100644 index 0000000000..ede590ae0f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py @@ -0,0 +1,3 @@ +result = "Hello from Main!!!" + +print(result) diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py new file mode 100644 index 0000000000..df8613df6b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py @@ -0,0 +1,56 @@ +import asyncio +import os +import sys +from argparse import ArgumentParser +from dotenv import load_dotenv + +from contoso_retail_application import inventory_service, replenishment_service, shopping_service + +async def run_mcp_service(): + + service_lists: list[str] = ['shopping', 'replenishment', 'inventory'] + + parser = ArgumentParser(description="Start the MCP service with provided or default configuration.") + + parser.add_argument('--service', required=True, help=f"The name of the service {service_lists}", choices=service_lists) + parser.add_argument('--envFile', required=False, default='.env', help='Path to .env file (default: .env)') + parser.add_argument('--host', required=False, default='0.0.0.0', help='Host IP or name for SSE (default: 0.0.0.0)') + parser.add_argument('--port', required=False, type=int, default=8000, help='Port number for SSE (default: 8000)') + + # Parse the application arguments + args = parser.parse_args() + + # Set up the Host name and port for the service + mcp_service: str = args.service + mcp_host: str = args.host + mcp_port: int = args.port + mcp_env_file: str = args.envFile + + if mcp_service not in service_lists: + parser.print_help() + sys.exit(1) + + # Check if envFile exists and load it + if mcp_env_file and os.path.exists(mcp_env_file): + load_dotenv(dotenv_path=mcp_env_file) + print(f"Environment variables loaded from {mcp_env_file}") + else: + print(f"Env file '{mcp_env_file}' not found. Skipping environment loading.") + + service_dictionary = { + 'inventory' : inventory_service, + 'replenishment': replenishment_service, + 'shopping': shopping_service, + } + + # Pick the service from the dictionary + target_service = service_dictionary[mcp_service] + + # initialize the service + service = target_service(host=mcp_host, port=mcp_port) + + # run the service with the streamable HTTP transport mode + await service.run_streamable_http_async() + +if __name__ == "__main__": + asyncio.run(run_mcp_service()) diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml new file mode 100644 index 0000000000..a9f28e96bc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "contoso-retail-application" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "azure-datastore-utils==0.2.4", + "mcp==1.13.1", + "pydantic-ai==1.0.2", + "pydantic-graph==1.0.2", + "rich>=14.1.0" +] diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py new file mode 100644 index 0000000000..c1055215f2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py @@ -0,0 +1,11 @@ +from contoso_retail_application.data_access_objects import ReplenishmentDao + +dao = ReplenishmentDao() + +result = dao.replenish_sku(vendor_id="israel@a.io", sku_id="101", units=1.00) + +print(result) + + +# This can be run as: +# uv run -m tests.test_replenishment \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py new file mode 100644 index 0000000000..771e83f1cd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py @@ -0,0 +1,11 @@ +from contoso_retail_application import SearchDataAccessObject + +sales = SearchDataAccessObject() + +results = sales.get_net_sales() + +print(results) + + +# This can be run as: +# uv run -m tests.test_sales \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock new file mode 100644 index 0000000000..e54b4d7c6b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock @@ -0,0 +1,2259 @@ +version = 1 +revision = 2 +requires-python = ">=3.12" + +[[package]] +name = "ag-ui-protocol" +version = "0.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/de/0bddf7f26d5f38274c99401735c82ad59df9cead6de42f4bb2ad837286fe/ag_ui_protocol-0.1.8.tar.gz", hash = "sha256:eb745855e9fc30964c77e953890092f8bd7d4bbe6550d6413845428dd0faac0b", size = 5323, upload-time = "2025-07-15T10:55:36.389Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/00/40c6b0313c25d1ab6fac2ecba1cd5b15b1cd3c3a71b3d267ad890e405889/ag_ui_protocol-0.1.8-py3-none-any.whl", hash = "sha256:1567ccb067b7b8158035b941a985e7bb185172d660d4542f3f9c6fff77b55c6e", size = 7066, upload-time = "2025-07-15T10:55:35.075Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.12.15" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/e7/d92a237d8802ca88483906c388f7c201bbe96cd80a165ffd0ac2f6a8d59f/aiohttp-3.12.15.tar.gz", hash = "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", size = 7823716, upload-time = "2025-07-29T05:52:32.215Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/97/77cb2450d9b35f517d6cf506256bf4f5bda3f93a66b4ad64ba7fc917899c/aiohttp-3.12.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", size = 702333, upload-time = "2025-07-29T05:50:46.507Z" }, + { url = "https://files.pythonhosted.org/packages/83/6d/0544e6b08b748682c30b9f65640d006e51f90763b41d7c546693bc22900d/aiohttp-3.12.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", size = 476948, upload-time = "2025-07-29T05:50:48.067Z" }, + { url = "https://files.pythonhosted.org/packages/3a/1d/c8c40e611e5094330284b1aea8a4b02ca0858f8458614fa35754cab42b9c/aiohttp-3.12.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", size = 469787, upload-time = "2025-07-29T05:50:49.669Z" }, + { url = "https://files.pythonhosted.org/packages/38/7d/b76438e70319796bfff717f325d97ce2e9310f752a267bfdf5192ac6082b/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", size = 1716590, upload-time = "2025-07-29T05:50:51.368Z" }, + { url = "https://files.pythonhosted.org/packages/79/b1/60370d70cdf8b269ee1444b390cbd72ce514f0d1cd1a715821c784d272c9/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", size = 1699241, upload-time = "2025-07-29T05:50:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/4968a7b8792437ebc12186db31523f541943e99bda8f30335c482bea6879/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", size = 1754335, upload-time = "2025-07-29T05:50:55.394Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c1/49524ed553f9a0bec1a11fac09e790f49ff669bcd14164f9fab608831c4d/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", size = 1800491, upload-time = "2025-07-29T05:50:57.202Z" }, + { url = "https://files.pythonhosted.org/packages/de/5e/3bf5acea47a96a28c121b167f5ef659cf71208b19e52a88cdfa5c37f1fcc/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", size = 1719929, upload-time = "2025-07-29T05:50:59.192Z" }, + { url = "https://files.pythonhosted.org/packages/39/94/8ae30b806835bcd1cba799ba35347dee6961a11bd507db634516210e91d8/aiohttp-3.12.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", size = 1635733, upload-time = "2025-07-29T05:51:01.394Z" }, + { url = "https://files.pythonhosted.org/packages/7a/46/06cdef71dd03acd9da7f51ab3a9107318aee12ad38d273f654e4f981583a/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", size = 1696790, upload-time = "2025-07-29T05:51:03.657Z" }, + { url = "https://files.pythonhosted.org/packages/02/90/6b4cfaaf92ed98d0ec4d173e78b99b4b1a7551250be8937d9d67ecb356b4/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", size = 1718245, upload-time = "2025-07-29T05:51:05.911Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e6/2593751670fa06f080a846f37f112cbe6f873ba510d070136a6ed46117c6/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", size = 1658899, upload-time = "2025-07-29T05:51:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/8f/28/c15bacbdb8b8eb5bf39b10680d129ea7410b859e379b03190f02fa104ffd/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", size = 1738459, upload-time = "2025-07-29T05:51:09.56Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/c269cbc4faa01fb10f143b1670633a8ddd5b2e1ffd0548f7aa49cb5c70e2/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", size = 1766434, upload-time = "2025-07-29T05:51:11.423Z" }, + { url = "https://files.pythonhosted.org/packages/52/b0/4ff3abd81aa7d929b27d2e1403722a65fc87b763e3a97b3a2a494bfc63bc/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", size = 1726045, upload-time = "2025-07-29T05:51:13.689Z" }, + { url = "https://files.pythonhosted.org/packages/71/16/949225a6a2dd6efcbd855fbd90cf476052e648fb011aa538e3b15b89a57a/aiohttp-3.12.15-cp312-cp312-win32.whl", hash = "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", size = 423591, upload-time = "2025-07-29T05:51:15.452Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d8/fa65d2a349fe938b76d309db1a56a75c4fb8cc7b17a398b698488a939903/aiohttp-3.12.15-cp312-cp312-win_amd64.whl", hash = "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", size = 450266, upload-time = "2025-07-29T05:51:17.239Z" }, + { url = "https://files.pythonhosted.org/packages/f2/33/918091abcf102e39d15aba2476ad9e7bd35ddb190dcdd43a854000d3da0d/aiohttp-3.12.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9f922ffd05034d439dde1c77a20461cf4a1b0831e6caa26151fe7aa8aaebc315", size = 696741, upload-time = "2025-07-29T05:51:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/7495a81e39a998e400f3ecdd44a62107254803d1681d9189be5c2e4530cd/aiohttp-3.12.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ee8a8ac39ce45f3e55663891d4b1d15598c157b4d494a4613e704c8b43112cd", size = 474407, upload-time = "2025-07-29T05:51:21.165Z" }, + { url = "https://files.pythonhosted.org/packages/49/fc/a9576ab4be2dcbd0f73ee8675d16c707cfc12d5ee80ccf4015ba543480c9/aiohttp-3.12.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3eae49032c29d356b94eee45a3f39fdf4b0814b397638c2f718e96cfadf4c4e4", size = 466703, upload-time = "2025-07-29T05:51:22.948Z" }, + { url = "https://files.pythonhosted.org/packages/09/2f/d4bcc8448cf536b2b54eed48f19682031ad182faa3a3fee54ebe5b156387/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97752ff12cc12f46a9b20327104448042fce5c33a624f88c18f66f9368091c7", size = 1705532, upload-time = "2025-07-29T05:51:25.211Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f3/59406396083f8b489261e3c011aa8aee9df360a96ac8fa5c2e7e1b8f0466/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:894261472691d6fe76ebb7fcf2e5870a2ac284c7406ddc95823c8598a1390f0d", size = 1686794, upload-time = "2025-07-29T05:51:27.145Z" }, + { url = "https://files.pythonhosted.org/packages/dc/71/164d194993a8d114ee5656c3b7ae9c12ceee7040d076bf7b32fb98a8c5c6/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fa5d9eb82ce98959fc1031c28198b431b4d9396894f385cb63f1e2f3f20ca6b", size = 1738865, upload-time = "2025-07-29T05:51:29.366Z" }, + { url = "https://files.pythonhosted.org/packages/1c/00/d198461b699188a93ead39cb458554d9f0f69879b95078dce416d3209b54/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fa751efb11a541f57db59c1dd821bec09031e01452b2b6217319b3a1f34f3d", size = 1788238, upload-time = "2025-07-29T05:51:31.285Z" }, + { url = "https://files.pythonhosted.org/packages/85/b8/9e7175e1fa0ac8e56baa83bf3c214823ce250d0028955dfb23f43d5e61fd/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5346b93e62ab51ee2a9d68e8f73c7cf96ffb73568a23e683f931e52450e4148d", size = 1710566, upload-time = "2025-07-29T05:51:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/59/e4/16a8eac9df39b48ae102ec030fa9f726d3570732e46ba0c592aeeb507b93/aiohttp-3.12.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:049ec0360f939cd164ecbfd2873eaa432613d5e77d6b04535e3d1fbae5a9e645", size = 1624270, upload-time = "2025-07-29T05:51:35.195Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/cd84dee7b6ace0740908fd0af170f9fab50c2a41ccbc3806aabcb1050141/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b52dcf013b57464b6d1e51b627adfd69a8053e84b7103a7cd49c030f9ca44461", size = 1677294, upload-time = "2025-07-29T05:51:37.215Z" }, + { url = "https://files.pythonhosted.org/packages/ce/42/d0f1f85e50d401eccd12bf85c46ba84f947a84839c8a1c2c5f6e8ab1eb50/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9b2af240143dd2765e0fb661fd0361a1b469cab235039ea57663cda087250ea9", size = 1708958, upload-time = "2025-07-29T05:51:39.328Z" }, + { url = "https://files.pythonhosted.org/packages/d5/6b/f6fa6c5790fb602538483aa5a1b86fcbad66244997e5230d88f9412ef24c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac77f709a2cde2cc71257ab2d8c74dd157c67a0558a0d2799d5d571b4c63d44d", size = 1651553, upload-time = "2025-07-29T05:51:41.356Z" }, + { url = "https://files.pythonhosted.org/packages/04/36/a6d36ad545fa12e61d11d1932eef273928b0495e6a576eb2af04297fdd3c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:47f6b962246f0a774fbd3b6b7be25d59b06fdb2f164cf2513097998fc6a29693", size = 1727688, upload-time = "2025-07-29T05:51:43.452Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c8/f195e5e06608a97a4e52c5d41c7927301bf757a8e8bb5bbf8cef6c314961/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:760fb7db442f284996e39cf9915a94492e1896baac44f06ae551974907922b64", size = 1761157, upload-time = "2025-07-29T05:51:45.643Z" }, + { url = "https://files.pythonhosted.org/packages/05/6a/ea199e61b67f25ba688d3ce93f63b49b0a4e3b3d380f03971b4646412fc6/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad702e57dc385cae679c39d318def49aef754455f237499d5b99bea4ef582e51", size = 1710050, upload-time = "2025-07-29T05:51:48.203Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2e/ffeb7f6256b33635c29dbed29a22a723ff2dd7401fff42ea60cf2060abfb/aiohttp-3.12.15-cp313-cp313-win32.whl", hash = "sha256:f813c3e9032331024de2eb2e32a88d86afb69291fbc37a3a3ae81cc9917fb3d0", size = 422647, upload-time = "2025-07-29T05:51:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8e/78ee35774201f38d5e1ba079c9958f7629b1fd079459aea9467441dbfbf5/aiohttp-3.12.15-cp313-cp313-win_amd64.whl", hash = "sha256:1a649001580bdb37c6fdb1bebbd7e3bc688e8ec2b5c6f52edbb664662b17dc84", size = 449067, upload-time = "2025-07-29T05:51:52.549Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anthropic" +version = "0.64.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/4f/f2b880cba1a76f3acc7d5eb2ae217632eac1b8cef5ed3027493545c59eba/anthropic-0.64.0.tar.gz", hash = "sha256:3d496c91a63dff64f451b3e8e4b238a9640bf87b0c11d0b74ddc372ba5a3fe58", size = 427893, upload-time = "2025-08-13T17:09:49.915Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/b2/2d268bcd5d6441df9dc0ebebc67107657edb8b0150d3fda1a5b81d1bec45/anthropic-0.64.0-py3-none-any.whl", hash = "sha256:6f5f7d913a6a95eb7f8e1bda4e75f76670e8acd8d4cd965e02e2a256b0429dd1", size = 297244, upload-time = "2025-08-13T17:09:47.908Z" }, +] + +[[package]] +name = "anyio" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, +] + +[[package]] +name = "argcomplete" +version = "3.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/16/0f/861e168fc813c56a78b35f3c30d91c6757d1fd185af1110f1aec784b35d0/argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf", size = 73403, upload-time = "2025-04-03T04:57:03.52Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/da/e42d7a9d8dd33fa775f467e4028a47936da2f01e4b0e561f9ba0d74cb0ca/argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591", size = 43708, upload-time = "2025-04-03T04:57:01.591Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "azure-common" +version = "1.1.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/71/f6f71a276e2e69264a97ad39ef850dca0a04fce67b12570730cb38d0ccac/azure-common-1.1.28.zip", hash = "sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3", size = 20914, upload-time = "2022-02-03T19:39:44.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/55/7f118b9c1b23ec15ca05d15a578d8207aa1706bc6f7c87218efffbbf875d/azure_common-1.1.28-py2.py3-none-any.whl", hash = "sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad", size = 14462, upload-time = "2022-02-03T19:39:42.417Z" }, +] + +[[package]] +name = "azure-core" +version = "1.34.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, + { name = "six" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/29/ff7a519a315e41c85bab92a7478c6acd1cf0b14353139a08caee4c691f77/azure_core-1.34.0.tar.gz", hash = "sha256:bdb544989f246a0ad1c85d72eeb45f2f835afdcbc5b45e43f0dbde7461c81ece", size = 297999, upload-time = "2025-05-01T23:17:27.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/9e/5c87b49f65bb16571599bc789857d0ded2f53014d3392bc88a5d1f3ad779/azure_core-1.34.0-py3-none-any.whl", hash = "sha256:0615d3b756beccdb6624d1c0ae97284f38b78fb59a2a9839bf927c66fbbdddd6", size = 207409, upload-time = "2025-05-01T23:17:29.818Z" }, +] + +[[package]] +name = "azure-cosmos" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-core" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/7c/a4e7810f85e7f83d94265ef5ff0fb1efad55a768de737d940151ea2eec45/azure_cosmos-4.9.0.tar.gz", hash = "sha256:c70db4cbf55b0ff261ed7bb8aa325a5dfa565d3c6eaa43d75d26ae5e2ad6d74f", size = 1824155, upload-time = "2024-11-19T04:09:30.195Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/dc/380f843744535497acd0b85aacb59565c84fc28bf938c8d6e897a858cd95/azure_cosmos-4.9.0-py3-none-any.whl", hash = "sha256:3b60eaa01a16a857d0faf0cec304bac6fa8620a81bc268ce760339032ef617fe", size = 303157, upload-time = "2024-11-19T04:09:32.148Z" }, +] + +[[package]] +name = "azure-datastore-utils" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "azure-core" }, + { name = "azure-cosmos" }, + { name = "azure-identity" }, + { name = "azure-search-documents" }, + { name = "certifi" }, + { name = "hatchling" }, + { name = "pydantic" }, + { name = "redis" }, + { name = "redis-entraid" }, + { name = "uv-dynamic-versioning" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/01/d0c7da86dbb0aa6d3dad4fea268d20ecdc7d179f866f13abbe006813ad5c/azure_datastore_utils-0.2.4.tar.gz", hash = "sha256:02be1b710ec5ea39a70f7c3230c77956b74a324397cd8ebac54fe67ab6a4d27a", size = 62875, upload-time = "2025-09-10T21:14:07.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/2f/777e48a8d0946d126610f1f2a950c632bdeb322595c684dcc3d45e3ec60c/azure_datastore_utils-0.2.4-py3-none-any.whl", hash = "sha256:978c31a228ba4d67b1977e438230cdf0f6dc098e16bc8bb194c10d3a42b2cd41", size = 20334, upload-time = "2025-09-10T21:14:06.325Z" }, +] + +[[package]] +name = "azure-identity" +version = "1.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-core" }, + { name = "cryptography" }, + { name = "msal" }, + { name = "msal-extensions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/89/7d170fab0b85d9650cdb7abda087e849644beb52bd28f6804620dd0cecd9/azure_identity-1.20.0.tar.gz", hash = "sha256:40597210d56c83e15031b0fe2ea3b26420189e1e7f3e20bdbb292315da1ba014", size = 264447, upload-time = "2025-02-12T00:40:41.225Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/aa/819513c1dbef990af690bb5eefb5e337f8698d75dfdb7302528f50ce1994/azure_identity-1.20.0-py3-none-any.whl", hash = "sha256:5f23fc4889a66330e840bd78830287e14f3761820fe3c5f77ac875edcb9ec998", size = 188243, upload-time = "2025-02-12T00:40:44.99Z" }, +] + +[[package]] +name = "azure-search-documents" +version = "11.5.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-common" }, + { name = "azure-core" }, + { name = "isodate" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/11/9ecde2bd9e6c00cc0e3f312ab096a33d333f8ba40c847f01f94d524895fe/azure_search_documents-11.5.3.tar.gz", hash = "sha256:6931149ec0db90485d78648407f18ea4271420473c7cb646bf87790374439989", size = 300353, upload-time = "2025-06-25T16:48:58.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/f5/0f6b52567cbb33f1efba13060514ed7088a86de84d74b77cda17d278bcd9/azure_search_documents-11.5.3-py3-none-any.whl", hash = "sha256:110617751c6c8bd50b1f0af2b00a478bd4fbaf4e2f0387e3454c26ec3eb433d6", size = 298772, upload-time = "2025-06-25T16:49:00.764Z" }, +] + +[[package]] +name = "boto3" +version = "1.40.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/b1/0f91a07dc87485a791f2d31df1c2dc75dc5d302fbf002e5446ffa04e8e32/boto3-1.40.17.tar.gz", hash = "sha256:e115dc87d5975d32dfa0ebaf19c39e360665317a350004fa94b03200fe853f2e", size = 112054, upload-time = "2025-08-25T19:37:21.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/b5/1973ed8c107beb2fe5a510d5609603537a4e18a920ead021bed5699c5437/boto3-1.40.17-py3-none-any.whl", hash = "sha256:2cacecd689cb51d81fbf54f84b64d0e6e922fbc18ee513c568b9f61caf4221e0", size = 140076, upload-time = "2025-08-25T19:37:20.087Z" }, +] + +[[package]] +name = "botocore" +version = "1.40.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/87/92b520e7f4ac2a64c6e68bedc1dc3c1335a5aa1efb89a4247b45e34e40ac/botocore-1.40.17.tar.gz", hash = "sha256:769cd04a6a612f2d48b5f456c676fd81733fab682870952f7e2887260ea6a2bc", size = 14375996, upload-time = "2025-08-25T19:37:11.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/fd/bcc913de90d6f0549a04ee40caaf7d4e76efb5a622fc6cc47379f686e50f/botocore-1.40.17-py3-none-any.whl", hash = "sha256:603951935c1a741ae70236bf15725c5293074f28503e7029ad0e24ece476a342", size = 14035937, upload-time = "2025-08-25T19:37:06.75Z" }, +] + +[[package]] +name = "cachetools" +version = "5.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/81/3747dad6b14fa2cf53fcf10548cf5aea6913e96fab41a3c198676f8948a5/cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", size = 28380, upload-time = "2025-02-20T21:01:19.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a", size = 10080, upload-time = "2025-02-20T21:01:16.647Z" }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + +[[package]] +name = "cohere" +version = "5.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastavro" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "pydantic" }, + { name = "pydantic-core" }, + { name = "requests" }, + { name = "tokenizers" }, + { name = "types-requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/ea/0b4bfb4b7f0f445db97acc979308f80ed5ab31df3786b1951d6e48b30d27/cohere-5.17.0.tar.gz", hash = "sha256:70d2fb7bccf8c9de77b07e1c0b3d93accf6346242e3cdc6ce293b577afa74a63", size = 164665, upload-time = "2025-08-13T06:58:00.608Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/21/d0eb7c8e5b3bb748190c59819928c38cafcdf8f8aaca9d21074c64cf1cae/cohere-5.17.0-py3-none-any.whl", hash = "sha256:fe7d8228cda5335a7db79a828893765a4d5a40b7f7a43443736f339dc7813fa4", size = 295301, upload-time = "2025-08-13T06:57:59.072Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "contoso-retail-application" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "azure-datastore-utils" }, + { name = "mcp" }, + { name = "pydantic-ai" }, + { name = "pydantic-graph" }, + { name = "rich" }, +] + +[package.metadata] +requires-dist = [ + { name = "azure-datastore-utils", specifier = "==0.2.4" }, + { name = "mcp", specifier = "==1.13.1" }, + { name = "pydantic-ai", specifier = "==1.0.2" }, + { name = "pydantic-graph", specifier = "==1.0.2" }, + { name = "rich", specifier = ">=14.1.0" }, +] + +[[package]] +name = "cryptography" +version = "45.0.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/0d/d13399c94234ee8f3df384819dc67e0c5ce215fb751d567a55a1f4b028c7/cryptography-45.0.6.tar.gz", hash = "sha256:5c966c732cf6e4a276ce83b6e4c729edda2df6929083a952cc7da973c539c719", size = 744949, upload-time = "2025-08-05T23:59:27.93Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/29/2793d178d0eda1ca4a09a7c4e09a5185e75738cc6d526433e8663b460ea6/cryptography-45.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:048e7ad9e08cf4c0ab07ff7f36cc3115924e22e2266e034450a890d9e312dd74", size = 7042702, upload-time = "2025-08-05T23:58:23.464Z" }, + { url = "https://files.pythonhosted.org/packages/b3/b6/cabd07410f222f32c8d55486c464f432808abaa1f12af9afcbe8f2f19030/cryptography-45.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:44647c5d796f5fc042bbc6d61307d04bf29bccb74d188f18051b635f20a9c75f", size = 4206483, upload-time = "2025-08-05T23:58:27.132Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9e/f9c7d36a38b1cfeb1cc74849aabe9bf817990f7603ff6eb485e0d70e0b27/cryptography-45.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e40b80ecf35ec265c452eea0ba94c9587ca763e739b8e559c128d23bff7ebbbf", size = 4429679, upload-time = "2025-08-05T23:58:29.152Z" }, + { url = "https://files.pythonhosted.org/packages/9c/2a/4434c17eb32ef30b254b9e8b9830cee4e516f08b47fdd291c5b1255b8101/cryptography-45.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:00e8724bdad672d75e6f069b27970883179bd472cd24a63f6e620ca7e41cc0c5", size = 4210553, upload-time = "2025-08-05T23:58:30.596Z" }, + { url = "https://files.pythonhosted.org/packages/ef/1d/09a5df8e0c4b7970f5d1f3aff1b640df6d4be28a64cae970d56c6cf1c772/cryptography-45.0.6-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a3085d1b319d35296176af31c90338eeb2ddac8104661df79f80e1d9787b8b2", size = 3894499, upload-time = "2025-08-05T23:58:32.03Z" }, + { url = "https://files.pythonhosted.org/packages/79/62/120842ab20d9150a9d3a6bdc07fe2870384e82f5266d41c53b08a3a96b34/cryptography-45.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1b7fa6a1c1188c7ee32e47590d16a5a0646270921f8020efc9a511648e1b2e08", size = 4458484, upload-time = "2025-08-05T23:58:33.526Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/1bc3634d45ddfed0871bfba52cf8f1ad724761662a0c792b97a951fb1b30/cryptography-45.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:275ba5cc0d9e320cd70f8e7b96d9e59903c815ca579ab96c1e37278d231fc402", size = 4210281, upload-time = "2025-08-05T23:58:35.445Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fe/ffb12c2d83d0ee625f124880a1f023b5878f79da92e64c37962bbbe35f3f/cryptography-45.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f4028f29a9f38a2025abedb2e409973709c660d44319c61762202206ed577c42", size = 4456890, upload-time = "2025-08-05T23:58:36.923Z" }, + { url = "https://files.pythonhosted.org/packages/8c/8e/b3f3fe0dc82c77a0deb5f493b23311e09193f2268b77196ec0f7a36e3f3e/cryptography-45.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ee411a1b977f40bd075392c80c10b58025ee5c6b47a822a33c1198598a7a5f05", size = 4333247, upload-time = "2025-08-05T23:58:38.781Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a6/c3ef2ab9e334da27a1d7b56af4a2417d77e7806b2e0f90d6267ce120d2e4/cryptography-45.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e2a21a8eda2d86bb604934b6b37691585bd095c1f788530c1fcefc53a82b3453", size = 4565045, upload-time = "2025-08-05T23:58:40.415Z" }, + { url = "https://files.pythonhosted.org/packages/31/c3/77722446b13fa71dddd820a5faab4ce6db49e7e0bf8312ef4192a3f78e2f/cryptography-45.0.6-cp311-abi3-win32.whl", hash = "sha256:d063341378d7ee9c91f9d23b431a3502fc8bfacd54ef0a27baa72a0843b29159", size = 2928923, upload-time = "2025-08-05T23:58:41.919Z" }, + { url = "https://files.pythonhosted.org/packages/38/63/a025c3225188a811b82932a4dcc8457a26c3729d81578ccecbcce2cb784e/cryptography-45.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:833dc32dfc1e39b7376a87b9a6a4288a10aae234631268486558920029b086ec", size = 3403805, upload-time = "2025-08-05T23:58:43.792Z" }, + { url = "https://files.pythonhosted.org/packages/5b/af/bcfbea93a30809f126d51c074ee0fac5bd9d57d068edf56c2a73abedbea4/cryptography-45.0.6-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:3436128a60a5e5490603ab2adbabc8763613f638513ffa7d311c900a8349a2a0", size = 7020111, upload-time = "2025-08-05T23:58:45.316Z" }, + { url = "https://files.pythonhosted.org/packages/98/c6/ea5173689e014f1a8470899cd5beeb358e22bb3cf5a876060f9d1ca78af4/cryptography-45.0.6-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0d9ef57b6768d9fa58e92f4947cea96ade1233c0e236db22ba44748ffedca394", size = 4198169, upload-time = "2025-08-05T23:58:47.121Z" }, + { url = "https://files.pythonhosted.org/packages/ba/73/b12995edc0c7e2311ffb57ebd3b351f6b268fed37d93bfc6f9856e01c473/cryptography-45.0.6-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea3c42f2016a5bbf71825537c2ad753f2870191134933196bee408aac397b3d9", size = 4421273, upload-time = "2025-08-05T23:58:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/f7/6e/286894f6f71926bc0da67408c853dd9ba953f662dcb70993a59fd499f111/cryptography-45.0.6-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:20ae4906a13716139d6d762ceb3e0e7e110f7955f3bc3876e3a07f5daadec5f3", size = 4199211, upload-time = "2025-08-05T23:58:50.139Z" }, + { url = "https://files.pythonhosted.org/packages/de/34/a7f55e39b9623c5cb571d77a6a90387fe557908ffc44f6872f26ca8ae270/cryptography-45.0.6-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dac5ec199038b8e131365e2324c03d20e97fe214af051d20c49db129844e8b3", size = 3883732, upload-time = "2025-08-05T23:58:52.253Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b9/c6d32edbcba0cd9f5df90f29ed46a65c4631c4fbe11187feb9169c6ff506/cryptography-45.0.6-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:18f878a34b90d688982e43f4b700408b478102dd58b3e39de21b5ebf6509c301", size = 4450655, upload-time = "2025-08-05T23:58:53.848Z" }, + { url = "https://files.pythonhosted.org/packages/77/2d/09b097adfdee0227cfd4c699b3375a842080f065bab9014248933497c3f9/cryptography-45.0.6-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5bd6020c80c5b2b2242d6c48487d7b85700f5e0038e67b29d706f98440d66eb5", size = 4198956, upload-time = "2025-08-05T23:58:55.209Z" }, + { url = "https://files.pythonhosted.org/packages/55/66/061ec6689207d54effdff535bbdf85cc380d32dd5377173085812565cf38/cryptography-45.0.6-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:eccddbd986e43014263eda489abbddfbc287af5cddfd690477993dbb31e31016", size = 4449859, upload-time = "2025-08-05T23:58:56.639Z" }, + { url = "https://files.pythonhosted.org/packages/41/ff/e7d5a2ad2d035e5a2af116e1a3adb4d8fcd0be92a18032917a089c6e5028/cryptography-45.0.6-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:550ae02148206beb722cfe4ef0933f9352bab26b087af00e48fdfb9ade35c5b3", size = 4320254, upload-time = "2025-08-05T23:58:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/82/27/092d311af22095d288f4db89fcaebadfb2f28944f3d790a4cf51fe5ddaeb/cryptography-45.0.6-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5b64e668fc3528e77efa51ca70fadcd6610e8ab231e3e06ae2bab3b31c2b8ed9", size = 4554815, upload-time = "2025-08-05T23:59:00.283Z" }, + { url = "https://files.pythonhosted.org/packages/7e/01/aa2f4940262d588a8fdf4edabe4cda45854d00ebc6eaac12568b3a491a16/cryptography-45.0.6-cp37-abi3-win32.whl", hash = "sha256:780c40fb751c7d2b0c6786ceee6b6f871e86e8718a8ff4bc35073ac353c7cd02", size = 2912147, upload-time = "2025-08-05T23:59:01.716Z" }, + { url = "https://files.pythonhosted.org/packages/0a/bc/16e0276078c2de3ceef6b5a34b965f4436215efac45313df90d55f0ba2d2/cryptography-45.0.6-cp37-abi3-win_amd64.whl", hash = "sha256:20d15aed3ee522faac1a39fbfdfee25d17b1284bafd808e1640a74846d7c4d1b", size = 3390459, upload-time = "2025-08-05T23:59:03.358Z" }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + +[[package]] +name = "dunamai" +version = "1.25.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/2f/194d9a34c4d831c6563d2d990720850f0baef9ab60cb4ad8ae0eff6acd34/dunamai-1.25.0.tar.gz", hash = "sha256:a7f8360ea286d3dbaf0b6a1473f9253280ac93d619836ad4514facb70c0719d1", size = 46155, upload-time = "2025-07-04T19:25:56.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/41/04e2a649058b0713b00d6c9bd22da35618bb157289e05d068e51fddf8d7e/dunamai-1.25.0-py3-none-any.whl", hash = "sha256:7f9dc687dd3256e613b6cc978d9daabfd2bb5deb8adc541fc135ee423ffa98ab", size = 27022, upload-time = "2025-07-04T19:25:54.863Z" }, +] + +[[package]] +name = "eval-type-backport" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/ea/8b0ac4469d4c347c6a385ff09dc3c048c2d021696664e26c7ee6791631b5/eval_type_backport-0.2.2.tar.gz", hash = "sha256:f0576b4cf01ebb5bd358d02314d31846af5e07678387486e2c798af0e7d849c1", size = 9079, upload-time = "2024-12-21T20:09:46.005Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/31/55cd413eaccd39125368be33c46de24a1f639f2e12349b0361b4678f3915/eval_type_backport-0.2.2-py3-none-any.whl", hash = "sha256:cb6ad7c393517f476f96d456d0412ea80f0a8cf96f6892834cd9340149111b0a", size = 5830, upload-time = "2024-12-21T20:09:44.175Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastavro" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/ec/762dcf213e5b97ea1733b27d5a2798599a1fa51565b70a93690246029f84/fastavro-1.12.0.tar.gz", hash = "sha256:a67a87be149825d74006b57e52be068dfa24f3bfc6382543ec92cd72327fe152", size = 1025604, upload-time = "2025-07-31T15:16:42.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/f0/df076a541144d2f351820f3d9e20afa0e4250e6e63cb5a26f94688ed508c/fastavro-1.12.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e849c70198e5bdf6f08df54a68db36ff72bd73e8f14b1fd664323df073c496d8", size = 944288, upload-time = "2025-07-31T15:17:09.756Z" }, + { url = "https://files.pythonhosted.org/packages/52/1d/5c1ea0f6e98a441953de822c7455c9ce8c3afdc7b359dd23c5a5e5039249/fastavro-1.12.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b260e1cdc9a77853a2586b32208302c08dddfb5c20720b5179ac5330e06ce698", size = 3404895, upload-time = "2025-07-31T15:17:11.939Z" }, + { url = "https://files.pythonhosted.org/packages/36/8b/115a3ffe67fb48de0de704284fa5e793afa70932b8b2e915cc7545752f05/fastavro-1.12.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:181779688d8b80957953031f0d82ec0761be667a78e03dac642511ff996c771a", size = 3469935, upload-time = "2025-07-31T15:17:14.145Z" }, + { url = "https://files.pythonhosted.org/packages/14/f8/bf3b7370687ab21205e07b37acdd2455ca69f5d25c72d2b315faf357b1cd/fastavro-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6881caf914b36a57d1f90810f04a89bd9c837dd4a48e1b66a8b92136e85c415d", size = 3306148, upload-time = "2025-07-31T15:17:16.121Z" }, + { url = "https://files.pythonhosted.org/packages/97/55/fba2726b59a984c7aa2fc19c6e8ef1865eca6a3f66e78810d602ca22af59/fastavro-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8bf638248499eb78c422f12fedc08f9b90b5646c3368415e388691db60e7defb", size = 3442851, upload-time = "2025-07-31T15:17:18.738Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3e/25059b8fe0b8084fd858dca77caf0815d73e0ca4731485f34402e8d40c43/fastavro-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ed4f18b7c2f651a5ee2233676f62aac332995086768301aa2c1741859d70b53e", size = 445449, upload-time = "2025-07-31T15:17:20.438Z" }, + { url = "https://files.pythonhosted.org/packages/db/c7/f18b73b39860d54eb724f881b8932882ba10c1d4905e491cd25d159a7e49/fastavro-1.12.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dbe2b690d9caba7d888126cc1dd980a8fcf5ee73de41a104e3f15bb5e08c19c8", size = 936220, upload-time = "2025-07-31T15:17:21.994Z" }, + { url = "https://files.pythonhosted.org/packages/20/22/61ec800fda2a0f051a21b067e4005fd272070132d0a0566c5094e09b666c/fastavro-1.12.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:07ff9e6c6e8739203ccced3205646fdac6141c2efc83f4dffabf5f7d0176646d", size = 3348450, upload-time = "2025-07-31T15:17:24.186Z" }, + { url = "https://files.pythonhosted.org/packages/ca/79/1f34618fb643b99e08853e8a204441ec11a24d3e1fce050e804e6ff5c5ae/fastavro-1.12.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a172655add31882cab4e1a96b7d49f419906b465b4c2165081db7b1db79852f", size = 3417238, upload-time = "2025-07-31T15:17:26.531Z" }, + { url = "https://files.pythonhosted.org/packages/ea/0b/79611769eb15cc17992dc3699141feb0f75afd37b0cb964b4a08be45214e/fastavro-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:be20ce0331b70b35dca1a4c7808afeedf348dc517bd41602ed8fc9a1ac2247a9", size = 3252425, upload-time = "2025-07-31T15:17:28.989Z" }, + { url = "https://files.pythonhosted.org/packages/86/1a/65e0999bcc4bbb38df32706b6ae6ce626d528228667a5e0af059a8b25bb2/fastavro-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a52906681384a18b99b47e5f9eab64b4744d6e6bc91056b7e28641c7b3c59d2b", size = 3385322, upload-time = "2025-07-31T15:17:31.232Z" }, + { url = "https://files.pythonhosted.org/packages/e9/49/c06ebc9e5144f7463c2bfcb900ca01f87db934caf131bccbffc5d0aaf7ec/fastavro-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:cf153531191bcfc445c21e05dd97232a634463aa717cf99fb2214a51b9886bff", size = 445586, upload-time = "2025-07-31T15:17:32.634Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c8/46ab37076dc0f86bb255791baf9b3c3a20f77603a86a40687edacff8c03d/fastavro-1.12.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:1928e88a760688e490118e1bedf0643b1f3727e5ba59c07ac64638dab81ae2a1", size = 1025933, upload-time = "2025-07-31T15:17:34.321Z" }, + { url = "https://files.pythonhosted.org/packages/a9/7f/cb3e069dcc903034a6fe82182d92c75d981d86aee94bd028200a083696b3/fastavro-1.12.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd51b706a3ab3fe4af84a0b37f60d1bcd79295df18932494fc9f49db4ba2bab2", size = 3560435, upload-time = "2025-07-31T15:17:36.314Z" }, + { url = "https://files.pythonhosted.org/packages/d0/12/9478c28a2ac4fcc10ad9488dd3dcd5fac1ef550c3022c57840330e7cec4b/fastavro-1.12.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1148263931f6965e1942cf670f146148ca95b021ae7b7e1f98bf179f1c26cc58", size = 3453000, upload-time = "2025-07-31T15:17:38.875Z" }, + { url = "https://files.pythonhosted.org/packages/00/32/a5c8b3af9561c308c8c27da0be998b6237a47dbbdd8d5499f02731bd4073/fastavro-1.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4099e0f6fb8a55f59891c0aed6bfa90c4d20a774737e5282c74181b4703ea0cb", size = 3383233, upload-time = "2025-07-31T15:17:40.833Z" }, + { url = "https://files.pythonhosted.org/packages/42/a0/f6290f3f8059543faf3ef30efbbe9bf3e4389df881891136cd5fb1066b64/fastavro-1.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:10c586e9e3bab34307f8e3227a2988b6e8ac49bff8f7b56635cf4928a153f464", size = 3402032, upload-time = "2025-07-31T15:17:42.958Z" }, +] + +[[package]] +name = "filelock" +version = "3.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b1/b64018016eeb087db503b038296fd782586432b9c077fc5c7839e9cb6ef6/frozenlist-1.7.0.tar.gz", hash = "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f", size = 45078, upload-time = "2025-06-09T23:02:35.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a2/c8131383f1e66adad5f6ecfcce383d584ca94055a34d683bbb24ac5f2f1c/frozenlist-1.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2", size = 81424, upload-time = "2025-06-09T23:00:42.24Z" }, + { url = "https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb", size = 47952, upload-time = "2025-06-09T23:00:43.481Z" }, + { url = "https://files.pythonhosted.org/packages/01/7a/0046ef1bd6699b40acd2067ed6d6670b4db2f425c56980fa21c982c2a9db/frozenlist-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478", size = 46688, upload-time = "2025-06-09T23:00:44.793Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a2/a910bafe29c86997363fb4c02069df4ff0b5bc39d33c5198b4e9dd42d8f8/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8", size = 243084, upload-time = "2025-06-09T23:00:46.125Z" }, + { url = "https://files.pythonhosted.org/packages/64/3e/5036af9d5031374c64c387469bfcc3af537fc0f5b1187d83a1cf6fab1639/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08", size = 233524, upload-time = "2025-06-09T23:00:47.73Z" }, + { url = "https://files.pythonhosted.org/packages/06/39/6a17b7c107a2887e781a48ecf20ad20f1c39d94b2a548c83615b5b879f28/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4", size = 248493, upload-time = "2025-06-09T23:00:49.742Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/711d1337c7327d88c44d91dd0f556a1c47fb99afc060ae0ef66b4d24793d/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b", size = 244116, upload-time = "2025-06-09T23:00:51.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/fe/74e6ec0639c115df13d5850e75722750adabdc7de24e37e05a40527ca539/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e", size = 224557, upload-time = "2025-06-09T23:00:52.855Z" }, + { url = "https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca", size = 241820, upload-time = "2025-06-09T23:00:54.43Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fa/cb4a76bea23047c8462976ea7b7a2bf53997a0ca171302deae9d6dd12096/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df", size = 236542, upload-time = "2025-06-09T23:00:56.409Z" }, + { url = "https://files.pythonhosted.org/packages/5d/32/476a4b5cfaa0ec94d3f808f193301debff2ea42288a099afe60757ef6282/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5", size = 249350, upload-time = "2025-06-09T23:00:58.468Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ba/9a28042f84a6bf8ea5dbc81cfff8eaef18d78b2a1ad9d51c7bc5b029ad16/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025", size = 225093, upload-time = "2025-06-09T23:01:00.015Z" }, + { url = "https://files.pythonhosted.org/packages/bc/29/3a32959e68f9cf000b04e79ba574527c17e8842e38c91d68214a37455786/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01", size = 245482, upload-time = "2025-06-09T23:01:01.474Z" }, + { url = "https://files.pythonhosted.org/packages/80/e8/edf2f9e00da553f07f5fa165325cfc302dead715cab6ac8336a5f3d0adc2/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08", size = 249590, upload-time = "2025-06-09T23:01:02.961Z" }, + { url = "https://files.pythonhosted.org/packages/1c/80/9a0eb48b944050f94cc51ee1c413eb14a39543cc4f760ed12657a5a3c45a/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43", size = 237785, upload-time = "2025-06-09T23:01:05.095Z" }, + { url = "https://files.pythonhosted.org/packages/f3/74/87601e0fb0369b7a2baf404ea921769c53b7ae00dee7dcfe5162c8c6dbf0/frozenlist-1.7.0-cp312-cp312-win32.whl", hash = "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3", size = 39487, upload-time = "2025-06-09T23:01:06.54Z" }, + { url = "https://files.pythonhosted.org/packages/0b/15/c026e9a9fc17585a9d461f65d8593d281fedf55fbf7eb53f16c6df2392f9/frozenlist-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a", size = 43874, upload-time = "2025-06-09T23:01:07.752Z" }, + { url = "https://files.pythonhosted.org/packages/24/90/6b2cebdabdbd50367273c20ff6b57a3dfa89bd0762de02c3a1eb42cb6462/frozenlist-1.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee", size = 79791, upload-time = "2025-06-09T23:01:09.368Z" }, + { url = "https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d", size = 47165, upload-time = "2025-06-09T23:01:10.653Z" }, + { url = "https://files.pythonhosted.org/packages/f4/25/a0895c99270ca6966110f4ad98e87e5662eab416a17e7fd53c364bf8b954/frozenlist-1.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43", size = 45881, upload-time = "2025-06-09T23:01:12.296Z" }, + { url = "https://files.pythonhosted.org/packages/19/7c/71bb0bbe0832793c601fff68cd0cf6143753d0c667f9aec93d3c323f4b55/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d", size = 232409, upload-time = "2025-06-09T23:01:13.641Z" }, + { url = "https://files.pythonhosted.org/packages/c0/45/ed2798718910fe6eb3ba574082aaceff4528e6323f9a8570be0f7028d8e9/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee", size = 225132, upload-time = "2025-06-09T23:01:15.264Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e2/8417ae0f8eacb1d071d4950f32f229aa6bf68ab69aab797b72a07ea68d4f/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb", size = 237638, upload-time = "2025-06-09T23:01:16.752Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b7/2ace5450ce85f2af05a871b8c8719b341294775a0a6c5585d5e6170f2ce7/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f", size = 233539, upload-time = "2025-06-09T23:01:18.202Z" }, + { url = "https://files.pythonhosted.org/packages/46/b9/6989292c5539553dba63f3c83dc4598186ab2888f67c0dc1d917e6887db6/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60", size = 215646, upload-time = "2025-06-09T23:01:19.649Z" }, + { url = "https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00", size = 232233, upload-time = "2025-06-09T23:01:21.175Z" }, + { url = "https://files.pythonhosted.org/packages/59/52/460db4d7ba0811b9ccb85af996019f5d70831f2f5f255f7cc61f86199795/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b", size = 227996, upload-time = "2025-06-09T23:01:23.098Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/f4b39e904c03927b7ecf891804fd3b4df3db29b9e487c6418e37988d6e9d/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c", size = 242280, upload-time = "2025-06-09T23:01:24.808Z" }, + { url = "https://files.pythonhosted.org/packages/b8/33/3f8d6ced42f162d743e3517781566b8481322be321b486d9d262adf70bfb/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949", size = 217717, upload-time = "2025-06-09T23:01:26.28Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e8/ad683e75da6ccef50d0ab0c2b2324b32f84fc88ceee778ed79b8e2d2fe2e/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca", size = 236644, upload-time = "2025-06-09T23:01:27.887Z" }, + { url = "https://files.pythonhosted.org/packages/b2/14/8d19ccdd3799310722195a72ac94ddc677541fb4bef4091d8e7775752360/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b", size = 238879, upload-time = "2025-06-09T23:01:29.524Z" }, + { url = "https://files.pythonhosted.org/packages/ce/13/c12bf657494c2fd1079a48b2db49fa4196325909249a52d8f09bc9123fd7/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e", size = 232502, upload-time = "2025-06-09T23:01:31.287Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8b/e7f9dfde869825489382bc0d512c15e96d3964180c9499efcec72e85db7e/frozenlist-1.7.0-cp313-cp313-win32.whl", hash = "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1", size = 39169, upload-time = "2025-06-09T23:01:35.503Z" }, + { url = "https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba", size = 43219, upload-time = "2025-06-09T23:01:36.784Z" }, + { url = "https://files.pythonhosted.org/packages/56/d5/5c4cf2319a49eddd9dd7145e66c4866bdc6f3dbc67ca3d59685149c11e0d/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d", size = 84345, upload-time = "2025-06-09T23:01:38.295Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/ec2c1e1dc16b85bc9d526009961953df9cec8481b6886debb36ec9107799/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d", size = 48880, upload-time = "2025-06-09T23:01:39.887Z" }, + { url = "https://files.pythonhosted.org/packages/69/86/f9596807b03de126e11e7d42ac91e3d0b19a6599c714a1989a4e85eeefc4/frozenlist-1.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b", size = 48498, upload-time = "2025-06-09T23:01:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cb/df6de220f5036001005f2d726b789b2c0b65f2363b104bbc16f5be8084f8/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146", size = 292296, upload-time = "2025-06-09T23:01:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/83/1f/de84c642f17c8f851a2905cee2dae401e5e0daca9b5ef121e120e19aa825/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74", size = 273103, upload-time = "2025-06-09T23:01:44.166Z" }, + { url = "https://files.pythonhosted.org/packages/88/3c/c840bfa474ba3fa13c772b93070893c6e9d5c0350885760376cbe3b6c1b3/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1", size = 292869, upload-time = "2025-06-09T23:01:45.681Z" }, + { url = "https://files.pythonhosted.org/packages/a6/1c/3efa6e7d5a39a1d5ef0abeb51c48fb657765794a46cf124e5aca2c7a592c/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1", size = 291467, upload-time = "2025-06-09T23:01:47.234Z" }, + { url = "https://files.pythonhosted.org/packages/4f/00/d5c5e09d4922c395e2f2f6b79b9a20dab4b67daaf78ab92e7729341f61f6/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384", size = 266028, upload-time = "2025-06-09T23:01:48.819Z" }, + { url = "https://files.pythonhosted.org/packages/4e/27/72765be905619dfde25a7f33813ac0341eb6b076abede17a2e3fbfade0cb/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb", size = 284294, upload-time = "2025-06-09T23:01:50.394Z" }, + { url = "https://files.pythonhosted.org/packages/88/67/c94103a23001b17808eb7dd1200c156bb69fb68e63fcf0693dde4cd6228c/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c", size = 281898, upload-time = "2025-06-09T23:01:52.234Z" }, + { url = "https://files.pythonhosted.org/packages/42/34/a3e2c00c00f9e2a9db5653bca3fec306349e71aff14ae45ecc6d0951dd24/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65", size = 290465, upload-time = "2025-06-09T23:01:53.788Z" }, + { url = "https://files.pythonhosted.org/packages/bb/73/f89b7fbce8b0b0c095d82b008afd0590f71ccb3dee6eee41791cf8cd25fd/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3", size = 266385, upload-time = "2025-06-09T23:01:55.769Z" }, + { url = "https://files.pythonhosted.org/packages/cd/45/e365fdb554159462ca12df54bc59bfa7a9a273ecc21e99e72e597564d1ae/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657", size = 288771, upload-time = "2025-06-09T23:01:57.4Z" }, + { url = "https://files.pythonhosted.org/packages/00/11/47b6117002a0e904f004d70ec5194fe9144f117c33c851e3d51c765962d0/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104", size = 288206, upload-time = "2025-06-09T23:01:58.936Z" }, + { url = "https://files.pythonhosted.org/packages/40/37/5f9f3c3fd7f7746082ec67bcdc204db72dad081f4f83a503d33220a92973/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf", size = 282620, upload-time = "2025-06-09T23:02:00.493Z" }, + { url = "https://files.pythonhosted.org/packages/0b/31/8fbc5af2d183bff20f21aa743b4088eac4445d2bb1cdece449ae80e4e2d1/frozenlist-1.7.0-cp313-cp313t-win32.whl", hash = "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81", size = 43059, upload-time = "2025-06-09T23:02:02.072Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ed/41956f52105b8dbc26e457c5705340c67c8cc2b79f394b79bffc09d0e938/frozenlist-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e", size = 47516, upload-time = "2025-06-09T23:02:03.779Z" }, + { url = "https://files.pythonhosted.org/packages/ee/45/b82e3c16be2182bff01179db177fe144d58b5dc787a7d4492c6ed8b9317f/frozenlist-1.7.0-py3-none-any.whl", hash = "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e", size = 13106, upload-time = "2025-06-09T23:02:34.204Z" }, +] + +[[package]] +name = "fsspec" +version = "2025.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/02/0835e6ab9cfc03916fe3f78c0956cfcdb6ff2669ffa6651065d5ebf7fc98/fsspec-2025.7.0.tar.gz", hash = "sha256:786120687ffa54b8283d942929540d8bc5ccfa820deb555a2b5d0ed2b737bf58", size = 304432, upload-time = "2025-07-15T16:05:21.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/e0/014d5d9d7a4564cf1c40b5039bc882db69fd881111e03ab3657ac0b218e2/fsspec-2025.7.0-py3-none-any.whl", hash = "sha256:8b012e39f63c7d5f10474de957f3ab793b47b45ae7d39f2fb735f8bbe25c0e21", size = 199597, upload-time = "2025-07-15T16:05:19.529Z" }, +] + +[[package]] +name = "genai-prices" +version = "0.0.24" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/3d/59c5d4d83999acb09e3c8062e34a73969db88d18353d55b3eed495d32921/genai_prices-0.0.24.tar.gz", hash = "sha256:faeac6276964bc31ca9a2551219d4642979426bd2c593e884ec5bb40089b298e", size = 44702, upload-time = "2025-08-26T12:12:57.476Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/d4/48ec6b327c2ba8c381a10484dd97f15e6b51a1ea708dc783e71fc5e01234/genai_prices-0.0.24-py3-none-any.whl", hash = "sha256:620beb35a845b32463201bb2816060181500e15c0a715b3bfa2583ef58e0702d", size = 47028, upload-time = "2025-08-26T12:12:56.162Z" }, +] + +[[package]] +name = "google-auth" +version = "2.40.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachetools" }, + { name = "pyasn1-modules" }, + { name = "rsa" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/9b/e92ef23b84fa10a64ce4831390b7a4c2e53c0132568d99d4ae61d04c8855/google_auth-2.40.3.tar.gz", hash = "sha256:500c3a29adedeb36ea9cf24b8d10858e152f2412e3ca37829b3fa18e33d63b77", size = 281029, upload-time = "2025-06-04T18:04:57.577Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/63/b19553b658a1692443c62bd07e5868adaa0ad746a0751ba62c59568cd45b/google_auth-2.40.3-py2.py3-none-any.whl", hash = "sha256:1370d4593e86213563547f97a92752fc658456fe4514c809544f330fed45a7ca", size = 216137, upload-time = "2025-06-04T18:04:55.573Z" }, +] + +[[package]] +name = "google-genai" +version = "1.31.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "google-auth" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/1b/da30fa6e2966942d7028a58eb7aa7d04544dcc3aa66194365b2e0adac570/google_genai-1.31.0.tar.gz", hash = "sha256:8572b47aa684357c3e5e10d290ec772c65414114939e3ad2955203e27cd2fcbc", size = 233482, upload-time = "2025-08-18T23:40:21.733Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/27/1525bc9cbec58660f0842ebcbfe910a1dde908c2672373804879666e0bb8/google_genai-1.31.0-py3-none-any.whl", hash = "sha256:5c6959bcf862714e8ed0922db3aaf41885bacf6318751b3421bf1e459f78892f", size = 231876, upload-time = "2025-08-18T23:40:20.385Z" }, +] + +[[package]] +name = "googleapis-common-protos" +version = "1.70.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903, upload-time = "2025-04-14T10:17:02.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" }, +] + +[[package]] +name = "griffe" +version = "1.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/b5/23b91f22b7b3a7f8f62223f6664946271c0f5cb4179605a3e6bbae863920/griffe-1.13.0.tar.gz", hash = "sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0", size = 412759, upload-time = "2025-08-26T13:27:11.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/8c/b7cfdd8dfe48f6b09f7353323732e1a290c388bd14f216947928dc85f904/griffe-1.13.0-py3-none-any.whl", hash = "sha256:470fde5b735625ac0a36296cd194617f039e9e83e301fcbd493e2b58382d0559", size = 139365, upload-time = "2025-08-26T13:27:09.882Z" }, +] + +[[package]] +name = "groq" +version = "0.31.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/a2/77fd1460e7d55859219223719aa44ae8902a3a1ad333cd5faf330eb0b894/groq-0.31.0.tar.gz", hash = "sha256:182252e9bf0d696df607c137cbafa851d2c84aaf94bcfe9165c0bc231043490c", size = 136237, upload-time = "2025-08-05T23:14:01.183Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/f8/14672d69a91495f43462c5490067eeafc30346e81bda1a62848e897f9bc3/groq-0.31.0-py3-none-any.whl", hash = "sha256:5e3c7ec9728b7cccf913da982a9b5ebb46dc18a070b35e12a3d6a1e12d6b0f7f", size = 131365, upload-time = "2025-08-05T23:13:59.768Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "hatchling" +version = "1.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "pathspec" }, + { name = "pluggy" }, + { name = "trove-classifiers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/8a/cc1debe3514da292094f1c3a700e4ca25442489731ef7c0814358816bb03/hatchling-1.27.0.tar.gz", hash = "sha256:971c296d9819abb3811112fc52c7a9751c8d381898f36533bb16f9791e941fd6", size = 54983, upload-time = "2024-12-15T17:08:11.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/e7/ae38d7a6dfba0533684e0b2136817d667588ae3ec984c1a4e5df5eb88482/hatchling-1.27.0-py3-none-any.whl", hash = "sha256:d3a2f3567c4f926ea39849cdf924c7e99e6686c9c8e288ae1037c8fa2a5d937b", size = 75794, upload-time = "2024-12-15T17:08:10.364Z" }, +] + +[[package]] +name = "hf-xet" +version = "1.1.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/49/91010b59debc7c862a5fd426d343134dd9a68778dbe570234b6495a4e204/hf_xet-1.1.8.tar.gz", hash = "sha256:62a0043e441753bbc446dcb5a3fe40a4d03f5fb9f13589ef1df9ab19252beb53", size = 484065, upload-time = "2025-08-18T22:01:03.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/91/5814db3a0d4a65fb6a87f0931ae28073b87f06307701fe66e7c41513bfb4/hf_xet-1.1.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3d5f82e533fc51c7daad0f9b655d9c7811b5308e5890236828bd1dd3ed8fea74", size = 2752357, upload-time = "2025-08-18T22:00:58.777Z" }, + { url = "https://files.pythonhosted.org/packages/70/72/ce898516e97341a7a9d450609e130e108643389110261eaee6deb1ba8545/hf_xet-1.1.8-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:8e2dba5896bca3ab61d0bef4f01a1647004de59640701b37e37eaa57087bbd9d", size = 2613142, upload-time = "2025-08-18T22:00:57.252Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d6/13af5f916cef795ac2b5e4cc1de31f2e0e375f4475d50799915835f301c2/hf_xet-1.1.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfe5700bc729be3d33d4e9a9b5cc17a951bf8c7ada7ba0c9198a6ab2053b7453", size = 3175859, upload-time = "2025-08-18T22:00:55.978Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ed/34a193c9d1d72b7c3901b3b5153b1be9b2736b832692e1c3f167af537102/hf_xet-1.1.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:09e86514c3c4284ed8a57d6b0f3d089f9836a0af0a1ceb3c9dd664f1f3eaefef", size = 3074178, upload-time = "2025-08-18T22:00:54.147Z" }, + { url = "https://files.pythonhosted.org/packages/4a/1b/de6817b4bf65385280252dff5c9cceeedfbcb27ddb93923639323c1034a4/hf_xet-1.1.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4a9b99ab721d385b83f4fc8ee4e0366b0b59dce03b5888a86029cc0ca634efbf", size = 3238122, upload-time = "2025-08-18T22:01:00.546Z" }, + { url = "https://files.pythonhosted.org/packages/b7/13/874c85c7ed519ec101deb654f06703d9e5e68d34416730f64c4755ada36a/hf_xet-1.1.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25b9d43333bbef39aeae1616789ec329c21401a7fe30969d538791076227b591", size = 3344325, upload-time = "2025-08-18T22:01:02.013Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/0aaf279f4f3dea58e99401b92c31c0f752924ba0e6c7d7bb07b1dbd7f35e/hf_xet-1.1.8-cp37-abi3-win_amd64.whl", hash = "sha256:4171f31d87b13da4af1ed86c98cf763292e4720c088b4957cf9d564f92904ca9", size = 2801689, upload-time = "2025-08-18T22:01:04.81Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624, upload-time = "2023-12-22T08:01:21.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819, upload-time = "2023-12-22T08:01:19.89Z" }, +] + +[[package]] +name = "huggingface-hub" +version = "0.34.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "hf-xet", marker = "platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/c9/bdbe19339f76d12985bc03572f330a01a93c04dffecaaea3061bdd7fb892/huggingface_hub-0.34.4.tar.gz", hash = "sha256:a4228daa6fb001be3f4f4bdaf9a0db00e1739235702848df00885c9b5742c85c", size = 459768, upload-time = "2025-08-08T09:14:52.365Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/7b/bb06b061991107cd8783f300adff3e7b7f284e330fd82f507f2a1417b11d/huggingface_hub-0.34.4-py3-none-any.whl", hash = "sha256:9b365d781739c93ff90c359844221beef048403f1bc1f1c123c191257c3c890a", size = 561452, upload-time = "2025-08-08T09:14:50.159Z" }, +] + +[package.optional-dependencies] +inference = [ + { name = "aiohttp" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, +] + +[[package]] +name = "invoke" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/42/127e6d792884ab860defc3f4d80a8f9812e48ace584ffc5a346de58cdc6c/invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5", size = 299835, upload-time = "2023-07-12T18:05:17.998Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/66/7f8c48009c72d73bc6bbe6eb87ac838d6a526146f7dab14af671121eb379/invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820", size = 160274, upload-time = "2023-07-12T18:05:16.294Z" }, +] + +[[package]] +name = "isodate" +version = "0.7.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705, upload-time = "2024-10-08T23:04:11.5Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jiter" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/9d/ae7ddb4b8ab3fb1b51faf4deb36cb48a4fbbd7cb36bad6a5fca4741306f7/jiter-0.10.0.tar.gz", hash = "sha256:07a7142c38aacc85194391108dc91b5b57093c978a9932bd86a36862759d9500", size = 162759, upload-time = "2025-05-18T19:04:59.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/b5/348b3313c58f5fbfb2194eb4d07e46a35748ba6e5b3b3046143f3040bafa/jiter-0.10.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1e274728e4a5345a6dde2d343c8da018b9d4bd4350f5a472fa91f66fda44911b", size = 312262, upload-time = "2025-05-18T19:03:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/9c/4a/6a2397096162b21645162825f058d1709a02965606e537e3304b02742e9b/jiter-0.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7202ae396446c988cb2a5feb33a543ab2165b786ac97f53b59aafb803fef0744", size = 320124, upload-time = "2025-05-18T19:03:46.341Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/1ce02cade7516b726dd88f59a4ee46914bf79d1676d1228ef2002ed2f1c9/jiter-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23ba7722d6748b6920ed02a8f1726fb4b33e0fd2f3f621816a8b486c66410ab2", size = 345330, upload-time = "2025-05-18T19:03:47.596Z" }, + { url = "https://files.pythonhosted.org/packages/75/d0/bb6b4f209a77190ce10ea8d7e50bf3725fc16d3372d0a9f11985a2b23eff/jiter-0.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:371eab43c0a288537d30e1f0b193bc4eca90439fc08a022dd83e5e07500ed026", size = 369670, upload-time = "2025-05-18T19:03:49.334Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f5/a61787da9b8847a601e6827fbc42ecb12be2c925ced3252c8ffcb56afcaf/jiter-0.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c675736059020365cebc845a820214765162728b51ab1e03a1b7b3abb70f74c", size = 489057, upload-time = "2025-05-18T19:03:50.66Z" }, + { url = "https://files.pythonhosted.org/packages/12/e4/6f906272810a7b21406c760a53aadbe52e99ee070fc5c0cb191e316de30b/jiter-0.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c5867d40ab716e4684858e4887489685968a47e3ba222e44cde6e4a2154f959", size = 389372, upload-time = "2025-05-18T19:03:51.98Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ba/77013b0b8ba904bf3762f11e0129b8928bff7f978a81838dfcc958ad5728/jiter-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395bb9a26111b60141757d874d27fdea01b17e8fac958b91c20128ba8f4acc8a", size = 352038, upload-time = "2025-05-18T19:03:53.703Z" }, + { url = "https://files.pythonhosted.org/packages/67/27/c62568e3ccb03368dbcc44a1ef3a423cb86778a4389e995125d3d1aaa0a4/jiter-0.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6842184aed5cdb07e0c7e20e5bdcfafe33515ee1741a6835353bb45fe5d1bd95", size = 391538, upload-time = "2025-05-18T19:03:55.046Z" }, + { url = "https://files.pythonhosted.org/packages/c0/72/0d6b7e31fc17a8fdce76164884edef0698ba556b8eb0af9546ae1a06b91d/jiter-0.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62755d1bcea9876770d4df713d82606c8c1a3dca88ff39046b85a048566d56ea", size = 523557, upload-time = "2025-05-18T19:03:56.386Z" }, + { url = "https://files.pythonhosted.org/packages/2f/09/bc1661fbbcbeb6244bd2904ff3a06f340aa77a2b94e5a7373fd165960ea3/jiter-0.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533efbce2cacec78d5ba73a41756beff8431dfa1694b6346ce7af3a12c42202b", size = 514202, upload-time = "2025-05-18T19:03:57.675Z" }, + { url = "https://files.pythonhosted.org/packages/1b/84/5a5d5400e9d4d54b8004c9673bbe4403928a00d28529ff35b19e9d176b19/jiter-0.10.0-cp312-cp312-win32.whl", hash = "sha256:8be921f0cadd245e981b964dfbcd6fd4bc4e254cdc069490416dd7a2632ecc01", size = 211781, upload-time = "2025-05-18T19:03:59.025Z" }, + { url = "https://files.pythonhosted.org/packages/9b/52/7ec47455e26f2d6e5f2ea4951a0652c06e5b995c291f723973ae9e724a65/jiter-0.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7c7d785ae9dda68c2678532a5a1581347e9c15362ae9f6e68f3fdbfb64f2e49", size = 206176, upload-time = "2025-05-18T19:04:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b0/279597e7a270e8d22623fea6c5d4eeac328e7d95c236ed51a2b884c54f70/jiter-0.10.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e0588107ec8e11b6f5ef0e0d656fb2803ac6cf94a96b2b9fc675c0e3ab5e8644", size = 311617, upload-time = "2025-05-18T19:04:02.078Z" }, + { url = "https://files.pythonhosted.org/packages/91/e3/0916334936f356d605f54cc164af4060e3e7094364add445a3bc79335d46/jiter-0.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cafc4628b616dc32530c20ee53d71589816cf385dd9449633e910d596b1f5c8a", size = 318947, upload-time = "2025-05-18T19:04:03.347Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8e/fd94e8c02d0e94539b7d669a7ebbd2776e51f329bb2c84d4385e8063a2ad/jiter-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:520ef6d981172693786a49ff5b09eda72a42e539f14788124a07530f785c3ad6", size = 344618, upload-time = "2025-05-18T19:04:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/6f/b0/f9f0a2ec42c6e9c2e61c327824687f1e2415b767e1089c1d9135f43816bd/jiter-0.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:554dedfd05937f8fc45d17ebdf298fe7e0c77458232bcb73d9fbbf4c6455f5b3", size = 368829, upload-time = "2025-05-18T19:04:06.912Z" }, + { url = "https://files.pythonhosted.org/packages/e8/57/5bbcd5331910595ad53b9fd0c610392ac68692176f05ae48d6ce5c852967/jiter-0.10.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bc299da7789deacf95f64052d97f75c16d4fc8c4c214a22bf8d859a4288a1c2", size = 491034, upload-time = "2025-05-18T19:04:08.222Z" }, + { url = "https://files.pythonhosted.org/packages/9b/be/c393df00e6e6e9e623a73551774449f2f23b6ec6a502a3297aeeece2c65a/jiter-0.10.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5161e201172de298a8a1baad95eb85db4fb90e902353b1f6a41d64ea64644e25", size = 388529, upload-time = "2025-05-18T19:04:09.566Z" }, + { url = "https://files.pythonhosted.org/packages/42/3e/df2235c54d365434c7f150b986a6e35f41ebdc2f95acea3036d99613025d/jiter-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e2227db6ba93cb3e2bf67c87e594adde0609f146344e8207e8730364db27041", size = 350671, upload-time = "2025-05-18T19:04:10.98Z" }, + { url = "https://files.pythonhosted.org/packages/c6/77/71b0b24cbcc28f55ab4dbfe029f9a5b73aeadaba677843fc6dc9ed2b1d0a/jiter-0.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15acb267ea5e2c64515574b06a8bf393fbfee6a50eb1673614aa45f4613c0cca", size = 390864, upload-time = "2025-05-18T19:04:12.722Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d3/ef774b6969b9b6178e1d1e7a89a3bd37d241f3d3ec5f8deb37bbd203714a/jiter-0.10.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:901b92f2e2947dc6dfcb52fd624453862e16665ea909a08398dde19c0731b7f4", size = 522989, upload-time = "2025-05-18T19:04:14.261Z" }, + { url = "https://files.pythonhosted.org/packages/0c/41/9becdb1d8dd5d854142f45a9d71949ed7e87a8e312b0bede2de849388cb9/jiter-0.10.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d0cb9a125d5a3ec971a094a845eadde2db0de85b33c9f13eb94a0c63d463879e", size = 513495, upload-time = "2025-05-18T19:04:15.603Z" }, + { url = "https://files.pythonhosted.org/packages/9c/36/3468e5a18238bdedae7c4d19461265b5e9b8e288d3f86cd89d00cbb48686/jiter-0.10.0-cp313-cp313-win32.whl", hash = "sha256:48a403277ad1ee208fb930bdf91745e4d2d6e47253eedc96e2559d1e6527006d", size = 211289, upload-time = "2025-05-18T19:04:17.541Z" }, + { url = "https://files.pythonhosted.org/packages/7e/07/1c96b623128bcb913706e294adb5f768fb7baf8db5e1338ce7b4ee8c78ef/jiter-0.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:75f9eb72ecb640619c29bf714e78c9c46c9c4eaafd644bf78577ede459f330d4", size = 205074, upload-time = "2025-05-18T19:04:19.21Z" }, + { url = "https://files.pythonhosted.org/packages/54/46/caa2c1342655f57d8f0f2519774c6d67132205909c65e9aa8255e1d7b4f4/jiter-0.10.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:28ed2a4c05a1f32ef0e1d24c2611330219fed727dae01789f4a335617634b1ca", size = 318225, upload-time = "2025-05-18T19:04:20.583Z" }, + { url = "https://files.pythonhosted.org/packages/43/84/c7d44c75767e18946219ba2d703a5a32ab37b0bc21886a97bc6062e4da42/jiter-0.10.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a4c418b1ec86a195f1ca69da8b23e8926c752b685af665ce30777233dfe070", size = 350235, upload-time = "2025-05-18T19:04:22.363Z" }, + { url = "https://files.pythonhosted.org/packages/01/16/f5a0135ccd968b480daad0e6ab34b0c7c5ba3bc447e5088152696140dcb3/jiter-0.10.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d7bfed2fe1fe0e4dda6ef682cee888ba444b21e7a6553e03252e4feb6cf0adca", size = 207278, upload-time = "2025-05-18T19:04:23.627Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9b/1d646da42c3de6c2188fdaa15bce8ecb22b635904fc68be025e21249ba44/jiter-0.10.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:5e9251a5e83fab8d87799d3e1a46cb4b7f2919b895c6f4483629ed2446f66522", size = 310866, upload-time = "2025-05-18T19:04:24.891Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0e/26538b158e8a7c7987e94e7aeb2999e2e82b1f9d2e1f6e9874ddf71ebda0/jiter-0.10.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:023aa0204126fe5b87ccbcd75c8a0d0261b9abdbbf46d55e7ae9f8e22424eeb8", size = 318772, upload-time = "2025-05-18T19:04:26.161Z" }, + { url = "https://files.pythonhosted.org/packages/7b/fb/d302893151caa1c2636d6574d213e4b34e31fd077af6050a9c5cbb42f6fb/jiter-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c189c4f1779c05f75fc17c0c1267594ed918996a231593a21a5ca5438445216", size = 344534, upload-time = "2025-05-18T19:04:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/01/d8/5780b64a149d74e347c5128d82176eb1e3241b1391ac07935693466d6219/jiter-0.10.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15720084d90d1098ca0229352607cd68256c76991f6b374af96f36920eae13c4", size = 369087, upload-time = "2025-05-18T19:04:28.896Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5b/f235a1437445160e777544f3ade57544daf96ba7e96c1a5b24a6f7ac7004/jiter-0.10.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4f2fb68e5f1cfee30e2b2a09549a00683e0fde4c6a2ab88c94072fc33cb7426", size = 490694, upload-time = "2025-05-18T19:04:30.183Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/9c3d4617caa2ff89cf61b41e83820c27ebb3f7b5fae8a72901e8cd6ff9be/jiter-0.10.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce541693355fc6da424c08b7edf39a2895f58d6ea17d92cc2b168d20907dee12", size = 388992, upload-time = "2025-05-18T19:04:32.028Z" }, + { url = "https://files.pythonhosted.org/packages/68/b1/344fd14049ba5c94526540af7eb661871f9c54d5f5601ff41a959b9a0bbd/jiter-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31c50c40272e189d50006ad5c73883caabb73d4e9748a688b216e85a9a9ca3b9", size = 351723, upload-time = "2025-05-18T19:04:33.467Z" }, + { url = "https://files.pythonhosted.org/packages/41/89/4c0e345041186f82a31aee7b9d4219a910df672b9fef26f129f0cda07a29/jiter-0.10.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fa3402a2ff9815960e0372a47b75c76979d74402448509ccd49a275fa983ef8a", size = 392215, upload-time = "2025-05-18T19:04:34.827Z" }, + { url = "https://files.pythonhosted.org/packages/55/58/ee607863e18d3f895feb802154a2177d7e823a7103f000df182e0f718b38/jiter-0.10.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:1956f934dca32d7bb647ea21d06d93ca40868b505c228556d3373cbd255ce853", size = 522762, upload-time = "2025-05-18T19:04:36.19Z" }, + { url = "https://files.pythonhosted.org/packages/15/d0/9123fb41825490d16929e73c212de9a42913d68324a8ce3c8476cae7ac9d/jiter-0.10.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:fcedb049bdfc555e261d6f65a6abe1d5ad68825b7202ccb9692636c70fcced86", size = 513427, upload-time = "2025-05-18T19:04:37.544Z" }, + { url = "https://files.pythonhosted.org/packages/d8/b3/2bd02071c5a2430d0b70403a34411fc519c2f227da7b03da9ba6a956f931/jiter-0.10.0-cp314-cp314-win32.whl", hash = "sha256:ac509f7eccca54b2a29daeb516fb95b6f0bd0d0d8084efaf8ed5dfc7b9f0b357", size = 210127, upload-time = "2025-05-18T19:04:38.837Z" }, + { url = "https://files.pythonhosted.org/packages/03/0c/5fe86614ea050c3ecd728ab4035534387cd41e7c1855ef6c031f1ca93e3f/jiter-0.10.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5ed975b83a2b8639356151cef5c0d597c68376fc4922b45d0eb384ac058cfa00", size = 318527, upload-time = "2025-05-18T19:04:40.612Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4a/4175a563579e884192ba6e81725fc0448b042024419be8d83aa8a80a3f44/jiter-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa96f2abba33dc77f79b4cf791840230375f9534e5fac927ccceb58c5e604a5", size = 354213, upload-time = "2025-05-18T19:04:41.894Z" }, +] + +[[package]] +name = "jmespath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bf/ce/46fbd9c8119cfc3581ee5643ea49464d168028cfb5caff5fc0596d0cf914/jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608", size = 15513, upload-time = "2025-04-23T12:34:07.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" }, +] + +[[package]] +name = "logfire" +version = "4.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "executing" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/fa/14cbd976e8ff77290c0c87f93c45029785537ffb84e2f5215416786cda11/logfire-4.6.0.tar.gz", hash = "sha256:974bc8f4efd3aa9df2d0c7b1d53b35dc4612ff5cee2be6c40dd65e5c26eab694", size = 533174, upload-time = "2025-09-10T14:56:42.168Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/9c/6384dc69601bfba19c1f5909a472b00cc4b5863f411ecf85be308beacf8f/logfire-4.6.0-py3-none-any.whl", hash = "sha256:d322844db7a2f1935976f2852a07e3753489ecc4e83fa288173b05a453bb1cbf", size = 219556, upload-time = "2025-09-10T14:56:37.278Z" }, +] + +[package.optional-dependencies] +httpx = [ + { name = "opentelemetry-instrumentation-httpx" }, +] + +[[package]] +name = "logfire-api" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/99/130ff82b2eed7856b7192d3a948071e519eff58f777ad5fb49a44e8953c1/logfire_api-4.3.6.tar.gz", hash = "sha256:c07e4fa165e15f0b22e5ff39c0253b48dc9a4b42ab574fb0d63eb40050c07ae1", size = 52914, upload-time = "2025-08-26T07:59:28.627Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/e8/b830d18f680e70215ba6cd150a335954f82fd86d65003902c133d8f14aa0/logfire_api-4.3.6-py3-none-any.whl", hash = "sha256:40c190d4aaca1d223bf1e312adda274288ea9267b6e9c4e6c1a896a14c006eed", size = 88495, upload-time = "2025-08-26T07:59:24.953Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, +] + +[[package]] +name = "mcp" +version = "1.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/3c/82c400c2d50afdac4fbefb5b4031fd327e2ad1f23ccef8eee13c5909aa48/mcp-1.13.1.tar.gz", hash = "sha256:165306a8fd7991dc80334edd2de07798175a56461043b7ae907b279794a834c5", size = 438198, upload-time = "2025-08-22T09:22:16.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/3f/d085c7f49ade6d273b185d61ec9405e672b6433f710ea64a90135a8dd445/mcp-1.13.1-py3-none-any.whl", hash = "sha256:c314e7c8bd477a23ba3ef472ee5a32880316c42d03e06dcfa31a1cc7a73b65df", size = 161494, upload-time = "2025-08-22T09:22:14.705Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mistralai" +version = "1.9.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eval-type-backport" }, + { name = "httpx" }, + { name = "invoke" }, + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "pyyaml" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dc/6f/12296d29c480a4101e2bc092347895ce1a8047b6bbc52f97f124177df0b4/mistralai-1.9.8.tar.gz", hash = "sha256:74eac8b3aee410dffbd8ef0878adb7f593940fa9592d9eb4428da9b067209b22", size = 204432, upload-time = "2025-08-25T16:30:31.354Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/b3/3c1d449eea89153a77e7093e90e0282d1a718865ae6787c379256b1db288/mistralai-1.9.8-py3-none-any.whl", hash = "sha256:f4874d62932245c438c4fce04aaf740a9d6da651dc598bf660978a21fb73f017", size = 439113, upload-time = "2025-08-25T16:30:29.855Z" }, +] + +[[package]] +name = "msal" +version = "1.31.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/f3/cdf2681e83a73c3355883c2884b6ff2f2d2aadfc399c28e9ac4edc3994fd/msal-1.31.1.tar.gz", hash = "sha256:11b5e6a3f802ffd3a72107203e20c4eac6ef53401961b880af2835b723d80578", size = 145362, upload-time = "2024-11-18T09:51:10.143Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/7c/489cd931a752d05753d730e848039f08f65f86237cf1b8724d0a1cbd700b/msal-1.31.1-py3-none-any.whl", hash = "sha256:29d9882de247e96db01386496d59f29035e5e841bcac892e6d7bf4390bf6bd17", size = 113216, upload-time = "2024-11-18T09:51:08.402Z" }, +] + +[[package]] +name = "msal-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msal" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/99/5d239b6156eddf761a636bded1118414d161bd6b7b37a9335549ed159396/msal_extensions-1.3.1.tar.gz", hash = "sha256:c5b0fd10f65ef62b5f1d62f4251d51cbcaf003fcedae8c91b040a488614be1a4", size = 23315, upload-time = "2025-03-14T23:51:03.902Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/75/bd9b7bb966668920f06b200e84454c8f3566b102183bc55c5473d96cb2b9/msal_extensions-1.3.1-py3-none-any.whl", hash = "sha256:96d3de4d034504e969ac5e85bae8106c8373b5c6568e4c8fa7af2eca9dbe6bca", size = 20583, upload-time = "2025-03-14T23:51:03.016Z" }, +] + +[[package]] +name = "multidict" +version = "6.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/69/7f/0652e6ed47ab288e3756ea9c0df8b14950781184d4bd7883f4d87dd41245/multidict-6.6.4.tar.gz", hash = "sha256:d2d4e4787672911b48350df02ed3fa3fffdc2f2e8ca06dd6afdf34189b76a9dd", size = 101843, upload-time = "2025-08-11T12:08:48.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/f6/512ffd8fd8b37fb2680e5ac35d788f1d71bbaf37789d21a820bdc441e565/multidict-6.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0ffb87be160942d56d7b87b0fdf098e81ed565add09eaa1294268c7f3caac4c8", size = 76516, upload-time = "2025-08-11T12:06:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d191de6cbab2aff5de6c5723101705fd044b3e4c7cfd587a1929b5028b9714b3", size = 45394, upload-time = "2025-08-11T12:06:54.555Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/e8c4472a93a26e4507c0b8e1f0762c0d8a32de1328ef72fd704ef9cc5447/multidict-6.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38a0956dd92d918ad5feff3db8fcb4a5eb7dba114da917e1a88475619781b57b", size = 43591, upload-time = "2025-08-11T12:06:55.672Z" }, + { url = "https://files.pythonhosted.org/packages/05/51/edf414f4df058574a7265034d04c935aa84a89e79ce90fcf4df211f47b16/multidict-6.6.4-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6865f6d3b7900ae020b495d599fcf3765653bc927951c1abb959017f81ae8287", size = 237215, upload-time = "2025-08-11T12:06:57.213Z" }, + { url = "https://files.pythonhosted.org/packages/c8/45/8b3d6dbad8cf3252553cc41abea09ad527b33ce47a5e199072620b296902/multidict-6.6.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a2088c126b6f72db6c9212ad827d0ba088c01d951cee25e758c450da732c138", size = 258299, upload-time = "2025-08-11T12:06:58.946Z" }, + { url = "https://files.pythonhosted.org/packages/3c/e8/8ca2e9a9f5a435fc6db40438a55730a4bf4956b554e487fa1b9ae920f825/multidict-6.6.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0f37bed7319b848097085d7d48116f545985db988e2256b2e6f00563a3416ee6", size = 242357, upload-time = "2025-08-11T12:07:00.301Z" }, + { url = "https://files.pythonhosted.org/packages/0f/84/80c77c99df05a75c28490b2af8f7cba2a12621186e0a8b0865d8e745c104/multidict-6.6.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:01368e3c94032ba6ca0b78e7ccb099643466cf24f8dc8eefcfdc0571d56e58f9", size = 268369, upload-time = "2025-08-11T12:07:01.638Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e9/920bfa46c27b05fb3e1ad85121fd49f441492dca2449c5bcfe42e4565d8a/multidict-6.6.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fe323540c255db0bffee79ad7f048c909f2ab0edb87a597e1c17da6a54e493c", size = 269341, upload-time = "2025-08-11T12:07:02.943Z" }, + { url = "https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8eb3025f17b0a4c3cd08cda49acf312a19ad6e8a4edd9dbd591e6506d999402", size = 256100, upload-time = "2025-08-11T12:07:04.564Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/655be13ae324212bf0bc15d665a4e34844f34c206f78801be42f7a0a8aaa/multidict-6.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bbc14f0365534d35a06970d6a83478b249752e922d662dc24d489af1aa0d1be7", size = 253584, upload-time = "2025-08-11T12:07:05.914Z" }, + { url = "https://files.pythonhosted.org/packages/5c/74/ab2039ecc05264b5cec73eb018ce417af3ebb384ae9c0e9ed42cb33f8151/multidict-6.6.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:75aa52fba2d96bf972e85451b99d8e19cc37ce26fd016f6d4aa60da9ab2b005f", size = 251018, upload-time = "2025-08-11T12:07:08.301Z" }, + { url = "https://files.pythonhosted.org/packages/af/0a/ccbb244ac848e56c6427f2392741c06302bbfba49c0042f1eb3c5b606497/multidict-6.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fefd4a815e362d4f011919d97d7b4a1e566f1dde83dc4ad8cfb5b41de1df68d", size = 251477, upload-time = "2025-08-11T12:07:10.248Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b0/0ed49bba775b135937f52fe13922bc64a7eaf0a3ead84a36e8e4e446e096/multidict-6.6.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:db9801fe021f59a5b375ab778973127ca0ac52429a26e2fd86aa9508f4d26eb7", size = 263575, upload-time = "2025-08-11T12:07:11.928Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/7fb85a85e14de2e44dfb6a24f03c41e2af8697a6df83daddb0e9b7569f73/multidict-6.6.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a650629970fa21ac1fb06ba25dabfc5b8a2054fcbf6ae97c758aa956b8dba802", size = 259649, upload-time = "2025-08-11T12:07:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/03/9e/b3a459bcf9b6e74fa461a5222a10ff9b544cb1cd52fd482fb1b75ecda2a2/multidict-6.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:452ff5da78d4720d7516a3a2abd804957532dd69296cb77319c193e3ffb87e24", size = 251505, upload-time = "2025-08-11T12:07:14.57Z" }, + { url = "https://files.pythonhosted.org/packages/86/a2/8022f78f041dfe6d71e364001a5cf987c30edfc83c8a5fb7a3f0974cff39/multidict-6.6.4-cp312-cp312-win32.whl", hash = "sha256:8c2fcb12136530ed19572bbba61b407f655e3953ba669b96a35036a11a485793", size = 41888, upload-time = "2025-08-11T12:07:15.904Z" }, + { url = "https://files.pythonhosted.org/packages/c7/eb/d88b1780d43a56db2cba24289fa744a9d216c1a8546a0dc3956563fd53ea/multidict-6.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:047d9425860a8c9544fed1b9584f0c8bcd31bcde9568b047c5e567a1025ecd6e", size = 46072, upload-time = "2025-08-11T12:07:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/9f/16/b929320bf5750e2d9d4931835a4c638a19d2494a5b519caaaa7492ebe105/multidict-6.6.4-cp312-cp312-win_arm64.whl", hash = "sha256:14754eb72feaa1e8ae528468f24250dd997b8e2188c3d2f593f9eba259e4b364", size = 43222, upload-time = "2025-08-11T12:07:18.328Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5d/e1db626f64f60008320aab00fbe4f23fc3300d75892a3381275b3d284580/multidict-6.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f46a6e8597f9bd71b31cc708195d42b634c8527fecbcf93febf1052cacc1f16e", size = 75848, upload-time = "2025-08-11T12:07:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:22e38b2bc176c5eb9c0a0e379f9d188ae4cd8b28c0f53b52bce7ab0a9e534657", size = 45060, upload-time = "2025-08-11T12:07:21.163Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c6/f5e97e5d99a729bc2aa58eb3ebfa9f1e56a9b517cc38c60537c81834a73f/multidict-6.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5df8afd26f162da59e218ac0eefaa01b01b2e6cd606cffa46608f699539246da", size = 43269, upload-time = "2025-08-11T12:07:22.392Z" }, + { url = "https://files.pythonhosted.org/packages/dc/31/d54eb0c62516776f36fe67f84a732f97e0b0e12f98d5685bebcc6d396910/multidict-6.6.4-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:49517449b58d043023720aa58e62b2f74ce9b28f740a0b5d33971149553d72aa", size = 237158, upload-time = "2025-08-11T12:07:23.636Z" }, + { url = "https://files.pythonhosted.org/packages/c4/1c/8a10c1c25b23156e63b12165a929d8eb49a6ed769fdbefb06e6f07c1e50d/multidict-6.6.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9408439537c5afdca05edd128a63f56a62680f4b3c234301055d7a2000220f", size = 257076, upload-time = "2025-08-11T12:07:25.049Z" }, + { url = "https://files.pythonhosted.org/packages/ad/86/90e20b5771d6805a119e483fd3d1e8393e745a11511aebca41f0da38c3e2/multidict-6.6.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:87a32d20759dc52a9e850fe1061b6e41ab28e2998d44168a8a341b99ded1dba0", size = 240694, upload-time = "2025-08-11T12:07:26.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/49/484d3e6b535bc0555b52a0a26ba86e4d8d03fd5587d4936dc59ba7583221/multidict-6.6.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52e3c8d43cdfff587ceedce9deb25e6ae77daba560b626e97a56ddcad3756879", size = 266350, upload-time = "2025-08-11T12:07:27.94Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b4/aa4c5c379b11895083d50021e229e90c408d7d875471cb3abf721e4670d6/multidict-6.6.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ad8850921d3a8d8ff6fbef790e773cecfc260bbfa0566998980d3fa8f520bc4a", size = 267250, upload-time = "2025-08-11T12:07:29.303Z" }, + { url = "https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:497a2954adc25c08daff36f795077f63ad33e13f19bfff7736e72c785391534f", size = 254900, upload-time = "2025-08-11T12:07:30.764Z" }, + { url = "https://files.pythonhosted.org/packages/17/38/58b27fed927c07035abc02befacab42491e7388ca105e087e6e0215ead64/multidict-6.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:024ce601f92d780ca1617ad4be5ac15b501cc2414970ffa2bb2bbc2bd5a68fa5", size = 252355, upload-time = "2025-08-11T12:07:32.205Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a1/dad75d23a90c29c02b5d6f3d7c10ab36c3197613be5d07ec49c7791e186c/multidict-6.6.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a693fc5ed9bdd1c9e898013e0da4dcc640de7963a371c0bd458e50e046bf6438", size = 250061, upload-time = "2025-08-11T12:07:33.623Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1a/ac2216b61c7f116edab6dc3378cca6c70dc019c9a457ff0d754067c58b20/multidict-6.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:190766dac95aab54cae5b152a56520fd99298f32a1266d66d27fdd1b5ac00f4e", size = 249675, upload-time = "2025-08-11T12:07:34.958Z" }, + { url = "https://files.pythonhosted.org/packages/d4/79/1916af833b800d13883e452e8e0977c065c4ee3ab7a26941fbfdebc11895/multidict-6.6.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:34d8f2a5ffdceab9dcd97c7a016deb2308531d5f0fced2bb0c9e1df45b3363d7", size = 261247, upload-time = "2025-08-11T12:07:36.588Z" }, + { url = "https://files.pythonhosted.org/packages/c5/65/d1f84fe08ac44a5fc7391cbc20a7cedc433ea616b266284413fd86062f8c/multidict-6.6.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:59e8d40ab1f5a8597abcef00d04845155a5693b5da00d2c93dbe88f2050f2812", size = 257960, upload-time = "2025-08-11T12:07:39.735Z" }, + { url = "https://files.pythonhosted.org/packages/13/b5/29ec78057d377b195ac2c5248c773703a6b602e132a763e20ec0457e7440/multidict-6.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:467fe64138cfac771f0e949b938c2e1ada2b5af22f39692aa9258715e9ea613a", size = 250078, upload-time = "2025-08-11T12:07:41.525Z" }, + { url = "https://files.pythonhosted.org/packages/c4/0e/7e79d38f70a872cae32e29b0d77024bef7834b0afb406ddae6558d9e2414/multidict-6.6.4-cp313-cp313-win32.whl", hash = "sha256:14616a30fe6d0a48d0a48d1a633ab3b8bec4cf293aac65f32ed116f620adfd69", size = 41708, upload-time = "2025-08-11T12:07:43.405Z" }, + { url = "https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf", size = 45912, upload-time = "2025-08-11T12:07:45.082Z" }, + { url = "https://files.pythonhosted.org/packages/c7/87/3bac136181e271e29170d8d71929cdeddeb77f3e8b6a0c08da3a8e9da114/multidict-6.6.4-cp313-cp313-win_arm64.whl", hash = "sha256:f6eb37d511bfae9e13e82cb4d1af36b91150466f24d9b2b8a9785816deb16605", size = 43076, upload-time = "2025-08-11T12:07:46.746Z" }, + { url = "https://files.pythonhosted.org/packages/64/94/0a8e63e36c049b571c9ae41ee301ada29c3fee9643d9c2548d7d558a1d99/multidict-6.6.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6c84378acd4f37d1b507dfa0d459b449e2321b3ba5f2338f9b085cf7a7ba95eb", size = 82812, upload-time = "2025-08-11T12:07:48.402Z" }, + { url = "https://files.pythonhosted.org/packages/25/1a/be8e369dfcd260d2070a67e65dd3990dd635cbd735b98da31e00ea84cd4e/multidict-6.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0e0558693063c75f3d952abf645c78f3c5dfdd825a41d8c4d8156fc0b0da6e7e", size = 48313, upload-time = "2025-08-11T12:07:49.679Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/dd4ade298674b2f9a7b06a32c94ffbc0497354df8285f27317c66433ce3b/multidict-6.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3f8e2384cb83ebd23fd07e9eada8ba64afc4c759cd94817433ab8c81ee4b403f", size = 46777, upload-time = "2025-08-11T12:07:51.318Z" }, + { url = "https://files.pythonhosted.org/packages/89/db/98aa28bc7e071bfba611ac2ae803c24e96dd3a452b4118c587d3d872c64c/multidict-6.6.4-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f996b87b420995a9174b2a7c1a8daf7db4750be6848b03eb5e639674f7963773", size = 229321, upload-time = "2025-08-11T12:07:52.965Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bc/01ddda2a73dd9d167bd85d0e8ef4293836a8f82b786c63fb1a429bc3e678/multidict-6.6.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc356250cffd6e78416cf5b40dc6a74f1edf3be8e834cf8862d9ed5265cf9b0e", size = 249954, upload-time = "2025-08-11T12:07:54.423Z" }, + { url = "https://files.pythonhosted.org/packages/06/78/6b7c0f020f9aa0acf66d0ab4eb9f08375bac9a50ff5e3edb1c4ccd59eafc/multidict-6.6.4-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:dadf95aa862714ea468a49ad1e09fe00fcc9ec67d122f6596a8d40caf6cec7d0", size = 228612, upload-time = "2025-08-11T12:07:55.914Z" }, + { url = "https://files.pythonhosted.org/packages/00/44/3faa416f89b2d5d76e9d447296a81521e1c832ad6e40b92f990697b43192/multidict-6.6.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dd57515bebffd8ebd714d101d4c434063322e4fe24042e90ced41f18b6d3395", size = 257528, upload-time = "2025-08-11T12:07:57.371Z" }, + { url = "https://files.pythonhosted.org/packages/05/5f/77c03b89af0fcb16f018f668207768191fb9dcfb5e3361a5e706a11db2c9/multidict-6.6.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:967af5f238ebc2eb1da4e77af5492219fbd9b4b812347da39a7b5f5c72c0fa45", size = 256329, upload-time = "2025-08-11T12:07:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e9/ed750a2a9afb4f8dc6f13dc5b67b514832101b95714f1211cd42e0aafc26/multidict-6.6.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a4c6875c37aae9794308ec43e3530e4aa0d36579ce38d89979bbf89582002bb", size = 247928, upload-time = "2025-08-11T12:08:01.037Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b5/e0571bc13cda277db7e6e8a532791d4403dacc9850006cb66d2556e649c0/multidict-6.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7f683a551e92bdb7fac545b9c6f9fa2aebdeefa61d607510b3533286fcab67f5", size = 245228, upload-time = "2025-08-11T12:08:02.96Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a3/69a84b0eccb9824491f06368f5b86e72e4af54c3067c37c39099b6687109/multidict-6.6.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:3ba5aaf600edaf2a868a391779f7a85d93bed147854925f34edd24cc70a3e141", size = 235869, upload-time = "2025-08-11T12:08:04.746Z" }, + { url = "https://files.pythonhosted.org/packages/a9/9d/28802e8f9121a6a0804fa009debf4e753d0a59969ea9f70be5f5fdfcb18f/multidict-6.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:580b643b7fd2c295d83cad90d78419081f53fd532d1f1eb67ceb7060f61cff0d", size = 243446, upload-time = "2025-08-11T12:08:06.332Z" }, + { url = "https://files.pythonhosted.org/packages/38/ea/6c98add069b4878c1d66428a5f5149ddb6d32b1f9836a826ac764b9940be/multidict-6.6.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:37b7187197da6af3ee0b044dbc9625afd0c885f2800815b228a0e70f9a7f473d", size = 252299, upload-time = "2025-08-11T12:08:07.931Z" }, + { url = "https://files.pythonhosted.org/packages/3a/09/8fe02d204473e14c0af3affd50af9078839dfca1742f025cca765435d6b4/multidict-6.6.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e1b93790ed0bc26feb72e2f08299691ceb6da5e9e14a0d13cc74f1869af327a0", size = 246926, upload-time = "2025-08-11T12:08:09.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/3d/7b1e10d774a6df5175ecd3c92bff069e77bed9ec2a927fdd4ff5fe182f67/multidict-6.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a506a77ddee1efcca81ecbeae27ade3e09cdf21a8ae854d766c2bb4f14053f92", size = 243383, upload-time = "2025-08-11T12:08:10.981Z" }, + { url = "https://files.pythonhosted.org/packages/50/b0/a6fae46071b645ae98786ab738447de1ef53742eaad949f27e960864bb49/multidict-6.6.4-cp313-cp313t-win32.whl", hash = "sha256:f93b2b2279883d1d0a9e1bd01f312d6fc315c5e4c1f09e112e4736e2f650bc4e", size = 47775, upload-time = "2025-08-11T12:08:12.439Z" }, + { url = "https://files.pythonhosted.org/packages/b2/0a/2436550b1520091af0600dff547913cb2d66fbac27a8c33bc1b1bccd8d98/multidict-6.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:6d46a180acdf6e87cc41dc15d8f5c2986e1e8739dc25dbb7dac826731ef381a4", size = 53100, upload-time = "2025-08-11T12:08:13.823Z" }, + { url = "https://files.pythonhosted.org/packages/97/ea/43ac51faff934086db9c072a94d327d71b7d8b40cd5dcb47311330929ef0/multidict-6.6.4-cp313-cp313t-win_arm64.whl", hash = "sha256:756989334015e3335d087a27331659820d53ba432befdef6a718398b0a8493ad", size = 45501, upload-time = "2025-08-11T12:08:15.173Z" }, + { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, +] + +[[package]] +name = "nexus-rpc" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/66/540687556bd28cf1ec370cc6881456203dfddb9dab047b8979c6865b5984/nexus_rpc-1.1.0.tar.gz", hash = "sha256:d65ad6a2f54f14e53ebe39ee30555eaeb894102437125733fb13034a04a44553", size = 77383, upload-time = "2025-07-07T19:03:58.368Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, +] + +[[package]] +name = "openai" +version = "1.101.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/7c/eaf06b62281f5ca4f774c4cff066e6ddfd6a027e0ac791be16acec3a95e3/openai-1.101.0.tar.gz", hash = "sha256:29f56df2236069686e64aca0e13c24a4ec310545afb25ef7da2ab1a18523f22d", size = 518415, upload-time = "2025-08-21T21:11:01.645Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/a6/0e39baa335bbd1c66c7e0a41dbbec10c5a15ab95c1344e7f7beb28eee65a/openai-1.101.0-py3-none-any.whl", hash = "sha256:6539a446cce154f8d9fb42757acdfd3ed9357ab0d34fcac11096c461da87133b", size = 810772, upload-time = "2025-08-21T21:10:59.215Z" }, +] + +[[package]] +name = "opentelemetry-api" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/d2/c782c88b8afbf961d6972428821c302bd1e9e7bc361352172f0ca31296e2/opentelemetry_api-1.36.0.tar.gz", hash = "sha256:9a72572b9c416d004d492cbc6e61962c0501eaf945ece9b5a0f56597d8348aa0", size = 64780, upload-time = "2025-07-29T15:12:06.02Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/ee/6b08dde0a022c463b88f55ae81149584b125a42183407dc1045c486cc870/opentelemetry_api-1.36.0-py3-none-any.whl", hash = "sha256:02f20bcacf666e1333b6b1f04e647dc1d5111f86b8e510238fcc56d7762cda8c", size = 65564, upload-time = "2025-07-29T15:11:47.998Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/da/7747e57eb341c59886052d733072bc878424bf20f1d8cf203d508bbece5b/opentelemetry_exporter_otlp_proto_common-1.36.0.tar.gz", hash = "sha256:6c496ccbcbe26b04653cecadd92f73659b814c6e3579af157d8716e5f9f25cbf", size = 20302, upload-time = "2025-07-29T15:12:07.71Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/ed/22290dca7db78eb32e0101738366b5bbda00d0407f00feffb9bf8c3fdf87/opentelemetry_exporter_otlp_proto_common-1.36.0-py3-none-any.whl", hash = "sha256:0fc002a6ed63eac235ada9aa7056e5492e9a71728214a61745f6ad04b923f840", size = 18349, upload-time = "2025-07-29T15:11:51.327Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/25/85/6632e7e5700ba1ce5b8a065315f92c1e6d787ccc4fb2bdab15139eaefc82/opentelemetry_exporter_otlp_proto_http-1.36.0.tar.gz", hash = "sha256:dd3637f72f774b9fc9608ab1ac479f8b44d09b6fb5b2f3df68a24ad1da7d356e", size = 16213, upload-time = "2025-07-29T15:12:08.932Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/41/a680d38b34f8f5ddbd78ed9f0042e1cc712d58ec7531924d71cb1e6c629d/opentelemetry_exporter_otlp_proto_http-1.36.0-py3-none-any.whl", hash = "sha256:3d769f68e2267e7abe4527f70deb6f598f40be3ea34c6adc35789bea94a32902", size = 18752, upload-time = "2025-07-29T15:11:53.164Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/37/cf17cf28f945a3aca5a038cfbb45ee01317d4f7f3a0e5209920883fe9b08/opentelemetry_instrumentation-0.57b0.tar.gz", hash = "sha256:f2a30135ba77cdea2b0e1df272f4163c154e978f57214795d72f40befd4fcf05", size = 30807, upload-time = "2025-07-29T15:42:44.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/6f/f20cd1542959f43fb26a5bf9bb18cd81a1ea0700e8870c8f369bd07f5c65/opentelemetry_instrumentation-0.57b0-py3-none-any.whl", hash = "sha256:9109280f44882e07cec2850db28210b90600ae9110b42824d196de357cbddf7e", size = 32460, upload-time = "2025-07-29T15:41:40.883Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation-httpx" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/28/65fea8b8e7f19502a8af1229c62384f9211c1480f5dee1776841810d6551/opentelemetry_instrumentation_httpx-0.57b0.tar.gz", hash = "sha256:ea5669cdb17185f8d247c2dbf756ae5b95b53110ca4d58424f2be5cc7223dbdd", size = 19511, upload-time = "2025-07-29T15:43:00.575Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/e59b319a5c6a41c6b4230f5e25651edbeb3a8d248afa1b411fd07cc3f9bf/opentelemetry_instrumentation_httpx-0.57b0-py3-none-any.whl", hash = "sha256:729fef97624016d3e5b03b71f51c9a1a2f7480b023373186d643fbed7496712a", size = 15111, upload-time = "2025-07-29T15:42:06.501Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/02/f6556142301d136e3b7e95ab8ea6a5d9dc28d879a99f3dd673b5f97dca06/opentelemetry_proto-1.36.0.tar.gz", hash = "sha256:0f10b3c72f74c91e0764a5ec88fd8f1c368ea5d9c64639fb455e2854ef87dd2f", size = 46152, upload-time = "2025-07-29T15:12:15.717Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/57/3361e06136225be8180e879199caea520f38026f8071366241ac458beb8d/opentelemetry_proto-1.36.0-py3-none-any.whl", hash = "sha256:151b3bf73a09f94afc658497cf77d45a565606f62ce0c17acb08cd9937ca206e", size = 72537, upload-time = "2025-07-29T15:12:02.243Z" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/85/8567a966b85a2d3f971c4d42f781c305b2b91c043724fa08fd37d158e9dc/opentelemetry_sdk-1.36.0.tar.gz", hash = "sha256:19c8c81599f51b71670661ff7495c905d8fdf6976e41622d5245b791b06fa581", size = 162557, upload-time = "2025-07-29T15:12:16.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/59/7bed362ad1137ba5886dac8439e84cd2df6d087be7c09574ece47ae9b22c/opentelemetry_sdk-1.36.0-py3-none-any.whl", hash = "sha256:19fe048b42e98c5c1ffe85b569b7073576ad4ce0bcb6e9b4c6a39e890a6c45fb", size = 119995, upload-time = "2025-07-29T15:12:03.181Z" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/31/67dfa252ee88476a29200b0255bda8dfc2cf07b56ad66dc9a6221f7dc787/opentelemetry_semantic_conventions-0.57b0.tar.gz", hash = "sha256:609a4a79c7891b4620d64c7aac6898f872d790d75f22019913a660756f27ff32", size = 124225, upload-time = "2025-07-29T15:12:17.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/75/7d591371c6c39c73de5ce5da5a2cc7b72d1d1cd3f8f4638f553c01c37b11/opentelemetry_semantic_conventions-0.57b0-py3-none-any.whl", hash = "sha256:757f7e76293294f124c827e514c2a3144f191ef175b069ce8d1211e1e38e9e78", size = 201627, upload-time = "2025-07-29T15:12:04.174Z" }, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9b/1b/6229c45445e08e798fa825f5376f6d6a4211d29052a4088eed6d577fa653/opentelemetry_util_http-0.57b0.tar.gz", hash = "sha256:f7417595ead0eb42ed1863ec9b2f839fc740368cd7bbbfc1d0a47bc1ab0aba11", size = 9405, upload-time = "2025-07-29T15:43:19.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/a6/b98d508d189b9c208f5978d0906141747d7e6df7c7cafec03657ed1ed559/opentelemetry_util_http-0.57b0-py3-none-any.whl", hash = "sha256:e54c0df5543951e471c3d694f85474977cd5765a3b7654398c83bab3d2ffb8e9", size = 7643, upload-time = "2025-07-29T15:42:41.744Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, +] + +[[package]] +name = "propcache" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/16/43264e4a779dd8588c21a70f0709665ee8f611211bdd2c87d952cfa7c776/propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168", size = 44139, upload-time = "2025-06-09T22:56:06.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/42/9ca01b0a6f48e81615dca4765a8f1dd2c057e0540f6116a27dc5ee01dfb6/propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10", size = 73674, upload-time = "2025-06-09T22:54:30.551Z" }, + { url = "https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154", size = 43570, upload-time = "2025-06-09T22:54:32.296Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c8/0393a0a3a2b8760eb3bde3c147f62b20044f0ddac81e9d6ed7318ec0d852/propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615", size = 43094, upload-time = "2025-06-09T22:54:33.929Z" }, + { url = "https://files.pythonhosted.org/packages/37/2c/489afe311a690399d04a3e03b069225670c1d489eb7b044a566511c1c498/propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db", size = 226958, upload-time = "2025-06-09T22:54:35.186Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ca/63b520d2f3d418c968bf596839ae26cf7f87bead026b6192d4da6a08c467/propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1", size = 234894, upload-time = "2025-06-09T22:54:36.708Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/1d0ed6fff455a028d678df30cc28dcee7af77fa2b0e6962ce1df95c9a2a9/propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c", size = 233672, upload-time = "2025-06-09T22:54:38.062Z" }, + { url = "https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67", size = 224395, upload-time = "2025-06-09T22:54:39.634Z" }, + { url = "https://files.pythonhosted.org/packages/ee/1a/89a40e0846f5de05fdc6779883bf46ba980e6df4d2ff8fb02643de126592/propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b", size = 212510, upload-time = "2025-06-09T22:54:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/5e/33/ca98368586c9566a6b8d5ef66e30484f8da84c0aac3f2d9aec6d31a11bd5/propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8", size = 222949, upload-time = "2025-06-09T22:54:43.038Z" }, + { url = "https://files.pythonhosted.org/packages/ba/11/ace870d0aafe443b33b2f0b7efdb872b7c3abd505bfb4890716ad7865e9d/propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251", size = 217258, upload-time = "2025-06-09T22:54:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/86fd6f7adffcfc74b42c10a6b7db721d1d9ca1055c45d39a1a8f2a740a21/propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474", size = 213036, upload-time = "2025-06-09T22:54:46.243Z" }, + { url = "https://files.pythonhosted.org/packages/07/94/2d7d1e328f45ff34a0a284cf5a2847013701e24c2a53117e7c280a4316b3/propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535", size = 227684, upload-time = "2025-06-09T22:54:47.63Z" }, + { url = "https://files.pythonhosted.org/packages/b7/05/37ae63a0087677e90b1d14710e532ff104d44bc1efa3b3970fff99b891dc/propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06", size = 234562, upload-time = "2025-06-09T22:54:48.982Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7c/3f539fcae630408d0bd8bf3208b9a647ccad10976eda62402a80adf8fc34/propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1", size = 222142, upload-time = "2025-06-09T22:54:50.424Z" }, + { url = "https://files.pythonhosted.org/packages/7c/d2/34b9eac8c35f79f8a962546b3e97e9d4b990c420ee66ac8255d5d9611648/propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1", size = 37711, upload-time = "2025-06-09T22:54:52.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/61/d582be5d226cf79071681d1b46b848d6cb03d7b70af7063e33a2787eaa03/propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c", size = 41479, upload-time = "2025-06-09T22:54:53.234Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d1/8c747fafa558c603c4ca19d8e20b288aa0c7cda74e9402f50f31eb65267e/propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945", size = 71286, upload-time = "2025-06-09T22:54:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252", size = 42425, upload-time = "2025-06-09T22:54:55.642Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/ef98f91bbb42b79e9bb82bdd348b255eb9d65f14dbbe3b1594644c4073f7/propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f", size = 41846, upload-time = "2025-06-09T22:54:57.246Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ad/3f0f9a705fb630d175146cd7b1d2bf5555c9beaed54e94132b21aac098a6/propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33", size = 208871, upload-time = "2025-06-09T22:54:58.975Z" }, + { url = "https://files.pythonhosted.org/packages/3a/38/2085cda93d2c8b6ec3e92af2c89489a36a5886b712a34ab25de9fbca7992/propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e", size = 215720, upload-time = "2025-06-09T22:55:00.471Z" }, + { url = "https://files.pythonhosted.org/packages/61/c1/d72ea2dc83ac7f2c8e182786ab0fc2c7bd123a1ff9b7975bee671866fe5f/propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1", size = 215203, upload-time = "2025-06-09T22:55:01.834Z" }, + { url = "https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3", size = 206365, upload-time = "2025-06-09T22:55:03.199Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/88549128bb89e66d2aff242488f62869014ae092db63ccea53c1cc75a81d/propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1", size = 196016, upload-time = "2025-06-09T22:55:04.518Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3f/3bdd14e737d145114a5eb83cb172903afba7242f67c5877f9909a20d948d/propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6", size = 205596, upload-time = "2025-06-09T22:55:05.942Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ca/2f4aa819c357d3107c3763d7ef42c03980f9ed5c48c82e01e25945d437c1/propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387", size = 200977, upload-time = "2025-06-09T22:55:07.792Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4a/e65276c7477533c59085251ae88505caf6831c0e85ff8b2e31ebcbb949b1/propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4", size = 197220, upload-time = "2025-06-09T22:55:09.173Z" }, + { url = "https://files.pythonhosted.org/packages/7c/54/fc7152e517cf5578278b242396ce4d4b36795423988ef39bb8cd5bf274c8/propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88", size = 210642, upload-time = "2025-06-09T22:55:10.62Z" }, + { url = "https://files.pythonhosted.org/packages/b9/80/abeb4a896d2767bf5f1ea7b92eb7be6a5330645bd7fb844049c0e4045d9d/propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206", size = 212789, upload-time = "2025-06-09T22:55:12.029Z" }, + { url = "https://files.pythonhosted.org/packages/b3/db/ea12a49aa7b2b6d68a5da8293dcf50068d48d088100ac016ad92a6a780e6/propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43", size = 205880, upload-time = "2025-06-09T22:55:13.45Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e5/9076a0bbbfb65d1198007059c65639dfd56266cf8e477a9707e4b1999ff4/propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02", size = 37220, upload-time = "2025-06-09T22:55:15.284Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05", size = 40678, upload-time = "2025-06-09T22:55:16.445Z" }, + { url = "https://files.pythonhosted.org/packages/a4/3a/6ece377b55544941a08d03581c7bc400a3c8cd3c2865900a68d5de79e21f/propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b", size = 76560, upload-time = "2025-06-09T22:55:17.598Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/64a2bb16418740fa634b0e9c3d29edff1db07f56d3546ca2d86ddf0305e1/propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0", size = 44676, upload-time = "2025-06-09T22:55:18.922Z" }, + { url = "https://files.pythonhosted.org/packages/36/7b/f025e06ea51cb72c52fb87e9b395cced02786610b60a3ed51da8af017170/propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e", size = 44701, upload-time = "2025-06-09T22:55:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/a4/00/faa1b1b7c3b74fc277f8642f32a4c72ba1d7b2de36d7cdfb676db7f4303e/propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28", size = 276934, upload-time = "2025-06-09T22:55:21.5Z" }, + { url = "https://files.pythonhosted.org/packages/74/ab/935beb6f1756e0476a4d5938ff44bf0d13a055fed880caf93859b4f1baf4/propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a", size = 278316, upload-time = "2025-06-09T22:55:22.918Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9d/994a5c1ce4389610838d1caec74bdf0e98b306c70314d46dbe4fcf21a3e2/propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c", size = 282619, upload-time = "2025-06-09T22:55:24.651Z" }, + { url = "https://files.pythonhosted.org/packages/2b/00/a10afce3d1ed0287cef2e09506d3be9822513f2c1e96457ee369adb9a6cd/propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725", size = 265896, upload-time = "2025-06-09T22:55:26.049Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a8/2aa6716ffa566ca57c749edb909ad27884680887d68517e4be41b02299f3/propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892", size = 252111, upload-time = "2025-06-09T22:55:27.381Z" }, + { url = "https://files.pythonhosted.org/packages/36/4f/345ca9183b85ac29c8694b0941f7484bf419c7f0fea2d1e386b4f7893eed/propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44", size = 268334, upload-time = "2025-06-09T22:55:28.747Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ca/fcd54f78b59e3f97b3b9715501e3147f5340167733d27db423aa321e7148/propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe", size = 255026, upload-time = "2025-06-09T22:55:30.184Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8e6a6bbbd78ac89c30c225210a5c687790e532ba4088afb8c0445b77ef37/propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81", size = 250724, upload-time = "2025-06-09T22:55:31.646Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b0/0dd03616142baba28e8b2d14ce5df6631b4673850a3d4f9c0f9dd714a404/propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba", size = 268868, upload-time = "2025-06-09T22:55:33.209Z" }, + { url = "https://files.pythonhosted.org/packages/c5/98/2c12407a7e4fbacd94ddd32f3b1e3d5231e77c30ef7162b12a60e2dd5ce3/propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770", size = 271322, upload-time = "2025-06-09T22:55:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/35/91/9cb56efbb428b006bb85db28591e40b7736847b8331d43fe335acf95f6c8/propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330", size = 265778, upload-time = "2025-06-09T22:55:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4c/b0fe775a2bdd01e176b14b574be679d84fc83958335790f7c9a686c1f468/propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394", size = 41175, upload-time = "2025-06-09T22:55:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ff/47f08595e3d9b5e149c150f88d9714574f1a7cbd89fe2817158a952674bf/propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198", size = 44857, upload-time = "2025-06-09T22:55:39.687Z" }, + { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, +] + +[[package]] +name = "protobuf" +version = "5.29.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/29/d09e70352e4e88c9c7a198d5645d7277811448d76c23b00345670f7c8a38/protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84", size = 425226, upload-time = "2025-05-28T23:51:59.82Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/11/6e40e9fc5bba02988a214c07cf324595789ca7820160bfd1f8be96e48539/protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079", size = 422963, upload-time = "2025-05-28T23:51:41.204Z" }, + { url = "https://files.pythonhosted.org/packages/81/7f/73cefb093e1a2a7c3ffd839e6f9fcafb7a427d300c7f8aef9c64405d8ac6/protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc", size = 434818, upload-time = "2025-05-28T23:51:44.297Z" }, + { url = "https://files.pythonhosted.org/packages/dd/73/10e1661c21f139f2c6ad9b23040ff36fee624310dc28fba20d33fdae124c/protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671", size = 418091, upload-time = "2025-05-28T23:51:45.907Z" }, + { url = "https://files.pythonhosted.org/packages/6c/04/98f6f8cf5b07ab1294c13f34b4e69b3722bb609c5b701d6c169828f9f8aa/protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015", size = 319824, upload-time = "2025-05-28T23:51:47.545Z" }, + { url = "https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61", size = 319942, upload-time = "2025-05-28T23:51:49.11Z" }, + { url = "https://files.pythonhosted.org/packages/7e/cc/7e77861000a0691aeea8f4566e5d3aa716f2b1dece4a24439437e41d3d25/protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5", size = 172823, upload-time = "2025-05-28T23:51:58.157Z" }, +] + +[[package]] +name = "pyasn1" +version = "0.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, +] + +[[package]] +name = "pydantic" +version = "2.11.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, +] + +[[package]] +name = "pydantic-ai" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "vertexai"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/41/b3cab0ae7bd94ade25dc41343fee8f46e35c2ad43b79a443456a5c59d9cf/pydantic_ai-1.0.2.tar.gz", hash = "sha256:0ed625db02bece2ce6e52c6326fc5f9c78482693ff89ce93477aec17687b20a5", size = 43802817, upload-time = "2025-09-09T00:38:33.049Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/fd/61b361553c77f36848f470908ac55c76624b17a1831b43da074f449650b8/pydantic_ai-1.0.2-py3-none-any.whl", hash = "sha256:616c224948097c2bb1607cd4aa87e971f94d3eb891156c9d77e94c18e346c839", size = 11670, upload-time = "2025-09-09T00:38:21.777Z" }, +] + +[[package]] +name = "pydantic-ai-slim" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "genai-prices" }, + { name = "griffe" }, + { name = "httpx" }, + { name = "opentelemetry-api" }, + { name = "pydantic" }, + { name = "pydantic-graph" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/fd/962a6d79b135cd2ed30d122431b73cb725a8f9206706dd95a35a0e442439/pydantic_ai_slim-1.0.2.tar.gz", hash = "sha256:a41642f9c248ab1e12911f54c5c5adff4b2667ef48c5578eeea718febb108395", size = 235860, upload-time = "2025-09-09T00:38:37.665Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/74/b68d3c61219d8b9ea67baefa0efcf7e20c641c4efef842100c0715c81b85/pydantic_ai_slim-1.0.2-py3-none-any.whl", hash = "sha256:d72922f7c0684c556c1182eee5281510a357c2f18bb3e54a9f117f548a74c236", size = 318441, upload-time = "2025-09-09T00:38:25.828Z" }, +] + +[package.optional-dependencies] +ag-ui = [ + { name = "ag-ui-protocol" }, + { name = "starlette" }, +] +anthropic = [ + { name = "anthropic" }, +] +bedrock = [ + { name = "boto3" }, +] +cli = [ + { name = "argcomplete" }, + { name = "prompt-toolkit" }, + { name = "pyperclip" }, + { name = "rich" }, +] +cohere = [ + { name = "cohere", marker = "sys_platform != 'emscripten'" }, +] +evals = [ + { name = "pydantic-evals" }, +] +google = [ + { name = "google-genai" }, +] +groq = [ + { name = "groq" }, +] +huggingface = [ + { name = "huggingface-hub", extra = ["inference"] }, +] +logfire = [ + { name = "logfire", extra = ["httpx"] }, +] +mcp = [ + { name = "mcp" }, +] +mistral = [ + { name = "mistralai" }, +] +openai = [ + { name = "openai" }, +] +retries = [ + { name = "tenacity" }, +] +temporal = [ + { name = "temporalio" }, +] +vertexai = [ + { name = "google-auth" }, + { name = "requests" }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, +] + +[[package]] +name = "pydantic-evals" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "pydantic-ai-slim" }, + { name = "pyyaml" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/62/1cd84d70362f2afaaacd1ae102ba46012156ec41c76762d7242bb9705b89/pydantic_evals-1.0.2.tar.gz", hash = "sha256:071bc4b80e1ced065ebcea53e03f06eca868266658a56dfb98ca78976f9022c8", size = 45489, upload-time = "2025-09-09T00:38:38.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/ff/63d8a76e50455b3d755cc940a5cc3f00d26c2a3636930f26f2b0e8f89fc4/pydantic_evals-1.0.2-py3-none-any.whl", hash = "sha256:48ea9510bc66ca2052298cd5a587306fa450f615d3e6542cbb021168b4cfc375", size = 54598, upload-time = "2025-09-09T00:38:27.82Z" }, +] + +[[package]] +name = "pydantic-graph" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/6d/c5a22894828a93e99a2d36d12749619afc7d561aaa926c7d2098e62ad8b5/pydantic_graph-1.0.2.tar.gz", hash = "sha256:249e0b834a37ae31846c93491c949a981179e6206f5b487e7421eb6380abb682", size = 21892, upload-time = "2025-09-09T00:38:40.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ac/9e/3f34115d2795d260e2a19a2cdce399ffa045aeed5532e46ed62155dec529/pydantic_graph-1.0.2-py3-none-any.whl", hash = "sha256:383811cf6802697d31eea3309fdf2738aef333c68e780e1b3f9dbd60c4e2ad97", size = 27536, upload-time = "2025-09-09T00:38:29.39Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/68/ce067f09fca4abeca8771fe667d89cc347d1e99da3e093112ac329c6020e/pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c", size = 78825, upload-time = "2024-08-01T15:01:08.445Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/84/0fdf9b18ba31d69877bd39c9cd6052b47f3761e9910c15de788e519f079f/PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", size = 22344, upload-time = "2024-08-01T15:01:06.481Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + +[[package]] +name = "pyperclip" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/23/2f0a3efc4d6a32f3b63cdff36cd398d9701d26cda58e3ab97ac79fb5e60d/pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310", size = 20961, upload-time = "2024-06-18T20:38:48.401Z" } + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + +[[package]] +name = "redis" +version = "6.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/d6/e8b92798a5bd67d659d51a18170e91c16ac3b59738d91894651ee255ed49/redis-6.4.0.tar.gz", hash = "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010", size = 4647399, upload-time = "2025-08-07T08:10:11.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/02/89e2ed7e85db6c93dfa9e8f691c5087df4e3551ab39081a4d7c6d1f90e05/redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f", size = 279847, upload-time = "2025-08-07T08:10:09.84Z" }, +] + +[[package]] +name = "redis-entraid" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-identity" }, + { name = "msal" }, + { name = "pyjwt" }, + { name = "redis" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/7b/f56aebb76ce71368e34e27c096537f2ee0249268f11eefee03dc6268c552/redis_entraid-1.0.0.tar.gz", hash = "sha256:585188b49597a70ad149ef012f20e478baf0d722c1a148318146db635be5a71e", size = 9550, upload-time = "2025-05-27T11:46:32.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/3c/187d524f735e531cf7c2e6adc660ac48860b4784a54663bf5dbc972b2f38/redis_entraid-1.0.0-py3-none-any.whl", hash = "sha256:4c9ec857e26e9ed2b3810ddb28b2f33a28035712ccba0dc8b55c70a3bf8a9908", size = 7864, upload-time = "2025-05-27T11:46:31.732Z" }, +] + +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rich" +version = "14.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/d9/991a0dee12d9fc53ed027e26a26a64b151d77252ac477e22666b9688bc16/rpds_py-0.27.0.tar.gz", hash = "sha256:8b23cf252f180cda89220b378d917180f29d313cd6a07b2431c0d3b776aae86f", size = 27420, upload-time = "2025-08-07T08:26:39.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/17/e67309ca1ac993fa1888a0d9b2f5ccc1f67196ace32e76c9f8e1dbbbd50c/rpds_py-0.27.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:19c990fdf5acecbf0623e906ae2e09ce1c58947197f9bced6bbd7482662231c4", size = 362611, upload-time = "2025-08-07T08:23:44.773Z" }, + { url = "https://files.pythonhosted.org/packages/93/2e/28c2fb84aa7aa5d75933d1862d0f7de6198ea22dfd9a0cca06e8a4e7509e/rpds_py-0.27.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c27a7054b5224710fcfb1a626ec3ff4f28bcb89b899148c72873b18210e446b", size = 347680, upload-time = "2025-08-07T08:23:46.014Z" }, + { url = "https://files.pythonhosted.org/packages/44/3e/9834b4c8f4f5fe936b479e623832468aa4bd6beb8d014fecaee9eac6cdb1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09965b314091829b378b60607022048953e25f0b396c2b70e7c4c81bcecf932e", size = 384600, upload-time = "2025-08-07T08:23:48Z" }, + { url = "https://files.pythonhosted.org/packages/19/78/744123c7b38865a965cd9e6f691fde7ef989a00a256fa8bf15b75240d12f/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:14f028eb47f59e9169bfdf9f7ceafd29dd64902141840633683d0bad5b04ff34", size = 400697, upload-time = "2025-08-07T08:23:49.407Z" }, + { url = "https://files.pythonhosted.org/packages/32/97/3c3d32fe7daee0a1f1a678b6d4dfb8c4dcf88197fa2441f9da7cb54a8466/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6168af0be75bba990a39f9431cdfae5f0ad501f4af32ae62e8856307200517b8", size = 517781, upload-time = "2025-08-07T08:23:50.557Z" }, + { url = "https://files.pythonhosted.org/packages/b2/be/28f0e3e733680aa13ecec1212fc0f585928a206292f14f89c0b8a684cad1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab47fe727c13c09d0e6f508e3a49e545008e23bf762a245b020391b621f5b726", size = 406449, upload-time = "2025-08-07T08:23:51.732Z" }, + { url = "https://files.pythonhosted.org/packages/95/ae/5d15c83e337c082d0367053baeb40bfba683f42459f6ebff63a2fd7e5518/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa01b3d5e3b7d97efab65bd3d88f164e289ec323a8c033c5c38e53ee25c007e", size = 386150, upload-time = "2025-08-07T08:23:52.822Z" }, + { url = "https://files.pythonhosted.org/packages/bf/65/944e95f95d5931112829e040912b25a77b2e7ed913ea5fe5746aa5c1ce75/rpds_py-0.27.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:6c135708e987f46053e0a1246a206f53717f9fadfba27174a9769ad4befba5c3", size = 406100, upload-time = "2025-08-07T08:23:54.339Z" }, + { url = "https://files.pythonhosted.org/packages/21/a4/1664b83fae02894533cd11dc0b9f91d673797c2185b7be0f7496107ed6c5/rpds_py-0.27.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc327f4497b7087d06204235199daf208fd01c82d80465dc5efa4ec9df1c5b4e", size = 421345, upload-time = "2025-08-07T08:23:55.832Z" }, + { url = "https://files.pythonhosted.org/packages/7c/26/b7303941c2b0823bfb34c71378249f8beedce57301f400acb04bb345d025/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e57906e38583a2cba67046a09c2637e23297618dc1f3caddbc493f2be97c93f", size = 561891, upload-time = "2025-08-07T08:23:56.951Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c8/48623d64d4a5a028fa99576c768a6159db49ab907230edddc0b8468b998b/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f4f69d7a4300fbf91efb1fb4916421bd57804c01ab938ab50ac9c4aa2212f03", size = 591756, upload-time = "2025-08-07T08:23:58.146Z" }, + { url = "https://files.pythonhosted.org/packages/b3/51/18f62617e8e61cc66334c9fb44b1ad7baae3438662098efbc55fb3fda453/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b4c4fbbcff474e1e5f38be1bf04511c03d492d42eec0babda5d03af3b5589374", size = 557088, upload-time = "2025-08-07T08:23:59.6Z" }, + { url = "https://files.pythonhosted.org/packages/bd/4c/e84c3a276e2496a93d245516be6b49e20499aa8ca1c94d59fada0d79addc/rpds_py-0.27.0-cp312-cp312-win32.whl", hash = "sha256:27bac29bbbf39601b2aab474daf99dbc8e7176ca3389237a23944b17f8913d97", size = 221926, upload-time = "2025-08-07T08:24:00.695Z" }, + { url = "https://files.pythonhosted.org/packages/83/89/9d0fbcef64340db0605eb0a0044f258076f3ae0a3b108983b2c614d96212/rpds_py-0.27.0-cp312-cp312-win_amd64.whl", hash = "sha256:8a06aa1197ec0281eb1d7daf6073e199eb832fe591ffa329b88bae28f25f5fe5", size = 233235, upload-time = "2025-08-07T08:24:01.846Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b0/e177aa9f39cbab060f96de4a09df77d494f0279604dc2f509263e21b05f9/rpds_py-0.27.0-cp312-cp312-win_arm64.whl", hash = "sha256:e14aab02258cb776a108107bd15f5b5e4a1bbaa61ef33b36693dfab6f89d54f9", size = 223315, upload-time = "2025-08-07T08:24:03.337Z" }, + { url = "https://files.pythonhosted.org/packages/81/d2/dfdfd42565a923b9e5a29f93501664f5b984a802967d48d49200ad71be36/rpds_py-0.27.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:443d239d02d9ae55b74015234f2cd8eb09e59fbba30bf60baeb3123ad4c6d5ff", size = 362133, upload-time = "2025-08-07T08:24:04.508Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/0a2e2460c4b66021d349ce9f6331df1d6c75d7eea90df9785d333a49df04/rpds_py-0.27.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8a7acf04fda1f30f1007f3cc96d29d8cf0a53e626e4e1655fdf4eabc082d367", size = 347128, upload-time = "2025-08-07T08:24:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/35/8d/7d1e4390dfe09d4213b3175a3f5a817514355cb3524593380733204f20b9/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0f92b78cfc3b74a42239fdd8c1266f4715b573204c234d2f9fc3fc7a24f185", size = 384027, upload-time = "2025-08-07T08:24:06.841Z" }, + { url = "https://files.pythonhosted.org/packages/c1/65/78499d1a62172891c8cd45de737b2a4b84a414b6ad8315ab3ac4945a5b61/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ce4ed8e0c7dbc5b19352b9c2c6131dd23b95fa8698b5cdd076307a33626b72dc", size = 399973, upload-time = "2025-08-07T08:24:08.143Z" }, + { url = "https://files.pythonhosted.org/packages/10/a1/1c67c1d8cc889107b19570bb01f75cf49852068e95e6aee80d22915406fc/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fde355b02934cc6b07200cc3b27ab0c15870a757d1a72fd401aa92e2ea3c6bfe", size = 515295, upload-time = "2025-08-07T08:24:09.711Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/700ec88e748436b6c7c4a2262d66e80f8c21ab585d5e98c45e02f13f21c0/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13bbc4846ae4c993f07c93feb21a24d8ec637573d567a924b1001e81c8ae80f9", size = 406737, upload-time = "2025-08-07T08:24:11.182Z" }, + { url = "https://files.pythonhosted.org/packages/33/cc/6b0ee8f0ba3f2df2daac1beda17fde5cf10897a7d466f252bd184ef20162/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0744661afbc4099fef7f4e604e7f1ea1be1dd7284f357924af12a705cc7d5c", size = 385898, upload-time = "2025-08-07T08:24:12.798Z" }, + { url = "https://files.pythonhosted.org/packages/e8/7e/c927b37d7d33c0a0ebf249cc268dc2fcec52864c1b6309ecb960497f2285/rpds_py-0.27.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:069e0384a54f427bd65d7fda83b68a90606a3835901aaff42185fcd94f5a9295", size = 405785, upload-time = "2025-08-07T08:24:14.906Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/8ed50746d909dcf402af3fa58b83d5a590ed43e07251d6b08fad1a535ba6/rpds_py-0.27.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4bc262ace5a1a7dc3e2eac2fa97b8257ae795389f688b5adf22c5db1e2431c43", size = 419760, upload-time = "2025-08-07T08:24:16.129Z" }, + { url = "https://files.pythonhosted.org/packages/d3/60/2b2071aee781cb3bd49f94d5d35686990b925e9b9f3e3d149235a6f5d5c1/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2fe6e18e5c8581f0361b35ae575043c7029d0a92cb3429e6e596c2cdde251432", size = 561201, upload-time = "2025-08-07T08:24:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/98/1f/27b67304272521aaea02be293fecedce13fa351a4e41cdb9290576fc6d81/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d93ebdb82363d2e7bec64eecdc3632b59e84bd270d74fe5be1659f7787052f9b", size = 591021, upload-time = "2025-08-07T08:24:18.999Z" }, + { url = "https://files.pythonhosted.org/packages/db/9b/a2fadf823164dd085b1f894be6443b0762a54a7af6f36e98e8fcda69ee50/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0954e3a92e1d62e83a54ea7b3fdc9efa5d61acef8488a8a3d31fdafbfb00460d", size = 556368, upload-time = "2025-08-07T08:24:20.54Z" }, + { url = "https://files.pythonhosted.org/packages/24/f3/6d135d46a129cda2e3e6d4c5e91e2cc26ea0428c6cf152763f3f10b6dd05/rpds_py-0.27.0-cp313-cp313-win32.whl", hash = "sha256:2cff9bdd6c7b906cc562a505c04a57d92e82d37200027e8d362518df427f96cd", size = 221236, upload-time = "2025-08-07T08:24:22.144Z" }, + { url = "https://files.pythonhosted.org/packages/c5/44/65d7494f5448ecc755b545d78b188440f81da98b50ea0447ab5ebfdf9bd6/rpds_py-0.27.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc79d192fb76fc0c84f2c58672c17bbbc383fd26c3cdc29daae16ce3d927e8b2", size = 232634, upload-time = "2025-08-07T08:24:23.642Z" }, + { url = "https://files.pythonhosted.org/packages/70/d9/23852410fadab2abb611733933401de42a1964ce6600a3badae35fbd573e/rpds_py-0.27.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b3a5c8089eed498a3af23ce87a80805ff98f6ef8f7bdb70bd1b7dae5105f6ac", size = 222783, upload-time = "2025-08-07T08:24:25.098Z" }, + { url = "https://files.pythonhosted.org/packages/15/75/03447917f78512b34463f4ef11066516067099a0c466545655503bed0c77/rpds_py-0.27.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:90fb790138c1a89a2e58c9282fe1089638401f2f3b8dddd758499041bc6e0774", size = 359154, upload-time = "2025-08-07T08:24:26.249Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fc/4dac4fa756451f2122ddaf136e2c6aeb758dc6fdbe9ccc4bc95c98451d50/rpds_py-0.27.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:010c4843a3b92b54373e3d2291a7447d6c3fc29f591772cc2ea0e9f5c1da434b", size = 343909, upload-time = "2025-08-07T08:24:27.405Z" }, + { url = "https://files.pythonhosted.org/packages/7b/81/723c1ed8e6f57ed9d8c0c07578747a2d3d554aaefc1ab89f4e42cfeefa07/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9ce7a9e967afc0a2af7caa0d15a3e9c1054815f73d6a8cb9225b61921b419bd", size = 379340, upload-time = "2025-08-07T08:24:28.714Z" }, + { url = "https://files.pythonhosted.org/packages/98/16/7e3740413de71818ce1997df82ba5f94bae9fff90c0a578c0e24658e6201/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa0bf113d15e8abdfee92aa4db86761b709a09954083afcb5bf0f952d6065fdb", size = 391655, upload-time = "2025-08-07T08:24:30.223Z" }, + { url = "https://files.pythonhosted.org/packages/e0/63/2a9f510e124d80660f60ecce07953f3f2d5f0b96192c1365443859b9c87f/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb91d252b35004a84670dfeafadb042528b19842a0080d8b53e5ec1128e8f433", size = 513017, upload-time = "2025-08-07T08:24:31.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/4e/cf6ff311d09776c53ea1b4f2e6700b9d43bb4e99551006817ade4bbd6f78/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db8a6313dbac934193fc17fe7610f70cd8181c542a91382531bef5ed785e5615", size = 402058, upload-time = "2025-08-07T08:24:32.613Z" }, + { url = "https://files.pythonhosted.org/packages/88/11/5e36096d474cb10f2a2d68b22af60a3bc4164fd8db15078769a568d9d3ac/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce96ab0bdfcef1b8c371ada2100767ace6804ea35aacce0aef3aeb4f3f499ca8", size = 383474, upload-time = "2025-08-07T08:24:33.767Z" }, + { url = "https://files.pythonhosted.org/packages/db/a2/3dff02805b06058760b5eaa6d8cb8db3eb3e46c9e452453ad5fc5b5ad9fe/rpds_py-0.27.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:7451ede3560086abe1aa27dcdcf55cd15c96b56f543fb12e5826eee6f721f858", size = 400067, upload-time = "2025-08-07T08:24:35.021Z" }, + { url = "https://files.pythonhosted.org/packages/67/87/eed7369b0b265518e21ea836456a4ed4a6744c8c12422ce05bce760bb3cf/rpds_py-0.27.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:32196b5a99821476537b3f7732432d64d93a58d680a52c5e12a190ee0135d8b5", size = 412085, upload-time = "2025-08-07T08:24:36.267Z" }, + { url = "https://files.pythonhosted.org/packages/8b/48/f50b2ab2fbb422fbb389fe296e70b7a6b5ea31b263ada5c61377e710a924/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a029be818059870664157194e46ce0e995082ac49926f1423c1f058534d2aaa9", size = 555928, upload-time = "2025-08-07T08:24:37.573Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/b18eb51045d06887666c3560cd4bbb6819127b43d758f5adb82b5f56f7d1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3841f66c1ffdc6cebce8aed64e36db71466f1dc23c0d9a5592e2a782a3042c79", size = 585527, upload-time = "2025-08-07T08:24:39.391Z" }, + { url = "https://files.pythonhosted.org/packages/be/03/a3dd6470fc76499959b00ae56295b76b4bdf7c6ffc60d62006b1217567e1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:42894616da0fc0dcb2ec08a77896c3f56e9cb2f4b66acd76fc8992c3557ceb1c", size = 554211, upload-time = "2025-08-07T08:24:40.6Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d1/ee5fd1be395a07423ac4ca0bcc05280bf95db2b155d03adefeb47d5ebf7e/rpds_py-0.27.0-cp313-cp313t-win32.whl", hash = "sha256:b1fef1f13c842a39a03409e30ca0bf87b39a1e2a305a9924deadb75a43105d23", size = 216624, upload-time = "2025-08-07T08:24:42.204Z" }, + { url = "https://files.pythonhosted.org/packages/1c/94/4814c4c858833bf46706f87349c37ca45e154da7dbbec9ff09f1abeb08cc/rpds_py-0.27.0-cp313-cp313t-win_amd64.whl", hash = "sha256:183f5e221ba3e283cd36fdfbe311d95cd87699a083330b4f792543987167eff1", size = 230007, upload-time = "2025-08-07T08:24:43.329Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a5/8fffe1c7dc7c055aa02df310f9fb71cfc693a4d5ccc5de2d3456ea5fb022/rpds_py-0.27.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f3cd110e02c5bf17d8fb562f6c9df5c20e73029d587cf8602a2da6c5ef1e32cb", size = 362595, upload-time = "2025-08-07T08:24:44.478Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c7/4e4253fd2d4bb0edbc0b0b10d9f280612ca4f0f990e3c04c599000fe7d71/rpds_py-0.27.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8d0e09cf4863c74106b5265c2c310f36146e2b445ff7b3018a56799f28f39f6f", size = 347252, upload-time = "2025-08-07T08:24:45.678Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c8/3d1a954d30f0174dd6baf18b57c215da03cf7846a9d6e0143304e784cddc/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f689ab822f9b5eb6dfc69893b4b9366db1d2420f7db1f6a2adf2a9ca15ad64", size = 384886, upload-time = "2025-08-07T08:24:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/e0/52/3c5835f2df389832b28f9276dd5395b5a965cea34226e7c88c8fbec2093c/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e36c80c49853b3ffda7aa1831bf175c13356b210c73128c861f3aa93c3cc4015", size = 399716, upload-time = "2025-08-07T08:24:48.174Z" }, + { url = "https://files.pythonhosted.org/packages/40/73/176e46992461a1749686a2a441e24df51ff86b99c2d34bf39f2a5273b987/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6de6a7f622860af0146cb9ee148682ff4d0cea0b8fd3ad51ce4d40efb2f061d0", size = 517030, upload-time = "2025-08-07T08:24:49.52Z" }, + { url = "https://files.pythonhosted.org/packages/79/2a/7266c75840e8c6e70effeb0d38922a45720904f2cd695e68a0150e5407e2/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4045e2fc4b37ec4b48e8907a5819bdd3380708c139d7cc358f03a3653abedb89", size = 408448, upload-time = "2025-08-07T08:24:50.727Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5f/a7efc572b8e235093dc6cf39f4dbc8a7f08e65fdbcec7ff4daeb3585eef1/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da162b718b12c4219eeeeb68a5b7552fbc7aadedf2efee440f88b9c0e54b45d", size = 387320, upload-time = "2025-08-07T08:24:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/a2/eb/9ff6bc92efe57cf5a2cb74dee20453ba444b6fdc85275d8c99e0d27239d1/rpds_py-0.27.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:0665be515767dc727ffa5f74bd2ef60b0ff85dad6bb8f50d91eaa6b5fb226f51", size = 407414, upload-time = "2025-08-07T08:24:53.664Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bd/3b9b19b00d5c6e1bd0f418c229ab0f8d3b110ddf7ec5d9d689ef783d0268/rpds_py-0.27.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:203f581accef67300a942e49a37d74c12ceeef4514874c7cede21b012613ca2c", size = 420766, upload-time = "2025-08-07T08:24:55.917Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/521a7b1079ce16258c70805166e3ac6ec4ee2139d023fe07954dc9b2d568/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7873b65686a6471c0037139aa000d23fe94628e0daaa27b6e40607c90e3f5ec4", size = 562409, upload-time = "2025-08-07T08:24:57.17Z" }, + { url = "https://files.pythonhosted.org/packages/8b/bf/65db5bfb14ccc55e39de8419a659d05a2a9cd232f0a699a516bb0991da7b/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:249ab91ceaa6b41abc5f19513cb95b45c6f956f6b89f1fe3d99c81255a849f9e", size = 590793, upload-time = "2025-08-07T08:24:58.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/b8/82d368b378325191ba7aae8f40f009b78057b598d4394d1f2cdabaf67b3f/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d2f184336bc1d6abfaaa1262ed42739c3789b1e3a65a29916a615307d22ffd2e", size = 558178, upload-time = "2025-08-07T08:24:59.756Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ff/f270bddbfbc3812500f8131b1ebbd97afd014cd554b604a3f73f03133a36/rpds_py-0.27.0-cp314-cp314-win32.whl", hash = "sha256:d3c622c39f04d5751408f5b801ecb527e6e0a471b367f420a877f7a660d583f6", size = 222355, upload-time = "2025-08-07T08:25:01.027Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/fdab055b1460c02ed356a0e0b0a78c1dd32dc64e82a544f7b31c9ac643dc/rpds_py-0.27.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf824aceaeffff029ccfba0da637d432ca71ab21f13e7f6f5179cd88ebc77a8a", size = 234007, upload-time = "2025-08-07T08:25:02.268Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a8/694c060005421797a3be4943dab8347c76c2b429a9bef68fb2c87c9e70c7/rpds_py-0.27.0-cp314-cp314-win_arm64.whl", hash = "sha256:86aca1616922b40d8ac1b3073a1ead4255a2f13405e5700c01f7c8d29a03972d", size = 223527, upload-time = "2025-08-07T08:25:03.45Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f9/77f4c90f79d2c5ca8ce6ec6a76cb4734ee247de6b3a4f337e289e1f00372/rpds_py-0.27.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:341d8acb6724c0c17bdf714319c393bb27f6d23d39bc74f94221b3e59fc31828", size = 359469, upload-time = "2025-08-07T08:25:04.648Z" }, + { url = "https://files.pythonhosted.org/packages/c0/22/b97878d2f1284286fef4172069e84b0b42b546ea7d053e5fb7adb9ac6494/rpds_py-0.27.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6b96b0b784fe5fd03beffff2b1533dc0d85e92bab8d1b2c24ef3a5dc8fac5669", size = 343960, upload-time = "2025-08-07T08:25:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b0/dfd55b5bb480eda0578ae94ef256d3061d20b19a0f5e18c482f03e65464f/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c431bfb91478d7cbe368d0a699978050d3b112d7f1d440a41e90faa325557fd", size = 380201, upload-time = "2025-08-07T08:25:07.513Z" }, + { url = "https://files.pythonhosted.org/packages/28/22/e1fa64e50d58ad2b2053077e3ec81a979147c43428de9e6de68ddf6aff4e/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e222a44ae9f507d0f2678ee3dd0c45ec1e930f6875d99b8459631c24058aec", size = 392111, upload-time = "2025-08-07T08:25:09.149Z" }, + { url = "https://files.pythonhosted.org/packages/49/f9/43ab7a43e97aedf6cea6af70fdcbe18abbbc41d4ae6cdec1bfc23bbad403/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:184f0d7b342967f6cda94a07d0e1fae177d11d0b8f17d73e06e36ac02889f303", size = 515863, upload-time = "2025-08-07T08:25:10.431Z" }, + { url = "https://files.pythonhosted.org/packages/38/9b/9bd59dcc636cd04d86a2d20ad967770bf348f5eb5922a8f29b547c074243/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a00c91104c173c9043bc46f7b30ee5e6d2f6b1149f11f545580f5d6fdff42c0b", size = 402398, upload-time = "2025-08-07T08:25:11.819Z" }, + { url = "https://files.pythonhosted.org/packages/71/bf/f099328c6c85667aba6b66fa5c35a8882db06dcd462ea214be72813a0dd2/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a37dd208f0d658e0487522078b1ed68cd6bce20ef4b5a915d2809b9094b410", size = 384665, upload-time = "2025-08-07T08:25:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c5/9c1f03121ece6634818490bd3c8be2c82a70928a19de03467fb25a3ae2a8/rpds_py-0.27.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:92f3b3ec3e6008a1fe00b7c0946a170f161ac00645cde35e3c9a68c2475e8156", size = 400405, upload-time = "2025-08-07T08:25:14.417Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b8/e25d54af3e63ac94f0c16d8fe143779fe71ff209445a0c00d0f6984b6b2c/rpds_py-0.27.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1b3db5fae5cbce2131b7420a3f83553d4d89514c03d67804ced36161fe8b6b2", size = 413179, upload-time = "2025-08-07T08:25:15.664Z" }, + { url = "https://files.pythonhosted.org/packages/f9/d1/406b3316433fe49c3021546293a04bc33f1478e3ec7950215a7fce1a1208/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5355527adaa713ab693cbce7c1e0ec71682f599f61b128cf19d07e5c13c9b1f1", size = 556895, upload-time = "2025-08-07T08:25:17.061Z" }, + { url = "https://files.pythonhosted.org/packages/5f/bc/3697c0c21fcb9a54d46ae3b735eb2365eea0c2be076b8f770f98e07998de/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fcc01c57ce6e70b728af02b2401c5bc853a9e14eb07deda30624374f0aebfe42", size = 585464, upload-time = "2025-08-07T08:25:18.406Z" }, + { url = "https://files.pythonhosted.org/packages/63/09/ee1bb5536f99f42c839b177d552f6114aa3142d82f49cef49261ed28dbe0/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3001013dae10f806380ba739d40dee11db1ecb91684febb8406a87c2ded23dae", size = 555090, upload-time = "2025-08-07T08:25:20.461Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2c/363eada9e89f7059199d3724135a86c47082cbf72790d6ba2f336d146ddb/rpds_py-0.27.0-cp314-cp314t-win32.whl", hash = "sha256:0f401c369186a5743694dd9fc08cba66cf70908757552e1f714bfc5219c655b5", size = 218001, upload-time = "2025-08-07T08:25:21.761Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3f/d6c216ed5199c9ef79e2a33955601f454ed1e7420a93b89670133bca5ace/rpds_py-0.27.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1dca5507fa1337f75dcd5070218b20bc68cf8844271c923c1b79dfcbc20391", size = 230993, upload-time = "2025-08-07T08:25:23.34Z" }, +] + +[[package]] +name = "rsa" +version = "4.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, +] + +[[package]] +name = "s3transfer" +version = "0.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/05/d52bf1e65044b4e5e27d4e63e8d1579dbdec54fce685908ae09bc3720030/s3transfer-0.13.1.tar.gz", hash = "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf", size = 150589, upload-time = "2025-07-18T19:22:42.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl", hash = "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724", size = 85308, upload-time = "2025-07-18T19:22:40.947Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "sse-starlette" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/6f/22ed6e33f8a9e76ca0a412405f31abb844b779d52c5f96660766edcd737c/sse_starlette-3.0.2.tar.gz", hash = "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a", size = 20985, upload-time = "2025-07-27T09:07:44.565Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/10/c78f463b4ef22eef8491f218f692be838282cd65480f6e423d7730dfd1fb/sse_starlette-3.0.2-py3-none-any.whl", hash = "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", size = 11297, upload-time = "2025-07-27T09:07:43.268Z" }, +] + +[[package]] +name = "starlette" +version = "0.47.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/15/b9/cc3017f9a9c9b6e27c5106cc10cc7904653c3eec0729793aec10479dd669/starlette-0.47.3.tar.gz", hash = "sha256:6bc94f839cc176c4858894f1f8908f0ab79dfec1a6b8402f6da9be26ebea52e9", size = 2584144, upload-time = "2025-08-24T13:36:42.122Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/fd/901cfa59aaa5b30a99e16876f11abe38b59a1a2c51ffb3d7142bb6089069/starlette-0.47.3-py3-none-any.whl", hash = "sha256:89c0778ca62a76b826101e7c709e70680a1699ca7da6b44d38eb0a7e61fe4b51", size = 72991, upload-time = "2025-08-24T13:36:40.887Z" }, +] + +[[package]] +name = "temporalio" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nexus-rpc" }, + { name = "protobuf" }, + { name = "types-protobuf" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/a7/622047cb731a104e455687793d724ed143925e9ea14b522ad5ce224e8d7f/temporalio-1.17.0.tar.gz", hash = "sha256:1ac8f1ade36fafe7110b979b6a16d89203e1f4fb9c874f2fe3b5d83c17b13244", size = 1734067, upload-time = "2025-09-03T01:27:05.205Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/9a/f6fd68e60afc67c402c0676c12baba3aa04d522c74f4123ed31b544d4159/temporalio-1.17.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:7a86948c74a872b7f5ecb51c5d7e8013fdda4d6a220fe92185629342e94393e7", size = 12905249, upload-time = "2025-09-03T01:26:51.93Z" }, + { url = "https://files.pythonhosted.org/packages/8c/7e/54cffb6a0ef4853f51bcefe5a74508940bad72a4442e50b3d52379a941c3/temporalio-1.17.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:00b34a986012a355bdadf0e7eb9e57e176f2e0b1d69ea4be9eb73c21672e7fd0", size = 12539749, upload-time = "2025-09-03T01:26:54.854Z" }, + { url = "https://files.pythonhosted.org/packages/ec/f3/e4c829eb31bdb5eb14411ce7765b4ad8087794231110ff6188497859f0e6/temporalio-1.17.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36a84e52727e287e13777d86fa0bbda11ba6523f75a616b811cc9d799b37b98c", size = 12969855, upload-time = "2025-09-03T01:26:57.464Z" }, + { url = "https://files.pythonhosted.org/packages/95/26/fef412e10408e35888815ac06c0c777cff1faa76157d861878d23a17edf0/temporalio-1.17.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:617f37edce3db97cc7d2ff81c145a1b92c100f6e0e42207739271d10c2eea38e", size = 13165153, upload-time = "2025-09-03T01:27:00.285Z" }, + { url = "https://files.pythonhosted.org/packages/58/2d/01d164b78ea414f1e2554cd9959ffcf95f0c91a6d595f03128a70e433f57/temporalio-1.17.0-cp39-abi3-win_amd64.whl", hash = "sha256:f2724220fda1fd5948d917350ac25069c62624f46e53d4d6c6171baa75681145", size = 13178439, upload-time = "2025-09-03T01:27:02.855Z" }, +] + +[[package]] +name = "tenacity" +version = "9.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, +] + +[[package]] +name = "tokenizers" +version = "0.21.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/2f/402986d0823f8d7ca139d969af2917fefaa9b947d1fb32f6168c509f2492/tokenizers-0.21.4.tar.gz", hash = "sha256:fa23f85fbc9a02ec5c6978da172cdcbac23498c3ca9f3645c5c68740ac007880", size = 351253, upload-time = "2025-07-28T15:48:54.325Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/c6/fdb6f72bf6454f52eb4a2510be7fb0f614e541a2554d6210e370d85efff4/tokenizers-0.21.4-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:2ccc10a7c3bcefe0f242867dc914fc1226ee44321eb618cfe3019b5df3400133", size = 2863987, upload-time = "2025-07-28T15:48:44.877Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a6/28975479e35ddc751dc1ddc97b9b69bf7fcf074db31548aab37f8116674c/tokenizers-0.21.4-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:5e2f601a8e0cd5be5cc7506b20a79112370b9b3e9cb5f13f68ab11acd6ca7d60", size = 2732457, upload-time = "2025-07-28T15:48:43.265Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8f/24f39d7b5c726b7b0be95dca04f344df278a3fe3a4deb15a975d194cbb32/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b376f5a1aee67b4d29032ee85511bbd1b99007ec735f7f35c8a2eb104eade5", size = 3012624, upload-time = "2025-07-28T13:22:43.895Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/26358925717687a58cb74d7a508de96649544fad5778f0cd9827398dc499/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2107ad649e2cda4488d41dfd031469e9da3fcbfd6183e74e4958fa729ffbf9c6", size = 2939681, upload-time = "2025-07-28T13:22:47.499Z" }, + { url = "https://files.pythonhosted.org/packages/99/6f/cc300fea5db2ab5ddc2c8aea5757a27b89c84469899710c3aeddc1d39801/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c73012da95afafdf235ba80047699df4384fdc481527448a078ffd00e45a7d9", size = 3247445, upload-time = "2025-07-28T15:48:39.711Z" }, + { url = "https://files.pythonhosted.org/packages/be/bf/98cb4b9c3c4afd8be89cfa6423704337dc20b73eb4180397a6e0d456c334/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f23186c40395fc390d27f519679a58023f368a0aad234af145e0f39ad1212732", size = 3428014, upload-time = "2025-07-28T13:22:49.569Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/96c1cc780e6ca7f01a57c13235dd05b7bc1c0f3588512ebe9d1331b5f5ae/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc88bb34e23a54cc42713d6d98af5f1bf79c07653d24fe984d2d695ba2c922a2", size = 3193197, upload-time = "2025-07-28T13:22:51.471Z" }, + { url = "https://files.pythonhosted.org/packages/f2/90/273b6c7ec78af547694eddeea9e05de771278bd20476525ab930cecaf7d8/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51b7eabb104f46c1c50b486520555715457ae833d5aee9ff6ae853d1130506ff", size = 3115426, upload-time = "2025-07-28T15:48:41.439Z" }, + { url = "https://files.pythonhosted.org/packages/91/43/c640d5a07e95f1cf9d2c92501f20a25f179ac53a4f71e1489a3dcfcc67ee/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:714b05b2e1af1288bd1bc56ce496c4cebb64a20d158ee802887757791191e6e2", size = 9089127, upload-time = "2025-07-28T15:48:46.472Z" }, + { url = "https://files.pythonhosted.org/packages/44/a1/dd23edd6271d4dca788e5200a807b49ec3e6987815cd9d0a07ad9c96c7c2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1340ff877ceedfa937544b7d79f5b7becf33a4cfb58f89b3b49927004ef66f78", size = 9055243, upload-time = "2025-07-28T15:48:48.539Z" }, + { url = "https://files.pythonhosted.org/packages/21/2b/b410d6e9021c4b7ddb57248304dc817c4d4970b73b6ee343674914701197/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3c1f4317576e465ac9ef0d165b247825a2a4078bcd01cba6b54b867bdf9fdd8b", size = 9298237, upload-time = "2025-07-28T15:48:50.443Z" }, + { url = "https://files.pythonhosted.org/packages/b7/0a/42348c995c67e2e6e5c89ffb9cfd68507cbaeb84ff39c49ee6e0a6dd0fd2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:c212aa4e45ec0bb5274b16b6f31dd3f1c41944025c2358faaa5782c754e84c24", size = 9461980, upload-time = "2025-07-28T15:48:52.325Z" }, + { url = "https://files.pythonhosted.org/packages/3d/d3/dacccd834404cd71b5c334882f3ba40331ad2120e69ded32cf5fda9a7436/tokenizers-0.21.4-cp39-abi3-win32.whl", hash = "sha256:6c42a930bc5f4c47f4ea775c91de47d27910881902b0f20e4990ebe045a415d0", size = 2329871, upload-time = "2025-07-28T15:48:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/41/f2/fd673d979185f5dcbac4be7d09461cbb99751554ffb6718d0013af8604cb/tokenizers-0.21.4-cp39-abi3-win_amd64.whl", hash = "sha256:475d807a5c3eb72c59ad9b5fcdb254f6e17f53dfcbb9903233b0dfa9c943b597", size = 2507568, upload-time = "2025-07-28T15:48:55.456Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, +] + +[[package]] +name = "tqdm" +version = "4.67.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, +] + +[[package]] +name = "trove-classifiers" +version = "2025.8.6.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/21/707af14daa638b0df15b5d5700349e0abdd3e5140069f9ab6e0ccb922806/trove_classifiers-2025.8.6.13.tar.gz", hash = "sha256:5a0abad839d2ed810f213ab133d555d267124ddea29f1d8a50d6eca12a50ae6e", size = 16932, upload-time = "2025-08-06T13:26:26.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/44/323a87d78f04d5329092aada803af3612dd004a64b69ba8b13046601a8c9/trove_classifiers-2025.8.6.13-py3-none-any.whl", hash = "sha256:c4e7fc83012770d80b3ae95816111c32b085716374dccee0d3fbf5c235495f9f", size = 14121, upload-time = "2025-08-06T13:26:25.063Z" }, +] + +[[package]] +name = "types-protobuf" +version = "6.30.2.20250822" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/68/0c7144be5c6dc16538e79458839fc914ea494481c7e64566de4ecc0c3682/types_protobuf-6.30.2.20250822.tar.gz", hash = "sha256:faacbbe87bd8cba4472361c0bd86f49296bd36f7761e25d8ada4f64767c1bde9", size = 62379, upload-time = "2025-08-22T03:01:56.572Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/64/b926a6355993f712d7828772e42b9ae942f2d306d25072329805c374e729/types_protobuf-6.30.2.20250822-py3-none-any.whl", hash = "sha256:5584c39f7e36104b5f8bdfd31815fa1d5b7b3455a79ddddc097b62320f4b1841", size = 76523, upload-time = "2025-08-22T03:01:55.157Z" }, +] + +[[package]] +name = "types-requests" +version = "2.32.4.20250809" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/b0/9355adb86ec84d057fea765e4c49cce592aaf3d5117ce5609a95a7fc3dac/types_requests-2.32.4.20250809.tar.gz", hash = "sha256:d8060de1c8ee599311f56ff58010fb4902f462a1470802cf9f6ed27bc46c4df3", size = 23027, upload-time = "2025-08-09T03:17:10.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/6f/ec0012be842b1d888d46884ac5558fd62aeae1f0ec4f7a581433d890d4b5/types_requests-2.32.4.20250809-py3-none-any.whl", hash = "sha256:f73d1832fb519ece02c85b1f09d5f0dd3108938e7d47e7f94bbfa18a6782b163", size = 20644, upload-time = "2025-08-09T03:17:09.716Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "uv-dynamic-versioning" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dunamai" }, + { name = "hatchling" }, + { name = "jinja2" }, + { name = "tomlkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/5e/f8cb4f05228225c9dfa27bc64e50247dd111dbdb7838aab59ef2ea70ea7b/uv_dynamic_versioning-0.11.0.tar.gz", hash = "sha256:0dc2aac525d7db15a69b4f1317040d2fd7df71d1f1ae7171cb85080c2b998c23", size = 39733, upload-time = "2025-08-22T10:11:03.765Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/07/4e11e21d0e9a9b801414ce7fb76f15a9888b1ea6df3112a4842065801c7f/uv_dynamic_versioning-0.11.0-py3-none-any.whl", hash = "sha256:954d50391820929ebcc5842284e04dd75f21ba9d5f47913426068eb883100122", size = 10909, upload-time = "2025-08-22T10:11:02.585Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + +[[package]] +name = "wrapt" +version = "1.17.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, + { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, + { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, + { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, + { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, + { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, + { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, + { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, + { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, + { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, + { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" }, + { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" }, + { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" }, + { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" }, + { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" }, + { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" }, + { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" }, + { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" }, + { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" }, + { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" }, + { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" }, + { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" }, + { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, + { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, + { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, +] + +[[package]] +name = "yarl" +version = "1.20.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/fb/efaa23fa4e45537b827620f04cf8f3cd658b76642205162e072703a5b963/yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac", size = 186428, upload-time = "2025-06-10T00:46:09.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/9a/cb7fad7d73c69f296eda6815e4a2c7ed53fc70c2f136479a91c8e5fbdb6d/yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9", size = 133667, upload-time = "2025-06-10T00:43:44.369Z" }, + { url = "https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a", size = 91025, upload-time = "2025-06-10T00:43:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/50/ec/72991ae51febeb11a42813fc259f0d4c8e0507f2b74b5514618d8b640365/yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2", size = 89709, upload-time = "2025-06-10T00:43:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/99/da/4d798025490e89426e9f976702e5f9482005c548c579bdae792a4c37769e/yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee", size = 352287, upload-time = "2025-06-10T00:43:49.924Z" }, + { url = "https://files.pythonhosted.org/packages/1a/26/54a15c6a567aac1c61b18aa0f4b8aa2e285a52d547d1be8bf48abe2b3991/yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819", size = 345429, upload-time = "2025-06-10T00:43:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/d6/95/9dcf2386cb875b234353b93ec43e40219e14900e046bf6ac118f94b1e353/yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16", size = 365429, upload-time = "2025-06-10T00:43:53.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/b2/33a8750f6a4bc224242a635f5f2cff6d6ad5ba651f6edcccf721992c21a0/yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6", size = 363862, upload-time = "2025-06-10T00:43:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd", size = 355616, upload-time = "2025-06-10T00:43:58.056Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f666894aa947a371724ec7cd2e5daa78ee8a777b21509b4252dd7bd15e29/yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a", size = 339954, upload-time = "2025-06-10T00:43:59.773Z" }, + { url = "https://files.pythonhosted.org/packages/f1/81/5f466427e09773c04219d3450d7a1256138a010b6c9f0af2d48565e9ad13/yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38", size = 365575, upload-time = "2025-06-10T00:44:02.051Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e3/e4b0ad8403e97e6c9972dd587388940a032f030ebec196ab81a3b8e94d31/yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef", size = 365061, upload-time = "2025-06-10T00:44:04.196Z" }, + { url = "https://files.pythonhosted.org/packages/ac/99/b8a142e79eb86c926f9f06452eb13ecb1bb5713bd01dc0038faf5452e544/yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f", size = 364142, upload-time = "2025-06-10T00:44:06.527Z" }, + { url = "https://files.pythonhosted.org/packages/34/f2/08ed34a4a506d82a1a3e5bab99ccd930a040f9b6449e9fd050320e45845c/yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8", size = 381894, upload-time = "2025-06-10T00:44:08.379Z" }, + { url = "https://files.pythonhosted.org/packages/92/f8/9a3fbf0968eac704f681726eff595dce9b49c8a25cd92bf83df209668285/yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a", size = 383378, upload-time = "2025-06-10T00:44:10.51Z" }, + { url = "https://files.pythonhosted.org/packages/af/85/9363f77bdfa1e4d690957cd39d192c4cacd1c58965df0470a4905253b54f/yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004", size = 374069, upload-time = "2025-06-10T00:44:12.834Z" }, + { url = "https://files.pythonhosted.org/packages/35/99/9918c8739ba271dcd935400cff8b32e3cd319eaf02fcd023d5dcd487a7c8/yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5", size = 81249, upload-time = "2025-06-10T00:44:14.731Z" }, + { url = "https://files.pythonhosted.org/packages/eb/83/5d9092950565481b413b31a23e75dd3418ff0a277d6e0abf3729d4d1ce25/yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698", size = 86710, upload-time = "2025-06-10T00:44:16.716Z" }, + { url = "https://files.pythonhosted.org/packages/8a/e1/2411b6d7f769a07687acee88a062af5833cf1966b7266f3d8dfb3d3dc7d3/yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a", size = 131811, upload-time = "2025-06-10T00:44:18.933Z" }, + { url = "https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3", size = 90078, upload-time = "2025-06-10T00:44:20.635Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9a/3246ae92d4049099f52d9b0fe3486e3b500e29b7ea872d0f152966fc209d/yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7", size = 88748, upload-time = "2025-06-10T00:44:22.34Z" }, + { url = "https://files.pythonhosted.org/packages/a3/25/35afe384e31115a1a801fbcf84012d7a066d89035befae7c5d4284df1e03/yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691", size = 349595, upload-time = "2025-06-10T00:44:24.314Z" }, + { url = "https://files.pythonhosted.org/packages/28/2d/8aca6cb2cabc8f12efcb82749b9cefecbccfc7b0384e56cd71058ccee433/yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31", size = 342616, upload-time = "2025-06-10T00:44:26.167Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e9/1312633d16b31acf0098d30440ca855e3492d66623dafb8e25b03d00c3da/yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28", size = 361324, upload-time = "2025-06-10T00:44:27.915Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a0/688cc99463f12f7669eec7c8acc71ef56a1521b99eab7cd3abb75af887b0/yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653", size = 359676, upload-time = "2025-06-10T00:44:30.041Z" }, + { url = "https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5", size = 352614, upload-time = "2025-06-10T00:44:32.171Z" }, + { url = "https://files.pythonhosted.org/packages/b1/91/31163295e82b8d5485d31d9cf7754d973d41915cadce070491778d9c9825/yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02", size = 336766, upload-time = "2025-06-10T00:44:34.494Z" }, + { url = "https://files.pythonhosted.org/packages/b4/8e/c41a5bc482121f51c083c4c2bcd16b9e01e1cf8729e380273a952513a21f/yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53", size = 364615, upload-time = "2025-06-10T00:44:36.856Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5b/61a3b054238d33d70ea06ebba7e58597891b71c699e247df35cc984ab393/yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc", size = 360982, upload-time = "2025-06-10T00:44:39.141Z" }, + { url = "https://files.pythonhosted.org/packages/df/a3/6a72fb83f8d478cb201d14927bc8040af901811a88e0ff2da7842dd0ed19/yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04", size = 369792, upload-time = "2025-06-10T00:44:40.934Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/4cc3c36dfc7c077f8dedb561eb21f69e1e9f2456b91b593882b0b18c19dc/yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4", size = 382049, upload-time = "2025-06-10T00:44:42.854Z" }, + { url = "https://files.pythonhosted.org/packages/19/3a/e54e2c4752160115183a66dc9ee75a153f81f3ab2ba4bf79c3c53b33de34/yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b", size = 384774, upload-time = "2025-06-10T00:44:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/200ae86dabfca89060ec6447649f219b4cbd94531e425e50d57e5f5ac330/yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1", size = 374252, upload-time = "2025-06-10T00:44:47.31Z" }, + { url = "https://files.pythonhosted.org/packages/83/75/11ee332f2f516b3d094e89448da73d557687f7d137d5a0f48c40ff211487/yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7", size = 81198, upload-time = "2025-06-10T00:44:49.164Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c", size = 86346, upload-time = "2025-06-10T00:44:51.182Z" }, + { url = "https://files.pythonhosted.org/packages/43/c7/669c52519dca4c95153c8ad96dd123c79f354a376346b198f438e56ffeb4/yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d", size = 138826, upload-time = "2025-06-10T00:44:52.883Z" }, + { url = "https://files.pythonhosted.org/packages/6a/42/fc0053719b44f6ad04a75d7f05e0e9674d45ef62f2d9ad2c1163e5c05827/yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf", size = 93217, upload-time = "2025-06-10T00:44:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/4f/7f/fa59c4c27e2a076bba0d959386e26eba77eb52ea4a0aac48e3515c186b4c/yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3", size = 92700, upload-time = "2025-06-10T00:44:56.784Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/062b2f48e7c93481e88eff97a6312dca15ea200e959f23e96d8ab898c5b8/yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d", size = 347644, upload-time = "2025-06-10T00:44:59.071Z" }, + { url = "https://files.pythonhosted.org/packages/89/47/78b7f40d13c8f62b499cc702fdf69e090455518ae544c00a3bf4afc9fc77/yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c", size = 323452, upload-time = "2025-06-10T00:45:01.605Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2b/490d3b2dc66f52987d4ee0d3090a147ea67732ce6b4d61e362c1846d0d32/yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1", size = 346378, upload-time = "2025-06-10T00:45:03.946Z" }, + { url = "https://files.pythonhosted.org/packages/66/ad/775da9c8a94ce925d1537f939a4f17d782efef1f973039d821cbe4bcc211/yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce", size = 353261, upload-time = "2025-06-10T00:45:05.992Z" }, + { url = "https://files.pythonhosted.org/packages/4b/23/0ed0922b47a4f5c6eb9065d5ff1e459747226ddce5c6a4c111e728c9f701/yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3", size = 335987, upload-time = "2025-06-10T00:45:08.227Z" }, + { url = "https://files.pythonhosted.org/packages/3e/49/bc728a7fe7d0e9336e2b78f0958a2d6b288ba89f25a1762407a222bf53c3/yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be", size = 329361, upload-time = "2025-06-10T00:45:10.11Z" }, + { url = "https://files.pythonhosted.org/packages/93/8f/b811b9d1f617c83c907e7082a76e2b92b655400e61730cd61a1f67178393/yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16", size = 346460, upload-time = "2025-06-10T00:45:12.055Z" }, + { url = "https://files.pythonhosted.org/packages/70/fd/af94f04f275f95da2c3b8b5e1d49e3e79f1ed8b6ceb0f1664cbd902773ff/yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513", size = 334486, upload-time = "2025-06-10T00:45:13.995Z" }, + { url = "https://files.pythonhosted.org/packages/84/65/04c62e82704e7dd0a9b3f61dbaa8447f8507655fd16c51da0637b39b2910/yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f", size = 342219, upload-time = "2025-06-10T00:45:16.479Z" }, + { url = "https://files.pythonhosted.org/packages/91/95/459ca62eb958381b342d94ab9a4b6aec1ddec1f7057c487e926f03c06d30/yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390", size = 350693, upload-time = "2025-06-10T00:45:18.399Z" }, + { url = "https://files.pythonhosted.org/packages/a6/00/d393e82dd955ad20617abc546a8f1aee40534d599ff555ea053d0ec9bf03/yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458", size = 355803, upload-time = "2025-06-10T00:45:20.677Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ed/c5fb04869b99b717985e244fd93029c7a8e8febdfcffa06093e32d7d44e7/yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e", size = 341709, upload-time = "2025-06-10T00:45:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/24/fd/725b8e73ac2a50e78a4534ac43c6addf5c1c2d65380dd48a9169cc6739a9/yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d", size = 86591, upload-time = "2025-06-10T00:45:25.793Z" }, + { url = "https://files.pythonhosted.org/packages/94/c3/b2e9f38bc3e11191981d57ea08cab2166e74ea770024a646617c9cddd9f6/yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f", size = 93003, upload-time = "2025-06-10T00:45:27.752Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2d/2345fce04cfd4bee161bf1e7d9cdc702e3e16109021035dbb24db654a622/yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77", size = 46542, upload-time = "2025-06-10T00:46:07.521Z" }, +] + +[[package]] +name = "zipp" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, +] diff --git a/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json new file mode 100644 index 0000000000..e1c79d1d7e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json @@ -0,0 +1,51 @@ +{ + "name": "departments_flat", + "fields": [ + { + "name": "id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": true, + "synonymMaps": [] + }, + { + "name": "department", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "description", + "type": "Edm.String", + "searchable": true, + "filterable": false, + "retrievable": true, + "stored": true, + "sortable": false, + "facetable": false, + "key": false, + "synonymMaps": [] + } + ], + "scoringProfiles": [], + "suggesters": [], + "analyzers": [], + "normalizers": [], + "tokenizers": [], + "tokenFilters": [], + "charFilters": [], + "similarity": { + "@odata.type": "#Microsoft.Azure.Search.BM25Similarity" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json new file mode 100644 index 0000000000..f1c36bbd2c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json @@ -0,0 +1,75 @@ +{ + "name": "net_sales", + "fields": [ + { + "name": "id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": true, + "synonymMaps": [] + }, + { + "name": "sku_id", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "net_sales", + "type": "Edm.Double", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "name", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "department", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + } + ], + "scoringProfiles": [], + "suggesters": [], + "analyzers": [], + "normalizers": [], + "tokenizers": [], + "tokenFilters": [], + "charFilters": [], + "similarity": { + "@odata.type": "#Microsoft.Azure.Search.BM25Similarity" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json new file mode 100644 index 0000000000..dd91605c9f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json @@ -0,0 +1,99 @@ +{ + "name": "product_inventory", + "fields": [ + { + "name": "id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": true, + "synonymMaps": [] + }, + { + "name": "sku_id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": false, + "synonymMaps": [] + }, + { + "name": "inventory_level", + "type": "Edm.Double", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "unit_price", + "type": "Edm.Double", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "name", + "type": "Edm.String", + "searchable": true, + "filterable": false, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": false, + "synonymMaps": [] + }, + { + "name": "description", + "type": "Edm.String", + "searchable": true, + "filterable": false, + "retrievable": true, + "stored": true, + "sortable": false, + "facetable": false, + "key": false, + "synonymMaps": [] + }, + { + "name": "department", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + } + ], + "scoringProfiles": [], + "suggesters": [], + "analyzers": [], + "normalizers": [], + "tokenizers": [], + "tokenFilters": [], + "charFilters": [], + "similarity": { + "@odata.type": "#Microsoft.Azure.Search.BM25Similarity" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh b/074-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh new file mode 100644 index 0000000000..10227bac7d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# This script creates the necessary indices in Azure AI Search +# It assumes that the CURL CLI is installed, configured, and the user is authenticated. +# It also assumes that the user has the necessary permissions (ADMIN API KEY) to create indices. + +AI_SEARCH_API_VERSION="2025-03-01-Preview" + +create_ai_search_index() +{ + # Get the index name from the first argument + INDEX_NAME="$1" + # Get the index schema from the second argument + INDEX_SCHEMA="./ai-search-schemas/${INDEX_NAME}.json" + # Get the search service name from the third argument + SEARCH_SERVICE_NAME="${AZURE_SEARCH_SERVICE_NAME}" + # Get the resource group name from the fourth argument + RESOURCE_GROUP="$4" + + # Create the index using the REST API endpoint + echo "" + echo "Creating index ${INDEX_NAME} in Azure AI Search service ${SEARCH_SERVICE_NAME}..." + # Use curl to send a PUT request to create the index + # Ensure the index schema file exists + if [ ! -f "${INDEX_SCHEMA}" ]; then + echo "Error: Index schema file ${INDEX_SCHEMA} does not exist." + exit 1 + fi + + # Use curl to send a PUT request to create the index + curl -X PUT \ + "https://${SEARCH_SERVICE_NAME}.search.windows.net/indexes/${INDEX_NAME}?api-version=${AI_SEARCH_API_VERSION}" \ + -H "Content-Type: application/json" \ + -H "api-key: ${AZURE_SEARCH_API_KEY}" \ + -d "@${INDEX_SCHEMA}" + + # Check if the index creation was successful + if [ $? -eq 0 ]; then + echo "Index ${INDEX_NAME} created successfully." + else + echo "Failed to create index ${INDEX_NAME}." + fi + + echo "" + echo "Done creating index ${INDEX_NAME} in Azure AI Search service ${SEARCH_SERVICE_NAME}..." + echo "" + echo "----------------------------------------------" + echo "" +} + +# List AI Search indices +# This will show all indices before creation +list_ai_search_indices() { + echo "" + echo "Listing all indices in Azure AI Search service ${AZURE_SEARCH_SERVICE_NAME}..." + + # Use curl to send a GET request and pipe output to jq for pretty-printing + response=$(curl -s -X GET \ + "https://${AZURE_SEARCH_SERVICE_NAME}.search.windows.net/indexes?api-version=${AI_SEARCH_API_VERSION}" \ + -H "Content-Type: application/json" \ + -H "api-key: ${AZURE_SEARCH_API_KEY}") + + # Check if curl executed successfully + if [ $? -eq 0 ]; then + echo "Listed all indices successfully." + echo "$response" | jq . + else + echo "Failed to list indices." + fi + + echo "" + echo "Done listing all indices in Azure AI Search service ${AZURE_SEARCH_SERVICE_NAME}..." + echo "" + echo "----------------------------------------------" + echo "" +} + + +# List all indices in the Azure AI Search service +list_ai_search_indices + +# Create the indices in Azure AI Search +create_ai_search_index "net_sales" +create_ai_search_index "product_inventory" + +# List all indices in the Azure AI Search service again +list_ai_search_indices + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml b/074-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml new file mode 100644 index 0000000000..fd6dd2abb3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml @@ -0,0 +1,34 @@ +--- +# Run the following commands to start the compose file +# docker-compose up + +# Run the following command to stop the compose file +# docker-compose down --remove-orphans + +networks: + default: + name: confluent_streams + driver: bridge + +services: + inventory: + image: izzyacademy/inventory:latest + env_file: [shared_environment_variables.env] + hostname: inventory + ports: ["8080:8080"] + + replenishment: + image: izzyacademy/replenishment:latest + env_file: [shared_environment_variables.env] + hostname: replenishment + ports: ["8081:8081"] + + employee: + image: izzyacademy/employee:latest + env_file: [shared_environment_variables.env] + hostname: employee + + supplier: + image: izzyacademy/supplier:latest + env_file: [shared_environment_variables.env] + hostname: supplier \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example b/074-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example new file mode 100644 index 0000000000..bc45c0d333 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example @@ -0,0 +1,32 @@ +# Azure Service Principal +AZURE_SUBSCRIPTION_ID=enter-your-subscription-id-here +AZURE_CLIENT_ID=enter-your-client-id-here +AZURE_CLIENT_SECRET=enter-your-client-secret-here +AZURE_TENANT_ID=enter-your-tenant-id-here + +# Azure AI Search +AZURE_AI_SEARCH_API_VERSION=2025-03-01-preview # keep or change as needed +AZURE_AI_SEARCH_ENDPOINT=https://your-search-service.search.windows.net +AZURE_AI_SEARCH_API_KEY=enter-your-ai-search-api-key-here + +# Azure Cosmos DB +COSMOS_CONNECTION_STRING=AccountEndpoint=https://your-cosmos-account.documents.azure.com:443/;AccountKey=enter-your-cosmos-key-here; +COSMOS_ENDPOINT=https://your-cosmos-account.documents.azure.com:443/ +COSMOS_DATABASE_NAME=enter-your-database-name-here + +# Azure Redis Cache +REDIS_HOST=your-redis-cache-name.redis.cache.windows.net +REDIS_PORT=6380 +REDIS_PASSWORD=enter-your-redis-password-here + +# Azure OpenAI (AI Foundry) +AZURE_OPENAI_ENDPOINT=https://your-openai-resource.openai.azure.com/ +AZURE_OPENAI_API_KEY=enter-your-openai-api-key-here +AZURE_OPENAI_MODEL_NAME=gpt-4o-mini +OPENAI_API_VERSION=2025-01-01-preview + +# MCP Services +# Adjust the below endpoint HTTP schemes, hostnames and ports as necessary for your setup +MCP_SERVICE_ENDPOINT_INVENTORY=http://inventory:8080/mcp +MCP_SERVICE_ENDPOINT_REPLENISHMENT=http://replenishment:8081/mcp +MCP_SERVICE_ENDPOINT_SHOPPING=http://shopping:8082/mcp diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh new file mode 100644 index 0000000000..947ff93fc6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Authenticate with Confluent Cloud CLI +# https://docs.confluent.io/cloud/current/cli/install.html +# Ensure you have the Confluent CLI installed and configured +confluent login + +confluent environment use "${CONFLUENT_ENVIRONMENT_ID}" + +# Ensure the Cluster Region matches the Azure Region +confluent kafka cluster use "${KAFKA_ID}" + +# Ensure the Flink Compute Pool Region matches the Azure Region +confluent flink compute-pool use "${FLINK_COMPUTE_POOL_ID}" + +confluent api-key store --force "${CONFLUENT_CLOUD_API_KEY}" "${CONFLUENT_CLOUD_API_SECRET}" +confluent api-key store --force "${KAFKA_API_KEY}" "${KAFKA_API_SECRET}" + +confluent api-key use "${KAFKA_API_KEY}" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh new file mode 100644 index 0000000000..3bf4ad013e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh @@ -0,0 +1,41 @@ + +# This script sets up a Confluent Connect cluster with the specified configuration file. + + +# Sets up a Confluent Connector using the provided configuration file. +setup_confluent_connector() +{ + local CONNECTOR_NAME="$1" + local CONNECTOR_CONFIG_DIRECTORY="./connector-configurations" + local CONNECTOR_CONFIG_FILE="${CONNECTOR_CONFIG_DIRECTORY}/${CONNECTOR_NAME}.final.json" + # Check if the connector configuration file exists + if [ ! -f "$CONNECTOR_CONFIG_FILE" ]; then + echo "Error: Connector configuration file $CONNECTOR_CONFIG_FILE does not exist." + exit 1 + fi + + # Create the connector using the provided configuration file + echo "" + echo "" + echo "Creating connector $CONNECTOR_NAME using configuration file $CONNECTOR_CONFIG_FILE..." + + # Create the Kafka Connector + confluent connect cluster create --config-file ${CONNECTOR_CONFIG_FILE} +} + + +# Create the Kafka Source Connectors for Azure Cosmos DB +setup_confluent_connector "cosmos_db_departments" +setup_confluent_connector "cosmos_db_product_pricing" +setup_confluent_connector "cosmos_db_product_skus" +setup_confluent_connector "cosmos_db_purchases" +setup_confluent_connector "cosmos_db_returns" +setup_confluent_connector "cosmos_db_replenishments" + +# Set up the Kafka Sink Connectors for Azure AI Search +setup_confluent_connector "ai_search_product_inventory" +setup_confluent_connector "ai_search_net_sales" +setup_confluent_connector "ai_search_departments_flat" + +# List all connectors in the cluster +confluent connect cluster list diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh new file mode 100644 index 0000000000..405aea9691 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# This script sets up the schemas for the Confluent Schema Registry. +# It creates the necessary topics and registers the schemas. +# Assumes that the Confluent CLI is installed, configured, and the user is authenticated. + +# Function to create a Kafka topic and register its key/value schemas +# Example usage +# create_topic_with_schema "sales_transactions" +create_topic_with_schema() { + + # Check if the topic name is provided + if [ -z "$1" ]; then + echo "Error: No topic name provided." + echo "Usage: create_topic_with_schema " + exit 1 + fi + + local topic_name="$1" # The name of the topic to create + local key_schema_file="./retail_store/${topic_name}/schemas/${topic_name}-key.json" # Path to the key schema file + local value_schema_file="./retail_store/${topic_name}/schemas/${topic_name}-value.json" # Path to the value schema file + + echo "" + echo "" + echo + echo "Creating topic: $topic_name" + confluent kafka topic create "$topic_name" --if-not-exists --partitions 6 + + echo "Registering value schema for subject: ${topic_name}-value" + confluent schema-registry schema create \ + --subject "${topic_name}-value" \ + --schema "$value_schema_file" \ + --type "json" + + echo "Registering key schema for subject: ${topic_name}-key" + confluent schema-registry schema create \ + --subject "${topic_name}-key" \ + --schema "$key_schema_file" \ + --type "json" + + echo "Verifying registered schemas for $topic_name" + confluent schema-registry schema list --subject-prefix "${topic_name}" + + echo "----------------------------------------------" + echo "Topic and schemas setup complete for: $topic_name" + echo "----------------------------------------------" + echo "" + echo "" +} + +# Set Kafka Topic Schema Registry Subject +set_schema_registry_subject_compatibility() { + local topic_name="$1" # The name of the topic to set compatibility for + local compatibility_level="$2" # The desired compatibility level. Can be "backward", "backward_transitive", "forward", "forward_transitive", "full", "full_transitive", or "none". + + local key_schema_subject="${topic_name}-key" + local value_schema_subject="${topic_name}-value" + + + echo "Setting schema registry topic key/value compatibility for $topic_name to $compatibility_level" + confluent schema-registry subject update ${key_schema_subject} --compatibility ${compatibility_level} + confluent schema-registry subject update ${value_schema_subject} --compatibility ${compatibility_level} + + echo "----------------------------------------------" + echo "Schema registry subject compatibility set for: $topic_name" + echo "----------------------------------------------" + +} + +# Reference topics from Azure Cosmos DB +create_topic_with_schema "departments" +create_topic_with_schema "product_pricing" +create_topic_with_schema "product_skus" + +# Transaction topics from Cosmos DB +create_topic_with_schema "purchases" +create_topic_with_schema "replenishments" +create_topic_with_schema "returns" + +# Transaction topics from Cosmos DB flattened +create_topic_with_schema "purchases_flat" +create_topic_with_schema "replenishments_flat" +create_topic_with_schema "returns_flat" + +# Destination topics heading over to Azure AI Search +create_topic_with_schema "net_sales" +create_topic_with_schema "product_inventory" +create_topic_with_schema "departments_flat" + +confluent schema-registry schema list + +# Set schema registry subject compatibility for cosomos db topics +set_schema_registry_subject_compatibility "purchases" "none" +set_schema_registry_subject_compatibility "replenishments" "none" +set_schema_registry_subject_compatibility "returns" "none" \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh new file mode 100644 index 0000000000..1ae27401e9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# This script deletes specified connectors from a Confluent Kafka Connect cluster. +# It assumes that the Confluent CLI is installed, configured, and the user is authenticated. +# It also assumes that the user has the necessary permissions to delete connectors. +# Function to get connector IDs from their names + +# Example usage: +# get_connector_ids "azure_cosmos_db_product_pricing_source,azure_cosmos_db_purchases_source,azure_cosmos_db_returns_source" +get_connector_ids() { + local connector_names_csv="$1" + local connector_names_array + + IFS=',' read -r -a connector_names_array <<< "$connector_names_csv" + + # Get current connectors JSON + local connectors_json + connectors_json=$(confluent connect cluster list -o json) + + # Initialize result + local connector_ids=() + + for name in "${connector_names_array[@]}"; do + id=$(echo "$connectors_json" | jq -r --arg NAME "$name" '.[] | select(.name == $NAME) | .id') + if [[ -n "$id" ]]; then + connector_ids+=("$id") + fi + done + + # Output space-delimited list + echo "${connector_ids[@]}" +} + +# List all connectors in the cluster +echo "Listing all connectors in the cluster before deletion:" +# This will show all connectors before deletion + +confluent connect cluster list + +echo "----------------------------------------------" +echo "Deleting specified connectors from the cluster:" + + +# These are the connector names to delete +connectors="ai_search_departments_sink,ai_search_net_sales_sink,ai_search_departments_flat_sink,ai_search_product_inventory_sink,azure_cosmos_db_product_pricing_source,azure_cosmos_db_purchases_source,azure_cosmos_db_product_skus_source,azure_cosmos_db_returns_source,azure_cosmos_db_replenishments_source,azure_cosmos_db_departments_source" + +# Call the function +ids=$(get_connector_ids "$connectors") + +echo "Connector IDs: $ids" + +# Delete the connectors using their IDs +for id in $ids; do + echo "Deleting connector with ID: $id" + confluent connect cluster delete "$id" --force + # Check if the deletion was successful + # The exit status of the last command is stored in $? + # If the exit status is 0, the command was successful + # If the exit status is not 0, the command failed + if [ $? -eq 0 ]; then + echo "Connector with ID $id deleted successfully." + else + echo "Failed to delete connector with ID $id." + fi +done +echo "All specified connectors have been deleted." + +# List all connectors in the cluster +confluent connect cluster list +echo "All connectors in the cluster have been listed." +echo "----------------------------------------------" +echo "Confluent Connectors deletion complete." + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh new file mode 100644 index 0000000000..1f4142955e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +delete_topic_schemas() { + local topic_name="$1" # The name of the topic to delete + local topic_key_schema="${topic_name}-key" # The key schema subject + local topic_value_schema="${topic_name}-value" # The value schema subject + + # Check if the topic name is provided + if [ -z "$topic_name" ]; then + echo "Error: No topic name provided." + echo "Usage: delete_topic_schemas " + exit 1 + fi + + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force + + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force --permanent + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force --permanent + +} + + +# List Schema Registry +confluent schema-registry schema list + + +# Reference topics from Azure Cosmos DB +delete_topic_schemas "departments" +delete_topic_schemas "product_pricing" +delete_topic_schemas "product_skus" + +# Transaction topics from Cosmos DB +delete_topic_schemas "purchases" +delete_topic_schemas "replenishments" +delete_topic_schemas "returns" + +# Destination topics heading over to Azure AI Search +delete_topic_schemas "net_sales" +delete_topic_schemas "product_inventory" + +confluent schema-registry schema list \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh new file mode 100644 index 0000000000..0a38f148ac --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh @@ -0,0 +1,49 @@ + + +# This script deletes all topics in the Confluent Cloud environment. +# It assumes that the Confluent CLI is installed, configured, and the user is authenticated. +# It also assumes that the user has the necessary permissions to delete topics. + +# Function to delete a Kafka topic and its associated schemas +# Example usage +# delete_kafka_topic "sales_transactions" +delete_kafka_topic_and_schemas() { + # Check if the topic name is provided + if [ -z "$1" ]; then + echo "Error: No topic name provided." + echo "Usage: delete_kafka_topic_and_schemas " + exit 1 + fi + + local topic_name="$1" # The name of the topic to delete + local topic_key_schema="${topic_name}-key" # The key schema subject + local topic_value_schema="${topic_name}-value" # The value schema subject + + # Delete the schemas associated with the topic + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force + + # Permanently delete the schemas + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force --permanent + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force --permanent + + # Delete the Kafka topic + confluent kafka topic delete "$topic_name" --force + echo "Topic $topic_name and its schemas have been deleted." +} + +# Reference topics from Azure Cosmos DB +delete_kafka_topic_and_schemas "departments" +delete_kafka_topic_and_schemas "product_pricing" +delete_kafka_topic_and_schemas "product_skus" + +# Transaction topics from Cosmos DB +delete_kafka_topic_and_schemas "purchases" +delete_kafka_topic_and_schemas "replenishments" +delete_kafka_topic_and_schemas "returns" + +# Destination topics heading over to Azure AI Search +delete_kafka_topic_and_schemas "net_sales" +delete_kafka_topic_and_schemas "product_inventory" + + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh new file mode 100644 index 0000000000..805dfb2e14 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +connector_config_populate_secrets() +{ + + + # Path to the input and output files + FILE_PREFIX="$1" + DIRECTORY_PREFIX="./connector-configurations" + INPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.example.json" + OUTPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.final.json" + + echo "" + echo "" + echo "Preparing Connector Configuration File ${FILE_PREFIX} ..." + # Replace placeholders and output to a new file + sed \ + -e "s|\[AZURE_RESOURCE_GROUP\]|${AZURE_RESOURCE_GROUP}|g" \ + -e "s|\[KAFKA_API_KEY\]|${KAFKA_API_KEY}|g" \ + -e "s|\[KAFKA_API_SECRET\]|${KAFKA_API_SECRET}|g" \ + -e "s|\[AZURE_SEARCH_SERVICE_NAME\]|${AZURE_SEARCH_SERVICE_NAME}|g" \ + -e "s|\[AZURE_SEARCH_API_KEY\]|${AZURE_SEARCH_API_KEY}|g" \ + -e "s|\[AZURE_STORAGE_ACCOUNT_NAME\]|${AZURE_STORAGE_ACCOUNT_NAME}|g" \ + -e "s|\[AZURE_STORAGE_ACCOUNT_KEY\]|${AZURE_STORAGE_ACCOUNT_KEY}|g" \ + -e "s|\[AZURE_COSMOS_DB_ACCOUNT_NAME\]|${AZURE_COSMOS_DB_ACCOUNT_NAME}|g" \ + -e "s|\[AZURE_COSMOS_DB_ACCOUNT_KEY\]|${AZURE_COSMOS_DB_ACCOUNT_KEY}|g" \ + -e "s|\[AZURE_COSMOS_DB_DATABASE_NAME\]|${AZURE_COSMOS_DB_DATABASE_NAME}|g" \ + -e "s|\[ARM_CLIENT_ID\]|${ARM_CLIENT_ID}|g" \ + -e "s|\[ARM_CLIENT_SECRET\]|${ARM_CLIENT_SECRET}|g" \ + -e "s|\[ARM_TENANT_ID\]|${ARM_TENANT_ID}|g" \ + -e "s|\[ARM_SUBSCRIPTION_ID\]|${ARM_SUBSCRIPTION_ID}|g" \ + "$INPUT_FILE" > "$OUTPUT_FILE" + + echo "Replacement complete. Modified file saved as $OUTPUT_FILE." +} + +connector_config_populate_secrets "ai_search_product_inventory" +connector_config_populate_secrets "ai_search_net_sales" +connector_config_populate_secrets "ai_search_departments_flat" + +connector_config_populate_secrets "cosmos_db_departments" +connector_config_populate_secrets "cosmos_db_product_skus" +connector_config_populate_secrets "cosmos_db_product_pricing" + +connector_config_populate_secrets "cosmos_db_purchases" +connector_config_populate_secrets "cosmos_db_returns" +connector_config_populate_secrets "cosmos_db_replenishments" \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh new file mode 100644 index 0000000000..6d423280b8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +connector_config_reset() +{ + + + # Path to the input and output files + FILE_PREFIX="$1" + DIRECTORY_PREFIX="./connector-configurations" + INPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.example.json" + OUTPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.final.json" + + echo "" + echo "Removing existing output file ${OUTPUT_FILE} if it exists..." + echo "Leaving Input file ${INPUT_FILE} intact..." + rm -v -f "$OUTPUT_FILE" + echo "" + +} + +connector_config_reset "ai_search_product_inventory" +connector_config_reset "ai_search_net_sales" +connector_config_reset "ai_search_departments_flat" + +connector_config_reset "cosmos_db_departments" +connector_config_reset "cosmos_db_product_skus" +connector_config_reset "cosmos_db_product_pricing" + +connector_config_reset "cosmos_db_purchases" +connector_config_reset "cosmos_db_returns" +connector_config_reset "cosmos_db_replenishments" \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json new file mode 100644 index 0000000000..97ef41ad8b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json @@ -0,0 +1,36 @@ +{ + "config": { + "topics": "departments", + "schema.context.name": "default", + "input.data.format": "JSON_SR", + "connector.class": "AzureCognitiveSearchSink", + "name": "ai_search_departments_sink", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azure.search.service.name": "[AZURE_SEARCH_SERVICE_NAME]", + "azure.search.api.key": "[AZURE_SEARCH_API_KEY]", + "azure.search.client.id": "[ARM_CLIENT_ID]", + "azure.search.client.secret": "[ARM_CLIENT_SECRET]", + "azure.search.tenant.id": "[ARM_TENANT_ID]", + "azure.search.subscription.id": "[ARM_SUBSCRIPTION_ID]", + "azure.search.resourcegroup.name": "[AZURE_RESOURCE_GROUP]", + "index.name": "departments", + "write.method": "Upload", + "delete.enabled": "true", + "key.mode": "KEY", + "max.batch.size": "25", + "max.retry.ms": "300000", + "max.poll.interval.ms": "300000", + "max.poll.records": "500", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "transforms": "department_to_key", + "transforms.department_to_key.type": "org.apache.kafka.connect.transforms.ValueToKey", + "transforms.department_to_key.fields": "department" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json new file mode 100644 index 0000000000..8650fd2e80 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json @@ -0,0 +1,36 @@ +{ + "config": { + "topics": "net_sales", + "schema.context.name": "default", + "input.data.format": "JSON_SR", + "connector.class": "AzureCognitiveSearchSink", + "name": "ai_search_net_sales_sink", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azure.search.service.name": "[AZURE_SEARCH_SERVICE_NAME]", + "azure.search.api.key": "[AZURE_SEARCH_API_KEY]", + "azure.search.client.id": "[ARM_CLIENT_ID]", + "azure.search.client.secret": "[ARM_CLIENT_SECRET]", + "azure.search.tenant.id": "[ARM_TENANT_ID]", + "azure.search.subscription.id": "[ARM_SUBSCRIPTION_ID]", + "azure.search.resourcegroup.name": "[AZURE_RESOURCE_GROUP]", + "index.name": "net_sales", + "write.method": "Upload", + "delete.enabled": "true", + "key.mode": "KEY", + "max.batch.size": "25", + "max.retry.ms": "300000", + "max.poll.interval.ms": "300000", + "max.poll.records": "500", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "transforms": "sku_id_to_key", + "transforms.sku_id_to_key.type": "org.apache.kafka.connect.transforms.ValueToKey", + "transforms.sku_id_to_key.fields": "sku_id" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json new file mode 100644 index 0000000000..8f5ba96465 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json @@ -0,0 +1,36 @@ +{ + "config": { + "topics": "product_inventory", + "schema.context.name": "default", + "input.data.format": "JSON_SR", + "connector.class": "AzureCognitiveSearchSink", + "name": "ai_search_product_inventory_sink", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azure.search.service.name": "[AZURE_SEARCH_SERVICE_NAME]", + "azure.search.api.key": "[AZURE_SEARCH_API_KEY]", + "azure.search.client.id": "[ARM_CLIENT_ID]", + "azure.search.client.secret": "[ARM_CLIENT_SECRET]", + "azure.search.tenant.id": "[ARM_TENANT_ID]", + "azure.search.subscription.id": "[ARM_SUBSCRIPTION_ID]", + "azure.search.resourcegroup.name": "[AZURE_RESOURCE_GROUP]", + "index.name": "product_inventory", + "write.method": "Upload", + "delete.enabled": "true", + "key.mode": "KEY", + "max.batch.size": "25", + "max.retry.ms": "300000", + "max.poll.interval.ms": "300000", + "max.poll.records": "500", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "transforms": "sku_id_to_key", + "transforms.sku_id_to_key.type": "org.apache.kafka.connect.transforms.ValueToKey", + "transforms.sku_id_to_key.fields": "sku_id" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json new file mode 100644 index 0000000000..c7fae74390 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_departments_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "departments#departments", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json new file mode 100644 index 0000000000..82d153537d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_product_pricing_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "product_pricing#product_pricing", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json new file mode 100644 index 0000000000..f11e8d20d8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_product_skus_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "product_skus#product_skus", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json new file mode 100644 index 0000000000..9639e64ba2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_purchases_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "purchases#purchases", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json new file mode 100644 index 0000000000..a8dca07930 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_replenishments_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "replenishments#replenishments", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json new file mode 100644 index 0000000000..8552cc6999 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_returns_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "returns#returns", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md new file mode 100644 index 0000000000..b072f5f510 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md @@ -0,0 +1,11 @@ +This folder contains seed data for the application + +We have data for the following collections: +- departments - this contains information about the departments available +- product_skus - all the unique SKUs available in the store +- product_pricing - the unit price for each sku +- purchases - transactions where customers purchased one or more items +- returns - transactions where customers returned one or more items +- replenishments - transactions where suppliers replenish one or more items +- product_inventory - the global inventory count for each SKU +- net_sales - the global view sales for a particular SKU considering returns as well diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md new file mode 100644 index 0000000000..e51a16bc0e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md @@ -0,0 +1,23 @@ +### Uploading Cosmos DB Contents + +We can use the following steps to upload the Cosmos DB container contents. First you will need to login to the Azure CLI. + +````bash + +az login + +```` + +#### Batch Document Uploads + +We can upload the departments, product_pricing and product_skus datasets to Cosmos DB using the Azure CLI commands. The script `azure_cosmos_upload.sh` automates this process. + +Make sure you have set the required environment variables: +- `AZURE_COSMOS_DB_ACCOUNT_NAME`: The name of your Cosmos DB account +- `AZURE_COSMOS_DB_DATABASE_NAME`: The name of your Cosmos DB database (typically "retailstore") + +Then run: + +````bash +./azure_cosmos_upload.sh +```` \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh new file mode 100644 index 0000000000..0c8817c2cf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Function to upload files to Cosmos DB +upload_to_cosmos_db() { + + COSMOS_DB_ACCOUNT_NAME="${AZURE_COSMOS_DB_ACCOUNT_NAME}" + COSMOS_DB_DATABASE_NAME="${AZURE_COSMOS_DB_DATABASE_NAME}" + + TARGET_FOLDER=$1 + CONTAINER_NAME="${TARGET_FOLDER//_/-}" + + echo "Uploading Files from ${TARGET_FOLDER} to Cosmos DB container ${CONTAINER_NAME} ..." + + echo "Changing directory to ${TARGET_FOLDER}" + cd ${TARGET_FOLDER} + + echo "Uploading JSON files to Cosmos DB Account ${COSMOS_DB_ACCOUNT_NAME}/${COSMOS_DB_DATABASE_NAME}/${CONTAINER_NAME} ..." + + # Loop through all JSON files in the current directory + for file in *.json; do + if [ -f "$file" ]; then + echo "Uploading $file to Cosmos DB container ${CONTAINER_NAME}..." + + # Use az cosmosdb sql container item create to upload the document + az cosmosdb sql container item create \ + --account-name "${COSMOS_DB_ACCOUNT_NAME}" \ + --database-name "${COSMOS_DB_DATABASE_NAME}" \ + --container-name "${CONTAINER_NAME}" \ + --item "@${file}" \ + --output none + + if [ $? -eq 0 ]; then + echo "✅ Successfully uploaded $file" + else + echo "❌ Failed to upload $file" + fi + fi + done + + echo "Upload completed for ${CONTAINER_NAME}." + + cd .. + +} + +upload_to_cosmos_db "departments" +upload_to_cosmos_db "product_pricing" +upload_to_cosmos_db "product_skus" + +echo "All uploads completed." diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json new file mode 100644 index 0000000000..aa3dc59655 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json @@ -0,0 +1,5 @@ +{ + "id": "appliance", + "department": "appliance", + "description": "The appliance department is where we have simple use electronics for the home but mostly for the kitchen area. This is the only department were returned items can count towards the available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json new file mode 100644 index 0000000000..beb188379f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json @@ -0,0 +1,5 @@ +{ + "id": "cleaning", + "department": "cleaning", + "description": "This is where we find cleaning supplies. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json new file mode 100644 index 0000000000..02c9ccbfe1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json @@ -0,0 +1,5 @@ +{ + "id": "dairy", + "department": "dairy", + "description": "The dairy department where we find products like cheese, milk, butter and other dairy items. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json new file mode 100644 index 0000000000..f8f8aab979 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json @@ -0,0 +1,5 @@ +{ + "id": "deli", + "department": "deli", + "description": "This is where we find cooked food and other ready-to-eat meals. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json new file mode 100644 index 0000000000..fc5ad4a9be --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json @@ -0,0 +1,5 @@ +{ + "id": "meat", + "department": "meat", + "description": "This is where we find meats such as chicken, pork, beef, lamb etc. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json new file mode 100644 index 0000000000..c4bae15a9b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json @@ -0,0 +1,5 @@ +{ + "id": "pharmacy", + "department": "pharmacy", + "description": "This is where we find pharmaceutical items like medications and first aid kits. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json new file mode 100644 index 0000000000..b8abac516f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json @@ -0,0 +1,5 @@ +{ + "id": "produce", + "department": "produce", + "description": "The produce departments is where we find fresh fruits and vegatables. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema new file mode 100644 index 0000000000..357445f306 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Departments Key", + "description": "A unique identifier for the department", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema new file mode 100644 index 0000000000..2257ad8b2a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema @@ -0,0 +1,16 @@ +{ + "type": "object", + "title": "Departments Value", + "description": "Contains the department and description of the product SKU.", + "properties": { + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + }, + "description": { + "type": "string" + } + }, + "required": ["department", "description"], + "additionalProperties": false + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json new file mode 100644 index 0000000000..fa10c34eea --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json @@ -0,0 +1,5 @@ +{ + "id": "seafood", + "department": "seafood", + "description": "This is the department where we find seafood products. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json new file mode 100644 index 0000000000..3faee78a40 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json @@ -0,0 +1,4 @@ +{ + "department": "appliance", + "description": "The appliance department is where we have simple use electronics for the home but mostly for the kitchen area. This is the only department were returned items can count towards the available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json new file mode 100644 index 0000000000..6afb38f0bd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json @@ -0,0 +1,4 @@ +{ + "department": "cleaning", + "description": "This is where we find cleaning supplies. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json new file mode 100644 index 0000000000..e76e02da7c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json @@ -0,0 +1,4 @@ +{ + "department": "dairy", + "description": "The dairy department where we find products like cheese, milk, butter and other dairy items. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json new file mode 100644 index 0000000000..916f559dde --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json @@ -0,0 +1,4 @@ +{ + "department": "deli", + "description": "This is where we find cooked food and other ready-to-eat meals. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json new file mode 100644 index 0000000000..8ae9dc22dc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json @@ -0,0 +1,4 @@ +{ + "department": "meat", + "description": "This is where we find meats such as chicken, pork, beef, lamb etc. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json new file mode 100644 index 0000000000..9cd81c200c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json @@ -0,0 +1,4 @@ +{ + "department": "pharmacy", + "description": "This is where we find pharmaceutical items like medications and first aid kits. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json new file mode 100644 index 0000000000..af785f89ca --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json @@ -0,0 +1,4 @@ +{ + "department": "produce", + "description": "The produce departments is where we find fresh fruits and vegatables. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema new file mode 100644 index 0000000000..357445f306 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Departments Key", + "description": "A unique identifier for the department", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema new file mode 100644 index 0000000000..2257ad8b2a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema @@ -0,0 +1,16 @@ +{ + "type": "object", + "title": "Departments Value", + "description": "Contains the department and description of the product SKU.", + "properties": { + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + }, + "description": { + "type": "string" + } + }, + "required": ["department", "description"], + "additionalProperties": false + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json new file mode 100644 index 0000000000..2a3f9097c2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json @@ -0,0 +1,4 @@ +{ + "department": "seafood", + "description": "This is the department where we find seafood products. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json new file mode 100644 index 0000000000..4cbb93f670 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json @@ -0,0 +1,6 @@ +{ + "sku_id": "101", + "name": "Toaster", + "department": "appliance", + "net_sales": 450.97 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema new file mode 100644 index 0000000000..490cbf1bb7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Net Sales SKU identifier for the product", + "description": "A unique identifier for the product SKU pricing", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema new file mode 100644 index 0000000000..f3dfa1b45c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema @@ -0,0 +1,25 @@ +{ + "title": "Net Sales for the Product SKU", + "description": "Schema for a sales record containing SKU ID, product name, department, and cummulative net sales amount.", + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "description": "Unique identifier for the stock keeping unit (SKU)." + }, + "name": { + "type": "string", + "description": "Name of the Product" + }, + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + }, + "net_sales": { + "type": "number", + "description": "Net sales amount for the transaction." + } + }, + "required": ["sku_id", "name", "department", "net_sales"] + } + \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json new file mode 100644 index 0000000000..ccfa53e7d3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json @@ -0,0 +1,8 @@ +{ + "sku_id": "101", + "inventory_level": 300.00, + "unit_price": 9.99, + "name": "Toaster", + "description": "Electric Toaster", + "department":"appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json new file mode 100644 index 0000000000..5474eb9dc8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json @@ -0,0 +1,8 @@ +{ + "sku_id": "102", + "inventory_level": 55.00, + "unit_price": 29.95, + "name": "Microwave Oven", + "description": "A solar-powered Microwave oven", + "department":"appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema new file mode 100644 index 0000000000..8e10f3ed2e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Product inventory Title SKU identifier Key", + "description": "A unique identifier for the product inventory SKU", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema new file mode 100644 index 0000000000..fc4c00e6ce --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema @@ -0,0 +1,37 @@ +{ + "description": "This schema defines the structure of the product inventory data.", + "title": "Product inventory Title SKU identifier Value", + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "minLength": 1 + }, + "inventory_level": { + "type": "number" + }, + "unit_price": { + "type": "number" + }, + "name": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 1 + }, + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + } + }, + "required": [ + "sku_id", + "inventory_level", + "unit_price", + "name", + "description", + "department" + ] + } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json new file mode 100644 index 0000000000..33c615ba4e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json @@ -0,0 +1,5 @@ +{ + "id": "101", + "sku_id": "101", + "unit_price": 49.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json new file mode 100644 index 0000000000..30779ecdcf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json @@ -0,0 +1,5 @@ +{ + "id": "102", + "sku_id": "102", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json new file mode 100644 index 0000000000..be1917d070 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json @@ -0,0 +1,5 @@ +{ + "id": "103", + "sku_id": "103", + "unit_price": 199.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json new file mode 100644 index 0000000000..18acecd534 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json @@ -0,0 +1,5 @@ +{ + "id": "104", + "sku_id": "104", + "unit_price": 89.95 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json new file mode 100644 index 0000000000..b2c67c434a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json @@ -0,0 +1,5 @@ +{ + "id": "105", + "sku_id": "105", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json new file mode 100644 index 0000000000..c87d60112f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json @@ -0,0 +1,5 @@ +{ + "id": "106", + "sku_id": "106", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json new file mode 100644 index 0000000000..00d2507b2c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json @@ -0,0 +1,5 @@ +{ + "id": "107", + "sku_id": "107", + "unit_price": 149.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json new file mode 100644 index 0000000000..fcf9b8332f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json @@ -0,0 +1,5 @@ +{ + "id": "108", + "sku_id": "108", + "unit_price": 59.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json new file mode 100644 index 0000000000..d44599296e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json @@ -0,0 +1,5 @@ +{ + "id": "109", + "sku_id": "109", + "unit_price": 99.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json new file mode 100644 index 0000000000..5c32e3c561 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json @@ -0,0 +1,5 @@ +{ + "id": "110", + "sku_id": "110", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json new file mode 100644 index 0000000000..1576bb08f6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json @@ -0,0 +1,5 @@ +{ + "id": "111", + "sku_id": "111", + "unit_price": 299.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json new file mode 100644 index 0000000000..ba2aedc68d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json @@ -0,0 +1,5 @@ +{ + "id": "112", + "sku_id": "112", + "unit_price": 45.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json new file mode 100644 index 0000000000..e6e76a4049 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json @@ -0,0 +1,5 @@ +{ + "id": "113", + "sku_id": "113", + "unit_price": 79.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json new file mode 100644 index 0000000000..4ef56bc85f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json @@ -0,0 +1,5 @@ +{ + "id": "114", + "sku_id": "114", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json new file mode 100644 index 0000000000..6e3de597ca --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json @@ -0,0 +1,5 @@ +{ + "id": "115", + "sku_id": "115", + "unit_price": 29.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json new file mode 100644 index 0000000000..bee9c3a07c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json @@ -0,0 +1,5 @@ +{ + "id": "116", + "sku_id": "116", + "unit_price": 129.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json new file mode 100644 index 0000000000..a0a00b5ae0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json @@ -0,0 +1,5 @@ +{ + "id": "117", + "sku_id": "117", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json new file mode 100644 index 0000000000..0ca7c8ec42 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json @@ -0,0 +1,5 @@ +{ + "id": "118", + "sku_id": "118", + "unit_price": 69.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json new file mode 100644 index 0000000000..33b5eb6017 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json @@ -0,0 +1,5 @@ +{ + "id": "119", + "sku_id": "119", + "unit_price": 99.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json new file mode 100644 index 0000000000..1bb5dd2386 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json @@ -0,0 +1,5 @@ +{ + "id": "120", + "sku_id": "120", + "unit_price": 399.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json new file mode 100644 index 0000000000..ca478fcaff --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json @@ -0,0 +1,5 @@ +{ + "id": "121", + "sku_id": "121", + "unit_price": 69.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json new file mode 100644 index 0000000000..08d24eeb1f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json @@ -0,0 +1,5 @@ +{ + "id": "122", + "sku_id": "122", + "unit_price": 129.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json new file mode 100644 index 0000000000..43cde5bd8a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json @@ -0,0 +1,5 @@ +{ + "id": "123", + "sku_id": "123", + "unit_price": 69.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json new file mode 100644 index 0000000000..24b7c2bddd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json @@ -0,0 +1,5 @@ +{ + "id": "124", + "sku_id": "124", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json new file mode 100644 index 0000000000..45735595d8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json @@ -0,0 +1,5 @@ +{ + "id": "125", + "sku_id": "125", + "unit_price": 25.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json new file mode 100644 index 0000000000..d2953ed114 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json @@ -0,0 +1,5 @@ +{ + "id": "201", + "sku_id": "201", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json new file mode 100644 index 0000000000..71b3fd279a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json @@ -0,0 +1,5 @@ +{ + "id": "202", + "sku_id": "202", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json new file mode 100644 index 0000000000..ba376831fb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json @@ -0,0 +1,5 @@ +{ + "id": "203", + "sku_id": "203", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json new file mode 100644 index 0000000000..43e0d37243 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json @@ -0,0 +1,5 @@ +{ + "id": "204", + "sku_id": "204", + "unit_price": 3.59 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json new file mode 100644 index 0000000000..b2f7d92a54 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json @@ -0,0 +1,5 @@ +{ + "id": "205", + "sku_id": "205", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json new file mode 100644 index 0000000000..af842a3a66 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json @@ -0,0 +1,5 @@ +{ + "id": "206", + "sku_id": "206", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json new file mode 100644 index 0000000000..d3f749b810 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json @@ -0,0 +1,5 @@ +{ + "id": "207", + "sku_id": "207", + "unit_price": 6.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json new file mode 100644 index 0000000000..f6fbe1b0e7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json @@ -0,0 +1,5 @@ +{ + "id": "208", + "sku_id": "208", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json new file mode 100644 index 0000000000..f4f0f95e2a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json @@ -0,0 +1,5 @@ +{ + "id": "209", + "sku_id": "209", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json new file mode 100644 index 0000000000..f11c1f1a7d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json @@ -0,0 +1,5 @@ +{ + "id": "210", + "sku_id": "210", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json new file mode 100644 index 0000000000..a82211674c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json @@ -0,0 +1,5 @@ +{ + "id": "211", + "sku_id": "211", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json new file mode 100644 index 0000000000..a9fd2a86cd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json @@ -0,0 +1,5 @@ +{ + "id": "212", + "sku_id": "212", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json new file mode 100644 index 0000000000..80e34507eb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json @@ -0,0 +1,5 @@ +{ + "id": "213", + "sku_id": "213", + "unit_price": 3.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json new file mode 100644 index 0000000000..b0ed15adf9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json @@ -0,0 +1,5 @@ +{ + "id": "214", + "sku_id": "214", + "unit_price": 4.19 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json new file mode 100644 index 0000000000..7e6e5c8806 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json @@ -0,0 +1,5 @@ +{ + "id": "215", + "sku_id": "215", + "unit_price": 2.79 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json new file mode 100644 index 0000000000..7b8c24c59e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json @@ -0,0 +1,5 @@ +{ + "id": "216", + "sku_id": "216", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json new file mode 100644 index 0000000000..3336675d60 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json @@ -0,0 +1,5 @@ +{ + "id": "217", + "sku_id": "217", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json new file mode 100644 index 0000000000..1ada5b3479 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json @@ -0,0 +1,5 @@ +{ + "id": "218", + "sku_id": "218", + "unit_price": 7.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json new file mode 100644 index 0000000000..b87d9a162f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json @@ -0,0 +1,5 @@ +{ + "id": "219", + "sku_id": "219", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json new file mode 100644 index 0000000000..7d9275eac3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json @@ -0,0 +1,5 @@ +{ + "id": "220", + "sku_id": "220", + "unit_price": 12.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json new file mode 100644 index 0000000000..b80db7a92a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json @@ -0,0 +1,5 @@ +{ + "id": "221", + "sku_id": "221", + "unit_price": 1.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json new file mode 100644 index 0000000000..0688042174 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json @@ -0,0 +1,5 @@ +{ + "id": "222", + "sku_id": "222", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json new file mode 100644 index 0000000000..0ae1cad58e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json @@ -0,0 +1,5 @@ +{ + "id": "223", + "sku_id": "223", + "unit_price": 7.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json new file mode 100644 index 0000000000..3b5381dc1d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json @@ -0,0 +1,5 @@ +{ + "id": "224", + "sku_id": "224", + "unit_price": 4.79 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json new file mode 100644 index 0000000000..f1c5221f68 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json @@ -0,0 +1,5 @@ +{ + "id": "225", + "sku_id": "225", + "unit_price": 8.39 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json new file mode 100644 index 0000000000..43bc08d8d0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json @@ -0,0 +1,5 @@ +{ + "id": "301", + "sku_id": "301", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json new file mode 100644 index 0000000000..814663df24 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json @@ -0,0 +1,5 @@ +{ + "id": "302", + "sku_id": "302", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json new file mode 100644 index 0000000000..41fc0dd2cf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json @@ -0,0 +1,5 @@ +{ + "id": "303", + "sku_id": "303", + "unit_price": 2.89 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json new file mode 100644 index 0000000000..3a4d47e169 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json @@ -0,0 +1,5 @@ +{ + "id": "304", + "sku_id": "304", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json new file mode 100644 index 0000000000..0da44bbaf9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json @@ -0,0 +1,5 @@ +{ + "id": "305", + "sku_id": "305", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json new file mode 100644 index 0000000000..f997e5764b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json @@ -0,0 +1,5 @@ +{ + "id": "306", + "sku_id": "306", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json new file mode 100644 index 0000000000..ecf16d46db --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json @@ -0,0 +1,5 @@ +{ + "id": "307", + "sku_id": "307", + "unit_price": 4.19 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json new file mode 100644 index 0000000000..d47a62ca87 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json @@ -0,0 +1,5 @@ +{ + "id": "308", + "sku_id": "308", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json new file mode 100644 index 0000000000..0860aa1e7f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json @@ -0,0 +1,5 @@ +{ + "id": "309", + "sku_id": "309", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json new file mode 100644 index 0000000000..51600df563 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json @@ -0,0 +1,5 @@ +{ + "id": "310", + "sku_id": "310", + "unit_price": 3.79 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json new file mode 100644 index 0000000000..d6015e1486 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json @@ -0,0 +1,5 @@ +{ + "id": "311", + "sku_id": "311", + "unit_price": 2.59 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json new file mode 100644 index 0000000000..58450e4ab8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json @@ -0,0 +1,5 @@ +{ + "id": "312", + "sku_id": "312", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json new file mode 100644 index 0000000000..002104c402 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json @@ -0,0 +1,5 @@ +{ + "id": "313", + "sku_id": "313", + "unit_price": 3.89 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json new file mode 100644 index 0000000000..cac5276317 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json @@ -0,0 +1,5 @@ +{ + "id": "314", + "sku_id": "314", + "unit_price": 5.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json new file mode 100644 index 0000000000..17e6a83a94 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json @@ -0,0 +1,5 @@ +{ + "id": "315", + "sku_id": "315", + "unit_price": 4.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json new file mode 100644 index 0000000000..8e82a96d18 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json @@ -0,0 +1,5 @@ +{ + "id": "316", + "sku_id": "316", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json new file mode 100644 index 0000000000..00225e7213 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json @@ -0,0 +1,5 @@ +{ + "id": "317", + "sku_id": "317", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json new file mode 100644 index 0000000000..3efe300b93 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json @@ -0,0 +1,5 @@ +{ + "id": "318", + "sku_id": "318", + "unit_price": 1.89 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json new file mode 100644 index 0000000000..6cdf8e227c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json @@ -0,0 +1,5 @@ +{ + "id": "319", + "sku_id": "319", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json new file mode 100644 index 0000000000..2758b1a9c6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json @@ -0,0 +1,5 @@ +{ + "id": "320", + "sku_id": "320", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json new file mode 100644 index 0000000000..bcafd68146 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json @@ -0,0 +1,5 @@ +{ + "id": "321", + "sku_id": "321", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json new file mode 100644 index 0000000000..03a608e853 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json @@ -0,0 +1,5 @@ +{ + "id": "322", + "sku_id": "322", + "unit_price": 3.59 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json new file mode 100644 index 0000000000..d232ea9b4c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json @@ -0,0 +1,5 @@ +{ + "id": "323", + "sku_id": "323", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json new file mode 100644 index 0000000000..6cfeb09e6a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json @@ -0,0 +1,5 @@ +{ + "id": "324", + "sku_id": "324", + "unit_price": 3.79 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json new file mode 100644 index 0000000000..ecf8ebbb97 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json @@ -0,0 +1,5 @@ +{ + "id": "325", + "sku_id": "325", + "unit_price": 3.19 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json new file mode 100644 index 0000000000..5d61d7ff8c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json @@ -0,0 +1,5 @@ +{ + "id": "401", + "sku_id": "401", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json new file mode 100644 index 0000000000..0bcb6afcd0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json @@ -0,0 +1,5 @@ +{ + "id": "402", + "sku_id": "402", + "unit_price": 9.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json new file mode 100644 index 0000000000..b2e81611ab --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json @@ -0,0 +1,5 @@ +{ + "id": "403", + "sku_id": "403", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json new file mode 100644 index 0000000000..5153483da1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json @@ -0,0 +1,5 @@ +{ + "id": "404", + "sku_id": "404", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json new file mode 100644 index 0000000000..516829764c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json @@ -0,0 +1,5 @@ +{ + "id": "405", + "sku_id": "405", + "unit_price": 10.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json new file mode 100644 index 0000000000..5cef1170f2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json @@ -0,0 +1,5 @@ +{ + "id": "406", + "sku_id": "406", + "unit_price": 7.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json new file mode 100644 index 0000000000..65a8b836c2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json @@ -0,0 +1,5 @@ +{ + "id": "407", + "sku_id": "407", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json new file mode 100644 index 0000000000..27efa3c2c3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json @@ -0,0 +1,5 @@ +{ + "id": "408", + "sku_id": "408", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json new file mode 100644 index 0000000000..78fc969dc7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json @@ -0,0 +1,5 @@ +{ + "id": "409", + "sku_id": "409", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json new file mode 100644 index 0000000000..accce4f24d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json @@ -0,0 +1,5 @@ +{ + "id": "410", + "sku_id": "410", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json new file mode 100644 index 0000000000..57d19e5159 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json @@ -0,0 +1,5 @@ +{ + "id": "411", + "sku_id": "411", + "unit_price": 6.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json new file mode 100644 index 0000000000..6f9dd102e7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json @@ -0,0 +1,5 @@ +{ + "id": "412", + "sku_id": "412", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json new file mode 100644 index 0000000000..626c62111a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json @@ -0,0 +1,5 @@ +{ + "id": "413", + "sku_id": "413", + "unit_price": 7.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json new file mode 100644 index 0000000000..b612f2c5a7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json @@ -0,0 +1,5 @@ +{ + "id": "414", + "sku_id": "414", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json new file mode 100644 index 0000000000..843854b138 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json @@ -0,0 +1,5 @@ +{ + "id": "415", + "sku_id": "415", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json new file mode 100644 index 0000000000..408c3d7a7c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json @@ -0,0 +1,5 @@ +{ + "id": "416", + "sku_id": "416", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json new file mode 100644 index 0000000000..59077d5ebe --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json @@ -0,0 +1,5 @@ +{ + "id": "417", + "sku_id": "417", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json new file mode 100644 index 0000000000..77c59f0475 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json @@ -0,0 +1,5 @@ +{ + "id": "418", + "sku_id": "418", + "unit_price": 7.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json new file mode 100644 index 0000000000..425f2c318a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json @@ -0,0 +1,5 @@ +{ + "id": "419", + "sku_id": "419", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json new file mode 100644 index 0000000000..b747386990 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json @@ -0,0 +1,5 @@ +{ + "id": "420", + "sku_id": "420", + "unit_price": 10.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json new file mode 100644 index 0000000000..d9830afa29 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json @@ -0,0 +1,5 @@ +{ + "id": "421", + "sku_id": "421", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json new file mode 100644 index 0000000000..1413e11e5a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json @@ -0,0 +1,5 @@ +{ + "id": "422", + "sku_id": "422", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json new file mode 100644 index 0000000000..8b422baf2c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json @@ -0,0 +1,5 @@ +{ + "id": "423", + "sku_id": "423", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json new file mode 100644 index 0000000000..5700c4211e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json @@ -0,0 +1,5 @@ +{ + "id": "424", + "sku_id": "424", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json new file mode 100644 index 0000000000..8e62840b46 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json @@ -0,0 +1,5 @@ +{ + "id": "425", + "sku_id": "425", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json new file mode 100644 index 0000000000..98f0f80feb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json @@ -0,0 +1,5 @@ +{ + "id": "501", + "sku_id": "501", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json new file mode 100644 index 0000000000..7a2bbcae27 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json @@ -0,0 +1,5 @@ +{ + "id": "502", + "sku_id": "502", + "unit_price": 9.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json new file mode 100644 index 0000000000..8445cc59ca --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json @@ -0,0 +1,5 @@ +{ + "id": "503", + "sku_id": "503", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json new file mode 100644 index 0000000000..f77b59f773 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json @@ -0,0 +1,5 @@ +{ + "id": "504", + "sku_id": "504", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json new file mode 100644 index 0000000000..57153a383b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json @@ -0,0 +1,5 @@ +{ + "id": "505", + "sku_id": "505", + "unit_price": 7.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json new file mode 100644 index 0000000000..66c0b172ba --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json @@ -0,0 +1,5 @@ +{ + "id": "506", + "sku_id": "506", + "unit_price": 18.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json new file mode 100644 index 0000000000..543724baf3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json @@ -0,0 +1,5 @@ +{ + "id": "507", + "sku_id": "507", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json new file mode 100644 index 0000000000..0b7a81d15b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json @@ -0,0 +1,5 @@ +{ + "id": "508", + "sku_id": "508", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json new file mode 100644 index 0000000000..415657d43a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json @@ -0,0 +1,5 @@ +{ + "id": "509", + "sku_id": "509", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json new file mode 100644 index 0000000000..69a1fb9d44 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json @@ -0,0 +1,5 @@ +{ + "id": "510", + "sku_id": "510", + "unit_price": 16.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json new file mode 100644 index 0000000000..9c7593196e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json @@ -0,0 +1,5 @@ +{ + "id": "511", + "sku_id": "511", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json new file mode 100644 index 0000000000..719029874d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json @@ -0,0 +1,5 @@ +{ + "id": "512", + "sku_id": "512", + "unit_price": 12.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json new file mode 100644 index 0000000000..0c8e9e7d05 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json @@ -0,0 +1,5 @@ +{ + "id": "513", + "sku_id": "513", + "unit_price": 20.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json new file mode 100644 index 0000000000..8dcf5a6197 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json @@ -0,0 +1,5 @@ +{ + "id": "514", + "sku_id": "514", + "unit_price": 12.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json new file mode 100644 index 0000000000..6bc6eb5074 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json @@ -0,0 +1,5 @@ +{ + "id": "515", + "sku_id": "515", + "unit_price": 8.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json new file mode 100644 index 0000000000..47d9590c9e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json @@ -0,0 +1,5 @@ +{ + "id": "516", + "sku_id": "516", + "unit_price": 10.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json new file mode 100644 index 0000000000..ebcecfdb33 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json @@ -0,0 +1,5 @@ +{ + "id": "517", + "sku_id": "517", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json new file mode 100644 index 0000000000..5be88115db --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json @@ -0,0 +1,5 @@ +{ + "id": "518", + "sku_id": "518", + "unit_price": 7.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json new file mode 100644 index 0000000000..07df0576fa --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json @@ -0,0 +1,5 @@ +{ + "id": "519", + "sku_id": "519", + "unit_price": 21.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json new file mode 100644 index 0000000000..2603f890c0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json @@ -0,0 +1,5 @@ +{ + "id": "520", + "sku_id": "520", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json new file mode 100644 index 0000000000..c376ea152a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json @@ -0,0 +1,5 @@ +{ + "id": "521", + "sku_id": "521", + "unit_price": 11.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json new file mode 100644 index 0000000000..3721eb86bf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json @@ -0,0 +1,5 @@ +{ + "id": "522", + "sku_id": "522", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json new file mode 100644 index 0000000000..dad8800375 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json @@ -0,0 +1,5 @@ +{ + "id": "523", + "sku_id": "523", + "unit_price": 6.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json new file mode 100644 index 0000000000..f10b3aad89 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json @@ -0,0 +1,5 @@ +{ + "id": "524", + "sku_id": "524", + "unit_price": 15.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json new file mode 100644 index 0000000000..a5dce3e37b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json @@ -0,0 +1,5 @@ +{ + "id": "525", + "sku_id": "525", + "unit_price": 13.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json new file mode 100644 index 0000000000..f56271e3f2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json @@ -0,0 +1,5 @@ +{ + "id": "601", + "sku_id": "601", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json new file mode 100644 index 0000000000..5ca8dd1492 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json @@ -0,0 +1,5 @@ +{ + "id": "602", + "sku_id": "602", + "unit_price": 12.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json new file mode 100644 index 0000000000..ee8fa64988 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json @@ -0,0 +1,5 @@ +{ + "id": "603", + "sku_id": "603", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json new file mode 100644 index 0000000000..0d69ae3bd9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json @@ -0,0 +1,5 @@ +{ + "id": "604", + "sku_id": "604", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json new file mode 100644 index 0000000000..4de4afeafa --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json @@ -0,0 +1,5 @@ +{ + "id": "605", + "sku_id": "605", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json new file mode 100644 index 0000000000..6626c625a7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json @@ -0,0 +1,5 @@ +{ + "id": "606", + "sku_id": "606", + "unit_price": 24.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json new file mode 100644 index 0000000000..ac6e29afd7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json @@ -0,0 +1,5 @@ +{ + "id": "607", + "sku_id": "607", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json new file mode 100644 index 0000000000..4d5974b888 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json @@ -0,0 +1,5 @@ +{ + "id": "608", + "sku_id": "608", + "unit_price": 15.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json new file mode 100644 index 0000000000..77a73a3934 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json @@ -0,0 +1,5 @@ +{ + "id": "609", + "sku_id": "609", + "unit_price": 22.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json new file mode 100644 index 0000000000..7d7837c818 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json @@ -0,0 +1,5 @@ +{ + "id": "610", + "sku_id": "610", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json new file mode 100644 index 0000000000..dad76f62ec --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json @@ -0,0 +1,5 @@ +{ + "id": "611", + "sku_id": "611", + "unit_price": 21.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json new file mode 100644 index 0000000000..e9cb8b570f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json @@ -0,0 +1,5 @@ +{ + "id": "612", + "sku_id": "612", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json new file mode 100644 index 0000000000..878396fc55 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json @@ -0,0 +1,5 @@ +{ + "id": "613", + "sku_id": "613", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json new file mode 100644 index 0000000000..d5f6b4c52a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json @@ -0,0 +1,5 @@ +{ + "id": "614", + "sku_id": "614", + "unit_price": 27.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json new file mode 100644 index 0000000000..72cb0df0ca --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json @@ -0,0 +1,5 @@ +{ + "id": "615", + "sku_id": "615", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json new file mode 100644 index 0000000000..e4a0be17d7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json @@ -0,0 +1,5 @@ +{ + "id": "616", + "sku_id": "616", + "unit_price": 10.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json new file mode 100644 index 0000000000..41e6574ea1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json @@ -0,0 +1,5 @@ +{ + "id": "617", + "sku_id": "617", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json new file mode 100644 index 0000000000..0bbfa87d4b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json @@ -0,0 +1,5 @@ +{ + "id": "618", + "sku_id": "618", + "unit_price": 9.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json new file mode 100644 index 0000000000..c0650619d7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json @@ -0,0 +1,5 @@ +{ + "id": "619", + "sku_id": "619", + "unit_price": 13.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json new file mode 100644 index 0000000000..807a04661e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json @@ -0,0 +1,5 @@ +{ + "id": "620", + "sku_id": "620", + "unit_price": 18.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json new file mode 100644 index 0000000000..6d43ac731a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json @@ -0,0 +1,5 @@ +{ + "id": "621", + "sku_id": "621", + "unit_price": 17.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json new file mode 100644 index 0000000000..48f538cdea --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json @@ -0,0 +1,5 @@ +{ + "id": "622", + "sku_id": "622", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json new file mode 100644 index 0000000000..ffd51b0336 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json @@ -0,0 +1,5 @@ +{ + "id": "623", + "sku_id": "623", + "unit_price": 15.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json new file mode 100644 index 0000000000..0030a18913 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json @@ -0,0 +1,5 @@ +{ + "id": "624", + "sku_id": "624", + "unit_price": 11.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json new file mode 100644 index 0000000000..58875cab8b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json @@ -0,0 +1,5 @@ +{ + "id": "625", + "sku_id": "625", + "unit_price": 23.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json new file mode 100644 index 0000000000..455468f4d9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json @@ -0,0 +1,5 @@ +{ + "id": "701", + "sku_id": "701", + "unit_price": 1.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json new file mode 100644 index 0000000000..e943b2f754 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json @@ -0,0 +1,5 @@ +{ + "id": "702", + "sku_id": "702", + "unit_price": 0.59 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json new file mode 100644 index 0000000000..e10054b138 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json @@ -0,0 +1,5 @@ +{ + "id": "703", + "sku_id": "703", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json new file mode 100644 index 0000000000..28daa10535 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json @@ -0,0 +1,5 @@ +{ + "id": "704", + "sku_id": "704", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json new file mode 100644 index 0000000000..065881a74d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json @@ -0,0 +1,5 @@ +{ + "id": "705", + "sku_id": "705", + "unit_price": 0.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json new file mode 100644 index 0000000000..9598f2e700 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json @@ -0,0 +1,5 @@ +{ + "id": "706", + "sku_id": "706", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json new file mode 100644 index 0000000000..6259e5f3c5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json @@ -0,0 +1,5 @@ +{ + "id": "707", + "sku_id": "707", + "unit_price": 1.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json new file mode 100644 index 0000000000..033e269b84 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json @@ -0,0 +1,5 @@ +{ + "id": "708", + "sku_id": "708", + "unit_price": 1.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json new file mode 100644 index 0000000000..4b6a876ef5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json @@ -0,0 +1,5 @@ +{ + "id": "709", + "sku_id": "709", + "unit_price": 0.79 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json new file mode 100644 index 0000000000..4daec77081 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json @@ -0,0 +1,5 @@ +{ + "id": "710", + "sku_id": "710", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json new file mode 100644 index 0000000000..665d89c0ed --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json @@ -0,0 +1,5 @@ +{ + "id": "711", + "sku_id": "711", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json new file mode 100644 index 0000000000..c7c2ad208a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json @@ -0,0 +1,5 @@ +{ + "id": "712", + "sku_id": "712", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json new file mode 100644 index 0000000000..509ff22685 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json @@ -0,0 +1,5 @@ +{ + "id": "713", + "sku_id": "713", + "unit_price": 0.89 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json new file mode 100644 index 0000000000..776438fe94 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json @@ -0,0 +1,5 @@ +{ + "id": "714", + "sku_id": "714", + "unit_price": 1.79 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json new file mode 100644 index 0000000000..15b4616e79 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json @@ -0,0 +1,5 @@ +{ + "id": "715", + "sku_id": "715", + "unit_price": 2.29 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json new file mode 100644 index 0000000000..4cae6c730c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json @@ -0,0 +1,5 @@ +{ + "id": "716", + "sku_id": "716", + "unit_price": 1.89 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json new file mode 100644 index 0000000000..95a5a1f7ff --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json @@ -0,0 +1,5 @@ +{ + "id": "717", + "sku_id": "717", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json new file mode 100644 index 0000000000..a35b17facb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json @@ -0,0 +1,5 @@ +{ + "id": "718", + "sku_id": "718", + "unit_price": 1.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json new file mode 100644 index 0000000000..5d24450fd9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json @@ -0,0 +1,5 @@ +{ + "id": "719", + "sku_id": "719", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json new file mode 100644 index 0000000000..f457faa5f9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json @@ -0,0 +1,5 @@ +{ + "id": "720", + "sku_id": "720", + "unit_price": 0.59 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json new file mode 100644 index 0000000000..a3d385a1c1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json @@ -0,0 +1,5 @@ +{ + "id": "721", + "sku_id": "721", + "unit_price": 0.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json new file mode 100644 index 0000000000..5da5ee7f53 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json @@ -0,0 +1,5 @@ +{ + "id": "722", + "sku_id": "722", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json new file mode 100644 index 0000000000..4543b17754 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json @@ -0,0 +1,5 @@ +{ + "id": "723", + "sku_id": "723", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json new file mode 100644 index 0000000000..1ea8749244 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json @@ -0,0 +1,5 @@ +{ + "id": "724", + "sku_id": "724", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json new file mode 100644 index 0000000000..6bea27553e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json @@ -0,0 +1,5 @@ +{ + "id": "725", + "sku_id": "725", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json new file mode 100644 index 0000000000..99efe1aca8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json @@ -0,0 +1,5 @@ +{ + "id": "801", + "sku_id": "801", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json new file mode 100644 index 0000000000..2f6440e5e8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json @@ -0,0 +1,5 @@ +{ + "id": "802", + "sku_id": "802", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json new file mode 100644 index 0000000000..7756bf5061 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json @@ -0,0 +1,5 @@ +{ + "id": "803", + "sku_id": "803", + "unit_price": 12.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json new file mode 100644 index 0000000000..333c87322a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json @@ -0,0 +1,5 @@ +{ + "id": "804", + "sku_id": "804", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json new file mode 100644 index 0000000000..da16d8ef12 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json @@ -0,0 +1,5 @@ +{ + "id": "805", + "sku_id": "805", + "unit_price": 25.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json new file mode 100644 index 0000000000..7681a8f8cd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json @@ -0,0 +1,5 @@ +{ + "id": "806", + "sku_id": "806", + "unit_price": 17.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json new file mode 100644 index 0000000000..f29d844f76 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json @@ -0,0 +1,5 @@ +{ + "id": "807", + "sku_id": "807", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json new file mode 100644 index 0000000000..3b15c7c132 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json @@ -0,0 +1,5 @@ +{ + "id": "808", + "sku_id": "808", + "unit_price": 29.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json new file mode 100644 index 0000000000..4f4e116282 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json @@ -0,0 +1,5 @@ +{ + "id": "809", + "sku_id": "809", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json new file mode 100644 index 0000000000..fa7d414350 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json @@ -0,0 +1,5 @@ +{ + "id": "810", + "sku_id": "810", + "unit_price": 16.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json new file mode 100644 index 0000000000..47271c87bb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json @@ -0,0 +1,5 @@ +{ + "id": "811", + "sku_id": "811", + "unit_price": 22.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json new file mode 100644 index 0000000000..55ca3e56db --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json @@ -0,0 +1,5 @@ +{ + "id": "812", + "sku_id": "812", + "unit_price": 10.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json new file mode 100644 index 0000000000..944fb22c8f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json @@ -0,0 +1,5 @@ +{ + "id": "813", + "sku_id": "813", + "unit_price": 26.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json new file mode 100644 index 0000000000..9bae40e662 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json @@ -0,0 +1,5 @@ +{ + "id": "814", + "sku_id": "814", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json new file mode 100644 index 0000000000..d7017e4bce --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json @@ -0,0 +1,5 @@ +{ + "id": "815", + "sku_id": "815", + "unit_price": 18.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json new file mode 100644 index 0000000000..f6d0445d38 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json @@ -0,0 +1,5 @@ +{ + "id": "816", + "sku_id": "816", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json new file mode 100644 index 0000000000..a1d54456a4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json @@ -0,0 +1,5 @@ +{ + "id": "817", + "sku_id": "817", + "unit_price": 1.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json new file mode 100644 index 0000000000..9d62b549a2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json @@ -0,0 +1,5 @@ +{ + "id": "818", + "sku_id": "818", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json new file mode 100644 index 0000000000..9e9aea87c7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json @@ -0,0 +1,5 @@ +{ + "id": "819", + "sku_id": "819", + "unit_price": 49.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json new file mode 100644 index 0000000000..3446e4fac7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json @@ -0,0 +1,5 @@ +{ + "id": "820", + "sku_id": "820", + "unit_price": 24.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json new file mode 100644 index 0000000000..12026da2ab --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json @@ -0,0 +1,5 @@ +{ + "id": "821", + "sku_id": "821", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json new file mode 100644 index 0000000000..91b8f0e649 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json @@ -0,0 +1,5 @@ +{ + "id": "822", + "sku_id": "822", + "unit_price": 12.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json new file mode 100644 index 0000000000..08202e2b5c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json @@ -0,0 +1,5 @@ +{ + "id": "823", + "sku_id": "823", + "unit_price": 15.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json new file mode 100644 index 0000000000..5f596b2fa5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json @@ -0,0 +1,5 @@ +{ + "id": "824", + "sku_id": "824", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json new file mode 100644 index 0000000000..739dd19379 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json @@ -0,0 +1,5 @@ +{ + "id": "825", + "sku_id": "825", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema new file mode 100644 index 0000000000..7e8cbeb4f1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema @@ -0,0 +1,7 @@ +{ + "type": "string", + "title": "Product Pricing SKU Key", + "description": "A unique identifier for the product SKU pricing", + "pattern": "^[0-9]+$" +} + \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema new file mode 100644 index 0000000000..89f769ab79 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema @@ -0,0 +1,19 @@ +{ + "type": "object", + "description": "A unique identifier for the department in the retail store.", + "title": "Product Pricing Value", + "properties": { + "id": { + "type": "string" + }, + "sku_id": { + "type": "string" + }, + "unit_price": { + "type": "number" + } + }, + "required": ["id", "sku_id", "unit_price"], + "additionalProperties": false + } + \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json new file mode 100644 index 0000000000..b03381f704 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json @@ -0,0 +1,7 @@ +{ + "id": "101", + "sku_id": "101", + "name": "Smart Toaster", + "description": "A smart toaster with touchscreen controls and multiple toast settings for perfect browning every time.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json new file mode 100644 index 0000000000..654842e01f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json @@ -0,0 +1,7 @@ +{ + "id": "102", + "sku_id": "102", + "name": "Air Fryer Pro", + "description": "Healthy air fryer that cooks crispy meals with little to no oil. 3.7 qt capacity.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json new file mode 100644 index 0000000000..eca1d2da1f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json @@ -0,0 +1,7 @@ +{ + "id": "103", + "sku_id": "103", + "name": "Cordless Vacuum Cleaner", + "description": "Lightweight and powerful cordless vacuum cleaner with HEPA filtration for allergy relief.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json new file mode 100644 index 0000000000..47d8c64595 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json @@ -0,0 +1,7 @@ +{ + "id": "104", + "sku_id": "104", + "name": "Instant Pot Duo 7-in-1", + "description": "Multi-use electric pressure cooker that can be used as a slow cooker, rice cooker, steamer, and more.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json new file mode 100644 index 0000000000..c8e071ef63 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json @@ -0,0 +1,7 @@ +{ + "id": "105", + "sku_id": "105", + "name": "Electric Kettle", + "description": "1.7-liter electric kettle with auto shut-off and boil-dry protection for safe, fast boiling.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json new file mode 100644 index 0000000000..a28ff1de96 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json @@ -0,0 +1,7 @@ +{ + "id": "106", + "sku_id": "106", + "name": "7-Quart Slow Cooker", + "description": "Programmable slow cooker with a locking lid and digital controls for easy meal prep.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json new file mode 100644 index 0000000000..614af11691 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json @@ -0,0 +1,7 @@ +{ + "id": "107", + "sku_id": "107", + "name": "Food Processor", + "description": "Versatile food processor with a 14-cup capacity and various blades for chopping, slicing, and shredding.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json new file mode 100644 index 0000000000..d5f6ba4afb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json @@ -0,0 +1,7 @@ +{ + "id": "108", + "sku_id": "108", + "name": "Coffee Maker", + "description": "12-cup programmable coffee maker with brew strength settings and a pause-and-serve feature.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json new file mode 100644 index 0000000000..b450d0c925 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json @@ -0,0 +1,7 @@ +{ + "id": "109", + "sku_id": "109", + "name": "Soda Maker", + "description": "Transform plain water into sparkling drinks at home with this easy-to-use soda maker.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json new file mode 100644 index 0000000000..fa24903aba --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json @@ -0,0 +1,7 @@ +{ + "id": "110", + "sku_id": "110", + "name": "Electric Griddle", + "description": "Large non-stick electric griddle with adjustable temperature settings for pancakes, eggs, and more.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json new file mode 100644 index 0000000000..e8847d51a5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json @@ -0,0 +1,7 @@ +{ + "id": "111", + "sku_id": "111", + "name": "Stand Mixer", + "description": "Powerful stand mixer with multiple attachments for baking, whipping, and kneading dough.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json new file mode 100644 index 0000000000..42e4311eef --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json @@ -0,0 +1,7 @@ +{ + "id": "112", + "sku_id": "112", + "name": "Rice Cooker", + "description": "Automatic rice cooker with a keep-warm function and non-stick pot for easy cleaning.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json new file mode 100644 index 0000000000..a5e2a3fd13 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json @@ -0,0 +1,7 @@ +{ + "id": "113", + "sku_id": "113", + "name": "Induction Cooktop", + "description": "Portable induction cooktop with two burners for fast cooking and precise temperature control.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json new file mode 100644 index 0000000000..c405d5906b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json @@ -0,0 +1,7 @@ +{ + "id": "114", + "sku_id": "114", + "name": "Blender", + "description": "High-speed blender that crushes ice and blends fruits smoothly for your favorite smoothies.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json new file mode 100644 index 0000000000..79b35c6991 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json @@ -0,0 +1,7 @@ +{ + "id": "115", + "sku_id": "115", + "name": "Waffle Maker", + "description": "Non-stick waffle maker with adjustable browning control for golden, fluffy waffles.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json new file mode 100644 index 0000000000..80a1675ef2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json @@ -0,0 +1,7 @@ +{ + "id": "116", + "sku_id": "116", + "name": "Juicer", + "description": "Centrifugal juicer that extracts juice from fruits and veggies quickly and efficiently.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json new file mode 100644 index 0000000000..96aae93b4d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json @@ -0,0 +1,7 @@ +{ + "id": "117", + "sku_id": "117", + "name": "Microwave Oven", + "description": "Compact microwave oven with preset cooking options and a sleek design for any kitchen.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json new file mode 100644 index 0000000000..07a6c9fd8b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json @@ -0,0 +1,7 @@ +{ + "id": "118", + "sku_id": "118", + "name": "Electric Grill", + "description": "Indoor electric grill with non-stick surface and adjustable temperature for grilling year-round.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json new file mode 100644 index 0000000000..c98e509572 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json @@ -0,0 +1,7 @@ +{ + "id": "119", + "sku_id": "119", + "name": "Sous Vide Precision Cooker", + "description": "Sous vide cooker for perfectly cooked meals with a precision temperature control.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json new file mode 100644 index 0000000000..fbe2f66dda --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json @@ -0,0 +1,7 @@ +{ + "id": "120", + "sku_id": "120", + "name": "Dishwasher", + "description": "Compact countertop dishwasher with 6 washing programs for easy cleaning of dishes.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json new file mode 100644 index 0000000000..9c1949d6c8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json @@ -0,0 +1,7 @@ +{ + "id": "121", + "sku_id": "121", + "name": "Dehydrator", + "description": "Food dehydrator for drying fruits, vegetables, and jerky with temperature control settings.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json new file mode 100644 index 0000000000..f5c67a2177 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json @@ -0,0 +1,7 @@ +{ + "id": "122", + "sku_id": "122", + "name": "Portable Ice Maker", + "description": "Compact ice maker that produces bullet ice cubes in just 6 minutes, perfect for parties.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json new file mode 100644 index 0000000000..1a2130d62b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json @@ -0,0 +1,7 @@ +{ + "id": "123", + "sku_id": "123", + "name": "Electric Pressure Cooker", + "description": "Electric pressure cooker with easy-to-use controls for fast cooking of stews, soups, and more.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json new file mode 100644 index 0000000000..3fc2002db2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json @@ -0,0 +1,7 @@ +{ + "id": "124", + "sku_id": "124", + "name": "Bread Machine", + "description": "Automatic bread machine with multiple settings to bake fresh bread at home with ease.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json new file mode 100644 index 0000000000..d2efde5ac6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json @@ -0,0 +1,7 @@ +{ + "id": "125", + "sku_id": "125", + "name": "Kitchen Scale", + "description": "Digital kitchen scale with a large display and tare function for precise ingredient measurements.", + "department": "appliance" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json new file mode 100644 index 0000000000..e6a3ea5635 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json @@ -0,0 +1,7 @@ +{ + "id": "201", + "sku_id": "201", + "name": "All-Purpose Cleaner", + "description": "A versatile cleaner suitable for various surfaces, including countertops and floors. Provides sparkling results with a fresh lemon scent.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json new file mode 100644 index 0000000000..0f641ad1b9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json @@ -0,0 +1,7 @@ +{ + "id": "202", + "sku_id": "202", + "name": "Window Cleaner Spray", + "description": "Streak-free window cleaner great for glass surfaces. Comes in a 22 oz spray bottle with a pleasant citrus scent.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json new file mode 100644 index 0000000000..3c82f987c0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json @@ -0,0 +1,7 @@ +{ + "id": "203", + "sku_id": "203", + "name": "Dish Soap", + "description": "Concentrated formula cuts through grease and grime on dishes and kitchenware. Comes in a 16 oz bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json new file mode 100644 index 0000000000..371f17c166 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json @@ -0,0 +1,7 @@ +{ + "id": "204", + "sku_id": "204", + "name": "Bathroom Cleaner Spray", + "description": "Powerful cleaner designed for bathroom surfaces. Effectively removes soap scum and hard water stains. 26 oz spray bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json new file mode 100644 index 0000000000..e46a3b5f46 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json @@ -0,0 +1,7 @@ +{ + "id": "205", + "sku_id": "205", + "name": "Laundry Detergent Pods", + "description": "Convenient laundry detergent pods for a powerful clean. 20-pack of scent-free pods suitable for all machines.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json new file mode 100644 index 0000000000..d35b33e7ee --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json @@ -0,0 +1,7 @@ +{ + "id": "206", + "sku_id": "206", + "name": "Heavy-Duty Scrub Sponges", + "description": "Durable scrub sponges ideal for tough stains on pots and pans. Pack of 6 sponges.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json new file mode 100644 index 0000000000..fdbd29c5cd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json @@ -0,0 +1,7 @@ +{ + "id": "207", + "sku_id": "207", + "name": "Disinfecting Wipes", + "description": "Convenient wipes designed to kill 99.9% of germs. Great for quick clean-ups, 75-count tub.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json new file mode 100644 index 0000000000..ac06be7325 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json @@ -0,0 +1,7 @@ +{ + "id": "208", + "sku_id": "208", + "name": "Mop and Broom Set", + "description": "Essential cleaning set that includes a mop and broom. Perfect for keeping floors clean and tidy.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json new file mode 100644 index 0000000000..0e1ce281ac --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json @@ -0,0 +1,7 @@ +{ + "id": "209", + "sku_id": "209", + "name": "Stainless Steel Cleaner", + "description": "Specially formulated cleaner for stainless steel appliances. Restores shine and protects surfaces. 12 oz spray.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json new file mode 100644 index 0000000000..8a0c1ed1c7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json @@ -0,0 +1,7 @@ +{ + "id": "210", + "sku_id": "210", + "name": "Carpet Stain Remover", + "description": "Effective stain remover for carpets and upholstery. Safe for use on most fabrics. 32 oz bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json new file mode 100644 index 0000000000..afbf15894c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json @@ -0,0 +1,7 @@ +{ + "id": "211", + "sku_id": "211", + "name": "Odor Eliminating Spray", + "description": "Quick-acting spray that eliminates persistent odors in the home. 15 oz can with a fresh fragrance.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json new file mode 100644 index 0000000000..c896a2b6b0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json @@ -0,0 +1,7 @@ +{ + "id": "212", + "sku_id": "212", + "name": "Microfiber Cleaning Cloths", + "description": "Soft microfiber cloths for dusting and polishing surfaces. Pack of 5 reusable cloths.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json new file mode 100644 index 0000000000..dd4d0ec8fc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json @@ -0,0 +1,7 @@ +{ + "id": "213", + "sku_id": "213", + "name": "Glass Cleaner with Vinegar", + "description": "Natural glass cleaner made with vinegar for a streak-free shine. 24 oz spray bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json new file mode 100644 index 0000000000..59876c35bf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json @@ -0,0 +1,7 @@ +{ + "id": "214", + "sku_id": "214", + "name": "Air Freshener Spray", + "description": "Odor-neutralizing spray that leaves a light fragrance in the air. 8 oz can available in various scents.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json new file mode 100644 index 0000000000..ea87ad542d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json @@ -0,0 +1,7 @@ +{ + "id": "215", + "sku_id": "215", + "name": "Toilet Bowl Cleaner", + "description": "Powerful toilet bowl cleaner that breaks down stains and eliminates odors. 24 oz bottle with a precision neck for easy application.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json new file mode 100644 index 0000000000..023267222a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json @@ -0,0 +1,7 @@ +{ + "id": "216", + "sku_id": "216", + "name": "Allergen Reducer Spray", + "description": "Spray that helps reduce allergens in the home, including dust and pet dander. 10 oz bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json new file mode 100644 index 0000000000..baa64387e4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json @@ -0,0 +1,7 @@ +{ + "id": "217", + "sku_id": "217", + "name": "Scented Garbage Bags", + "description": "Strong and durable garbage bags infused with a pleasant scent. 30-count box of 13-gallon bags.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json new file mode 100644 index 0000000000..562f8510f0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json @@ -0,0 +1,7 @@ +{ + "id": "218", + "sku_id": "218", + "name": "Floor Cleaner Concentrate", + "description": "Concentrated floor cleaner for all hard surfaces. Makes 4 gallons of cleaner per bottle. 32 oz.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json new file mode 100644 index 0000000000..ae95d251b2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json @@ -0,0 +1,7 @@ +{ + "id": "219", + "sku_id": "219", + "name": "Foam Bathroom Cleaner", + "description": "Thick foam cleaner that clings to surfaces for maximum cleaning power. 19 oz aerosol can.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json new file mode 100644 index 0000000000..f771c63f9b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json @@ -0,0 +1,7 @@ +{ + "id": "220", + "sku_id": "220", + "name": "Heavy Duty Trash Bags", + "description": "Extra thick trash bags designed for heavy loads. 30-count box of 30-gallon bags for tough clean-up tasks.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json new file mode 100644 index 0000000000..b5bc3c35b9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json @@ -0,0 +1,7 @@ +{ + "id": "221", + "sku_id": "221", + "name": "Baking Soda Cleaning Powder", + "description": "A natural cleaner and deodorizer for various household tasks. 16 oz container of pure baking soda.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json new file mode 100644 index 0000000000..5632ccbb76 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json @@ -0,0 +1,7 @@ +{ + "id": "222", + "sku_id": "222", + "name": "Fabric Freshener Spray", + "description": "A fabric freshening spray that neutralizes odors and refreshes upholstery. 13 oz bottle available in multiple scents.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json new file mode 100644 index 0000000000..20c163aac4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json @@ -0,0 +1,7 @@ +{ + "id": "223", + "sku_id": "223", + "name": "Dishwasher Cleaner Tablets", + "description": "Tablets for cleaning the inside of your dishwasher for better performance. 6-count pack.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json new file mode 100644 index 0000000000..117e05eabf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json @@ -0,0 +1,7 @@ +{ + "id": "224", + "sku_id": "224", + "name": "Auto Interior Cleaner", + "description": "Specially formulated cleaner for car interiors, leaves a fresh scent. 16 oz spray bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json new file mode 100644 index 0000000000..caeaff1cc7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json @@ -0,0 +1,7 @@ +{ + "id": "225", + "sku_id": "225", + "name": "Hardwood Floor Cleaner", + "description": "Gentle cleaner designed specifically for hardwood floors. 32 oz bottle, leaves no residue.", + "department": "cleaning" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json new file mode 100644 index 0000000000..f1e546490c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json @@ -0,0 +1,7 @@ +{ + "id": "301", + "sku_id": "301", + "name": "Whole Milk", + "description": "Fresh whole milk, 1 gallon, sourced from local farms.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json new file mode 100644 index 0000000000..697aeac06d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json @@ -0,0 +1,7 @@ +{ + "id": "302", + "sku_id": "302", + "name": "2% Milk", + "description": "Low-fat milk with 2% milkfat, 1 gallon, perfect for everyday use.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json new file mode 100644 index 0000000000..824c4e261a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json @@ -0,0 +1,7 @@ +{ + "id": "303", + "sku_id": "303", + "name": "Almond Milk", + "description": "Unsweetened almond milk, 64 oz, a great dairy alternative for lactose intolerant individuals.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json new file mode 100644 index 0000000000..c84a6c9c17 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json @@ -0,0 +1,7 @@ +{ + "id": "304", + "sku_id": "304", + "name": "Greek Yogurt", + "description": "Creamy and rich Greek yogurt, 32 oz, available in various flavors.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json new file mode 100644 index 0000000000..24daa19b7a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json @@ -0,0 +1,7 @@ +{ + "id": "305", + "sku_id": "305", + "name": "Cottage Cheese", + "description": "Low-fat cottage cheese, 16 oz, high in protein and perfect for snacking.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json new file mode 100644 index 0000000000..6fb546f7a3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json @@ -0,0 +1,7 @@ +{ + "id": "306", + "sku_id": "306", + "name": "Cream Cheese", + "description": "Soft and spreadable cream cheese, 8 oz, perfect for bagels and dips.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json new file mode 100644 index 0000000000..f0ff835ef3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json @@ -0,0 +1,7 @@ +{ + "id": "307", + "sku_id": "307", + "name": "Butter", + "description": "Salted butter, 1 lb, from grass-fed cows, ideal for cooking and baking.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json new file mode 100644 index 0000000000..df86e589f5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json @@ -0,0 +1,7 @@ +{ + "id": "308", + "sku_id": "308", + "name": "Cheddar Cheese", + "description": "Sharp cheddar cheese, 8 oz, great for sandwiches and cheese boards.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json new file mode 100644 index 0000000000..338a286edc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json @@ -0,0 +1,7 @@ +{ + "id": "309", + "sku_id": "309", + "name": "Mozzarella Cheese", + "description": "Fresh mozzarella cheese, 8 oz, perfect for pizza and salads.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json new file mode 100644 index 0000000000..436126bbe5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json @@ -0,0 +1,7 @@ +{ + "id": "310", + "sku_id": "310", + "name": "Parmesan Cheese", + "description": "Grated Parmesan cheese, 8 oz, perfect for adding flavor to dishes.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json new file mode 100644 index 0000000000..e7f26fef18 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json @@ -0,0 +1,7 @@ +{ + "id": "311", + "sku_id": "311", + "name": "Sour Cream", + "description": "Rich and creamy sour cream, 16 oz, perfect for toppings and dips.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json new file mode 100644 index 0000000000..65ef141fb2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json @@ -0,0 +1,7 @@ +{ + "id": "312", + "sku_id": "312", + "name": "Ice Cream", + "description": "Vanilla ice cream, 1.5 quart, a classic dessert favorite.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json new file mode 100644 index 0000000000..0daada5d6a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json @@ -0,0 +1,7 @@ +{ + "id": "313", + "sku_id": "313", + "name": "Heavy Whipping Cream", + "description": "Heavy cream, 16 oz, ideal for whipping and cooking.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json new file mode 100644 index 0000000000..4576185b39 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json @@ -0,0 +1,7 @@ +{ + "id": "314", + "sku_id": "314", + "name": "Goat Cheese", + "description": "Soft goat cheese, 5 oz, great for spreads and salads.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json new file mode 100644 index 0000000000..ca185b970a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json @@ -0,0 +1,7 @@ +{ + "id": "315", + "sku_id": "315", + "name": "Yogurt Parfait", + "description": "Layered yogurt parfait with granola and berries, 12 oz, a great snack.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json new file mode 100644 index 0000000000..556ad5eb80 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json @@ -0,0 +1,7 @@ +{ + "id": "316", + "sku_id": "316", + "name": "Ricotta Cheese", + "description": "Creamy ricotta cheese, 15 oz, perfect for pasta dishes and desserts.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json new file mode 100644 index 0000000000..ea4c74c117 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json @@ -0,0 +1,7 @@ +{ + "id": "317", + "sku_id": "317", + "name": "Buttermilk", + "description": "Cultured buttermilk, 32 oz, great for baking and cooking.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json new file mode 100644 index 0000000000..aa3c135ec6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json @@ -0,0 +1,7 @@ +{ + "id": "318", + "sku_id": "318", + "name": "Almond Milk Yogurt", + "description": "Dairy-free almond yogurt, 5.3 oz, available in various flavors.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json new file mode 100644 index 0000000000..6880f1f155 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json @@ -0,0 +1,7 @@ +{ + "id": "319", + "sku_id": "319", + "name": "Skim Milk", + "description": "Fat-free skim milk, 1 gallon, perfect for a low-calorie diet.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json new file mode 100644 index 0000000000..0afd69e944 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json @@ -0,0 +1,7 @@ +{ + "id": "320", + "sku_id": "320", + "name": "String Cheese", + "description": "Mozzarella string cheese, 12 count, a convenient snack for kids.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json new file mode 100644 index 0000000000..2c63b476a2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json @@ -0,0 +1,7 @@ +{ + "id": "321", + "sku_id": "321", + "name": "Kefir", + "description": "Probiotic rich kefir, 32 oz, a great addition to smoothies.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json new file mode 100644 index 0000000000..ca3ef6c6e8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json @@ -0,0 +1,7 @@ +{ + "id": "322", + "sku_id": "322", + "name": "Tofu Cream Cheese", + "description": "Vegan cream cheese made from tofu, 8 oz, a great dairy alternative.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json new file mode 100644 index 0000000000..2353430c25 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json @@ -0,0 +1,7 @@ +{ + "id": "323", + "sku_id": "323", + "name": "Frozen Yogurt", + "description": "Soft-serve frozen yogurt, 1.5 quart, available in assorted flavors.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json new file mode 100644 index 0000000000..cfb68604d3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json @@ -0,0 +1,7 @@ +{ + "id": "324", + "sku_id": "324", + "name": "Plant-Based Milk", + "description": "Oat milk, 64 oz, a creamy dairy alternative, ideal for coffee.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json new file mode 100644 index 0000000000..7ef0ff94fc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json @@ -0,0 +1,7 @@ +{ + "id": "325", + "sku_id": "325", + "name": "Flavored Creamer", + "description": "Vanilla flavored coffee creamer, 16 oz, perfect for enhancing your morning brew.", + "department": "dairy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json new file mode 100644 index 0000000000..beb7588a97 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json @@ -0,0 +1,7 @@ +{ + "id": "401", + "sku_id": "401", + "name": "Honey Glazed Ham", + "description": "Delicious honey glazed ham, perfect for sandwiches or as a centerpiece.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json new file mode 100644 index 0000000000..bb67fd88d4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json @@ -0,0 +1,7 @@ +{ + "id": "402", + "sku_id": "402", + "name": "Turkey Breast", + "description": "Oven-roasted turkey breast, low in fat and high in flavor.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json new file mode 100644 index 0000000000..05b3ff5af3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json @@ -0,0 +1,7 @@ +{ + "id": "403", + "sku_id": "403", + "name": "Italian Salami", + "description": "A blend of seasoned pork and beef, perfect for antipasto platters.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json new file mode 100644 index 0000000000..46f7a425a2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json @@ -0,0 +1,7 @@ +{ + "id": "404", + "sku_id": "404", + "name": "Sliced Provolone Cheese", + "description": "Creamy provolone cheese slices, great for sandwiches or cheese boards.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json new file mode 100644 index 0000000000..ad27b38b94 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json @@ -0,0 +1,7 @@ +{ + "id": "405", + "sku_id": "405", + "name": "Roast Beef", + "description": "Flavorful roast beef, cut thin for easy stacking on sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json new file mode 100644 index 0000000000..4226e9ec40 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json @@ -0,0 +1,7 @@ +{ + "id": "406", + "sku_id": "406", + "name": "Black Forest Ham", + "description": "Rich and flavorful Black Forest ham, ideal for lunchtime favorites.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json new file mode 100644 index 0000000000..a0bb034139 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json @@ -0,0 +1,7 @@ +{ + "id": "407", + "sku_id": "407", + "name": "Genoa Salami", + "description": "Authentic Genoa salami, mildly spiced, perfect for charcuterie boards.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json new file mode 100644 index 0000000000..47d0a96513 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json @@ -0,0 +1,7 @@ +{ + "id": "408", + "sku_id": "408", + "name": "Bacon Bits", + "description": "Crispy bacon bits, perfect for toppings on salads or baked potatoes.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json new file mode 100644 index 0000000000..2c745ad0d8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json @@ -0,0 +1,7 @@ +{ + "id": "409", + "sku_id": "409", + "name": "Pepper Jack Cheese", + "description": "Spicy pepper jack cheese, great for melting or adding flavor to dishes.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json new file mode 100644 index 0000000000..0e919cfba3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json @@ -0,0 +1,7 @@ +{ + "id": "410", + "sku_id": "410", + "name": "Sliced Swiss Cheese", + "description": "Smooth Swiss cheese, perfect for sandwiches or snacking.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json new file mode 100644 index 0000000000..8d667f48d6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json @@ -0,0 +1,7 @@ +{ + "id": "411", + "sku_id": "411", + "name": "Meatloaf Slice", + "description": "Homemade meatloaf slices, ready to heat and serve for a quick meal.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json new file mode 100644 index 0000000000..65c8c0688b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json @@ -0,0 +1,7 @@ +{ + "id": "412", + "sku_id": "412", + "name": "Hummus Spread", + "description": "Creamy hummus spread made with fresh chickpeas and tahini, perfect for dipping.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json new file mode 100644 index 0000000000..a759429e6c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json @@ -0,0 +1,7 @@ +{ + "id": "413", + "sku_id": "413", + "name": "Sliced Chicken Breast", + "description": "Tender chicken breast, perfect for salads or sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json new file mode 100644 index 0000000000..fd34eb00f3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json @@ -0,0 +1,7 @@ +{ + "id": "414", + "sku_id": "414", + "name": "Pimento Cheese Spread", + "description": "Savory pimento cheese spread, great with crackers or veggies.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json new file mode 100644 index 0000000000..0905d67d5f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json @@ -0,0 +1,7 @@ +{ + "id": "415", + "sku_id": "415", + "name": "Tuna Salad", + "description": "Freshly made tuna salad with mayonnaise and seasoning, perfect for sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json new file mode 100644 index 0000000000..10d8c0fa84 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json @@ -0,0 +1,7 @@ +{ + "id": "416", + "sku_id": "416", + "name": "Baked Ham & Cheese Sandwich", + "description": "Delicious baked ham and cheese sandwich, ready for a quick meal.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json new file mode 100644 index 0000000000..7b56286cb5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json @@ -0,0 +1,7 @@ +{ + "id": "417", + "sku_id": "417", + "name": "Antipasto Salad", + "description": "Mixed antipasto salad with olives, peppers, and meats, ideal for sharing.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json new file mode 100644 index 0000000000..449d61cb98 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json @@ -0,0 +1,7 @@ +{ + "id": "418", + "sku_id": "418", + "name": "Mediterranean Wrap", + "description": "Flavorful wrap filled with turkey, cheese, and Mediterranean veggies.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json new file mode 100644 index 0000000000..f3d10ec712 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json @@ -0,0 +1,7 @@ +{ + "id": "419", + "sku_id": "419", + "name": "BBQ Chicken Sandwich", + "description": "Pulled BBQ chicken on a bun, perfect for lunch or a light meal.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json new file mode 100644 index 0000000000..3ade7745bb --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json @@ -0,0 +1,7 @@ +{ + "id": "420", + "sku_id": "420", + "name": "Sliced Roast Pork", + "description": "Tender, slow-roasted pork, perfect for sandwiches or as a main dish.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json new file mode 100644 index 0000000000..b91236adf8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json @@ -0,0 +1,7 @@ +{ + "id": "421", + "sku_id": "421", + "name": "Cranberry Chicken Salad", + "description": "Chicken salad with cranberries, nuts, and dressing, perfect for sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json new file mode 100644 index 0000000000..b3ff27b9d4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json @@ -0,0 +1,7 @@ +{ + "id": "422", + "sku_id": "422", + "name": "Shrimp Salad", + "description": "Fresh shrimp salad with a tangy dressing, ideal for seafood lovers.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json new file mode 100644 index 0000000000..0fa271b50f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json @@ -0,0 +1,7 @@ +{ + "id": "423", + "sku_id": "423", + "name": "Caprese Sandwich", + "description": "A classic Caprese sandwich with fresh mozzarella, tomatoes, and basil.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json new file mode 100644 index 0000000000..9825fb8a62 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json @@ -0,0 +1,7 @@ +{ + "id": "424", + "sku_id": "424", + "name": "Curried Egg Salad", + "description": "Egg salad mixed with curry spices, great on its own or in a sandwich.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json new file mode 100644 index 0000000000..0fe110bb1d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json @@ -0,0 +1,7 @@ +{ + "id": "425", + "sku_id": "425", + "name": "Veggie Platter with Dip", + "description": "A colorful assortment of fresh veggies served with a tasty dip.", + "department": "deli" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json new file mode 100644 index 0000000000..910bdf1789 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json @@ -0,0 +1,7 @@ +{ + "id": "501", + "sku_id": "501", + "name": "Grass-Fed Beef Steak", + "description": "Premium grass-fed beef steak, tender and flavorful. Perfect for grilling or pan-searing.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json new file mode 100644 index 0000000000..d1445449ef --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json @@ -0,0 +1,7 @@ +{ + "id": "502", + "sku_id": "502", + "name": "Organic Chicken Breast", + "description": "Juicy organic chicken breasts, free-range and hormone-free, perfect for healthy meals.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json new file mode 100644 index 0000000000..e24f1c6d20 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json @@ -0,0 +1,7 @@ +{ + "id": "503", + "sku_id": "503", + "name": "Pork Tenderloin", + "description": "Lean and tender pork tenderloin, ideal for roasting or grilling, packed with flavor.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json new file mode 100644 index 0000000000..55d724f62b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json @@ -0,0 +1,7 @@ +{ + "id": "504", + "sku_id": "504", + "name": "Bacon Strips", + "description": "Crispy, smoky bacon strips made from premium pork, great for breakfast sandwiches.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json new file mode 100644 index 0000000000..b7635a3a79 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json @@ -0,0 +1,7 @@ +{ + "id": "505", + "sku_id": "505", + "name": "Ground Turkey", + "description": "Lean ground turkey, versatile and nutritious, perfect for burgers or meatballs.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json new file mode 100644 index 0000000000..7d21297390 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json @@ -0,0 +1,7 @@ +{ + "id": "506", + "sku_id": "506", + "name": "Salmon Fillet", + "description": "Fresh Atlantic salmon fillet, rich in omega-3 fatty acids, perfect for grilling or baking.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json new file mode 100644 index 0000000000..f34f146088 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json @@ -0,0 +1,7 @@ +{ + "id": "507", + "sku_id": "507", + "name": "Beef Brisket", + "description": "Flavorful beef brisket, great for slow cooking or barbecuing, melts in your mouth.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json new file mode 100644 index 0000000000..deb47771f2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json @@ -0,0 +1,7 @@ +{ + "id": "508", + "sku_id": "508", + "name": "Chicken Thighs", + "description": "Tender chicken thighs, skin-on and bone-in for maximum flavor, great for roasting.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json new file mode 100644 index 0000000000..a279a24ac5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json @@ -0,0 +1,7 @@ +{ + "id": "509", + "sku_id": "509", + "name": "Italian Sausage Links", + "description": "Savory Italian sausage links, made with herbs and spices, perfect for grilling or pasta dishes.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json new file mode 100644 index 0000000000..7bebdb00df --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json @@ -0,0 +1,7 @@ +{ + "id": "510", + "sku_id": "510", + "name": "Lamb Chops", + "description": "Juicy lamb chops, expertly cut and seasoned, ideal for grilling or pan-searing.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json new file mode 100644 index 0000000000..c571653867 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json @@ -0,0 +1,7 @@ +{ + "id": "511", + "sku_id": "511", + "name": "Turkey Bacon", + "description": "Lean turkey bacon, a healthier alternative to pork bacon without compromising on taste.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json new file mode 100644 index 0000000000..8c781c2c18 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json @@ -0,0 +1,7 @@ +{ + "id": "512", + "sku_id": "512", + "name": "Whole Chicken", + "description": "Fresh whole chicken, ideal for roasting or slow-cooking, feeds the whole family.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json new file mode 100644 index 0000000000..895a46dffe --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json @@ -0,0 +1,7 @@ +{ + "id": "513", + "sku_id": "513", + "name": "Beef Short Ribs", + "description": "Rich and flavorful beef short ribs, perfect for braising or slow-cooking.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json new file mode 100644 index 0000000000..afa28d663a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json @@ -0,0 +1,7 @@ +{ + "id": "514", + "sku_id": "514", + "name": "Smoked Sausage", + "description": "Delicious smoked sausage, great for grilling or adding to stews and casseroles.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json new file mode 100644 index 0000000000..a847c7974f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json @@ -0,0 +1,7 @@ +{ + "id": "515", + "sku_id": "515", + "name": "Deli Ham", + "description": "Premium deli ham, perfect for sandwiches and charcuterie boards.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json new file mode 100644 index 0000000000..ae73b95cf6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json @@ -0,0 +1,7 @@ +{ + "id": "516", + "sku_id": "516", + "name": "Fish Filet (Tilapia)", + "description": "Mild-tasting tilapia filets, perfect for baking or frying.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json new file mode 100644 index 0000000000..556444822c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json @@ -0,0 +1,7 @@ +{ + "id": "517", + "sku_id": "517", + "name": "Chicken Wings", + "description": "Flavorful chicken wings, perfect for frying or baking with your favorite sauces.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json new file mode 100644 index 0000000000..a81848c2c8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json @@ -0,0 +1,7 @@ +{ + "id": "518", + "sku_id": "518", + "name": "Pork Chops", + "description": "Juicy pork loin chops, perfect for grilling or sautéing, seasoned to perfection.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json new file mode 100644 index 0000000000..a6680a738a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json @@ -0,0 +1,7 @@ +{ + "id": "519", + "sku_id": "519", + "name": "Duck Breast", + "description": "Succulent duck breast, ideal for gourmet meals, rich in flavor and tender.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json new file mode 100644 index 0000000000..c910604383 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json @@ -0,0 +1,7 @@ +{ + "id": "520", + "sku_id": "520", + "name": "Salami Slices", + "description": "Delicious salami slices, great for sandwiches or snacking on cheese plates.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json new file mode 100644 index 0000000000..cd0e9aa052 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json @@ -0,0 +1,7 @@ +{ + "id": "521", + "sku_id": "521", + "name": "Beef Meatballs", + "description": "Savory beef meatballs, perfect for pasta dishes or as an appetizer.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json new file mode 100644 index 0000000000..1b74b6f93e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json @@ -0,0 +1,7 @@ +{ + "id": "522", + "sku_id": "522", + "name": "Fish Filet (Cod)", + "description": "Fresh cod filets, versatile and mild in flavor, ideal for a variety of recipes.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json new file mode 100644 index 0000000000..3ea87bcfea --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json @@ -0,0 +1,7 @@ +{ + "id": "523", + "sku_id": "523", + "name": "Spicy Chorizo", + "description": "Flavor-packed spicy chorizo sausage, great for tacos, pasta, or breakfast dishes.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json new file mode 100644 index 0000000000..5ef84adb20 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json @@ -0,0 +1,7 @@ +{ + "id": "524", + "sku_id": "524", + "name": "Corned Beef Brisket", + "description": "Tender corned beef brisket, perfect for sandwiches or classic home-cooked meals.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json new file mode 100644 index 0000000000..cdf848f7a5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json @@ -0,0 +1,7 @@ +{ + "id": "525", + "sku_id": "525", + "name": "Sliced Roast Beef", + "description": "Premium sliced roast beef, perfect for sandwiches or as part of a charcuterie spread.", + "department": "meat" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json new file mode 100644 index 0000000000..3b1ff2345a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json @@ -0,0 +1,7 @@ +{ + "id": "601", + "sku_id": "601", + "name": "Ibuprofen 200mg", + "description": "Relieves pain, reduces inflammation, and lowers fever. Over-the-counter pain reliever.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json new file mode 100644 index 0000000000..1b67263192 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json @@ -0,0 +1,7 @@ +{ + "id": "602", + "sku_id": "602", + "name": "Cetirizine 10mg", + "description": "Antihistamine for allergy relief. Helps alleviate symptoms like sneezing and runny nose.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json new file mode 100644 index 0000000000..878de27ad7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json @@ -0,0 +1,7 @@ +{ + "id": "603", + "sku_id": "603", + "name": "Lisinopril 10mg", + "description": "Medication used to treat high blood pressure and heart failure.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json new file mode 100644 index 0000000000..7282b041a8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json @@ -0,0 +1,7 @@ +{ + "id": "604", + "sku_id": "604", + "name": "Metformin 500mg", + "description": "Oral medication for diabetes management, helps control blood sugar levels.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json new file mode 100644 index 0000000000..3399a6b792 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json @@ -0,0 +1,7 @@ +{ + "id": "605", + "sku_id": "605", + "name": "Aspirin 81mg", + "description": "Low-dose aspirin for heart health, helps prevent blood clots.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json new file mode 100644 index 0000000000..4dc7b7e5bc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json @@ -0,0 +1,7 @@ +{ + "id": "606", + "sku_id": "606", + "name": "Amoxicillin 500mg", + "description": "Antibiotic used to treat various infections, including respiratory and skin infections.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json new file mode 100644 index 0000000000..c79909bc83 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json @@ -0,0 +1,7 @@ +{ + "id": "607", + "sku_id": "607", + "name": "Simvastatin 20mg", + "description": "Cholesterol-lowering medication that helps reduce heart disease risk.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json new file mode 100644 index 0000000000..b2c6b0a360 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json @@ -0,0 +1,7 @@ +{ + "id": "608", + "sku_id": "608", + "name": "Pantoprazole 40mg", + "description": "Proton pump inhibitor used to treat gastroesophageal reflux disease (GERD).", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json new file mode 100644 index 0000000000..3f5a654ef1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json @@ -0,0 +1,7 @@ +{ + "id": "609", + "sku_id": "609", + "name": "Levothyroxine 100mcg", + "description": "Thyroid hormone replacement therapy for hypothyroidism.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json new file mode 100644 index 0000000000..5d905183c8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json @@ -0,0 +1,7 @@ +{ + "id": "610", + "sku_id": "610", + "name": "Alprazolam 0.25mg", + "description": "Medication used to treat anxiety and panic disorders.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json new file mode 100644 index 0000000000..1eb4d7f4cf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json @@ -0,0 +1,7 @@ +{ + "id": "611", + "sku_id": "611", + "name": "Omeprazole 20mg", + "description": "Proton pump inhibitor used for treating stomach ulcers and acid reflux.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json new file mode 100644 index 0000000000..cfd52252f8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json @@ -0,0 +1,7 @@ +{ + "id": "612", + "sku_id": "612", + "name": "Hydrochlorothiazide 12.5mg", + "description": "Diuretic used to treat high blood pressure and fluid retention.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json new file mode 100644 index 0000000000..1ba3d39bff --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json @@ -0,0 +1,7 @@ +{ + "id": "613", + "sku_id": "613", + "name": "Zolpidem 10mg", + "description": "Medication for short-term treatment of insomnia.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json new file mode 100644 index 0000000000..41302ac062 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json @@ -0,0 +1,7 @@ +{ + "id": "614", + "sku_id": "614", + "name": "Insulin Glargine 100 units/ml", + "description": "Long-acting insulin for blood sugar control in diabetes.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json new file mode 100644 index 0000000000..345ad2b976 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json @@ -0,0 +1,7 @@ +{ + "id": "615", + "sku_id": "615", + "name": "Dextromethorphan 10mg", + "description": "Cough suppressant effective in treating dry cough.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json new file mode 100644 index 0000000000..8482c3e3d5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json @@ -0,0 +1,7 @@ +{ + "id": "616", + "sku_id": "616", + "name": "Guaifenesin 600mg", + "description": "Expectorant that helps relieve chest congestion by thinning mucus.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json new file mode 100644 index 0000000000..7f9025902b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json @@ -0,0 +1,7 @@ +{ + "id": "617", + "sku_id": "617", + "name": "Naproxen 250mg", + "description": "Nonsteroidal anti-inflammatory drug (NSAID) for pain relief.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json new file mode 100644 index 0000000000..ef2cd1e563 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json @@ -0,0 +1,7 @@ +{ + "id": "618", + "sku_id": "618", + "name": "Clonazepam 0.5mg", + "description": "Medication used to treat seizure disorders and panic disorders.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json new file mode 100644 index 0000000000..e4b3df7772 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json @@ -0,0 +1,7 @@ +{ + "id": "619", + "sku_id": "619", + "name": "Ranitidine 150mg", + "description": "Histamine-2 blocker used to treat heartburn and acid reflux.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json new file mode 100644 index 0000000000..3388c72729 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json @@ -0,0 +1,7 @@ +{ + "id": "620", + "sku_id": "620", + "name": "Montelukast 10mg", + "description": "Medication for asthma and seasonal allergies management.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json new file mode 100644 index 0000000000..5b95fbfaf7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json @@ -0,0 +1,7 @@ +{ + "id": "621", + "sku_id": "621", + "name": "Fexofenadine 180mg", + "description": "Non-drowsy antihistamine for allergy relief.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json new file mode 100644 index 0000000000..731549c119 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json @@ -0,0 +1,7 @@ +{ + "id": "622", + "sku_id": "622", + "name": "Loratadine 10mg", + "description": "Antihistamine used to relieve allergy symptoms without drowsiness.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json new file mode 100644 index 0000000000..52f2d32cb9 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json @@ -0,0 +1,7 @@ +{ + "id": "623", + "sku_id": "623", + "name": "Propranolol 20mg", + "description": "Beta-blocker used to treat high blood pressure and anxiety.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json new file mode 100644 index 0000000000..bf8c990c70 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json @@ -0,0 +1,7 @@ +{ + "id": "624", + "sku_id": "624", + "name": "Levocetirizine 5mg", + "description": "Antihistamine for allergic rhinitis and chronic urticaria (hives).", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json new file mode 100644 index 0000000000..5b5d09c410 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json @@ -0,0 +1,7 @@ +{ + "id": "625", + "sku_id": "625", + "name": "Bupropion 150mg", + "description": "Medication used to treat depression and to help people quit smoking.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json new file mode 100644 index 0000000000..20ee187227 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json @@ -0,0 +1,7 @@ +{ + "id": "701", + "sku_id": "701", + "name": "Organic Gala Apples", + "description": "Fresh organic gala apples, crisp and sweet, perfect for snacks and salads.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json new file mode 100644 index 0000000000..b7aee26faf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json @@ -0,0 +1,7 @@ +{ + "id": "702", + "sku_id": "702", + "name": "Bananas", + "description": "Ripe yellow bananas, high in potassium and perfect for smoothies or on-the-go snacks.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json new file mode 100644 index 0000000000..83e738a9e7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json @@ -0,0 +1,7 @@ +{ + "id": "703", + "sku_id": "703", + "name": "Strawberries", + "description": "Juicy and sweet strawberries, great for desserts or fresh salads.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json new file mode 100644 index 0000000000..76d7cdaf79 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json @@ -0,0 +1,7 @@ +{ + "id": "704", + "sku_id": "704", + "name": "Baby Spinach", + "description": "Fresh baby spinach, perfect for salads, sandwiches, or adding to smoothies.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json new file mode 100644 index 0000000000..fa8b47aa28 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json @@ -0,0 +1,7 @@ +{ + "id": "705", + "sku_id": "705", + "name": "Carrots", + "description": "Crunchy carrots, perfect for snacking or cooking in your favorite dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json new file mode 100644 index 0000000000..c0df37fc02 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json @@ -0,0 +1,7 @@ +{ + "id": "706", + "sku_id": "706", + "name": "Broccoli Florets", + "description": "Fresh broccoli florets, great for steaming or adding to stir-fries.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json new file mode 100644 index 0000000000..def26da89c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json @@ -0,0 +1,7 @@ +{ + "id": "707", + "sku_id": "707", + "name": "Ripe Avocados", + "description": "Creamy avocados, ideal for guacamole, salads, or spreading on toast.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json new file mode 100644 index 0000000000..e1363147ea --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json @@ -0,0 +1,7 @@ +{ + "id": "708", + "sku_id": "708", + "name": "Red Bell Peppers", + "description": "Sweet and crunchy red bell peppers, perfect for salads or grilling.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json new file mode 100644 index 0000000000..3643a0c1dc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json @@ -0,0 +1,7 @@ +{ + "id": "709", + "sku_id": "709", + "name": "Seedless Cucumbers", + "description": "Fresh seedless cucumbers, great for salads, sandwiches, or just snacking.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json new file mode 100644 index 0000000000..466da35f3e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json @@ -0,0 +1,7 @@ +{ + "id": "710", + "sku_id": "710", + "name": "Fresh Basil", + "description": "Aromatic fresh basil, perfect for garnishing or adding flavor to dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json new file mode 100644 index 0000000000..61b829b914 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json @@ -0,0 +1,7 @@ +{ + "id": "711", + "sku_id": "711", + "name": "Green Grapes", + "description": "Sweet and juicy green grapes, great for snacking or adding to fruit salads.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json new file mode 100644 index 0000000000..866b0915b3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json @@ -0,0 +1,7 @@ +{ + "id": "712", + "sku_id": "712", + "name": "Pineapple", + "description": "Fresh pineapple, tropical and sweet, ideal for fresh-cut fruit or smoothies.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json new file mode 100644 index 0000000000..8c151aee8f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json @@ -0,0 +1,7 @@ +{ + "id": "713", + "sku_id": "713", + "name": "Lemons", + "description": "Fresh lemons, perfect for lemonade, cooking, or flavoring drinks.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json new file mode 100644 index 0000000000..39215a7710 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json @@ -0,0 +1,7 @@ +{ + "id": "714", + "sku_id": "714", + "name": "Zucchini", + "description": "Tender zucchini, versatile for grilling, baking, and stir-frying.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json new file mode 100644 index 0000000000..46b1e14840 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json @@ -0,0 +1,7 @@ +{ + "id": "715", + "sku_id": "715", + "name": "Red Potatoes", + "description": "Nutritious red potatoes, great for baking, boiling, or roasting.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json new file mode 100644 index 0000000000..e53c9733cd --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json @@ -0,0 +1,7 @@ +{ + "id": "716", + "sku_id": "716", + "name": "Sweet Potatoes", + "description": "Delicious sweet potatoes, perfect for baking or mashing.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json new file mode 100644 index 0000000000..ab48ac1c6f --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json @@ -0,0 +1,7 @@ +{ + "id": "717", + "sku_id": "717", + "name": "Cauliflower", + "description": "Fresh cauliflower, perfect for roasting or using in low-carb dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json new file mode 100644 index 0000000000..42cba51bd7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json @@ -0,0 +1,7 @@ +{ + "id": "718", + "sku_id": "718", + "name": "Green Beans", + "description": "Crispy green beans, great for sautéing or enjoying as a side dish.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json new file mode 100644 index 0000000000..4d035df9a4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json @@ -0,0 +1,7 @@ +{ + "id": "719", + "sku_id": "719", + "name": "Kale", + "description": "Nutritious kale, perfect for salads or smoothies packed with vitamins.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json new file mode 100644 index 0000000000..c81e7d0ade --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json @@ -0,0 +1,7 @@ +{ + "id": "720", + "sku_id": "720", + "name": "Onions", + "description": "Fresh onions, essential for cooking and adding flavor to many dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json new file mode 100644 index 0000000000..86e1ab11c8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json @@ -0,0 +1,7 @@ +{ + "id": "721", + "sku_id": "721", + "name": "Garlic", + "description": "Fresh garlic, a must-have for enhancing the flavor of your meals.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json new file mode 100644 index 0000000000..6d4dc5fe99 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json @@ -0,0 +1,7 @@ +{ + "id": "722", + "sku_id": "722", + "name": "Mangoes", + "description": "Juicy mangoes, sweet and tropical, great for snacking or smoothies.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json new file mode 100644 index 0000000000..06f2691bb8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json @@ -0,0 +1,7 @@ +{ + "id": "723", + "sku_id": "723", + "name": "Cherries", + "description": "Sweet cherries, perfect for desserts or eating fresh.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json new file mode 100644 index 0000000000..ebcba25b10 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json @@ -0,0 +1,7 @@ +{ + "id": "724", + "sku_id": "724", + "name": "Raspberries", + "description": "Fresh raspberries, sweet and tart, ideal for snacking or baking.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json new file mode 100644 index 0000000000..a2a420db93 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json @@ -0,0 +1,7 @@ +{ + "id": "725", + "sku_id": "725", + "name": "Blackberries", + "description": "Juicy blackberries, perfect for adding to desserts or enjoying fresh.", + "department": "produce" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json new file mode 100644 index 0000000000..47562d3999 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json @@ -0,0 +1,7 @@ +{ + "id": "801", + "sku_id": "801", + "name": "Wild Caught Salmon Fillet", + "description": "Delicious and healthy wild caught salmon fillet, rich in omega-3 fatty acids. Perfect for grilling or baking.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json new file mode 100644 index 0000000000..3938bd8d53 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json @@ -0,0 +1,7 @@ +{ + "id": "802", + "sku_id": "802", + "name": "Shrimp Cocktail", + "description": "Fresh shrimp served chilled with a side of tangy cocktail sauce. A perfect appetizer for any gathering.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json new file mode 100644 index 0000000000..97cbb2a687 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json @@ -0,0 +1,7 @@ +{ + "id": "803", + "sku_id": "803", + "name": "Fresh Atlantic Cod", + "description": "Mild and flaky Atlantic cod, great for frying or baking. Sustainably sourced and always fresh.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json new file mode 100644 index 0000000000..5e80d88759 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json @@ -0,0 +1,7 @@ +{ + "id": "804", + "sku_id": "804", + "name": "Seared Ahi Tuna Steaks", + "description": "Premium ahi tuna steaks, perfect for searing or sushi. A must-try for tuna lovers.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json new file mode 100644 index 0000000000..9991f8a812 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json @@ -0,0 +1,7 @@ +{ + "id": "805", + "sku_id": "805", + "name": "Maine Lobster Tails", + "description": "Caught in the cool waters of Maine, these lobster tails are sweet, succulent, and perfect for a special dinner.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json new file mode 100644 index 0000000000..ba38374ac3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json @@ -0,0 +1,7 @@ +{ + "id": "806", + "sku_id": "806", + "name": "Sea Bass Fillet", + "description": "Fresh sea bass fillet, known for its delicate texture and mild flavor. Ideal for grilling or pan-searing.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json new file mode 100644 index 0000000000..cd1d7bfc6b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json @@ -0,0 +1,7 @@ +{ + "id": "807", + "sku_id": "807", + "name": "Pacific Mackerel", + "description": "Rich in flavor and healthy fats, Pacific mackerel is perfect for grilling or smoking.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json new file mode 100644 index 0000000000..e8faf12c59 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json @@ -0,0 +1,7 @@ +{ + "id": "808", + "sku_id": "808", + "name": "Organic Blue Crab Meat", + "description": "Sweet and tender organic blue crab meat, perfect for crab cakes or pasta dishes.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json new file mode 100644 index 0000000000..34e4694ecc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json @@ -0,0 +1,7 @@ +{ + "id": "809", + "sku_id": "809", + "name": "Frozen Shrimp (31/40 Count)", + "description": "Frozen, easy-to-peel shrimp, perfect for stir-frys, pasta, or shrimp tacos.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json new file mode 100644 index 0000000000..59fab4aac7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json @@ -0,0 +1,7 @@ +{ + "id": "810", + "sku_id": "810", + "name": "Smoked Salmon Lox", + "description": "Delicious smoked salmon lox, great for bagels, salads, or gourmet dishes.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json new file mode 100644 index 0000000000..35d42c436e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json @@ -0,0 +1,7 @@ +{ + "id": "811", + "sku_id": "811", + "name": "Seafood Medley", + "description": "A delightful mix of shrimp, scallops, and calamari, ideal for pasta, stir-fry, or seafood boils.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json new file mode 100644 index 0000000000..63194b1769 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json @@ -0,0 +1,7 @@ +{ + "id": "812", + "sku_id": "812", + "name": "Fresh Clams (Diners Choice)", + "description": "Select fresh clams, perfect for steaming or in chowders. Freshly harvested from local waters.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json new file mode 100644 index 0000000000..25c63638a4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json @@ -0,0 +1,7 @@ +{ + "id": "813", + "sku_id": "813", + "name": "Scallops - Jumbo", + "description": "Sweet and tender jumbo scallops, great for grilling or broiling. A true delicacy for seafood lovers.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json new file mode 100644 index 0000000000..91cfdb2fa5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json @@ -0,0 +1,7 @@ +{ + "id": "814", + "sku_id": "814", + "name": "Canned Tuna (Chunk Light)", + "description": "Canned chunk light tuna in water, perfect for salads, sandwiches, and casseroles.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json new file mode 100644 index 0000000000..1d9617747c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json @@ -0,0 +1,7 @@ +{ + "id": "815", + "sku_id": "815", + "name": "Whole Fresh Fish (Snapper)", + "description": "Fresh snapper fish, perfect for grilling whole or filleting. Sustainably caught for great quality.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json new file mode 100644 index 0000000000..61a0b1b5e8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json @@ -0,0 +1,7 @@ +{ + "id": "816", + "sku_id": "816", + "name": "Marinated Anchovies", + "description": "Savory marinated anchovies, great as a topping for salads or as a snack. Rich in protein and flavor.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json new file mode 100644 index 0000000000..e2edb4f2e0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json @@ -0,0 +1,7 @@ +{ + "id": "817", + "sku_id": "817", + "name": "Oysters (Live)", + "description": "Fresh live oysters from the coast, perfect for shucking and enjoying raw or grilled.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json new file mode 100644 index 0000000000..6a14719bde --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json @@ -0,0 +1,7 @@ +{ + "id": "818", + "sku_id": "818", + "name": "Fish Sauce", + "description": "Authentic fish sauce made from fermented fish, essential for Vietnamese and Thai cooking.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json new file mode 100644 index 0000000000..5b2f12d424 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json @@ -0,0 +1,7 @@ +{ + "id": "819", + "sku_id": "819", + "name": "Crab Legs (King)", + "description": "Freshly frozen king crab legs, sweet and succulent, perfect for special occasions.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json new file mode 100644 index 0000000000..e06a342480 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json @@ -0,0 +1,7 @@ +{ + "id": "820", + "sku_id": "820", + "name": "Sushi Grade Salmon", + "description": "High-quality sushi grade salmon, perfect for sashimi or making sushi rolls.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json new file mode 100644 index 0000000000..8c41c284ab --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json @@ -0,0 +1,7 @@ +{ + "id": "821", + "sku_id": "821", + "name": "Smoked Whitefish Salad", + "description": "Creamy smoked whitefish salad, perfect for spreading on crackers or bagels. A delicious snack or appetizer.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json new file mode 100644 index 0000000000..79e42b761b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json @@ -0,0 +1,7 @@ +{ + "id": "822", + "sku_id": "822", + "name": "Fish Tacos Kit", + "description": "Everything you need to make delicious fish tacos, including fresh tortillas, seasoned fish, and toppings.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json new file mode 100644 index 0000000000..8075ad715d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json @@ -0,0 +1,7 @@ +{ + "id": "823", + "sku_id": "823", + "name": "Tuna Poke Bowl Kit", + "description": "A DIY poke bowl kit with sushi-grade tuna, rice, and authentic toppings for a fresh meal.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json new file mode 100644 index 0000000000..b233fc7005 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json @@ -0,0 +1,7 @@ +{ + "id": "824", + "sku_id": "824", + "name": "Sardines (Canned in Olive Oil)", + "description": "Canned sardines in extra virgin olive oil, perfect for salads, pastas, or as a healthy snack.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json new file mode 100644 index 0000000000..c317fddc49 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json @@ -0,0 +1,7 @@ +{ + "id": "825", + "sku_id": "825", + "name": "Fish Stock", + "description": "Rich and flavorful fish stock, perfect for soups and sauces that require a seafood base.", + "department": "seafood" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema new file mode 100644 index 0000000000..7d6ae599b7 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} + \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema new file mode 100644 index 0000000000..0fe6c5999a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema @@ -0,0 +1,24 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "sku_id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + } + }, + "required": ["id", "sku_id", "name", "description", "department"], + "additionalProperties": false + } + \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json new file mode 100644 index 0000000000..99838a27a3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json @@ -0,0 +1,9 @@ +{ + "id": "1000", + "receipt_id": "1000", + "transaction_date": "2025-04-01 10:30:00", + "customer_id": "50001", + "items": [ + {"sku_id": "101", "units": 0.0, "unit_price": 0.00, "discounts": 0.00} + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json new file mode 100644 index 0000000000..a2c5ef6ffa --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json @@ -0,0 +1,9 @@ +{ + "id": "1001", + "receipt_id": "1001", + "transaction_date": "2025-04-02 08:30:00", + "customer_id": "50001", + "items": [ + {"sku_id": "201", "units": 5.0, "unit_price": 9.99, "discounts": 0.00} + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json new file mode 100644 index 0000000000..10ec3ace73 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json @@ -0,0 +1,9 @@ +{ + "id": "1002", + "receipt_id": "1002", + "transaction_date": "2025-04-02 10:30:08", + "customer_id": "50001", + "items": [ + {"sku_id": "301", "units": 3.0, "unit_price": 9.99, "discounts": 0.00} + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema new file mode 100644 index 0000000000..1dc805ee1b --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Purchases Identifier Key", + "description": "A unique identifier for the purchase transaction", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema new file mode 100644 index 0000000000..a25b1a5160 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema @@ -0,0 +1,63 @@ +{ + "title": "Purchase Transaction Record Value", + "description": "Schema for a transaction record containing receipt information, transaction date, and purchased items.", + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Unique identifier for the transaction record." + }, + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the purchase." + }, + "items": { + "type": "array", + "description": "List of items included in the transaction.", + "items": { + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "description": "SKU identifier for the purchased item." + }, + "units": { + "type": "number", + "description": "Number of units purchased." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the item." + }, + "discounts": { + "type": "number", + "description": "Total discounts applied to the item." + } + }, + "required": [ + "sku_id", + "units", + "unit_price", + "discounts" + ] + } + } + }, + "required": [ + "id", + "receipt_id", + "transaction_date", + "items", + "customer_id" + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema new file mode 100644 index 0000000000..b172353823 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema @@ -0,0 +1,5 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema new file mode 100644 index 0000000000..ecbb8c3758 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema @@ -0,0 +1,45 @@ +{ + "title": "Purchase Transactions", + "description": "Flattened Table for all purchases", + "type": "object", + "properties": { + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the purchase." + }, + "sku_id": { + "type": "string", + "description": "SKU identifier for the purchased item." + }, + "units": { + "type": "number", + "description": "Number of units purchased." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the item." + }, + "discounts": { + "type": "number", + "description": "Total discounts applied to the item." + } + }, + "required": [ + "receipt_id", + "transaction_date", + "customer_id", + "sku_id", + "units", + "unit_price", + "discounts" + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json new file mode 100644 index 0000000000..ccd800dcd0 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json @@ -0,0 +1,8 @@ +{ + "id": "3000", + "replenishment_id": "3000", + "transaction_date": "2025-03-31 20:30:00", + "sku_id": "101", + "units": 300.0, + "vendor_id": "30001" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema new file mode 100644 index 0000000000..6a2e0dddcc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Replenishment Identifier Key", + "description": "A unique identifier for the replenishment transaction", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema new file mode 100644 index 0000000000..9386ad46fc --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema @@ -0,0 +1,65 @@ +{ + "title": "ReplenishmentTransaction", + "description": "Schema for a replenishment transaction including ID, transaction date, SKU ID, and units replenished.", + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Unique identifier for the replenishment transaction." + }, + "replenishment_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier linking to the replenishment event." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in YYYY-MM-DD HH:MM:SS format." + }, + "sku_id": { + "type": "string", + "description": "Stock keeping unit (SKU) identifier for the replenished product." + }, + "units": { + "type": "number", + "description": "Number of units replenished during the transaction." + }, + "vendor_id": { + "type": "string", + "description": "Unique identifier for the vendor supplying the product." + }, + "_attachments": { + "type": "string", + "description": "A link to the documents attachments (e.g., media, binary data) if any exist. In most cases, it will just be an empty string unless you actually upload attachments." + }, + "_etag": { + "type": "string", + "description": "The entity tag for optimistic concurrency control. It changes every time the document is updated. Cosmos DB uses it to check if the document has changed since a client last read it." + }, + "_lsn": { + "type": "number", + "description": "Logical Sequence Number. It represents the order in which operations (insert/update/delete) were performed. Used internally for replication and change feed processing." + }, + "_rid": { + "type": "string", + "description": "The resource ID of the document — a unique, internal identifier that Cosmos DB uses to find the document quickly inside its physical storage" + }, + "_self": { + "type": "string", + "description": "A URI path to the document within the Cosmos DB REST API. You can use it to directly operate (read/update/delete) on the document via the API." + }, + "_ts": { + "type": "number", + "description": "The timestamp (in UNIX epoch seconds) of when the document was last modified" + } + }, + "required": [ + "id", + "replenishment_id", + "transaction_date", + "sku_id", + "units", + "vendor_id" + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema new file mode 100644 index 0000000000..b172353823 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema @@ -0,0 +1,5 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema new file mode 100644 index 0000000000..2e5d616a4e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema @@ -0,0 +1,35 @@ +{ + "title": "Return Transactions", + "description": "Flattened Table for all returns", + "type": "object", + "properties": { + "replenishment_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "vendor_id": { + "type": "string", + "description": "Unique identifier for the customer making the return." + }, + "sku_id": { + "type": "string", + "description": "SKU identifier for the returned item." + }, + "units": { + "type": "number", + "description": "Number of units returns." + } + }, + "required": [ + "replenishment_id", + "transaction_date", + "vendor_id", + "sku_id", + "units" + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json new file mode 100644 index 0000000000..fd1cb70752 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json @@ -0,0 +1,12 @@ +{ + "id": "2000", + "return_id": "2000", + "receipt_id": "1000", + "transaction_date": "2025-04-02 10:30:00", + "customer_id": "50001", + "items": [ + {"sku_id": "101", "units": 1.0, "unit_price": 9.99}, + {"sku_id": "201", "units": 1.0, "unit_price": 9.99}, + {"sku_id": "301", "units": 1.0, "unit_price": 9.99} + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema new file mode 100644 index 0000000000..66c44a88c6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Returns Transaction Identifier Key", + "description": "A unique identifier for the returns transaction", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema new file mode 100644 index 0000000000..70f4954615 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema @@ -0,0 +1,66 @@ +{ + "title": "Return Transaction Record Value", + "description": "Schema for a return transaction record, including return ID, receipt ID, transaction date, and a list of returned items.", + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Unique identifier for the return transaction." + }, + "return_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier for the return associated with the transaction." + }, + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier of the original receipt linked to the return." + }, + "transaction_date": { + "type": "string", + "format": "date-time", + "description": "Timestamp of when the return transaction occurred, in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the return." + }, + "items": { + "type": "array", + "description": "List of returned items in the transaction.", + "items": { + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "SKU identifier for the returned item." + }, + "units": { + "type": "number", + "description": "Number of units returned." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the returned item." + } + }, + "required": [ + "sku_id", + "units", + "unit_price" + ] + } + } + }, + "required": [ + "id", + "return_id", + "receipt_id", + "transaction_date", + "items", + "customer_id" + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema new file mode 100644 index 0000000000..b172353823 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema @@ -0,0 +1,5 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema new file mode 100644 index 0000000000..dabf42f1c3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema @@ -0,0 +1,41 @@ +{ + "title": "Return Transactions", + "description": "Flattened Table for all returns", + "type": "object", + "properties": { + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the return." + }, + "sku_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "SKU identifier for the returned item." + }, + "units": { + "type": "number", + "description": "Number of units returns." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the item." + } + }, + "required": [ + "receipt_id", + "transaction_date", + "customer_id", + "sku_id", + "units", + "unit_price" + ] +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md b/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md new file mode 100644 index 0000000000..295889f2d1 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md @@ -0,0 +1,125 @@ +# Azure Resource Provisioning + +This guide shows you how to set up the Azure Resources using Terraform + +### 1. **Install Terraform** + +- If you haven’t installed Terraform yet, install it: + + ```bash + # (on MacOS with Homebrew) + + # Configure connection to the repo + brew tap hashicorp/tap + + # Install the latest version of Terraform CLi + brew install hashicorp/tap/terraform + + ``` + or + [Download Terraform manually](https://developer.hashicorp.com/terraform/downloads). + +--- + +### 2. **Authenticate to Azure** + +You must be logged into Azure so Terraform can create the resources for you. + +Run: + +```bash + +az login + +``` +- This will open a browser to authenticate. +- If you have multiple Azure subscriptions, you might also need: + + ```bash + # Display your Azure Subscriptions + az account list + + # Specify the Azure Subscription you are using for the Automation + az account set --subscription "your-subscription-id" + + # Specifiy the Subscription in the Environment Variable for Terraform + ARM_SUBSCRIPTION_ID="your-subscription-id" + ``` + +--- + +### 3. **Initialize Terraform** + +Inside the folder where you have your `main.tf`: + +```bash + +terraform init + +``` +- This downloads the **Azure Provider** and sets up your working directory. + +--- + +### 4. **(Optional) Review What Terraform Will Do** + +See what Terraform *plans* to create: + +```bash + +terraform plan + +``` +- It checks your script and shows you exactly what it will create **without** making changes yet. +- Always a good practice before applying. + +--- + +### 5. **Apply Terraform to Create Resources** + +Now **provision** the resources: + +```bash + +terraform apply + +``` + +- Terraform will show you a detailed list of all resources it will create. +- Type **`yes`** when prompted to approve. + +🌟 After a few minutes, Cosmos DB, Azure AI Search, Storage Account, and Redis Cache will be created in your Azure account! + +--- + +### 6. **Outputs** + +If you included the `output` blocks (like I did in the Terraform file earlier), after `apply`, Terraform will print the important connection details: + +✅ Cosmos DB endpoint +✅ Redis hostname and access key +✅ Azure Search keys + +You can copy this and keep them save for later. These will be needed to provision the Confluent Cloud Resources. + +--- + +### Quick Recap +| Step | Command | +|-------------------|-------------------------------------------| +| Authenticate to Azure | `az login` | +| Initialize Terraform | `terraform init` | +| Plan (Preview) | `terraform plan` | +| Apply (Provision) | `terraform apply` | + +--- + +### **Destroy the resources when you are done ** +If you ever want to delete everything created by the script: + +```bash +terraform destroy +``` +(Also prompts you for confirmation.) + +--- \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh new file mode 100644 index 0000000000..8cf09fe05a --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +API_KEY="GXBNXDHDJ3PQK2ZT" +API_SECRET="GApDfNmd09jMAFzdwedbUZWI3FNM6aOTWe95H0gkN1bXpJuEYsin2hs09jTZne9u" + +# export KAFKA_CLUSTER_ID="lkc-vvwyq0" +# export KAFKA_API_KEY="GXBNXDHDJ3PQK2ZT" +# export KAFKA_API_SECRET="GApDfNmd09jMAFzdwedbUZWI3FNM6aOTWe95H0gkN1bXpJuEYsin2hs09jTZne9u" + +curl -u "${API_KEY}:${API_SECRET}" \ + https://api.confluent.cloud/connect/v1/environments diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh new file mode 100644 index 0000000000..c88ae25860 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Generate a local env.sh file from terraform output + +# Exit immediately if a command exits with a non-zero status +set -e + +# Where to output the env file +ENV_FILE="./azure_environment_variables.sh" + +# Generate the env.sh file +echo "#!/bin/bash" > "$ENV_FILE" +echo "" >> "$ENV_FILE" + +# Read outputs and write them as export statements + +echo "# Azure Resource Group for Resources" >> "$ENV_FILE" +terraform output -raw resource_group_name | awk '{print "export AZURE_RESOURCE_GROUP=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +echo "# Azure Cosmos DB Credentials" >> "$ENV_FILE" +terraform output -raw cosmosdb_account_name | awk '{print "export AZURE_COSMOS_DB_ACCOUNT_NAME=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw cosmosdb_primary_key | awk '{print "export AZURE_COSMOS_DB_ACCOUNT_KEY=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw cosmosdb_database_name | awk '{print "export AZURE_COSMOS_DB_DATABASE_NAME=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +echo "# Azure AI Search Credentials" >> "$ENV_FILE" +terraform output -raw search_service_name | awk '{print "export AZURE_SEARCH_SERVICE_NAME=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw azure_search_admin_key | awk '{print "export AZURE_SEARCH_API_KEY=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +#echo "# Azure Redis Cache Credentials" >> "$ENV_FILE" +#terraform output -raw redis_hostname | awk '{print "export REDIS_HOSTNAME=\"" $0 "\""}' >> "$ENV_FILE" +#terraform output -raw redis_primary_access_key | awk '{print "export REDIS_PRIMARY_ACCESS_KEY=\"" $0 "\""}' >> "$ENV_FILE" +#echo "" >> "$ENV_FILE" + +echo "✅ Environment file generated: $ENV_FILE" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf new file mode 100644 index 0000000000..5947bcf9b8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf @@ -0,0 +1,136 @@ + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.37.0" + } + + confluent = { + source = "confluentinc/confluent" + version = "2.35.0" + } + + random = { + source = "hashicorp/random" + version = "3.7.2" + } + } + + required_version = ">= 1.12.2" +} + +provider "random" { + # Random provider configuration + # This can be left empty or configured as needed +} + +provider "azurerm" { + features {} + subscription_id = var.azure_subscription_id + storage_use_azuread = true +} + +provider "confluent" { + kafka_id = var.kafka_id # optionally use KAFKA_ID env var + kafka_rest_endpoint = var.kafka_rest_endpoint # optionally use KAFKA_REST_ENDPOINT env var + kafka_api_key = var.kafka_api_key # optionally use KAFKA_API_KEY env var + kafka_api_secret = var.kafka_api_secret # optionally use KAFKA_API_SECRET env var + + flink_api_key = var.flink_api_key # optionally use FLINK_API_KEY env var + flink_api_secret = var.flink_api_secret # optionally use FLINK_API_SECRET env var + flink_rest_endpoint = var.flink_rest_endpoint # optionally use FLINK_REST_ENDPOINT env var + flink_compute_pool_id = var.flink_compute_pool_id # optionally use FLINK_COMPUTE_POOL_ID env var + flink_principal_id = var.flink_principal_id # optionally use FLINK_PRINCIPAL_ID + organization_id = var.confluent_organization_id # optionally use ORGANIZATION_ID env var + environment_id = var.confluent_environment_id # optionally use ENVIRONMENT_ID env var + + schema_registry_id = var.schema_registry_id # optionally use SCHEMA_REGISTRY_ID env var + schema_registry_rest_endpoint = var.schema_registry_rest_endpoint # optionally use SCHEMA_REGISTRY_REST_ENDPOINT env var + schema_registry_api_key = var.schema_registry_api_key # optionally use SCHEMA_REGISTRY_API_KEY env var + schema_registry_api_secret = var.schema_registry_api_secret # optionally use SCHEMA_REGISTRY_API_SECRET env var + + # Confluent Cloud API (for managing connectors and environments) + cloud_api_key = var.cloud_api_key + cloud_api_secret = var.cloud_api_secret +} + +# New variables for merged changes +variable "cloud_api_key" { type = string } +variable "cloud_api_secret" { type = string } + +# ----------------- +# Core Confluent IDs / Endpoints +# ----------------- +variable "kafka_id" { type = string } +variable "kafka_rest_endpoint" { type = string } +variable "kafka_api_key" { type = string } +variable "kafka_api_secret" { type = string } +variable "flink_api_key" { type = string } +variable "flink_api_secret" { type = string } +variable "flink_rest_endpoint" { type = string } +variable "flink_compute_pool_id" { type = string } +variable "flink_principal_id" { type = string } +variable "confluent_organization_id" { type = string } +variable "confluent_environment_id" { type = string } +variable "schema_registry_id" { type = string } +variable "schema_registry_rest_endpoint" { type = string } +variable "schema_registry_api_key" { type = string } +variable "schema_registry_api_secret" { type = string } +variable "name_prefix" { + description = "Prefix for all resource names" + type = string + + validation { + condition = length(var.name_prefix) <= 6 && can(regex("^[a-z0-9]+$", var.name_prefix)) + error_message = "The name_prefix must be 6 characters or fewer and contain only lowercase letters (a-z) or numbers (0-9)." + } +} + +# ----------------- +# Azure variables +# ----------------- +variable "resource_group_location" { + type = string + default = "eastus2" +} +variable "azure_subscription_id" { type = string } + +/* +# Service Principal (for Azure Search connector) - supply if using AI Search connectors +variable "service_principal_tenant_id" { type = string } +variable "service_principal_subscription_id" { type = string } +variable "service_principal_client_id" { type = string } +variable "service_principal_client_secret" { type = string } +*/ + + +# ----------------- +# Kafka topic configuration +# ----------------- +variable "kafka_partitions_count" { + type = number + default = 6 +} + +# ----------------- +# Connector Maps +# ----------------- +variable "cosmos_db_connectors" { + description = "Cosmos DB source connectors map" + type = map(object({ + name = string + topic = string + })) + default = {} +} + +variable "ai_search_connectors" { + description = "Azure AI Search sink connectors map" + type = map(object({ + name = string + topic = string + index = string + })) + default = {} +} diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf new file mode 100644 index 0000000000..0c8cc8c6ed --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf @@ -0,0 +1,166 @@ +# Resource Group +resource "azurerm_resource_group" "main" { + name = "${var.name_prefix}-confluentwth-rg" + location = var.resource_group_location +} + +# Azure AI Search Instance +# New changes to the Azure Search Service API require the use of +# `local_authentication_enabled` and `authentication_failure_mode` properties. +# These properties are required to enable local authentication and set the failure mode. +# The `public_network_access_enabled` property is also set to true to allow public access. +# https://learn.microsoft.com/en-us/azure/search/search-security-enable-roles?tabs=config-svc-rest%2Cdisable-keys-cli +# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/search_service +resource "azurerm_search_service" "search" { + name = "${var.name_prefix}-search" + resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.main.location + sku = "standard" + partition_count = 1 + replica_count = 1 + local_authentication_enabled = true + authentication_failure_mode = "http403" + public_network_access_enabled = true +} + +# Azure Cosmos DB (SQL API) +resource "azurerm_cosmosdb_account" "cosmosdb" { + name = "${var.name_prefix}cosmos" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + offer_type = "Standard" + kind = "GlobalDocumentDB" + public_network_access_enabled = true + local_authentication_disabled = false + + + consistency_policy { + consistency_level = "Strong" + } + + geo_location { + location = azurerm_resource_group.main.location + failover_priority = 0 + } +} + +# Cosmos DB SQL Database +resource "azurerm_cosmosdb_sql_database" "retailstore" { + name = "retailstore" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + + throughput = 400 # Provisioned throughput at the database level (optional if you want) +} + +# Purchases Container +resource "azurerm_cosmosdb_sql_container" "purchases" { + name = "purchases" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/customer_id"] + throughput = 400 # optional: you can set throughput here too, or rely on database throughput +} + +# Returns Container +resource "azurerm_cosmosdb_sql_container" "returns" { + name = "returns" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/customer_id"] + throughput = 400 +} + +# Replenishments Container +resource "azurerm_cosmosdb_sql_container" "replenishments" { + name = "replenishments" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/vendor_id"] + throughput = 400 +} + +# Departments Container +resource "azurerm_cosmosdb_sql_container" "departments" { + name = "departments" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/department"] + throughput = 400 +} + +# Product Pricing Container +resource "azurerm_cosmosdb_sql_container" "product_pricing" { + name = "product_pricing" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/sku_id"] + throughput = 400 +} + +# Product SKUs Container +resource "azurerm_cosmosdb_sql_container" "product_skus" { + name = "product_skus" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/sku_id"] + throughput = 400 +} + +# Azure Redis Cache +resource "azurerm_redis_cache" "redis" { + name = "${var.name_prefix}redis" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + capacity = 1 + family = "C" + sku_name = "Standard" + non_ssl_port_enabled = false + minimum_tls_version = "1.2" + public_network_access_enabled = true + redis_version = "6" + shard_count = 0 + + redis_configuration { + active_directory_authentication_enabled = true + aof_backup_enabled = false + authentication_enabled = true + maxfragmentationmemory_reserved = 125 + maxmemory_delta = 125 + maxmemory_reserved = 125 + notify_keyspace_events = "" + } +} + +# Azure AI Services (AI Foundry) +resource "azurerm_ai_services" "ai_services" { + name = "${var.name_prefix}aiservices" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + sku_name = "S0" + custom_subdomain_name = "${var.name_prefix}models" + + local_authentication_enabled = true + public_network_access = "Enabled" + outbound_network_access_restricted = false + + identity { + type = "SystemAssigned" + } + + network_acls { + default_action = "Allow" + } +} \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf new file mode 100644 index 0000000000..95348229c6 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf @@ -0,0 +1,204 @@ + +# Define a list of Kafka topic names +locals { + kafka_topic_names = [ + "departments", + "departments_flat", + "product_pricing", + "product_skus", + "purchases", + "replenishments", + "returns", + "net_sales", # need to drop this because we now use net_sales_depot + "product_inventory" # need to drop this because we now use product_inventory_depot + ] + + kafka_topic_key_names = [ + "purchases", + "replenishments", + "returns", + "net_sales", # need to drop this because we now use net_sales_depot + "product_inventory" # need to drop this because we now use product_inventory_depot + ] +} + +# New variables for service account auth and Cosmos DB sink connectors +variable "kafka_service_account_id" { + description = "Kafka Service Account ID for connector authentication" + type = string +} + +#variable "cosmos_db_sink_connectors" { +# description = "Map of Cosmos DB sink connectors configuration" +# type = map(object({ +# name = string +# topic = string +# container_mapping = string +# })) +#} + +resource "confluent_schema_registry_cluster_config" "microsoft_hackathon" { + compatibility_level = "NONE" + + lifecycle { + prevent_destroy = false + } +} + +# Create the Retail Store Kafka Topics +resource "confluent_kafka_topic" "topics" { + for_each = toset(local.kafka_topic_names) + topic_name = each.value + partitions_count = var.kafka_partitions_count + + depends_on = [ + confluent_schema_registry_cluster_config.microsoft_hackathon + ] + + lifecycle { + prevent_destroy = false + } +} + +# Create the Schema Registry Entries for each Topic Key +resource "confluent_schema" "key_schemas" { + for_each = toset(local.kafka_topic_key_names) + subject_name = "${each.value}-key" + format = "JSON" + schema = file("../retail_store/${each.value}/schemas/${each.value}-key.schema") + hard_delete = true # Optional: Set to true if you want to hard delete the schema + + depends_on = [ confluent_schema_registry_cluster_config.microsoft_hackathon ] +} + +# Create the Schema Registry Entries for each Topic Value +resource "confluent_schema" "value_schemas" { + for_each = toset(local.kafka_topic_names) + subject_name = "${each.value}-value" + format = "JSON" + schema = file("../retail_store/${each.value}/schemas/${each.value}-value.schema") + hard_delete = true # Optional: Set to true if you want to hard delete the schema + depends_on = [ confluent_schema_registry_cluster_config.microsoft_hackathon ] +} + +# Create the Source Connectors for Azure Cosmos DB +resource "confluent_connector" "cosmos_db_connectors" { + for_each = var.cosmos_db_connectors + + environment { + id = var.confluent_environment_id + } + + kafka_cluster { + id = var.kafka_id + } + + config_sensitive = { + # Using master key as sensitive (if source connector requires writes for offset mgmt) + "connect.cosmos.master.key" = azurerm_cosmosdb_account.cosmosdb.primary_key + } + + config_nonsensitive = { + "connect.cosmos.connection.endpoint" = "https://${azurerm_cosmosdb_account.cosmosdb.name}.documents.azure.com:443/" + "connect.cosmos.databasename" = azurerm_cosmosdb_sql_database.retailstore.name + "connector.class" = "CosmosDbSource" + "name" = each.value.name + "schema.context.name" = "default" + "kafka.auth.mode" = "SERVICE_ACCOUNT" + "kafka.service.account.id" = var.kafka_service_account_id + "connect.cosmos.containers.topicmap" = each.value.topic + "connect.cosmos.task.timeout" = "5000" + "connect.cosmos.task.buffer.size" = "10000" + "connect.cosmos.task.batch.size" = "100" + "connect.cosmos.task.poll.interval" = "1000" + "output.data.format" = "JSON_SR" + "connect.cosmos.messagekey.enabled" = "true" + "connect.cosmos.messagekey.field" = "id" + "tasks.max" = "1" + "auto.restart.on.user.error" = "true" + "value.converter.decimal.format" = "BASE64" + "value.converter.reference.subject.name.strategy" = "DefaultReferenceSubjectNameStrategy" + "value.converter.value.subject.name.strategy" = "TopicNameStrategy" + "key.converter.key.subject.name.strategy" = "TopicNameStrategy" + } + + depends_on = [ + azurerm_cosmosdb_account.cosmosdb, + azurerm_cosmosdb_sql_database.retailstore, + azurerm_cosmosdb_sql_container.purchases, + azurerm_cosmosdb_sql_container.returns, + azurerm_cosmosdb_sql_container.replenishments, + azurerm_cosmosdb_sql_container.departments, + azurerm_cosmosdb_sql_container.product_pricing, + azurerm_cosmosdb_sql_container.product_skus, + confluent_kafka_topic.topics, + confluent_schema.key_schemas, + confluent_schema.value_schemas + ] + + lifecycle { + prevent_destroy = false + } +} + +# Create the Source Connectors for Azure AI Search +resource "confluent_connector" "ai_search_connectors" { + for_each = var.ai_search_connectors + + environment { + id = var.confluent_environment_id + } + + kafka_cluster { + id = var.kafka_id + } + + config_sensitive = { + # API key for Azure Search and client secret treated as sensitive + "azure.search.api.key" = azurerm_search_service.search.primary_key + "azure.search.client.secret" = var.service_principal_client_secret + } + + config_nonsensitive = { + "azure.search.resourcegroup.name" = var.resource_group_name + "azure.search.service.name" = azurerm_search_service.search.name + "azure.search.tenant.id" = var.service_principal_tenant_id + "azure.search.subscription.id" = var.service_principal_subscription_id + "azure.search.client.id" = var.service_principal_client_id + "index.name" = each.value.index + "topics" = each.value.topic + "schema.context.name" = "default" + "input.data.format" = "JSON_SR" + "connector.class" = "AzureCognitiveSearchSink" + "name" = each.value.name + "kafka.auth.mode" = "SERVICE_ACCOUNT" + "kafka.service.account.id" = var.kafka_service_account_id + "write.method" = "Upload" + "delete.enabled" = "true" + "key.mode" = "KEY" + "max.batch.size" = "25" + "max.retry.ms" = "300000" + "max.poll.interval.ms" = "300000" + "max.poll.records" = "500" + "tasks.max" = "1" + "auto.restart.on.user.error" = "true" + "value.converter.decimal.format" = "BASE64" + "value.converter.reference.subject.name.strategy" = "DefaultReferenceSubjectNameStrategy" + "value.converter.value.subject.name.strategy" = "TopicNameStrategy" + "key.converter.key.subject.name.strategy" = "TopicNameStrategy" + "transforms" = "sku_id_to_key" + "transforms.sku_id_to_key.type" = "org.apache.kafka.connect.transforms.ValueToKey" + "transforms.sku_id_to_key.fields" = "sku_id" + } + + depends_on = [ + azurerm_search_service.search, + confluent_kafka_topic.topics, + confluent_schema.key_schemas, + confluent_schema.value_schemas + ] + + lifecycle { + prevent_destroy = false + } +} diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf new file mode 100644 index 0000000000..3a6c9b42c4 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf @@ -0,0 +1,51 @@ +# Outputs (Used Later for Setting Up Confluent Resources) +output "resource_group_name" { + description = "The name of the resource group" + value = azurerm_resource_group.main.name +} + +output "cosmosdb_endpoint" { + description = "Endpoint URI for CosmosDB Account" + value = azurerm_cosmosdb_account.cosmosdb.endpoint +} + +output "cosmosdb_account_name" { + description = "The name of the Cosmos DB account" + value = azurerm_cosmosdb_account.cosmosdb.name +} + +output "cosmosdb_primary_key" { + description = "Primary key for CosmosDB Account" + value = azurerm_cosmosdb_account.cosmosdb.primary_key + sensitive = true +} + +output "cosmosdb_database_name" { + description = "The name of the Cosmos DB SQL database" + value = azurerm_cosmosdb_sql_database.retailstore.name +} + +output "search_service_name" { + description = "The name of the Azure AI Search instance" + value = azurerm_search_service.search.name +} + +output "azure_search_admin_key" { + description = "Primary Admin Key for Azure AI Search" + value = azurerm_search_service.search.primary_key + sensitive = true +} + +output "azure_search_query_key" { + description = "Primary Query Key for Azure AI Search" + value = azurerm_search_service.search.query_keys[0].key + sensitive = true +} + +output "azure_search_endpoint" { + description = "Endpoint URI for Azure AI Search" + value = azurerm_search_service.search.name +} + + + diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh new file mode 100644 index 0000000000..9539a52d33 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + + +echo "Cleaning up Terraform resources..." + +# Remove Terraform state files and directories +rm -vrf .terraform* +rm -vrf .terraform.lock.hcl +rm -vrf terraform.tfstate +rm -vrf terraform.tfstate.backup +rm -vrf *.tfplan + +echo "Terraform resources cleaned up successfully."