Skip to content

Jw websets #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 60 additions & 60 deletions .github/workflows/run-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,41 @@ name: Test SDK and Run Examples

on:
push:
branches: [ main ]
branches: [main]
pull_request:

jobs:
test-sdk-and-run-examples:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18'

- name: Install dependencies
run: npm ci

- name: Build SDK
run: npm run build

- name: Run tests
run: npm test

- name: Run Node.js example
working-directory: ./examples/node
run: |
npm ci
npm run build
node dist/server.js &
sleep 10
curl http://localhost:8000
kill %1
env:
EXASEARCH_API_KEY: ${{ secrets.EXA_API_KEY }}
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18"

- name: Install dependencies
run: npm ci

- name: Build SDK
run: npm run build

- name: Run tests
run: npm test

- name: Run Node.js example
working-directory: ./examples/node
run: |
npm ci
npm run build
node dist/server.js &
sleep 10
curl -s -o /tmp/curl_output.txt http://localhost:8000 || cat /tmp/curl_output.txt
kill %1
env:
EXASEARCH_API_KEY: ${{ secrets.EXA_API_KEY }}

# Optional: Add steps to publish the package if on main branch
# - name: Publish to npm
Expand All @@ -49,35 +49,35 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18'

- name: Install dependencies
run: npm ci

- name: Install TypeScript
run: npm install -g typescript

- name: Compile TypeScript files
run: |
cd examples
for file in *.ts; do
echo "Compiling $file"
tsc $file
done

- name: List compiled files
run: ls -R examples/*.js

- name: Run JavaScript files
run: |
for file in examples/*.js; do
echo "Running $file"
node $file || echo "Failed to run $file"
done
env:
EXASEARCH_API_KEY: ${{ secrets.EXA_API_KEY }}
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18"

- name: Install dependencies
run: npm ci

- name: Install TypeScript
run: npm install -g typescript

- name: Compile TypeScript files
run: |
cd examples
for file in *.ts; do
echo "Compiling $file"
tsc $file
done

- name: List compiled files
run: ls -R examples/*.js

- name: Run JavaScript files
run: |
for file in examples/*.js; do
echo "Running $file"
node $file || echo "Failed to run $file"
done
env:
EXASEARCH_API_KEY: ${{ secrets.EXA_API_KEY }}
38 changes: 38 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Exa-JS Code Assistant Guide

## Build & Test Commands
- Build: `npm run build`
- Fast Build: `npm run build-fast` (only builds index.ts)
- Test All: `npm run test`
- Test Single: `npx vitest run test/path/to/test.ts`
- Generate Docs: `npm run generate-docs`

## Code Style Guidelines
- **TypeScript**: ES2020 target, ESNext modules, strict mode
- **Formatting**: Default Prettier (2.8.4)
- **Imports**: ES imports, built-in modules first
- **Types**:
- Comprehensive TypeScript types with JSDoc comments
- Generic types for API responses
- Interfaces/Types in PascalCase (e.g., `SearchOptions`)
- Optional properties with `?` suffix
- **Naming**:
- Classes: PascalCase (e.g., `Exa`)
- Methods/Variables: camelCase
- Consistent patterns (e.g., `*Options`, `*Response`)
- **Error Handling**:
- Explicit errors with descriptive messages
- API error handling with status codes
- **API Design**:
- Class-based design with clear method signatures
- Private helper methods for common functionality
- Method overloading via optional parameters

## Websets API Implementation
- The Python SDK has a comprehensive Websets API implementation that needs to be mirrored in TypeScript
- Key components include:
- WebsetsClient with methods for create, get, list, update, delete, cancel, wait_until_idle
- Sub-clients for items, searches, enrichments, and webhooks
- Extensive type definitions for all request/response objects
- Proper handling of pagination for list operations
- Support for entity types (company, person, article, research paper, custom)
2 changes: 1 addition & 1 deletion examples/find_similar_example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runFindSimilarExamples() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/get_contents_example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runGetContentsExample() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/links_example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runLinksExample() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/livecrawl_example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runLivecrawlExample() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/schema_summary_example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa, { JSONSchema } from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runSchemaSummaryExample() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/search_example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runSearchExamples() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/search_with_contents.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runSearchExamples() {
try {
Expand Down
2 changes: 1 addition & 1 deletion examples/subpages.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Exa from "../src/index";

const exa = new Exa(process.env.EXASEARCH_API_KEY);
const exa = new Exa(process.env.EXA_API_KEY);

async function runExamples() {
try {
Expand Down
154 changes: 154 additions & 0 deletions examples/websets_example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Example demonstrating usage of the Websets API
*
* This example shows how to:
* 1. Create a new Webset
* 2. Check its status and wait until it's idle
* 3. List and filter items in the Webset
* 4. Add an enrichment
* 5. Update Webset metadata
* 6. Use advanced pagination features
* 7. Monitor events
* 8. Work with webhooks and webhook attempts
* 9. Clean up resources
*/

