diff --git a/packages/jigsawstack/package.json b/packages/jigsawstack/package.json new file mode 100644 index 000000000..88fbf63f0 --- /dev/null +++ b/packages/jigsawstack/package.json @@ -0,0 +1,48 @@ +{ + "name": "@agentic/jigsawstack", + "version": "1.0.0", + "description": "Agentic adapter for the Jigsawstack AI SDK.", + "author": "Narcisse Egonu", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/transitive-bullshit/agentic.git" + }, + "type": "module", + "source": "./src/index.ts", + "types": "./dist/index.d.ts", + "sideEffects": false, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsup --config ../../tsup.config.ts", + "dev": "tsup --config ../../tsup.config.ts --watch", + "clean": "del dist", + "test": "run-s test:*", + "test:lint": "eslint .", + "test:typecheck": "tsc --noEmit", + "test:unit": "vitest run" + }, + "peerDependencies": { + "@agentic/core": "workspace:*" + }, + "devDependencies": { + "@agentic/core": "workspace:*", + "@agentic/tsconfig": "workspace:*" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "ky": "^1.5.0", + "p-throttle": "^6.1.0" + } +} \ No newline at end of file diff --git a/packages/jigsawstack/src/index.ts b/packages/jigsawstack/src/index.ts new file mode 100644 index 000000000..d64c94518 --- /dev/null +++ b/packages/jigsawstack/src/index.ts @@ -0,0 +1 @@ +export * from './jigsawstack-client' diff --git a/packages/jigsawstack/src/integration.test.ts b/packages/jigsawstack/src/integration.test.ts new file mode 100644 index 000000000..6a7cace13 --- /dev/null +++ b/packages/jigsawstack/src/integration.test.ts @@ -0,0 +1,57 @@ +// eslint-disable-next-line simple-import-sort/imports + +import { expect, test } from 'vitest' + +import { type jigsawstack,JigsawStackClient } from './jigsawstack-client' + +const jigsaw = new JigsawStackClient() + +test.skip('should run successfully and return the search result', async () => { + const params: jigsawstack.SearchParams = { + query: 'The leaning tower of pisa', + ai_overview: true, + spell_check: true + } + const result = await jigsaw.aiSearch(params) + expect(result).toBeTruthy() + expect(result.success).toBe(true) +}) + +test.skip('should run successfully and return the valid sql result', async () => { + const params: jigsawstack.TextToSqlParams = { + sql_schema: + "CREATE TABLE Transactions (transaction_id INT PRIMARY KEY, user_id INT NOT NULL,total_amount DECIMAL(10, 2 NOT NULL, transaction_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,status VARCHAR(20) DEFAULT 'pending',FOREIGN KEY(user_id) REFERENCES Users(user_id))", + prompt: + 'Generate a query to get transactions that amount exceed 10000 and sort by when created' + } + + const result = await jigsaw.textToSql(params) + expect(result).toBeTruthy() + expect(result.success).toBe(true) +}) + +test.skip('should return result.success is true for successful vocr', async () => { + const result = await jigsaw.vocr({ + prompt: 'Describe the image in detail', + url: 'https://rogilvkqloanxtvjfrkm.supabase.co/storage/v1/object/public/demo/Collabo%201080x842.jpg?t=2024-03-22T09%3A22%3A48.442Z' + }) + expect(result.success).toBe(true) +}) + +test('should run successfully and return the transcribe result', async () => { + const data = await jigsaw.speechToText({ + url: 'https://rogilvkqloanxtvjfrkm.supabase.co/storage/v1/object/public/demo/Video%201737458382653833217.mp4?t=2024-03-22T09%3A50%3A49.894' + }) + expect(data).toBeTruthy() + expect(data.success).toBe(true) +}) + +test.skip('should run successfully and return scrape result', async () => { + const params: jigsawstack.ScrapeParams = { + url: 'https://jigsawstack.com/pricing', + element_prompts: ['Pro Plan'] + } + const result = await jigsaw.aiScrape(params) + expect(result).toBeTruthy() + expect(result.success).toBe(true) +}) diff --git a/packages/jigsawstack/src/jigsawstack-client.ts b/packages/jigsawstack/src/jigsawstack-client.ts new file mode 100644 index 000000000..fd0d7ffeb --- /dev/null +++ b/packages/jigsawstack/src/jigsawstack-client.ts @@ -0,0 +1,210 @@ +import { AIFunctionsProvider, assert, getEnv } from '@agentic/core' +import ky, { type KyInstance } from 'ky' + +export namespace jigsawstack { + export interface BaseResponse { + success: boolean + } + + export const API_BASE_URL = 'https://api.jigsawstack.com/v1/' + + export interface SearchParams { + query: string + ai_overview?: boolean + safe_search?: 'moderate' | 'strict' | 'off' + spell_check?: boolean + } + + export interface SearchResponse extends BaseResponse { + query: string + spell_fixed: string + is_safe: boolean + ai_overview: string + results: { + title: string + url: string + description: string + content: string + is_safe: boolean + site_name: string + site_long_name: string + age: string + language: string + favicon: string + snippets: string[] + related_index: [] + }[] + } + + export interface CookieParameter { + name: string + value: string + url?: string + domain?: string + path?: string + secure?: boolean + httpOnly?: boolean + sameSite?: 'Strict' | 'Lax' | 'None' + expires?: boolean + priority?: string + sameParty?: boolean + } + + export interface ScrapeParams { + url: string + element_prompts: string[] + http_headers?: object + reject_request_pattern?: string[] + goto_options?: { + timeout: number + wait_until: string + } + wait_for?: { + mode: string + value: string | number + } + advance_config?: { + console: boolean + network: boolean + cookies: boolean + } + size_preset?: string + is_mobile?: boolean + scale?: number + width?: number + height?: number + cookies?: Array + } + + export interface ScrapeResponse extends BaseResponse { + data: any + } + + export interface VOCRParams { + prompt: string | string[] + url?: string + file_store_key?: string + } + + export interface VOCRResponse extends BaseResponse { + context: string + width: number + height: number + tags: string[] + has_text: boolean + sections: Array + } + + export interface TextToSqlParams { + prompt: string + sql_schema?: string + file_store_key?: string + } + + export interface TextToSqlResponse extends BaseResponse { + sql: string + } + + export interface SpeechToTextParams { + url?: string + file_store_key?: string + language?: string + translate?: boolean + by_speaker?: boolean + webhook_url?: string + } + + export interface SpeechToTextResponse extends BaseResponse { + text: string + chunks: Array<{ + timestamp: number[] + text: string + }> + status?: 'processing' | 'error' + id?: string + } +} + +/** + * Basic JigsawStack API wrapper. + */ +export class JigsawStackClient extends AIFunctionsProvider { + protected readonly apiKey: string + protected readonly ky: KyInstance + constructor({ + apiKey = getEnv('JIGSAWSTACK_API_KEY'), + timeoutMs = 60_000 + }: { + apiKey?: string + throttle?: boolean + timeoutMs?: number + } = {}) { + assert( + apiKey, + 'Please set the JIGSAWSTACK_API_KEY environment variable or pass it to the constructor as the apiKey field.' + ) + super() + this.apiKey = apiKey + this.ky = ky.extend({ + prefixUrl: jigsawstack.API_BASE_URL, + timeout: timeoutMs, + headers: { + 'x-api-key': this.apiKey + } + }) + } + + async aiSearch(params: jigsawstack.SearchParams) { + return this.ky + .get('web/search', { + searchParams: { + ...params + } + }) + .json() + } + + async aiScrape(params: jigsawstack.ScrapeParams) { + return this.ky + .post('ai/scrape', { + json: { + ...params + } + }) + .json() + } + + async vocr(params: jigsawstack.VOCRParams) { + return this.ky + .post('vocr', { + json: { + ...params + } + }) + .json() + } + + async textToSql( + params: jigsawstack.TextToSqlParams + ): Promise { + return this.ky + .post('ai/sql', { + json: { + ...params + } + }) + .json() + } + + async speechToText( + params: jigsawstack.SpeechToTextParams + ): Promise { + return this.ky + .post('ai/transcribe', { + json: { + ...params + } + }) + .json() + } +} diff --git a/packages/jigsawstack/tsconfig.json b/packages/jigsawstack/tsconfig.json new file mode 100644 index 000000000..ad53d9447 --- /dev/null +++ b/packages/jigsawstack/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@agentic/tsconfig/base.json", + "include": ["src"], + "exclude": ["node_modules", "dist"] + } + \ No newline at end of file