diff --git a/.gitignore b/.gitignore index d3ddc9f..2643c1b 100644 --- a/.gitignore +++ b/.gitignore @@ -135,3 +135,5 @@ test.ts .DS_Store .vscode + +local_tests/* diff --git a/src/audio/audio.ts b/src/audio/audio.ts index 46f81f7..571a514 100644 --- a/src/audio/audio.ts +++ b/src/audio/audio.ts @@ -1,14 +1,33 @@ import { RequestClient } from "../request"; import { createFileUploadFormData } from "../utils"; -import { SpeechToTextParams, SpeechToTextSyncResponse, SpeechToTextWebhookResponse } from "./interfaces"; +import { + SpeechToTextParams, + SpeechToTextParamsWithWebhook, + SpeechToTextParamsWithoutWebhook, + SpeechToTextResponse, + SpeechToTextWebhookResponse, +} from "./interfaces"; + class Audio { constructor(private readonly client: RequestClient) {} - speech_to_text(params: SpeechToTextParams): Promise; - speech_to_text(file: Blob | Buffer, params?: Omit): Promise; + + // Overload for webhook case + speech_to_text(params: SpeechToTextParamsWithWebhook): Promise; + + // Overload for Blob/Buffer with webhook + speech_to_text(file: Blob | Buffer, params: Omit): Promise; + + // Overload for non-webhook case + speech_to_text(params: SpeechToTextParamsWithoutWebhook): Promise; + + // Overload for Blob/Buffer without webhook + speech_to_text(file: Blob | Buffer, params?: Omit): Promise; + + // Implementation async speech_to_text( params: SpeechToTextParams | Blob | Buffer, options?: SpeechToTextParams - ): Promise { + ): Promise { if (params instanceof Blob || params instanceof Buffer) { const formData = createFileUploadFormData(params, options); return await this.client.fetchJSS("/ai/transcribe", "POST", formData); diff --git a/src/audio/interfaces.ts b/src/audio/interfaces.ts index 90dd79c..288bd2b 100644 --- a/src/audio/interfaces.ts +++ b/src/audio/interfaces.ts @@ -1,4 +1,5 @@ import { BaseResponse } from "../../types"; +import { LanguageCodes } from "../utils"; export interface SpeechToTextParams { url?: string; @@ -11,184 +12,28 @@ export interface SpeechToTextParams { chunk_duration?: number; } -export interface SpeechToTextSyncResponse extends BaseResponse { +export interface SpeechToTextParamsWithWebhook extends SpeechToTextParams { + webhook_url: string; +} + +export interface SpeechToTextParamsWithoutWebhook extends Omit { + webhook_url?: never; +} + +export interface SpeechToTextResponse extends BaseResponse { text: string; chunks: Array<{ timestamp: number[]; text: string; }>; - speakers?: { + speakers?: Array<{ speaker: string; timestamp: number[]; text: string; - }[]; + }>; } export interface SpeechToTextWebhookResponse extends BaseResponse { status: "processing" | "error"; id: string; } - -export type LanguageCodes = - | "af" - | "am" - | "ar" - | "as" - | "az" - | "ba" - | "be" - | "bg" - | "bn" - | "bo" - | "br" - | "bs" - | "ca" - | "ch" - | "co" - | "cs" - | "cy" - | "da" - | "de" - | "dv" - | "dz" - | "el" - | "en" - | "eo" - | "es" - | "et" - | "eu" - | "fa" - | "ff" - | "fi" - | "fj" - | "fo" - | "fr" - | "fy" - | "ga" - | "gd" - | "gl" - | "gu" - | "gv" - | "ha" - | "he" - | "hi" - | "hr" - | "ht" - | "hu" - | "hy" - | "id" - | "ig" - | "is" - | "it" - | "iu" - | "ja" - | "jv" - | "ka" - | "kg" - | "ki" - | "kj" - | "kk" - | "kl" - | "km" - | "kn" - | "ko" - | "kr" - | "ks" - | "ku" - | "kv" - | "kw" - | "ky" - | "la" - | "lb" - | "lg" - | "li" - | "ln" - | "lo" - | "lt" - | "lu" - | "lv" - | "mg" - | "mh" - | "mi" - | "mk" - | "ml" - | "mn" - | "mo" - | "mr" - | "ms" - | "mt" - | "my" - | "na" - | "nb" - | "nd" - | "ne" - | "ng" - | "nl" - | "nn" - | "no" - | "nr" - | "nv" - | "ny" - | "oc" - | "oj" - | "om" - | "or" - | "os" - | "pa" - | "pi" - | "pl" - | "ps" - | "pt" - | "qu" - | "rm" - | "rn" - | "ro" - | "ru" - | "rw" - | "sa" - | "sc" - | "sd" - | "se" - | "sg" - | "sh" - | "si" - | "sk" - | "sl" - | "sm" - | "sn" - | "so" - | "sq" - | "sr" - | "ss" - | "st" - | "su" - | "sv" - | "sw" - | "ta" - | "te" - | "tg" - | "th" - | "ti" - | "tk" - | "tl" - | "tn" - | "to" - | "tr" - | "ts" - | "tt" - | "tw" - | "ty" - | "ug" - | "uk" - | "ur" - | "uz" - | "ve" - | "vi" - | "vo" - | "wo" - | "xh" - | "yi" - | "yo" - | "zh" - | "zh-TW" - | "zu"; diff --git a/src/classification/index.ts b/src/classification/index.ts index ffaf2d4..f528a7c 100644 --- a/src/classification/index.ts +++ b/src/classification/index.ts @@ -1,5 +1,5 @@ import { RequestClient } from "../request"; -import { ClassificationImageParams, ClassificationResponse, ClassificationTextParams } from "./interfaces"; +import { ClassificationParams, ClassificationResponse } from "./interfaces"; class Classification { private readonly client: RequestClient; @@ -7,11 +7,7 @@ class Classification { this.client = client; } - text = async (params: ClassificationTextParams): Promise => { - return await this.client.fetchJSS("/classification", "POST", params); - }; - - image = async (params: ClassificationImageParams): Promise => { + classify = async (params: ClassificationParams): Promise => { return await this.client.fetchJSS("/classification", "POST", params); }; } diff --git a/src/classification/interfaces.ts b/src/classification/interfaces.ts index a2f345e..7c9a25b 100644 --- a/src/classification/interfaces.ts +++ b/src/classification/interfaces.ts @@ -4,27 +4,14 @@ export interface ClassificationResponse extends BaseResponse { predictions: (string | string[])[]; } -export interface ClassificationTextParams { +export interface ClassificationParams { dataset: Array<{ - type: "text"; + type: "text" | "image"; value: string; }>; labels: Array<{ key?: string; - type: "text"; - value: string; - }>; - multiple_labels?: boolean; -} - -export interface ClassificationImageParams { - dataset: Array<{ - type: "image"; - value: string; - }>; - labels: Array<{ - key?: string; - type: "image" | "text"; + type: "text" | "image"; value: string; }>; multiple_labels?: boolean; diff --git a/src/core.ts b/src/core.ts index 1d3b8aa..f456478 100644 --- a/src/core.ts +++ b/src/core.ts @@ -51,12 +51,13 @@ export const JigsawStack = (config?: BaseConfig) => { }, web: { ai_scrape: web.ai_scrape, - html_to_any: web.html_to_any, + html_to_any: createBoundMethod(web, web.html_to_any), search: web.search, search_suggestions: web.search_suggestions, + deep_research: web.deep_research, }, store, validate, - classification, + classification: classification.classify, }; }; diff --git a/src/general/index.ts b/src/general/index.ts index 56fc0b3..7183e52 100644 --- a/src/general/index.ts +++ b/src/general/index.ts @@ -62,8 +62,8 @@ class General { }; summary(params: SummaryParams & { type: "points" }): Promise; - summary(params: SummaryParams & { type: "text" }): Promise; - async summary(params: SummaryParams): Promise { + summary(params: SummaryParams & { type: "text" }): Promise; + async summary(params: SummaryParams): Promise<(BaseResponse & { summary: string[] }) | (BaseResponse & { summary: string })> { if (params.type === "points") { const resp = await this.client.fetchJSS("/ai/summary", "POST", params); return resp as BaseResponse & { summary: string[] }; diff --git a/src/general/interfaces.ts b/src/general/interfaces.ts index 1bd2e99..1d6e80d 100644 --- a/src/general/interfaces.ts +++ b/src/general/interfaces.ts @@ -1,4 +1,5 @@ import { BaseResponse } from "../../types"; +import { LanguageCodes } from "../utils"; export type TextToSQLParams = { prompt: string; @@ -7,6 +8,10 @@ export type TextToSQLParams = { file_store_key?: string; }; +export interface TextToSQLResponse extends BaseResponse { + sql: string; +} + export interface ImageGenerationParams { prompt: string; aspect_ratio?: "1:1" | "16:9" | "21:9" | "3:2" | "2:3" | "4:5" | "5:4" | "3:4" | "4:3" | "9:16" | "9:21"; @@ -43,13 +48,13 @@ export interface SentimentResponse extends BaseResponse { } export interface TranslateResponse extends BaseResponse { - translated_text: string; + translated_text: string | string[]; } export interface TranslateParams { - current_language?: string; - target_language: string; text: string | string[]; + current_language?: LanguageCodes; + target_language: LanguageCodes; } export type TranslateImageParams = { @@ -76,21 +81,17 @@ export interface SpeechToTextWebhookResponse extends BaseResponse { id: string; } -export interface TextToSQLResponse extends BaseResponse { - sql: string; -} - export interface SummaryParams { - text?: string; // maximum 300_000 characters + text?: string | null; // maximum 300_000 characters + url?: string | null; // PDF url only supported type?: "text" | "points"; - url?: string; // PDF url only supported - file_store_key?: string; - max_points?: number; // max 100 - max_characters?: number; + file_store_key?: string | null; + max_points?: number | null; // max 100 + max_characters?: number | null; } export interface SummaryResponse extends BaseResponse { - summary: string; + summary: string | string[]; } export interface PredictionParams { @@ -117,5 +118,5 @@ export interface EmbeddingParams { export interface EmbeddingResponse extends BaseResponse { embeddings: number[][]; - chunks: string[]; // only for text + chunks?: Array<{ text: string; timestamp: number[] }>; // only available for text and audio } diff --git a/src/store/interfaces/file.ts b/src/store/interfaces/file.ts index 6c9da06..7acd9b6 100644 --- a/src/store/interfaces/file.ts +++ b/src/store/interfaces/file.ts @@ -7,10 +7,6 @@ export interface FileUploadParams { temp_public_url?: boolean; } -export interface FileRetrieveParams { - key: string; -} - export interface FileUploadResponse extends BaseResponse { key: string; url: string; diff --git a/src/utils.ts b/src/utils.ts index a189153..8bd3e73 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -34,3 +34,442 @@ export function createFileUploadFormData(file: Blob | Buffer, options?: Record; nsfw(file: Blob | Buffer, params?: Omit): Promise; @@ -34,9 +32,9 @@ class Validate { return await this.client.fetchJSS("/validate/spell_check", "POST", { text, language_code }); }; - spamcheck(text: string): Promise; - spamcheck(text: string[]): Promise; - async spamcheck(text: string | string[]): Promise { + spamcheck({ text }: { text: string }): Promise; + spamcheck({ text }: { text: string[] }): Promise; + async spamcheck({ text }: { text: string | string[] }): Promise { return await this.client.fetchJSS("/validate/spam_check", "POST", { text }); } } diff --git a/src/validate/interfaces.ts b/src/validate/interfaces.ts index 649b778..4fd0a80 100644 --- a/src/validate/interfaces.ts +++ b/src/validate/interfaces.ts @@ -1,4 +1,5 @@ -export interface EmailValidationResponse { +import { BaseResponse } from "../../types"; +export interface EmailValidationResponse extends BaseResponse { email: string; disposable: boolean; role_account: boolean; @@ -9,30 +10,19 @@ export interface EmailValidationResponse { valid: boolean; } -export interface NSFWValidationResponse { - success: boolean; - nsfw: boolean; - nudity: boolean; - gore: boolean; - nsfw_score: number; - nudity_score: number; - gore_score: number; -} - export interface ProfanityParams { text: string; censor_replacement?: string; } -export interface ProfanityValidationResponse { - success: boolean; +export interface ProfanityValidationResponse extends BaseResponse { message: string; clean_text: string; - profanities: { - profanity: string; + profanities: Array<{ + profanity: string | null; startIndex: number; endIndex: number; - }[]; + }>; profanities_found: boolean; } @@ -41,11 +31,10 @@ export interface SpellCheckParams { language_code?: string; } -export interface SpellCheckValidationResponse { - success: boolean; +export interface SpellCheckValidationResponse extends BaseResponse { misspellings_found: boolean; misspellings: Array<{ - word: string; + word: string | null; startIndex: number; endIndex: number; expected: string[]; @@ -54,23 +43,30 @@ export interface SpellCheckValidationResponse { auto_correct_text: string; } -export interface SpamCheckValidationResponse { - success: boolean; +export interface SpamCheckValidationResponse extends BaseResponse { check: { is_spam: boolean; score: number; }; } -export interface SpamCheckValidationArrayResponse { - success: boolean; - check: { +export interface SpamCheckValidationArrayResponse extends BaseResponse { + check: Array<{ is_spam: boolean; score: number; - }[]; + }>; } export interface NSFWParams { url?: string; file_store_key?: string; } + +export interface NSFWValidationResponse extends BaseResponse { + nsfw: boolean; + nudity: boolean; + gore: boolean; + nsfw_score: number; + nudity_score: number; + gore_score: number; +} diff --git a/src/vercel-ai-toolkit.ts b/src/vercel-ai-toolkit.ts index a6bcb91..610e50d 100644 --- a/src/vercel-ai-toolkit.ts +++ b/src/vercel-ai-toolkit.ts @@ -1,7 +1,7 @@ import { z } from "zod"; import { BaseConfig } from "../types"; -import { LanguageCodes } from "./audio/interfaces"; import { JigsawStack } from "./core"; +import { LanguageCodes } from "./utils"; import { tool } from "./vercel-tool"; export interface JigsawStackToolOptions { tools?: string[]; @@ -74,8 +74,8 @@ export class JigsawStackToolSet { execute: async ({ text, target_language, current_language }) => { return await this.jigsawStack.translate.text({ text, - target_language, - current_language, + target_language: target_language as LanguageCodes, + current_language: current_language as LanguageCodes, }); }, }), @@ -179,7 +179,7 @@ export class JigsawStackToolSet { parameters: z.object({ html: z.string().optional().describe("HTML content to convert"), url: z.string().optional().describe("URL of webpage to convert"), - type: z.string().optional().describe("Output format type"), + type: z.enum(["pdf", "png", "jpeg", "webp"]).optional().describe("Output format type"), width: z.number().optional().describe("Output width"), height: z.number().optional().describe("Output height"), full_page: z.boolean().optional().describe("Capture full page"), @@ -225,7 +225,7 @@ export class JigsawStackToolSet { query: z.string().describe("Query to get suggestions for"), }), execute: async ({ query }) => { - return await this.jigsawStack.web.search_suggestions(query); + return await this.jigsawStack.web.search_suggestions({ query }); }, }), @@ -332,7 +332,7 @@ export class JigsawStackToolSet { text: z.string().describe("Text to check for spam"), }), execute: async ({ text }) => { - return await this.jigsawStack.validate.spamcheck(text); + return await this.jigsawStack.validate.spamcheck({ text }); }, }), }; diff --git a/src/vision/interfaces.ts b/src/vision/interfaces.ts index aba7b4b..ae1cfd4 100644 --- a/src/vision/interfaces.ts +++ b/src/vision/interfaces.ts @@ -1,32 +1,14 @@ +import { BaseResponse } from "../../types"; + export type VOCRParams = { - prompt?: string | string[]; + prompt?: string | string[] | Record; url?: string; file_store_key?: string; page_range?: Array; }; -interface Bounds { - top_left: { - x: number; - y: number; - }; - top_right: { - x: number; - y: number; - }; - bottom_left: { - x: number; - y: number; - }; - bottom_right: { - x: number; - y: number; - }; -} - -export interface VOCRResponse { - success: boolean; - context: string; +export interface VOCRResponse extends BaseResponse { + context?: string | Record; width: number; height: number; tags: string[]; @@ -35,10 +17,10 @@ export interface VOCRResponse { text: string; lines: Array<{ text: string; - bounds: Bounds; + bounds: BoundingBox; words: Array<{ text: string; - bounds: Bounds; + bounds: BoundingBox; }>; }>; }>; @@ -53,9 +35,10 @@ export type ObjectDetectionParams = { features?: ("object_detection" | "gui")[]; annotated_image?: boolean; return_type?: "url" | "base64"; + return_masks?: boolean; }; -export interface ObjectDetectionResponse { +export interface ObjectDetectionResponse extends BaseResponse { // Optional annotated image - included only if annotated_image=true and objects/gui_elements exist annotated_image?: string; // URL or base64 string depending on return_type @@ -64,11 +47,15 @@ export interface ObjectDetectionResponse { // Optional detected objects - included only if features includes "object_detection" objects?: DetectedObject[]; + + tags?: string[]; } interface GuiElement { bounds: BoundingBox; content: string | null; // Can be null if no object detected + interactivity: boolean; + type: string; } interface DetectedObject { diff --git a/src/web/interfaces/deep_research.ts b/src/web/interfaces/deep_research.ts index 8d69030..c978e1b 100644 --- a/src/web/interfaces/deep_research.ts +++ b/src/web/interfaces/deep_research.ts @@ -1,17 +1,18 @@ +import { BaseResponse } from "../../../types"; +import { CountryCode } from "../../utils"; // Input parameters interface for reference export interface DeepResearchParams { query: string; spell_check?: boolean; safe_search?: "strict" | "moderate" | "off"; - country_code?: string; + country_code?: CountryCode | null; max_depth?: number; max_breadth?: number; max_output_tokens?: number; target_output_tokens?: number; } -export interface DeepResearchResponse { - success: boolean; +export interface DeepResearchResponse extends BaseResponse { query: string; results: string; sources: SearchResult[]; diff --git a/src/web/interfaces/html_to_any.ts b/src/web/interfaces/html_to_any.ts index 1750250..a05d993 100644 --- a/src/web/interfaces/html_to_any.ts +++ b/src/web/interfaces/html_to_any.ts @@ -1,23 +1,45 @@ +import { BaseResponse } from "../../../types"; +import { ScreenSizeNames } from "../../utils"; + export interface HTMLAnyParams { - html?: string; - url?: string; - use_graphic_renderer?: boolean; - dark_mode?: boolean; - is_mobile?: boolean; - pdf_page_range?: string; - pdf_print_background?: boolean; - pdf_display_header_footer?: boolean; - size_preset?: string; + html?: string | null; + url?: string | null; + goto_options?: { + timeout: number; + wait_until: "load" | "domcontentloaded" | "networkidle0" | "networkidle2"; + } | null; + full_page?: boolean; + omit_background?: boolean; + type?: "pdf" | "png" | "jpeg" | "webp"; height?: number; width?: number; - type?: string; - quality?: number; - omit_background?: boolean; - full_page?: boolean; scale?: number; - goto_options?: { - timeout: number; - wait_until: string; - }; + is_mobile?: boolean; + dark_mode?: boolean; + use_graphic_renderer?: boolean; + size_preset?: ScreenSizeNames | null; + pdf_display_header_footer?: boolean; + pdf_print_background?: boolean; + pdf_page_range?: string | null; return_type?: "url" | "binary" | "base64"; + quality?: number; +} + +// response for "url" and "base64" return types (both return url string) +export interface HTMLAnyURLResponse extends BaseResponse { + url: string; +} + +export interface HTMLAnyBinaryResponse extends Response { + // binary response doesn't have structure +} + +export interface HTMLAnyURLParams extends Omit { + return_type: "url" | "base64"; +} + +export interface HTMLAnyBinaryParams extends Omit { + return_type: "binary"; } + +export type HTMLAnyResponse = HTMLAnyURLResponse | HTMLAnyBinaryResponse; diff --git a/src/web/interfaces/scrape.ts b/src/web/interfaces/scrape.ts index 91acf9a..bbdc51d 100644 --- a/src/web/interfaces/scrape.ts +++ b/src/web/interfaces/scrape.ts @@ -1,43 +1,42 @@ -export interface CookieParameter { +import { BaseResponse } from "../../../types"; +import { ScreenSizeNames } from "../../utils"; + +interface CookieParameter { name: string; value: string; - url?: string; domain?: string; - path?: string; + url?: string; secure?: boolean; httpOnly?: boolean; - sameSite?: "Strict" | "Lax" | "None"; - expires?: boolean; - priority?: string; sameParty?: boolean; + expires?: number; + priority?: "Low" | "High" | "Medium"; } export interface BaseAIScrapeParams { - url?: string; - html?: string; - root_element_selector?: string; - page_position?: number; - http_headers?: object; - reject_request_pattern?: string[]; + url?: string | null; + html?: string | null; + http_headers?: Record | null; + reject_request_pattern?: string[] | null; goto_options?: { timeout?: number; wait_until?: "load" | "domcontentloaded" | "networkidle0" | "networkidle2"; } | null; wait_for?: { - mode: string; + mode: "selector" | "timeout" | "function"; value: string | number; - }; + } | null; advance_config?: { console?: boolean; network?: boolean; cookies?: boolean; - }; - size_preset?: string; + } | null; + size_preset?: ScreenSizeNames | null; is_mobile?: boolean; scale?: number; width?: number; height?: number; - cookies?: Array; + cookies?: Array | null; force_rotate_proxy?: boolean; byo_proxy?: { server: string; @@ -45,24 +44,18 @@ export interface BaseAIScrapeParams { username: string; password: string; }; - }; + } | null; features?: Array<"meta" | "link"> | null; + selectors?: Array | null; } -export interface AIScrapeParamsWithSelector extends BaseAIScrapeParams { - selectors: Array; - element_prompts?: string[]; -} - -export interface AIScrapeParamsWithPrompts extends BaseAIScrapeParams { - selectors?: Array; - element_prompts?: string[]; +export interface AIScrapeParams extends BaseAIScrapeParams { + element_prompts?: string[] | null; + root_element_selector?: string; + page_position?: number; } -export type AIScrapeParams = AIScrapeParamsWithSelector | AIScrapeParamsWithPrompts; - -export interface AIScrapeResponse { - success: boolean; +export interface AIScrapeResponse extends BaseResponse { data: Array<{ key: string; selector: string; @@ -79,9 +72,16 @@ export interface AIScrapeResponse { page_position_length: number; advance_config: | { - console?: any[]; - network?: any[]; - cookies?: any[]; + console?: any; + network?: { + url: string; + method: string; + status: number; + headers: Record; + body: string | null; + type: "request" | "response"; + }; + cookies?: any; } | undefined; context: any; diff --git a/src/web/interfaces/search.ts b/src/web/interfaces/search.ts index e8fdd8e..8d77c4d 100644 --- a/src/web/interfaces/search.ts +++ b/src/web/interfaces/search.ts @@ -1,3 +1,5 @@ +import { BaseResponse } from "../../../types"; +import { CountryCode } from "../../utils"; export interface SearchParams { query: string; spell_check?: boolean; @@ -5,15 +7,8 @@ export interface SearchParams { safe_search?: "strict" | "moderate" | "off"; ai_overview?: boolean; byo_urls?: string[]; - country_code?: string; + country_code?: CountryCode; auto_scrape?: boolean; - deep_research?: boolean; - deep_research_config?: { - max_depth?: number; - max_breadth?: number; - max_output_tokens?: number; - target_output_tokens?: number; - }; } interface RelatedIndex { @@ -23,13 +18,12 @@ interface RelatedIndex { is_safe?: boolean; } -export interface SearchResponse { - success: boolean; +export interface SearchResponse extends BaseResponse { query: string; ai_overview?: string; spell_fixed: boolean; is_safe: boolean; - results: { + results: Array<{ title: string; url: string; description: string; @@ -48,10 +42,10 @@ export interface SearchResponse { favicon: string; snippets: string[]; related_index: RelatedIndex[]; - }[]; + }>; image_urls: string[]; links: string[]; - geo_results: { + geo_results: Array<{ type: string; full_address: string; name: string; @@ -69,10 +63,9 @@ export interface SearchResponse { }; poi_category?: string; additional_properties?: any; - }[]; + }>; } -export interface SuggestionResponse { - success: boolean; +export interface SuggestionResponse extends BaseResponse { suggestions: string[]; } diff --git a/src/web/web.ts b/src/web/web.ts index ca54599..9e90173 100644 --- a/src/web/web.ts +++ b/src/web/web.ts @@ -1,7 +1,6 @@ -import { respToFileChoice } from "../helpers"; import { RequestClient } from "../request"; import { DeepResearchParams, DeepResearchResponse } from "./interfaces/deep_research"; -import { HTMLAnyParams } from "./interfaces/html_to_any"; +import { HTMLAnyBinaryParams, HTMLAnyBinaryResponse, HTMLAnyParams, HTMLAnyURLParams, HTMLAnyURLResponse } from "./interfaces/html_to_any"; import { AIScrapeParams, AIScrapeResponse } from "./interfaces/scrape"; import { SearchParams, SearchResponse, SuggestionResponse } from "./interfaces/search"; class Web { @@ -11,10 +10,17 @@ class Web { return await this.client.fetchJSS("/ai/scrape", "POST", params); }; - html_to_any = async (params: HTMLAnyParams) => { - const resp = await this.client.fetchJSS("/web/html_to_any", "POST", params); - return respToFileChoice(resp); - }; + // Simplified function overloads + html_to_any(params: HTMLAnyURLParams): Promise; + html_to_any(params: HTMLAnyBinaryParams): Promise; + html_to_any(params: HTMLAnyParams): Promise; + async html_to_any(params: HTMLAnyParams): Promise { + if (params.return_type === "binary") { + return (await this.client.fetchJSS("/web/html_to_any", "POST", params)) as HTMLAnyBinaryResponse; + } + // For both "url" and "base64", return the same structure with url property + return (await this.client.fetchJSS("/web/html_to_any", "POST", params)) as HTMLAnyURLResponse; + } deep_research = async (params: DeepResearchParams): Promise => { return await this.client.fetchJSS("/web/deep_research", "POST", params); @@ -23,7 +29,7 @@ class Web { search = async (params: SearchParams): Promise => { return await this.client.fetchJSS("/web/search", "POST", params); }; - search_suggestions = async (query: string): Promise => { + search_suggestions = async ({ query }: { query: string }): Promise => { return await this.client.fetchJSS(`/web/search/suggest?query=${query}`, "GET", undefined); }; } diff --git a/tests/classification.test.ts b/tests/classification.test.ts index d8f3206..7fdcfa8 100644 --- a/tests/classification.test.ts +++ b/tests/classification.test.ts @@ -77,7 +77,7 @@ describe("Text Classification API", () => { // Test missing required parameters test("should fail when no parameters are provided", async () => { try { - await client.classification.text({} as any); + await client.classification({} as any); throw new Error("Expected API call to fail with no parameters"); } catch (error) { expectType(error, "object"); @@ -86,7 +86,7 @@ describe("Text Classification API", () => { test("should fail when dataset is missing", async () => { try { - await client.classification.text({ + await client.classification({ labels: TEXT_LABELS, } as any); throw new Error("Expected API call to fail with missing dataset"); @@ -97,7 +97,7 @@ describe("Text Classification API", () => { test("should fail when labels are missing", async () => { try { - await client.classification.text({ + await client.classification({ dataset: TEST_TEXT_DATA, labels: [], } as any); @@ -109,7 +109,7 @@ describe("Text Classification API", () => { test("should fail when dataset is empty", async () => { try { - await client.classification.text({ + await client.classification({ dataset: [], labels: TEXT_LABELS, }); @@ -121,7 +121,7 @@ describe("Text Classification API", () => { // Basic functionality tests test("should work with basic text classification", async () => { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [ { type: "text" as const, value: "This is a great product! I love it." }, { type: "text" as const, value: "This is a great product! I hate it." }, @@ -145,7 +145,7 @@ describe("Text Classification API", () => { }); test("should work with multiple text samples", async () => { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [ { type: "text" as const, value: "This is a great product! I love it." }, { type: "text" as const, value: "This product is terrible and broken." }, @@ -168,7 +168,7 @@ describe("Text Classification API", () => { }); test("should work with multiple_labels enabled", async () => { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: "This is a great product with excellent customer service!" }], labels: [ { key: "quality", type: "text" as const, value: "relates to product quality" }, @@ -193,7 +193,7 @@ describe("Text Classification API", () => { }); test("should work with multiple_labels disabled", async () => { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: "This is a great product! I love it." }], labels: [ { key: "positive", type: "text" as const, value: "positive sentiment" }, @@ -210,7 +210,7 @@ describe("Text Classification API", () => { test("should work with long text", async () => { const longText = "This is a comprehensive review of a product that I purchased recently. ".repeat(10); - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: longText }], labels: [ { key: "review", type: "text" as const, value: "product review" }, @@ -223,7 +223,7 @@ describe("Text Classification API", () => { }); test("should work with special characters and unicode", async () => { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: "¡Excelente producto! 🚀 Me encanta. Ñoño café français." }], labels: [ { key: "positive", type: "text" as const, value: "positive sentiment" }, @@ -245,7 +245,7 @@ describe("Text Classification API", () => { }); } - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: "This is a test text for classification." }], labels: labels, }); @@ -257,7 +257,7 @@ describe("Text Classification API", () => { // Edge cases and error handling test("should handle empty text gracefully", async () => { try { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: "" }], labels: [ { key: "empty", type: "text" as const, value: "empty text" }, @@ -275,7 +275,7 @@ describe("Text Classification API", () => { test("should handle whitespace-only text", async () => { try { - const result = await client.classification.text({ + const result = await client.classification({ dataset: [{ type: "text" as const, value: " \n\t " }], labels: [ { key: "whitespace", type: "text" as const, value: "whitespace content" }, @@ -293,7 +293,7 @@ describe("Text Classification API", () => { test("should fail with invalid dataset type", async () => { try { - await client.classification.text({ + await client.classification({ dataset: [{ type: "image" as any, value: "This is a great product! I love it." }], labels: [{ key: "positive", type: "text" as const, value: "positive sentiment" }], } as any); @@ -305,7 +305,7 @@ describe("Text Classification API", () => { test("should fail with invalid label type", async () => { try { - await client.classification.text({ + await client.classification({ dataset: [{ type: "text" as const, value: "This is a great product! I love it." }], labels: [{ key: "positive", type: "image" as any, value: "positive sentiment" }], } as any); @@ -327,7 +327,7 @@ describe("Image Classification API", () => { // Test missing required parameters test("should fail when no parameters are provided", async () => { try { - await client.classification.image({} as any); + await client.classification({} as any); throw new Error("Expected API call to fail with no parameters"); } catch (error) { expectType(error, "object"); @@ -336,7 +336,7 @@ describe("Image Classification API", () => { test("should fail when dataset is missing", async () => { try { - await client.classification.image({ + await client.classification({ labels: IMAGE_LABELS, } as any); throw new Error("Expected API call to fail with missing dataset"); @@ -347,7 +347,7 @@ describe("Image Classification API", () => { test("should fail when labels are missing", async () => { try { - await client.classification.image({ + await client.classification({ dataset: TEST_IMAGE_DATA, } as any); throw new Error("Expected API call to fail with missing labels"); @@ -358,7 +358,7 @@ describe("Image Classification API", () => { test("should fail when dataset is empty", async () => { try { - await client.classification.image({ + await client.classification({ dataset: [], labels: IMAGE_LABELS, }); @@ -370,7 +370,7 @@ describe("Image Classification API", () => { test("should fail when labels are empty", async () => { try { - await client.classification.image({ + await client.classification({ dataset: TEST_IMAGE_DATA, labels: [], }); @@ -382,7 +382,7 @@ describe("Image Classification API", () => { // Basic functionality tests test("should work with basic image classification", async () => { - const result = await client.classification.image({ + const result = await client.classification({ dataset: TEST_IMAGE_DATA, labels: IMAGE_LABELS, }); @@ -404,7 +404,7 @@ describe("Image Classification API", () => { }); test("should work with multiple images", async () => { - const result = await client.classification.image({ + const result = await client.classification({ dataset: [ { type: "image" as const, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }, { type: "image" as const, value: "https://t3.ftcdn.net/jpg/02/95/44/22/240_F_295442295_OXsXOmLmqBUfZreTnGo9PREuAPSLQhff.jpg" }, @@ -425,7 +425,7 @@ describe("Image Classification API", () => { }); test("should work with multiple_labels enabled for images", async () => { - const result = await client.classification.image({ + const result = await client.classification({ dataset: [{ type: "image" as const, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }], labels: [ { key: "banana", type: "text" as const, value: "banana" }, @@ -449,7 +449,7 @@ describe("Image Classification API", () => { }); test("should work with multiple_labels disabled for images", async () => { - const result = await client.classification.image({ + const result = await client.classification({ dataset: [{ type: "image" as const, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }], labels: [ { key: "banana", type: "text" as const, value: "banana" }, @@ -475,7 +475,7 @@ describe("Image Classification API", () => { }); } - const result = await client.classification.image({ + const result = await client.classification({ dataset: [{ type: "image" as const, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }], labels: labels, }); @@ -487,7 +487,7 @@ describe("Image Classification API", () => { // Edge cases and error handling test("should handle invalid image URL gracefully", async () => { try { - await client.classification.image({ + await client.classification({ dataset: [{ type: "image" as const, value: "not-a-valid-url" }], labels: [{ key: "banana", type: "text" as const, value: "banana" }], }); @@ -499,7 +499,7 @@ describe("Image Classification API", () => { test("should handle empty image URL", async () => { try { - await client.classification.image({ + await client.classification({ dataset: [{ type: "image" as const, value: "" }], labels: [{ key: "banana", type: "text" as const, value: "banana" }], }); @@ -511,7 +511,7 @@ describe("Image Classification API", () => { test("should fail with invalid dataset type", async () => { try { - await client.classification.image({ + await client.classification({ dataset: [{ type: "text" as any, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }], labels: [{ key: "banana", type: "text" as const, value: "banana" }], } as any); @@ -523,7 +523,7 @@ describe("Image Classification API", () => { test("should fail with invalid label type", async () => { try { - await client.classification.image({ + await client.classification({ dataset: [ { type: "image" as const, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }, ], @@ -537,7 +537,7 @@ describe("Image Classification API", () => { // Complex scenario test test("should work with comprehensive image classification configuration", async () => { - const result = await client.classification.image({ + const result = await client.classification({ dataset: [ { type: "image" as const, value: "https://as2.ftcdn.net/v2/jpg/02/24/11/57/1000_F_224115780_2ssvcCoTfQrx68Qsl5NxtVIDFWKtAgq2.jpg" }, { type: "image" as const, value: "https://t3.ftcdn.net/jpg/02/95/44/22/240_F_295442295_OXsXOmLmqBUfZreTnGo9PREuAPSLQhff.jpg" }, @@ -572,7 +572,7 @@ describe("Classification API Edge Cases", () => { }); } - const result = await client.classification.text({ + const result = await client.classification({ dataset: dataset, labels: [ { key: "test", type: "text" as const, value: "test content" }, diff --git a/tests/web.test.ts b/tests/web.test.ts index 9c9e225..49fb077 100644 --- a/tests/web.test.ts +++ b/tests/web.test.ts @@ -1103,21 +1103,6 @@ describe("Web Search API", () => { expectArray(result.results); }); - test("should work with deep research mode", async () => { - const result = await client.web.search({ - query: "What is diffusion?", - deep_research: true, - deep_research_config: { - max_depth: 3, - max_breadth: 2, - max_output_tokens: 12000, - }, - }); - - expectSuccess(result); - expectArray(result.results); - }); - test("should handle empty query gracefully", async () => { try { await client.web.search({ @@ -1162,7 +1147,7 @@ describe("Web Search Suggestions API", () => { }); test("should work with basic query", async () => { - const result = await client.web.search_suggestions("artificial int"); + const result = await client.web.search_suggestions({ query: "artificial int" }); expectSuccess(result); expectProperty(result, "suggestions"); @@ -1175,7 +1160,7 @@ describe("Web Search Suggestions API", () => { }); test("should work with partial query", async () => { - const result = await client.web.search_suggestions("machine learn"); + const result = await client.web.search_suggestions({ query: "machine learn" }); expectSuccess(result); expectArray(result.suggestions); @@ -1191,7 +1176,7 @@ describe("Web Search Suggestions API", () => { test("should fail with empty string", async () => { try { - await client.web.search_suggestions(""); + await client.web.search_suggestions({ query: "" }); throw new Error("Expected API call to fail with empty string"); } catch (error) { expectType(error, "object"); @@ -1202,7 +1187,7 @@ describe("Web Search Suggestions API", () => { const longQuery = "a".repeat(201); // Over 200 character limit try { - await client.web.search_suggestions(longQuery); + await client.web.search_suggestions({ query: longQuery }); throw new Error("Expected API call to fail with query too long"); } catch (error) { expectType(error, "object"); @@ -1210,14 +1195,14 @@ describe("Web Search Suggestions API", () => { }); test("should work with special characters", async () => { - const result = await client.web.search_suggestions("what is the capital?"); + const result = await client.web.search_suggestions({ query: "what is the capital?" }); expectSuccess(result); expectArray(result.suggestions); }); test("should work with unicode characters", async () => { - const result = await client.web.search_suggestions("café français"); + const result = await client.web.search_suggestions({ query: "café français" }); expectSuccess(result); expectArray(result.suggestions);