boostgpt
v8.5.0
Published
BoostGPT client library for nodejs.
Maintainers
Readme
Features
- Full ES Modules (ESM) and CommonJS (CJS) support
- Complete coverage of the public
/v1API — everybot/*andmcp/*endpoint has a method - Bot/Agent management (create, read, update, delete)
- Chat operations, including server-sent streaming and reconnection
- Training source management
- Workflows (create, run, and monitor multi-step automations)
- Scheduled tasks (autonomous agent runs, recurring or one-shot)
- Workspaces (sandbox file system — read, write, publish)
- Email inbox management (read, reply, configure)
- MCP connector management (deploy from catalog, OpenAPI, or Postman)
- Tools management (MCP server integration)
- Message voting and feedback
- Comprehensive analytics and statistics
- TypeScript-friendly (type definitions coming soon)
Table of Contents
Requirements
- Node.js >= 12.20.0
- For ES Modules: Node.js >= 14.0.0 recommended
- BoostGPT API Key
Installation
npm install boostgptUsage
ES Modules (Recommended)
import { BoostGPT } from 'boostgpt';
const client = new BoostGPT({
project_id: 'your-project-id',
key: 'your-api-key'
});
// Create a bot
const botResponse = await client.createBot({
name: 'My Bot',
model: 'gpt-5.6-luna',
instruction: 'You are a helpful assistant',
max_reply_tokens: 1000,
status: 1
});
if (botResponse.err) {
console.error('Error:', botResponse.err);
} else {
console.log('Bot created:', botResponse.response);
}
// Chat with the bot
const chatResponse = await client.chat({
bot_id: 'bot-id',
message: 'Hello, how are you?'
});
console.log('Response:', chatResponse.response);CommonJS (Legacy Support)
const { BoostGPT } = require('boostgpt');
const client = new BoostGPT({
project_id: 'your-project-id',
key: 'your-api-key'
});
// Use async/await or promises
(async () => {
const botResponse = await client.createBot({
name: 'My Bot',
model: 'gpt-5.6-luna',
instruction: 'You are a helpful assistant'
});
console.log(botResponse.response);
})();API Reference
Constructor
const client = new BoostGPT({
project_id: 'your-project-id', // Required
key: 'your-api-key' // Required
});Bot Management
Create Bot
await client.createBot({
name: 'Bot Name',
model: 'gpt-5.6-luna',
instruction: 'System instruction',
max_reply_tokens: 1000,
status: 1
});Fetch Bot
await client.fetchBot(bot_id);Fetch All Bots
await client.fetchBots({
page: 1,
per_page: 10
});Update Bot
await client.updateBot({
bot_id: 'bot-id',
name: 'Updated Name',
model: 'gpt-5.6-luna',
instruction: 'Updated instruction',
max_reply_tokens: 1500,
status: "0" // 1 = online, 0 = offline
});Reset Bot
await client.resetBot(bot_id);Delete Bot
await client.deleteBot(bot_id);Chat Operations
Send Chat Message
await client.chat({
bot_id: 'bot-id',
model: 'gpt-5.6-luna', //Optional
provider_key: 'optional-provider-key', //Optional
provider_host: 'optionl-provider-host', // Only needed and required when using ollama models
instruction: 'Optional override instruction',
label_instruction: 'Optional: how to word each tool step, e.g. "a short progressive phrase like Searching the web"',
reasoning_mode: 'optional-reasoning-mode', //Default to standard
source_ids: ['source1', 'source2'], //Optional
message: 'Your message here',
max_reply_tokens: 1000, //Optional
chat_id: 'optional-chat-id',
stream: false, //Optional
memory: false, // Optional: Disables the agents memory
purpose: 'service', // Optional: this call is YOUR backend, acting for many end users
workspace_uuid: 'ws-uuid' // Optional: pin the turn to a workspace (requires purpose: 'service')
});Calling as a service
Most calls represent one person chatting. When your own backend is calling on behalf of many end
users — a WhatsApp assistant, a helpdesk, a community bot — say so with purpose: 'service'.
It grants two things an ordinary call does not get:
- A workspace of your choosing. Pass
workspace_uuidand the turn runs there, so your agent can keep durable notes and read them back in a later conversation. - A chat mode that sticks.
chat_mode: 'edit'survives the request, so the agent can write files.
And withholds one on purpose: a service call is not a builder conversation. It never receives the
Site builder persona, and never gets read_conversations — the tool that reads what other people
have asked. Workspace scope, never cross-conversation reach.
await client.chat({
bot_id: 'bot-id',
chat_id: 'community-42',
message: 'What did we decide about the venue?',
purpose: 'service',
workspace_uuid: 'ws-abc123',
path_scope: '/groups/community-42', // Optional: confine this turn to one folder
chat_mode: 'edit'
});path_scope confines the turn's file tools — read, write, edit, grep, glob, ls and
bash — to one folder of the workspace. Anything outside it reads as absent rather than
forbidden, so one customer's folder cannot reveal that another's exists. Only honoured for
purpose: 'service'.
purpose is a request, not a credential: it is granted only when your API key belongs to someone who
runs the project, and asking for it otherwise changes nothing. It is opt-in too — omit it and your
existing integration behaves exactly as before.
A pinned workspace is remembered against the chat_id, so a turn that pauses for tool execution
resumes in the same workspace. You do not re-send workspace_uuid to executeTool().
Service workspaces count against their own plan allowance, separate from the workspaces you create in the dashboard, and are shown in your account usage. Neither allowance can be spent by the other.
Search
await client.search({
bot_id: 'bot-id',
source_ids: ['source1', 'source2'],
keywords: 'search terms'
});Fetch Chat
await client.fetchChat({
bot_id: 'bot-id',
chat_id: 'chat-id',
page: 1,
per_page: 10
});Fetch All Chats
await client.fetchChats({
bot_id: 'bot-id',
page: 1,
per_page: 10
});Delete Chat
await client.deleteChat({
chat_id: 'chat-id',
bot_id: 'bot-id'
});Execute Tool
When a chat() response comes back needing a tool run, it carries the execution details. Pass them
straight back as execution_data — it must contain executionId, toolName and parameters.
const { response } = await client.chat({ bot_id: 'bot-id', message: 'What is 5 + 3?' });
if (response.chat?.type === 'tool_approval_required') {
await client.executeTool({
bot_id: 'bot-id',
chat_id: 'chat-id',
execution_data: {
executionId: response.chat.executionId,
toolName: response.chat.tool.name,
parameters: response.chat.tool.parameters,
serverLabel: response.chat.tool.server_label, // Optional
originalQuery: 'What is 5 + 3?' // Optional
},
memory: true, // Optional: overrides the turn's setting
source_ids: ['src-1'], // Optional: overrides the turn's scope ([] clears it)
tags: ['docs'], // Optional: overrides the turn's tags
label_instruction: '...', // Optional: as on chat(), and sent per call
stream: false // Optional: returns an event stream when true
});
}A continuation resumes the turn that asked for the tool and inherits that turn's memory,
source_ids and tags, plus the chat's saved chat_mode — so a scoped chat() call stays scoped
for every tool step that follows, with nothing to re-send. The three parameters above are overrides:
send one only to change it, and send [] to clear an inherited scope.
label_instruction is not one of them. Like instruction, it is sent per call: it shapes the
prompt rather than the retrieval, so a continuation that omits it falls back to the default wording
rather than inheriting the turn's. Send it on every hop if you want one voice across a whole turn.
Wording the tool steps
Each tool call carries a LABEL the agent writes for the person watching. By default the model is
asked for it with imperative examples, so it produces "Search the web for X" — which suits a tool
card sitting beside a result, and reads oddly as a live status line where "Searching the web" is
wanted. label_instruction replaces that guidance:
await client.chat({
bot_id: 'bot-id',
message: 'what is the fuel price?',
reasoning_mode: 'agent',
label_instruction: 'a very short phrase in the present continuous, e.g. Searching the web or Reading the page'
});It is guidance for the model, not a template — the label is still written per call and still names
what that step is doing. Newlines and the LABEL:/REASONING:/PARAMS: markers are stripped
server-side, because the reply is parsed on those, and the text is capped at 300 characters.
Before 8.0.1 this method sent tool_calls, which the endpoint does not read — every call
returned 400.
Vote on Message
await client.voteMessage({
bot_id: 'bot-id',
message_id: 'message-id',
voter_id: 'user-id',
voter_type: 'member',
vote_type: 'upvote' // or 'downvote'
});Fetch Vote Status
await client.fetchVoteStatus({
bot_id: 'bot-id',
message_id: 'message-id',
voter_id: 'user-id',
voter_type: 'member'
});Delete Message
await client.deleteMessage({
bot_id: 'bot-id',
chat_id: 'chat-id',
message_id: 'message-id'
});Rename a Chat
await client.renameChat({ bot_id: 'bot-id', chat_id: 'chat-id', name: 'Onboarding questions' });Set the Chat Mode
// ask — reads and answers
// edit — may change files in the agent's workspace
// plan — proposes a plan first, then executes what you approve
await client.setChatMode({ bot_id: 'bot-id', chat_id: 'chat-id', mode: 'plan' });chat() also accepts chat_mode per message, if you would rather not change the conversation's
stored mode:
await client.chat({ bot_id: 'bot-id', message: 'Add a pricing page', chat_mode: 'edit' });Cancel a Reply in Progress
await client.cancelChat({ bot_id: 'bot-id', chat_id: 'chat-id' });Stream State
await client.fetchStreamStatus({ bot_id: 'bot-id', chat_id: 'chat-id' });
await client.fetchActiveStreams({ bot_id: 'bot-id' });Subscribe to a Conversation
Both subscribe methods answer text/event-stream, so response is the raw stream rather than a
parsed object. This is how a client that dropped its connection mid-reply picks up the rest of it.
const { err, response } = await client.subscribeChat({ bot_id: 'bot-id', chat_id: 'chat-id' });
if (!err) {
for await (const chunk of response) {
process.stdout.write(chunk.toString());
}
}
// Notifications for the whole agent; chat_id is optional.
await client.subscribeNotifications({ bot_id: 'bot-id' });chat({ stream: true }) returns a stream the same way.
Schedules Attached to a Conversation
await client.fetchChatScheduledTasks({ bot_id: 'bot-id', chat_id: 'chat-id' });
// A toggle, not a setter: it flips the schedule's current state.
await client.toggleChatScheduledTask({
bot_id: 'bot-id',
chat_id: 'chat-id',
task_id: 'task-id'
});The Plan Behind a Conversation
await client.fetchChatPlan({ bot_id: 'bot-id', chat_id: 'chat-id' });
// No accept method: a plan is accepted through the agent's review question in the conversation.
await client.cancelChatPlan({ bot_id: 'bot-id', chat_id: 'chat-id' });Agents Delegated in a Conversation
// This turn's agents…
const { response } = await client.fetchChatAgents({ bot_id: 'bot-id', chat_id: 'chat-id' });
// …or every turn's, the way the dashboard's agent map shows them
await client.fetchChatAgents({ bot_id: 'bot-id', chat_id: 'chat-id', scope: 'chat' });
// One agent in full: brief, report, and the tools it ran
await client.fetchChatAgent({ bot_id: 'bot-id', chat_id: 'chat-id', agent_id: response.agents[0].uuid });
// Remove its record; a running one is stopped first
await client.deleteChatAgent({ bot_id: 'bot-id', chat_id: 'chat-id', agent_id: response.agents[0].uuid });Training/Source Management
Start Training
await client.startTraining({
bot_id: 'bot-id',
type: 'text',
source: 'Training content here',
title: 'Optional title', // Optional
description: 'Optional summary', // Optional
tags: ['docs'], // Optional
forget_after: 'never', // Optional: when to drop this source
sync_frequency: 'never' // Optional: how often to re-crawl it
});Fetch Training
await client.fetchTraining({
source_id: 'source-id',
bot_id: 'bot-id'
});Fetch All Trainings
await client.fetchTrainings({
bot_id: 'bot-id',
page: 1,
per_page: 10
});Update Training
await client.updateTraining({
source_id: 'source-id',
bot_id: 'bot-id',
source: 'Updated content',
title: 'Optional title', // Optional
description: 'Optional summary', // Optional
tags: ['docs'], // Optional
forget_after: 'never', // Optional
sync_frequency: 'never' // Optional
});A source's
typeis fixed when it is created.updateTraininghas notypeparameter — passing one is silently ignored, because the request is built from named parameters only.
#### Delete Training
```javascript
await client.deleteTraining({
source_id: 'source-id',
bot_id: 'bot-id'
});Tools Management
Fetch Tools
await client.fetchTools({
bot_id: 'bot-id',
page: 1,
per_page: 10,
filter: { type: 'mcp' } // Optional filter
});Create Tool
await client.createTool({
bot_id: 'bot-id',
name: 'My Tool',
description: 'Tool description',
config: {
url: 'https://api.example.com',
auth: 'bearer_token'
},
type: 'mcp'
});Fetch Tool
await client.fetchTool({
tool_id: 'tool-id',
bot_id: 'bot-id'
});Update Tool
await client.updateTool({
tool_id: 'tool-id',
bot_id: 'bot-id',
name: 'Updated Tool Name',
description: 'Updated description',
config: { /* updated config */ },
type: 'mcp'
});Delete Tool
await client.deleteTool({
tool_id: 'tool-id',
bot_id: 'bot-id'
});Configure Tools
await client.configureTools({
tool_id: 'tool-id',
bot_id: 'bot-id',
settings: {
enabled: true,
timeout: 30000
}
});Refresh Tools
await client.refreshTools({
tool_id: 'tool-id',
bot_id: 'bot-id'
});Toggle Tool
await client.toggleTool({
tool_id: 'tool-id',
bot_id: 'bot-id',
tool_name: 'specific-tool',
active: true
});Test Tool Connection
await client.testToolConnection({
tool_id: 'tool-id',
bot_id: 'bot-id'
});Workflows
Fetch Workflow Catalog
await client.fetchWorkflowCatalog({ bot_id: 'bot-id' });List Workflows
await client.fetchWorkflows({ bot_id: 'bot-id' });Get a Workflow
await client.fetchWorkflow({ bot_id: 'bot-id', workflow_id: 'wf-id' });Create a Workflow
await client.createWorkflow({
bot_id: 'bot-id',
name: 'Lead Qualification',
trigger: 'webhook',
steps: [/* step objects */]
});Update a Workflow
await client.updateWorkflow({
bot_id: 'bot-id',
workflow_id: 'wf-id',
enabled: true
});Delete a Workflow
await client.deleteWorkflow({ bot_id: 'bot-id', workflow_id: 'wf-id' });Run a Workflow
await client.runWorkflow({ bot_id: 'bot-id', workflow_id: 'wf-id' });Fetch Workflow Logs
await client.fetchWorkflowLogs({ bot_id: 'bot-id' });Workflow Templates
// The prebuilt workflows available to this agent
await client.fetchWorkflowTemplates({ bot_id: 'bot-id' });
// Create one from a template
await client.applyWorkflowTemplate({ bot_id: 'bot-id', template_key: 'weekly-digest' });Scheduled tasks
Recurring or one-shot runs the agent performs on its own. They appear on the agent's Tasks board in the dashboard — recurring ones under Schedules.
Create a task
await client.createTask({
bot_id: 'bot-id',
name: 'Triage support tickets',
prompt: 'Check for new support tickets and summarize urgent ones',
cron_pattern: '0 9 * * 1-5', // weekdays at 9am
enabled: true,
timezone: 'America/New_York',
max_consecutive_errors: 5
});cron_pattern is a convenience for a recurring schedule. For anything else, pass schedule_type
and schedule_config directly:
await client.createTask({
bot_id: 'bot-id',
name: 'Hourly inbox check',
prompt: 'Check the inbox',
schedule_type: 'interval', // interval | daily | weekly | cron | once
schedule_config: { interval_minutes: 60 }
});Schedule frequency
Every plan enforces a minimum interval of 15 minutes. It is an infrastructure limit, not a tier: credits are what meter automation, and the floor exists to stop a schedule firing faster than a run can finish. A schedule below it is refused:
const { err } = await client.createTask({
bot_id: 'bot-id',
name: 'Too eager',
prompt: 'Check the inbox',
schedule_type: 'interval',
schedule_config: { interval_minutes: 1 }
});
err.status; // 400
err.message; // "The shortest interval on this plan is 15 minutes; 1 was requested."Cron is measured the same way — the shortest gap between fires has to clear the floor, so
* * * * * is refused and 0 9 * * 1-5 is not.
Update a task
await client.updateTask({
bot_id: 'bot-id',
task_id: 'task-id',
prompt: 'Check for new tickets and summarize the urgent ones',
schedule_config: { interval_minutes: 60 }, // subject to the same floor
enabled: true
});Get a task
await client.fetchTask({ bot_id: 'bot-id', task_id: 'task-id' });List tasks
await client.fetchTasks({ bot_id: 'bot-id' });Enable / Disable
await client.enableTask({ bot_id: 'bot-id', task_id: 'task-id' });
await client.disableTask({ bot_id: 'bot-id', task_id: 'task-id' });Trigger Manually
await client.triggerTask({ bot_id: 'bot-id', task_id: 'task-id' });Delete a task
await client.deleteTask({ bot_id: 'bot-id', task_id: 'task-id' });Fetch Logs & Stats
await client.fetchTaskLogs({ bot_id: 'bot-id' });
await client.fetchTaskStats({ bot_id: 'bot-id' });
// Narrowed to one task, one status, one page
await client.fetchTaskLogs({
bot_id: 'bot-id',
task_id: 'task-id',
status: 'interrupted',
page: 1,
per_page: 20
});Each run carries a status:
| status | meaning |
|---|---|
| success | The run finished. |
| error | The run started and failed. Consecutive errors eventually pause the schedule. |
| skipped | The run was declined before starting; reason says why. |
| interrupted | The run was killed mid-flight, normally by a deploy or restart. Not counted as an error. |
Common reason values on a skip: already_running (the previous fire has not finished),
schedule_clamped (the schedule was below the plan floor and was slowed to it), no_credits,
outside_active_hours, max_executions_reached, assigned_to_member, bot_offline.
Delete a run
await client.deleteTaskLog({ bot_id: 'bot-id', run_id: 'run-uuid' });Upgrading from 5.x: these replace the
*Heartbeatmethods, andheartbeat_idis nowtask_id. See the CHANGELOG for the full mapping.
Workspaces
List Workspaces
await client.fetchWorkspaces({ bot_id: 'bot-id' });Create / Delete Workspace
await client.createWorkspace({ bot_id: 'bot-id', name: 'My Workspace' });
// Integrations: put the workspace in the SERVICE allowance rather than the dashboard one — the
// pool to spend when you create one workspace per customer you serve. Granted only when your key
// belongs to someone who runs the project; otherwise it lands in the usual pool.
await client.createWorkspace({ bot_id: 'bot-id', name: 'acme-corp', purpose: 'service' });
await client.deleteWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });File Operations
// List files
await client.fetchFiles({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
// Read a file
await client.readFile({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', file_uuid: 'file-uuid' });
// Create a file
await client.createFile({
bot_id: 'bot-id',
workspace_uuid: 'ws-uuid',
file_path: '/src/app.js',
content: 'console.log("hello");',
language: 'javascript'
});
// Update a file
await client.updateFile({
bot_id: 'bot-id',
workspace_uuid: 'ws-uuid',
file_uuid: 'file-uuid',
content: '// updated content'
});
// Rename / move a file
await client.renameFile({
bot_id: 'bot-id',
workspace_uuid: 'ws-uuid',
old_path: '/src/app.js',
new_path: '/src/main.js'
});
// Delete a file
await client.deleteFile({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', file_uuid: 'file-uuid' });
// Download workspace as ZIP
await client.downloadWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });Publishing
await client.suggestSubdomain({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
await client.publishWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', subdomain: 'my-app' });
await client.unpublishWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
// Custom domain
await client.addCustomDomain({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', custom_domain: 'app.example.com' });
await client.removeCustomDomain({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
await client.refreshDomainStatus({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
await client.getDomainInfo({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });Email Inbox
Get Email Address
await client.fetchEmailAddress({ bot_id: 'bot-id' });Update Settings
await client.updateEmailSettings({
bot_id: 'bot-id',
auto_reply: true,
signature: 'Best, Support Team'
});Stats, List, Read, Reply, Delete
await client.fetchEmailStats({ bot_id: 'bot-id' });
await client.fetchEmails({ bot_id: 'bot-id', page: 1, per_page: 20 });
await client.fetchEmail({ bot_id: 'bot-id', email_id: 'email-uuid' });
await client.replyToEmail({
bot_id: 'bot-id',
email_id: 'email-uuid',
content: 'Thanks for reaching out!'
});
await client.deleteEmail({ bot_id: 'bot-id', email_id: 'email-uuid' });MCP Connectors
Connector Catalog
// List all available connectors
await client.fetchConnectors();
// Get connector details (auth requirements, tools)
await client.fetchConnector('jamendo');Deploy MCP Servers
// From a pre-built connector
await client.createMcpFromPredefined({
name: 'My Jamendo Server',
connectorName: 'jamendo',
credentials: { client_id: 'your_client_id' }
});
// From an OpenAPI spec
await client.createMcpFromOpenApi({
name: 'My API Server',
openApiSpec: { /* OpenAPI 3.0 object */ },
credentials: { api_key: 'sk-xxx' }
});
// From a Postman collection
await client.createMcpFromPostman({
name: 'My Postman Server',
postmanCollection: { /* Postman Collection v2.1 */ }
});Manage Servers
await client.fetchMcpServers();
await client.fetchMcpServer('server-uuid');
await client.updateMcpServer({ id: 'server-uuid', name: 'Renamed' });
await client.cloneMcpServer({ id: 'server-uuid', name: 'Clone' });
await client.deleteMcpServer('server-uuid');
await client.fetchMcpUsage('server-uuid');Validate Specs
await client.validateOpenApi({ spec: openApiObject });
await client.validatePostman({ collection: postmanObject });Widget
Serves the embeddable chat widget, so a backend can read the same configuration the widget reads.
// Branding and widget settings for an embedded agent
await client.fetchWidgetConfig({ bot_id: 'bot-id' });Analytics
Fetch Vote Statistics
await client.fetchVoteStats({
bot_id: 'bot-id'
});Fetch Summary Statistics
await client.fetchSummaryStats({
bot_id: 'bot-id'
});Fetch Dashboard Statistics
await client.fetchDashboardStats({
bot_id: 'bot-id'
});Fetch Tool Usage Statistics
await client.fetchToolUsageStats({
bot_id: 'bot-id'
});Fetch Workflow Statistics
await client.fetchWorkflowStats({
bot_id: 'bot-id'
});Fetch Performance Metrics
await client.fetchPerformanceMetrics({
bot_id: 'bot-id'
});Fetch User Behavior Statistics
await client.fetchBehaviorStats({
bot_id: 'bot-id'
});Fetch Error Analysis
await client.fetchErrorAnalysis({
bot_id: 'bot-id'
});Fetch Reasoning Summary
await client.fetchReasoningSummary({
bot_id: 'bot-id'
});Response Format
All methods return a BoostGPTResponse object:
{
err: null | Error, // Set when the request failed
response: null | Object // The parsed body when it succeeded
}Methods never throw. A request that came back with a non-2xx status populates err:
const result = await client.createBot({ name: 'My Bot' });
if (result.err) {
console.error(result.err.message); // what the server said
console.error(result.err.status); // 400, 403, 429, 500 …
console.error(result.err.code); // e.g. 'schedule_too_frequent', when the API sends one
} else {
console.log(result.response);
}For a streaming call — chat({ stream: true }), subscribeChat, subscribeNotifications —
response is the raw event stream instead of a parsed object; iterate it with for await.
Changed in 8.0.0. Earlier versions decided whether a request had failed by reading a field the API only populates in development, so against production
errwas alwaysnulland a failed call returned the error body as though it were data. If your code inspectsresponse.messageto detect failures, it can now checkerrinstead.
Not covered
Sites (/v1/sites)
Development
Building the Package
# Install dependencies
npm install
# Build CommonJS files from ESM source
npm run buildThe build process converts the ES Module source files in src/ to CommonJS in dist/.
Project Structure
src/- ES Module source code (edit these files)dist/- Generated CommonJS build (don't edit, auto-generated)build.js- Build script that transpiles ESM to CJSpackage.json- Configured with"type": "module"and dual exports
Making Changes
- Edit files in
src/(ESM format) - Run
npm run buildto generate CJS indist/ - Run
npm test— it stands up a local stub server, so it needs no API key and spends no credits. The suite also checks this README and QUICKSTART against the source: a documented parameter the SDK would silently drop, or a method shown nowhere, fails the build. - The
prepublishOnlyscript automatically builds before publishing
TypeScript Support
While this package is written in JavaScript, it works with TypeScript. Type definitions may be added in a future release.
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes in
src/ - Run
npm run build - Test both ESM and CJS usage
- Submit a Pull Request
License
MIT
Links
Support
For support, please visit the GitHub Issues page.
