From 26e91618ab737f6eee316cee1c72af3f6ba59edb Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Tue, 26 Aug 2025 23:01:34 -0400 Subject: [PATCH 01/11] add optional params to getListing and change back to getListingForShop instead of getFeaturedListing --- .../toolkits/etsy/tools/get-listings/base.ts | 42 ++++++++++++++++++- .../etsy/tools/get-listings/server.ts | 15 +++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts index 74dc6515..ab7e9ff1 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts @@ -4,8 +4,46 @@ import type { IShopListing } from "etsy-ts"; export const getListings = createBaseTool({ description: - "Fetches all listings from the Etsy shop associated with the authenticated user.", - inputSchema: z.object({}), + "Fetches all listings from the Etsy shop associated with the authenticated user." + + "No additional input is required. But there are optional ones:" + + "limit — page size (default 25; max typically 100)" + + "offset — number of results to skip (use for pagination)" + + "sort_on — field to sort by (e.g., created, updated, price, score). Note: some sorts only work when combined with a search option; score is always descending regardless of sort_order." + + "sort_order — up (ascending) or down (descending), when supported by the chosen sort_on." + + "keywords - Search term or phrase that must appear in all results.", + inputSchema: z.object({ + limit: z + .number() + .min(1) + .max(100) + .optional() + .describe( + "Maximum number of items to return. Default: 25. Min: 1. Max: 100" + ), + sort_on: z + .enum(["created", "updated", "price", "score"]) + .optional() + .describe( + "Field to sort by (e.g., created, updated, price, score). Note: some sorts only work when combined with a search option; score is always descending regardless of sort_order. Default: created" + ), + sort_order: z + .enum(["asc", "desc", "up", "down"]) + .optional() + .describe( + "Sort order: up (ascending) or down (descending). Default: desc" + ), + offset: z + .number() + .min(0) + .optional() + .describe("Number of results to skip (use for pagination). Default: 0"), + keywords: z + .string() + .optional() + .describe( + "Search term or phrase that must appear in all results. Default: null" + ), + }), outputSchema: z.object({ results: z.array(z.custom()), }), diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts index f6e11259..9022a9be 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts @@ -10,7 +10,7 @@ export const getListingsServerConfig = ( typeof getListings.outputSchema.shape > => { return { - callback: async () => { + callback: async ({ limit = 25, offset = 0, sort_on = "created", sort_order = "desc", keywords = undefined }) => { try { const user = await etsy.User.getMe(); @@ -24,9 +24,16 @@ export const getListingsServerConfig = ( if (!shopId) throw new Error("Missing Etsy shop ID"); - const listings = await etsy.ShopListing.getFeaturedListingsByShop({ - shopId, - }); + const listings = await etsy.ShopListing.findAllActiveListingsByShop( + { + shopId: shopId, + limit: limit, + offset: offset, + sort_on: sort_on, + sort_order: sort_order, + keywords: keywords + } + ); if (!listings.data.results) throw new Error("Missing Etsy listings"); From a127b2f10c057d19cbdcfed04b2536bd0f774142 Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Wed, 27 Aug 2025 00:15:42 -0400 Subject: [PATCH 02/11] switch to getListing by shop, everything working --- .../toolkits/etsy/tools/get-listings/server.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts index 9022a9be..adbca0e1 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts @@ -24,14 +24,16 @@ export const getListingsServerConfig = ( if (!shopId) throw new Error("Missing Etsy shop ID"); - const listings = await etsy.ShopListing.findAllActiveListingsByShop( + console.log(shop); + console.log(user); + + const listings = await etsy.ShopListing.getListingsByShop( { shopId: shopId, - limit: limit, - offset: offset, - sort_on: sort_on, - sort_order: sort_order, - keywords: keywords + // limit: limit, + // offset: offset, + // sort_on: sort_on, + // sort_order: sort_order, } ); From ba322a8426e615af498538e8c31acdcd0c43f03f Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Wed, 3 Sep 2025 22:00:36 -0400 Subject: [PATCH 03/11] adding rest of getListingByShop params and includes --- .../toolkits/etsy/tools/get-listings/base.ts | 9 ++++----- .../toolkits/etsy/tools/get-listings/server.ts | 14 ++++++-------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts index ab7e9ff1..999e2991 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts @@ -37,12 +37,11 @@ export const getListings = createBaseTool({ .min(0) .optional() .describe("Number of results to skip (use for pagination). Default: 0"), - keywords: z - .string() + includes: z + .enum(["Shipping", "Images", "Shop", "User", "Translations", "Inventory", "Videos"]) + .array() .optional() - .describe( - "Search term or phrase that must appear in all results. Default: null" - ), + .describe("An enumerated string that attaches a valid association. Acceptable inputs are 'Shipping', 'Shop', 'Images', 'User', 'Translations' and 'Inventory'.") }), outputSchema: z.object({ results: z.array(z.custom()), diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts index adbca0e1..8e96498d 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts @@ -10,7 +10,7 @@ export const getListingsServerConfig = ( typeof getListings.outputSchema.shape > => { return { - callback: async ({ limit = 25, offset = 0, sort_on = "created", sort_order = "desc", keywords = undefined }) => { + callback: async ({ limit = 25, offset = 0, sort_on = "created", sort_order = "desc", includes = undefined }) => { try { const user = await etsy.User.getMe(); @@ -24,16 +24,14 @@ export const getListingsServerConfig = ( if (!shopId) throw new Error("Missing Etsy shop ID"); - console.log(shop); - console.log(user); - const listings = await etsy.ShopListing.getListingsByShop( { shopId: shopId, - // limit: limit, - // offset: offset, - // sort_on: sort_on, - // sort_order: sort_order, + limit: limit, + offset: offset, + sort_on: sort_on, + sort_order: sort_order, + includes: includes, } ); From 9ebc5809d732a0e753cfb92624c89a15a65a955e Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Thu, 4 Sep 2025 00:47:12 -0400 Subject: [PATCH 04/11] defining createDraftListing possible params --- src/toolkits/toolkits/etsy/base.ts | 1 + src/toolkits/toolkits/etsy/client.tsx | 2 +- src/toolkits/toolkits/etsy/server.ts | 3 +- .../etsy/tools/create-draft-listing/base.ts | 265 ++++++++++++++++++ .../tools/create-draft-listing/client.tsx | 0 .../etsy/tools/create-draft-listing/server.ts | 0 .../toolkits/etsy/tools/get-listings/base.ts | 4 +- .../etsy/tools/get-listings/server.ts | 22 +- src/toolkits/toolkits/etsy/tools/tools.ts | 1 + 9 files changed, 283 insertions(+), 15 deletions(-) create mode 100644 src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts create mode 100644 src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx create mode 100644 src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts diff --git a/src/toolkits/toolkits/etsy/base.ts b/src/toolkits/toolkits/etsy/base.ts index d585bf7d..bfb4b588 100644 --- a/src/toolkits/toolkits/etsy/base.ts +++ b/src/toolkits/toolkits/etsy/base.ts @@ -14,6 +14,7 @@ export const baseEtsyToolkitConfig: ToolkitConfig< > = { tools: { [EtsyTools.getListings]: getListings, + [EtsyTools.createDraftListing]: createDraftListing, }, parameters: etsyParameters, }; diff --git a/src/toolkits/toolkits/etsy/client.tsx b/src/toolkits/toolkits/etsy/client.tsx index dc79b09b..0b238a35 100644 --- a/src/toolkits/toolkits/etsy/client.tsx +++ b/src/toolkits/toolkits/etsy/client.tsx @@ -17,7 +17,7 @@ export const etsyClientToolkit = createClientToolkit( baseEtsyToolkitConfig, { name: "Etsy Toolkit", - description: "Etsy toolkit for fetching listing details.", + description: "Etsy toolkit for Listing management, Payment management, Receipt management, Shipping management, Shop management and more!", icon: SiEtsy, form: null, type: ToolkitGroups.DataSource, diff --git a/src/toolkits/toolkits/etsy/server.ts b/src/toolkits/toolkits/etsy/server.ts index a2cc94f5..b28e1916 100644 --- a/src/toolkits/toolkits/etsy/server.ts +++ b/src/toolkits/toolkits/etsy/server.ts @@ -14,7 +14,8 @@ import { getListingsServerConfig } from "@/toolkits/toolkits/etsy/tools/get-list export const etsyToolkitServer = createServerToolkit( baseEtsyToolkitConfig, "You have access to the Etsy toolkit for general account management. Currently, this toolkit provides:\n" + - "- **Get Listings**: Retrieves all listings and their image URLs associated with the shop associated with the signed-in user.\n\n", + "- **Get Listings By Shop**: Retrieves listings associated with the shop owned by authenticated user. Has the ability to fetch associations relating to each listing as well.\n" + + "- **Create Draft Listing**: Creates a new draft listing in the shop owned by authenticated user. Accepts a variety of inputs to assign to listing.\n", async () => { const account = await api.accounts.getAccountByProvider("etsy"); diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts new file mode 100644 index 00000000..1955047b --- /dev/null +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts @@ -0,0 +1,265 @@ +import { z } from "zod"; +import { createBaseTool } from "@/toolkits/create-tool"; +import type { IShopListing } from "etsy-ts"; + +export const createDraftListing = createBaseTool({ + description: + "Creates a new draft listing in the Etsy shop associated with the authenticated user." + + "Requires input: quantity, title, description, price, who_made, when_made, is_supply, and taxonomy_id." + + "Optional inputs include: (if not specified, the default value is null" + + "shipping_profile_id — ID of the shipping profile to associate with the listing. REQUIRED if listing type is physical." + + "return_policy_id - the numeric ID of the Return Policy." + + "materials - A list of material strings for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u)." + + "shop_section_id - The numeric ID of the shop section for this listing." + + "processing_min - The minimum number of days it takes to produce the item." + + "processing_max - The maximum number of days it takes to produce the item." + + "readiness_state_id - The numeric ID of the processing profile associated with the listing. Required when type is physical." + + "tags - A comma-separated list of tag strings for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}-'™©®]/u)." + + "styles - An array of style strings for this listing, each of which is free-form text string such as \"Formal\", or \"Steampunk\". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u)." + + "item_weight - The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0." + + "item_length - The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." + + "item_width - The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." + + "item_height - The numeric height of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." + + "item_weight_unit - The unit of measurement for the weight of the product. Valid values are 'g' (grams), 'kg' (kilograms), 'oz' (ounces), and 'lb' (pounds). Required if 'item_weight' is provided." + + "item_dimensions_unit - The unit of measurement for the dimensions of the product. Valid values are 'mm' (millimeters), 'cm' (centimeters), 'm' (meters), 'in' (inches), and 'ft' (feet). Required if any of 'item_length', 'item_width', or 'item_height' is provided." + + "is_personalizable - When ture, indicates that the listing is personalizable." + + "personalization_is_required - When true, indicates that personalization is required for the listing. Will only change if _is_personalizable is true" + + "personalization_char_count_max - The maximum number of characters allowed for personalization. Will only change if _is_personalizable is true." + + "personalization_instructions - Instructions for personalization. Will only change if _is_personalizable is true." + + "production_partner_ids - An array of unique IDs of production partner ids." + + "image_ids - An array of numeric image IDs of the images in a listing, which can include up to 10 images." + + "is_customizable - When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders." + + "should_auto_renew - When true, renews a listing for four months upon expiration." + + "is_taxable - When true, applicable shop tax rates apply to this listing at checkout" + + "type - An enumerated type string that indicates whether the listing is physical or a digital download or both.", + inputSchema: z.object({ + title: z + .string() + .min(1) + .max(140) + .describe("The title of the listing. Can only contain letters, numbers, punctuation marks, mathematical symbols, whitespace characters"), + description: z + .string() + .min(1) + .max(1000) + .describe("The description of the listing."), + price: z + .string() + .regex(/^\d+(\.\d{1,2})?$/) + .describe( + "The price of the item as a string in the format \"0.00\". Must be a positive value with up to two decimal places." + ), + quantity: z + .number() + .min(1) + .describe("The quantity of items available in this listing. Must be at least 1."), + who_made: z + .enum(["i_did", "collective", "someone_else"]) + .describe("Who made the item."), + when_made: z + .enum([ + "made_to_order", + "2020_2025", + "2010_2019", + "2006_2009", + "before_2006", + "2000_2005", + "1990s", + "1980s", + "1970s", + "1960s", + "1950s", + "1940s", + "1930s", + "1920s", + "1910s", + "1900s", + "1800s", + "1700s", + "before_1700", + ]) + .describe("An enumerated string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading."), + taxonomy_id: z + .number() + .int() + .positive() + .describe("The taxonomy ID for the category of the listing."), + is_supply: z + .boolean() + .describe("When true, tags the listing as a supply product, else indicates that it's a finished product."), + shipping_profile_id: z + .number() + .int() + .positive() + .optional() + .describe( + "ID of the shipping profile to associate with the listing. REQUIRED if listing type is physical." + ), + return_policy_id: z + .number() + .int() + .positive() + .optional() + .describe("The numeric ID of the Return Policy."), + materials: z + .array( + z + .string() + .regex(/[^\p{L}\p{Nd}\p{Zs}]/u, { + message: + "Valid materials strings contain only letters, numbers, and whitespace characters.", + }) + .min(1) + .max(25) + .describe( + "A material string for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters." + ) + ) + .max(25), + shop_section_id: z + .number() + .int() + .positive() + .optional() + .describe("The numeric ID of the shop section for this listing."), + processing_min: z + .number() + .int() + .min(0) + .optional() + .describe("The minimum number of days it takes to produce the item."), + processing_max: z + .number() + .int() + .min(0) + .optional() + .describe("The maximum number of days it takes to produce the item."), + readiness_state_id: z + .number() + .int() + .positive() + .optional() + .describe( + "The numeric ID of the processing profile associated with the listing. Required when type is physical." + ), + tags: z + .array( + z + .string() + .regex(/[^\\p{L}\p{Nd}\p{Zs}-'™©®]/u, { + message: + "Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®.", + }) + .min(1) + .max(25) + .describe( + "A tag string for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®." + ) + ) + .max(13) + .describe("A list of tag strings for the listing."), + styles: z + .array( + z + .string() + .regex(/[^\p{L}\p{Nd}\p{Zs}]/u, { + message: + "Valid style strings contain only letters, numbers, and whitespace characters.", + }) + .min(1) + .max(25) + .describe( + "A style string for this listing, such as \"Formal\", or \"Steampunk\". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters." + ) + ) + .max(2) + .describe("An array of style strings for this listing."), + item_weight: z + .number() + .positive() + .optional() + .describe("The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0."), + item_length: z + .number() + .positive() + .optional() + .describe("The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0."), + item_width: z + .number() + .positive() + .optional() + .describe("The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0."), + item_height: z + .number() + .positive() + .optional() + .describe("The numeric height of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0."), + item_weight_unit: z + .enum(["g", "kg", "oz", "lb"]) + .optional() + .describe("The unit of measurement for the weight of the product. Valid values are 'g' (grams), 'kg' (kilograms), 'oz' (ounces), and 'lb' (pounds). Required if 'item_weight' is provided."), + item_dimensions_unit: z + .enum(["mm", "cm", "m", "in", "ft"]) + .optional() + .describe("The unit of measurement for the dimensions of the product. Valid values are 'mm' (millimeters), 'cm' (centimeters), 'm' (meters), 'in' (inches), and 'ft' (feet). Required if any of 'item_length', 'item_width', or 'item_height' is provided."), + is_personalizable: z + .boolean() + .optional() + .describe("When true, indicates that the listing is personalizable."), + personalization_is_required: z + .boolean() + .optional() + .describe("When true, indicates that personalization is required for the listing. Will only change if _is_personalizable is true"), + personalization_char_count_max: z + .number() + .int() + .min(1) + .max(250) + .optional() + .describe("The maximum number of characters allowed for personalization. Will only change if _is_personalizable is true."), + personalization_instructions: z + .string() + .max(500) + .optional() + .describe("Instructions for personalization. Will only change if _is_personalizable is true."), + production_partner_ids: z + .array( + z + .number() + .int() + .positive() + .describe("A unique ID of a production partner.") + ) + .optional() + .describe("An array of unique IDs of production partner ids."), + image_ids: z + .array( + z + .number() + .int() + .positive() + .describe("A numeric image ID of an image in a listing.") + ) + .max(10) + .optional() + .describe("An array of numeric image IDs of the images in a listing, which can include up to 10 images."), + is_customizable: z + .boolean() + .optional() + .describe("When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders."), + should_auto_renew: z + .boolean() + .optional() + .describe("When true, renews a listing for four months upon expiration."), + is_taxable: z + .boolean() + .optional() + .describe("When true, applicable shop tax rates apply to this listing at checkout"), + type: z + .enum(["physical", "digital", "both"]) + .describe("An enumerated type string that indicates whether the listing is physical or a digital download or both."), + }), + outputSchema: z.object({ + result: z.custom(), + }), +}); \ No newline at end of file diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx b/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts index 999e2991..e164e1a5 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts @@ -6,11 +6,11 @@ export const getListings = createBaseTool({ description: "Fetches all listings from the Etsy shop associated with the authenticated user." + "No additional input is required. But there are optional ones:" + - "limit — page size (default 25; max typically 100)" + + "limit — page size (default 25; max 100)" + "offset — number of results to skip (use for pagination)" + "sort_on — field to sort by (e.g., created, updated, price, score). Note: some sorts only work when combined with a search option; score is always descending regardless of sort_order." + "sort_order — up (ascending) or down (descending), when supported by the chosen sort_on." + - "keywords - Search term or phrase that must appear in all results.", + "includes - An enumerated string that attaches a valid association. Acceptable inputs are 'Shipping', 'Shop', 'Images', 'User', 'Translations' and 'Inventory'.", inputSchema: z.object({ limit: z .number() diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts index 8e96498d..f2beaee2 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts @@ -1,4 +1,4 @@ -import type { Etsy } from "etsy-ts"; +import type { Etsy, IGetListingsByShopParams } from "etsy-ts"; import type { ServerToolConfig } from "@/toolkits/types"; import type { getListings } from "./base"; @@ -24,16 +24,16 @@ export const getListingsServerConfig = ( if (!shopId) throw new Error("Missing Etsy shop ID"); - const listings = await etsy.ShopListing.getListingsByShop( - { - shopId: shopId, - limit: limit, - offset: offset, - sort_on: sort_on, - sort_order: sort_order, - includes: includes, - } - ); + const params: IGetListingsByShopParams = { + shopId, + ...(limit !== undefined ? { limit } : {}), + ...(offset !== undefined ? { offset } : {}), + ...(sort_on !== undefined ? { sort_on } : {}), + ...(sort_order !== undefined ? { sort_order } : {}), + ...(includes !== undefined ? { includes } : {}), + }; + + const listings = await etsy.ShopListing.getListingsByShop(params); if (!listings.data.results) throw new Error("Missing Etsy listings"); diff --git a/src/toolkits/toolkits/etsy/tools/tools.ts b/src/toolkits/toolkits/etsy/tools/tools.ts index 8af37ff8..f8724452 100644 --- a/src/toolkits/toolkits/etsy/tools/tools.ts +++ b/src/toolkits/toolkits/etsy/tools/tools.ts @@ -1,3 +1,4 @@ export enum EtsyTools { getListings = "get-listings", + createDraftListing = "create-draft-listing", } From 4fdad111711634965c79ecd04856c09f0d8670c6 Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Mon, 8 Sep 2025 23:48:09 -0400 Subject: [PATCH 05/11] create draft listing success --- src/server/auth/custom-providers/etsy.ts | 2 +- src/toolkits/toolkits/etsy/base.ts | 2 + src/toolkits/toolkits/etsy/client.tsx | 3 + src/toolkits/toolkits/etsy/server.ts | 4 +- .../etsy/tools/create-draft-listing/base.ts | 10 +- .../tools/create-draft-listing/client.tsx | 21 ++++ .../etsy/tools/create-draft-listing/server.ts | 112 ++++++++++++++++++ .../etsy/tools/get-listings/server.ts | 11 +- 8 files changed, 150 insertions(+), 15 deletions(-) diff --git a/src/server/auth/custom-providers/etsy.ts b/src/server/auth/custom-providers/etsy.ts index 2358607b..a8ef3b95 100644 --- a/src/server/auth/custom-providers/etsy.ts +++ b/src/server/auth/custom-providers/etsy.ts @@ -10,7 +10,7 @@ export interface EtsyProfile { image_url_75x75?: string | null; } -export const etsyScopes = "email_r shops_r listings_r"; +export const etsyScopes = "address_r address_w billing_r cart_r cart_w email_r favorites_r favorites_w feedback_r listings_d listings_r listings_w profile_r profile_w recommend_r recommend_w shops_r shops_w transactions_r transactions_w"; export default function EtsyProvider

( options: OAuthUserConfig

, diff --git a/src/toolkits/toolkits/etsy/base.ts b/src/toolkits/toolkits/etsy/base.ts index bfb4b588..31ee13ac 100644 --- a/src/toolkits/toolkits/etsy/base.ts +++ b/src/toolkits/toolkits/etsy/base.ts @@ -4,6 +4,8 @@ import { EtsyTools } from "./tools/tools"; import { getListings } from "@/toolkits/toolkits/etsy/tools/get-listings/base"; +import { createDraftListing } from "@/toolkits/toolkits/etsy/tools/create-draft-listing/base"; + import type { ToolkitConfig } from "@/toolkits/types"; export const etsyParameters = z.object({}); diff --git a/src/toolkits/toolkits/etsy/client.tsx b/src/toolkits/toolkits/etsy/client.tsx index 0b238a35..832ac7dc 100644 --- a/src/toolkits/toolkits/etsy/client.tsx +++ b/src/toolkits/toolkits/etsy/client.tsx @@ -10,6 +10,8 @@ import { createClientToolkit } from "@/toolkits/create-toolkit"; import { getListingsClientConfig } from "@/toolkits/toolkits/etsy/tools/get-listings/client"; +import { createDraftListingClientConfig } from "@/toolkits/toolkits/etsy/tools/create-draft-listing/client"; + import { ToolkitGroups } from "@/toolkits/types"; import { EtsyTools } from "./tools/tools"; @@ -37,5 +39,6 @@ export const etsyClientToolkit = createClientToolkit( }, { [EtsyTools.getListings]: getListingsClientConfig, + [EtsyTools.createDraftListing]: createDraftListingClientConfig, }, ); diff --git a/src/toolkits/toolkits/etsy/server.ts b/src/toolkits/toolkits/etsy/server.ts index b28e1916..00856f88 100644 --- a/src/toolkits/toolkits/etsy/server.ts +++ b/src/toolkits/toolkits/etsy/server.ts @@ -10,6 +10,7 @@ import { EtsyTools } from "./tools/tools"; import { EtsySecurityDataStorage } from "./security-data-storage"; import { getListingsServerConfig } from "@/toolkits/toolkits/etsy/tools/get-listings/server"; +import { createDraftListingServerConfig } from "@/toolkits/toolkits/etsy/tools/create-draft-listing/server"; export const etsyToolkitServer = createServerToolkit( baseEtsyToolkitConfig, @@ -33,7 +34,8 @@ export const etsyToolkitServer = createServerToolkit( }); return { - [EtsyTools.getListings]: getListingsServerConfig(etsy), + [EtsyTools.getListings]: getListingsServerConfig(etsy, account.providerAccountId), + [EtsyTools.createDraftListing]: createDraftListingServerConfig(etsy, account.providerAccountId) }; }, ); diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts index 1955047b..2d28ab91 100644 --- a/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts @@ -44,10 +44,10 @@ export const createDraftListing = createBaseTool({ .max(1000) .describe("The description of the listing."), price: z - .string() - .regex(/^\d+(\.\d{1,2})?$/) + .number() + .positive() .describe( - "The price of the item as a string in the format \"0.00\". Must be a positive value with up to two decimal places." + "The price of the item. Must be a positive value with up to two decimal places." ), quantity: z .number() @@ -146,7 +146,7 @@ export const createDraftListing = createBaseTool({ .array( z .string() - .regex(/[^\\p{L}\p{Nd}\p{Zs}-'™©®]/u, { + .regex(/^[\p{L}\p{Nd}\p{Zs}'™©®-]+$/u, { message: "Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®.", }) @@ -256,7 +256,7 @@ export const createDraftListing = createBaseTool({ .optional() .describe("When true, applicable shop tax rates apply to this listing at checkout"), type: z - .enum(["physical", "digital", "both"]) + .enum(["physical", "download", "both"]) .describe("An enumerated type string that indicates whether the listing is physical or a digital download or both."), }), outputSchema: z.object({ diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx b/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx index e69de29b..710e4ca3 100644 --- a/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx @@ -0,0 +1,21 @@ +import { Search } from "lucide-react"; +import type { ClientToolConfig } from "@/toolkits/types"; +import type { createDraftListing } from "./base"; + +export const createDraftListingClientConfig: ClientToolConfig< + typeof createDraftListing.inputSchema.shape, + typeof createDraftListing.outputSchema.shape +> = { + CallComponent: ({ isPartial }) => ( +

+ + {isPartial && ...} +
+ ), + ResultComponent: ({ result: { result } }) => +
+

Listing

+
{result.title}
+ ) +
+}; diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts index e69de29b..63e9716d 100644 --- a/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts @@ -0,0 +1,112 @@ +import type { Etsy, ICreateDraftListingPayload } from "etsy-ts"; + +import type { ServerToolConfig } from "@/toolkits/types"; +import type { createDraftListing } from "./base"; + +export const createDraftListingServerConfig = ( + etsy: Etsy, + userId: string +): ServerToolConfig< + typeof createDraftListing.inputSchema.shape, + typeof createDraftListing.outputSchema.shape +> => { + return { + callback: async ({ + title, + description, + price, + quantity, + who_made, + is_supply, + when_made, + taxonomy_id, + shipping_profile_id, + shop_section_id, + materials, + return_policy_id, + processing_min, + processing_max, + readiness_state_id, + tags, + styles, + item_weight, + item_weight_unit, + item_length, + item_width, + item_height, + item_dimensions_unit, + is_personalizable, + personalization_is_required, + personalization_char_count_max, + personalization_instructions, + production_partner_ids, + image_ids, + is_customizable, + should_auto_renew, + is_taxable, + type + }) => { + try { + const shop = await etsy.Shop.getShopByOwnerUserId(Number(userId)); + + const shopId = shop.data.shop_id; + + if (!shopId) throw new Error("Missing Etsy shop ID"); + + const params: ICreateDraftListingPayload = { + title, + description, + price, + quantity, + who_made, + is_supply, + when_made, + taxonomy_id, + materials, + type, + styles, + ...(shipping_profile_id !== undefined ? {shipping_profile_id} : {}), + ...(shop_section_id !== undefined ? {shop_section_id} : {}), + ...(return_policy_id !== undefined ? {return_policy_id} : {}), + ...(processing_min !== undefined ? {processing_min} : {}), + ...(processing_max !== undefined ? {processing_max} : {}), + ...(readiness_state_id !== undefined ? {readiness_state_id} : {}), + ...(item_weight !== undefined ? {item_weight} : {}), + ...(item_weight_unit !== undefined ? {item_weight_unit} : {}), + ...(item_length !== undefined ? {item_length} : {}), + ...(item_width !== undefined ? {item_width} : {}), + ...(item_height !== undefined ? {item_height} : {}), + ...(item_dimensions_unit !== undefined ? {item_dimensions_unit} : {}), + ...(is_personalizable !== undefined ? {is_personalizable} : {}), + ...(personalization_is_required !== undefined ? {personalization_is_required} : {}), + ...(personalization_char_count_max !== undefined ? {personalization_char_count_max} : {}), + ...(personalization_instructions !== undefined ? {personalization_instructions} : {}), + ...(production_partner_ids !== undefined ? {production_partner_ids} : {}), + ...(image_ids !== undefined ? {image_ids} : {}), + ...(is_customizable !== undefined ? {is_customizable} : {}), + ...(should_auto_renew !== undefined ? {should_auto_renew} : {}), + ...(is_taxable !== undefined ? {is_taxable} : {}), + ...(type !== undefined ? {type} : {}), + }; + + const listing = await etsy.ShopListing.createDraftListing( + shopId, + params, + undefined + ); + + if (!listing.data) throw new Error("Missing Etsy listing"); + + return { + result: listing.data + }; + } catch (error) { + console.error("Etsy API error:", error); + throw new Error("Failed to create draft listing on Etsy"); + } + }, + message: + "Successfully created the Etsy draft listing. The user is shown the responses in the UI. Do not reiterate them. " + + "If you called this tool because the user asked a question, answer the question.", + }; +} diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts index f2beaee2..5dd9e73d 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts @@ -5,20 +5,15 @@ import type { getListings } from "./base"; export const getListingsServerConfig = ( etsy: Etsy, + userId: string ): ServerToolConfig< typeof getListings.inputSchema.shape, typeof getListings.outputSchema.shape > => { return { - callback: async ({ limit = 25, offset = 0, sort_on = "created", sort_order = "desc", includes = undefined }) => { + callback: async ({ limit, offset, sort_on , sort_order, includes }) => { try { - const user = await etsy.User.getMe(); - - const userId = user.data.user_id; - - if (!userId) throw new Error("Missing Etsy user ID"); - - const shop = await etsy.Shop.getShopByOwnerUserId(userId); + const shop = await etsy.Shop.getShopByOwnerUserId(Number(userId)); const shopId = shop.data.shop_id; From 8a040e90566980b5a4eb77064e642dce0a0f4ffb Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Mon, 8 Sep 2025 23:57:57 -0400 Subject: [PATCH 06/11] prettier --- src/server/auth/custom-providers/etsy.ts | 3 +- src/toolkits/toolkits/etsy/client.tsx | 3 +- src/toolkits/toolkits/etsy/server.ts | 10 +- .../etsy/tools/create-draft-listing/base.ts | 94 +++++++++++++------ .../tools/create-draft-listing/client.tsx | 6 +- .../etsy/tools/create-draft-listing/server.ts | 72 ++++++++------ .../toolkits/etsy/tools/get-listings/base.ts | 20 +++- .../etsy/tools/get-listings/server.ts | 4 +- 8 files changed, 137 insertions(+), 75 deletions(-) diff --git a/src/server/auth/custom-providers/etsy.ts b/src/server/auth/custom-providers/etsy.ts index a8ef3b95..20e3e3e2 100644 --- a/src/server/auth/custom-providers/etsy.ts +++ b/src/server/auth/custom-providers/etsy.ts @@ -10,7 +10,8 @@ export interface EtsyProfile { image_url_75x75?: string | null; } -export const etsyScopes = "address_r address_w billing_r cart_r cart_w email_r favorites_r favorites_w feedback_r listings_d listings_r listings_w profile_r profile_w recommend_r recommend_w shops_r shops_w transactions_r transactions_w"; +export const etsyScopes = + "address_r address_w billing_r cart_r cart_w email_r favorites_r favorites_w feedback_r listings_d listings_r listings_w profile_r profile_w recommend_r recommend_w shops_r shops_w transactions_r transactions_w"; export default function EtsyProvider

( options: OAuthUserConfig

, diff --git a/src/toolkits/toolkits/etsy/client.tsx b/src/toolkits/toolkits/etsy/client.tsx index 832ac7dc..1274e57f 100644 --- a/src/toolkits/toolkits/etsy/client.tsx +++ b/src/toolkits/toolkits/etsy/client.tsx @@ -19,7 +19,8 @@ export const etsyClientToolkit = createClientToolkit( baseEtsyToolkitConfig, { name: "Etsy Toolkit", - description: "Etsy toolkit for Listing management, Payment management, Receipt management, Shipping management, Shop management and more!", + description: + "Etsy toolkit for Listing management, Payment management, Receipt management, Shipping management, Shop management and more!", icon: SiEtsy, form: null, type: ToolkitGroups.DataSource, diff --git a/src/toolkits/toolkits/etsy/server.ts b/src/toolkits/toolkits/etsy/server.ts index 00856f88..9985fc3e 100644 --- a/src/toolkits/toolkits/etsy/server.ts +++ b/src/toolkits/toolkits/etsy/server.ts @@ -34,8 +34,14 @@ export const etsyToolkitServer = createServerToolkit( }); return { - [EtsyTools.getListings]: getListingsServerConfig(etsy, account.providerAccountId), - [EtsyTools.createDraftListing]: createDraftListingServerConfig(etsy, account.providerAccountId) + [EtsyTools.getListings]: getListingsServerConfig( + etsy, + account.providerAccountId, + ), + [EtsyTools.createDraftListing]: createDraftListingServerConfig( + etsy, + account.providerAccountId, + ), }; }, ); diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts index 2d28ab91..603e2866 100644 --- a/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts @@ -15,7 +15,7 @@ export const createDraftListing = createBaseTool({ "processing_max - The maximum number of days it takes to produce the item." + "readiness_state_id - The numeric ID of the processing profile associated with the listing. Required when type is physical." + "tags - A comma-separated list of tag strings for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}-'™©®]/u)." + - "styles - An array of style strings for this listing, each of which is free-form text string such as \"Formal\", or \"Steampunk\". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u)." + + 'styles - An array of style strings for this listing, each of which is free-form text string such as "Formal", or "Steampunk". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u).' + "item_weight - The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0." + "item_length - The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." + "item_width - The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." + @@ -37,7 +37,9 @@ export const createDraftListing = createBaseTool({ .string() .min(1) .max(140) - .describe("The title of the listing. Can only contain letters, numbers, punctuation marks, mathematical symbols, whitespace characters"), + .describe( + "The title of the listing. Can only contain letters, numbers, punctuation marks, mathematical symbols, whitespace characters", + ), description: z .string() .min(1) @@ -47,12 +49,14 @@ export const createDraftListing = createBaseTool({ .number() .positive() .describe( - "The price of the item. Must be a positive value with up to two decimal places." + "The price of the item. Must be a positive value with up to two decimal places.", ), quantity: z .number() .min(1) - .describe("The quantity of items available in this listing. Must be at least 1."), + .describe( + "The quantity of items available in this listing. Must be at least 1.", + ), who_made: z .enum(["i_did", "collective", "someone_else"]) .describe("Who made the item."), @@ -78,7 +82,9 @@ export const createDraftListing = createBaseTool({ "1700s", "before_1700", ]) - .describe("An enumerated string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading."), + .describe( + "An enumerated string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading.", + ), taxonomy_id: z .number() .int() @@ -86,14 +92,16 @@ export const createDraftListing = createBaseTool({ .describe("The taxonomy ID for the category of the listing."), is_supply: z .boolean() - .describe("When true, tags the listing as a supply product, else indicates that it's a finished product."), + .describe( + "When true, tags the listing as a supply product, else indicates that it's a finished product.", + ), shipping_profile_id: z .number() .int() .positive() .optional() .describe( - "ID of the shipping profile to associate with the listing. REQUIRED if listing type is physical." + "ID of the shipping profile to associate with the listing. REQUIRED if listing type is physical.", ), return_policy_id: z .number() @@ -112,8 +120,8 @@ export const createDraftListing = createBaseTool({ .min(1) .max(25) .describe( - "A material string for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters." - ) + "A material string for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters.", + ), ) .max(25), shop_section_id: z @@ -140,7 +148,7 @@ export const createDraftListing = createBaseTool({ .positive() .optional() .describe( - "The numeric ID of the processing profile associated with the listing. Required when type is physical." + "The numeric ID of the processing profile associated with the listing. Required when type is physical.", ), tags: z .array( @@ -153,8 +161,8 @@ export const createDraftListing = createBaseTool({ .min(1) .max(25) .describe( - "A tag string for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®." - ) + "A tag string for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®.", + ), ) .max(13) .describe("A list of tag strings for the listing."), @@ -169,8 +177,8 @@ export const createDraftListing = createBaseTool({ .min(1) .max(25) .describe( - "A style string for this listing, such as \"Formal\", or \"Steampunk\". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters." - ) + 'A style string for this listing, such as "Formal", or "Steampunk". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters.', + ), ) .max(2) .describe("An array of style strings for this listing."), @@ -178,30 +186,42 @@ export const createDraftListing = createBaseTool({ .number() .positive() .optional() - .describe("The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0."), + .describe( + "The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0.", + ), item_length: z .number() .positive() .optional() - .describe("The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0."), + .describe( + "The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0.", + ), item_width: z .number() .positive() .optional() - .describe("The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0."), + .describe( + "The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0.", + ), item_height: z .number() .positive() .optional() - .describe("The numeric height of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0."), + .describe( + "The numeric height of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0.", + ), item_weight_unit: z .enum(["g", "kg", "oz", "lb"]) .optional() - .describe("The unit of measurement for the weight of the product. Valid values are 'g' (grams), 'kg' (kilograms), 'oz' (ounces), and 'lb' (pounds). Required if 'item_weight' is provided."), + .describe( + "The unit of measurement for the weight of the product. Valid values are 'g' (grams), 'kg' (kilograms), 'oz' (ounces), and 'lb' (pounds). Required if 'item_weight' is provided.", + ), item_dimensions_unit: z .enum(["mm", "cm", "m", "in", "ft"]) .optional() - .describe("The unit of measurement for the dimensions of the product. Valid values are 'mm' (millimeters), 'cm' (centimeters), 'm' (meters), 'in' (inches), and 'ft' (feet). Required if any of 'item_length', 'item_width', or 'item_height' is provided."), + .describe( + "The unit of measurement for the dimensions of the product. Valid values are 'mm' (millimeters), 'cm' (centimeters), 'm' (meters), 'in' (inches), and 'ft' (feet). Required if any of 'item_length', 'item_width', or 'item_height' is provided.", + ), is_personalizable: z .boolean() .optional() @@ -209,26 +229,32 @@ export const createDraftListing = createBaseTool({ personalization_is_required: z .boolean() .optional() - .describe("When true, indicates that personalization is required for the listing. Will only change if _is_personalizable is true"), + .describe( + "When true, indicates that personalization is required for the listing. Will only change if _is_personalizable is true", + ), personalization_char_count_max: z .number() .int() .min(1) .max(250) .optional() - .describe("The maximum number of characters allowed for personalization. Will only change if _is_personalizable is true."), + .describe( + "The maximum number of characters allowed for personalization. Will only change if _is_personalizable is true.", + ), personalization_instructions: z .string() .max(500) .optional() - .describe("Instructions for personalization. Will only change if _is_personalizable is true."), + .describe( + "Instructions for personalization. Will only change if _is_personalizable is true.", + ), production_partner_ids: z .array( z .number() .int() .positive() - .describe("A unique ID of a production partner.") + .describe("A unique ID of a production partner."), ) .optional() .describe("An array of unique IDs of production partner ids."), @@ -238,15 +264,19 @@ export const createDraftListing = createBaseTool({ .number() .int() .positive() - .describe("A numeric image ID of an image in a listing.") + .describe("A numeric image ID of an image in a listing."), ) .max(10) .optional() - .describe("An array of numeric image IDs of the images in a listing, which can include up to 10 images."), + .describe( + "An array of numeric image IDs of the images in a listing, which can include up to 10 images.", + ), is_customizable: z .boolean() .optional() - .describe("When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders."), + .describe( + "When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders.", + ), should_auto_renew: z .boolean() .optional() @@ -254,12 +284,16 @@ export const createDraftListing = createBaseTool({ is_taxable: z .boolean() .optional() - .describe("When true, applicable shop tax rates apply to this listing at checkout"), + .describe( + "When true, applicable shop tax rates apply to this listing at checkout", + ), type: z .enum(["physical", "download", "both"]) - .describe("An enumerated type string that indicates whether the listing is physical or a digital download or both."), + .describe( + "An enumerated type string that indicates whether the listing is physical or a digital download or both.", + ), }), outputSchema: z.object({ result: z.custom(), }), -}); \ No newline at end of file +}); diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx b/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx index 710e4ca3..92fe60d4 100644 --- a/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/client.tsx @@ -12,10 +12,10 @@ export const createDraftListingClientConfig: ClientToolConfig< {isPartial && ...} ), - ResultComponent: ({ result: { result } }) => + ResultComponent: ({ result: { result } }) => (

Listing

-
{result.title}
- ) +
{result.title}
)
+ ), }; diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts index 63e9716d..f351962d 100644 --- a/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts +++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/server.ts @@ -5,7 +5,7 @@ import type { createDraftListing } from "./base"; export const createDraftListingServerConfig = ( etsy: Etsy, - userId: string + userId: string, ): ServerToolConfig< typeof createDraftListing.inputSchema.shape, typeof createDraftListing.outputSchema.shape @@ -44,7 +44,7 @@ export const createDraftListingServerConfig = ( is_customizable, should_auto_renew, is_taxable, - type + type, }) => { try { const shop = await etsy.Shop.getShopByOwnerUserId(Number(userId)); @@ -65,48 +65,58 @@ export const createDraftListingServerConfig = ( materials, type, styles, - ...(shipping_profile_id !== undefined ? {shipping_profile_id} : {}), - ...(shop_section_id !== undefined ? {shop_section_id} : {}), - ...(return_policy_id !== undefined ? {return_policy_id} : {}), - ...(processing_min !== undefined ? {processing_min} : {}), - ...(processing_max !== undefined ? {processing_max} : {}), - ...(readiness_state_id !== undefined ? {readiness_state_id} : {}), - ...(item_weight !== undefined ? {item_weight} : {}), - ...(item_weight_unit !== undefined ? {item_weight_unit} : {}), - ...(item_length !== undefined ? {item_length} : {}), - ...(item_width !== undefined ? {item_width} : {}), - ...(item_height !== undefined ? {item_height} : {}), - ...(item_dimensions_unit !== undefined ? {item_dimensions_unit} : {}), - ...(is_personalizable !== undefined ? {is_personalizable} : {}), - ...(personalization_is_required !== undefined ? {personalization_is_required} : {}), - ...(personalization_char_count_max !== undefined ? {personalization_char_count_max} : {}), - ...(personalization_instructions !== undefined ? {personalization_instructions} : {}), - ...(production_partner_ids !== undefined ? {production_partner_ids} : {}), - ...(image_ids !== undefined ? {image_ids} : {}), - ...(is_customizable !== undefined ? {is_customizable} : {}), - ...(should_auto_renew !== undefined ? {should_auto_renew} : {}), - ...(is_taxable !== undefined ? {is_taxable} : {}), - ...(type !== undefined ? {type} : {}), + ...(shipping_profile_id !== undefined ? { shipping_profile_id } : {}), + ...(shop_section_id !== undefined ? { shop_section_id } : {}), + ...(return_policy_id !== undefined ? { return_policy_id } : {}), + ...(processing_min !== undefined ? { processing_min } : {}), + ...(processing_max !== undefined ? { processing_max } : {}), + ...(readiness_state_id !== undefined ? { readiness_state_id } : {}), + ...(item_weight !== undefined ? { item_weight } : {}), + ...(item_weight_unit !== undefined ? { item_weight_unit } : {}), + ...(item_length !== undefined ? { item_length } : {}), + ...(item_width !== undefined ? { item_width } : {}), + ...(item_height !== undefined ? { item_height } : {}), + ...(item_dimensions_unit !== undefined + ? { item_dimensions_unit } + : {}), + ...(is_personalizable !== undefined ? { is_personalizable } : {}), + ...(personalization_is_required !== undefined + ? { personalization_is_required } + : {}), + ...(personalization_char_count_max !== undefined + ? { personalization_char_count_max } + : {}), + ...(personalization_instructions !== undefined + ? { personalization_instructions } + : {}), + ...(production_partner_ids !== undefined + ? { production_partner_ids } + : {}), + ...(image_ids !== undefined ? { image_ids } : {}), + ...(is_customizable !== undefined ? { is_customizable } : {}), + ...(should_auto_renew !== undefined ? { should_auto_renew } : {}), + ...(is_taxable !== undefined ? { is_taxable } : {}), + ...(type !== undefined ? { type } : {}), }; const listing = await etsy.ShopListing.createDraftListing( - shopId, - params, - undefined + shopId, + params, + undefined, ); if (!listing.data) throw new Error("Missing Etsy listing"); return { - result: listing.data + result: listing.data, }; } catch (error) { console.error("Etsy API error:", error); throw new Error("Failed to create draft listing on Etsy"); - } - }, + } + }, message: "Successfully created the Etsy draft listing. The user is shown the responses in the UI. Do not reiterate them. " + "If you called this tool because the user asked a question, answer the question.", }; -} +}; diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts index e164e1a5..b67c9734 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/base.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/base.ts @@ -18,19 +18,19 @@ export const getListings = createBaseTool({ .max(100) .optional() .describe( - "Maximum number of items to return. Default: 25. Min: 1. Max: 100" + "Maximum number of items to return. Default: 25. Min: 1. Max: 100", ), sort_on: z .enum(["created", "updated", "price", "score"]) .optional() .describe( - "Field to sort by (e.g., created, updated, price, score). Note: some sorts only work when combined with a search option; score is always descending regardless of sort_order. Default: created" + "Field to sort by (e.g., created, updated, price, score). Note: some sorts only work when combined with a search option; score is always descending regardless of sort_order. Default: created", ), sort_order: z .enum(["asc", "desc", "up", "down"]) .optional() .describe( - "Sort order: up (ascending) or down (descending). Default: desc" + "Sort order: up (ascending) or down (descending). Default: desc", ), offset: z .number() @@ -38,10 +38,20 @@ export const getListings = createBaseTool({ .optional() .describe("Number of results to skip (use for pagination). Default: 0"), includes: z - .enum(["Shipping", "Images", "Shop", "User", "Translations", "Inventory", "Videos"]) + .enum([ + "Shipping", + "Images", + "Shop", + "User", + "Translations", + "Inventory", + "Videos", + ]) .array() .optional() - .describe("An enumerated string that attaches a valid association. Acceptable inputs are 'Shipping', 'Shop', 'Images', 'User', 'Translations' and 'Inventory'.") + .describe( + "An enumerated string that attaches a valid association. Acceptable inputs are 'Shipping', 'Shop', 'Images', 'User', 'Translations' and 'Inventory'.", + ), }), outputSchema: z.object({ results: z.array(z.custom()), diff --git a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts index 5dd9e73d..77c66250 100644 --- a/src/toolkits/toolkits/etsy/tools/get-listings/server.ts +++ b/src/toolkits/toolkits/etsy/tools/get-listings/server.ts @@ -5,13 +5,13 @@ import type { getListings } from "./base"; export const getListingsServerConfig = ( etsy: Etsy, - userId: string + userId: string, ): ServerToolConfig< typeof getListings.inputSchema.shape, typeof getListings.outputSchema.shape > => { return { - callback: async ({ limit, offset, sort_on , sort_order, includes }) => { + callback: async ({ limit, offset, sort_on, sort_order, includes }) => { try { const shop = await etsy.Shop.getShopByOwnerUserId(Number(userId)); From ef5639ba0f432e83513e59ea6a189f9f732baa8f Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Tue, 9 Sep 2025 21:42:43 -0400 Subject: [PATCH 07/11] patch etsy-ts made to order --- patches/etsy-ts@4.2.0.patch | 13 +++++++++++++ pnpm-lock.yaml | 13 +++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 patches/etsy-ts@4.2.0.patch diff --git a/patches/etsy-ts@4.2.0.patch b/patches/etsy-ts@4.2.0.patch new file mode 100644 index 00000000..fdd4a1d2 --- /dev/null +++ b/patches/etsy-ts@4.2.0.patch @@ -0,0 +1,13 @@ +diff --git a/dist/api/data-contracts.d.ts b/dist/api/data-contracts.d.ts +index 5e8b06b081a84e93153e2e325ed76d53669fb033..675b39b3240104358379d1ef7ddc1d46bc1a3384 100644 +--- a/dist/api/data-contracts.d.ts ++++ b/dist/api/data-contracts.d.ts +@@ -2082,7 +2082,7 @@ export interface ICreateDraftListingPayload { + /** An enumerated string indicating who made the product. Helps buyers locate the listing under the Handmade heading. Requires 'is_supply' and 'when_made'. */ + who_made: "i_did" | "someone_else" | "collective"; + /** An enumerated string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading. Requires 'is_supply' and 'who_made'. */ +- when_made: "made_to_order" | "2020_2023" | "2010_2019" | "2004_2009" | "before_2004" | "2000_2003" | "1990s" | "1980s" | "1970s" | "1960s" | "1950s" | "1940s" | "1930s" | "1920s" | "1910s" | "1900s" | "1800s" | "1700s" | "before_1700"; ++ when_made: "made_to_order" | "2020_2025" | "2010_2019" | "2006_2009" | "before_2006" | "2000_2005" | "1990s" | "1980s" | "1970s" | "1960s" | "1950s" | "1940s" | "1930s" | "1920s" | "1910s" | "1900s" | "1800s" | "1700s" | "before_1700"; + /** + * The numerical taxonomy ID of the listing. See [SellerTaxonomy](/documentation/reference#tag/SellerTaxonomy) and [BuyerTaxonomy](/documentation/reference#tag/BuyerTaxonomy) for more information. + * @min 1 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9cafcd36..b8590284 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,11 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + etsy-ts@4.2.0: + hash: 1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e + path: patches/etsy-ts@4.2.0.patch + importers: .: @@ -179,12 +184,12 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 - etsy-ts: - specifier: ^4.2.0 - version: 4.2.0 discord-api-types: specifier: ^0.38.17 version: 0.38.18 + etsy-ts: + specifier: ^4.2.0 + version: 4.2.0(patch_hash=1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e) exa-js: specifier: ^1.8.8 version: 1.8.8(encoding@0.1.13)(ws@8.18.3)(zod@3.25.56) @@ -8670,7 +8675,7 @@ snapshots: etag@1.8.1: {} - etsy-ts@4.2.0: + etsy-ts@4.2.0(patch_hash=1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e): dependencies: axios: 1.7.7 axios-auth-refresh: 3.3.6(axios@1.7.7) From 07c304b6ba32080c211770d6ff5b80c1fcc0d72d Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Tue, 9 Sep 2025 21:58:23 -0400 Subject: [PATCH 08/11] add patchDependency and sync lockfile --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 5616cf0b..d1a89ae2 100644 --- a/package.json +++ b/package.json @@ -140,6 +140,9 @@ "typescript": "^5.8.2", "typescript-eslint": "^8.27.0" }, + "patchedDependencies": { + "etsy-ts@4.2.0": "patches/etsy-ts@4.2.0.patch" + }, "ct3aMetadata": { "initVersion": "7.39.3" }, From 1c29c467527d8997ee6c66449bdfdb4b7a569b12 Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Tue, 9 Sep 2025 22:00:59 -0400 Subject: [PATCH 09/11] update lock --- pnpm-lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b8590284..f0990c45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,7 +4,7 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -patchedDependencies: +patchedDependencies: etsy-ts@4.2.0: hash: 1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e path: patches/etsy-ts@4.2.0.patch From f63d8885c6e304df9f9a399d141187a2e9e327f8 Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Tue, 9 Sep 2025 22:07:13 -0400 Subject: [PATCH 10/11] pin etsy-ts@4.2.0 to match patchedDependencies --- package.json | 2 +- pnpm-lock.yaml | 121 ++++++++++++++++++++++++++----------------------- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index d1a89ae2..fb779b92 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "cmdk": "^1.1.1", "cookies-next": "^6.0.0", "date-fns": "^4.1.0", - "etsy-ts": "^4.2.0", + "etsy-ts": "4.2.0", "discord-api-types": "^0.38.17", "exa-js": "^1.8.8", "fast-deep-equal": "^3.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0990c45..4a403f4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,7 +4,7 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -patchedDependencies: +patchedDependencies: etsy-ts@4.2.0: hash: 1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e path: patches/etsy-ts@4.2.0.patch @@ -188,7 +188,7 @@ importers: specifier: ^0.38.17 version: 0.38.18 etsy-ts: - specifier: ^4.2.0 + specifier: 4.2.0 version: 4.2.0(patch_hash=1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e) exa-js: specifier: ^1.8.8 @@ -2096,14 +2096,14 @@ packages: '@types/node@18.19.111': resolution: {integrity: sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==} - '@types/node@18.19.121': - resolution: {integrity: sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==} + '@types/node@18.19.124': + resolution: {integrity: sha512-hY4YWZFLs3ku6D2Gqo3RchTd9VRCcrjqp/I0mmohYeUVA5Y8eCXKJEasHxLAJVZRJuQogfd1GiJ9lgogBgKeuQ==} '@types/node@20.19.0': resolution: {integrity: sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==} - '@types/node@20.19.9': - resolution: {integrity: sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==} + '@types/node@20.19.13': + resolution: {integrity: sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==} '@types/pg@8.11.0': resolution: {integrity: sha512-sDAlRiBNthGjNFfvt0k6mtotoVYVQ63pA8R4EMWka7crawSR60waVYR0HAgmPRs/e2YaeJTD/43OoZ3PFw80pw==} @@ -2508,6 +2508,9 @@ packages: peerDependencies: axios: '>= 0.18 < 0.19.0 || >= 0.19.1' + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + axios@1.7.7: resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} @@ -3306,6 +3309,15 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -3654,8 +3666,8 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + ip-address@10.0.1: + resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -3852,8 +3864,8 @@ packages: jose@6.0.11: resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==} - js-tiktoken@1.0.20: - resolution: {integrity: sha512-Xlaqhhs8VfCd6Sh7a1cFkZHQbYTLCwVJJWiHVxBYzLPxW0XsoxBy1hitmjkdIjD3Aon5BXLHFwU5O8WUx6HH+A==} + js-tiktoken@1.0.21: + resolution: {integrity: sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3862,9 +3874,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -3906,8 +3915,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - langsmith@0.3.50: - resolution: {integrity: sha512-yosW6sR0EFnMnYKKyBmcqTNknDVOs+dUfcswWk80JoRxox6WEyel7hmSkSzabP/GmTs0hXbrtc+lZwpJWSnI0w==} + langsmith@0.3.67: + resolution: {integrity: sha512-l4y3RmJ9yWF5a29fLg3eWZQxn6Q6dxTOgLGgQHzPGZHF3NUynn+A+airYIe/Yt4rwjGbuVrABAPsXBkVu/Hi7g==} peerDependencies: '@opentelemetry/api': '*' '@opentelemetry/exporter-trace-otlp-proto': '*' @@ -4418,8 +4427,8 @@ packages: sass: optional: true - node-abi@3.75.0: - resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==} + node-abi@3.77.0: + resolution: {integrity: sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==} engines: {node: '>=10'} node-addon-api@7.1.1: @@ -5188,8 +5197,8 @@ packages: resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} engines: {node: '>= 10'} - socks@2.8.6: - resolution: {integrity: sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==} + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} sonner@2.0.5: @@ -5209,9 +5218,6 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - sqlite3@5.1.7: resolution: {integrity: sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==} @@ -5808,7 +5814,7 @@ snapshots: '@anthropic-ai/sdk@0.40.1(encoding@0.1.13)': dependencies: - '@types/node': 18.19.121 + '@types/node': 18.19.124 '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 @@ -6181,7 +6187,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.19.9 + '@types/node': 20.19.13 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -6208,8 +6214,8 @@ snapshots: ansi-styles: 5.2.0 camelcase: 6.3.0 decamelize: 1.2.0 - js-tiktoken: 1.0.20 - langsmith: 0.3.50(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)) + js-tiktoken: 1.0.21 + langsmith: 0.3.67(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)) mustache: 4.2.0 p-queue: 6.6.2 p-retry: 4.6.2 @@ -7387,14 +7393,14 @@ snapshots: '@types/node-fetch@2.6.13': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 form-data: 4.0.4 '@types/node@18.19.111': dependencies: undici-types: 5.26.5 - '@types/node@18.19.121': + '@types/node@18.19.124': dependencies: undici-types: 5.26.5 @@ -7402,13 +7408,13 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@20.19.9': + '@types/node@20.19.13': dependencies: undici-types: 6.21.0 '@types/pg@8.11.0': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 pg-protocol: 1.10.3 pg-types: 4.1.0 @@ -7426,7 +7432,7 @@ snapshots: '@types/sqlite3@3.1.11': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 '@types/stack-utils@2.0.3': {} @@ -7438,7 +7444,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 '@types/yargs-parser@21.0.3': {} @@ -7810,9 +7816,17 @@ snapshots: axe-core@4.10.3: {} - axios-auth-refresh@3.3.6(axios@1.7.7): + axios-auth-refresh@3.3.6(axios@1.11.0): dependencies: - axios: 1.7.7 + axios: 1.11.0 + + axios@1.11.0: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug axios@1.7.7: dependencies: @@ -7984,7 +7998,7 @@ snapshots: cloudflare@4.3.0(encoding@0.1.13): dependencies: - '@types/node': 18.19.121 + '@types/node': 18.19.124 '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 @@ -8677,9 +8691,9 @@ snapshots: etsy-ts@4.2.0(patch_hash=1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e): dependencies: - axios: 1.7.7 - axios-auth-refresh: 3.3.6(axios@1.7.7) - form-data: 4.0.3 + axios: 1.11.0 + axios-auth-refresh: 3.3.6(axios@1.11.0) + form-data: 4.0.4 tslib: 2.8.1 transitivePeerDependencies: - debug @@ -8824,6 +8838,8 @@ snapshots: flatted@3.3.3: {} + follow-redirects@1.15.11: {} + follow-redirects@1.15.9: {} for-each@0.3.5: @@ -9055,7 +9071,7 @@ snapshots: groq-sdk@0.3.0(encoding@0.1.13): dependencies: - '@types/node': 18.19.121 + '@types/node': 18.19.124 '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 @@ -9309,10 +9325,7 @@ snapshots: internmap@2.0.3: {} - ip-address@9.0.5: - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 + ip-address@10.0.1: optional: true ipaddr.js@1.9.1: {} @@ -9506,7 +9519,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.9 + '@types/node': 20.19.13 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -9518,7 +9531,7 @@ snapshots: jose@6.0.11: {} - js-tiktoken@1.0.20: + js-tiktoken@1.0.21: dependencies: base64-js: 1.5.1 @@ -9528,9 +9541,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsbn@1.1.0: - optional: true - json-bigint@1.0.0: dependencies: bignumber.js: 9.3.0 @@ -9579,7 +9589,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - langsmith@0.3.50(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)): + langsmith@0.3.67(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)): dependencies: '@types/uuid': 10.0.0 chalk: 4.1.2 @@ -10295,7 +10305,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - node-abi@3.75.0: + node-abi@3.77.0: dependencies: semver: 7.7.2 @@ -10648,7 +10658,7 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.75.0 + node-abi: 3.77.0 pump: 3.0.3 rc: 1.2.8 simple-get: 4.0.1 @@ -11177,14 +11187,14 @@ snapshots: dependencies: agent-base: 6.0.2 debug: 4.4.1 - socks: 2.8.6 + socks: 2.8.7 transitivePeerDependencies: - supports-color optional: true - socks@2.8.6: + socks@2.8.7: dependencies: - ip-address: 9.0.5 + ip-address: 10.0.1 smart-buffer: 4.2.0 optional: true @@ -11199,9 +11209,6 @@ snapshots: split2@4.2.0: {} - sprintf-js@1.1.3: - optional: true - sqlite3@5.1.7: dependencies: bindings: 1.5.0 From f89287334c791f3a710d9decffd76239f0d6f005 Mon Sep 17 00:00:00 2001 From: Derrick Chen Date: Tue, 9 Sep 2025 23:38:20 -0400 Subject: [PATCH 11/11] update ci workflow --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffd0ee7b..dd0a73d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: cache: "pnpm" - name: Install dependencies - run: pnpm install + run: pnpm install --no-frozen-lockfile - name: Check formatting run: pnpm run format:check