kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/643/head^2
rodzic
e3f1b5641f
commit
783f375d38
|
@ -44,7 +44,6 @@
|
||||||
"test:unit": "vitest run"
|
"test:unit": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dexaai/dexter": "^2.0.0",
|
|
||||||
"@nangohq/node": "^0.39.30",
|
"@nangohq/node": "^0.39.30",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"delay": "^6.0.0",
|
"delay": "^6.0.0",
|
||||||
|
@ -52,12 +51,9 @@
|
||||||
"exit-hook": "^4.0.0",
|
"exit-hook": "^4.0.0",
|
||||||
"jsonrepair": "^3.6.1",
|
"jsonrepair": "^3.6.1",
|
||||||
"ky": "^1.2.4",
|
"ky": "^1.2.4",
|
||||||
"openai": "^4.47.1",
|
|
||||||
"p-map": "^7.0.2",
|
"p-map": "^7.0.2",
|
||||||
"p-retry": "^6.2.0",
|
"p-retry": "^6.2.0",
|
||||||
"p-throttle": "^6.1.0",
|
"p-throttle": "^6.1.0",
|
||||||
"proxycurl-js-linkedin-profile-scraper": "^1.0.2",
|
|
||||||
"reflect-metadata": "^0.2.2",
|
|
||||||
"restore-cursor": "^5.0.0",
|
"restore-cursor": "^5.0.0",
|
||||||
"tiny-invariant": "^1.3.3",
|
"tiny-invariant": "^1.3.3",
|
||||||
"twitter-api-sdk": "^1.2.1",
|
"twitter-api-sdk": "^1.2.1",
|
||||||
|
|
8367
pnpm-lock.yaml
8367
pnpm-lock.yaml
Plik diff jest za duży
Load Diff
28
readme.md
28
readme.md
|
@ -17,6 +17,34 @@
|
||||||
|
|
||||||
**Coming soon**
|
**Coming soon**
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
- Clearbit
|
||||||
|
- Dexa
|
||||||
|
- Diffbot
|
||||||
|
- Proxycurl
|
||||||
|
- SerpAPI
|
||||||
|
- Serper
|
||||||
|
- Twitter
|
||||||
|
- WeatherAPI
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- core
|
||||||
|
- company schema
|
||||||
|
- person schema
|
||||||
|
- database
|
||||||
|
- move out to a separate project
|
||||||
|
- agentic
|
||||||
|
- walter
|
||||||
|
- services
|
||||||
|
- Exa
|
||||||
|
- Firecrawl
|
||||||
|
- Unstructured
|
||||||
|
- pull from [langchain](https://github.com/langchain-ai/langchainjs/tree/main/langchain)
|
||||||
|
- pull from other libs
|
||||||
|
- pull from [nango](https://docs.nango.dev/integrations/overview)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
PROPRIETARY © [Travis Fischer](https://twitter.com/transitive_bs)
|
PROPRIETARY © [Travis Fischer](https://twitter.com/transitive_bs)
|
||||||
|
|
12
src/fns.ts
12
src/fns.ts
|
@ -1,4 +1,4 @@
|
||||||
import 'reflect-metadata'
|
import './symbol-polyfill.js'
|
||||||
|
|
||||||
import type { z } from 'zod'
|
import type { z } from 'zod'
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export abstract class AIToolsProvider {
|
||||||
const functions = invocables.map((invocable) => ({
|
const functions = invocables.map((invocable) => ({
|
||||||
...invocable,
|
...invocable,
|
||||||
name: invocable.name ?? `${namespace}_${invocable.propertyKey}`,
|
name: invocable.name ?? `${namespace}_${invocable.propertyKey}`,
|
||||||
callback: (target as any)[invocable.propertyKey].bind(target)
|
callback: (this as any)[invocable.propertyKey].bind(target)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const functions = invocables.map(getFunctionSpec)
|
const functions = invocables.map(getFunctionSpec)
|
||||||
|
@ -88,18 +88,14 @@ export function aiFunction<
|
||||||
context: ClassMethodDecoratorContext<
|
context: ClassMethodDecoratorContext<
|
||||||
This,
|
This,
|
||||||
(this: This, ...args: Args) => Return
|
(this: This, ...args: Args) => Return
|
||||||
> & {
|
>
|
||||||
readonly metadata: {
|
|
||||||
invocables: Invocable[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) => {
|
) => {
|
||||||
const methodName = String(context.name)
|
const methodName = String(context.name)
|
||||||
if (!context.metadata.invocables) {
|
if (!context.metadata.invocables) {
|
||||||
context.metadata.invocables = []
|
context.metadata.invocables = []
|
||||||
}
|
}
|
||||||
|
|
||||||
context.metadata.invocables.push({
|
;(context.metadata.invocables as Invocable[]).push({
|
||||||
name: name ?? methodName,
|
name: name ?? methodName,
|
||||||
description,
|
description,
|
||||||
inputSchema,
|
inputSchema,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import defaultKy from 'ky'
|
import defaultKy from 'ky'
|
||||||
import pThrottle from 'p-throttle'
|
import pThrottle from 'p-throttle'
|
||||||
|
|
||||||
import type { DeepNullable } from '../types.js'
|
import type { DeepNullable, KyInstance } from '../types.js'
|
||||||
import { assert, delay, getEnv, throttleKy } from '../utils.js'
|
import { assert, delay, getEnv, throttleKy } from '../utils.js'
|
||||||
|
|
||||||
// Only allow 20 clearbit API requests per 60s
|
// Only allow 20 clearbit API requests per 60s
|
||||||
|
@ -362,7 +362,7 @@ export namespace clearbit {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClearbitClient {
|
export class ClearbitClient {
|
||||||
readonly ky: typeof defaultKy
|
readonly ky: KyInstance
|
||||||
readonly apiKey: string
|
readonly apiKey: string
|
||||||
readonly _maxPageSize = 100
|
readonly _maxPageSize = 100
|
||||||
|
|
||||||
|
@ -516,17 +516,19 @@ export class ClearbitClient {
|
||||||
constructor({
|
constructor({
|
||||||
apiKey = getEnv('CLEARBIT_API_KEY'),
|
apiKey = getEnv('CLEARBIT_API_KEY'),
|
||||||
timeoutMs = 30_000,
|
timeoutMs = 30_000,
|
||||||
|
throttle = true,
|
||||||
ky = defaultKy
|
ky = defaultKy
|
||||||
}: {
|
}: {
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
timeoutMs?: number
|
timeoutMs?: number
|
||||||
ky?: typeof defaultKy
|
throttle?: boolean
|
||||||
|
ky?: KyInstance
|
||||||
} = {}) {
|
} = {}) {
|
||||||
assert(apiKey, 'Error clearbit client missing required "apiKey"')
|
assert(apiKey, 'Error clearbit client missing required "apiKey"')
|
||||||
|
|
||||||
this.apiKey = apiKey
|
this.apiKey = apiKey
|
||||||
|
|
||||||
const throttledKy = throttleKy(ky, clearbitAPIThrottle)
|
const throttledKy = throttle ? throttleKy(ky, clearbitAPIThrottle) : ky
|
||||||
|
|
||||||
this.ky = throttledKy.extend({
|
this.ky = throttledKy.extend({
|
||||||
timeout: timeoutMs,
|
timeout: timeoutMs,
|
||||||
|
@ -652,7 +654,8 @@ export class ClearbitClient {
|
||||||
employments: Array<DeepNullable<clearbit.EmploymentAttributes> | null> | null
|
employments: Array<DeepNullable<clearbit.EmploymentAttributes> | null> | null
|
||||||
) {
|
) {
|
||||||
if (employments && employments.length > 0) {
|
if (employments && employments.length > 0) {
|
||||||
// We filter by employment endDate because some people could have multiple jobs at the same time.
|
// We filter by employment endDate because some people could have multiple
|
||||||
|
// jobs at the same time.
|
||||||
// Here we want to filter by people that actively works at a specific company.
|
// Here we want to filter by people that actively works at a specific company.
|
||||||
return employments
|
return employments
|
||||||
.filter((item) => !item?.endDate)
|
.filter((item) => !item?.endDate)
|
||||||
|
@ -660,6 +663,7 @@ export class ClearbitClient {
|
||||||
item?.company?.toLowerCase().includes(companyName.toLowerCase())
|
item?.company?.toLowerCase().includes(companyName.toLowerCase())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { type Prompt } from '@dexaai/dexter'
|
|
||||||
import defaultKy, { type KyInstance } from 'ky'
|
import defaultKy, { type KyInstance } from 'ky'
|
||||||
|
|
||||||
|
import type * as types from '../types.js'
|
||||||
import { assert, getEnv } from '../utils.js'
|
import { assert, getEnv } from '../utils.js'
|
||||||
|
|
||||||
export class DexaClient {
|
export class DexaClient {
|
||||||
|
@ -11,20 +11,22 @@ export class DexaClient {
|
||||||
constructor({
|
constructor({
|
||||||
apiKey = getEnv('DEXA_API_KEY'),
|
apiKey = getEnv('DEXA_API_KEY'),
|
||||||
apiBaseUrl = getEnv('DEXA_API_BASE_URL') ?? 'https://dexa.ai',
|
apiBaseUrl = getEnv('DEXA_API_BASE_URL') ?? 'https://dexa.ai',
|
||||||
|
timeoutMs = 60_000,
|
||||||
ky = defaultKy
|
ky = defaultKy
|
||||||
}: {
|
}: {
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
apiBaseUrl?: string
|
apiBaseUrl?: string
|
||||||
|
timeoutMs?: number
|
||||||
ky?: KyInstance
|
ky?: KyInstance
|
||||||
} = {}) {
|
} = {}) {
|
||||||
assert(apiKey, 'DEXA_API_KEY is required')
|
assert(apiKey, 'DexaClient missing required "apiKey"')
|
||||||
|
|
||||||
this.apiKey = apiKey
|
this.apiKey = apiKey
|
||||||
this.apiBaseUrl = apiBaseUrl
|
this.apiBaseUrl = apiBaseUrl
|
||||||
this.ky = ky.extend({ prefixUrl: this.apiBaseUrl, timeout: 60_000 })
|
this.ky = ky.extend({ prefixUrl: this.apiBaseUrl, timeout: timeoutMs })
|
||||||
}
|
}
|
||||||
|
|
||||||
async askDexa({ messages }: { messages: Prompt.Msg[] }) {
|
async askDexa({ messages }: { messages: types.Msg[] }) {
|
||||||
return this.ky
|
return this.ky
|
||||||
.post('api/ask-dexa', {
|
.post('api/ask-dexa', {
|
||||||
json: {
|
json: {
|
||||||
|
|
|
@ -330,7 +330,7 @@ export namespace diffbot {
|
||||||
|
|
||||||
export class DiffbotClient {
|
export class DiffbotClient {
|
||||||
readonly ky: KyInstance
|
readonly ky: KyInstance
|
||||||
readonly kyKnowledgeGraph: typeof defaultKy
|
readonly kyKnowledgeGraph: KyInstance
|
||||||
|
|
||||||
readonly apiKey: string
|
readonly apiKey: string
|
||||||
readonly apiBaseUrl: string
|
readonly apiBaseUrl: string
|
||||||
|
@ -341,21 +341,23 @@ export class DiffbotClient {
|
||||||
apiBaseUrl = diffbot.API_BASE_URL,
|
apiBaseUrl = diffbot.API_BASE_URL,
|
||||||
apiKnowledgeGraphBaseUrl = diffbot.KNOWLEDGE_GRAPH_API_BASE_URL,
|
apiKnowledgeGraphBaseUrl = diffbot.KNOWLEDGE_GRAPH_API_BASE_URL,
|
||||||
timeoutMs = 30_000,
|
timeoutMs = 30_000,
|
||||||
|
throttle = true,
|
||||||
ky = defaultKy
|
ky = defaultKy
|
||||||
}: {
|
}: {
|
||||||
apiKey?: string
|
apiKey?: string
|
||||||
apiBaseUrl?: string
|
apiBaseUrl?: string
|
||||||
apiKnowledgeGraphBaseUrl?: string
|
apiKnowledgeGraphBaseUrl?: string
|
||||||
timeoutMs?: number
|
timeoutMs?: number
|
||||||
|
throttle?: boolean
|
||||||
ky?: KyInstance
|
ky?: KyInstance
|
||||||
} = {}) {
|
} = {}) {
|
||||||
assert(apiKey, `Error DiffbotClient missing required "apiKey"`)
|
assert(apiKey, `DiffbotClient missing required "apiKey"`)
|
||||||
|
|
||||||
this.apiKey = apiKey
|
this.apiKey = apiKey
|
||||||
this.apiBaseUrl = apiBaseUrl
|
this.apiBaseUrl = apiBaseUrl
|
||||||
this.apiKnowledgeGraphBaseUrl = apiKnowledgeGraphBaseUrl
|
this.apiKnowledgeGraphBaseUrl = apiKnowledgeGraphBaseUrl
|
||||||
|
|
||||||
const throttledKy = throttleKy(ky, diffbotAPIThrottle)
|
const throttledKy = throttle ? throttleKy(ky, diffbotAPIThrottle) : ky
|
||||||
|
|
||||||
this.ky = throttledKy.extend({
|
this.ky = throttledKy.extend({
|
||||||
prefixUrl: apiBaseUrl,
|
prefixUrl: apiBaseUrl,
|
||||||
|
|
|
@ -0,0 +1,264 @@
|
||||||
|
import defaultKy, { type KyInstance } from 'ky'
|
||||||
|
|
||||||
|
import { assert, getEnv } from '../utils.js'
|
||||||
|
|
||||||
|
export namespace exa {
|
||||||
|
/**
|
||||||
|
* Search options for performing a search query.
|
||||||
|
*/
|
||||||
|
export type BaseSearchOptions = {
|
||||||
|
/** Number of search results to return. Default 10. Max 10 for basic plans. */
|
||||||
|
numResults?: number
|
||||||
|
/** List of domains to include in the search. */
|
||||||
|
includeDomains?: string[]
|
||||||
|
/** List of domains to exclude in the search. */
|
||||||
|
excludeDomains?: string[]
|
||||||
|
/** Start date for results based on crawl date. */
|
||||||
|
startCrawlDate?: string
|
||||||
|
/** End date for results based on crawl date. */
|
||||||
|
endCrawlDate?: string
|
||||||
|
/** Start date for results based on published date. */
|
||||||
|
startPublishedDate?: string
|
||||||
|
/** End date for results based on published date. */
|
||||||
|
endPublishedDate?: string
|
||||||
|
/** A data category to focus on, with higher comprehensivity and data cleanliness. Currently, the only category is company. */
|
||||||
|
category?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search options for performing a search query.
|
||||||
|
*/
|
||||||
|
export type RegularSearchOptions = BaseSearchOptions & {
|
||||||
|
/** If true, converts query to a Metaphor query. */
|
||||||
|
useAutoprompt?: boolean
|
||||||
|
/** Type of search, 'keyword' or 'neural'. */
|
||||||
|
type?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for finding similar links.
|
||||||
|
*/
|
||||||
|
export type FindSimilarOptions = BaseSearchOptions & {
|
||||||
|
/** If true, excludes links from the base domain of the input. */
|
||||||
|
excludeSourceDomain?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search options for performing a search query.
|
||||||
|
*/
|
||||||
|
export type ContentsOptions = {
|
||||||
|
/** Options for retrieving text contents. */
|
||||||
|
text?: TextContentsOptions | true
|
||||||
|
/** Options for retrieving highlights. */
|
||||||
|
highlights?: HighlightsContentsOptions | true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for retrieving text from page.
|
||||||
|
*/
|
||||||
|
export type TextContentsOptions = {
|
||||||
|
/** The maximum number of characters to return. */
|
||||||
|
maxCharacters?: number
|
||||||
|
/** If true, includes HTML tags in the returned text. Default: false */
|
||||||
|
includeHtmlTags?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for retrieving highlights from page.
|
||||||
|
* @typedef {Object} HighlightsContentsOptions
|
||||||
|
*/
|
||||||
|
export type HighlightsContentsOptions = {
|
||||||
|
/** The query string to use for highlights search. */
|
||||||
|
query?: string
|
||||||
|
/** The number of sentences to return for each highlight. */
|
||||||
|
numSentences?: number
|
||||||
|
/** The number of highlights to return for each URL. */
|
||||||
|
highlightsPerUrl?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TextResponse = {
|
||||||
|
/** Text from page */
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HighlightsResponse = {
|
||||||
|
/** The highlights as an array of strings. */
|
||||||
|
highlights: string[]
|
||||||
|
/** The corresponding scores as an array of floats, 0 to 1 */
|
||||||
|
highlightScores: number[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Default<T extends {}, U> = [keyof T] extends [never] ? U : T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending on 'ContentsOptions', this yields either a 'TextResponse',
|
||||||
|
* a 'HighlightsResponse', both, or an empty object.
|
||||||
|
*/
|
||||||
|
export type ContentsResultComponent<T extends ContentsOptions> = Default<
|
||||||
|
(T['text'] extends object | true ? TextResponse : {}) &
|
||||||
|
(T['highlights'] extends object | true ? HighlightsResponse : {}),
|
||||||
|
TextResponse
|
||||||
|
>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a search result object.
|
||||||
|
*/
|
||||||
|
export type SearchResult<T extends ContentsOptions = ContentsOptions> = {
|
||||||
|
/** The title of the search result. */
|
||||||
|
title: string | null
|
||||||
|
/** The URL of the search result. */
|
||||||
|
url: string
|
||||||
|
/** The estimated creation date of the content. */
|
||||||
|
publishedDate?: string
|
||||||
|
/** The author of the content, if available. */
|
||||||
|
author?: string
|
||||||
|
/** Similarity score between the query/url and the result. */
|
||||||
|
score?: number
|
||||||
|
/** The temporary ID for the document. */
|
||||||
|
id: string
|
||||||
|
} & ContentsResultComponent<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a search response object.
|
||||||
|
*/
|
||||||
|
export type SearchResponse<T extends ContentsOptions = ContentsOptions> = {
|
||||||
|
/** The list of search results. */
|
||||||
|
results: SearchResult<T>[]
|
||||||
|
/** The autoprompt string, if applicable. */
|
||||||
|
autopromptString?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExaClient {
|
||||||
|
readonly apiKey: string
|
||||||
|
readonly apiBaseUrl: string
|
||||||
|
readonly ky: KyInstance
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
apiKey = getEnv('EXA_API_KEY'),
|
||||||
|
apiBaseUrl = getEnv('EXA_API_BASE_URL') ?? 'https://api.exa.ai',
|
||||||
|
ky = defaultKy
|
||||||
|
}: {
|
||||||
|
apiKey?: string
|
||||||
|
apiBaseUrl?: string
|
||||||
|
ky?: KyInstance
|
||||||
|
} = {}) {
|
||||||
|
assert(apiKey, 'ExaClient missing required "apiKey"')
|
||||||
|
|
||||||
|
this.apiKey = apiKey
|
||||||
|
this.apiBaseUrl = apiBaseUrl
|
||||||
|
this.ky = ky.extend({
|
||||||
|
prefixUrl: this.apiBaseUrl,
|
||||||
|
headers: {
|
||||||
|
'x-api-key': apiKey
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async search(query: string, options?: exa.RegularSearchOptions) {
|
||||||
|
return this.ky
|
||||||
|
.post('search', { json: { ...options, query } })
|
||||||
|
.json<exa.SearchResponse>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a search with a Exa prompt-engineered query and returns the
|
||||||
|
* contents of the documents.
|
||||||
|
*
|
||||||
|
* @param {string} query - The query string.
|
||||||
|
*/
|
||||||
|
async searchAndContents<T extends exa.ContentsOptions = exa.ContentsOptions>(
|
||||||
|
query: string,
|
||||||
|
options?: exa.RegularSearchOptions & T
|
||||||
|
) {
|
||||||
|
const { text, highlights, ...rest } = options || {}
|
||||||
|
|
||||||
|
return this.ky
|
||||||
|
.post('search', {
|
||||||
|
json: {
|
||||||
|
query,
|
||||||
|
contents:
|
||||||
|
!text && !highlights
|
||||||
|
? { text: true }
|
||||||
|
: {
|
||||||
|
...(text ? { text } : {}),
|
||||||
|
...(highlights ? { highlights } : {})
|
||||||
|
},
|
||||||
|
...rest
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.json<exa.SearchResponse<T>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds similar links to the provided URL.
|
||||||
|
*
|
||||||
|
* @param {string} url - The URL for which to find similar links.
|
||||||
|
*/
|
||||||
|
async findSimilar(url: string, options?: exa.FindSimilarOptions) {
|
||||||
|
return this.ky
|
||||||
|
.post('findSimilar', { json: { url, ...options } })
|
||||||
|
.json<exa.SearchResponse>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds similar links to the provided URL and returns the contents of the
|
||||||
|
* documents.
|
||||||
|
*
|
||||||
|
* @param {string} url - The URL for which to find similar links.
|
||||||
|
*/
|
||||||
|
async findSimilarAndContents<
|
||||||
|
T extends exa.ContentsOptions = exa.ContentsOptions
|
||||||
|
>(url: string, options?: exa.FindSimilarOptions & T) {
|
||||||
|
const { text, highlights, ...rest } = options || {}
|
||||||
|
|
||||||
|
return this.ky
|
||||||
|
.post('findSimilar', {
|
||||||
|
json: {
|
||||||
|
url,
|
||||||
|
contents:
|
||||||
|
!text && !highlights
|
||||||
|
? { text: true }
|
||||||
|
: {
|
||||||
|
...(text ? { text } : {}),
|
||||||
|
...(highlights ? { highlights } : {})
|
||||||
|
},
|
||||||
|
...rest
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.json<exa.SearchResponse<T>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves contents of documents based on a list of document IDs.
|
||||||
|
*
|
||||||
|
* @param {string | string[] | SearchResult[]} ids - An array of document IDs.
|
||||||
|
*/
|
||||||
|
async getContents<T extends exa.ContentsOptions>(
|
||||||
|
ids: string | string[] | exa.SearchResult[],
|
||||||
|
options?: T
|
||||||
|
) {
|
||||||
|
let requestIds: string[]
|
||||||
|
|
||||||
|
if (typeof ids === 'string') {
|
||||||
|
requestIds = [ids]
|
||||||
|
} else if (typeof ids[0] === 'string') {
|
||||||
|
requestIds = ids as string[]
|
||||||
|
} else {
|
||||||
|
requestIds = (ids as exa.SearchResult[]).map((result) => result.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ids.length === 0) {
|
||||||
|
throw new Error('Must provide at least one ID')
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.ky
|
||||||
|
.post('contents', {
|
||||||
|
json: {
|
||||||
|
ids: requestIds,
|
||||||
|
...options
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.json<exa.SearchResponse<T>>()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
export * from './clearbit-client.js'
|
export * from './clearbit-client.js'
|
||||||
export * from './dexa-client.js'
|
export * from './dexa-client.js'
|
||||||
export * from './diffbot-client.js'
|
export * from './diffbot-client.js'
|
||||||
export * from './openai-client.js'
|
export * from './exa-client.js'
|
||||||
export * from './proxycurl-client.js'
|
export * from './proxycurl-client.js'
|
||||||
export * from './scraper-client.js'
|
export * from './scraper-client.js'
|
||||||
export * from './serpapi-client.js'
|
export * from './serpapi-client.js'
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from 'openai'
|
|
|
@ -2003,6 +2003,7 @@ export namespace proxycurl {
|
||||||
export class ProxycurlClient {
|
export class ProxycurlClient {
|
||||||
readonly ky: KyInstance
|
readonly ky: KyInstance
|
||||||
readonly apiKey: string
|
readonly apiKey: string
|
||||||
|
readonly apiBaseUrl: string
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
apiKey = getEnv('PROXYCURL_API_KEY'),
|
apiKey = getEnv('PROXYCURL_API_KEY'),
|
||||||
|
@ -2014,9 +2015,11 @@ export class ProxycurlClient {
|
||||||
apiBaseUrl?: string
|
apiBaseUrl?: string
|
||||||
ky?: KyInstance
|
ky?: KyInstance
|
||||||
} = {}) {
|
} = {}) {
|
||||||
assert(apiKey, 'Error ProxycurlClient missing required "apiKey"')
|
assert(apiKey, 'ProxycurlClient missing required "apiKey"')
|
||||||
|
assert(apiBaseUrl, 'ProxycurlClient missing required "apiBaseUrl"')
|
||||||
|
|
||||||
this.apiKey = apiKey
|
this.apiKey = apiKey
|
||||||
|
this.apiBaseUrl = apiBaseUrl
|
||||||
|
|
||||||
this.ky = ky.extend({
|
this.ky = ky.extend({
|
||||||
prefixUrl: apiBaseUrl,
|
prefixUrl: apiBaseUrl,
|
||||||
|
|
|
@ -45,7 +45,7 @@ export class ScraperClient {
|
||||||
apiBaseUrl?: string
|
apiBaseUrl?: string
|
||||||
ky?: KyInstance
|
ky?: KyInstance
|
||||||
} = {}) {
|
} = {}) {
|
||||||
assert(apiBaseUrl, 'SCRAPER_API_BASE_URL is required')
|
assert(apiBaseUrl, 'ScraperClient apiBaseUrl is required')
|
||||||
|
|
||||||
this.apiBaseUrl = apiBaseUrl
|
this.apiBaseUrl = apiBaseUrl
|
||||||
this.ky = ky.extend({ prefixUrl: this.apiBaseUrl })
|
this.ky = ky.extend({ prefixUrl: this.apiBaseUrl })
|
||||||
|
|
|
@ -667,7 +667,7 @@ export class SerpAPIClient extends AIToolsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@aiFunction({
|
@aiFunction({
|
||||||
name: 'serpapiGoogleSearch',
|
name: 'serpapi_google_search',
|
||||||
description:
|
description:
|
||||||
'Uses Google Search to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.',
|
'Uses Google Search to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.',
|
||||||
inputSchema: z.object({
|
inputSchema: z.object({
|
||||||
|
|
|
@ -230,10 +230,12 @@ export class SerperClient extends AIToolsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@aiFunction({
|
@aiFunction({
|
||||||
name: 'serperGoogleSearch',
|
name: 'serper_google_search',
|
||||||
description:
|
description:
|
||||||
'Uses Google Search to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.',
|
'Uses Google Search to return the most relevant web pages for a given query. Can also be used to find up-to-date news and information about many topics.',
|
||||||
inputSchema: serper.SearchParamsSchema
|
inputSchema: serper.SearchParamsSchema.pick({
|
||||||
|
q: true
|
||||||
|
})
|
||||||
})
|
})
|
||||||
async search(queryOrOpts: string | serper.SearchParams) {
|
async search(queryOrOpts: string | serper.SearchParams) {
|
||||||
return this._fetch<serper.SearchResponse>('search', queryOrOpts)
|
return this._fetch<serper.SearchResponse>('search', queryOrOpts)
|
||||||
|
|
|
@ -98,7 +98,7 @@ export class WeatherClient extends AIToolsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@aiFunction({
|
@aiFunction({
|
||||||
name: 'getCurrentWeather',
|
name: 'get_current_weather',
|
||||||
description: 'Gets info about the current weather at a given location.',
|
description: 'Gets info about the current weather at a given location.',
|
||||||
inputSchema: z.object({
|
inputSchema: z.object({
|
||||||
q: z
|
q: z
|
||||||
|
|
|
@ -2,8 +2,6 @@ import type { Jsonifiable } from 'type-fest'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stringifies a JSON value in a way that's optimized for use with LLM prompts.
|
* Stringifies a JSON value in a way that's optimized for use with LLM prompts.
|
||||||
*
|
|
||||||
* This is intended to be used with `function` and `tool` arguments and responses.
|
|
||||||
*/
|
*/
|
||||||
export function stringifyForModel(jsonObject?: Jsonifiable): string {
|
export function stringifyForModel(jsonObject?: Jsonifiable): string {
|
||||||
if (jsonObject === undefined) {
|
if (jsonObject === undefined) {
|
||||||
|
|
|
@ -21,16 +21,21 @@ export interface AIToolSpec {
|
||||||
export interface Msg {
|
export interface Msg {
|
||||||
/** The contents of the message. `content` is required for all messages, and may be null for assistant messages with function calls. */
|
/** The contents of the message. `content` is required for all messages, and may be null for assistant messages with function calls. */
|
||||||
content: string | null
|
content: string | null
|
||||||
|
|
||||||
/** The role of the messages author. One of `system`, `user`, `assistant`, 'tool', or `function`. */
|
/** The role of the messages author. One of `system`, `user`, `assistant`, 'tool', or `function`. */
|
||||||
role: Msg.Role
|
role: Msg.Role
|
||||||
|
|
||||||
/** The name and arguments of a function that should be called, as generated by the model. */
|
/** The name and arguments of a function that should be called, as generated by the model. */
|
||||||
function_call?: Msg.Call.Function
|
function_call?: Msg.Call.Function
|
||||||
|
|
||||||
/** The tool calls generated by the model, such as function calls. */
|
/** The tool calls generated by the model, such as function calls. */
|
||||||
tool_calls?: Msg.Call.Tool[]
|
tool_calls?: Msg.Call.Tool[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tool call that this message is responding to.
|
* Tool call that this message is responding to.
|
||||||
*/
|
*/
|
||||||
tool_call_id?: string
|
tool_call_id?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the author of this message. `name` is required if role is
|
* The name of the author of this message. `name` is required if role is
|
||||||
* `function`, and it should be the name of the function whose response is in the
|
* `function`, and it should be the name of the function whose response is in the
|
||||||
|
@ -50,6 +55,7 @@ export namespace Msg {
|
||||||
export type Function = {
|
export type Function = {
|
||||||
/** The arguments to call the function with, as generated by the model in JSON format. */
|
/** The arguments to call the function with, as generated by the model in JSON format. */
|
||||||
arguments: string
|
arguments: string
|
||||||
|
|
||||||
/** The name of the function to call. */
|
/** The name of the function to call. */
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
@ -58,8 +64,10 @@ export namespace Msg {
|
||||||
export type Tool = {
|
export type Tool = {
|
||||||
/** The ID of the tool call. */
|
/** The ID of the tool call. */
|
||||||
id: string
|
id: string
|
||||||
|
|
||||||
/** The type of the tool. Currently, only `function` is supported. */
|
/** The type of the tool. Currently, only `function` is supported. */
|
||||||
type: 'function'
|
type: 'function'
|
||||||
|
|
||||||
/** The function that the model called. */
|
/** The function that the model called. */
|
||||||
function: Call.Function
|
function: Call.Function
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
|
|
||||||
"experimentalDecorators": true,
|
// "experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
// "emitDecoratorMetadata": true,
|
||||||
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
"noUncheckedIndexedAccess": true,
|
||||||
|
|
Ładowanie…
Reference in New Issue