kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add ZoomInfo tool
rodzic
05d25e211d
commit
562fe2b9c3
|
@ -82,7 +82,8 @@
|
|||
"tools/weather",
|
||||
"tools/wikidata",
|
||||
"tools/wikipedia",
|
||||
"tools/wolfram-alpha"
|
||||
"tools/wolfram-alpha",
|
||||
"tools/zoominfo"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
|
@ -10,25 +10,25 @@ title: Quick Start
|
|||
</Info>
|
||||
|
||||
<Steps>
|
||||
<Step title='Install core deps'>
|
||||
<Step title='Install core deps (zod)'>
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install @agentic/core zod
|
||||
npm install zod
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add @agentic/core zod
|
||||
yarn add zod
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm add @agentic/core zod
|
||||
pnpm add zod
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title='Install AI tools'>
|
||||
You can either install all of the AI tools via the convenience package `@agentic/stdlib`, or you can install them individually via their respective packages (`@agentic/weather`, `@agentic/twitter`, etc.).
|
||||
You can either install all of the AI tools via `@agentic/stdlib`, or you can install them individually via their respective packages (`@agentic/weather`, `@agentic/twitter`, etc.).
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Install all AI tools">
|
||||
|
@ -72,7 +72,7 @@ title: Quick Start
|
|||
<Note>
|
||||
There is no functional difference between using `@agentic/stdlib` versus using the individual tool packages directly. The only difference is if you want to optimize your install size (when running on serverless functions, for instance).
|
||||
|
||||
The default examples all use `@agentic/stdlib` because it provides a simpler DX.
|
||||
The default examples all use `@agentic/stdlib` for simplicity.
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
@ -138,15 +138,15 @@ title: Quick Start
|
|||
<Accordion title="Firebase Genkit">
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install @agentic/genkit @genkit-ai/ai @genkit-ai/core
|
||||
npm install @agentic/genkit genkit
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add @agentic/genkit @genkit-ai/ai @genkit-ai/core
|
||||
yarn add @agentic/genkit genkit
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm add @agentic/genkit @genkit-ai/ai @genkit-ai/core
|
||||
pnpm add @agentic/genkit genkit
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: ZoomInfo
|
||||
description: ZoomInfo provides a powerful API for B2B person and company data enrichment.
|
||||
---
|
||||
|
||||
- package: `@agentic/zoominfo`
|
||||
- exports: `class ZoomInfo`, `namespace zoominfo`
|
||||
- env vars:
|
||||
- `ZOOMINFO_USERNAME` and `ZOOMINFO_PASSWORD` for basic auth
|
||||
- `ZOOMINFO_USERNAME`, `ZOOMINFO_CLIENT_ID`, and `ZOOMINFO_PRIVATE_KEY` for PKI auth
|
||||
- [source](https://github.com/transitive-bullshit/agentic/blob/main/packages/wolfram-alpha/src/zoominfo-client.ts)
|
||||
- [zoominfo api docs](https://api-docs.zoominfo.com)
|
||||
|
||||
## Install
|
||||
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install @agentic/zoominfo
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add @agentic/zoominfo
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm add @agentic/zoominfo
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { ZoomInfoClient } from '@agentic/zoominfo'
|
||||
|
||||
const zoomInfo = new ZoomInfoClient()
|
||||
const res = await zoomInfo.enrichContact({
|
||||
emailAddress: 'travis@transitivebullsh.it'
|
||||
})
|
||||
```
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "@agentic/zoominfo",
|
||||
"version": "7.3.2",
|
||||
"description": "Agentic SDK for ZoomInfo.",
|
||||
"author": "Travis Fischer <travis@transitivebullsh.it>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/transitive-bullshit/agentic.git",
|
||||
"directory": "packages/zoominfo"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentic/core": "workspace:*",
|
||||
"jsrsasign": "^11.1.0",
|
||||
"ky": "^1.7.5",
|
||||
"p-throttle": "^6.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@agentic/tsconfig": "workspace:*",
|
||||
"@types/jsrsasign": "^10.5.15"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<p align="center">
|
||||
<a href="https://agentic.so">
|
||||
<img alt="Agentic" src="https://raw.githubusercontent.com/transitive-bullshit/agentic/main/docs/media/agentic-header.jpg" width="308">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<em>AI agent stdlib that works with any LLM and TypeScript AI SDK.</em>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml"><img alt="Build Status" src="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml/badge.svg" /></a>
|
||||
<a href="https://www.npmjs.com/package/@agentic/stdlib"><img alt="NPM" src="https://img.shields.io/npm/v/@agentic/stdlib.svg" /></a>
|
||||
<a href="https://github.com/transitive-bullshit/agentic/blob/main/license"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue" /></a>
|
||||
<a href="https://prettier.io"><img alt="Prettier Code Formatting" src="https://img.shields.io/badge/code_style-prettier-brightgreen.svg" /></a>
|
||||
</p>
|
||||
|
||||
# Agentic
|
||||
|
||||
**See the [github repo](https://github.com/transitive-bullshit/agentic) or [docs](https://agentic.so) for more info.**
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Travis Fischer](https://x.com/transitive_bs)
|
|
@ -0,0 +1 @@
|
|||
export * from './zoominfo-client'
|
|
@ -0,0 +1,586 @@
|
|||
import {
|
||||
aiFunction,
|
||||
AIFunctionsProvider,
|
||||
assert,
|
||||
getEnv,
|
||||
throttleKy
|
||||
} from '@agentic/core'
|
||||
import { KJUR } from 'jsrsasign'
|
||||
import defaultKy, { type KyInstance } from 'ky'
|
||||
import pThrottle from 'p-throttle'
|
||||
import { z } from 'zod'
|
||||
|
||||
export namespace zoominfo {
|
||||
export const API_BASE_URL = 'https://api.zoominfo.com'
|
||||
|
||||
// Access tokens expire after 60 minutes, so renew them every 55 minutes.
|
||||
export const ACCESS_TOKEN_EXPIRATION_MS = 55 * 60 * 1000
|
||||
|
||||
// Allow up to 25 requests per second by default.
|
||||
// https://api-docs.zoominfo.com/#rate-and-usage-limits
|
||||
export const throttle = pThrottle({
|
||||
limit: 25,
|
||||
interval: 1000
|
||||
})
|
||||
|
||||
export interface EnrichContactOptions {
|
||||
personId?: string
|
||||
emailAddress?: string
|
||||
hashedEmail?: string
|
||||
phone?: string
|
||||
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
companyId?: string
|
||||
companyName?: string
|
||||
|
||||
fullName?: string
|
||||
|
||||
jobTitle?: string
|
||||
externalURL?: string
|
||||
lastUpdatedDateAfter?: string
|
||||
validDateAfter?: string
|
||||
contactAccuracyScoreMin?: number
|
||||
}
|
||||
|
||||
export interface EnrichCompanyOptions {
|
||||
companyId?: string // Unique ZoomInfo identifier for a company
|
||||
companyName?: string // Company name
|
||||
companyWebsite?: string // Company website URL in http://www.example.com format
|
||||
companyTicker?: string // Company stock ticker symbol
|
||||
companyPhone?: string // Phone number of the company headquarters
|
||||
companyFax?: string // Fax number of the company headquarters
|
||||
companyStreet?: string // Street address for the company's primary address
|
||||
companyCity?: string // City for the company's primary address
|
||||
companyState?: string // Company state (U.S.) or province (Canada). You can use free text state or province names (e.g., "new hampshire"), the two-letter common abbreviation for a U.S. state (e.g., "nh"), or values provided in the State lookup endpoint.
|
||||
companyZipCode?: string // Zip Code or Postal Code for the company's primary address
|
||||
companyCountry?: string // Country for the company's primary address. You can use free text or see the Country lookup endpoint for values.
|
||||
ipAddress?: string // IP address associated with the company
|
||||
}
|
||||
|
||||
export interface EnrichContactResponse {
|
||||
success: boolean
|
||||
data: {
|
||||
outputFields: string[][]
|
||||
result: EnrichContactResult[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface EnrichContactResult {
|
||||
input: Partial<EnrichContactOptions>
|
||||
data: EnrichedContact[]
|
||||
}
|
||||
|
||||
export interface EnrichedContact {
|
||||
id: number
|
||||
firstName: string
|
||||
middleName: string
|
||||
lastName: string
|
||||
email: string
|
||||
hasCanadianEmail: string
|
||||
phone: string
|
||||
directPhoneDoNotCall: boolean
|
||||
street: string
|
||||
city: string
|
||||
region: string
|
||||
metroArea: string
|
||||
zipCode: string
|
||||
state: string
|
||||
country: string
|
||||
personHasMoved: string
|
||||
withinEu: boolean
|
||||
withinCalifornia: boolean
|
||||
withinCanada: boolean
|
||||
lastUpdatedDate: string
|
||||
noticeProvidedDate: string
|
||||
salutation: string
|
||||
suffix: string
|
||||
jobTitle: string
|
||||
jobFunction: JobFunction[]
|
||||
education: Education[]
|
||||
hashedEmails: string[]
|
||||
picture: string
|
||||
mobilePhoneDoNotCall: boolean
|
||||
externalUrls: ExternalUrl[]
|
||||
contactAccuracyScore: number
|
||||
isDefunct: boolean
|
||||
employmentHistory: EmploymentHistory[]
|
||||
managementLevel: string[]
|
||||
locationCompanyId: number
|
||||
company: Company
|
||||
}
|
||||
|
||||
export interface JobFunction {
|
||||
name: string
|
||||
department: string
|
||||
}
|
||||
|
||||
export interface Education {
|
||||
school: string
|
||||
educationDegree: EducationDegree
|
||||
}
|
||||
|
||||
export interface EducationDegree {
|
||||
degree: string
|
||||
areaOfStudy: string
|
||||
}
|
||||
|
||||
export interface ExternalUrl {
|
||||
type: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface EmploymentHistory {
|
||||
jobTitle: string
|
||||
managementLevel: string[]
|
||||
fromDate: string
|
||||
toDate: string
|
||||
company: {
|
||||
companyId: number
|
||||
companyName: string
|
||||
companyPhone?: string
|
||||
companyWebsite?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Company {
|
||||
id: number
|
||||
name: string
|
||||
type: string
|
||||
division: string
|
||||
descriptionList: DescriptionList[]
|
||||
phone: string
|
||||
fax: string
|
||||
street: string
|
||||
city: string
|
||||
state: string
|
||||
zipCode: string
|
||||
country: string
|
||||
logo: string
|
||||
sicCodes: Code[]
|
||||
naicsCodes: Code[]
|
||||
website: string
|
||||
revenue: string
|
||||
revenueNumeric: number
|
||||
employeeCount: number
|
||||
ticker: string
|
||||
ranking: string[]
|
||||
socialMediaUrls: any[]
|
||||
primaryIndustry: string[]
|
||||
industries: string[]
|
||||
revenueRange: string
|
||||
employeeRange: string
|
||||
}
|
||||
|
||||
export interface DescriptionList {
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface Code {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface EnrichCompanyResponse {
|
||||
success: boolean
|
||||
data: {
|
||||
outputFields: string[][]
|
||||
result: EnrichCompanyResult[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface EnrichCompanyResult {
|
||||
input: Partial<EnrichCompanyOptions>
|
||||
data: EnrichedCompany[]
|
||||
}
|
||||
|
||||
export interface EnrichedCompany {
|
||||
id: number
|
||||
ticker: string
|
||||
name: string
|
||||
website: string
|
||||
domainList: string[]
|
||||
logo: string
|
||||
socialMediaUrls: SocialMediaUrl[]
|
||||
revenue: number
|
||||
employeeCount: number
|
||||
numberOfContactsInZoomInfo: number
|
||||
phone: string
|
||||
fax: string
|
||||
street: string
|
||||
city: string
|
||||
state: string
|
||||
zipCode: string
|
||||
country: string
|
||||
continent: string
|
||||
companyStatus: string
|
||||
companyStatusDate: string
|
||||
descriptionList: DescriptionList[]
|
||||
sicCodes: Code[]
|
||||
naicsCodes: Code[]
|
||||
competitors: Competitor[]
|
||||
ultimateParentId: number
|
||||
ultimateParentName: string
|
||||
ultimateParentRevenue: number
|
||||
ultimateParentEmployees: number
|
||||
subUnitCodes: any[]
|
||||
subUnitType: string
|
||||
subUnitIndustries: string[]
|
||||
primaryIndustry: string[]
|
||||
industries: string[]
|
||||
parentId: number
|
||||
parentName: string
|
||||
locationCount: number
|
||||
alexaRank: string
|
||||
metroArea: string
|
||||
lastUpdatedDate: string
|
||||
createdDate: string
|
||||
certificationDate: string
|
||||
certified: boolean
|
||||
hashtags: Hashtag[]
|
||||
products: any[]
|
||||
techAttributes: TechAttribute[]
|
||||
revenueRange: string
|
||||
employeeRange: string
|
||||
companyFunding: CompanyFunding[]
|
||||
recentFundingAmount: number
|
||||
recentFundingDate: string
|
||||
totalFundingAmount: number
|
||||
employeeGrowth: EmployeeGrowth
|
||||
}
|
||||
|
||||
export interface SocialMediaUrl {
|
||||
type: string
|
||||
url: string
|
||||
followerCount: string
|
||||
}
|
||||
|
||||
export interface DescriptionList {
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface Competitor {
|
||||
rank: number
|
||||
id: number
|
||||
name: string
|
||||
website: string
|
||||
employeeCount: number
|
||||
}
|
||||
|
||||
export interface Hashtag {
|
||||
tag: string
|
||||
external_id: any
|
||||
searchString: string
|
||||
displayLabel: string
|
||||
description: string
|
||||
group: string
|
||||
score: any
|
||||
priority?: number
|
||||
parentCategory: string
|
||||
displayScore: string
|
||||
inverseScoreBase?: number
|
||||
scoreMultipler: any
|
||||
scoreUnit: string
|
||||
hidden: boolean
|
||||
label: string
|
||||
categorizedFlag: boolean
|
||||
}
|
||||
|
||||
export interface TechAttribute {
|
||||
tag: string
|
||||
categoryParent: string
|
||||
category: string
|
||||
vendor: string
|
||||
product: string
|
||||
attribute: string
|
||||
website: string
|
||||
logo?: string
|
||||
domain?: string
|
||||
createdTime: string
|
||||
modifiedTime: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface CompanyFunding {
|
||||
date: string
|
||||
type: string
|
||||
amount: number
|
||||
}
|
||||
|
||||
export interface EmployeeGrowth {
|
||||
oneYearGrowthRate: string
|
||||
twoYearGrowthRate: string
|
||||
employeeGrowthDataPoints: EmployeeGrowthDataPoint[]
|
||||
}
|
||||
|
||||
export interface EmployeeGrowthDataPoint {
|
||||
label: string
|
||||
employeeCount: number
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ZoomInfo ia a robust B2B entity enrichment API.
|
||||
*
|
||||
* @see https://api-docs.zoominfo.com
|
||||
*/
|
||||
export class ZoomInfoClient extends AIFunctionsProvider {
|
||||
protected readonly ky: KyInstance
|
||||
protected readonly apiBaseUrl: string
|
||||
|
||||
protected readonly username: string
|
||||
protected readonly password: string | undefined
|
||||
protected readonly clientId: string | undefined
|
||||
protected readonly privateKey: string | undefined
|
||||
|
||||
protected accessToken: string | undefined
|
||||
protected accessTokenDateMS: number | undefined
|
||||
|
||||
constructor({
|
||||
username = getEnv('ZOOMINFO_USERNAME'),
|
||||
password = getEnv('ZOOMINFO_PASSWORD'),
|
||||
clientId = getEnv('ZOOMINFO_CLIENT_ID'),
|
||||
privateKey = getEnv('ZOOMINFO_PRIVATE_KEY'),
|
||||
apiBaseUrl = zoominfo.API_BASE_URL,
|
||||
timeoutMs = 60_000,
|
||||
throttle = true,
|
||||
ky = defaultKy
|
||||
}: {
|
||||
username?: string
|
||||
password?: string
|
||||
clientId?: string
|
||||
privateKey?: string
|
||||
apiBaseUrl?: string
|
||||
apiKnowledgeGraphBaseUrl?: string
|
||||
timeoutMs?: number
|
||||
throttle?: boolean
|
||||
ky?: KyInstance
|
||||
} = {}) {
|
||||
assert(
|
||||
username,
|
||||
`ZoomInfoClient missing required "username" (defaults to "ZOOMINFO_USERNAME")`
|
||||
)
|
||||
assert(
|
||||
password || (clientId && privateKey),
|
||||
`ZoomInfoClient missing required "password" for basic auth or "clientId" and "privateKey" for PKI auth (defaults to "ZOOMINFO_PASSWORD", "ZOOMINFO_CLIENT_ID", and "ZOOMINFO_PRIVATE_KEY")`
|
||||
)
|
||||
super()
|
||||
|
||||
this.username = username
|
||||
this.password = password
|
||||
this.clientId = clientId
|
||||
this.privateKey = privateKey
|
||||
|
||||
this.apiBaseUrl = apiBaseUrl
|
||||
|
||||
const throttledKy = throttle ? throttleKy(ky, zoominfo.throttle) : ky
|
||||
|
||||
this.ky = throttledKy.extend({
|
||||
prefixUrl: apiBaseUrl,
|
||||
timeout: timeoutMs
|
||||
})
|
||||
}
|
||||
|
||||
async authenticate({
|
||||
force = false
|
||||
}: { force?: boolean } = {}): Promise<void> {
|
||||
if (
|
||||
!force &&
|
||||
this.accessToken &&
|
||||
this.accessTokenDateMS! + zoominfo.ACCESS_TOKEN_EXPIRATION_MS < Date.now()
|
||||
) {
|
||||
// Access token is still valid.
|
||||
return
|
||||
}
|
||||
|
||||
if (this.username && this.password) {
|
||||
this.accessTokenDateMS = Date.now()
|
||||
this.accessToken = await this.getAccessTokenViaBasicAuth({
|
||||
username: this.username,
|
||||
password: this.password
|
||||
})
|
||||
assert(
|
||||
this.accessToken,
|
||||
'ZoomInfo failed to get access token via basic auth'
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (this.username && this.clientId && this.privateKey) {
|
||||
this.accessTokenDateMS = Date.now()
|
||||
this.accessToken = await this.getAccessTokenViaPKI({
|
||||
username: this.username,
|
||||
clientId: this.clientId,
|
||||
privateKey: this.privateKey
|
||||
})
|
||||
assert(
|
||||
this.accessToken,
|
||||
'ZoomInfo failed to get access token via PKI auth'
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
'ZoomInfoClient missing required authentication credentials'
|
||||
)
|
||||
}
|
||||
|
||||
async getAccessTokenViaBasicAuth({
|
||||
username,
|
||||
password
|
||||
}: {
|
||||
username: string
|
||||
password: string
|
||||
}): Promise<string> {
|
||||
const res = await this.ky
|
||||
.post('authenticate', {
|
||||
json: {
|
||||
username,
|
||||
password
|
||||
}
|
||||
})
|
||||
.json<{ data: { jwt: string } }>()
|
||||
|
||||
return res.data.jwt
|
||||
}
|
||||
|
||||
async getAccessTokenViaPKI({
|
||||
username,
|
||||
clientId,
|
||||
privateKey
|
||||
}: {
|
||||
username: string
|
||||
clientId: string
|
||||
privateKey: string
|
||||
}): Promise<string> {
|
||||
const dtNow = Date.now()
|
||||
const header = {
|
||||
typ: 'JWT',
|
||||
alg: 'RS256'
|
||||
}
|
||||
const data = {
|
||||
iss: 'zoominfo-api-auth-client-nodejs',
|
||||
aud: 'enterprise_api',
|
||||
username,
|
||||
client_id: clientId,
|
||||
iat: getIAT(dtNow),
|
||||
exp: getEXP(dtNow)
|
||||
}
|
||||
const sHeader = JSON.stringify(header)
|
||||
const sPayload = JSON.stringify(data)
|
||||
|
||||
const clientJWT = KJUR.jws.JWS.sign(
|
||||
header.alg,
|
||||
sHeader,
|
||||
sPayload,
|
||||
privateKey
|
||||
)
|
||||
|
||||
const res = await this.ky
|
||||
.post('authenticate', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${clientJWT}`
|
||||
}
|
||||
})
|
||||
.json<{ data: { jwt: string } }>()
|
||||
|
||||
return res.data.jwt
|
||||
}
|
||||
|
||||
@aiFunction({
|
||||
name: 'zoominfo_enrich_contact',
|
||||
description: `Attempts to enrich a person contact with ZoomInfo data. To match a contact, you must use one of the following combinations of parameters to construct your input:
|
||||
|
||||
personId OR emailAddress OR hashedEmail OR phone. Because these values are unique to a single person, you can use any one of these values to search without providing any additional parameters. You can optionally combine one of these values with a companyId/companyName.
|
||||
|
||||
firstName AND lastName AND companyId/companyName. Combining these values effectively results in a unique person.
|
||||
|
||||
fullName AND companyId/companyName. Combining these values effectively results in a unique person.`,
|
||||
inputSchema: z.object({
|
||||
firstName: z.string().optional().describe('First name of the person.'),
|
||||
lastName: z.string().optional().describe('Last name of the person.'),
|
||||
companyId: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Unique ZoomInfo identifier of the person's company."),
|
||||
companyName: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Name of the company where the contact works, or has worked.'
|
||||
),
|
||||
personId: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Unique ZoomInfo identifier of the person.'),
|
||||
emailAddress: z.string().optional(),
|
||||
hashedEmail: z.string().optional(),
|
||||
phone: z.string().optional(),
|
||||
fullName: z.string().optional(),
|
||||
jobTitle: z.string().optional(),
|
||||
externalURL: z.string().optional(),
|
||||
lastUpdatedDateAfter: z.string().optional(),
|
||||
validDateAfter: z.string().optional(),
|
||||
contactAccuracyScoreMin: z.number().optional()
|
||||
})
|
||||
})
|
||||
async enrichContact(opts: zoominfo.EnrichContactOptions) {
|
||||
await this.authenticate()
|
||||
|
||||
return this.ky
|
||||
.post('enrich/contact', {
|
||||
json: opts,
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.accessToken}`
|
||||
}
|
||||
})
|
||||
.json<zoominfo.EnrichContactResponse>()
|
||||
}
|
||||
|
||||
@aiFunction({
|
||||
name: 'zoominfo_enrich_company',
|
||||
description:
|
||||
'Attempts to enrich a company with ZoomInfo data. To match a company, you should ideally provide the `companyName` and `companyWebsite`.',
|
||||
inputSchema: z.object({
|
||||
companyId: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Unique ZoomInfo identifier of company.'),
|
||||
companyName: z.string().optional().describe('Name of the company.'),
|
||||
companyWebsite: z.string().optional(),
|
||||
companyTicker: z.string().optional(),
|
||||
companyPhone: z.string().optional(),
|
||||
companyFax: z.string().optional(),
|
||||
companyStreet: z.string().optional(),
|
||||
companyCity: z.string().optional(),
|
||||
companyState: z.string().optional(),
|
||||
companyZipCode: z.string().optional(),
|
||||
companyCountry: z.string().optional(),
|
||||
ipAddress: z.string().optional()
|
||||
})
|
||||
})
|
||||
async enrichCompany(opts: zoominfo.EnrichCompanyOptions) {
|
||||
await this.authenticate()
|
||||
|
||||
return this.ky
|
||||
.post('enrich/company', {
|
||||
json: opts,
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.accessToken}`
|
||||
}
|
||||
})
|
||||
.json<zoominfo.EnrichCompanyResponse>()
|
||||
}
|
||||
}
|
||||
|
||||
function getIAT(dtNow: number) {
|
||||
const iat = Math.floor(dtNow / 1000)
|
||||
return iat - 60
|
||||
}
|
||||
|
||||
function getEXP(dtNow: number) {
|
||||
const exp = Math.floor(dtNow / 1000) + 5 * 60
|
||||
return exp - 60
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "@agentic/tsconfig/base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -1038,6 +1038,28 @@ importers:
|
|||
specifier: workspace:*
|
||||
version: link:../tsconfig
|
||||
|
||||
packages/zoominfo:
|
||||
dependencies:
|
||||
'@agentic/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
jsrsasign:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
ky:
|
||||
specifier: ^1.7.5
|
||||
version: 1.7.5
|
||||
p-throttle:
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.0
|
||||
devDependencies:
|
||||
'@agentic/tsconfig':
|
||||
specifier: workspace:*
|
||||
version: link:../tsconfig
|
||||
'@types/jsrsasign':
|
||||
specifier: ^10.5.15
|
||||
version: 10.5.15
|
||||
|
||||
packages:
|
||||
|
||||
'@ai-sdk/openai@1.1.13':
|
||||
|
@ -2581,6 +2603,9 @@ packages:
|
|||
'@types/json5@0.0.29':
|
||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||
|
||||
'@types/jsrsasign@10.5.15':
|
||||
resolution: {integrity: sha512-3stUTaSRtN09PPzVWR6aySD9gNnuymz+WviNHoTb85dKu+BjaV4uBbWWGykBBJkfwPtcNZVfTn2lbX00U+yhpQ==}
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
|
||||
|
||||
|
@ -4544,6 +4569,9 @@ packages:
|
|||
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
|
||||
jsrsasign@11.1.0:
|
||||
resolution: {integrity: sha512-Ov74K9GihaK9/9WncTe1mPmvrO7Py665TUfUKvraXBpu+xcTWitrtuOwcjf4KMU9maPaYn0OuaWy0HOzy/GBXg==}
|
||||
|
||||
jsx-ast-utils@3.3.5:
|
||||
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
@ -8764,6 +8792,8 @@ snapshots:
|
|||
|
||||
'@types/json5@0.0.29': {}
|
||||
|
||||
'@types/jsrsasign@10.5.15': {}
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
dependencies:
|
||||
'@types/lodash': 4.17.15
|
||||
|
@ -11035,6 +11065,8 @@ snapshots:
|
|||
ms: 2.1.3
|
||||
semver: 7.7.1
|
||||
|
||||
jsrsasign@11.1.0: {}
|
||||
|
||||
jsx-ast-utils@3.3.5:
|
||||
dependencies:
|
||||
array-includes: 3.1.8
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
- [Firebase Genkit](#firebase-genkit)
|
||||
- [Dexa Dexter](#dexa-dexter)
|
||||
- [OpenAI](#openai)
|
||||
- [GenAIScript](#genaiscript)
|
||||
- [Tools](#tools)
|
||||
- [Contributors](#contributors)
|
||||
- [License](#license)
|
||||
|
@ -177,6 +178,7 @@ Full docs are available at [agentic.so](https://agentic.so).
|
|||
| [Wikidata](https://www.wikidata.org/wiki/Wikidata:Data_access) | `@agentic/wikidata` | [docs](https://agentic.so/tools/wikidata) | Basic Wikidata client. |
|
||||
| [Wikipedia](https://www.mediawiki.org/wiki/API) | `@agentic/wikipedia` | [docs](https://agentic.so/tools/wikipedia) | Wikipedia page search and summaries. |
|
||||
| [Wolfram Alpha](https://products.wolframalpha.com/llm-api/documentation) | `@agentic/wolfram-alpha` | [docs](https://agentic.so/tools/wolfram-alpha) | Wolfram Alpha LLM API client for answering computational, mathematical, and scientific questions. |
|
||||
| [ZoomInfo](https://api-docs.zoominfo.com) | `@agentic/zoominfo` | [docs](https://agentic.so/tools/zoominfo) | Powerful B2B person and company data enrichment. |
|
||||
|
||||
For more details, see the [docs](https://agentic.so).
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue