feat: add @agentic/typeform Typeform client

pull/706/head
Travis Fischer 2025-04-09 22:44:21 +07:00
rodzic eafbe5e06d
commit 6287455dcd
12 zmienionych plików z 336 dodań i 2 usunięć

Wyświetl plik

@ -93,6 +93,7 @@
"tools/tavily",
"tools/twilio",
"tools/twitter",
"tools/typeform",
"tools/weather",
"tools/wikidata",
"tools/wikipedia",

Wyświetl plik

@ -0,0 +1,43 @@
---
title: Typeform
description: Readonly Typeform API client for fetching form insights and responses.
---
- package: `@agentic/typeform`
- exports: `class TypeformClient`, `namespace typeform`
- env vars: `TYPEFORM_API_KEY`
- [source](https://github.com/transitive-bullshit/agentic/blob/main/packages/typeform/src/typeform-client.ts)
- [typeform api docs](https://www.typeform.com/developers/get-started/)
## Install
<CodeGroup>
```bash npm
npm install @agentic/typeform
```
```bash yarn
yarn add @agentic/typeform
```
```bash pnpm
pnpm add @agentic/typeform
```
</CodeGroup>
## Usage
```ts
import { TypeformClient } from '@agentic/typeform'
const typeform = new TypeformClient()
const responses = await typeform.getResponsesForForm({
formId: 'TODO'
})
const insights = await typeform.getInsightsForForm({
formId: 'TODO'
})
```

Wyświetl plik

@ -72,6 +72,7 @@
"@agentic/tavily": "workspace:*",
"@agentic/twilio": "workspace:*",
"@agentic/twitter": "workspace:*",
"@agentic/typeform": "workspace:*",
"@agentic/weather": "workspace:*",
"@agentic/wikidata": "workspace:*",
"@agentic/wikipedia": "workspace:*",

Wyświetl plik

@ -37,6 +37,7 @@ export * from '@agentic/social-data'
export * from '@agentic/tavily'
export * from '@agentic/twilio'
export * from '@agentic/twitter'
export * from '@agentic/typeform'
export * from '@agentic/weather'
export * from '@agentic/wikidata'
export * from '@agentic/wikipedia'

Wyświetl plik

@ -141,10 +141,10 @@ const twitterApiRateLimitsByPlan: Record<
}
/**
* Twitter API v2 client wrapper with rate-limited methods and `@aiFunction`
* Twitter/X API v2 client wrapper with rate-limited methods and `@aiFunction`
* compatibility.
*
* Rate limits differ by plan, so make sure theh `twitterApiPlan` parameter is
* Rate limits differ by plan, so make sure the `twitterApiPlan` parameter is
* properly set to maximize your rate-limit usage.
*
* @note This class does not handle distributed rate-limits. It assumes a

Wyświetl plik

@ -0,0 +1,45 @@
{
"name": "@agentic/typeform",
"version": "7.6.3",
"description": "Agentic SDK for the Typeform data API.",
"author": "Travis Fischer <travis@transitivebullsh.it>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/transitive-bullshit/agentic.git",
"directory": "packages/typeform"
},
"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",
"dev": "tsup --watch",
"clean": "del dist",
"test": "run-s test:*",
"test:lint": "eslint .",
"test:typecheck": "tsc --noEmit"
},
"dependencies": {
"@agentic/core": "workspace:*",
"ky": "catalog:",
"p-throttle": "catalog:"
},
"peerDependencies": {
"zod": "catalog:"
},
"publishConfig": {
"access": "public"
}
}

Wyświetl plik

@ -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)

Wyświetl plik

@ -0,0 +1 @@
export * from './typeform-client'

Wyświetl plik

@ -0,0 +1,194 @@
import {
aiFunction,
AIFunctionsProvider,
assert,
getEnv,
sanitizeSearchParams
} from '@agentic/core'
import defaultKy, { type KyInstance } from 'ky'
import { z } from 'zod'
export namespace typeform {
export const API_BASE_URL = 'https://api.typeform.com'
export interface GetInsightsForFormResponse {
fields: Array<{
dropoffs: number
id: string
label: string
ref: string
title: string
type: string
views: number
}>
form: {
platforms: Array<{
average_time: number
completion_rate: number
platform: string
responses_count: number
total_visits: number
unique_visits: number
}>
summary: {
average_time: number
completion_rate: number
responses_count: number
total_visits: number
unique_visits: number
}
}
}
export interface GetResponsesForFormParams {
formId: string
pageSize?: number
since?: string
until?: string
completed?: boolean
}
export interface GetResponsesForFormResponse {
total_items: number
page_count: number
items: Array<{
landing_id: string
token: string
landed_at: string
submitted_at: string
metadata: {
user_agent: string
platform: string
referer: string
network_id: string
browser: string
}
answers: Array<{
field: {
id: string
type: string
ref: string
}
type: string
[key: string]: any
}>
hidden: Record<string, any>
calculated: {
score: number
}
variables: Array<{
key: string
type: string
[key: string]: any
}>
}>
}
}
/**
* Readonly Typeform API client for fetching form insights and responses.
*
* @see https://www.typeform.com/developers/get-started/
*/
export class TypeformClient extends AIFunctionsProvider {
protected readonly ky: KyInstance
protected readonly apiKey: string
protected readonly apiBaseUrl: string
constructor({
apiKey = getEnv('TYPEFORM_API_KEY'),
apiBaseUrl = typeform.API_BASE_URL,
ky = defaultKy
}: {
/** Typeform Personal Access Token */
apiKey?: string
apiBaseUrl?: string
ky?: KyInstance
} = {}) {
assert(
apiKey,
'TypeformClient missing required "apiKey" (defaults to "TYPEFORM_API_KEY")'
)
super()
this.apiKey = apiKey
this.apiBaseUrl = apiBaseUrl
this.ky = ky.extend({
prefixUrl: this.apiBaseUrl,
headers: {
Authorization: `Bearer ${this.apiKey}`
}
})
}
/**
* Retrieves insights and analytics for a Typeform form.
*/
@aiFunction({
name: 'typeform_get_insights_for_form',
description: 'Retrieve insights and analytics for a Typeform form.',
inputSchema: z.object({
formId: z
.string()
.describe('The ID of the Typeform form to get insights for.')
})
})
async getInsightsForForm(
formIdOrOptions: string | { formId: string }
): Promise<typeform.GetInsightsForFormResponse> {
const { formId } =
typeof formIdOrOptions === 'string'
? { formId: formIdOrOptions }
: formIdOrOptions
const encodedFormId = encodeURIComponent(formId)
return this.ky
.get(`insights/${encodedFormId}/summary`)
.json<typeform.GetInsightsForFormResponse>()
}
/**
* Retrieves responses for a Typeform form.
*/
@aiFunction({
name: 'typeform_get_responses_for_form',
description: 'Retrieve responses for a Typeform form.',
inputSchema: z.object({
formId: z
.string()
.describe('The ID of the Typeform form to get responses for.'),
pageSize: z
.number()
.describe('The number of responses to retrieve per page.')
.optional(),
since: z
.string()
.describe('The date to start retrieving responses from.')
.optional(),
until: z
.string()
.describe('The date to stop retrieving responses at.')
.optional(),
completed: z
.boolean()
.describe('Filter responses by completion status.')
.optional()
})
})
async getResponsesForForm(
formIdOrOptions: string | typeform.GetResponsesForFormParams
): Promise<typeform.GetResponsesForFormResponse> {
const { formId, ...params } =
typeof formIdOrOptions === 'string'
? { formId: formIdOrOptions }
: formIdOrOptions
const encodedFormId = encodeURIComponent(formId)
return this.ky
.get(`forms/${encodedFormId}/responses`, {
searchParams: sanitizeSearchParams(params)
})
.json<typeform.GetResponsesForFormResponse>()
}
}

Wyświetl plik

@ -0,0 +1,5 @@
{
"extends": "@fisch0920/config/tsconfig-node",
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

Wyświetl plik

@ -1191,6 +1191,9 @@ importers:
'@agentic/twitter':
specifier: workspace:*
version: link:../twitter
'@agentic/typeform':
specifier: workspace:*
version: link:../typeform
'@agentic/weather':
specifier: workspace:*
version: link:../weather
@ -1267,6 +1270,21 @@ importers:
specifier: 'catalog:'
version: 3.24.2
packages/typeform:
dependencies:
'@agentic/core':
specifier: workspace:*
version: link:../core
ky:
specifier: 'catalog:'
version: 1.8.0
p-throttle:
specifier: 'catalog:'
version: 6.2.0
zod:
specifier: 'catalog:'
version: 3.24.2
packages/weather:
dependencies:
'@agentic/core':

Wyświetl plik

@ -218,6 +218,7 @@ Full docs are available at [agentic.so](https://agentic.so).
| [Tavily](https://tavily.com) | `@agentic/tavily` | [docs](https://agentic.so/tools/tavily) | Web search API tailored for LLMs. |
| [Twilio](https://www.twilio.com/docs/conversations/api) | `@agentic/twilio` | [docs](https://agentic.so/tools/twilio) | Twilio conversation API to send and receive SMS messages. |
| [Twitter](https://developer.x.com/en/docs/twitter-api) | `@agentic/twitter` | [docs](https://agentic.so/tools/twitter) | Basic Twitter API methods for fetching users, tweets, and searching recent tweets. Includes support for plan-aware rate-limiting. Uses [Nango](https://www.nango.dev) for OAuth support. |
| [Typeform](https://www.typeform.com/developers/get-started/) | `@agentic/typeform` | [docs](https://agentic.so/tools/typeform) | Readonly Typeform client for fetching form insights and responses. |
| [Weather](https://www.weatherapi.com) | `@agentic/weather` | [docs](https://agentic.so/tools/weather) | Basic access to current weather data based on location. |
| [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. |