import * as dotenv from "dotenv";
import Exa, {
CreateEnrichmentParameters,
CreateEnrichmentParametersFormat,
CreateWebsetParameters,
EventType,
} from "../src";

// Load environment variables from .env file
dotenv.config();

async function main() {
// Initialize the client with the API key
const exa = new Exa(process.env.EXA_API_KEY);

console.log("Creating a new Webset...");
const createParams: CreateWebsetParameters = {
search: {
query:
"AI research labs that have published research in the last two years",
count: 25,
},
enrichments: [
{
description: "Latest company funding round",
format: CreateEnrichmentParametersFormat.number,
},
{
description: "Primary focus area",
format: CreateEnrichmentParametersFormat.options,
options: [
{ label: "Language models" },
{ label: "Computer vision" },
{ label: "Robotics" },
{ label: "Multi-modal AI" },
{ label: "Other" },
],
},
{
description:
"Find the LinkedIn profile of the VP of engineering or similar role",
format: CreateEnrichmentParametersFormat.text,
},
],
};

const webset = await exa.websets.create(createParams);
console.log(`Webset created with ID: ${webset.id}`);
console.log(`Status: ${webset.status}`);

console.log("Waiting for Webset to finish processing...");
const idleWebset = await exa.websets.waitUntilIdle(webset.id, {
timeout: 300000,
pollInterval: 2000,
onPoll: (status) => {
console.log(`Current status: ${status}...`);
},
});
console.log(`Webset processing complete. Status: ${idleWebset.status}`);

console.log("Listing Webset items...");
const items = await exa.websets.items.list(webset.id, { limit: 10 });
console.log(`Found ${items.data.length} items:`);
for (const item of items.data) {
console.log(
`- ${
item.properties.type === "company"
? item.properties.company.name
: "Unknown"
}: ${item.properties.url}`
);
}

console.log("\nCollecting all items at once:");
const allItems = await exa.websets.items.getAll(webset.id);
console.log(`Retrieved ${allItems.length} items in total`);

console.log("\nAdding an enrichment...");
const enrichmentParams: CreateEnrichmentParameters = {
description: "Estimate the company's founding year",
format: CreateEnrichmentParametersFormat.number,
metadata: { purpose: "Timeline analysis" },
};
const enrichment = await exa.websets.enrichments.create(
webset.id,
enrichmentParams
);
console.log(`Enrichment created with ID: ${enrichment.id}`);

console.log("\nGetting Webset with items expanded...");
const expandedWebset = await exa.websets.get(webset.id, ["items"]);
console.log(`Expanded Webset has ${expandedWebset.items?.length ?? 0} items`);

console.log("\nListing recent events...");
const events = await exa.websets.events.list({
limit: 5,
types: [
EventType.webset_created,
EventType.webset_idle,
EventType.webset_item_created,
],
});
console.log(`Found ${events.data.length} recent events:`);
for (const event of events.data) {
console.log(`- ${event.type} at ${event.createdAt}`);
}

console.log("\nCreating a webhook...");
const webhook = await exa.websets.webhooks.create({
url: "https://example.com/webhook",
events: [EventType.webset_idle, EventType.webset_item_created],
});
console.log(`Webhook created with ID: ${webhook.id}`);

// If there are any webhook attempts, list them
console.log("\nListing webhook attempts...");
const attempts = await exa.websets.webhooks.listAttempts(webhook.id, {
limit: 5,
});
console.log(`Found ${attempts.data.length} webhook attempts`);

if (attempts.data.length > 0) {
console.log("Recent webhook attempts:");
for (const attempt of attempts.data) {
console.log(
`- ${attempt.eventType} at ${attempt.attemptedAt} (${attempt.successful ? "success" : "failed"})`
);
console.log(` Status code: ${attempt.responseStatusCode}`);
}
}

console.log("\nCleaning up resources...");
await exa.websets.webhooks.delete(webhook.id);
console.log("Webhook deleted successfully");
await exa.websets.delete(webset.id);
console.log("Webset deleted successfully");
}

main();
Loading