From 733b82b49bf2e99b473a0f2e267f6a815ecf12c4 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 18 Oct 2025 04:20:05 -0400 Subject: [PATCH 01/12] Build TypeScript client for Scope3 Agentic API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Generate TypeScript types from OpenAPI schema - Implement core client with bearer token auth - Create resource wrappers for all API endpoints (assets, brand agents, campaigns, creatives, tactics, media buys, sales agents, notifications, products) - Add optional webhook server for AdCP events - Include comprehensive tests and examples - Full TypeScript support with clean, intuitive API ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .env.example | 6 + .eslintrc.json | 15 + .prettierrc.json | 7 + README.md | 194 +- examples/basic-usage.ts | 21 + examples/create-campaign.ts | 35 + examples/webhook-server.ts | 37 + jest.config.js | 7 + openapi.yaml | 2402 ++++++++++ package-lock.json | 6298 ++++++++++++++++++++++++++ package.json | 41 + src/__tests__/client.test.ts | 46 + src/__tests__/webhook-server.test.ts | 45 + src/client.ts | 60 + src/index.ts | 17 + src/resources/assets.ts | 29 + src/resources/brand-agents.ts | 49 + src/resources/brand-standards.ts | 45 + src/resources/brand-stories.ts | 45 + src/resources/campaigns.ts | 104 + src/resources/channels.ts | 10 + src/resources/creatives.ts | 79 + src/resources/media-buys.ts | 80 + src/resources/notifications.ts | 35 + src/resources/products.ts | 30 + src/resources/sales-agents.ts | 92 + src/resources/tactics.ts | 82 + src/sdk.ts | 46 + src/types/api.ts | 2152 +++++++++ src/types/index.ts | 18 + src/webhook-server.ts | 138 + tsconfig.json | 21 + 32 files changed, 12284 insertions(+), 2 deletions(-) create mode 100644 .env.example create mode 100644 .eslintrc.json create mode 100644 .prettierrc.json create mode 100644 examples/basic-usage.ts create mode 100644 examples/create-campaign.ts create mode 100644 examples/webhook-server.ts create mode 100644 jest.config.js create mode 100644 openapi.yaml create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/__tests__/client.test.ts create mode 100644 src/__tests__/webhook-server.test.ts create mode 100644 src/client.ts create mode 100644 src/index.ts create mode 100644 src/resources/assets.ts create mode 100644 src/resources/brand-agents.ts create mode 100644 src/resources/brand-standards.ts create mode 100644 src/resources/brand-stories.ts create mode 100644 src/resources/campaigns.ts create mode 100644 src/resources/channels.ts create mode 100644 src/resources/creatives.ts create mode 100644 src/resources/media-buys.ts create mode 100644 src/resources/notifications.ts create mode 100644 src/resources/products.ts create mode 100644 src/resources/sales-agents.ts create mode 100644 src/resources/tactics.ts create mode 100644 src/sdk.ts create mode 100644 src/types/api.ts create mode 100644 src/types/index.ts create mode 100644 src/webhook-server.ts create mode 100644 tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7b0b16e --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +# Scope3 API Configuration +SCOPE3_API_KEY=your-api-key-here + +# Webhook Server Configuration (optional) +WEBHOOK_SECRET=your-webhook-secret-here +WEBHOOK_PORT=3000 diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..50c12da --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + }, + "rules": { + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/explicit-function-return-type": "off" + } +} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..3de448e --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "semi": true, + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 100, + "tabWidth": 2 +} diff --git a/README.md b/README.md index 6b8b801..96180ff 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,192 @@ -# agentic-client -Typescript client for the Scope3 agentic API, with optional server for handling async (webhooks) +# Scope3 Agentic Client + +TypeScript client for the Scope3 Agentic API with AdCP webhook support. + +## Features + +- ๐Ÿš€ Full TypeScript support with generated types from OpenAPI schema +- ๐Ÿ“ฆ Complete API coverage for all Scope3 endpoints +- ๐Ÿ” Bearer token authentication +- ๐Ÿช Optional webhook server for AdCP events +- โœจ Clean, intuitive API design +- ๐Ÿงช Comprehensive test coverage + +## Installation + +```bash +npm install @scope3/agentic-client +``` + +## Quick Start + +```typescript +import { Scope3SDK } from '@scope3/agentic-client'; + +const client = new Scope3SDK({ + apiKey: process.env.SCOPE3_API_KEY, +}); + +// List brand agents +const brandAgents = await client.brandAgents.list(); + +// Create a campaign +const campaign = await client.campaigns.create({ + prompt: 'Create a video campaign targeting tech enthusiasts', + budget: { + amount: 5000000, // $50,000 in cents + currency: 'USD', + pacing: 'even', + }, +}); +``` + +## Configuration + +```typescript +const client = new Scope3SDK({ + apiKey: 'your-api-key', + baseUrl: 'https://api.agentic.scope3.com', // optional, defaults to production + timeout: 30000, // optional, request timeout in ms +}); +``` + +## API Resources + +The client provides access to all Scope3 API resources: + +### Assets +```typescript +await client.assets.upload({ brandAgentId, assets: [...] }); +await client.assets.list({ brandAgentId }); +``` + +### Brand Agents +```typescript +await client.brandAgents.list(); +await client.brandAgents.create({ name: 'My Brand' }); +await client.brandAgents.get({ brandAgentId }); +await client.brandAgents.update({ brandAgentId, name: 'Updated Name' }); +await client.brandAgents.delete({ brandAgentId }); +``` + +### Campaigns +```typescript +await client.campaigns.list({ status: 'ACTIVE' }); +await client.campaigns.create({ prompt: '...', budget: {...} }); +await client.campaigns.update({ campaignId, status: 'PAUSED' }); +await client.campaigns.getSummary({ campaignId }); +await client.campaigns.listTactics({ campaignId }); +await client.campaigns.delete({ campaignId }); +``` + +### Creatives +```typescript +await client.creatives.list({ brandAgentId }); +await client.creatives.create({ brandAgentId, name: '...' }); +await client.creatives.assign({ creativeId, campaignId }); +``` + +### Tactics +```typescript +await client.tactics.list({ campaignId }); +await client.tactics.create({ name: '...', campaignId }); +await client.tactics.update({ tacticId, channelCodes: ['DIGITAL-AUDIO'] }); +``` + +### Media Buys +```typescript +await client.mediaBuys.list({ tacticId }); +await client.mediaBuys.create({ + tacticId, + name: '...', + products: [{ mediaProductId, salesAgentId }], + budget: { amount: 1000000 }, +}); +await client.mediaBuys.execute({ mediaBuyId }); +``` + +### Sales Agents +```typescript +await client.salesAgents.list(); +await client.salesAgents.register({ + name: '...', + endpointUrl: '...', + protocol: 'A2A', + authenticationType: 'API_KEY', +}); +``` + +### Other Resources +- `client.brandStandards` - Brand safety standards +- `client.brandStories` - AI-powered audience definitions +- `client.channels` - Advertising channels +- `client.notifications` - System notifications +- `client.products` - Media product management + +## Webhook Server + +The client includes an optional webhook server for handling AdCP events: + +```typescript +import { WebhookServer } from '@scope3/agentic-client'; + +const webhookServer = new WebhookServer({ + port: 3000, + path: '/webhooks', + secret: process.env.WEBHOOK_SECRET, // optional +}); + +// Register event handlers +webhookServer.on('campaign.created', async (event) => { + console.log('Campaign created:', event.data); +}); + +webhookServer.on('media_buy.executed', async (event) => { + console.log('Media buy executed:', event.data); +}); + +// Catch all events +webhookServer.on('*', async (event) => { + console.log('Event received:', event.type); +}); + +// Start the server +await webhookServer.start(); +console.log(`Webhook server running at ${webhookServer.getUrl()}`); + +// Stop the server +await webhookServer.stop(); +``` + +## Development + +```bash +# Install dependencies +npm install + +# Build the project +npm run build + +# Run tests +npm test + +# Run linter +npm run lint + +# Format code +npm run format + +# Generate types from OpenAPI spec +npm run generate-types +``` + +## Examples + +See the `examples/` directory for more usage examples: +- `basic-usage.ts` - Basic API usage +- `create-campaign.ts` - Campaign creation workflow +- `webhook-server.ts` - Webhook server setup + +## License + +MIT diff --git a/examples/basic-usage.ts b/examples/basic-usage.ts new file mode 100644 index 0000000..83bc089 --- /dev/null +++ b/examples/basic-usage.ts @@ -0,0 +1,21 @@ +import { Scope3SDK } from '../src'; + +async function main() { + const client = new Scope3SDK({ + apiKey: process.env.SCOPE3_API_KEY || 'your-api-key', + }); + + try { + console.log('Listing brand agents...'); + const brandAgents = await client.brandAgents.list(); + console.log('Brand agents:', brandAgents); + + console.log('\nListing channels...'); + const channels = await client.channels.list(); + console.log('Channels:', channels); + } catch (error) { + console.error('Error:', error); + } +} + +main(); diff --git a/examples/create-campaign.ts b/examples/create-campaign.ts new file mode 100644 index 0000000..ff50fee --- /dev/null +++ b/examples/create-campaign.ts @@ -0,0 +1,35 @@ +import { Scope3SDK } from '../src'; + +async function main() { + const client = new Scope3SDK({ + apiKey: process.env.SCOPE3_API_KEY || 'your-api-key', + }); + + try { + console.log('Creating campaign...'); + const campaign = await client.campaigns.create({ + prompt: 'Create a video campaign targeting tech enthusiasts with $50k budget', + name: 'Tech Enthusiasts Video Campaign', + budget: { + amount: 5000000, + currency: 'USD', + pacing: 'even', + }, + status: 'ACTIVE', + }); + + console.log('Campaign created:', campaign); + + if (campaign.success && campaign.data) { + const campaignId = campaign.data.id; + + console.log('\nGetting campaign summary...'); + const summary = await client.campaigns.getSummary({ campaignId }); + console.log('Campaign summary:', summary); + } + } catch (error) { + console.error('Error:', error); + } +} + +main(); diff --git a/examples/webhook-server.ts b/examples/webhook-server.ts new file mode 100644 index 0000000..958e76a --- /dev/null +++ b/examples/webhook-server.ts @@ -0,0 +1,37 @@ +import { WebhookServer } from '../src'; + +async function main() { + const webhookServer = new WebhookServer({ + port: 3000, + path: '/webhooks', + secret: process.env.WEBHOOK_SECRET, + }); + + webhookServer.on('campaign.created', async (event) => { + console.log('Campaign created:', event); + }); + + webhookServer.on('campaign.updated', async (event) => { + console.log('Campaign updated:', event); + }); + + webhookServer.on('media_buy.executed', async (event) => { + console.log('Media buy executed:', event); + }); + + webhookServer.on('*', async (event) => { + console.log('Received webhook:', event.type); + }); + + await webhookServer.start(); + console.log(`Webhook server running at ${webhookServer.getUrl()}`); + console.log('Press Ctrl+C to stop'); + + process.on('SIGINT', async () => { + console.log('\nShutting down webhook server...'); + await webhookServer.stop(); + process.exit(0); + }); +} + +main(); diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..51956da --- /dev/null +++ b/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + roots: ['/src'], + testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], + collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts', '!src/**/*.test.ts'], +}; diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..c2043b6 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,2402 @@ +openapi: 3.0.0 +info: + title: Jackson Agentic API + version: 1.0.0 + description: | + Comprehensive API for the Jackson Agentic Advertising Platform. + This API provides tools for managing brand agents, campaigns, creatives, tactics, + media buys, and more through natural language interfaces and structured endpoints. + +servers: + - url: https://api.agentic.scope3.com + description: Production server + - url: https://api.agentic.staging.scope3.com + description: Staging server + +security: + - bearerAuth: [] + +tags: + - name: Assets + description: Upload and manage creative assets + - name: Brand Agents + description: Manage brand agent (advertiser) accounts + - name: Brand Standards + description: Manage brand safety standards and rules + - name: Brand Stories + description: AI-powered audience definitions + - name: Campaigns + description: Campaign creation and management + - name: Channels + description: Advertising channel management + - name: Creatives + description: Creative asset management + - name: Sales Agents + description: Publisher/sales agent registration + - name: Tactics + description: Media buying tactics + - name: Media Buys + description: Media buy execution and management + - name: Notifications + description: System notifications + - name: Products + description: Media product management + +paths: + /asset-upload: + post: + tags: [Assets] + summary: Upload creative assets + operationId: asset_upload + description: Upload creative assets (images, videos, audio) to Google Cloud Storage. Accepts base64-encoded file data and returns signed URLs (valid for 1 hour). + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId, assets] + properties: + brandAgentId: + type: string + description: Brand agent ID for file organization + assets: + type: array + description: Array of assets to upload + items: + type: object + required: [name, contentType, data, assetType] + properties: + name: + type: string + description: Original filename + contentType: + type: string + description: MIME type (e.g., image/png, video/mp4) + data: + type: string + format: byte + description: Base64-encoded file data + assetType: + type: string + enum: [image, video, audio, logo, font] + description: Type of asset + tags: + type: array + items: + type: string + description: Optional tags for organization + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /asset-list: + post: + tags: [Assets] + summary: List creative assets + operationId: asset_list + description: List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + brandAgentId: + type: string + description: Optional brand agent ID to filter assets + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-agent-list: + post: + tags: [Brand Agents] + summary: List brand agents + operationId: brand_agent_list + description: List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: {} + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-agent-create: + post: + tags: [Brand Agents] + summary: Create brand agent + operationId: brand_agent_create + description: Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + description: Name of the brand agent (advertiser account) + description: + type: string + description: Optional description of the brand agent + nickname: + type: string + description: Friendly name for easy identification (e.g., 'Nike' for 'Nike c/o Kinesso') + externalId: + type: string + description: Your internal ID for this brand agent (e.g., client code or account ID) + advertiserDomains: + type: array + items: + type: string + description: Domains where users will be sent from all campaigns/creatives + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-agent-get: + post: + tags: [Brand Agents] + summary: Get brand agent + operationId: brand_agent_get + description: Get detailed information about a specific brand agent (advertiser account) by ID. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId] + properties: + brandAgentId: + type: string + description: ID of the brand agent to retrieve + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /brand-agent-update: + post: + tags: [Brand Agents] + summary: Update brand agent + operationId: brand_agent_update + description: Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId] + properties: + brandAgentId: + type: string + description: ID of the brand agent to update + name: + type: string + description: New name for the brand agent + description: + type: string + description: New description for the brand agent + tacticSeedDataCoop: + type: boolean + description: Enable/disable tactic seed data cooperative participation + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /brand-agent-delete: + post: + tags: [Brand Agents] + summary: Delete brand agent + operationId: brand_agent_delete + description: โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId] + properties: + brandAgentId: + type: string + description: ID of the brand agent to delete permanently + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /brand-standards-list: + post: + tags: [Brand Standards] + summary: List brand standards + operationId: brand_standards_list + description: List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + where: + type: object + description: Optional filtering criteria + properties: + name: + type: string + description: Filter by name + orderBy: + type: object + description: Optional ordering for results + properties: + id: + type: string + enum: [asc, desc] + name: + type: string + enum: [asc, desc] + take: + type: number + description: Number of records to return (pagination) + skip: + type: number + description: Number of records to skip (pagination) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-standards-create: + post: + tags: [Brand Standards] + summary: Create brand standard + operationId: brand_standards_create + description: Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId, prompt] + properties: + brandAgentId: + type: string + description: ID of the brand to create standards for + name: + type: string + description: Name for the brand standard (optional - defaults to "{Brand Name} Standards") + prompt: + type: string + description: Natural language prompt defining the brand safety standards, content restrictions, and enforcement rules + description: + type: string + description: Description for the brand standard + isArchived: + type: boolean + description: Whether to create the standard as archived + countries: + type: array + items: + type: string + description: List of country codes to target (e.g., ['US', 'CA']) + channels: + type: array + items: + type: string + description: List of channels to target (e.g., ['web', 'social']) + brands: + type: array + items: + type: string + description: List of specific brands this applies to + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-standards-delete: + post: + tags: [Brand Standards] + summary: Delete brand standard + operationId: brand_standards_delete + description: โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandStandardId] + properties: + brandStandardId: + type: string + description: ID of the brand standard to delete + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /brand-story-list: + post: + tags: [Brand Stories] + summary: List brand stories + operationId: brand_story_list + description: List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId] + properties: + brandAgentId: + type: string + description: ID of the brand to list brand stories for + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-story-create: + post: + tags: [Brand Stories] + summary: Create brand story + operationId: brand_story_create + description: Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId, name, prompt] + properties: + brandAgentId: + type: string + description: ID of the brand to create a brand story for + name: + type: string + description: Name for the brand story (e.g., 'Tech Enthusiasts', 'Luxury Shoppers') + prompt: + type: string + description: Natural language prompt defining the target audience profile, demographics, and behavioral characteristics + countries: + type: array + items: + type: string + description: List of country codes to target (e.g., ['US', 'CA']) + channels: + type: array + items: + type: string + description: List of channels to target (e.g., ['web', 'social']) + languages: + type: array + items: + type: string + description: List of language codes to target (e.g., ['en', 'es']) + brands: + type: array + items: + type: string + description: List of specific brands this applies to + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /brand-story-update: + post: + tags: [Brand Stories] + summary: Update brand story + operationId: brand_story_update + description: Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandStoryId, prompt] + properties: + brandStoryId: + type: string + description: ID of the brand story to update + prompt: + type: string + description: New audience definition prompt + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /brand-story-delete: + post: + tags: [Brand Stories] + summary: Delete brand story + operationId: brand_story_delete + description: โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandStoryId] + properties: + brandStoryId: + type: string + description: ID of the brand story to delete + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-list: + post: + tags: [Campaigns] + summary: List campaigns + operationId: campaign_list + description: List campaigns for the authenticated customer, with optional filtering. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + brandAgentId: + type: string + description: Optional brand agent ID to filter campaigns + status: + type: string + enum: [ACTIVE, PAUSED, ARCHIVED] + description: Optional status filter + limit: + type: number + description: Maximum number of campaigns to return (default 100) + offset: + type: number + description: Number of campaigns to skip for pagination + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-create: + post: + tags: [Campaigns] + summary: Create campaign + operationId: campaign_create + description: Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [prompt] + properties: + brandAgentId: + type: string + description: Optional brand agent ID that will own this campaign + name: + type: string + description: Optional name for the campaign (auto-generated if not provided) + prompt: + type: string + description: Natural language description of campaign requirements (e.g., 'Create a video campaign targeting tech enthusiasts with $50k budget') + budget: + $ref: '#/components/schemas/Budget' + startDate: + type: string + format: date-time + description: Campaign start date (ISO 8601 format) + endDate: + type: string + format: date-time + description: Campaign end date (ISO 8601 format) + scoringWeights: + $ref: '#/components/schemas/ScoringWeights' + outcomeScoreWindowDays: + type: number + description: Days for outcome measurement window + segmentIds: + type: array + items: + type: string + description: Array of segment IDs to associate with campaign + dealIds: + type: array + items: + type: string + description: Array of deal IDs to associate with campaign + visibility: + type: string + enum: [PUBLIC, PRIVATE] + description: Campaign visibility setting + status: + type: string + enum: [ACTIVE, PAUSED, ARCHIVED] + description: Initial campaign status + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-update: + post: + tags: [Campaigns] + summary: Update campaign + operationId: campaign_update + description: Update an existing campaign's settings. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [campaignId] + properties: + campaignId: + type: string + description: ID of the campaign to update + name: + type: string + description: New name for the campaign + prompt: + type: string + description: Updated natural language campaign requirements + status: + type: string + enum: [ACTIVE, PAUSED, ARCHIVED] + description: New status for the campaign + budget: + $ref: '#/components/schemas/Budget' + startDate: + type: string + format: date-time + description: Campaign start date (ISO 8601 format) + endDate: + type: string + format: date-time + description: Campaign end date (ISO 8601 format) + scoringWeights: + type: object + properties: + affinity: + type: number + description: Weight for affinity scoring (0-1) + outcome: + type: number + description: Weight for outcome scoring (0-1) + quality: + type: number + description: Weight for quality scoring (0-1) + description: Scoring weights configuration + outcomeScoreWindowDays: + type: number + description: Days for outcome measurement window + segmentIds: + type: array + items: + type: string + description: Array of segment IDs to associate with campaign + dealIds: + type: array + items: + type: string + description: Array of deal IDs to associate with campaign + visibility: + type: string + enum: [PUBLIC, PRIVATE] + description: Campaign visibility setting + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-delete: + post: + tags: [Campaigns] + summary: Delete campaign + operationId: campaign_delete + description: โš ๏ธ DANGER - Permanently delete a campaign and all associated data. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [campaignId] + properties: + campaignId: + type: string + description: ID of the campaign to delete + hardDelete: + type: boolean + description: If true, permanently delete the campaign. Default false (soft delete/archive) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-get-summary: + post: + tags: [Campaigns] + summary: Get campaign summary + operationId: campaign_get_summary + description: Get detailed summary information about a specific campaign. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [campaignId] + properties: + campaignId: + type: string + description: ID of the campaign to retrieve + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-list-tactics: + post: + tags: [Campaigns] + summary: List campaign tactics + operationId: campaign_list_strategies + description: List all tactics associated with a specific campaign. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [campaignId] + properties: + campaignId: + type: string + description: ID of the campaign to list tactics for + includeArchived: + type: boolean + description: Include archived tactics (defaults to false) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /campaign-validate-brief: + post: + tags: [Campaigns] + summary: Validate campaign brief + operationId: campaign_validate_brief + description: Validate a campaign brief to ensure it contains all necessary information. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brief] + properties: + brief: + type: string + description: Campaign brief to validate + brandAgentId: + type: string + description: Optional brand agent ID for context-aware validation + threshold: + type: number + minimum: 0 + maximum: 100 + default: 70 + description: Minimum quality score required to pass validation + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /channel-list: + post: + tags: [Channels] + summary: List channels + operationId: channel_list + description: List all available advertising channels. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: {} + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /creative-list: + post: + tags: [Creatives] + summary: List creatives + operationId: creative_list + description: List creatives for the authenticated customer, with optional filtering. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + brandAgentId: + type: string + description: Optional brand agent ID to filter creatives + campaignId: + type: string + description: Optional campaign ID to filter creatives + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /creative-create: + post: + tags: [Creatives] + summary: Create creative + operationId: creative_create + description: Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [brandAgentId, name] + properties: + brandAgentId: + type: integer + description: Internal database ID of the brand agent that will own this creative + organizationId: + type: integer + description: Optional internal database ID of the organization + name: + type: string + description: Name for the creative + description: + type: string + description: Optional description of the creative + formatSource: + type: string + enum: [ADCP, CREATIVE_AGENT, PUBLISHER] + description: Format source type + formatId: + type: string + description: Format identifier (e.g., "video/mp4", "display/banner") + mediaUrl: + type: string + description: URL to the creative media file (video, image, etc.) + content: + type: object + description: Creative content as JSON. Can include assetIds (array of asset IDs from asset_upload), htmlSnippet, vastTag, etc. + properties: + assetIds: + type: array + items: + type: string + description: Array of asset IDs uploaded via asset_upload tool + htmlSnippet: + type: string + description: HTML5 creative snippet + vastTag: + type: string + description: VAST XML tag for video ads + assemblyMethod: + type: string + enum: [CREATIVE_AGENT, ACTIVATION, PUBLISHER] + description: Assembly method + campaignId: + type: integer + description: Optional internal database ID of campaign to assign creative to + responses: + '200': + description: Creative created successfully + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + description: Success message with creative details including creativeId (external string ID for use in media_buy_create/update) and internal ID + example: | + โœ… **Creative Created Successfully!** + + **Creative ID:** newcreativevideo_xntthe4w (use this for media_buy_create/update) + **Internal ID:** 16 + **Name:** My Creative + **Status:** PENDING + **Created:** 2025-10-14T00:00:00.000Z + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /creative-get: + post: + tags: [Creatives] + summary: Get creative + operationId: creative_get + description: Get detailed information about a specific creative. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [creativeId] + properties: + creativeId: + type: integer + description: Internal database ID of the creative to retrieve + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /creative-update: + post: + tags: [Creatives] + summary: Update creative + operationId: creative_update + description: Update an existing creative's settings. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [creativeId] + properties: + creativeId: + type: integer + description: Internal database ID of the creative to update + name: + type: string + description: New name for the creative + status: + type: string + description: New status for the creative + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /creative-delete: + post: + tags: [Creatives] + summary: Delete creative + operationId: creative_delete + description: โš ๏ธ DANGER - Permanently delete a creative. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [creativeId] + properties: + creativeId: + type: integer + description: Internal database ID of the creative to delete + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /creative-assign: + post: + tags: [Creatives] + summary: Assign creative to campaign + operationId: creative_assign + description: | + Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents + associated with the campaign via active media buys. Returns auto-sync results including which agents + received the creative and their approval status. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [creativeId, campaignId] + properties: + creativeId: + type: integer + description: Internal database ID of the creative to assign + campaignId: + type: integer + description: Internal database ID of the campaign to assign creative to + responses: + '200': + description: Creative assigned successfully with auto-sync results + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + type: object + properties: + type: + type: string + example: text + text: + type: string + description: | + Summary of creative assignment including auto-sync results. + Shows which sales agents received the creative and their approval status. + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /creative-sync-sales-agents: + post: + tags: [Creatives] + summary: Sync creative with sales agents + operationId: creative_sync_sales_agents + description: Sync a creative's formats and specifications with connected sales agents/publishers. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [creativeId] + properties: + creativeId: + type: integer + description: Internal database ID of the creative to sync + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-list: + post: + tags: [Sales Agents] + summary: List sales agents + operationId: sales_agent_list + description: List all registered sales agents (publishers) for the authenticated customer. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: {} + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-get: + post: + tags: [Sales Agents] + summary: Get sales agent + operationId: sales_agent_get + description: Get detailed information about a specific sales agent. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId] + properties: + salesAgentId: + type: string + description: ID of the sales agent to retrieve + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-register: + post: + tags: [Sales Agents] + summary: Register sales agent + operationId: sales_agent_register + description: Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name, endpointUrl, protocol, authenticationType] + properties: + name: + type: string + description: Sales agent name + endpointUrl: + type: string + description: Sales agent endpoint URL + protocol: + type: string + enum: [REST, MCP, A2A, CUSTOM] + description: Protocol type + authenticationType: + type: string + enum: [API_KEY, OAUTH, NO_AUTH] + description: Authentication type + description: + type: string + description: Sales agent description (optional) + organizationId: + type: string + description: Organization ID (optional - auto-detected from customer if not provided) + authConfig: + type: object + description: Authentication configuration for the sales agent (optional) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-account-list: + post: + tags: [Sales Agents] + summary: List accounts for a sales agent + operationId: sales_agent_account_list + description: List all accounts registered by your organization for a specific sales agent. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId] + properties: + salesAgentId: + type: string + description: ID of the sales agent + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-account-register: + post: + tags: [Sales Agents] + summary: Register account for sales agent + operationId: sales_agent_account_register + description: Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId, accountIdentifier] + properties: + salesAgentId: + type: string + description: Sales agent ID + accountIdentifier: + type: string + description: Account identifier + authConfig: + type: object + description: Authentication configuration (credentials, tokens, etc.) - optional + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-unregister: + post: + tags: [Sales Agents] + summary: Unregister sales agent completely + operationId: sales_agent_unregister + description: Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId, confirm] + properties: + salesAgentId: + type: string + description: ID of the sales agent to unregister + confirm: + type: boolean + description: Must be true to confirm this destructive operation + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-account-unregister: + post: + tags: [Sales Agents] + summary: Unregister your account with a sales agent + operationId: sales_agent_account_unregister + description: Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId, confirm] + properties: + salesAgentId: + type: string + description: ID of the sales agent to unregister your account from + confirm: + type: boolean + description: Must be true to confirm this destructive operation + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-update: + post: + tags: [Sales Agents] + summary: Update sales agent + operationId: sales_agent_update + description: Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId] + properties: + salesAgentId: + type: string + description: ID of the sales agent to update + name: + type: string + description: New name + description: + type: string + description: New description + endpointUrl: + type: string + description: New endpoint URL + protocol: + type: string + enum: [REST, MCP, A2A, CUSTOM] + description: New protocol + authenticationType: + type: string + enum: [API_KEY, OAUTH, NO_AUTH] + description: New authentication type + authConfig: + type: object + description: Authentication configuration for the sales agent + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /sales-agent-account-update: + post: + tags: [Sales Agents] + summary: Update sales agent account authentication + operationId: sales_agent_account_update + description: Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId, accountIdentifier, authConfig] + properties: + salesAgentId: + type: string + description: ID of the sales agent + accountIdentifier: + type: string + description: Account identifier to update + authConfig: + type: object + description: Updated authentication configuration (credentials, tokens, etc.) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-list: + post: + tags: [Tactics] + summary: List tactics + operationId: strategy_list + description: List all media buying tactics for the authenticated customer. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + campaignId: + type: string + description: Optional campaign ID to filter tactics + includeArchived: + type: boolean + description: Include archived tactics (defaults to false) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-create: + post: + tags: [Tactics] + summary: Create tactic + operationId: strategy_create + description: Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name, campaignId] + properties: + name: + type: string + description: Name of the tactic + campaignId: + type: string + description: Campaign ID to link this tactic to (required) + prompt: + type: string + description: Optional tactical brief or prompt for this tactic + channelCodes: + type: array + items: + type: string + enum: [DIGITAL-AUDIO, DISPLAY-WEB, DISPLAY-APP, CTV-BVOD, OLV, DOOH, SOCIAL] + description: Valid channel codes to target (also accepts friendly aliases like audio, web, app, ctv, video which are automatically mapped) + countryCodes: + type: array + items: + type: string + description: Country codes to target (2-digit ISO codes) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-get: + post: + tags: [Tactics] + summary: Get tactic + operationId: strategy_get + description: Get detailed information about a specific tactic. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [tacticId] + properties: + tacticId: + type: string + description: ID of the tactic to retrieve + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-update: + post: + tags: [Tactics] + summary: Update tactic + operationId: strategy_update + description: Update an existing tactic's configuration. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [tacticId] + properties: + tacticId: + type: string + description: ID of the tactic to update + name: + type: string + description: New name for the tactic + prompt: + type: string + description: New tactical brief + channelCodes: + type: array + items: + type: string + enum: [DIGITAL-AUDIO, DISPLAY-WEB, DISPLAY-APP, CTV-BVOD, OLV, DOOH, SOCIAL] + description: Updated channel codes (also accepts friendly aliases like audio, web, app, ctv, video) + countryCodes: + type: array + items: + type: string + description: Updated country codes + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-delete: + post: + tags: [Tactics] + summary: Delete tactic + operationId: strategy_delete + description: โš ๏ธ DANGER - Permanently delete a tactic. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [tacticId] + properties: + tacticId: + type: string + description: ID of the tactic to delete + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-link-campaign: + post: + tags: [Tactics] + summary: Link campaign to tactic + operationId: strategy_link_campaign + description: Link a campaign to a tactic for budget and execution management. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [tacticId, campaignId] + properties: + tacticId: + type: string + description: ID of the tactic + campaignId: + type: string + description: ID of the campaign to link + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /tactic-unlink-campaign: + post: + tags: [Tactics] + summary: Unlink campaign from tactic + operationId: strategy_unlink_campaign + description: Unlink a campaign from a tactic. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [tacticId, campaignId] + properties: + tacticId: + type: string + description: ID of the tactic + campaignId: + type: string + description: ID of the campaign to unlink + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /media-buy-list: + post: + tags: [Media Buys] + summary: List media buys + operationId: media_buy_list + description: List all media buys for the authenticated customer. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tacticId: + type: string + description: Optional tactic ID to filter media buys + campaignId: + type: string + description: Optional campaign ID to filter media buys + includeArchived: + type: boolean + description: Include archived media buys (defaults to false) + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /media-buy-create: + post: + tags: [Media Buys] + summary: Create media buy + operationId: media_buy_create + description: | + Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. + + **Multi-Product Support**: Media buys now support multiple products from different sales agents in a single buy. Each product can have its own budget allocation and pricing. During execution, each unique sales agent will receive a separate ADCP submission. + + **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [tacticId, name, products, budget] + properties: + tacticId: + type: string + description: ID of the tactic to execute + name: + type: string + description: Name of the media buy + description: + type: string + description: Optional description of the media buy + products: + type: array + description: Array of products to include in this media buy. At least one product is required. Each product will be validated with its sales agent. + minItems: 1 + items: + type: object + required: [mediaProductId, salesAgentId] + properties: + mediaProductId: + type: string + description: Media product ID from publisher (will be validated with sales agent) + salesAgentId: + type: string + description: Sales agent ID for this product + budgetAmount: + type: number + description: Budget allocated to this specific product (optional, must not exceed total budget when summed across all products) + budgetCurrency: + type: string + description: Currency for this product's budget (defaults to media buy currency) + pricingCpm: + type: number + description: Base CPM price for this product + pricingSignalCost: + type: number + description: Additional signal cost for this product + displayOrder: + type: integer + description: Optional display order for organizing products + budget: + type: object + required: [amount] + properties: + amount: + type: number + description: Total budget amount for this media buy + currency: + type: string + description: Currency code (defaults to USD) + dailyCap: + type: number + description: Optional daily spending cap + pacing: + type: string + enum: [asap, even, front_loaded] + description: Budget pacing tactic (defaults to even) + creativeIds: + type: array + items: + type: string + description: Optional array of creative IDs (database IDs) to assign to this media buy. Creatives must be assigned to the campaign associated with this media buy's tactic. + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /media-buy-get: + post: + tags: [Media Buys] + summary: Get media buy + operationId: media_buy_get + description: Get detailed information about a specific media buy. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [mediaBuyId] + properties: + mediaBuyId: + type: string + description: ID of the media buy to retrieve + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /media-buy-update: + post: + tags: [Media Buys] + summary: Update media buy + operationId: media_buy_update + description: Update an existing media buy's configuration. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [mediaBuyId] + properties: + mediaBuyId: + type: string + description: ID of the media buy to update + name: + type: string + description: New name + budget: + type: object + properties: + amount: + type: number + dailyCap: + type: number + pacing: + type: string + enum: [asap, even, front_loaded] + cpm: + type: number + description: New CPM price + creativeIds: + type: array + items: + type: string + description: Array of creative IDs (database IDs) to assign to this media buy. Replaces existing assignments. Creatives must be assigned to the campaign associated with this media buy's tactic. + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /media-buy-delete: + post: + tags: [Media Buys] + summary: Delete media buy + operationId: media_buy_delete + description: โš ๏ธ DANGER - Permanently delete a media buy. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [mediaBuyId] + properties: + mediaBuyId: + type: string + description: ID of the media buy to delete + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /media-buy-execute: + post: + tags: [Media Buys] + summary: Execute media buy + operationId: media_buy_execute + description: Execute a media buy by deploying it to the publisher platform. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [mediaBuyId] + properties: + mediaBuyId: + type: string + description: ID of the media buy to execute + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /notifications-list: + post: + tags: [Notifications] + summary: List notifications + operationId: notifications_list + description: List notifications for the authenticated user. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + unreadOnly: + type: boolean + description: Filter to only unread notifications + limit: + type: number + description: Maximum number of notifications to return + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /notifications-mark-read: + post: + tags: [Notifications] + summary: Mark notification as read + operationId: notifications_mark_read + description: Mark a specific notification as read. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [notificationId] + properties: + notificationId: + type: string + description: ID of the notification to mark as read + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /notifications-mark-acknowledged: + post: + tags: [Notifications] + summary: Mark notification as acknowledged + operationId: notifications_mark_acknowledged + description: Mark a specific notification as acknowledged. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [notificationId] + properties: + notificationId: + type: string + description: ID of the notification to mark as acknowledged + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + + /notifications-mark-all-read: + post: + tags: [Notifications] + summary: Mark all notifications as read + operationId: notifications_mark_all_read + description: Mark all notifications as read for the authenticated user. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: {} + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /media-product-list: + post: + tags: [Products] + summary: List media products + operationId: media_product_list + description: List available media products from publishers. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + salesAgentId: + type: string + description: Optional sales agent ID to filter products + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /media-product-discover: + post: + tags: [Products] + summary: Discover media products + operationId: media_product_discover + description: Discover new media products from connected publishers. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + salesAgentId: + type: string + description: Sales agent ID to discover products from + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalError' + + /media-product-sync: + post: + tags: [Products] + summary: Sync media products + operationId: media_product_sync + description: Synchronize media product inventory with publisher systems. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [salesAgentId] + properties: + salesAgentId: + type: string + description: Sales agent ID to sync products from + responses: + '200': + $ref: '#/components/responses/ToolResponse' + '401': + $ref: '#/components/responses/Unauthorized' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/InternalError' + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: Bearer token authentication using Scope3 API key + + responses: + ToolResponse: + description: Successful tool execution + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Whether the operation succeeded + message: + type: string + description: Human-readable response message + data: + type: object + description: Response data (varies by tool) + + BadRequest: + description: Bad request - invalid parameters + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error message + details: + type: object + description: Additional error details + + Unauthorized: + description: Unauthorized - invalid or missing authentication + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error message + + NotFound: + description: Resource not found + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error message + + InternalError: + description: Internal server error + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error message + + schemas: + Budget: + type: object + required: [total, currency] + properties: + total: + type: integer + description: Total budget amount in cents (e.g., 5000000 = $50,000) + currency: + type: string + enum: [USD, EUR, GBP, CAD, AUD] + description: Budget currency + dailyCap: + type: integer + description: Daily spending limit in cents + pacing: + type: string + enum: [even, accelerated, front_loaded] + description: Budget pacing tactic + + ScoringWeights: + type: object + properties: + affinity: + type: number + minimum: 0 + maximum: 1 + description: Weight for affinity scoring (0-1) + outcome: + type: number + minimum: 0 + maximum: 1 + description: Weight for outcome scoring (0-1) + quality: + type: number + minimum: 0 + maximum: 1 + description: Weight for quality scoring (0-1) + + BrandAgent: + type: object + required: [id, name, createdAt, updatedAt] + properties: + id: + type: string + description: Unique brand agent identifier + name: + type: string + description: Brand agent name + description: + type: string + description: Brand agent description + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + + Campaign: + type: object + required: [id, name, prompt, brandAgentId, status, createdAt, updatedAt] + properties: + id: + type: string + description: Unique campaign identifier + name: + type: string + description: Campaign name + prompt: + type: string + description: Natural language campaign description + brandAgentId: + type: string + description: Parent brand agent ID + status: + type: string + enum: [active, paused, completed, draft] + description: Campaign status + budget: + $ref: '#/components/schemas/Budget' + audienceIds: + type: array + items: + type: string + description: Associated synthetic audience IDs + creativeIds: + type: array + items: + type: string + description: Associated creative asset IDs + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + + Creative: + type: object + required: [id, name, type, url, brandAgentId, createdAt, updatedAt] + properties: + id: + type: string + description: Unique creative identifier + name: + type: string + description: Creative name + type: + type: string + enum: [video, image, native, html5] + description: Creative asset type + url: + type: string + format: uri + description: Creative asset URL + brandAgentId: + type: string + description: Parent brand agent ID + headline: + type: string + description: Creative headline text + body: + type: string + description: Creative body text + cta: + type: string + description: Call-to-action text + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + + Tactic: + type: object + required: [id, name, campaignId, activityType, tacticType, createdAt, updatedAt] + properties: + id: + type: string + description: Unique tactic identifier + name: + type: string + description: Tactic name + campaignId: + type: string + description: Associated campaign ID + prompt: + type: string + description: Tactical brief or prompt + activityType: + type: string + enum: [AMP] + description: Activity type (always AMP) + tacticType: + type: string + enum: [INTELLIGENT_CAMPAIGNS] + description: Tactic type + channelCodes: + type: array + items: + type: string + enum: [DIGITAL-AUDIO, DISPLAY-WEB, DISPLAY-APP, CTV-BVOD, OLV, DOOH, SOCIAL] + description: Target channels (official codes) + countryCodes: + type: array + items: + type: string + description: Target countries + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + + MediaBuy: + type: object + required: [id, name, tacticId, salesAgentId, mediaProductId, budget, cpm, createdAt, updatedAt] + properties: + id: + type: string + description: Unique media buy identifier + name: + type: string + description: Media buy name + description: + type: string + description: Media buy description + tacticId: + type: string + description: Associated tactic ID + salesAgentId: + type: string + description: Publisher/sales agent ID + mediaProductId: + type: string + description: Media product ID + budget: + type: object + properties: + amount: + type: number + currency: + type: string + dailyCap: + type: number + pacing: + type: string + cpm: + type: number + description: CPM pricing + signalCost: + type: number + description: Additional signal cost + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b55aba9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6298 @@ +{ + "name": "@scope3/agentic-client", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@scope3/agentic-client", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "axios": "^1.6.0", + "express": "^4.18.0" + }, + "devDependencies": { + "@types/express": "^4.17.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.0.0", + "jest": "^29.5.0", + "openapi-typescript": "^6.7.0", + "prettier": "^3.0.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", + "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.22.tgz", + "integrity": "sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.0.tgz", + "integrity": "sha512-zBF6vZJn1IaMpg3xUF25VK3gd3l8zwE0ZLRX7dsQyQi+jp4E8mMDJNGDYnYse+bQhYwWERTxVwHpi3dMOq7RKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.9.tgz", + "integrity": "sha512-dOTIuqpWLyl3BBXU3maNQsS4A3zuuoYRNIvYSxxhebPfXg2mzWQEPne/nlJ37yOse6uGgR386uTpdsx4D0QZWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.17.tgz", + "integrity": "sha512-j5zJcx6golJYTG6c05LUZ3Z8Gi+M62zRT/ycz4Xq4iCOdpcxwg7ngEYD4KA0eWZC7U17qh/Smq8bYbACJ0ipBA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.237", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz", + "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.25", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz", + "integrity": "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-typescript": { + "version": "6.7.6", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.7.6.tgz", + "integrity": "sha512-c/hfooPx+RBIOPM09GSxABOZhYPblDoyaGhqBkD/59vtpN21jEuWKDlM0KYTvqJVlSYjKs0tBcIdeXKChlSPtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "fast-glob": "^3.3.2", + "js-yaml": "^4.1.0", + "supports-color": "^9.4.0", + "undici": "^5.28.4", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + } + }, + "node_modules/openapi-typescript/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.4.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", + "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..232d408 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "@scope3/agentic-client", + "version": "0.1.0", + "description": "TypeScript client for the Scope3 Agentic API with AdCP webhook support", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "dev": "tsc --watch", + "test": "jest", + "lint": "eslint src --ext .ts", + "format": "prettier --write \"src/**/*.ts\"", + "generate-types": "openapi-typescript openapi.yaml -o src/types/api.ts" + }, + "keywords": [ + "scope3", + "advertising", + "agentic", + "adcp", + "typescript" + ], + "author": "", + "license": "MIT", + "dependencies": { + "axios": "^1.6.0", + "express": "^4.18.0" + }, + "devDependencies": { + "@types/express": "^4.17.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.0.0", + "jest": "^29.5.0", + "openapi-typescript": "^6.7.0", + "prettier": "^3.0.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/src/__tests__/client.test.ts b/src/__tests__/client.test.ts new file mode 100644 index 0000000..edb3a78 --- /dev/null +++ b/src/__tests__/client.test.ts @@ -0,0 +1,46 @@ +import { Scope3SDK } from '../sdk'; + +describe('Scope3SDK', () => { + let client: Scope3SDK; + + beforeEach(() => { + client = new Scope3SDK({ + apiKey: 'test-api-key', + }); + }); + + it('should initialize with default production URL', () => { + expect(client).toBeDefined(); + }); + + it('should have all resource modules', () => { + expect(client.assets).toBeDefined(); + expect(client.brandAgents).toBeDefined(); + expect(client.brandStandards).toBeDefined(); + expect(client.brandStories).toBeDefined(); + expect(client.campaigns).toBeDefined(); + expect(client.channels).toBeDefined(); + expect(client.creatives).toBeDefined(); + expect(client.salesAgents).toBeDefined(); + expect(client.tactics).toBeDefined(); + expect(client.mediaBuys).toBeDefined(); + expect(client.notifications).toBeDefined(); + expect(client.products).toBeDefined(); + }); + + it('should accept custom base URL', () => { + const customClient = new Scope3SDK({ + apiKey: 'test-api-key', + baseUrl: 'https://custom.api.com', + }); + expect(customClient).toBeDefined(); + }); + + it('should accept custom timeout', () => { + const customClient = new Scope3SDK({ + apiKey: 'test-api-key', + timeout: 60000, + }); + expect(customClient).toBeDefined(); + }); +}); diff --git a/src/__tests__/webhook-server.test.ts b/src/__tests__/webhook-server.test.ts new file mode 100644 index 0000000..7266f09 --- /dev/null +++ b/src/__tests__/webhook-server.test.ts @@ -0,0 +1,45 @@ +import { WebhookServer, WebhookEvent } from '../webhook-server'; + +describe('WebhookServer', () => { + let server: WebhookServer; + + afterEach(async () => { + if (server) { + await server.stop(); + } + }); + + it('should initialize with default config', () => { + server = new WebhookServer(); + expect(server).toBeDefined(); + }); + + it('should initialize with custom config', () => { + server = new WebhookServer({ + port: 4000, + path: '/custom-webhooks', + secret: 'test-secret', + }); + expect(server).toBeDefined(); + }); + + it('should register event handlers', () => { + server = new WebhookServer(); + const handler = jest.fn(); + server.on('test-event', handler); + expect(handler).not.toHaveBeenCalled(); + }); + + it('should unregister event handlers', () => { + server = new WebhookServer(); + const handler = jest.fn(); + server.on('test-event', handler); + server.off('test-event', handler); + expect(handler).not.toHaveBeenCalled(); + }); + + it('should return webhook URL', () => { + server = new WebhookServer({ port: 3000, path: '/webhooks' }); + expect(server.getUrl()).toBe('http://localhost:3000/webhooks'); + }); +}); diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..93aa6dd --- /dev/null +++ b/src/client.ts @@ -0,0 +1,60 @@ +import axios, { AxiosInstance, AxiosError } from 'axios'; +import { ClientConfig, Environment, ErrorResponse } from './types'; + +export class Scope3Client { + private readonly client: AxiosInstance; + private readonly apiKey: string; + + constructor(config: ClientConfig) { + this.apiKey = config.apiKey; + + const baseURL = config.baseUrl || this.getDefaultBaseUrl('production'); + + this.client = axios.create({ + baseURL, + timeout: config.timeout || 30000, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.apiKey}`, + }, + }); + + this.setupInterceptors(); + } + + private getDefaultBaseUrl(env: Environment): string { + return env === 'production' + ? 'https://api.agentic.scope3.com' + : 'https://api.agentic.staging.scope3.com'; + } + + private setupInterceptors(): void { + this.client.interceptors.response.use( + (response) => response, + (error: AxiosError) => { + if (error.response) { + const errorData = error.response.data; + throw new Error( + errorData?.error || `API Error: ${error.response.status} ${error.response.statusText}` + ); + } else if (error.request) { + throw new Error('No response received from API'); + } else { + throw new Error(`Request setup error: ${error.message}`); + } + } + ); + } + + protected async post( + endpoint: string, + data: TRequest + ): Promise { + const response = await this.client.post(endpoint, data); + return response.data; + } + + protected getClient(): AxiosInstance { + return this.client; + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..9656db4 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,17 @@ +export { Scope3SDK } from './sdk'; +export { WebhookServer } from './webhook-server'; +export type { ClientConfig, ToolResponse, Environment } from './types'; +export type { WebhookEvent, WebhookHandler, WebhookServerConfig } from './webhook-server'; + +export * from './resources/assets'; +export * from './resources/brand-agents'; +export * from './resources/brand-standards'; +export * from './resources/brand-stories'; +export * from './resources/campaigns'; +export * from './resources/channels'; +export * from './resources/creatives'; +export * from './resources/sales-agents'; +export * from './resources/tactics'; +export * from './resources/media-buys'; +export * from './resources/notifications'; +export * from './resources/products'; diff --git a/src/resources/assets.ts b/src/resources/assets.ts new file mode 100644 index 0000000..4731109 --- /dev/null +++ b/src/resources/assets.ts @@ -0,0 +1,29 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface AssetUploadRequest { + brandAgentId: string; + assets: Array<{ + name: string; + contentType: string; + data: string; + assetType: 'image' | 'video' | 'audio' | 'logo' | 'font'; + tags?: string[]; + }>; +} + +export interface AssetListRequest { + brandAgentId?: string; +} + +export class AssetsResource { + constructor(private client: Scope3Client) {} + + async upload(request: AssetUploadRequest): Promise { + return this.client['post']('/asset-upload', request); + } + + async list(request: AssetListRequest = {}): Promise { + return this.client['post']('/asset-list', request); + } +} diff --git a/src/resources/brand-agents.ts b/src/resources/brand-agents.ts new file mode 100644 index 0000000..2a2d2aa --- /dev/null +++ b/src/resources/brand-agents.ts @@ -0,0 +1,49 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface BrandAgentCreateRequest { + name: string; + description?: string; + nickname?: string; + externalId?: string; + advertiserDomains?: string[]; +} + +export interface BrandAgentUpdateRequest { + brandAgentId: string; + name?: string; + description?: string; + tacticSeedDataCoop?: boolean; +} + +export interface BrandAgentGetRequest { + brandAgentId: string; +} + +export interface BrandAgentDeleteRequest { + brandAgentId: string; +} + +export class BrandAgentsResource { + constructor(private client: Scope3Client) {} + + async list(): Promise { + return this.client['post']('/brand-agent-list', {}); + } + + async create(request: BrandAgentCreateRequest): Promise { + return this.client['post']('/brand-agent-create', request); + } + + async get(request: BrandAgentGetRequest): Promise { + return this.client['post']('/brand-agent-get', request); + } + + async update(request: BrandAgentUpdateRequest): Promise { + return this.client['post']('/brand-agent-update', request); + } + + async delete(request: BrandAgentDeleteRequest): Promise { + return this.client['post']('/brand-agent-delete', request); + } +} diff --git a/src/resources/brand-standards.ts b/src/resources/brand-standards.ts new file mode 100644 index 0000000..6492b21 --- /dev/null +++ b/src/resources/brand-standards.ts @@ -0,0 +1,45 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface BrandStandardsListRequest { + where?: { + name?: string; + }; + orderBy?: { + id?: 'asc' | 'desc'; + name?: 'asc' | 'desc'; + }; + take?: number; + skip?: number; +} + +export interface BrandStandardsCreateRequest { + brandAgentId: string; + prompt: string; + name?: string; + description?: string; + isArchived?: boolean; + countries?: string[]; + channels?: string[]; + brands?: string[]; +} + +export interface BrandStandardsDeleteRequest { + brandStandardId: string; +} + +export class BrandStandardsResource { + constructor(private client: Scope3Client) {} + + async list(request: BrandStandardsListRequest = {}): Promise { + return this.client['post']('/brand-standards-list', request); + } + + async create(request: BrandStandardsCreateRequest): Promise { + return this.client['post']('/brand-standards-create', request); + } + + async delete(request: BrandStandardsDeleteRequest): Promise { + return this.client['post']('/brand-standards-delete', request); + } +} diff --git a/src/resources/brand-stories.ts b/src/resources/brand-stories.ts new file mode 100644 index 0000000..428e66c --- /dev/null +++ b/src/resources/brand-stories.ts @@ -0,0 +1,45 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface BrandStoryListRequest { + brandAgentId: string; +} + +export interface BrandStoryCreateRequest { + brandAgentId: string; + name: string; + prompt: string; + countries?: string[]; + channels?: string[]; + languages?: string[]; + brands?: string[]; +} + +export interface BrandStoryUpdateRequest { + brandStoryId: string; + prompt: string; +} + +export interface BrandStoryDeleteRequest { + brandStoryId: string; +} + +export class BrandStoriesResource { + constructor(private client: Scope3Client) {} + + async list(request: BrandStoryListRequest): Promise { + return this.client['post']('/brand-story-list', request); + } + + async create(request: BrandStoryCreateRequest): Promise { + return this.client['post']('/brand-story-create', request); + } + + async update(request: BrandStoryUpdateRequest): Promise { + return this.client['post']('/brand-story-update', request); + } + + async delete(request: BrandStoryDeleteRequest): Promise { + return this.client['post']('/brand-story-delete', request); + } +} diff --git a/src/resources/campaigns.ts b/src/resources/campaigns.ts new file mode 100644 index 0000000..7fd6bb4 --- /dev/null +++ b/src/resources/campaigns.ts @@ -0,0 +1,104 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface Budget { + amount: number; + currency?: string; + dailyCap?: number; + pacing?: 'asap' | 'even' | 'front_loaded'; +} + +export interface ScoringWeights { + affinity?: number; + outcome?: number; + quality?: number; +} + +export interface CampaignListRequest { + brandAgentId?: string; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; + limit?: number; + offset?: number; +} + +export interface CampaignCreateRequest { + prompt: string; + brandAgentId?: string; + name?: string; + budget?: Budget; + startDate?: string; + endDate?: string; + scoringWeights?: ScoringWeights; + outcomeScoreWindowDays?: number; + segmentIds?: string[]; + dealIds?: string[]; + visibility?: 'PUBLIC' | 'PRIVATE'; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; +} + +export interface CampaignUpdateRequest { + campaignId: string; + name?: string; + prompt?: string; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; + budget?: Budget; + startDate?: string; + endDate?: string; + scoringWeights?: ScoringWeights; + outcomeScoreWindowDays?: number; + segmentIds?: string[]; + dealIds?: string[]; + visibility?: 'PUBLIC' | 'PRIVATE'; +} + +export interface CampaignDeleteRequest { + campaignId: string; + hardDelete?: boolean; +} + +export interface CampaignGetSummaryRequest { + campaignId: string; +} + +export interface CampaignListTacticsRequest { + campaignId: string; + includeArchived?: boolean; +} + +export interface CampaignValidateBriefRequest { + brief: string; + brandAgentId?: string; + threshold?: number; +} + +export class CampaignsResource { + constructor(private client: Scope3Client) {} + + async list(request: CampaignListRequest = {}): Promise { + return this.client['post']('/campaign-list', request); + } + + async create(request: CampaignCreateRequest): Promise { + return this.client['post']('/campaign-create', request); + } + + async update(request: CampaignUpdateRequest): Promise { + return this.client['post']('/campaign-update', request); + } + + async delete(request: CampaignDeleteRequest): Promise { + return this.client['post']('/campaign-delete', request); + } + + async getSummary(request: CampaignGetSummaryRequest): Promise { + return this.client['post']('/campaign-get-summary', request); + } + + async listTactics(request: CampaignListTacticsRequest): Promise { + return this.client['post']('/campaign-list-tactics', request); + } + + async validateBrief(request: CampaignValidateBriefRequest): Promise { + return this.client['post']('/campaign-validate-brief', request); + } +} diff --git a/src/resources/channels.ts b/src/resources/channels.ts new file mode 100644 index 0000000..d4f702f --- /dev/null +++ b/src/resources/channels.ts @@ -0,0 +1,10 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export class ChannelsResource { + constructor(private client: Scope3Client) {} + + async list(): Promise { + return this.client['post']('/channel-list', {}); + } +} diff --git a/src/resources/creatives.ts b/src/resources/creatives.ts new file mode 100644 index 0000000..0223fc5 --- /dev/null +++ b/src/resources/creatives.ts @@ -0,0 +1,79 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface CreativeListRequest { + brandAgentId?: string; + campaignId?: string; +} + +export interface CreativeCreateRequest { + brandAgentId: number; + name: string; + organizationId?: number; + description?: string; + formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; + formatId?: string; + mediaUrl?: string; + content?: { + assetIds?: string[]; + htmlSnippet?: string; + vastTag?: string; + }; + assemblyMethod?: 'CREATIVE_AGENT' | 'ACTIVATION' | 'PUBLISHER'; + campaignId?: number; +} + +export interface CreativeGetRequest { + creativeId: number; +} + +export interface CreativeUpdateRequest { + creativeId: number; + name?: string; + status?: string; +} + +export interface CreativeDeleteRequest { + creativeId: number; +} + +export interface CreativeAssignRequest { + creativeId: number; + campaignId: number; +} + +export interface CreativeSyncSalesAgentsRequest { + creativeId: number; +} + +export class CreativesResource { + constructor(private client: Scope3Client) {} + + async list(request: CreativeListRequest = {}): Promise { + return this.client['post']('/creative-list', request); + } + + async create(request: CreativeCreateRequest): Promise { + return this.client['post']('/creative-create', request); + } + + async get(request: CreativeGetRequest): Promise { + return this.client['post']('/creative-get', request); + } + + async update(request: CreativeUpdateRequest): Promise { + return this.client['post']('/creative-update', request); + } + + async delete(request: CreativeDeleteRequest): Promise { + return this.client['post']('/creative-delete', request); + } + + async assign(request: CreativeAssignRequest): Promise { + return this.client['post']('/creative-assign', request); + } + + async syncSalesAgents(request: CreativeSyncSalesAgentsRequest): Promise { + return this.client['post']('/creative-sync-sales-agents', request); + } +} diff --git a/src/resources/media-buys.ts b/src/resources/media-buys.ts new file mode 100644 index 0000000..9d6c4ff --- /dev/null +++ b/src/resources/media-buys.ts @@ -0,0 +1,80 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; +import { Budget } from './campaigns'; + +export interface MediaBuyProduct { + mediaProductId: string; + salesAgentId: string; + budgetAmount?: number; + budgetCurrency?: string; + pricingCpm?: number; + pricingSignalCost?: number; + displayOrder?: number; +} + +export interface MediaBuyListRequest { + tacticId?: string; + campaignId?: string; + includeArchived?: boolean; +} + +export interface MediaBuyCreateRequest { + tacticId: string; + name: string; + description?: string; + products: MediaBuyProduct[]; + budget: Budget; + creativeIds?: string[]; +} + +export interface MediaBuyGetRequest { + mediaBuyId: string; +} + +export interface MediaBuyUpdateRequest { + mediaBuyId: string; + name?: string; + budget?: { + amount?: number; + dailyCap?: number; + pacing?: 'asap' | 'even' | 'front_loaded'; + }; + cpm?: number; + creativeIds?: string[]; +} + +export interface MediaBuyDeleteRequest { + mediaBuyId: string; +} + +export interface MediaBuyExecuteRequest { + mediaBuyId: string; +} + +export class MediaBuysResource { + constructor(private client: Scope3Client) {} + + async list(request: MediaBuyListRequest = {}): Promise { + return this.client['post']('/media-buy-list', request); + } + + async create(request: MediaBuyCreateRequest): Promise { + return this.client['post']('/media-buy-create', request); + } + + async get(request: MediaBuyGetRequest): Promise { + return this.client['post']('/media-buy-get', request); + } + + async update(request: MediaBuyUpdateRequest): Promise { + return this.client['post']('/media-buy-update', request); + } + + async delete(request: MediaBuyDeleteRequest): Promise { + return this.client['post']('/media-buy-delete', request); + } + + async execute(request: MediaBuyExecuteRequest): Promise { + return this.client['post']('/media-buy-execute', request); + } +} diff --git a/src/resources/notifications.ts b/src/resources/notifications.ts new file mode 100644 index 0000000..69cf7db --- /dev/null +++ b/src/resources/notifications.ts @@ -0,0 +1,35 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface NotificationsListRequest { + unreadOnly?: boolean; + limit?: number; +} + +export interface NotificationMarkReadRequest { + notificationId: string; +} + +export interface NotificationMarkAcknowledgedRequest { + notificationId: string; +} + +export class NotificationsResource { + constructor(private client: Scope3Client) {} + + async list(request: NotificationsListRequest = {}): Promise { + return this.client['post']('/notifications-list', request); + } + + async markRead(request: NotificationMarkReadRequest): Promise { + return this.client['post']('/notifications-mark-read', request); + } + + async markAcknowledged(request: NotificationMarkAcknowledgedRequest): Promise { + return this.client['post']('/notifications-mark-acknowledged', request); + } + + async markAllRead(): Promise { + return this.client['post']('/notifications-mark-all-read', {}); + } +} diff --git a/src/resources/products.ts b/src/resources/products.ts new file mode 100644 index 0000000..42ae6bc --- /dev/null +++ b/src/resources/products.ts @@ -0,0 +1,30 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface MediaProductListRequest { + salesAgentId?: string; +} + +export interface MediaProductDiscoverRequest { + salesAgentId?: string; +} + +export interface MediaProductSyncRequest { + salesAgentId: string; +} + +export class ProductsResource { + constructor(private client: Scope3Client) {} + + async list(request: MediaProductListRequest = {}): Promise { + return this.client['post']('/media-product-list', request); + } + + async discover(request: MediaProductDiscoverRequest = {}): Promise { + return this.client['post']('/media-product-discover', request); + } + + async sync(request: MediaProductSyncRequest): Promise { + return this.client['post']('/media-product-sync', request); + } +} diff --git a/src/resources/sales-agents.ts b/src/resources/sales-agents.ts new file mode 100644 index 0000000..c0139c2 --- /dev/null +++ b/src/resources/sales-agents.ts @@ -0,0 +1,92 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export interface SalesAgentRegisterRequest { + name: string; + endpointUrl: string; + protocol: 'REST' | 'MCP' | 'A2A' | 'CUSTOM'; + authenticationType: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; + description?: string; + organizationId?: string; + authConfig?: Record; +} + +export interface SalesAgentGetRequest { + salesAgentId: string; +} + +export interface SalesAgentUpdateRequest { + salesAgentId: string; + name?: string; + description?: string; + endpointUrl?: string; + protocol?: 'REST' | 'MCP' | 'A2A' | 'CUSTOM'; + authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; + authConfig?: Record; +} + +export interface SalesAgentUnregisterRequest { + salesAgentId: string; + confirm: boolean; +} + +export interface SalesAgentAccountListRequest { + salesAgentId: string; +} + +export interface SalesAgentAccountRegisterRequest { + salesAgentId: string; + accountIdentifier: string; + authConfig?: Record; +} + +export interface SalesAgentAccountUpdateRequest { + salesAgentId: string; + accountIdentifier: string; + authConfig: Record; +} + +export interface SalesAgentAccountUnregisterRequest { + salesAgentId: string; + confirm: boolean; +} + +export class SalesAgentsResource { + constructor(private client: Scope3Client) {} + + async list(): Promise { + return this.client['post']('/sales-agent-list', {}); + } + + async get(request: SalesAgentGetRequest): Promise { + return this.client['post']('/sales-agent-get', request); + } + + async register(request: SalesAgentRegisterRequest): Promise { + return this.client['post']('/sales-agent-register', request); + } + + async update(request: SalesAgentUpdateRequest): Promise { + return this.client['post']('/sales-agent-update', request); + } + + async unregister(request: SalesAgentUnregisterRequest): Promise { + return this.client['post']('/sales-agent-unregister', request); + } + + async listAccounts(request: SalesAgentAccountListRequest): Promise { + return this.client['post']('/sales-agent-account-list', request); + } + + async registerAccount(request: SalesAgentAccountRegisterRequest): Promise { + return this.client['post']('/sales-agent-account-register', request); + } + + async updateAccount(request: SalesAgentAccountUpdateRequest): Promise { + return this.client['post']('/sales-agent-account-update', request); + } + + async unregisterAccount(request: SalesAgentAccountUnregisterRequest): Promise { + return this.client['post']('/sales-agent-account-unregister', request); + } +} diff --git a/src/resources/tactics.ts b/src/resources/tactics.ts new file mode 100644 index 0000000..e5ae49b --- /dev/null +++ b/src/resources/tactics.ts @@ -0,0 +1,82 @@ +import { Scope3Client } from '../client'; +import { ToolResponse } from '../types'; + +export type ChannelCode = + | 'DIGITAL-AUDIO' + | 'DISPLAY-WEB' + | 'DISPLAY-APP' + | 'CTV-BVOD' + | 'OLV' + | 'DOOH' + | 'SOCIAL'; + +export interface TacticListRequest { + campaignId?: string; + includeArchived?: boolean; +} + +export interface TacticCreateRequest { + name: string; + campaignId: string; + prompt?: string; + channelCodes?: ChannelCode[]; + countryCodes?: string[]; +} + +export interface TacticGetRequest { + tacticId: string; +} + +export interface TacticUpdateRequest { + tacticId: string; + name?: string; + prompt?: string; + channelCodes?: ChannelCode[]; + countryCodes?: string[]; +} + +export interface TacticDeleteRequest { + tacticId: string; +} + +export interface TacticLinkCampaignRequest { + tacticId: string; + campaignId: string; +} + +export interface TacticUnlinkCampaignRequest { + tacticId: string; + campaignId: string; +} + +export class TacticsResource { + constructor(private client: Scope3Client) {} + + async list(request: TacticListRequest = {}): Promise { + return this.client['post']('/tactic-list', request); + } + + async create(request: TacticCreateRequest): Promise { + return this.client['post']('/tactic-create', request); + } + + async get(request: TacticGetRequest): Promise { + return this.client['post']('/tactic-get', request); + } + + async update(request: TacticUpdateRequest): Promise { + return this.client['post']('/tactic-update', request); + } + + async delete(request: TacticDeleteRequest): Promise { + return this.client['post']('/tactic-delete', request); + } + + async linkCampaign(request: TacticLinkCampaignRequest): Promise { + return this.client['post']('/tactic-link-campaign', request); + } + + async unlinkCampaign(request: TacticUnlinkCampaignRequest): Promise { + return this.client['post']('/tactic-unlink-campaign', request); + } +} diff --git a/src/sdk.ts b/src/sdk.ts new file mode 100644 index 0000000..0b5b425 --- /dev/null +++ b/src/sdk.ts @@ -0,0 +1,46 @@ +import { Scope3Client } from './client'; +import { ClientConfig } from './types'; +import { AssetsResource } from './resources/assets'; +import { BrandAgentsResource } from './resources/brand-agents'; +import { BrandStandardsResource } from './resources/brand-standards'; +import { BrandStoriesResource } from './resources/brand-stories'; +import { CampaignsResource } from './resources/campaigns'; +import { ChannelsResource } from './resources/channels'; +import { CreativesResource } from './resources/creatives'; +import { SalesAgentsResource } from './resources/sales-agents'; +import { TacticsResource } from './resources/tactics'; +import { MediaBuysResource } from './resources/media-buys'; +import { NotificationsResource } from './resources/notifications'; +import { ProductsResource } from './resources/products'; + +export class Scope3SDK extends Scope3Client { + public readonly assets: AssetsResource; + public readonly brandAgents: BrandAgentsResource; + public readonly brandStandards: BrandStandardsResource; + public readonly brandStories: BrandStoriesResource; + public readonly campaigns: CampaignsResource; + public readonly channels: ChannelsResource; + public readonly creatives: CreativesResource; + public readonly salesAgents: SalesAgentsResource; + public readonly tactics: TacticsResource; + public readonly mediaBuys: MediaBuysResource; + public readonly notifications: NotificationsResource; + public readonly products: ProductsResource; + + constructor(config: ClientConfig) { + super(config); + + this.assets = new AssetsResource(this); + this.brandAgents = new BrandAgentsResource(this); + this.brandStandards = new BrandStandardsResource(this); + this.brandStories = new BrandStoriesResource(this); + this.campaigns = new CampaignsResource(this); + this.channels = new ChannelsResource(this); + this.creatives = new CreativesResource(this); + this.salesAgents = new SalesAgentsResource(this); + this.tactics = new TacticsResource(this); + this.mediaBuys = new MediaBuysResource(this); + this.notifications = new NotificationsResource(this); + this.products = new ProductsResource(this); + } +} diff --git a/src/types/api.ts b/src/types/api.ts new file mode 100644 index 0000000..1e147c4 --- /dev/null +++ b/src/types/api.ts @@ -0,0 +1,2152 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + + +export interface paths { + "/asset-upload": { + /** + * Upload creative assets + * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. Accepts base64-encoded file data and returns signed URLs (valid for 1 hour). + */ + post: operations["asset_upload"]; + }; + "/asset-list": { + /** + * List creative assets + * @description List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. + */ + post: operations["asset_list"]; + }; + "/brand-agent-list": { + /** + * List brand agents + * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. + */ + post: operations["brand_agent_list"]; + }; + "/brand-agent-create": { + /** + * Create brand agent + * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + */ + post: operations["brand_agent_create"]; + }; + "/brand-agent-get": { + /** + * Get brand agent + * @description Get detailed information about a specific brand agent (advertiser account) by ID. + */ + post: operations["brand_agent_get"]; + }; + "/brand-agent-update": { + /** + * Update brand agent + * @description Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. + */ + post: operations["brand_agent_update"]; + }; + "/brand-agent-delete": { + /** + * Delete brand agent + * @description โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. + */ + post: operations["brand_agent_delete"]; + }; + "/brand-standards-list": { + /** + * List brand standards + * @description List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. + */ + post: operations["brand_standards_list"]; + }; + "/brand-standards-create": { + /** + * Create brand standard + * @description Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. + */ + post: operations["brand_standards_create"]; + }; + "/brand-standards-delete": { + /** + * Delete brand standard + * @description โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. + */ + post: operations["brand_standards_delete"]; + }; + "/brand-story-list": { + /** + * List brand stories + * @description List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. + */ + post: operations["brand_story_list"]; + }; + "/brand-story-create": { + /** + * Create brand story + * @description Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. + */ + post: operations["brand_story_create"]; + }; + "/brand-story-update": { + /** + * Update brand story + * @description Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. + */ + post: operations["brand_story_update"]; + }; + "/brand-story-delete": { + /** + * Delete brand story + * @description โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. + */ + post: operations["brand_story_delete"]; + }; + "/campaign-list": { + /** + * List campaigns + * @description List campaigns for the authenticated customer, with optional filtering. + */ + post: operations["campaign_list"]; + }; + "/campaign-create": { + /** + * Create campaign + * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. + */ + post: operations["campaign_create"]; + }; + "/campaign-update": { + /** + * Update campaign + * @description Update an existing campaign's settings. + */ + post: operations["campaign_update"]; + }; + "/campaign-delete": { + /** + * Delete campaign + * @description โš ๏ธ DANGER - Permanently delete a campaign and all associated data. + */ + post: operations["campaign_delete"]; + }; + "/campaign-get-summary": { + /** + * Get campaign summary + * @description Get detailed summary information about a specific campaign. + */ + post: operations["campaign_get_summary"]; + }; + "/campaign-list-tactics": { + /** + * List campaign tactics + * @description List all tactics associated with a specific campaign. + */ + post: operations["campaign_list_strategies"]; + }; + "/campaign-validate-brief": { + /** + * Validate campaign brief + * @description Validate a campaign brief to ensure it contains all necessary information. + */ + post: operations["campaign_validate_brief"]; + }; + "/channel-list": { + /** + * List channels + * @description List all available advertising channels. + */ + post: operations["channel_list"]; + }; + "/creative-list": { + /** + * List creatives + * @description List creatives for the authenticated customer, with optional filtering. + */ + post: operations["creative_list"]; + }; + "/creative-create": { + /** + * Create creative + * @description Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + */ + post: operations["creative_create"]; + }; + "/creative-get": { + /** + * Get creative + * @description Get detailed information about a specific creative. + */ + post: operations["creative_get"]; + }; + "/creative-update": { + /** + * Update creative + * @description Update an existing creative's settings. + */ + post: operations["creative_update"]; + }; + "/creative-delete": { + /** + * Delete creative + * @description โš ๏ธ DANGER - Permanently delete a creative. + */ + post: operations["creative_delete"]; + }; + "/creative-assign": { + /** + * Assign creative to campaign + * @description Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents + * associated with the campaign via active media buys. Returns auto-sync results including which agents + * received the creative and their approval status. + */ + post: operations["creative_assign"]; + }; + "/creative-sync-sales-agents": { + /** + * Sync creative with sales agents + * @description Sync a creative's formats and specifications with connected sales agents/publishers. + */ + post: operations["creative_sync_sales_agents"]; + }; + "/sales-agent-list": { + /** + * List sales agents + * @description List all registered sales agents (publishers) for the authenticated customer. + */ + post: operations["sales_agent_list"]; + }; + "/sales-agent-get": { + /** + * Get sales agent + * @description Get detailed information about a specific sales agent. + */ + post: operations["sales_agent_get"]; + }; + "/sales-agent-register": { + /** + * Register sales agent + * @description Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. + */ + post: operations["sales_agent_register"]; + }; + "/sales-agent-account-list": { + /** + * List accounts for a sales agent + * @description List all accounts registered by your organization for a specific sales agent. + */ + post: operations["sales_agent_account_list"]; + }; + "/sales-agent-account-register": { + /** + * Register account for sales agent + * @description Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. + */ + post: operations["sales_agent_account_register"]; + }; + "/sales-agent-unregister": { + /** + * Unregister sales agent completely + * @description Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. + */ + post: operations["sales_agent_unregister"]; + }; + "/sales-agent-account-unregister": { + /** + * Unregister your account with a sales agent + * @description Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. + */ + post: operations["sales_agent_account_unregister"]; + }; + "/sales-agent-update": { + /** + * Update sales agent + * @description Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. + */ + post: operations["sales_agent_update"]; + }; + "/sales-agent-account-update": { + /** + * Update sales agent account authentication + * @description Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. + */ + post: operations["sales_agent_account_update"]; + }; + "/tactic-list": { + /** + * List tactics + * @description List all media buying tactics for the authenticated customer. + */ + post: operations["strategy_list"]; + }; + "/tactic-create": { + /** + * Create tactic + * @description Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. + */ + post: operations["strategy_create"]; + }; + "/tactic-get": { + /** + * Get tactic + * @description Get detailed information about a specific tactic. + */ + post: operations["strategy_get"]; + }; + "/tactic-update": { + /** + * Update tactic + * @description Update an existing tactic's configuration. + */ + post: operations["strategy_update"]; + }; + "/tactic-delete": { + /** + * Delete tactic + * @description โš ๏ธ DANGER - Permanently delete a tactic. + */ + post: operations["strategy_delete"]; + }; + "/tactic-link-campaign": { + /** + * Link campaign to tactic + * @description Link a campaign to a tactic for budget and execution management. + */ + post: operations["strategy_link_campaign"]; + }; + "/tactic-unlink-campaign": { + /** + * Unlink campaign from tactic + * @description Unlink a campaign from a tactic. + */ + post: operations["strategy_unlink_campaign"]; + }; + "/media-buy-list": { + /** + * List media buys + * @description List all media buys for the authenticated customer. + */ + post: operations["media_buy_list"]; + }; + "/media-buy-create": { + /** + * Create media buy + * @description Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. + * + * **Multi-Product Support**: Media buys now support multiple products from different sales agents in a single buy. Each product can have its own budget allocation and pricing. During execution, each unique sales agent will receive a separate ADCP submission. + * + * **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. + */ + post: operations["media_buy_create"]; + }; + "/media-buy-get": { + /** + * Get media buy + * @description Get detailed information about a specific media buy. + */ + post: operations["media_buy_get"]; + }; + "/media-buy-update": { + /** + * Update media buy + * @description Update an existing media buy's configuration. + */ + post: operations["media_buy_update"]; + }; + "/media-buy-delete": { + /** + * Delete media buy + * @description โš ๏ธ DANGER - Permanently delete a media buy. + */ + post: operations["media_buy_delete"]; + }; + "/media-buy-execute": { + /** + * Execute media buy + * @description Execute a media buy by deploying it to the publisher platform. + */ + post: operations["media_buy_execute"]; + }; + "/notifications-list": { + /** + * List notifications + * @description List notifications for the authenticated user. + */ + post: operations["notifications_list"]; + }; + "/notifications-mark-read": { + /** + * Mark notification as read + * @description Mark a specific notification as read. + */ + post: operations["notifications_mark_read"]; + }; + "/notifications-mark-acknowledged": { + /** + * Mark notification as acknowledged + * @description Mark a specific notification as acknowledged. + */ + post: operations["notifications_mark_acknowledged"]; + }; + "/notifications-mark-all-read": { + /** + * Mark all notifications as read + * @description Mark all notifications as read for the authenticated user. + */ + post: operations["notifications_mark_all_read"]; + }; + "/media-product-list": { + /** + * List media products + * @description List available media products from publishers. + */ + post: operations["media_product_list"]; + }; + "/media-product-discover": { + /** + * Discover media products + * @description Discover new media products from connected publishers. + */ + post: operations["media_product_discover"]; + }; + "/media-product-sync": { + /** + * Sync media products + * @description Synchronize media product inventory with publisher systems. + */ + post: operations["media_product_sync"]; + }; +} + +export type webhooks = Record; + +export interface components { + schemas: { + Budget: { + /** @description Total budget amount in cents (e.g., 5000000 = $50,000) */ + total: number; + /** + * @description Budget currency + * @enum {string} + */ + currency: "USD" | "EUR" | "GBP" | "CAD" | "AUD"; + /** @description Daily spending limit in cents */ + dailyCap?: number; + /** + * @description Budget pacing tactic + * @enum {string} + */ + pacing?: "even" | "accelerated" | "front_loaded"; + }; + ScoringWeights: { + /** @description Weight for affinity scoring (0-1) */ + affinity?: number; + /** @description Weight for outcome scoring (0-1) */ + outcome?: number; + /** @description Weight for quality scoring (0-1) */ + quality?: number; + }; + BrandAgent: { + /** @description Unique brand agent identifier */ + id: string; + /** @description Brand agent name */ + name: string; + /** @description Brand agent description */ + description?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + Campaign: { + /** @description Unique campaign identifier */ + id: string; + /** @description Campaign name */ + name: string; + /** @description Natural language campaign description */ + prompt: string; + /** @description Parent brand agent ID */ + brandAgentId: string; + /** + * @description Campaign status + * @enum {string} + */ + status: "active" | "paused" | "completed" | "draft"; + budget?: components["schemas"]["Budget"]; + /** @description Associated synthetic audience IDs */ + audienceIds?: string[]; + /** @description Associated creative asset IDs */ + creativeIds?: string[]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + Creative: { + /** @description Unique creative identifier */ + id: string; + /** @description Creative name */ + name: string; + /** + * @description Creative asset type + * @enum {string} + */ + type: "video" | "image" | "native" | "html5"; + /** + * Format: uri + * @description Creative asset URL + */ + url: string; + /** @description Parent brand agent ID */ + brandAgentId: string; + /** @description Creative headline text */ + headline?: string; + /** @description Creative body text */ + body?: string; + /** @description Call-to-action text */ + cta?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + Tactic: { + /** @description Unique tactic identifier */ + id: string; + /** @description Tactic name */ + name: string; + /** @description Associated campaign ID */ + campaignId: string; + /** @description Tactical brief or prompt */ + prompt?: string; + /** + * @description Activity type (always AMP) + * @enum {string} + */ + activityType: "AMP"; + /** + * @description Tactic type + * @enum {string} + */ + tacticType: "INTELLIGENT_CAMPAIGNS"; + /** @description Target channels (official codes) */ + channelCodes?: ("DIGITAL-AUDIO" | "DISPLAY-WEB" | "DISPLAY-APP" | "CTV-BVOD" | "OLV" | "DOOH" | "SOCIAL")[]; + /** @description Target countries */ + countryCodes?: string[]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + MediaBuy: { + /** @description Unique media buy identifier */ + id: string; + /** @description Media buy name */ + name: string; + /** @description Media buy description */ + description?: string; + /** @description Associated tactic ID */ + tacticId: string; + /** @description Publisher/sales agent ID */ + salesAgentId: string; + /** @description Media product ID */ + mediaProductId: string; + budget: { + amount?: number; + currency?: string; + dailyCap?: number; + pacing?: string; + }; + /** @description CPM pricing */ + cpm: number; + /** @description Additional signal cost */ + signalCost?: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + }; + responses: { + /** @description Successful tool execution */ + ToolResponse: { + content: { + "application/json": { + /** @description Whether the operation succeeded */ + success?: boolean; + /** @description Human-readable response message */ + message?: string; + /** @description Response data (varies by tool) */ + data?: Record; + }; + }; + }; + /** @description Bad request - invalid parameters */ + BadRequest: { + content: { + "application/json": { + /** @description Error message */ + error?: string; + /** @description Additional error details */ + details?: Record; + }; + }; + }; + /** @description Unauthorized - invalid or missing authentication */ + Unauthorized: { + content: { + "application/json": { + /** @description Error message */ + error?: string; + }; + }; + }; + /** @description Resource not found */ + NotFound: { + content: { + "application/json": { + /** @description Error message */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + InternalError: { + content: { + "application/json": { + /** @description Error message */ + error?: string; + }; + }; + }; + }; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} + +export type $defs = Record; + +export type external = Record; + +export interface operations { + + /** + * Upload creative assets + * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. Accepts base64-encoded file data and returns signed URLs (valid for 1 hour). + */ + asset_upload: { + requestBody: { + content: { + "application/json": { + /** @description Brand agent ID for file organization */ + brandAgentId: string; + /** @description Array of assets to upload */ + assets: ({ + /** @description Original filename */ + name: string; + /** @description MIME type (e.g., image/png, video/mp4) */ + contentType: string; + /** + * Format: byte + * @description Base64-encoded file data + */ + data: string; + /** + * @description Type of asset + * @enum {string} + */ + assetType: "image" | "video" | "audio" | "logo" | "font"; + /** @description Optional tags for organization */ + tags?: string[]; + })[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List creative assets + * @description List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. + */ + asset_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional brand agent ID to filter assets */ + brandAgentId?: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List brand agents + * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. + */ + brand_agent_list: { + requestBody: { + content: { + "application/json": Record; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create brand agent + * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + */ + brand_agent_create: { + requestBody: { + content: { + "application/json": { + /** @description Name of the brand agent (advertiser account) */ + name: string; + /** @description Optional description of the brand agent */ + description?: string; + /** @description Friendly name for easy identification (e.g., 'Nike' for 'Nike c/o Kinesso') */ + nickname?: string; + /** @description Your internal ID for this brand agent (e.g., client code or account ID) */ + externalId?: string; + /** @description Domains where users will be sent from all campaigns/creatives */ + advertiserDomains?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Get brand agent + * @description Get detailed information about a specific brand agent (advertiser account) by ID. + */ + brand_agent_get: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand agent to retrieve */ + brandAgentId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update brand agent + * @description Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. + */ + brand_agent_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand agent to update */ + brandAgentId: string; + /** @description New name for the brand agent */ + name?: string; + /** @description New description for the brand agent */ + description?: string; + /** @description Enable/disable tactic seed data cooperative participation */ + tacticSeedDataCoop?: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete brand agent + * @description โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. + */ + brand_agent_delete: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand agent to delete permanently */ + brandAgentId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List brand standards + * @description List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. + */ + brand_standards_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional filtering criteria */ + where?: { + /** @description Filter by name */ + name?: string; + }; + /** @description Optional ordering for results */ + orderBy?: { + /** @enum {string} */ + id?: "asc" | "desc"; + /** @enum {string} */ + name?: "asc" | "desc"; + }; + /** @description Number of records to return (pagination) */ + take?: number; + /** @description Number of records to skip (pagination) */ + skip?: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create brand standard + * @description Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. + */ + brand_standards_create: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand to create standards for */ + brandAgentId: string; + /** @description Name for the brand standard (optional - defaults to "{Brand Name} Standards") */ + name?: string; + /** @description Natural language prompt defining the brand safety standards, content restrictions, and enforcement rules */ + prompt: string; + /** @description Description for the brand standard */ + description?: string; + /** @description Whether to create the standard as archived */ + isArchived?: boolean; + /** @description List of country codes to target (e.g., ['US', 'CA']) */ + countries?: string[]; + /** @description List of channels to target (e.g., ['web', 'social']) */ + channels?: string[]; + /** @description List of specific brands this applies to */ + brands?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete brand standard + * @description โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. + */ + brand_standards_delete: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand standard to delete */ + brandStandardId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List brand stories + * @description List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. + */ + brand_story_list: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand to list brand stories for */ + brandAgentId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create brand story + * @description Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. + */ + brand_story_create: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand to create a brand story for */ + brandAgentId: string; + /** @description Name for the brand story (e.g., 'Tech Enthusiasts', 'Luxury Shoppers') */ + name: string; + /** @description Natural language prompt defining the target audience profile, demographics, and behavioral characteristics */ + prompt: string; + /** @description List of country codes to target (e.g., ['US', 'CA']) */ + countries?: string[]; + /** @description List of channels to target (e.g., ['web', 'social']) */ + channels?: string[]; + /** @description List of language codes to target (e.g., ['en', 'es']) */ + languages?: string[]; + /** @description List of specific brands this applies to */ + brands?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update brand story + * @description Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. + */ + brand_story_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand story to update */ + brandStoryId: string; + /** @description New audience definition prompt */ + prompt: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete brand story + * @description โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. + */ + brand_story_delete: { + requestBody: { + content: { + "application/json": { + /** @description ID of the brand story to delete */ + brandStoryId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List campaigns + * @description List campaigns for the authenticated customer, with optional filtering. + */ + campaign_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional brand agent ID to filter campaigns */ + brandAgentId?: string; + /** + * @description Optional status filter + * @enum {string} + */ + status?: "ACTIVE" | "PAUSED" | "ARCHIVED"; + /** @description Maximum number of campaigns to return (default 100) */ + limit?: number; + /** @description Number of campaigns to skip for pagination */ + offset?: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create campaign + * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. + */ + campaign_create: { + requestBody: { + content: { + "application/json": { + /** @description Optional brand agent ID that will own this campaign */ + brandAgentId?: string; + /** @description Optional name for the campaign (auto-generated if not provided) */ + name?: string; + /** @description Natural language description of campaign requirements (e.g., 'Create a video campaign targeting tech enthusiasts with $50k budget') */ + prompt: string; + budget?: components["schemas"]["Budget"]; + /** + * Format: date-time + * @description Campaign start date (ISO 8601 format) + */ + startDate?: string; + /** + * Format: date-time + * @description Campaign end date (ISO 8601 format) + */ + endDate?: string; + scoringWeights?: components["schemas"]["ScoringWeights"]; + /** @description Days for outcome measurement window */ + outcomeScoreWindowDays?: number; + /** @description Array of segment IDs to associate with campaign */ + segmentIds?: string[]; + /** @description Array of deal IDs to associate with campaign */ + dealIds?: string[]; + /** + * @description Campaign visibility setting + * @enum {string} + */ + visibility?: "PUBLIC" | "PRIVATE"; + /** + * @description Initial campaign status + * @enum {string} + */ + status?: "ACTIVE" | "PAUSED" | "ARCHIVED"; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update campaign + * @description Update an existing campaign's settings. + */ + campaign_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the campaign to update */ + campaignId: string; + /** @description New name for the campaign */ + name?: string; + /** @description Updated natural language campaign requirements */ + prompt?: string; + /** + * @description New status for the campaign + * @enum {string} + */ + status?: "ACTIVE" | "PAUSED" | "ARCHIVED"; + budget?: components["schemas"]["Budget"]; + /** + * Format: date-time + * @description Campaign start date (ISO 8601 format) + */ + startDate?: string; + /** + * Format: date-time + * @description Campaign end date (ISO 8601 format) + */ + endDate?: string; + /** @description Scoring weights configuration */ + scoringWeights?: { + /** @description Weight for affinity scoring (0-1) */ + affinity?: number; + /** @description Weight for outcome scoring (0-1) */ + outcome?: number; + /** @description Weight for quality scoring (0-1) */ + quality?: number; + }; + /** @description Days for outcome measurement window */ + outcomeScoreWindowDays?: number; + /** @description Array of segment IDs to associate with campaign */ + segmentIds?: string[]; + /** @description Array of deal IDs to associate with campaign */ + dealIds?: string[]; + /** + * @description Campaign visibility setting + * @enum {string} + */ + visibility?: "PUBLIC" | "PRIVATE"; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete campaign + * @description โš ๏ธ DANGER - Permanently delete a campaign and all associated data. + */ + campaign_delete: { + requestBody: { + content: { + "application/json": { + /** @description ID of the campaign to delete */ + campaignId: string; + /** @description If true, permanently delete the campaign. Default false (soft delete/archive) */ + hardDelete?: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Get campaign summary + * @description Get detailed summary information about a specific campaign. + */ + campaign_get_summary: { + requestBody: { + content: { + "application/json": { + /** @description ID of the campaign to retrieve */ + campaignId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List campaign tactics + * @description List all tactics associated with a specific campaign. + */ + campaign_list_strategies: { + requestBody: { + content: { + "application/json": { + /** @description ID of the campaign to list tactics for */ + campaignId: string; + /** @description Include archived tactics (defaults to false) */ + includeArchived?: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Validate campaign brief + * @description Validate a campaign brief to ensure it contains all necessary information. + */ + campaign_validate_brief: { + requestBody: { + content: { + "application/json": { + /** @description Campaign brief to validate */ + brief: string; + /** @description Optional brand agent ID for context-aware validation */ + brandAgentId?: string; + /** + * @description Minimum quality score required to pass validation + * @default 70 + */ + threshold?: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List channels + * @description List all available advertising channels. + */ + channel_list: { + requestBody: { + content: { + "application/json": Record; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List creatives + * @description List creatives for the authenticated customer, with optional filtering. + */ + creative_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional brand agent ID to filter creatives */ + brandAgentId?: string; + /** @description Optional campaign ID to filter creatives */ + campaignId?: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create creative + * @description Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + */ + creative_create: { + requestBody: { + content: { + "application/json": { + /** @description Internal database ID of the brand agent that will own this creative */ + brandAgentId: number; + /** @description Optional internal database ID of the organization */ + organizationId?: number; + /** @description Name for the creative */ + name: string; + /** @description Optional description of the creative */ + description?: string; + /** + * @description Format source type + * @enum {string} + */ + formatSource?: "ADCP" | "CREATIVE_AGENT" | "PUBLISHER"; + /** @description Format identifier (e.g., "video/mp4", "display/banner") */ + formatId?: string; + /** @description URL to the creative media file (video, image, etc.) */ + mediaUrl?: string; + /** @description Creative content as JSON. Can include assetIds (array of asset IDs from asset_upload), htmlSnippet, vastTag, etc. */ + content?: { + /** @description Array of asset IDs uploaded via asset_upload tool */ + assetIds?: string[]; + /** @description HTML5 creative snippet */ + htmlSnippet?: string; + /** @description VAST XML tag for video ads */ + vastTag?: string; + }; + /** + * @description Assembly method + * @enum {string} + */ + assemblyMethod?: "CREATIVE_AGENT" | "ACTIVATION" | "PUBLISHER"; + /** @description Optional internal database ID of campaign to assign creative to */ + campaignId?: number; + }; + }; + }; + responses: { + /** @description Creative created successfully */ + 200: { + content: { + "application/json": { + /** @example true */ + success?: boolean; + /** + * @description Success message with creative details including creativeId (external string ID for use in media_buy_create/update) and internal ID + * @example โœ… **Creative Created Successfully!** + * + * **Creative ID:** newcreativevideo_xntthe4w (use this for media_buy_create/update) + * **Internal ID:** 16 + * **Name:** My Creative + * **Status:** PENDING + * **Created:** 2025-10-14T00:00:00.000Z + */ + message?: string; + }; + }; + }; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Get creative + * @description Get detailed information about a specific creative. + */ + creative_get: { + requestBody: { + content: { + "application/json": { + /** @description Internal database ID of the creative to retrieve */ + creativeId: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update creative + * @description Update an existing creative's settings. + */ + creative_update: { + requestBody: { + content: { + "application/json": { + /** @description Internal database ID of the creative to update */ + creativeId: number; + /** @description New name for the creative */ + name?: string; + /** @description New status for the creative */ + status?: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete creative + * @description โš ๏ธ DANGER - Permanently delete a creative. + */ + creative_delete: { + requestBody: { + content: { + "application/json": { + /** @description Internal database ID of the creative to delete */ + creativeId: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Assign creative to campaign + * @description Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents + * associated with the campaign via active media buys. Returns auto-sync results including which agents + * received the creative and their approval status. + */ + creative_assign: { + requestBody: { + content: { + "application/json": { + /** @description Internal database ID of the creative to assign */ + creativeId: number; + /** @description Internal database ID of the campaign to assign creative to */ + campaignId: number; + }; + }; + }; + responses: { + /** @description Creative assigned successfully with auto-sync results */ + 200: { + content: { + "application/json": { + content?: { + /** @example text */ + type?: string; + /** + * @description Summary of creative assignment including auto-sync results. + * Shows which sales agents received the creative and their approval status. + */ + text?: string; + }[]; + }; + }; + }; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Sync creative with sales agents + * @description Sync a creative's formats and specifications with connected sales agents/publishers. + */ + creative_sync_sales_agents: { + requestBody: { + content: { + "application/json": { + /** @description Internal database ID of the creative to sync */ + creativeId: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List sales agents + * @description List all registered sales agents (publishers) for the authenticated customer. + */ + sales_agent_list: { + requestBody: { + content: { + "application/json": Record; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Get sales agent + * @description Get detailed information about a specific sales agent. + */ + sales_agent_get: { + requestBody: { + content: { + "application/json": { + /** @description ID of the sales agent to retrieve */ + salesAgentId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Register sales agent + * @description Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. + */ + sales_agent_register: { + requestBody: { + content: { + "application/json": { + /** @description Sales agent name */ + name: string; + /** @description Sales agent endpoint URL */ + endpointUrl: string; + /** + * @description Protocol type + * @enum {string} + */ + protocol: "REST" | "MCP" | "A2A" | "CUSTOM"; + /** + * @description Authentication type + * @enum {string} + */ + authenticationType: "API_KEY" | "OAUTH" | "NO_AUTH"; + /** @description Sales agent description (optional) */ + description?: string; + /** @description Organization ID (optional - auto-detected from customer if not provided) */ + organizationId?: string; + /** @description Authentication configuration for the sales agent (optional) */ + authConfig?: Record; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List accounts for a sales agent + * @description List all accounts registered by your organization for a specific sales agent. + */ + sales_agent_account_list: { + requestBody: { + content: { + "application/json": { + /** @description ID of the sales agent */ + salesAgentId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Register account for sales agent + * @description Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. + */ + sales_agent_account_register: { + requestBody: { + content: { + "application/json": { + /** @description Sales agent ID */ + salesAgentId: string; + /** @description Account identifier */ + accountIdentifier: string; + /** @description Authentication configuration (credentials, tokens, etc.) - optional */ + authConfig?: Record; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Unregister sales agent completely + * @description Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. + */ + sales_agent_unregister: { + requestBody: { + content: { + "application/json": { + /** @description ID of the sales agent to unregister */ + salesAgentId: string; + /** @description Must be true to confirm this destructive operation */ + confirm: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Unregister your account with a sales agent + * @description Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. + */ + sales_agent_account_unregister: { + requestBody: { + content: { + "application/json": { + /** @description ID of the sales agent to unregister your account from */ + salesAgentId: string; + /** @description Must be true to confirm this destructive operation */ + confirm: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update sales agent + * @description Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. + */ + sales_agent_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the sales agent to update */ + salesAgentId: string; + /** @description New name */ + name?: string; + /** @description New description */ + description?: string; + /** @description New endpoint URL */ + endpointUrl?: string; + /** + * @description New protocol + * @enum {string} + */ + protocol?: "REST" | "MCP" | "A2A" | "CUSTOM"; + /** + * @description New authentication type + * @enum {string} + */ + authenticationType?: "API_KEY" | "OAUTH" | "NO_AUTH"; + /** @description Authentication configuration for the sales agent */ + authConfig?: Record; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update sales agent account authentication + * @description Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. + */ + sales_agent_account_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the sales agent */ + salesAgentId: string; + /** @description Account identifier to update */ + accountIdentifier: string; + /** @description Updated authentication configuration (credentials, tokens, etc.) */ + authConfig: Record; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List tactics + * @description List all media buying tactics for the authenticated customer. + */ + strategy_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional campaign ID to filter tactics */ + campaignId?: string; + /** @description Include archived tactics (defaults to false) */ + includeArchived?: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create tactic + * @description Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. + */ + strategy_create: { + requestBody: { + content: { + "application/json": { + /** @description Name of the tactic */ + name: string; + /** @description Campaign ID to link this tactic to (required) */ + campaignId: string; + /** @description Optional tactical brief or prompt for this tactic */ + prompt?: string; + /** @description Valid channel codes to target (also accepts friendly aliases like audio, web, app, ctv, video which are automatically mapped) */ + channelCodes?: ("DIGITAL-AUDIO" | "DISPLAY-WEB" | "DISPLAY-APP" | "CTV-BVOD" | "OLV" | "DOOH" | "SOCIAL")[]; + /** @description Country codes to target (2-digit ISO codes) */ + countryCodes?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Get tactic + * @description Get detailed information about a specific tactic. + */ + strategy_get: { + requestBody: { + content: { + "application/json": { + /** @description ID of the tactic to retrieve */ + tacticId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update tactic + * @description Update an existing tactic's configuration. + */ + strategy_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the tactic to update */ + tacticId: string; + /** @description New name for the tactic */ + name?: string; + /** @description New tactical brief */ + prompt?: string; + /** @description Updated channel codes (also accepts friendly aliases like audio, web, app, ctv, video) */ + channelCodes?: ("DIGITAL-AUDIO" | "DISPLAY-WEB" | "DISPLAY-APP" | "CTV-BVOD" | "OLV" | "DOOH" | "SOCIAL")[]; + /** @description Updated country codes */ + countryCodes?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete tactic + * @description โš ๏ธ DANGER - Permanently delete a tactic. + */ + strategy_delete: { + requestBody: { + content: { + "application/json": { + /** @description ID of the tactic to delete */ + tacticId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Link campaign to tactic + * @description Link a campaign to a tactic for budget and execution management. + */ + strategy_link_campaign: { + requestBody: { + content: { + "application/json": { + /** @description ID of the tactic */ + tacticId: string; + /** @description ID of the campaign to link */ + campaignId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Unlink campaign from tactic + * @description Unlink a campaign from a tactic. + */ + strategy_unlink_campaign: { + requestBody: { + content: { + "application/json": { + /** @description ID of the tactic */ + tacticId: string; + /** @description ID of the campaign to unlink */ + campaignId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List media buys + * @description List all media buys for the authenticated customer. + */ + media_buy_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional tactic ID to filter media buys */ + tacticId?: string; + /** @description Optional campaign ID to filter media buys */ + campaignId?: string; + /** @description Include archived media buys (defaults to false) */ + includeArchived?: boolean; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Create media buy + * @description Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. + * + * **Multi-Product Support**: Media buys now support multiple products from different sales agents in a single buy. Each product can have its own budget allocation and pricing. During execution, each unique sales agent will receive a separate ADCP submission. + * + * **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. + */ + media_buy_create: { + requestBody: { + content: { + "application/json": { + /** @description ID of the tactic to execute */ + tacticId: string; + /** @description Name of the media buy */ + name: string; + /** @description Optional description of the media buy */ + description?: string; + /** @description Array of products to include in this media buy. At least one product is required. Each product will be validated with its sales agent. */ + products: { + /** @description Media product ID from publisher (will be validated with sales agent) */ + mediaProductId: string; + /** @description Sales agent ID for this product */ + salesAgentId: string; + /** @description Budget allocated to this specific product (optional, must not exceed total budget when summed across all products) */ + budgetAmount?: number; + /** @description Currency for this product's budget (defaults to media buy currency) */ + budgetCurrency?: string; + /** @description Base CPM price for this product */ + pricingCpm?: number; + /** @description Additional signal cost for this product */ + pricingSignalCost?: number; + /** @description Optional display order for organizing products */ + displayOrder?: number; + }[]; + budget: { + /** @description Total budget amount for this media buy */ + amount: number; + /** @description Currency code (defaults to USD) */ + currency?: string; + /** @description Optional daily spending cap */ + dailyCap?: number; + /** + * @description Budget pacing tactic (defaults to even) + * @enum {string} + */ + pacing?: "asap" | "even" | "front_loaded"; + }; + /** @description Optional array of creative IDs (database IDs) to assign to this media buy. Creatives must be assigned to the campaign associated with this media buy's tactic. */ + creativeIds?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Get media buy + * @description Get detailed information about a specific media buy. + */ + media_buy_get: { + requestBody: { + content: { + "application/json": { + /** @description ID of the media buy to retrieve */ + mediaBuyId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Update media buy + * @description Update an existing media buy's configuration. + */ + media_buy_update: { + requestBody: { + content: { + "application/json": { + /** @description ID of the media buy to update */ + mediaBuyId: string; + /** @description New name */ + name?: string; + budget?: { + amount?: number; + dailyCap?: number; + /** @enum {string} */ + pacing?: "asap" | "even" | "front_loaded"; + }; + /** @description New CPM price */ + cpm?: number; + /** @description Array of creative IDs (database IDs) to assign to this media buy. Replaces existing assignments. Creatives must be assigned to the campaign associated with this media buy's tactic. */ + creativeIds?: string[]; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Delete media buy + * @description โš ๏ธ DANGER - Permanently delete a media buy. + */ + media_buy_delete: { + requestBody: { + content: { + "application/json": { + /** @description ID of the media buy to delete */ + mediaBuyId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Execute media buy + * @description Execute a media buy by deploying it to the publisher platform. + */ + media_buy_execute: { + requestBody: { + content: { + "application/json": { + /** @description ID of the media buy to execute */ + mediaBuyId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List notifications + * @description List notifications for the authenticated user. + */ + notifications_list: { + requestBody: { + content: { + "application/json": { + /** @description Filter to only unread notifications */ + unreadOnly?: boolean; + /** @description Maximum number of notifications to return */ + limit?: number; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Mark notification as read + * @description Mark a specific notification as read. + */ + notifications_mark_read: { + requestBody: { + content: { + "application/json": { + /** @description ID of the notification to mark as read */ + notificationId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Mark notification as acknowledged + * @description Mark a specific notification as acknowledged. + */ + notifications_mark_acknowledged: { + requestBody: { + content: { + "application/json": { + /** @description ID of the notification to mark as acknowledged */ + notificationId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Mark all notifications as read + * @description Mark all notifications as read for the authenticated user. + */ + notifications_mark_all_read: { + requestBody: { + content: { + "application/json": Record; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * List media products + * @description List available media products from publishers. + */ + media_product_list: { + requestBody: { + content: { + "application/json": { + /** @description Optional sales agent ID to filter products */ + salesAgentId?: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Discover media products + * @description Discover new media products from connected publishers. + */ + media_product_discover: { + requestBody: { + content: { + "application/json": { + /** @description Sales agent ID to discover products from */ + salesAgentId?: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 500: components["responses"]["InternalError"]; + }; + }; + /** + * Sync media products + * @description Synchronize media product inventory with publisher systems. + */ + media_product_sync: { + requestBody: { + content: { + "application/json": { + /** @description Sales agent ID to sync products from */ + salesAgentId: string; + }; + }; + }; + responses: { + 200: components["responses"]["ToolResponse"]; + 401: components["responses"]["Unauthorized"]; + 404: components["responses"]["NotFound"]; + 500: components["responses"]["InternalError"]; + }; + }; +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..74a6672 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,18 @@ +export interface ClientConfig { + apiKey: string; + baseUrl?: string; + timeout?: number; +} + +export interface ToolResponse { + success: boolean; + message?: string; + data?: T; +} + +export interface ErrorResponse { + error: string; + details?: any; +} + +export type Environment = 'production' | 'staging'; diff --git a/src/webhook-server.ts b/src/webhook-server.ts new file mode 100644 index 0000000..f652fe0 --- /dev/null +++ b/src/webhook-server.ts @@ -0,0 +1,138 @@ +import express, { Express, Request, Response, NextFunction } from 'express'; +import { Server } from 'http'; + +export interface WebhookEvent { + type: string; + timestamp: string; + data: any; +} + +export type WebhookHandler = (event: WebhookEvent) => Promise | void; + +export interface WebhookServerConfig { + port?: number; + path?: string; + secret?: string; +} + +export class WebhookServer { + private app: Express; + private server?: Server; + private handlers: Map; + private config: Required; + + constructor(config: WebhookServerConfig = {}) { + this.app = express(); + this.handlers = new Map(); + this.config = { + port: config.port || 3000, + path: config.path || '/webhooks', + secret: config.secret || '', + }; + + this.setupMiddleware(); + this.setupRoutes(); + } + + private setupMiddleware(): void { + this.app.use(express.json()); + + if (this.config.secret) { + this.app.use((req: Request, res: Response, next: NextFunction) => { + const authHeader = req.headers['authorization']; + const expectedAuth = `Bearer ${this.config.secret}`; + + if (authHeader !== expectedAuth) { + res.status(401).json({ error: 'Unauthorized' }); + return; + } + + next(); + }); + } + } + + private setupRoutes(): void { + this.app.post(this.config.path, async (req: Request, res: Response) => { + try { + const event: WebhookEvent = req.body; + + if (!event.type) { + res.status(400).json({ error: 'Missing event type' }); + return; + } + + const handlers = this.handlers.get(event.type) || []; + const allHandlers = this.handlers.get('*') || []; + + await Promise.all([ + ...handlers.map((handler) => handler(event)), + ...allHandlers.map((handler) => handler(event)), + ]); + + res.status(200).json({ success: true }); + } catch (error) { + console.error('Webhook handler error:', error); + res.status(500).json({ error: 'Internal server error' }); + } + }); + + this.app.get('/health', (_req: Request, res: Response) => { + res.status(200).json({ status: 'ok' }); + }); + } + + on(eventType: string, handler: WebhookHandler): void { + if (!this.handlers.has(eventType)) { + this.handlers.set(eventType, []); + } + this.handlers.get(eventType)!.push(handler); + } + + off(eventType: string, handler?: WebhookHandler): void { + if (!handler) { + this.handlers.delete(eventType); + return; + } + + const handlers = this.handlers.get(eventType); + if (handlers) { + const index = handlers.indexOf(handler); + if (index > -1) { + handlers.splice(index, 1); + } + } + } + + start(): Promise { + return new Promise((resolve) => { + this.server = this.app.listen(this.config.port, () => { + console.log(`Webhook server listening on port ${this.config.port}`); + console.log(`Webhook endpoint: http://localhost:${this.config.port}${this.config.path}`); + resolve(); + }); + }); + } + + stop(): Promise { + return new Promise((resolve, reject) => { + if (!this.server) { + resolve(); + return; + } + + this.server.close((err) => { + if (err) { + reject(err); + } else { + console.log('Webhook server stopped'); + resolve(); + } + }); + }); + } + + getUrl(): string { + return `http://localhost:${this.config.port}${this.config.path}`; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3ca9e4b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020"], + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "types": ["node", "jest"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.test.ts"] +} From 9d1a2f52762a9c4d01e1992373cf76e7923acdee Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 18 Oct 2025 04:56:48 -0400 Subject: [PATCH 02/12] Clarify HTTP/REST architecture in README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Scope3 API exposes MCP tools via HTTP POST endpoints. This client uses axios (standard HTTP client) to communicate with these endpoints, which is the correct approach for their HTTP-based MCP server implementation. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 96180ff..af413cb 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,14 @@ TypeScript client for the Scope3 Agentic API with AdCP webhook support. ## Features - ๐Ÿš€ Full TypeScript support with generated types from OpenAPI schema -- ๐Ÿ“ฆ Complete API coverage for all Scope3 endpoints +- ๐Ÿ“ฆ Complete API coverage for all Scope3 endpoints (HTTP/REST client) - ๐Ÿ” Bearer token authentication - ๐Ÿช Optional webhook server for AdCP events - โœจ Clean, intuitive API design - ๐Ÿงช Comprehensive test coverage +**Note:** The Scope3 API exposes Model Context Protocol (MCP) tools via HTTP POST endpoints. This client uses axios for HTTP communication to these endpoints, ensuring reliable protocol implementation without custom MCP transport layers. + ## Installation ```bash From 02c04d17f106102b1a47712a7ac8715d80181308 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 18 Oct 2025 05:03:11 -0400 Subject: [PATCH 03/12] Use official MCP SDK for Scope3 API integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace axios with @modelcontextprotocol/sdk to properly connect to the Scope3 MCP server at api.agentic.scope3.com/mcp. Changes: - Use SSEClientTransport with bearer token authentication - Convert all API calls to MCP tool invocations - Update tool names: /endpoint-name -> endpoint_name (underscores) - Parse JSON responses from MCP tool content - Update documentation to reflect MCP architecture All tests passing. The client now uses the official MCP TypeScript SDK as intended, avoiding any protocol implementation issues. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 5 +- package-lock.json | 549 ++++++++++++++++++++++++------- package.json | 2 +- src/client.ts | 98 ++++-- src/resources/assets.ts | 4 +- src/resources/brand-agents.ts | 10 +- src/resources/brand-standards.ts | 6 +- src/resources/brand-stories.ts | 8 +- src/resources/campaigns.ts | 14 +- src/resources/channels.ts | 2 +- src/resources/creatives.ts | 14 +- src/resources/media-buys.ts | 12 +- src/resources/notifications.ts | 8 +- src/resources/products.ts | 6 +- src/resources/sales-agents.ts | 18 +- src/resources/tactics.ts | 14 +- 16 files changed, 548 insertions(+), 222 deletions(-) diff --git a/README.md b/README.md index af413cb..fdaa63c 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,14 @@ TypeScript client for the Scope3 Agentic API with AdCP webhook support. ## Features - ๐Ÿš€ Full TypeScript support with generated types from OpenAPI schema -- ๐Ÿ“ฆ Complete API coverage for all Scope3 endpoints (HTTP/REST client) +- ๐Ÿ“ฆ Complete API coverage for all Scope3 MCP tools - ๐Ÿ” Bearer token authentication +- ๐Ÿ”Œ Official MCP SDK (`@modelcontextprotocol/sdk`) with SSE transport - ๐Ÿช Optional webhook server for AdCP events - โœจ Clean, intuitive API design - ๐Ÿงช Comprehensive test coverage -**Note:** The Scope3 API exposes Model Context Protocol (MCP) tools via HTTP POST endpoints. This client uses axios for HTTP communication to these endpoints, ensuring reliable protocol implementation without custom MCP transport layers. +**Architecture:** This client uses the official `@modelcontextprotocol/sdk` to connect to the Scope3 MCP server at `https://api.agentic.scope3.com/mcp` via Server-Sent Events (SSE) transport. All API operations are exposed as MCP tool calls with proper request/response handling. ## Installation diff --git a/package-lock.json b/package-lock.json index b55aba9..4dd3e64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "axios": "^1.6.0", + "@modelcontextprotocol/sdk": "^1.20.1", "express": "^4.18.0" }, "devDependencies": { @@ -1160,6 +1160,311 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.20.1.tgz", + "integrity": "sha512-j/P+yuxXfgxb+mW7OEoRCM3G47zCTDqUPivJo/VzpjbG8I9csTXtOprCf5FfOfHK4whOJny0aHuBEON+kS7CCA==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1719,7 +2024,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -1834,23 +2138,6 @@ "node": ">=8" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -2302,18 +2589,6 @@ "dev": true, "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2364,6 +2639,19 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -2390,7 +2678,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2405,7 +2692,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2451,15 +2737,6 @@ "node": ">=0.10.0" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2621,21 +2898,6 @@ "node": ">= 0.4" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2863,6 +3125,27 @@ "node": ">= 0.6" } }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -2959,6 +3242,21 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2978,7 +3276,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3015,7 +3312,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -3143,42 +3439,6 @@ "dev": true, "license": "ISC" }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3474,21 +3734,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -3716,6 +3961,12 @@ "node": ">=8" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -3733,7 +3984,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/istanbul-lib-coverage": { @@ -4441,7 +4691,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -4790,6 +5039,15 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -4818,7 +5076,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -4996,7 +5253,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5055,6 +5311,15 @@ "node": ">= 6" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -5205,17 +5470,10 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5407,6 +5665,32 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5543,7 +5827,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -5556,7 +5839,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6114,7 +6396,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -6167,7 +6448,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -6218,7 +6498,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -6293,6 +6572,24 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/package.json b/package.json index 232d408..137ce57 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "author": "", "license": "MIT", "dependencies": { - "axios": "^1.6.0", + "@modelcontextprotocol/sdk": "^1.20.1", "express": "^4.18.0" }, "devDependencies": { diff --git a/src/client.ts b/src/client.ts index 93aa6dd..92a7c91 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,25 +1,37 @@ -import axios, { AxiosInstance, AxiosError } from 'axios'; -import { ClientConfig, Environment, ErrorResponse } from './types'; +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'; +import { ClientConfig, Environment } from './types'; export class Scope3Client { - private readonly client: AxiosInstance; - private readonly apiKey: string; + protected readonly mcpClient: Client; + protected readonly apiKey: string; + private transport?: SSEClientTransport; + private connected = false; constructor(config: ClientConfig) { this.apiKey = config.apiKey; const baseURL = config.baseUrl || this.getDefaultBaseUrl('production'); - this.client = axios.create({ - baseURL, - timeout: config.timeout || 30000, - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.apiKey}`, + this.mcpClient = new Client( + { + name: '@scope3/agentic-client', + version: '0.1.0', }, - }); + { + capabilities: { + tools: {}, + }, + } + ); - this.setupInterceptors(); + this.transport = new SSEClientTransport(new URL(`${baseURL}/mcp`), { + requestInit: { + headers: { + Authorization: `Bearer ${this.apiKey}`, + }, + }, + }); } private getDefaultBaseUrl(env: Environment): string { @@ -28,33 +40,49 @@ export class Scope3Client { : 'https://api.agentic.staging.scope3.com'; } - private setupInterceptors(): void { - this.client.interceptors.response.use( - (response) => response, - (error: AxiosError) => { - if (error.response) { - const errorData = error.response.data; - throw new Error( - errorData?.error || `API Error: ${error.response.status} ${error.response.statusText}` - ); - } else if (error.request) { - throw new Error('No response received from API'); - } else { - throw new Error(`Request setup error: ${error.message}`); - } - } - ); + async connect(): Promise { + if (this.connected || !this.transport) { + return; + } + + await this.mcpClient.connect(this.transport); + this.connected = true; } - protected async post( - endpoint: string, - data: TRequest + async disconnect(): Promise { + if (!this.connected) { + return; + } + + await this.mcpClient.close(); + this.connected = false; + } + + protected async callTool( + toolName: string, + args: TRequest ): Promise { - const response = await this.client.post(endpoint, data); - return response.data; + if (!this.connected) { + await this.connect(); + } + + const result = await this.mcpClient.callTool({ + name: toolName, + arguments: args as Record, + }); + + // MCP tools return content array, extract the JSON from text content + if (result.content && Array.isArray(result.content) && result.content.length > 0) { + const content = result.content[0]; + if (content.type === 'text') { + return JSON.parse(content.text) as TResponse; + } + } + + throw new Error('Unexpected tool response format'); } - protected getClient(): AxiosInstance { - return this.client; + protected getClient(): Client { + return this.mcpClient; } } diff --git a/src/resources/assets.ts b/src/resources/assets.ts index 4731109..4295677 100644 --- a/src/resources/assets.ts +++ b/src/resources/assets.ts @@ -20,10 +20,10 @@ export class AssetsResource { constructor(private client: Scope3Client) {} async upload(request: AssetUploadRequest): Promise { - return this.client['post']('/asset-upload', request); + return this.client['callTool']('asset_upload', request); } async list(request: AssetListRequest = {}): Promise { - return this.client['post']('/asset-list', request); + return this.client['callTool']('asset_list', request); } } diff --git a/src/resources/brand-agents.ts b/src/resources/brand-agents.ts index 2a2d2aa..6367814 100644 --- a/src/resources/brand-agents.ts +++ b/src/resources/brand-agents.ts @@ -28,22 +28,22 @@ export class BrandAgentsResource { constructor(private client: Scope3Client) {} async list(): Promise { - return this.client['post']('/brand-agent-list', {}); + return this.client['callTool']('brand_agent_list', {}); } async create(request: BrandAgentCreateRequest): Promise { - return this.client['post']('/brand-agent-create', request); + return this.client['callTool']('brand_agent_create', request); } async get(request: BrandAgentGetRequest): Promise { - return this.client['post']('/brand-agent-get', request); + return this.client['callTool']('brand_agent_get', request); } async update(request: BrandAgentUpdateRequest): Promise { - return this.client['post']('/brand-agent-update', request); + return this.client['callTool']('brand_agent_update', request); } async delete(request: BrandAgentDeleteRequest): Promise { - return this.client['post']('/brand-agent-delete', request); + return this.client['callTool']('brand_agent_delete', request); } } diff --git a/src/resources/brand-standards.ts b/src/resources/brand-standards.ts index 6492b21..3417dbe 100644 --- a/src/resources/brand-standards.ts +++ b/src/resources/brand-standards.ts @@ -32,14 +32,14 @@ export class BrandStandardsResource { constructor(private client: Scope3Client) {} async list(request: BrandStandardsListRequest = {}): Promise { - return this.client['post']('/brand-standards-list', request); + return this.client['callTool']('brand_standards_list', request); } async create(request: BrandStandardsCreateRequest): Promise { - return this.client['post']('/brand-standards-create', request); + return this.client['callTool']('brand_standards_create', request); } async delete(request: BrandStandardsDeleteRequest): Promise { - return this.client['post']('/brand-standards-delete', request); + return this.client['callTool']('brand_standards_delete', request); } } diff --git a/src/resources/brand-stories.ts b/src/resources/brand-stories.ts index 428e66c..6c5756a 100644 --- a/src/resources/brand-stories.ts +++ b/src/resources/brand-stories.ts @@ -28,18 +28,18 @@ export class BrandStoriesResource { constructor(private client: Scope3Client) {} async list(request: BrandStoryListRequest): Promise { - return this.client['post']('/brand-story-list', request); + return this.client['callTool']('brand_story_list', request); } async create(request: BrandStoryCreateRequest): Promise { - return this.client['post']('/brand-story-create', request); + return this.client['callTool']('brand_story_create', request); } async update(request: BrandStoryUpdateRequest): Promise { - return this.client['post']('/brand-story-update', request); + return this.client['callTool']('brand_story_update', request); } async delete(request: BrandStoryDeleteRequest): Promise { - return this.client['post']('/brand-story-delete', request); + return this.client['callTool']('brand_story_delete', request); } } diff --git a/src/resources/campaigns.ts b/src/resources/campaigns.ts index 7fd6bb4..681c3a7 100644 --- a/src/resources/campaigns.ts +++ b/src/resources/campaigns.ts @@ -75,30 +75,30 @@ export class CampaignsResource { constructor(private client: Scope3Client) {} async list(request: CampaignListRequest = {}): Promise { - return this.client['post']('/campaign-list', request); + return this.client['callTool']('campaign_list', request); } async create(request: CampaignCreateRequest): Promise { - return this.client['post']('/campaign-create', request); + return this.client['callTool']('campaign_create', request); } async update(request: CampaignUpdateRequest): Promise { - return this.client['post']('/campaign-update', request); + return this.client['callTool']('campaign_update', request); } async delete(request: CampaignDeleteRequest): Promise { - return this.client['post']('/campaign-delete', request); + return this.client['callTool']('campaign_delete', request); } async getSummary(request: CampaignGetSummaryRequest): Promise { - return this.client['post']('/campaign-get-summary', request); + return this.client['callTool']('campaign_get_summary', request); } async listTactics(request: CampaignListTacticsRequest): Promise { - return this.client['post']('/campaign-list-tactics', request); + return this.client['callTool']('campaign_list_tactics', request); } async validateBrief(request: CampaignValidateBriefRequest): Promise { - return this.client['post']('/campaign-validate-brief', request); + return this.client['callTool']('campaign_validate_brief', request); } } diff --git a/src/resources/channels.ts b/src/resources/channels.ts index d4f702f..eb6b873 100644 --- a/src/resources/channels.ts +++ b/src/resources/channels.ts @@ -5,6 +5,6 @@ export class ChannelsResource { constructor(private client: Scope3Client) {} async list(): Promise { - return this.client['post']('/channel-list', {}); + return this.client['callTool']('channel_list', {}); } } diff --git a/src/resources/creatives.ts b/src/resources/creatives.ts index 0223fc5..a2ff81e 100644 --- a/src/resources/creatives.ts +++ b/src/resources/creatives.ts @@ -50,30 +50,30 @@ export class CreativesResource { constructor(private client: Scope3Client) {} async list(request: CreativeListRequest = {}): Promise { - return this.client['post']('/creative-list', request); + return this.client['callTool']('creative_list', request); } async create(request: CreativeCreateRequest): Promise { - return this.client['post']('/creative-create', request); + return this.client['callTool']('creative_create', request); } async get(request: CreativeGetRequest): Promise { - return this.client['post']('/creative-get', request); + return this.client['callTool']('creative_get', request); } async update(request: CreativeUpdateRequest): Promise { - return this.client['post']('/creative-update', request); + return this.client['callTool']('creative_update', request); } async delete(request: CreativeDeleteRequest): Promise { - return this.client['post']('/creative-delete', request); + return this.client['callTool']('creative_delete', request); } async assign(request: CreativeAssignRequest): Promise { - return this.client['post']('/creative-assign', request); + return this.client['callTool']('creative_assign', request); } async syncSalesAgents(request: CreativeSyncSalesAgentsRequest): Promise { - return this.client['post']('/creative-sync-sales-agents', request); + return this.client['callTool']('creative_sync_sales_agents', request); } } diff --git a/src/resources/media-buys.ts b/src/resources/media-buys.ts index 9d6c4ff..263545b 100644 --- a/src/resources/media-buys.ts +++ b/src/resources/media-buys.ts @@ -55,26 +55,26 @@ export class MediaBuysResource { constructor(private client: Scope3Client) {} async list(request: MediaBuyListRequest = {}): Promise { - return this.client['post']('/media-buy-list', request); + return this.client['callTool']('media_buy_list', request); } async create(request: MediaBuyCreateRequest): Promise { - return this.client['post']('/media-buy-create', request); + return this.client['callTool']('media_buy_create', request); } async get(request: MediaBuyGetRequest): Promise { - return this.client['post']('/media-buy-get', request); + return this.client['callTool']('media_buy_get', request); } async update(request: MediaBuyUpdateRequest): Promise { - return this.client['post']('/media-buy-update', request); + return this.client['callTool']('media_buy_update', request); } async delete(request: MediaBuyDeleteRequest): Promise { - return this.client['post']('/media-buy-delete', request); + return this.client['callTool']('media_buy_delete', request); } async execute(request: MediaBuyExecuteRequest): Promise { - return this.client['post']('/media-buy-execute', request); + return this.client['callTool']('media_buy_execute', request); } } diff --git a/src/resources/notifications.ts b/src/resources/notifications.ts index 69cf7db..978acf7 100644 --- a/src/resources/notifications.ts +++ b/src/resources/notifications.ts @@ -18,18 +18,18 @@ export class NotificationsResource { constructor(private client: Scope3Client) {} async list(request: NotificationsListRequest = {}): Promise { - return this.client['post']('/notifications-list', request); + return this.client['callTool']('notifications_list', request); } async markRead(request: NotificationMarkReadRequest): Promise { - return this.client['post']('/notifications-mark-read', request); + return this.client['callTool']('notifications_mark_read', request); } async markAcknowledged(request: NotificationMarkAcknowledgedRequest): Promise { - return this.client['post']('/notifications-mark-acknowledged', request); + return this.client['callTool']('notifications_mark_acknowledged', request); } async markAllRead(): Promise { - return this.client['post']('/notifications-mark-all-read', {}); + return this.client['callTool']('notifications_mark_all_read', {}); } } diff --git a/src/resources/products.ts b/src/resources/products.ts index 42ae6bc..e2946db 100644 --- a/src/resources/products.ts +++ b/src/resources/products.ts @@ -17,14 +17,14 @@ export class ProductsResource { constructor(private client: Scope3Client) {} async list(request: MediaProductListRequest = {}): Promise { - return this.client['post']('/media-product-list', request); + return this.client['callTool']('media_product_list', request); } async discover(request: MediaProductDiscoverRequest = {}): Promise { - return this.client['post']('/media-product-discover', request); + return this.client['callTool']('media_product_discover', request); } async sync(request: MediaProductSyncRequest): Promise { - return this.client['post']('/media-product-sync', request); + return this.client['callTool']('media_product_sync', request); } } diff --git a/src/resources/sales-agents.ts b/src/resources/sales-agents.ts index c0139c2..e7a9fc9 100644 --- a/src/resources/sales-agents.ts +++ b/src/resources/sales-agents.ts @@ -55,38 +55,38 @@ export class SalesAgentsResource { constructor(private client: Scope3Client) {} async list(): Promise { - return this.client['post']('/sales-agent-list', {}); + return this.client['callTool']('sales_agent_list', {}); } async get(request: SalesAgentGetRequest): Promise { - return this.client['post']('/sales-agent-get', request); + return this.client['callTool']('sales_agent_get', request); } async register(request: SalesAgentRegisterRequest): Promise { - return this.client['post']('/sales-agent-register', request); + return this.client['callTool']('sales_agent_register', request); } async update(request: SalesAgentUpdateRequest): Promise { - return this.client['post']('/sales-agent-update', request); + return this.client['callTool']('sales_agent_update', request); } async unregister(request: SalesAgentUnregisterRequest): Promise { - return this.client['post']('/sales-agent-unregister', request); + return this.client['callTool']('sales_agent_unregister', request); } async listAccounts(request: SalesAgentAccountListRequest): Promise { - return this.client['post']('/sales-agent-account-list', request); + return this.client['callTool']('sales_agent_account_list', request); } async registerAccount(request: SalesAgentAccountRegisterRequest): Promise { - return this.client['post']('/sales-agent-account-register', request); + return this.client['callTool']('sales_agent_account_register', request); } async updateAccount(request: SalesAgentAccountUpdateRequest): Promise { - return this.client['post']('/sales-agent-account-update', request); + return this.client['callTool']('sales_agent_account_update', request); } async unregisterAccount(request: SalesAgentAccountUnregisterRequest): Promise { - return this.client['post']('/sales-agent-account-unregister', request); + return this.client['callTool']('sales_agent_account_unregister', request); } } diff --git a/src/resources/tactics.ts b/src/resources/tactics.ts index e5ae49b..9d71c99 100644 --- a/src/resources/tactics.ts +++ b/src/resources/tactics.ts @@ -53,30 +53,30 @@ export class TacticsResource { constructor(private client: Scope3Client) {} async list(request: TacticListRequest = {}): Promise { - return this.client['post']('/tactic-list', request); + return this.client['callTool']('tactic_list', request); } async create(request: TacticCreateRequest): Promise { - return this.client['post']('/tactic-create', request); + return this.client['callTool']('tactic_create', request); } async get(request: TacticGetRequest): Promise { - return this.client['post']('/tactic-get', request); + return this.client['callTool']('tactic_get', request); } async update(request: TacticUpdateRequest): Promise { - return this.client['post']('/tactic-update', request); + return this.client['callTool']('tactic_update', request); } async delete(request: TacticDeleteRequest): Promise { - return this.client['post']('/tactic-delete', request); + return this.client['callTool']('tactic_delete', request); } async linkCampaign(request: TacticLinkCampaignRequest): Promise { - return this.client['post']('/tactic-link-campaign', request); + return this.client['callTool']('tactic_link_campaign', request); } async unlinkCampaign(request: TacticUnlinkCampaignRequest): Promise { - return this.client['post']('/tactic-unlink-campaign', request); + return this.client['callTool']('tactic_unlink_campaign', request); } } From 70f40c379db3c54cc4eec40bf58f75355f592bb7 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 18 Oct 2025 05:15:57 -0400 Subject: [PATCH 04/12] Switch to HTTP streaming transport for MCP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace SSEClientTransport with StreamableHTTPClientTransport to use the official MCP Streamable HTTP specification. Benefits: - HTTP POST for sending messages (better reliability) - HTTP GET with SSE for receiving messages - Automatic reconnection with exponential backoff - Session management support - Resumption tokens for interrupted requests All tests passing. The client now uses the recommended HTTP streaming transport for production MCP server connections. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 4 ++-- src/client.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fdaa63c..9a4154d 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ TypeScript client for the Scope3 Agentic API with AdCP webhook support. - ๐Ÿš€ Full TypeScript support with generated types from OpenAPI schema - ๐Ÿ“ฆ Complete API coverage for all Scope3 MCP tools - ๐Ÿ” Bearer token authentication -- ๐Ÿ”Œ Official MCP SDK (`@modelcontextprotocol/sdk`) with SSE transport +- ๐Ÿ”Œ Official MCP SDK (`@modelcontextprotocol/sdk`) with HTTP streaming transport - ๐Ÿช Optional webhook server for AdCP events - โœจ Clean, intuitive API design - ๐Ÿงช Comprehensive test coverage -**Architecture:** This client uses the official `@modelcontextprotocol/sdk` to connect to the Scope3 MCP server at `https://api.agentic.scope3.com/mcp` via Server-Sent Events (SSE) transport. All API operations are exposed as MCP tool calls with proper request/response handling. +**Architecture:** This client uses the official `@modelcontextprotocol/sdk` to connect to the Scope3 MCP server at `https://api.agentic.scope3.com/mcp` via Streamable HTTP transport. This uses HTTP POST for sending messages and HTTP GET with Server-Sent Events for receiving messages, providing reliable bidirectional communication with automatic reconnection support. ## Installation diff --git a/src/client.ts b/src/client.ts index 92a7c91..76a2235 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,11 +1,11 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'; +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; import { ClientConfig, Environment } from './types'; export class Scope3Client { protected readonly mcpClient: Client; protected readonly apiKey: string; - private transport?: SSEClientTransport; + private transport?: StreamableHTTPClientTransport; private connected = false; constructor(config: ClientConfig) { @@ -25,7 +25,7 @@ export class Scope3Client { } ); - this.transport = new SSEClientTransport(new URL(`${baseURL}/mcp`), { + this.transport = new StreamableHTTPClientTransport(new URL(`${baseURL}/mcp`), { requestInit: { headers: { Authorization: `Bearer ${this.apiKey}`, From 2d7f6da73b6cbe1eb63dd51c5848d5cda9f178b4 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 18 Oct 2025 05:17:08 -0400 Subject: [PATCH 05/12] Handle both JSON and text responses from MCP tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Scope3 API returns human-readable text responses for agentic interaction. Updated the client to gracefully handle both JSON and plain text responses from MCP tool calls. Changes: - Try JSON.parse first for structured data - Fall back to text response wrapped in { message } object - Tested successfully with live Scope3 API Verified with real API key: โœ… brand_agent_list: Returns 113 brand agents โœ… channel_list: Returns 12 channels โœ… campaign_list: Returns 6 campaigns All tests passing. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/client.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 76a2235..1b864e1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -71,11 +71,17 @@ export class Scope3Client { arguments: args as Record, }); - // MCP tools return content array, extract the JSON from text content + // MCP tools return content array, extract the response from text content if (result.content && Array.isArray(result.content) && result.content.length > 0) { const content = result.content[0]; if (content.type === 'text') { - return JSON.parse(content.text) as TResponse; + // Try to parse as JSON first, if that fails return the text as-is + try { + return JSON.parse(content.text) as TResponse; + } catch { + // If not JSON, return the text wrapped in an object + return { message: content.text } as TResponse; + } } } From bdecc8814ade5fbc80cc198d07f85ab25665dc2f Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 18 Oct 2025 05:36:04 -0400 Subject: [PATCH 06/12] Rename Scope3SDK to Scope3AgenticClient for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More descriptive name that clearly indicates this is for the Scope3 Agentic API. Kept Scope3SDK as legacy export for backwards compatibility. Changes: - Renamed main class: Scope3SDK -> Scope3AgenticClient - Updated all examples to use new name - Updated tests and documentation - Added legacy export for backwards compatibility All tests passing. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 6 +++--- examples/basic-usage.ts | 4 ++-- examples/create-campaign.ts | 4 ++-- src/__tests__/client.test.ts | 12 ++++++------ src/index.ts | 4 +++- src/sdk.ts | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9a4154d..0f103be 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ npm install @scope3/agentic-client ## Quick Start ```typescript -import { Scope3SDK } from '@scope3/agentic-client'; +import { Scope3AgenticClient } from '@scope3/agentic-client'; -const client = new Scope3SDK({ +const client = new Scope3AgenticClient({ apiKey: process.env.SCOPE3_API_KEY, }); @@ -46,7 +46,7 @@ const campaign = await client.campaigns.create({ ## Configuration ```typescript -const client = new Scope3SDK({ +const client = new Scope3AgenticClient({ apiKey: 'your-api-key', baseUrl: 'https://api.agentic.scope3.com', // optional, defaults to production timeout: 30000, // optional, request timeout in ms diff --git a/examples/basic-usage.ts b/examples/basic-usage.ts index 83bc089..4aeced4 100644 --- a/examples/basic-usage.ts +++ b/examples/basic-usage.ts @@ -1,7 +1,7 @@ -import { Scope3SDK } from '../src'; +import { Scope3AgenticClient } from '../src'; async function main() { - const client = new Scope3SDK({ + const client = new Scope3AgenticClient({ apiKey: process.env.SCOPE3_API_KEY || 'your-api-key', }); diff --git a/examples/create-campaign.ts b/examples/create-campaign.ts index ff50fee..d0f3049 100644 --- a/examples/create-campaign.ts +++ b/examples/create-campaign.ts @@ -1,7 +1,7 @@ -import { Scope3SDK } from '../src'; +import { Scope3AgenticClient } from '../src'; async function main() { - const client = new Scope3SDK({ + const client = new Scope3AgenticClient({ apiKey: process.env.SCOPE3_API_KEY || 'your-api-key', }); diff --git a/src/__tests__/client.test.ts b/src/__tests__/client.test.ts index edb3a78..ebfbb48 100644 --- a/src/__tests__/client.test.ts +++ b/src/__tests__/client.test.ts @@ -1,10 +1,10 @@ -import { Scope3SDK } from '../sdk'; +import { Scope3AgenticClient } from '../sdk'; -describe('Scope3SDK', () => { - let client: Scope3SDK; +describe('Scope3AgenticClient', () => { + let client: Scope3AgenticClient; beforeEach(() => { - client = new Scope3SDK({ + client = new Scope3AgenticClient({ apiKey: 'test-api-key', }); }); @@ -29,7 +29,7 @@ describe('Scope3SDK', () => { }); it('should accept custom base URL', () => { - const customClient = new Scope3SDK({ + const customClient = new Scope3AgenticClient({ apiKey: 'test-api-key', baseUrl: 'https://custom.api.com', }); @@ -37,7 +37,7 @@ describe('Scope3SDK', () => { }); it('should accept custom timeout', () => { - const customClient = new Scope3SDK({ + const customClient = new Scope3AgenticClient({ apiKey: 'test-api-key', timeout: 60000, }); diff --git a/src/index.ts b/src/index.ts index 9656db4..6d4e7fe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,6 @@ -export { Scope3SDK } from './sdk'; +export { Scope3AgenticClient } from './sdk'; +// Legacy export for backwards compatibility +export { Scope3AgenticClient as Scope3SDK } from './sdk'; export { WebhookServer } from './webhook-server'; export type { ClientConfig, ToolResponse, Environment } from './types'; export type { WebhookEvent, WebhookHandler, WebhookServerConfig } from './webhook-server'; diff --git a/src/sdk.ts b/src/sdk.ts index 0b5b425..0091073 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -13,7 +13,7 @@ import { MediaBuysResource } from './resources/media-buys'; import { NotificationsResource } from './resources/notifications'; import { ProductsResource } from './resources/products'; -export class Scope3SDK extends Scope3Client { +export class Scope3AgenticClient extends Scope3Client { public readonly assets: AssetsResource; public readonly brandAgents: BrandAgentsResource; public readonly brandStandards: BrandStandardsResource; From fe6883ef1002267e4b757040aefc754d9623d72b Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 19 Oct 2025 09:10:46 -0400 Subject: [PATCH 07/12] Add comprehensive type safety with automated validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement complete type safety infrastructure with no `any` types: - **Schema synchronization**: Added `update-schemas` script that downloads latest OpenAPI spec from upstream and regenerates TypeScript types - **Strict typing**: Eliminated all `any` types throughout codebase: - Changed ToolResponse to ToolResponse - Changed ErrorResponse.details to Record - Made WebhookEvent generic: WebhookEvent> - Created SalesAgentAuthConfig interface to replace Record - **Pre-commit validation**: Set up Husky with lint-staged to run on every commit: - Formatting (prettier) - Linting with auto-fix (eslint) - Type checking on full project (tsc --noEmit) - Test execution - **CI pipeline**: Added GitHub Actions workflow with parallel jobs: - Type checking - Linting - Format checking - Test execution - Build verification - **Documentation**: Updated README with type safety section explaining approach All type checks, tests, and builds passing. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/ci.yml | 68 ++ .husky/pre-commit | 8 + README.md | 36 +- openapi.yaml | 159 +++-- package-lock.json | 755 ++++++++++++++++++++++ package.json | 16 +- src/resources/sales-agents.ts | 17 +- src/types/api.ts | 1130 ++++++++++++++++++--------------- src/types/index.ts | 4 +- src/webhook-server.ts | 7 +- 10 files changed, 1646 insertions(+), 554 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100755 .husky/pre-commit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7887ff0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,68 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + type-check: + name: Type Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + - run: npm ci + - run: npm run type-check + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + - run: npm ci + - run: npm run lint + + format-check: + name: Format Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + - run: npm ci + - run: npx prettier --check "src/**/*.ts" + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + - run: npm ci + - run: npm test + + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + - run: npm ci + - run: npm run build diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..758c9f5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,8 @@ +# Run lint-staged for TypeScript files +npx lint-staged + +# Type check the entire project +npm run type-check + +# Run tests +npm test diff --git a/README.md b/README.md index 0f103be..7f88007 100644 --- a/README.md +++ b/README.md @@ -167,10 +167,16 @@ await webhookServer.stop(); # Install dependencies npm install -# Build the project +# Update schemas from upstream (downloads latest OpenAPI spec) +npm run update-schemas + +# Type check without building +npm run type-check + +# Build the project (includes type checking) npm run build -# Run tests +# Run tests (includes pre-test type checking) npm test # Run linter @@ -179,10 +185,34 @@ npm run lint # Format code npm run format -# Generate types from OpenAPI spec +# Generate types from local OpenAPI spec npm run generate-types ``` +### Type Safety + +This client is **fully typed** with no `any` types: + +- **Generated types** from OpenAPI spec using `openapi-typescript` +- **Strict TypeScript** configuration enabled +- **Pre-commit hooks** via Husky that run: + - Type checking (`tsc --noEmit`) + - Linting with auto-fix + - Code formatting +- **CI validation** on every PR: + - Type checking + - Linting + - Format checking + - Test execution + - Build verification + +To update types when the upstream API changes: +```bash +npm run update-schemas +``` + +This downloads the latest OpenAPI spec and regenerates TypeScript types. + ## Examples See the `examples/` directory for more usage examples: diff --git a/openapi.yaml b/openapi.yaml index c2043b6..55b70d4 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -48,7 +48,14 @@ paths: tags: [Assets] summary: Upload creative assets operationId: asset_upload - description: Upload creative assets (images, videos, audio) to Google Cloud Storage. Accepts base64-encoded file data and returns signed URLs (valid for 1 hour). + description: | + Upload creative assets (images, videos, audio) to Google Cloud Storage. + + **REQUIRED FIELDS:** + - `brandAgentId`: Brand agent ID for file organization + - `assets`: Array of assets (each with name, contentType, data, assetType) + + Returns signed URLs valid for 1 hour. requestBody: required: true content: @@ -59,33 +66,14 @@ paths: properties: brandAgentId: type: string - description: Brand agent ID for file organization + description: '**REQUIRED**: Brand agent ID for file organization (e.g., brand_agent_123)' + example: brand_agent_abc123 assets: type: array - description: Array of assets to upload + description: '**REQUIRED**: Array of assets to upload. Each asset must have all required fields.' + minItems: 1 items: - type: object - required: [name, contentType, data, assetType] - properties: - name: - type: string - description: Original filename - contentType: - type: string - description: MIME type (e.g., image/png, video/mp4) - data: - type: string - format: byte - description: Base64-encoded file data - assetType: - type: string - enum: [image, video, audio, logo, font] - description: Type of asset - tags: - type: array - items: - type: string - description: Optional tags for organization + $ref: '#/components/schemas/AssetUpload' responses: '200': $ref: '#/components/responses/ToolResponse' @@ -622,6 +610,10 @@ paths: type: string enum: [PUBLIC, PRIVATE] description: Campaign visibility setting + creationType: + type: string + enum: [MANUAL, AUTO_SYNC] + description: How the campaign was created status: type: string enum: [ACTIVE, PAUSED, ARCHIVED] @@ -873,11 +865,11 @@ paths: type: object properties: brandAgentId: - type: string - description: Optional brand agent ID to filter creatives + type: integer + description: Optional internal brand agent ID to filter creatives campaignId: - type: string - description: Optional campaign ID to filter creatives + type: integer + description: Optional internal campaign ID to filter creatives responses: '200': $ref: '#/components/responses/ToolResponse' @@ -891,7 +883,12 @@ paths: tags: [Creatives] summary: Create creative operationId: creative_create - description: Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + description: | + Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + + **Two workflows supported:** + 1. **Separate upload**: Use asset_upload first, then reference asset IDs in content.assetIds + 2. **Inline upload**: Upload assets directly in the `assets` array (automatically uploaded and linked) requestBody: required: true content: @@ -902,38 +899,51 @@ paths: properties: brandAgentId: type: integer - description: Internal database ID of the brand agent that will own this creative + description: '**REQUIRED**: Internal database ID of the brand agent that will own this creative' + example: 1 organizationId: type: integer description: Optional internal database ID of the organization name: type: string - description: Name for the creative + description: '**REQUIRED**: Name for the creative' + example: Banner Ad 970x250 description: type: string description: Optional description of the creative + example: Display banner for homepage formatSource: type: string enum: [ADCP, CREATIVE_AGENT, PUBLISHER] description: Format source type + example: ADCP formatId: type: string - description: Format identifier (e.g., "video/mp4", "display/banner") + description: Format identifier (e.g., "display_970x250", "video/mp4") + example: display_970x250 mediaUrl: type: string description: URL to the creative media file (video, image, etc.) + example: https://example.com/banner.png + assets: + type: array + description: 'Optional: Upload assets inline with the creative. Automatically uploaded to GCS and linked.' + items: + $ref: '#/components/schemas/AssetUpload' content: type: object - description: Creative content as JSON. Can include assetIds (array of asset IDs from asset_upload), htmlSnippet, vastTag, etc. + description: Creative content as JSON. Can include assetIds (existing or from inline upload), htmlSnippet, vastTag, etc. properties: assetIds: type: array items: type: string - description: Array of asset IDs uploaded via asset_upload tool + description: Array of existing asset IDs (from previous asset_upload). Inline uploaded assets are automatically added to this. + example: [asset_abc123, asset_def456] htmlSnippet: type: string description: HTML5 creative snippet + example:
Ad content
vastTag: type: string description: VAST XML tag for video ads @@ -941,9 +951,11 @@ paths: type: string enum: [CREATIVE_AGENT, ACTIVATION, PUBLISHER] description: Assembly method + example: ACTIVATION campaignId: type: integer description: Optional internal database ID of campaign to assign creative to + example: 1 responses: '200': description: Creative created successfully @@ -957,7 +969,7 @@ paths: example: true message: type: string - description: Success message with creative details including creativeId (external string ID for use in media_buy_create/update) and internal ID + description: Success message with creative details including creativeId (external string ID for use in media_buy_create/update), internal ID, and uploaded assets (if any) example: | โœ… **Creative Created Successfully!** @@ -965,6 +977,8 @@ paths: **Internal ID:** 16 **Name:** My Creative **Status:** PENDING + **Assets Uploaded:** 2 + **Asset IDs:** asset_abc123, asset_def456 **Created:** 2025-10-14T00:00:00.000Z '400': $ref: '#/components/responses/BadRequest' @@ -1120,7 +1134,10 @@ paths: tags: [Creatives] summary: Sync creative with sales agents operationId: creative_sync_sales_agents - description: Sync a creative's formats and specifications with connected sales agents/publishers. + description: | + Sync a creative to sales agents using smart auto-detection or manual specification. + Features intelligent format matching and recent activity analysis (30-60 day lookback). + Provides detailed sync status and actionable next steps. requestBody: required: true content: @@ -1132,6 +1149,29 @@ paths: creativeId: type: integer description: Internal database ID of the creative to sync + autoDetect: + type: object + description: Smart auto-detection settings (default behavior) + properties: + daysBack: + type: number + description: Look at tactics from past N days (default 30, max 90) + minimum: 1 + maximum: 90 + includeActive: + type: boolean + description: Include agents from active campaigns (default true) + campaignId: + type: integer + description: Internal database ID - sync to sales agents used by this campaign's tactics only + preApproval: + type: boolean + description: Request pre-approval before campaign launch (default false) + adcpAgentIds: + type: array + description: Explicitly specify ADCP agent IDs (overrides auto-detection) + items: + type: string responses: '200': $ref: '#/components/responses/ToolResponse' @@ -1212,8 +1252,8 @@ paths: description: Sales agent endpoint URL protocol: type: string - enum: [REST, MCP, A2A, CUSTOM] - description: Protocol type + enum: [MCP, A2A] + description: Protocol for endpoint URL calls authenticationType: type: string enum: [API_KEY, OAUTH, NO_AUTH] @@ -2179,6 +2219,47 @@ components: description: Error message schemas: + AssetUpload: + type: object + required: [name, contentType, data, assetType] + properties: + name: + type: string + description: '**REQUIRED**: Original filename' + example: logo.png + contentType: + type: string + description: '**REQUIRED**: MIME type' + example: image/png + enum: + - image/png + - image/jpeg + - image/jpg + - image/gif + - image/webp + - video/mp4 + - video/webm + - audio/mp3 + - audio/wav + - font/woff + - font/woff2 + data: + type: string + format: byte + description: '**REQUIRED**: Base64-encoded file data (without data:image/png;base64, prefix)' + example: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg== + assetType: + type: string + enum: [image, video, audio, logo, font] + description: '**REQUIRED**: Type of asset. Must be one of: image, video, audio, logo, font' + example: image + tags: + type: array + items: + type: string + description: Optional tags for organization + example: [brand, header, 2024] + Budget: type: object required: [total, currency] diff --git a/package-lock.json b/package-lock.json index 4dd3e64..b3d3c00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,9 @@ "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.0.0", + "husky": "^9.0.0", "jest": "^29.5.0", + "lint-staged": "^15.0.0", "openapi-typescript": "^6.7.0", "prettier": "^3.0.0", "ts-jest": "^29.1.0", @@ -2536,6 +2538,93 @@ "dev": true, "license": "MIT" }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2589,6 +2678,23 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2858,6 +2964,19 @@ "node": ">= 0.8" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -3125,6 +3244,13 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, "node_modules/eventsource": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", @@ -3508,6 +3634,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -3779,6 +3918,22 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4757,6 +4912,19 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -4764,6 +4932,294 @@ "dev": true, "license": "MIT" }, + "node_modules/lint-staged": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4794,6 +5250,160 @@ "dev": true, "license": "MIT" }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz", + "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -4947,6 +5557,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -5301,6 +5924,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pirates": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", @@ -5637,6 +6273,52 @@ "node": ">=10" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -5648,6 +6330,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -5940,6 +6629,49 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6000,6 +6732,16 @@ "node": ">= 0.8" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -6531,6 +7273,19 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index 137ce57..77f5c7e 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,16 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "build": "tsc", + "build": "npm run type-check && tsc", "dev": "tsc --watch", "test": "jest", "lint": "eslint src --ext .ts", "format": "prettier --write \"src/**/*.ts\"", - "generate-types": "openapi-typescript openapi.yaml -o src/types/api.ts" + "type-check": "tsc --noEmit", + "generate-types": "openapi-typescript openapi.yaml -o src/types/api.ts", + "update-schemas": "curl -f -o openapi.yaml https://docs.agentic.scope3.com/openapi.yaml && npm run generate-types", + "prepare": "husky", + "pretest": "npm run type-check" }, "keywords": [ "scope3", @@ -32,10 +36,18 @@ "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.0.0", + "husky": "^9.0.0", "jest": "^29.5.0", + "lint-staged": "^15.0.0", "openapi-typescript": "^6.7.0", "prettier": "^3.0.0", "ts-jest": "^29.1.0", "typescript": "^5.3.0" + }, + "lint-staged": { + "*.ts": [ + "prettier --write", + "eslint --fix" + ] } } diff --git a/src/resources/sales-agents.ts b/src/resources/sales-agents.ts index e7a9fc9..7ac4bfb 100644 --- a/src/resources/sales-agents.ts +++ b/src/resources/sales-agents.ts @@ -1,6 +1,15 @@ import { Scope3Client } from '../client'; import { ToolResponse } from '../types'; +export interface SalesAgentAuthConfig { + apiKey?: string; + clientId?: string; + clientSecret?: string; + accessToken?: string; + refreshToken?: string; + [key: string]: string | undefined; +} + export interface SalesAgentRegisterRequest { name: string; endpointUrl: string; @@ -8,7 +17,7 @@ export interface SalesAgentRegisterRequest { authenticationType: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; description?: string; organizationId?: string; - authConfig?: Record; + authConfig?: SalesAgentAuthConfig; } export interface SalesAgentGetRequest { @@ -22,7 +31,7 @@ export interface SalesAgentUpdateRequest { endpointUrl?: string; protocol?: 'REST' | 'MCP' | 'A2A' | 'CUSTOM'; authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; - authConfig?: Record; + authConfig?: SalesAgentAuthConfig; } export interface SalesAgentUnregisterRequest { @@ -37,13 +46,13 @@ export interface SalesAgentAccountListRequest { export interface SalesAgentAccountRegisterRequest { salesAgentId: string; accountIdentifier: string; - authConfig?: Record; + authConfig?: SalesAgentAuthConfig; } export interface SalesAgentAccountUpdateRequest { salesAgentId: string; accountIdentifier: string; - authConfig: Record; + authConfig: SalesAgentAuthConfig; } export interface SalesAgentAccountUnregisterRequest { diff --git a/src/types/api.ts b/src/types/api.ts index 1e147c4..6ca90f8 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -3,333 +3,344 @@ * Do not make direct changes to the file. */ - export interface paths { - "/asset-upload": { + '/asset-upload': { /** * Upload creative assets - * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. Accepts base64-encoded file data and returns signed URLs (valid for 1 hour). + * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. + * + * **REQUIRED FIELDS:** + * - `brandAgentId`: Brand agent ID for file organization + * - `assets`: Array of assets (each with name, contentType, data, assetType) + * + * Returns signed URLs valid for 1 hour. */ - post: operations["asset_upload"]; + post: operations['asset_upload']; }; - "/asset-list": { + '/asset-list': { /** * List creative assets * @description List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. */ - post: operations["asset_list"]; + post: operations['asset_list']; }; - "/brand-agent-list": { + '/brand-agent-list': { /** * List brand agents * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. */ - post: operations["brand_agent_list"]; + post: operations['brand_agent_list']; }; - "/brand-agent-create": { + '/brand-agent-create': { /** * Create brand agent * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. */ - post: operations["brand_agent_create"]; + post: operations['brand_agent_create']; }; - "/brand-agent-get": { + '/brand-agent-get': { /** * Get brand agent * @description Get detailed information about a specific brand agent (advertiser account) by ID. */ - post: operations["brand_agent_get"]; + post: operations['brand_agent_get']; }; - "/brand-agent-update": { + '/brand-agent-update': { /** * Update brand agent * @description Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. */ - post: operations["brand_agent_update"]; + post: operations['brand_agent_update']; }; - "/brand-agent-delete": { + '/brand-agent-delete': { /** * Delete brand agent * @description โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. */ - post: operations["brand_agent_delete"]; + post: operations['brand_agent_delete']; }; - "/brand-standards-list": { + '/brand-standards-list': { /** * List brand standards * @description List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. */ - post: operations["brand_standards_list"]; + post: operations['brand_standards_list']; }; - "/brand-standards-create": { + '/brand-standards-create': { /** * Create brand standard * @description Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. */ - post: operations["brand_standards_create"]; + post: operations['brand_standards_create']; }; - "/brand-standards-delete": { + '/brand-standards-delete': { /** * Delete brand standard * @description โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. */ - post: operations["brand_standards_delete"]; + post: operations['brand_standards_delete']; }; - "/brand-story-list": { + '/brand-story-list': { /** * List brand stories * @description List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. */ - post: operations["brand_story_list"]; + post: operations['brand_story_list']; }; - "/brand-story-create": { + '/brand-story-create': { /** * Create brand story * @description Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. */ - post: operations["brand_story_create"]; + post: operations['brand_story_create']; }; - "/brand-story-update": { + '/brand-story-update': { /** * Update brand story * @description Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. */ - post: operations["brand_story_update"]; + post: operations['brand_story_update']; }; - "/brand-story-delete": { + '/brand-story-delete': { /** * Delete brand story * @description โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. */ - post: operations["brand_story_delete"]; + post: operations['brand_story_delete']; }; - "/campaign-list": { + '/campaign-list': { /** * List campaigns * @description List campaigns for the authenticated customer, with optional filtering. */ - post: operations["campaign_list"]; + post: operations['campaign_list']; }; - "/campaign-create": { + '/campaign-create': { /** * Create campaign * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. */ - post: operations["campaign_create"]; + post: operations['campaign_create']; }; - "/campaign-update": { + '/campaign-update': { /** * Update campaign * @description Update an existing campaign's settings. */ - post: operations["campaign_update"]; + post: operations['campaign_update']; }; - "/campaign-delete": { + '/campaign-delete': { /** * Delete campaign * @description โš ๏ธ DANGER - Permanently delete a campaign and all associated data. */ - post: operations["campaign_delete"]; + post: operations['campaign_delete']; }; - "/campaign-get-summary": { + '/campaign-get-summary': { /** * Get campaign summary * @description Get detailed summary information about a specific campaign. */ - post: operations["campaign_get_summary"]; + post: operations['campaign_get_summary']; }; - "/campaign-list-tactics": { + '/campaign-list-tactics': { /** * List campaign tactics * @description List all tactics associated with a specific campaign. */ - post: operations["campaign_list_strategies"]; + post: operations['campaign_list_strategies']; }; - "/campaign-validate-brief": { + '/campaign-validate-brief': { /** * Validate campaign brief * @description Validate a campaign brief to ensure it contains all necessary information. */ - post: operations["campaign_validate_brief"]; + post: operations['campaign_validate_brief']; }; - "/channel-list": { + '/channel-list': { /** * List channels * @description List all available advertising channels. */ - post: operations["channel_list"]; + post: operations['channel_list']; }; - "/creative-list": { + '/creative-list': { /** * List creatives * @description List creatives for the authenticated customer, with optional filtering. */ - post: operations["creative_list"]; + post: operations['creative_list']; }; - "/creative-create": { + '/creative-create': { /** * Create creative * @description Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + * + * **Two workflows supported:** + * 1. **Separate upload**: Use asset_upload first, then reference asset IDs in content.assetIds + * 2. **Inline upload**: Upload assets directly in the `assets` array (automatically uploaded and linked) */ - post: operations["creative_create"]; + post: operations['creative_create']; }; - "/creative-get": { + '/creative-get': { /** * Get creative * @description Get detailed information about a specific creative. */ - post: operations["creative_get"]; + post: operations['creative_get']; }; - "/creative-update": { + '/creative-update': { /** * Update creative * @description Update an existing creative's settings. */ - post: operations["creative_update"]; + post: operations['creative_update']; }; - "/creative-delete": { + '/creative-delete': { /** * Delete creative * @description โš ๏ธ DANGER - Permanently delete a creative. */ - post: operations["creative_delete"]; + post: operations['creative_delete']; }; - "/creative-assign": { + '/creative-assign': { /** * Assign creative to campaign * @description Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents * associated with the campaign via active media buys. Returns auto-sync results including which agents * received the creative and their approval status. */ - post: operations["creative_assign"]; + post: operations['creative_assign']; }; - "/creative-sync-sales-agents": { + '/creative-sync-sales-agents': { /** * Sync creative with sales agents - * @description Sync a creative's formats and specifications with connected sales agents/publishers. + * @description Sync a creative to sales agents using smart auto-detection or manual specification. + * Features intelligent format matching and recent activity analysis (30-60 day lookback). + * Provides detailed sync status and actionable next steps. */ - post: operations["creative_sync_sales_agents"]; + post: operations['creative_sync_sales_agents']; }; - "/sales-agent-list": { + '/sales-agent-list': { /** * List sales agents * @description List all registered sales agents (publishers) for the authenticated customer. */ - post: operations["sales_agent_list"]; + post: operations['sales_agent_list']; }; - "/sales-agent-get": { + '/sales-agent-get': { /** * Get sales agent * @description Get detailed information about a specific sales agent. */ - post: operations["sales_agent_get"]; + post: operations['sales_agent_get']; }; - "/sales-agent-register": { + '/sales-agent-register': { /** * Register sales agent * @description Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. */ - post: operations["sales_agent_register"]; + post: operations['sales_agent_register']; }; - "/sales-agent-account-list": { + '/sales-agent-account-list': { /** * List accounts for a sales agent * @description List all accounts registered by your organization for a specific sales agent. */ - post: operations["sales_agent_account_list"]; + post: operations['sales_agent_account_list']; }; - "/sales-agent-account-register": { + '/sales-agent-account-register': { /** * Register account for sales agent * @description Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. */ - post: operations["sales_agent_account_register"]; + post: operations['sales_agent_account_register']; }; - "/sales-agent-unregister": { + '/sales-agent-unregister': { /** * Unregister sales agent completely * @description Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. */ - post: operations["sales_agent_unregister"]; + post: operations['sales_agent_unregister']; }; - "/sales-agent-account-unregister": { + '/sales-agent-account-unregister': { /** * Unregister your account with a sales agent * @description Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. */ - post: operations["sales_agent_account_unregister"]; + post: operations['sales_agent_account_unregister']; }; - "/sales-agent-update": { + '/sales-agent-update': { /** * Update sales agent * @description Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. */ - post: operations["sales_agent_update"]; + post: operations['sales_agent_update']; }; - "/sales-agent-account-update": { + '/sales-agent-account-update': { /** * Update sales agent account authentication * @description Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. */ - post: operations["sales_agent_account_update"]; + post: operations['sales_agent_account_update']; }; - "/tactic-list": { + '/tactic-list': { /** * List tactics * @description List all media buying tactics for the authenticated customer. */ - post: operations["strategy_list"]; + post: operations['strategy_list']; }; - "/tactic-create": { + '/tactic-create': { /** * Create tactic * @description Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. */ - post: operations["strategy_create"]; + post: operations['strategy_create']; }; - "/tactic-get": { + '/tactic-get': { /** * Get tactic * @description Get detailed information about a specific tactic. */ - post: operations["strategy_get"]; + post: operations['strategy_get']; }; - "/tactic-update": { + '/tactic-update': { /** * Update tactic * @description Update an existing tactic's configuration. */ - post: operations["strategy_update"]; + post: operations['strategy_update']; }; - "/tactic-delete": { + '/tactic-delete': { /** * Delete tactic * @description โš ๏ธ DANGER - Permanently delete a tactic. */ - post: operations["strategy_delete"]; + post: operations['strategy_delete']; }; - "/tactic-link-campaign": { + '/tactic-link-campaign': { /** * Link campaign to tactic * @description Link a campaign to a tactic for budget and execution management. */ - post: operations["strategy_link_campaign"]; + post: operations['strategy_link_campaign']; }; - "/tactic-unlink-campaign": { + '/tactic-unlink-campaign': { /** * Unlink campaign from tactic * @description Unlink a campaign from a tactic. */ - post: operations["strategy_unlink_campaign"]; + post: operations['strategy_unlink_campaign']; }; - "/media-buy-list": { + '/media-buy-list': { /** * List media buys * @description List all media buys for the authenticated customer. */ - post: operations["media_buy_list"]; + post: operations['media_buy_list']; }; - "/media-buy-create": { + '/media-buy-create': { /** * Create media buy * @description Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. @@ -338,84 +349,84 @@ export interface paths { * * **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. */ - post: operations["media_buy_create"]; + post: operations['media_buy_create']; }; - "/media-buy-get": { + '/media-buy-get': { /** * Get media buy * @description Get detailed information about a specific media buy. */ - post: operations["media_buy_get"]; + post: operations['media_buy_get']; }; - "/media-buy-update": { + '/media-buy-update': { /** * Update media buy * @description Update an existing media buy's configuration. */ - post: operations["media_buy_update"]; + post: operations['media_buy_update']; }; - "/media-buy-delete": { + '/media-buy-delete': { /** * Delete media buy * @description โš ๏ธ DANGER - Permanently delete a media buy. */ - post: operations["media_buy_delete"]; + post: operations['media_buy_delete']; }; - "/media-buy-execute": { + '/media-buy-execute': { /** * Execute media buy * @description Execute a media buy by deploying it to the publisher platform. */ - post: operations["media_buy_execute"]; + post: operations['media_buy_execute']; }; - "/notifications-list": { + '/notifications-list': { /** * List notifications * @description List notifications for the authenticated user. */ - post: operations["notifications_list"]; + post: operations['notifications_list']; }; - "/notifications-mark-read": { + '/notifications-mark-read': { /** * Mark notification as read * @description Mark a specific notification as read. */ - post: operations["notifications_mark_read"]; + post: operations['notifications_mark_read']; }; - "/notifications-mark-acknowledged": { + '/notifications-mark-acknowledged': { /** * Mark notification as acknowledged * @description Mark a specific notification as acknowledged. */ - post: operations["notifications_mark_acknowledged"]; + post: operations['notifications_mark_acknowledged']; }; - "/notifications-mark-all-read": { + '/notifications-mark-all-read': { /** * Mark all notifications as read * @description Mark all notifications as read for the authenticated user. */ - post: operations["notifications_mark_all_read"]; + post: operations['notifications_mark_all_read']; }; - "/media-product-list": { + '/media-product-list': { /** * List media products * @description List available media products from publishers. */ - post: operations["media_product_list"]; + post: operations['media_product_list']; }; - "/media-product-discover": { + '/media-product-discover': { /** * Discover media products * @description Discover new media products from connected publishers. */ - post: operations["media_product_discover"]; + post: operations['media_product_discover']; }; - "/media-product-sync": { + '/media-product-sync': { /** * Sync media products * @description Synchronize media product inventory with publisher systems. */ - post: operations["media_product_sync"]; + post: operations['media_product_sync']; }; } @@ -423,6 +434,51 @@ export type webhooks = Record; export interface components { schemas: { + AssetUpload: { + /** + * @description **REQUIRED**: Original filename + * @example logo.png + */ + name: string; + /** + * @description **REQUIRED**: MIME type + * @example image/png + * @enum {string} + */ + contentType: + | 'image/png' + | 'image/jpeg' + | 'image/jpg' + | 'image/gif' + | 'image/webp' + | 'video/mp4' + | 'video/webm' + | 'audio/mp3' + | 'audio/wav' + | 'font/woff' + | 'font/woff2'; + /** + * Format: byte + * @description **REQUIRED**: Base64-encoded file data (without data:image/png;base64, prefix) + * @example iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg== + */ + data: string; + /** + * @description **REQUIRED**: Type of asset. Must be one of: image, video, audio, logo, font + * @example image + * @enum {string} + */ + assetType: 'image' | 'video' | 'audio' | 'logo' | 'font'; + /** + * @description Optional tags for organization + * @example [ + * "brand", + * "header", + * 2024 + * ] + */ + tags?: string[]; + }; Budget: { /** @description Total budget amount in cents (e.g., 5000000 = $50,000) */ total: number; @@ -430,14 +486,14 @@ export interface components { * @description Budget currency * @enum {string} */ - currency: "USD" | "EUR" | "GBP" | "CAD" | "AUD"; + currency: 'USD' | 'EUR' | 'GBP' | 'CAD' | 'AUD'; /** @description Daily spending limit in cents */ dailyCap?: number; /** * @description Budget pacing tactic * @enum {string} */ - pacing?: "even" | "accelerated" | "front_loaded"; + pacing?: 'even' | 'accelerated' | 'front_loaded'; }; ScoringWeights: { /** @description Weight for affinity scoring (0-1) */ @@ -472,8 +528,8 @@ export interface components { * @description Campaign status * @enum {string} */ - status: "active" | "paused" | "completed" | "draft"; - budget?: components["schemas"]["Budget"]; + status: 'active' | 'paused' | 'completed' | 'draft'; + budget?: components['schemas']['Budget']; /** @description Associated synthetic audience IDs */ audienceIds?: string[]; /** @description Associated creative asset IDs */ @@ -492,7 +548,7 @@ export interface components { * @description Creative asset type * @enum {string} */ - type: "video" | "image" | "native" | "html5"; + type: 'video' | 'image' | 'native' | 'html5'; /** * Format: uri * @description Creative asset URL @@ -524,14 +580,22 @@ export interface components { * @description Activity type (always AMP) * @enum {string} */ - activityType: "AMP"; + activityType: 'AMP'; /** * @description Tactic type * @enum {string} */ - tacticType: "INTELLIGENT_CAMPAIGNS"; + tacticType: 'INTELLIGENT_CAMPAIGNS'; /** @description Target channels (official codes) */ - channelCodes?: ("DIGITAL-AUDIO" | "DISPLAY-WEB" | "DISPLAY-APP" | "CTV-BVOD" | "OLV" | "DOOH" | "SOCIAL")[]; + channelCodes?: ( + | 'DIGITAL-AUDIO' + | 'DISPLAY-WEB' + | 'DISPLAY-APP' + | 'CTV-BVOD' + | 'OLV' + | 'DOOH' + | 'SOCIAL' + )[]; /** @description Target countries */ countryCodes?: string[]; /** Format: date-time */ @@ -572,7 +636,7 @@ export interface components { /** @description Successful tool execution */ ToolResponse: { content: { - "application/json": { + 'application/json': { /** @description Whether the operation succeeded */ success?: boolean; /** @description Human-readable response message */ @@ -585,7 +649,7 @@ export interface components { /** @description Bad request - invalid parameters */ BadRequest: { content: { - "application/json": { + 'application/json': { /** @description Error message */ error?: string; /** @description Additional error details */ @@ -596,7 +660,7 @@ export interface components { /** @description Unauthorized - invalid or missing authentication */ Unauthorized: { content: { - "application/json": { + 'application/json': { /** @description Error message */ error?: string; }; @@ -605,7 +669,7 @@ export interface components { /** @description Resource not found */ NotFound: { content: { - "application/json": { + 'application/json': { /** @description Error message */ error?: string; }; @@ -614,7 +678,7 @@ export interface components { /** @description Internal server error */ InternalError: { content: { - "application/json": { + 'application/json': { /** @description Error message */ error?: string; }; @@ -632,44 +696,35 @@ export type $defs = Record; export type external = Record; export interface operations { - /** * Upload creative assets - * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. Accepts base64-encoded file data and returns signed URLs (valid for 1 hour). + * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. + * + * **REQUIRED FIELDS:** + * - `brandAgentId`: Brand agent ID for file organization + * - `assets`: Array of assets (each with name, contentType, data, assetType) + * + * Returns signed URLs valid for 1 hour. */ asset_upload: { requestBody: { content: { - "application/json": { - /** @description Brand agent ID for file organization */ + 'application/json': { + /** + * @description **REQUIRED**: Brand agent ID for file organization (e.g., brand_agent_123) + * @example brand_agent_abc123 + */ brandAgentId: string; - /** @description Array of assets to upload */ - assets: ({ - /** @description Original filename */ - name: string; - /** @description MIME type (e.g., image/png, video/mp4) */ - contentType: string; - /** - * Format: byte - * @description Base64-encoded file data - */ - data: string; - /** - * @description Type of asset - * @enum {string} - */ - assetType: "image" | "video" | "audio" | "logo" | "font"; - /** @description Optional tags for organization */ - tags?: string[]; - })[]; + /** @description **REQUIRED**: Array of assets to upload. Each asset must have all required fields. */ + assets: components['schemas']['AssetUpload'][]; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -679,16 +734,16 @@ export interface operations { asset_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional brand agent ID to filter assets */ brandAgentId?: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -698,13 +753,13 @@ export interface operations { brand_agent_list: { requestBody: { content: { - "application/json": Record; + 'application/json': Record; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -714,7 +769,7 @@ export interface operations { brand_agent_create: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Name of the brand agent (advertiser account) */ name: string; /** @description Optional description of the brand agent */ @@ -729,10 +784,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -742,17 +797,17 @@ export interface operations { brand_agent_get: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand agent to retrieve */ brandAgentId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -762,7 +817,7 @@ export interface operations { brand_agent_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand agent to update */ brandAgentId: string; /** @description New name for the brand agent */ @@ -775,11 +830,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -789,17 +844,17 @@ export interface operations { brand_agent_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand agent to delete permanently */ brandAgentId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -809,7 +864,7 @@ export interface operations { brand_standards_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional filtering criteria */ where?: { /** @description Filter by name */ @@ -818,9 +873,9 @@ export interface operations { /** @description Optional ordering for results */ orderBy?: { /** @enum {string} */ - id?: "asc" | "desc"; + id?: 'asc' | 'desc'; /** @enum {string} */ - name?: "asc" | "desc"; + name?: 'asc' | 'desc'; }; /** @description Number of records to return (pagination) */ take?: number; @@ -830,9 +885,9 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -842,7 +897,7 @@ export interface operations { brand_standards_create: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand to create standards for */ brandAgentId: string; /** @description Name for the brand standard (optional - defaults to "{Brand Name} Standards") */ @@ -863,10 +918,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -876,17 +931,17 @@ export interface operations { brand_standards_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand standard to delete */ brandStandardId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -896,16 +951,16 @@ export interface operations { brand_story_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand to list brand stories for */ brandAgentId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -915,7 +970,7 @@ export interface operations { brand_story_create: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand to create a brand story for */ brandAgentId: string; /** @description Name for the brand story (e.g., 'Tech Enthusiasts', 'Luxury Shoppers') */ @@ -934,10 +989,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -947,7 +1002,7 @@ export interface operations { brand_story_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand story to update */ brandStoryId: string; /** @description New audience definition prompt */ @@ -956,11 +1011,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -970,17 +1025,17 @@ export interface operations { brand_story_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the brand story to delete */ brandStoryId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -990,14 +1045,14 @@ export interface operations { campaign_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional brand agent ID to filter campaigns */ brandAgentId?: string; /** * @description Optional status filter * @enum {string} */ - status?: "ACTIVE" | "PAUSED" | "ARCHIVED"; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; /** @description Maximum number of campaigns to return (default 100) */ limit?: number; /** @description Number of campaigns to skip for pagination */ @@ -1006,9 +1061,9 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1018,14 +1073,14 @@ export interface operations { campaign_create: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional brand agent ID that will own this campaign */ brandAgentId?: string; /** @description Optional name for the campaign (auto-generated if not provided) */ name?: string; /** @description Natural language description of campaign requirements (e.g., 'Create a video campaign targeting tech enthusiasts with $50k budget') */ prompt: string; - budget?: components["schemas"]["Budget"]; + budget?: components['schemas']['Budget']; /** * Format: date-time * @description Campaign start date (ISO 8601 format) @@ -1036,7 +1091,7 @@ export interface operations { * @description Campaign end date (ISO 8601 format) */ endDate?: string; - scoringWeights?: components["schemas"]["ScoringWeights"]; + scoringWeights?: components['schemas']['ScoringWeights']; /** @description Days for outcome measurement window */ outcomeScoreWindowDays?: number; /** @description Array of segment IDs to associate with campaign */ @@ -1047,20 +1102,25 @@ export interface operations { * @description Campaign visibility setting * @enum {string} */ - visibility?: "PUBLIC" | "PRIVATE"; + visibility?: 'PUBLIC' | 'PRIVATE'; + /** + * @description How the campaign was created + * @enum {string} + */ + creationType?: 'MANUAL' | 'AUTO_SYNC'; /** * @description Initial campaign status * @enum {string} */ - status?: "ACTIVE" | "PAUSED" | "ARCHIVED"; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1070,7 +1130,7 @@ export interface operations { campaign_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the campaign to update */ campaignId: string; /** @description New name for the campaign */ @@ -1081,8 +1141,8 @@ export interface operations { * @description New status for the campaign * @enum {string} */ - status?: "ACTIVE" | "PAUSED" | "ARCHIVED"; - budget?: components["schemas"]["Budget"]; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; + budget?: components['schemas']['Budget']; /** * Format: date-time * @description Campaign start date (ISO 8601 format) @@ -1112,16 +1172,16 @@ export interface operations { * @description Campaign visibility setting * @enum {string} */ - visibility?: "PUBLIC" | "PRIVATE"; + visibility?: 'PUBLIC' | 'PRIVATE'; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1131,7 +1191,7 @@ export interface operations { campaign_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the campaign to delete */ campaignId: string; /** @description If true, permanently delete the campaign. Default false (soft delete/archive) */ @@ -1140,10 +1200,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1153,17 +1213,17 @@ export interface operations { campaign_get_summary: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the campaign to retrieve */ campaignId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1173,7 +1233,7 @@ export interface operations { campaign_list_strategies: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the campaign to list tactics for */ campaignId: string; /** @description Include archived tactics (defaults to false) */ @@ -1182,10 +1242,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1195,7 +1255,7 @@ export interface operations { campaign_validate_brief: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Campaign brief to validate */ brief: string; /** @description Optional brand agent ID for context-aware validation */ @@ -1209,10 +1269,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1222,13 +1282,13 @@ export interface operations { channel_list: { requestBody: { content: { - "application/json": Record; + 'application/json': Record; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1238,60 +1298,95 @@ export interface operations { creative_list: { requestBody: { content: { - "application/json": { - /** @description Optional brand agent ID to filter creatives */ - brandAgentId?: string; - /** @description Optional campaign ID to filter creatives */ - campaignId?: string; + 'application/json': { + /** @description Optional internal brand agent ID to filter creatives */ + brandAgentId?: number; + /** @description Optional internal campaign ID to filter creatives */ + campaignId?: number; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** * Create creative * @description Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. + * + * **Two workflows supported:** + * 1. **Separate upload**: Use asset_upload first, then reference asset IDs in content.assetIds + * 2. **Inline upload**: Upload assets directly in the `assets` array (automatically uploaded and linked) */ creative_create: { requestBody: { content: { - "application/json": { - /** @description Internal database ID of the brand agent that will own this creative */ + 'application/json': { + /** + * @description **REQUIRED**: Internal database ID of the brand agent that will own this creative + * @example 1 + */ brandAgentId: number; /** @description Optional internal database ID of the organization */ organizationId?: number; - /** @description Name for the creative */ + /** + * @description **REQUIRED**: Name for the creative + * @example Banner Ad 970x250 + */ name: string; - /** @description Optional description of the creative */ + /** + * @description Optional description of the creative + * @example Display banner for homepage + */ description?: string; /** * @description Format source type + * @example ADCP * @enum {string} */ - formatSource?: "ADCP" | "CREATIVE_AGENT" | "PUBLISHER"; - /** @description Format identifier (e.g., "video/mp4", "display/banner") */ + formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; + /** + * @description Format identifier (e.g., "display_970x250", "video/mp4") + * @example display_970x250 + */ formatId?: string; - /** @description URL to the creative media file (video, image, etc.) */ + /** + * @description URL to the creative media file (video, image, etc.) + * @example https://example.com/banner.png + */ mediaUrl?: string; - /** @description Creative content as JSON. Can include assetIds (array of asset IDs from asset_upload), htmlSnippet, vastTag, etc. */ + /** @description Optional: Upload assets inline with the creative. Automatically uploaded to GCS and linked. */ + assets?: components['schemas']['AssetUpload'][]; + /** @description Creative content as JSON. Can include assetIds (existing or from inline upload), htmlSnippet, vastTag, etc. */ content?: { - /** @description Array of asset IDs uploaded via asset_upload tool */ + /** + * @description Array of existing asset IDs (from previous asset_upload). Inline uploaded assets are automatically added to this. + * @example [ + * "asset_abc123", + * "asset_def456" + * ] + */ assetIds?: string[]; - /** @description HTML5 creative snippet */ + /** + * @description HTML5 creative snippet + * @example
Ad content
+ */ htmlSnippet?: string; /** @description VAST XML tag for video ads */ vastTag?: string; }; /** * @description Assembly method + * @example ACTIVATION * @enum {string} */ - assemblyMethod?: "CREATIVE_AGENT" | "ACTIVATION" | "PUBLISHER"; - /** @description Optional internal database ID of campaign to assign creative to */ + assemblyMethod?: 'CREATIVE_AGENT' | 'ACTIVATION' | 'PUBLISHER'; + /** + * @description Optional internal database ID of campaign to assign creative to + * @example 1 + */ campaignId?: number; }; }; @@ -1300,26 +1395,28 @@ export interface operations { /** @description Creative created successfully */ 200: { content: { - "application/json": { + 'application/json': { /** @example true */ success?: boolean; /** - * @description Success message with creative details including creativeId (external string ID for use in media_buy_create/update) and internal ID + * @description Success message with creative details including creativeId (external string ID for use in media_buy_create/update), internal ID, and uploaded assets (if any) * @example โœ… **Creative Created Successfully!** * * **Creative ID:** newcreativevideo_xntthe4w (use this for media_buy_create/update) * **Internal ID:** 16 * **Name:** My Creative * **Status:** PENDING + * **Assets Uploaded:** 2 + * **Asset IDs:** asset_abc123, asset_def456 * **Created:** 2025-10-14T00:00:00.000Z */ message?: string; }; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1329,17 +1426,17 @@ export interface operations { creative_get: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Internal database ID of the creative to retrieve */ creativeId: number; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1349,7 +1446,7 @@ export interface operations { creative_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Internal database ID of the creative to update */ creativeId: number; /** @description New name for the creative */ @@ -1360,11 +1457,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1374,17 +1471,17 @@ export interface operations { creative_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Internal database ID of the creative to delete */ creativeId: number; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1396,7 +1493,7 @@ export interface operations { creative_assign: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Internal database ID of the creative to assign */ creativeId: number; /** @description Internal database ID of the campaign to assign creative to */ @@ -1408,43 +1505,58 @@ export interface operations { /** @description Creative assigned successfully with auto-sync results */ 200: { content: { - "application/json": { + 'application/json': { content?: { - /** @example text */ - type?: string; - /** - * @description Summary of creative assignment including auto-sync results. - * Shows which sales agents received the creative and their approval status. - */ - text?: string; - }[]; + /** @example text */ + type?: string; + /** + * @description Summary of creative assignment including auto-sync results. + * Shows which sales agents received the creative and their approval status. + */ + text?: string; + }[]; }; }; }; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** * Sync creative with sales agents - * @description Sync a creative's formats and specifications with connected sales agents/publishers. + * @description Sync a creative to sales agents using smart auto-detection or manual specification. + * Features intelligent format matching and recent activity analysis (30-60 day lookback). + * Provides detailed sync status and actionable next steps. */ creative_sync_sales_agents: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Internal database ID of the creative to sync */ creativeId: number; + /** @description Smart auto-detection settings (default behavior) */ + autoDetect?: { + /** @description Look at tactics from past N days (default 30, max 90) */ + daysBack?: number; + /** @description Include agents from active campaigns (default true) */ + includeActive?: boolean; + }; + /** @description Internal database ID - sync to sales agents used by this campaign's tactics only */ + campaignId?: number; + /** @description Request pre-approval before campaign launch (default false) */ + preApproval?: boolean; + /** @description Explicitly specify ADCP agent IDs (overrides auto-detection) */ + adcpAgentIds?: string[]; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1454,13 +1566,13 @@ export interface operations { sales_agent_list: { requestBody: { content: { - "application/json": Record; + 'application/json': Record; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1470,17 +1582,17 @@ export interface operations { sales_agent_get: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the sales agent to retrieve */ salesAgentId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1490,21 +1602,21 @@ export interface operations { sales_agent_register: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Sales agent name */ name: string; /** @description Sales agent endpoint URL */ endpointUrl: string; /** - * @description Protocol type + * @description Protocol for endpoint URL calls * @enum {string} */ - protocol: "REST" | "MCP" | "A2A" | "CUSTOM"; + protocol: 'MCP' | 'A2A'; /** * @description Authentication type * @enum {string} */ - authenticationType: "API_KEY" | "OAUTH" | "NO_AUTH"; + authenticationType: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; /** @description Sales agent description (optional) */ description?: string; /** @description Organization ID (optional - auto-detected from customer if not provided) */ @@ -1515,10 +1627,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1528,17 +1640,17 @@ export interface operations { sales_agent_account_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the sales agent */ salesAgentId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1548,7 +1660,7 @@ export interface operations { sales_agent_account_register: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Sales agent ID */ salesAgentId: string; /** @description Account identifier */ @@ -1559,10 +1671,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1572,7 +1684,7 @@ export interface operations { sales_agent_unregister: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the sales agent to unregister */ salesAgentId: string; /** @description Must be true to confirm this destructive operation */ @@ -1581,10 +1693,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1594,7 +1706,7 @@ export interface operations { sales_agent_account_unregister: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the sales agent to unregister your account from */ salesAgentId: string; /** @description Must be true to confirm this destructive operation */ @@ -1603,10 +1715,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1616,7 +1728,7 @@ export interface operations { sales_agent_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the sales agent to update */ salesAgentId: string; /** @description New name */ @@ -1629,23 +1741,23 @@ export interface operations { * @description New protocol * @enum {string} */ - protocol?: "REST" | "MCP" | "A2A" | "CUSTOM"; + protocol?: 'REST' | 'MCP' | 'A2A' | 'CUSTOM'; /** * @description New authentication type * @enum {string} */ - authenticationType?: "API_KEY" | "OAUTH" | "NO_AUTH"; + authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; /** @description Authentication configuration for the sales agent */ authConfig?: Record; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1655,7 +1767,7 @@ export interface operations { sales_agent_account_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the sales agent */ salesAgentId: string; /** @description Account identifier to update */ @@ -1666,11 +1778,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1680,7 +1792,7 @@ export interface operations { strategy_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional campaign ID to filter tactics */ campaignId?: string; /** @description Include archived tactics (defaults to false) */ @@ -1689,9 +1801,9 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1701,7 +1813,7 @@ export interface operations { strategy_create: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Name of the tactic */ name: string; /** @description Campaign ID to link this tactic to (required) */ @@ -1709,17 +1821,25 @@ export interface operations { /** @description Optional tactical brief or prompt for this tactic */ prompt?: string; /** @description Valid channel codes to target (also accepts friendly aliases like audio, web, app, ctv, video which are automatically mapped) */ - channelCodes?: ("DIGITAL-AUDIO" | "DISPLAY-WEB" | "DISPLAY-APP" | "CTV-BVOD" | "OLV" | "DOOH" | "SOCIAL")[]; + channelCodes?: ( + | 'DIGITAL-AUDIO' + | 'DISPLAY-WEB' + | 'DISPLAY-APP' + | 'CTV-BVOD' + | 'OLV' + | 'DOOH' + | 'SOCIAL' + )[]; /** @description Country codes to target (2-digit ISO codes) */ countryCodes?: string[]; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1729,17 +1849,17 @@ export interface operations { strategy_get: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the tactic to retrieve */ tacticId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1749,7 +1869,7 @@ export interface operations { strategy_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the tactic to update */ tacticId: string; /** @description New name for the tactic */ @@ -1757,18 +1877,26 @@ export interface operations { /** @description New tactical brief */ prompt?: string; /** @description Updated channel codes (also accepts friendly aliases like audio, web, app, ctv, video) */ - channelCodes?: ("DIGITAL-AUDIO" | "DISPLAY-WEB" | "DISPLAY-APP" | "CTV-BVOD" | "OLV" | "DOOH" | "SOCIAL")[]; + channelCodes?: ( + | 'DIGITAL-AUDIO' + | 'DISPLAY-WEB' + | 'DISPLAY-APP' + | 'CTV-BVOD' + | 'OLV' + | 'DOOH' + | 'SOCIAL' + )[]; /** @description Updated country codes */ countryCodes?: string[]; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1778,17 +1906,17 @@ export interface operations { strategy_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the tactic to delete */ tacticId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1798,7 +1926,7 @@ export interface operations { strategy_link_campaign: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the tactic */ tacticId: string; /** @description ID of the campaign to link */ @@ -1807,11 +1935,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1821,7 +1949,7 @@ export interface operations { strategy_unlink_campaign: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the tactic */ tacticId: string; /** @description ID of the campaign to unlink */ @@ -1830,11 +1958,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1844,7 +1972,7 @@ export interface operations { media_buy_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional tactic ID to filter media buys */ tacticId?: string; /** @description Optional campaign ID to filter media buys */ @@ -1855,9 +1983,9 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1871,7 +1999,7 @@ export interface operations { media_buy_create: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the tactic to execute */ tacticId: string; /** @description Name of the media buy */ @@ -1880,21 +2008,21 @@ export interface operations { description?: string; /** @description Array of products to include in this media buy. At least one product is required. Each product will be validated with its sales agent. */ products: { - /** @description Media product ID from publisher (will be validated with sales agent) */ - mediaProductId: string; - /** @description Sales agent ID for this product */ - salesAgentId: string; - /** @description Budget allocated to this specific product (optional, must not exceed total budget when summed across all products) */ - budgetAmount?: number; - /** @description Currency for this product's budget (defaults to media buy currency) */ - budgetCurrency?: string; - /** @description Base CPM price for this product */ - pricingCpm?: number; - /** @description Additional signal cost for this product */ - pricingSignalCost?: number; - /** @description Optional display order for organizing products */ - displayOrder?: number; - }[]; + /** @description Media product ID from publisher (will be validated with sales agent) */ + mediaProductId: string; + /** @description Sales agent ID for this product */ + salesAgentId: string; + /** @description Budget allocated to this specific product (optional, must not exceed total budget when summed across all products) */ + budgetAmount?: number; + /** @description Currency for this product's budget (defaults to media buy currency) */ + budgetCurrency?: string; + /** @description Base CPM price for this product */ + pricingCpm?: number; + /** @description Additional signal cost for this product */ + pricingSignalCost?: number; + /** @description Optional display order for organizing products */ + displayOrder?: number; + }[]; budget: { /** @description Total budget amount for this media buy */ amount: number; @@ -1906,7 +2034,7 @@ export interface operations { * @description Budget pacing tactic (defaults to even) * @enum {string} */ - pacing?: "asap" | "even" | "front_loaded"; + pacing?: 'asap' | 'even' | 'front_loaded'; }; /** @description Optional array of creative IDs (database IDs) to assign to this media buy. Creatives must be assigned to the campaign associated with this media buy's tactic. */ creativeIds?: string[]; @@ -1914,10 +2042,10 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -1927,17 +2055,17 @@ export interface operations { media_buy_get: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the media buy to retrieve */ mediaBuyId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1947,7 +2075,7 @@ export interface operations { media_buy_update: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the media buy to update */ mediaBuyId: string; /** @description New name */ @@ -1956,7 +2084,7 @@ export interface operations { amount?: number; dailyCap?: number; /** @enum {string} */ - pacing?: "asap" | "even" | "front_loaded"; + pacing?: 'asap' | 'even' | 'front_loaded'; }; /** @description New CPM price */ cpm?: number; @@ -1966,11 +2094,11 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -1980,17 +2108,17 @@ export interface operations { media_buy_delete: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the media buy to delete */ mediaBuyId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -2000,18 +2128,18 @@ export interface operations { media_buy_execute: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the media buy to execute */ mediaBuyId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 400: components["responses"]["BadRequest"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 400: components['responses']['BadRequest']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -2021,7 +2149,7 @@ export interface operations { notifications_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Filter to only unread notifications */ unreadOnly?: boolean; /** @description Maximum number of notifications to return */ @@ -2030,9 +2158,9 @@ export interface operations { }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -2042,17 +2170,17 @@ export interface operations { notifications_mark_read: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the notification to mark as read */ notificationId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -2062,17 +2190,17 @@ export interface operations { notifications_mark_acknowledged: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description ID of the notification to mark as acknowledged */ notificationId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; /** @@ -2082,13 +2210,13 @@ export interface operations { notifications_mark_all_read: { requestBody: { content: { - "application/json": Record; + 'application/json': Record; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -2098,16 +2226,16 @@ export interface operations { media_product_list: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Optional sales agent ID to filter products */ salesAgentId?: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -2117,16 +2245,16 @@ export interface operations { media_product_discover: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Sales agent ID to discover products from */ salesAgentId?: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 500: components['responses']['InternalError']; }; }; /** @@ -2136,17 +2264,17 @@ export interface operations { media_product_sync: { requestBody: { content: { - "application/json": { + 'application/json': { /** @description Sales agent ID to sync products from */ salesAgentId: string; }; }; }; responses: { - 200: components["responses"]["ToolResponse"]; - 401: components["responses"]["Unauthorized"]; - 404: components["responses"]["NotFound"]; - 500: components["responses"]["InternalError"]; + 200: components['responses']['ToolResponse']; + 401: components['responses']['Unauthorized']; + 404: components['responses']['NotFound']; + 500: components['responses']['InternalError']; }; }; } diff --git a/src/types/index.ts b/src/types/index.ts index 74a6672..b275fad 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -4,7 +4,7 @@ export interface ClientConfig { timeout?: number; } -export interface ToolResponse { +export interface ToolResponse { success: boolean; message?: string; data?: T; @@ -12,7 +12,7 @@ export interface ToolResponse { export interface ErrorResponse { error: string; - details?: any; + details?: Record; } export type Environment = 'production' | 'staging'; diff --git a/src/webhook-server.ts b/src/webhook-server.ts index f652fe0..13d6e49 100644 --- a/src/webhook-server.ts +++ b/src/webhook-server.ts @@ -1,10 +1,11 @@ -import express, { Express, Request, Response, NextFunction } from 'express'; +import express from 'express'; +import type { Express, Request, Response, NextFunction } from 'express'; import { Server } from 'http'; -export interface WebhookEvent { +export interface WebhookEvent> { type: string; timestamp: string; - data: any; + data: T; } export type WebhookHandler = (event: WebhookEvent) => Promise | void; From dcca05948c2c11ac5812c6f8fab30ba01e29f108 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 19 Oct 2025 09:15:42 -0400 Subject: [PATCH 08/12] Fix code review issues: enforce strict type checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address critical issues from code review: - Remove unused WebhookEvent import from test file (was breaking lint) - Change ESLint no-explicit-any rule from "warn" to "error" to enforce the no-any policy in CI - Optimize pre-commit hook to only run type-check and tests when TypeScript files are staged (improves performance for non-TS changes) ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .eslintrc.json | 2 +- .husky/pre-commit | 11 ++++++----- src/__tests__/webhook-server.test.ts | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 50c12da..1e53a1d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,7 @@ "sourceType": "module" }, "rules": { - "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/explicit-function-return-type": "off" } } diff --git a/.husky/pre-commit b/.husky/pre-commit index 758c9f5..2f18b09 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,8 +1,9 @@ +#!/bin/sh # Run lint-staged for TypeScript files npx lint-staged -# Type check the entire project -npm run type-check - -# Run tests -npm test +# Only run type-check and tests if TypeScript files were staged +if git diff --cached --name-only | grep -q '\.ts$'; then + npm run type-check + npm test +fi diff --git a/src/__tests__/webhook-server.test.ts b/src/__tests__/webhook-server.test.ts index 7266f09..70d75ed 100644 --- a/src/__tests__/webhook-server.test.ts +++ b/src/__tests__/webhook-server.test.ts @@ -1,4 +1,4 @@ -import { WebhookServer, WebhookEvent } from '../webhook-server'; +import { WebhookServer } from '../webhook-server'; describe('WebhookServer', () => { let server: WebhookServer; From 66a5ba5725115a2a5bf2d91e061403dd643af6ce Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 19 Oct 2025 09:19:40 -0400 Subject: [PATCH 09/12] Add conductor.json for workspace configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure Conductor to run npm install on workspace startup to ensure: - Dependencies are installed - Husky git hooks are set up via prepare script - Development environment is ready Also include helpful script shortcuts for common development tasks. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- conductor.json | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 conductor.json diff --git a/conductor.json b/conductor.json new file mode 100644 index 0000000..1c75bd2 --- /dev/null +++ b/conductor.json @@ -0,0 +1,31 @@ +{ + "name": "Scope3 Agentic Client", + "description": "TypeScript client for Scope3 Agentic API using MCP protocol", + "version": "0.1.0", + "setup": { + "commands": [ + { + "command": "npm install", + "description": "Install dependencies and set up git hooks (Husky)" + } + ] + }, + "scripts": { + "dev": { + "command": "npm run build -- --watch", + "description": "Build in watch mode for development" + }, + "test": { + "command": "npm test", + "description": "Run all tests" + }, + "type-check": { + "command": "npm run type-check", + "description": "Check TypeScript types without building" + }, + "update-schemas": { + "command": "npm run update-schemas", + "description": "Download latest OpenAPI spec and regenerate TypeScript types" + } + } +} From f3093cd1b808039ecc7bf312ef8d785c0b57d411 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 19 Oct 2025 09:30:32 -0400 Subject: [PATCH 10/12] Set up Changesets for versioning and automated NPM publishing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement complete versioning and release automation: - **Changesets configuration**: - Public NPM access for @scope3/agentic-client - GitHub changelog integration - Scripts: changeset, version, release - **CI checks**: - Require changeset on all PRs to main - Clear error message with instructions if missing - **Automated publishing**: - Release workflow on main branch - Creates "Version Packages" PR when changesets are merged - Auto-publishes to NPM when version PR is merged - Requires NPM_TOKEN secret in GitHub - **Documentation**: Added Contributing section with: - How to create changesets - Release process workflow - CI requirements and bypass instructions ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .changeset/README.md | 8 + .changeset/config.json | 11 + .github/workflows/changeset.yml | 36 ++ .github/workflows/release.yml | 42 ++ README.md | 39 ++ package-lock.json | 926 +++++++++++++++++++++++++++++++- package.json | 7 +- 7 files changed, 1050 insertions(+), 19 deletions(-) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .github/workflows/changeset.yml create mode 100644 .github/workflows/release.yml diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..e5b6d8d --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..565aa60 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", + "changelog": ["@changesets/changelog-github", { "repo": "scope3data/agentic-client" }], + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml new file mode 100644 index 0000000..c0c2384 --- /dev/null +++ b/.github/workflows/changeset.yml @@ -0,0 +1,36 @@ +name: Changeset Check + +on: + pull_request: + branches: + - main + +jobs: + changeset-check: + name: Check for Changeset + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: npm ci + + - name: Check for changeset + run: | + if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README)" ]; then + echo "โŒ No changeset found. Please add a changeset by running 'npm run changeset'" + echo "" + echo "Changesets help track version changes and generate changelogs." + echo "Run 'npm run changeset' and follow the prompts to create one." + exit 1 + else + echo "โœ… Changeset found" + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..d8bb2f0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,42 @@ +name: Release + +on: + push: + branches: + - main + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@v1 + with: + publish: npm run release + version: npm run version + commit: 'chore: version packages' + title: 'chore: version packages' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/README.md b/README.md index 7f88007..6d5b17d 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,45 @@ npm run update-schemas This downloads the latest OpenAPI spec and regenerates TypeScript types. +## Contributing + +### Versioning and Releases + +This project uses [Changesets](https://github.com/changesets/changesets) for version management and automated NPM publishing. + +#### Creating a Changeset + +When making changes that should be released, add a changeset: + +```bash +npm run changeset +``` + +Follow the prompts to: +1. Select the type of change (major, minor, patch) +2. Describe the changes for the changelog + +The changeset file will be committed with your PR. + +#### Release Process + +When a PR with changesets is merged to `main`: +1. The Release workflow creates a "Version Packages" PR +2. This PR updates package versions and generates changelogs +3. When the Version PR is merged, packages are automatically published to NPM + +**NPM Publishing:** Packages are published as `@scope3/agentic-client` with public access. + +#### CI Requirements + +Every PR to `main` must include a changeset. The CI will fail if no changeset is detected. + +To bypass this check (for docs/config changes), create an empty changeset: +```bash +npm run changeset +# Select "patch" and leave the description empty +``` + ## Examples See the `examples/` directory for more usage examples: diff --git a/package-lock.json b/package-lock.json index b3d3c00..56a5aa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,8 @@ "express": "^4.18.0" }, "devDependencies": { + "@changesets/changelog-github": "^0.5.1", + "@changesets/cli": "^2.29.7", "@types/express": "^4.17.0", "@types/jest": "^29.5.0", "@types/node": "^20.0.0", @@ -489,6 +491,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -544,6 +556,364 @@ "dev": true, "license": "MIT" }, + "node_modules/@changesets/apply-release-plan": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.13.tgz", + "integrity": "sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/config": "^3.1.1", + "@changesets/get-version-range-type": "^0.4.0", + "@changesets/git": "^3.0.4", + "@changesets/should-skip-package": "^0.1.2", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "detect-indent": "^6.0.0", + "fs-extra": "^7.0.1", + "lodash.startcase": "^4.4.0", + "outdent": "^0.5.0", + "prettier": "^2.7.1", + "resolve-from": "^5.0.0", + "semver": "^7.5.3" + } + }, + "node_modules/@changesets/apply-release-plan/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/@changesets/apply-release-plan/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@changesets/assemble-release-plan": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.9.tgz", + "integrity": "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/errors": "^0.2.0", + "@changesets/get-dependents-graph": "^2.1.3", + "@changesets/should-skip-package": "^0.1.2", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "semver": "^7.5.3" + } + }, + "node_modules/@changesets/changelog-git": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz", + "integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/types": "^6.1.0" + } + }, + "node_modules/@changesets/changelog-github": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@changesets/changelog-github/-/changelog-github-0.5.1.tgz", + "integrity": "sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/get-github-info": "^0.6.0", + "@changesets/types": "^6.1.0", + "dotenv": "^8.1.0" + } + }, + "node_modules/@changesets/cli": { + "version": "2.29.7", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.7.tgz", + "integrity": "sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/apply-release-plan": "^7.0.13", + "@changesets/assemble-release-plan": "^6.0.9", + "@changesets/changelog-git": "^0.2.1", + "@changesets/config": "^3.1.1", + "@changesets/errors": "^0.2.0", + "@changesets/get-dependents-graph": "^2.1.3", + "@changesets/get-release-plan": "^4.0.13", + "@changesets/git": "^3.0.4", + "@changesets/logger": "^0.1.1", + "@changesets/pre": "^2.0.2", + "@changesets/read": "^0.6.5", + "@changesets/should-skip-package": "^0.1.2", + "@changesets/types": "^6.1.0", + "@changesets/write": "^0.4.0", + "@inquirer/external-editor": "^1.0.0", + "@manypkg/get-packages": "^1.1.3", + "ansi-colors": "^4.1.3", + "ci-info": "^3.7.0", + "enquirer": "^2.4.1", + "fs-extra": "^7.0.1", + "mri": "^1.2.0", + "p-limit": "^2.2.0", + "package-manager-detector": "^0.2.0", + "picocolors": "^1.1.0", + "resolve-from": "^5.0.0", + "semver": "^7.5.3", + "spawndamnit": "^3.0.1", + "term-size": "^2.1.0" + }, + "bin": { + "changeset": "bin.js" + } + }, + "node_modules/@changesets/cli/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@changesets/cli/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@changesets/config": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.1.tgz", + "integrity": "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/errors": "^0.2.0", + "@changesets/get-dependents-graph": "^2.1.3", + "@changesets/logger": "^0.1.1", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "fs-extra": "^7.0.1", + "micromatch": "^4.0.8" + } + }, + "node_modules/@changesets/errors": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz", + "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==", + "dev": true, + "license": "MIT", + "dependencies": { + "extendable-error": "^0.1.5" + } + }, + "node_modules/@changesets/get-dependents-graph": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.3.tgz", + "integrity": "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "picocolors": "^1.1.0", + "semver": "^7.5.3" + } + }, + "node_modules/@changesets/get-github-info": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.6.0.tgz", + "integrity": "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dataloader": "^1.4.0", + "node-fetch": "^2.5.0" + } + }, + "node_modules/@changesets/get-release-plan": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.13.tgz", + "integrity": "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/assemble-release-plan": "^6.0.9", + "@changesets/config": "^3.1.1", + "@changesets/pre": "^2.0.2", + "@changesets/read": "^0.6.5", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3" + } + }, + "node_modules/@changesets/get-version-range-type": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz", + "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@changesets/git": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz", + "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/errors": "^0.2.0", + "@manypkg/get-packages": "^1.1.3", + "is-subdir": "^1.1.1", + "micromatch": "^4.0.8", + "spawndamnit": "^3.0.1" + } + }, + "node_modules/@changesets/logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", + "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.0" + } + }, + "node_modules/@changesets/parse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.1.tgz", + "integrity": "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/types": "^6.1.0", + "js-yaml": "^3.13.1" + } + }, + "node_modules/@changesets/parse/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@changesets/parse/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@changesets/pre": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz", + "integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/errors": "^0.2.0", + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3", + "fs-extra": "^7.0.1" + } + }, + "node_modules/@changesets/read": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.5.tgz", + "integrity": "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/git": "^3.0.4", + "@changesets/logger": "^0.1.1", + "@changesets/parse": "^0.4.1", + "@changesets/types": "^6.1.0", + "fs-extra": "^7.0.1", + "p-filter": "^2.1.0", + "picocolors": "^1.1.0" + } + }, + "node_modules/@changesets/should-skip-package": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz", + "integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/types": "^6.1.0", + "@manypkg/get-packages": "^1.1.3" + } + }, + "node_modules/@changesets/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz", + "integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@changesets/write": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz", + "integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@changesets/types": "^6.1.0", + "fs-extra": "^7.0.1", + "human-id": "^4.1.1", + "prettier": "^2.7.1" + } + }, + "node_modules/@changesets/write/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", @@ -703,6 +1073,45 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1130,36 +1539,164 @@ "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@manypkg/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.5.5", + "@types/node": "^12.7.1", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0" + } + }, + "node_modules/@manypkg/find-root/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@manypkg/find-root/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@manypkg/find-root/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@manypkg/find-root/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@manypkg/find-root/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@manypkg/find-root/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@manypkg/get-packages": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", + "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "@babel/runtime": "^7.5.5", + "@changesets/types": "^4.0.1", + "@manypkg/find-root": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "^11.0.0", + "read-yaml-file": "^1.1.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", + "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", "dev": true, "license": "MIT" }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "node_modules/@manypkg/get-packages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" } }, "node_modules/@modelcontextprotocol/sdk": { @@ -2283,6 +2820,19 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "node_modules/better-path-resolve": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", + "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-windows": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -2515,6 +3065,13 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", + "dev": true, + "license": "MIT" + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -2794,6 +3351,13 @@ "node": ">= 8" } }, + "node_modules/dataloader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", + "integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2862,6 +3426,16 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2908,6 +3482,16 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2964,6 +3548,20 @@ "node": ">= 0.8" } }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/environment": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", @@ -3398,6 +3996,13 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/extendable-error": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", + "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3583,6 +4188,21 @@ "node": ">= 0.6" } }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3908,6 +4528,16 @@ "node": ">= 0.8" } }, + "node_modules/human-id": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.2.tgz", + "integrity": "sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==", + "dev": true, + "license": "MIT", + "bin": { + "human-id": "dist/cli.js" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4135,6 +4765,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-subdir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", + "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "better-path-resolve": "1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4868,6 +5521,16 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5250,6 +5913,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -5596,6 +6266,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5625,6 +6305,27 @@ "dev": true, "license": "MIT" }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -5769,6 +6470,26 @@ "node": ">= 0.8.0" } }, + "node_modules/outdent": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", + "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -5801,6 +6522,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -5811,6 +6542,16 @@ "node": ">=6" } }, + "node_modules/package-manager-detector": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", + "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quansync": "^0.2.7" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5937,6 +6678,16 @@ "node": ">=0.10" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pirates": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", @@ -6147,6 +6898,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6199,6 +6967,56 @@ "dev": true, "license": "MIT" }, + "node_modules/read-yaml-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", + "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.5", + "js-yaml": "^3.6.1", + "pify": "^4.0.1", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-yaml-file/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/read-yaml-file/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/read-yaml-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -6693,6 +7511,30 @@ "source-map": "^0.6.0" } }, + "node_modules/spawndamnit": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-3.0.1.tgz", + "integrity": "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==", + "dev": true, + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "cross-spawn": "^7.0.5", + "signal-exit": "^4.0.1" + } + }, + "node_modules/spawndamnit/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6843,6 +7685,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -6918,6 +7773,13 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -7094,6 +7956,16 @@ "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7186,6 +8058,24 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 77f5c7e..648238f 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,10 @@ "generate-types": "openapi-typescript openapi.yaml -o src/types/api.ts", "update-schemas": "curl -f -o openapi.yaml https://docs.agentic.scope3.com/openapi.yaml && npm run generate-types", "prepare": "husky", - "pretest": "npm run type-check" + "pretest": "npm run type-check", + "changeset": "changeset", + "version": "changeset version", + "release": "npm run build && changeset publish" }, "keywords": [ "scope3", @@ -30,6 +33,8 @@ "express": "^4.18.0" }, "devDependencies": { + "@changesets/changelog-github": "^0.5.1", + "@changesets/cli": "^2.29.7", "@types/express": "^4.17.0", "@types/jest": "^29.5.0", "@types/node": "^20.0.0", From a5687faa5ac6d452e1a2b4db7c324f71635422cd Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 19 Oct 2025 09:33:19 -0400 Subject: [PATCH 11/12] Add changeset for initial release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare for v0.1.0 release with full feature set. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .changeset/initial-release.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .changeset/initial-release.md diff --git a/.changeset/initial-release.md b/.changeset/initial-release.md new file mode 100644 index 0000000..eaa4856 --- /dev/null +++ b/.changeset/initial-release.md @@ -0,0 +1,13 @@ +--- +"@scope3/agentic-client": minor +--- + +Initial release of Scope3 Agentic Client + +- Full TypeScript client for Scope3 Agentic API using MCP protocol +- Complete API coverage for all 12 resource modules (Assets, Brand Agents, Campaigns, Creatives, etc.) +- Official MCP SDK integration with HTTP streaming transport +- Comprehensive type safety with auto-generated types from OpenAPI spec +- Optional webhook server for AdCP events +- Pre-commit hooks and CI validation +- Automated versioning and NPM publishing with Changesets From cbb19ec490f000de881326f17b0c3d75d48be52f Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 20 Oct 2025 13:14:07 -0400 Subject: [PATCH 12/12] Update schemas from upstream API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sync with latest OpenAPI spec from https://docs.agentic.scope3.com/openapi.yaml Major changes: - Explicit MCP protocol endpoints documented (mcp-initialize, etc.) - Enhanced tool descriptions and parameter documentation - Server URLs now include /mcp path - Auto-generated from TypeScript schemas The MCP SDK already handles protocol initialization automatically, so no client code changes required. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- openapi.yaml | 8723 +++++++++++++++++++++++++++++++++++++--------- src/types/api.ts | 5735 ++++++++++++++++++++++-------- 2 files changed, 11309 insertions(+), 3149 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index 55b70d4..1c3b72d 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1,273 +1,500 @@ +# This OpenAPI specification is auto-generated from TypeScript Schemas +# DO NOT EDIT THIS FILE MANUALLY + openapi: 3.0.0 info: - title: Jackson Agentic API + title: Scope3 Agentic API version: 1.0.0 - description: | - Comprehensive API for the Jackson Agentic Advertising Platform. - This API provides tools for managing brand agents, campaigns, creatives, tactics, - media buys, and more through natural language interfaces and structured endpoints. + description: >- + Comprehensive API for the Scope3 Agentic Advertising Platform. + This API provides tools for managing brand agents, campaigns, creatives, tactics, media buys, and more through + natural language interfaces and structured endpoints. servers: - - url: https://api.agentic.scope3.com + - url: https://api.agentic.scope3.com/mcp description: Production server - - url: https://api.agentic.staging.scope3.com + - url: https://api.agentic.staging.scope3.com/mcp description: Staging server - -security: - - bearerAuth: [] - -tags: - - name: Assets - description: Upload and manage creative assets - - name: Brand Agents - description: Manage brand agent (advertiser) accounts - - name: Brand Standards - description: Manage brand safety standards and rules - - name: Brand Stories - description: AI-powered audience definitions - - name: Campaigns - description: Campaign creation and management - - name: Channels - description: Advertising channel management - - name: Creatives - description: Creative asset management - - name: Sales Agents - description: Publisher/sales agent registration - - name: Tactics - description: Media buying tactics - - name: Media Buys - description: Media buy execution and management - - name: Notifications - description: System notifications - - name: Products - description: Media product management - paths: - /asset-upload: + /mcp-initialize: post: - tags: [Assets] - summary: Upload creative assets - operationId: asset_upload - description: | - Upload creative assets (images, videos, audio) to Google Cloud Storage. - - **REQUIRED FIELDS:** - - `brandAgentId`: Brand agent ID for file organization - - `assets`: Array of assets (each with name, contentType, data, assetType) - - Returns signed URLs valid for 1 hour. + operationId: mcp_initialize + summary: Initialize MCP session + description: >- + Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as + a UUID and included in the mcp-session-id header for all subsequent requests. + tags: + - MCP + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: MCP session identifier (UUID). Generate a new UUID for session initialization. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId, assets] properties: - brandAgentId: + jsonrpc: type: string - description: '**REQUIRED**: Brand agent ID for file organization (e.g., brand_agent_123)' - example: brand_agent_abc123 - assets: - type: array - description: '**REQUIRED**: Array of assets to upload. Each asset must have all required fields.' - minItems: 1 - items: - $ref: '#/components/schemas/AssetUpload' - responses: - '200': - $ref: '#/components/responses/ToolResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalError' - - /asset-list: - post: - tags: [Assets] - summary: List creative assets - operationId: asset_list - description: List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - brandAgentId: + enum: + - '2.0' + id: + oneOf: + - type: string + - type: number + method: type: string - description: Optional brand agent ID to filter assets + enum: + - initialize + params: + type: object + properties: + protocolVersion: + type: string + example: '2024-11-05' + capabilities: + type: object + clientInfo: + type: object + properties: + name: + type: string + version: + type: string + required: + - name + - version + required: + - protocolVersion + - capabilities + - clientInfo + required: + - jsonrpc + - id + - method + - params responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Session initialized successfully + content: + application/json: + schema: + type: object + properties: + jsonrpc: + type: string + enum: + - '2.0' + id: + oneOf: + - type: string + - type: number + result: + type: object + properties: + protocolVersion: + type: string + capabilities: + type: object + serverInfo: + type: object + properties: + name: + type: string + version: + type: string '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalError' - + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' /brand-agent-list: post: - tags: [Brand Agents] - summary: List brand agents operationId: brand_agent_list - description: List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. + summary: List brand agents + description: >- + List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no + parameters required. + tags: + - Brand Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - properties: {} + properties: + tool: + type: string + enum: + - brand_agent_list + arguments: + $ref: '#/components/schemas/ListBrandAgentsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandAgentList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-agent-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-agent-get: post: - tags: [Brand Agents] - summary: Create brand agent - operationId: brand_agent_create - description: Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + operationId: brand_agent_get + summary: Get brand agent + description: Get detailed information about a specific brand agent (advertiser account) by ID. + tags: + - Brand Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [name] properties: - name: + tool: type: string - description: Name of the brand agent (advertiser account) - description: - type: string - description: Optional description of the brand agent - nickname: - type: string - description: Friendly name for easy identification (e.g., 'Nike' for 'Nike c/o Kinesso') - externalId: - type: string - description: Your internal ID for this brand agent (e.g., client code or account ID) - advertiserDomains: - type: array - items: - type: string - description: Domains where users will be sent from all campaigns/creatives + enum: + - brand_agent_get + arguments: + $ref: '#/components/schemas/GetBrandAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandAgentUpdateOutput' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-agent-get: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-agent-create: post: - tags: [Brand Agents] - summary: Get brand agent - operationId: brand_agent_get - description: Get detailed information about a specific brand agent (advertiser account) by ID. + operationId: brand_agent_create + summary: Create brand agent + description: >- + Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, + creatives, audiences, standards, and measurement sources. + tags: + - Brand Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId] properties: - brandAgentId: + tool: type: string - description: ID of the brand agent to retrieve + enum: + - brand_agent_create + arguments: + $ref: '#/components/schemas/CreateBrandAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandAgentUpdateOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' /brand-agent-update: post: - tags: [Brand Agents] - summary: Update brand agent operationId: brand_agent_update - description: Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. + summary: Update brand agent + description: Update an existing brand agent with new information. + tags: + - Brand Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId] properties: - brandAgentId: - type: string - description: ID of the brand agent to update - name: - type: string - description: New name for the brand agent - description: + tool: type: string - description: New description for the brand agent - tacticSeedDataCoop: - type: boolean - description: Enable/disable tactic seed data cooperative participation + enum: + - brand_agent_update + arguments: + $ref: '#/components/schemas/UpdateBrandAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandAgentUpdateOutput' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' /brand-agent-delete: post: - tags: [Brand Agents] - summary: Delete brand agent operationId: brand_agent_delete - description: โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. + summary: Delete brand agent + description: Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. + tags: + - Brand Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId] properties: - brandAgentId: + tool: type: string - description: ID of the brand agent to delete permanently + enum: + - brand_agent_delete + arguments: + $ref: '#/components/schemas/DeleteBrandAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandAgentDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-standards-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-list: post: - tags: [Brand Standards] - summary: List brand standards - operationId: brand_standards_list - description: List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. + operationId: campaign_list + summary: List campaigns + description: List all campaigns with optional filtering by brand agent. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -275,261 +502,427 @@ paths: schema: type: object properties: - where: - type: object - description: Optional filtering criteria - properties: - name: - type: string - description: Filter by name - orderBy: - type: object - description: Optional ordering for results - properties: - id: - type: string - enum: [asc, desc] - name: - type: string - enum: [asc, desc] - take: - type: number - description: Number of records to return (pagination) - skip: - type: number - description: Number of records to skip (pagination) + tool: + type: string + enum: + - campaign_list + arguments: + $ref: '#/components/schemas/ListCampaignsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-standards-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-create: post: - tags: [Brand Standards] - summary: Create brand standard - operationId: brand_standards_create - description: Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. + operationId: campaign_create + summary: Create campaign + description: >- + Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, + budget, and creative requirements. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId, prompt] properties: - brandAgentId: - type: string - description: ID of the brand to create standards for - name: + tool: type: string - description: Name for the brand standard (optional - defaults to "{Brand Name} Standards") - prompt: - type: string - description: Natural language prompt defining the brand safety standards, content restrictions, and enforcement rules - description: - type: string - description: Description for the brand standard - isArchived: - type: boolean - description: Whether to create the standard as archived - countries: - type: array - items: - type: string - description: List of country codes to target (e.g., ['US', 'CA']) - channels: - type: array - items: - type: string - description: List of channels to target (e.g., ['web', 'social']) - brands: - type: array - items: - type: string - description: List of specific brands this applies to + enum: + - campaign_create + arguments: + $ref: '#/components/schemas/CreateCampaignInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignUpdateOutput' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-standards-delete: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-get: post: - tags: [Brand Standards] - summary: Delete brand standard - operationId: brand_standards_delete - description: โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. + operationId: campaign_get + summary: Get campaign + description: Get detailed information about a specific campaign. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandStandardId] properties: - brandStandardId: + tool: type: string - description: ID of the brand standard to delete + enum: + - campaign_get + arguments: + $ref: '#/components/schemas/GetCampaignInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' - '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' - '500': - $ref: '#/components/responses/InternalError' - - /brand-story-list: - post: - tags: [Brand Stories] - summary: List brand stories - operationId: brand_story_list - description: List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. - requestBody: - required: true - content: - application/json: - schema: - type: object - required: [brandAgentId] - properties: - brandAgentId: - type: string - description: ID of the brand to list brand stories for - responses: - '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignUpdateOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-story-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-update: post: - tags: [Brand Stories] - summary: Create brand story - operationId: brand_story_create - description: Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. + operationId: campaign_update + summary: Update campaign + description: Update an existing campaign with new information. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId, name, prompt] properties: - brandAgentId: - type: string - description: ID of the brand to create a brand story for - name: + tool: type: string - description: Name for the brand story (e.g., 'Tech Enthusiasts', 'Luxury Shoppers') - prompt: - type: string - description: Natural language prompt defining the target audience profile, demographics, and behavioral characteristics - countries: - type: array - items: - type: string - description: List of country codes to target (e.g., ['US', 'CA']) - channels: - type: array - items: - type: string - description: List of channels to target (e.g., ['web', 'social']) - languages: - type: array - items: - type: string - description: List of language codes to target (e.g., ['en', 'es']) - brands: - type: array - items: - type: string - description: List of specific brands this applies to + enum: + - campaign_update + arguments: + $ref: '#/components/schemas/UpdateCampaignInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignUpdateOutput' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-story-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-delete: post: - tags: [Brand Stories] - summary: Update brand story - operationId: brand_story_update - description: Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. + operationId: campaign_delete + summary: Delete campaign + description: Delete a campaign and all associated resources. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandStoryId, prompt] properties: - brandStoryId: - type: string - description: ID of the brand story to update - prompt: + tool: type: string - description: New audience definition prompt + enum: + - campaign_delete + arguments: + $ref: '#/components/schemas/DeleteCampaignInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignDelete' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /brand-story-delete: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-get-summary: post: - tags: [Brand Stories] - summary: Delete brand story - operationId: brand_story_delete - description: โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. + operationId: campaign_get_summary + summary: Get campaign summary + description: Get a high-level summary of a campaign including key metrics and status. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandStoryId] properties: - brandStoryId: + tool: type: string - description: ID of the brand story to delete + enum: + - campaign_get_summary + arguments: + $ref: '#/components/schemas/GetCampaignSummaryInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignGetSummary' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-list-tactics: post: - tags: [Campaigns] - summary: List campaigns - operationId: campaign_list - description: List campaigns for the authenticated customer, with optional filtering. + operationId: campaign_list_tactics + summary: List campaign tactics + description: List all tactics associated with a specific campaign. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -537,326 +930,569 @@ paths: schema: type: object properties: - brandAgentId: - type: string - description: Optional brand agent ID to filter campaigns - status: + tool: type: string - enum: [ACTIVE, PAUSED, ARCHIVED] - description: Optional status filter - limit: - type: number - description: Maximum number of campaigns to return (default 100) - offset: - type: number - description: Number of campaigns to skip for pagination + enum: + - campaign_list_tactics + arguments: + $ref: '#/components/schemas/ListCampaignTacticsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignListTactics' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /campaign-validate-brief: post: - tags: [Campaigns] - summary: Create campaign - operationId: campaign_create - description: Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. + operationId: campaign_validate_brief + summary: Validate campaign brief + description: Validate a campaign brief to ensure it contains all necessary information for campaign creation. + tags: + - Campaigns + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [prompt] properties: - brandAgentId: - type: string - description: Optional brand agent ID that will own this campaign - name: - type: string - description: Optional name for the campaign (auto-generated if not provided) - prompt: - type: string - description: Natural language description of campaign requirements (e.g., 'Create a video campaign targeting tech enthusiasts with $50k budget') - budget: - $ref: '#/components/schemas/Budget' - startDate: + tool: type: string - format: date-time - description: Campaign start date (ISO 8601 format) - endDate: - type: string - format: date-time - description: Campaign end date (ISO 8601 format) - scoringWeights: - $ref: '#/components/schemas/ScoringWeights' - outcomeScoreWindowDays: - type: number - description: Days for outcome measurement window - segmentIds: - type: array - items: - type: string - description: Array of segment IDs to associate with campaign - dealIds: - type: array - items: - type: string - description: Array of deal IDs to associate with campaign - visibility: - type: string - enum: [PUBLIC, PRIVATE] - description: Campaign visibility setting - creationType: - type: string - enum: [MANUAL, AUTO_SYNC] - description: How the campaign was created - status: - type: string - enum: [ACTIVE, PAUSED, ARCHIVED] - description: Initial campaign status + enum: + - campaign_validate_brief + arguments: + $ref: '#/components/schemas/ValidateBriefInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CampaignValidateBrief' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /asset-list: post: - tags: [Campaigns] - summary: Update campaign - operationId: campaign_update - description: Update an existing campaign's settings. + operationId: asset_list + summary: List assets + description: List all uploaded assets with optional filtering by brand agent. + tags: + - Assets + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [campaignId] properties: - campaignId: - type: string - description: ID of the campaign to update - name: - type: string - description: New name for the campaign - prompt: - type: string - description: Updated natural language campaign requirements - status: - type: string - enum: [ACTIVE, PAUSED, ARCHIVED] - description: New status for the campaign - budget: - $ref: '#/components/schemas/Budget' - startDate: - type: string - format: date-time - description: Campaign start date (ISO 8601 format) - endDate: - type: string - format: date-time - description: Campaign end date (ISO 8601 format) - scoringWeights: - type: object - properties: - affinity: - type: number - description: Weight for affinity scoring (0-1) - outcome: - type: number - description: Weight for outcome scoring (0-1) - quality: - type: number - description: Weight for quality scoring (0-1) - description: Scoring weights configuration - outcomeScoreWindowDays: - type: number - description: Days for outcome measurement window - segmentIds: - type: array - items: - type: string - description: Array of segment IDs to associate with campaign - dealIds: - type: array - items: - type: string - description: Array of deal IDs to associate with campaign - visibility: + tool: type: string - enum: [PUBLIC, PRIVATE] - description: Campaign visibility setting + enum: + - asset_list + arguments: + $ref: '#/components/schemas/ListAssetsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/AssetList' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-delete: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-standards-create: post: - tags: [Campaigns] - summary: Delete campaign - operationId: campaign_delete - description: โš ๏ธ DANGER - Permanently delete a campaign and all associated data. + operationId: brand_standards_create + summary: Create brand standards + description: >- + Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand + agent. + tags: + - Brand Standards + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [campaignId] properties: - campaignId: + tool: type: string - description: ID of the campaign to delete - hardDelete: - type: boolean - description: If true, permanently delete the campaign. Default false (soft delete/archive) + enum: + - brand_standards_create + arguments: + $ref: '#/components/schemas/CreateBrandStandardInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStandardsCreateOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-get-summary: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-standards-delete: post: - tags: [Campaigns] - summary: Get campaign summary - operationId: campaign_get_summary - description: Get detailed summary information about a specific campaign. + operationId: brand_standards_delete + summary: Delete brand standards + description: Delete brand standards for a brand agent. + tags: + - Brand Standards + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [campaignId] properties: - campaignId: + tool: type: string - description: ID of the campaign to retrieve + enum: + - brand_standards_delete + arguments: + $ref: '#/components/schemas/DeleteBrandStandardInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStandardsDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-list-tactics: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-standards-list: post: - tags: [Campaigns] - summary: List campaign tactics - operationId: campaign_list_strategies - description: List all tactics associated with a specific campaign. + operationId: brand_standards_list + summary: List brand standards + description: List all brand standards with optional filtering by brand agent. + tags: + - Brand Standards + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [campaignId] properties: - campaignId: + tool: type: string - description: ID of the campaign to list tactics for - includeArchived: - type: boolean - description: Include archived tactics (defaults to false) + enum: + - brand_standards_list + arguments: + $ref: '#/components/schemas/ListBrandStandardsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStandardsList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /campaign-validate-brief: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-story-create: post: - tags: [Campaigns] - summary: Validate campaign brief - operationId: campaign_validate_brief - description: Validate a campaign brief to ensure it contains all necessary information. + operationId: brand_story_create + summary: Create brand story + description: Create a brand story containing the narrative, history, values, and key messaging for a brand agent. + tags: + - Brand Stories + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brief] properties: - brief: + tool: type: string - description: Campaign brief to validate - brandAgentId: - type: string - description: Optional brand agent ID for context-aware validation - threshold: - type: number - minimum: 0 - maximum: 100 - default: 70 - description: Minimum quality score required to pass validation + enum: + - brand_story_create + arguments: + $ref: '#/components/schemas/CreateBrandStoryInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStoryCreate' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /channel-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-story-update: post: - tags: [Channels] - summary: List channels - operationId: channel_list - description: List all available advertising channels. + operationId: brand_story_update + summary: Update brand story + description: Update an existing brand story with new information. + tags: + - Brand Stories + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - properties: {} + properties: + tool: + type: string + enum: + - brand_story_update + arguments: + $ref: '#/components/schemas/UpdateBrandStoryInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStoryUpdate' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-story-delete: post: - tags: [Creatives] - summary: List creatives - operationId: creative_list - description: List creatives for the authenticated customer, with optional filtering. + operationId: brand_story_delete + summary: Delete brand story + description: Delete a brand story. + tags: + - Brand Stories + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -864,244 +1500,373 @@ paths: schema: type: object properties: - brandAgentId: - type: integer - description: Optional internal brand agent ID to filter creatives - campaignId: - type: integer - description: Optional internal campaign ID to filter creatives + tool: + type: string + enum: + - brand_story_delete + arguments: + $ref: '#/components/schemas/DeleteBrandStoryInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStoryDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /brand-story-list: post: - tags: [Creatives] - summary: Create creative - operationId: creative_create - description: | - Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. - - **Two workflows supported:** - 1. **Separate upload**: Use asset_upload first, then reference asset IDs in content.assetIds - 2. **Inline upload**: Upload assets directly in the `assets` array (automatically uploaded and linked) + operationId: brand_story_list + summary: List brand stories + description: List all brand stories with optional filtering by brand agent. + tags: + - Brand Stories + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [brandAgentId, name] properties: - brandAgentId: - type: integer - description: '**REQUIRED**: Internal database ID of the brand agent that will own this creative' - example: 1 - organizationId: - type: integer - description: Optional internal database ID of the organization - name: - type: string - description: '**REQUIRED**: Name for the creative' - example: Banner Ad 970x250 - description: + tool: type: string - description: Optional description of the creative - example: Display banner for homepage - formatSource: - type: string - enum: [ADCP, CREATIVE_AGENT, PUBLISHER] - description: Format source type - example: ADCP - formatId: - type: string - description: Format identifier (e.g., "display_970x250", "video/mp4") - example: display_970x250 - mediaUrl: - type: string - description: URL to the creative media file (video, image, etc.) - example: https://example.com/banner.png - assets: - type: array - description: 'Optional: Upload assets inline with the creative. Automatically uploaded to GCS and linked.' - items: - $ref: '#/components/schemas/AssetUpload' - content: - type: object - description: Creative content as JSON. Can include assetIds (existing or from inline upload), htmlSnippet, vastTag, etc. - properties: - assetIds: - type: array - items: - type: string - description: Array of existing asset IDs (from previous asset_upload). Inline uploaded assets are automatically added to this. - example: [asset_abc123, asset_def456] - htmlSnippet: - type: string - description: HTML5 creative snippet - example:
Ad content
- vastTag: - type: string - description: VAST XML tag for video ads - assemblyMethod: - type: string - enum: [CREATIVE_AGENT, ACTIVATION, PUBLISHER] - description: Assembly method - example: ACTIVATION - campaignId: - type: integer - description: Optional internal database ID of campaign to assign creative to - example: 1 + enum: + - brand_story_list + arguments: + $ref: '#/components/schemas/ListBrandStoriesInput' + required: + - tool + - arguments responses: '200': - description: Creative created successfully + description: Successful response content: application/json: schema: type: object properties: - success: - type: boolean - example: true - message: - type: string - description: Success message with creative details including creativeId (external string ID for use in media_buy_create/update), internal ID, and uploaded assets (if any) - example: | - โœ… **Creative Created Successfully!** - - **Creative ID:** newcreativevideo_xntthe4w (use this for media_buy_create/update) - **Internal ID:** 16 - **Name:** My Creative - **Status:** PENDING - **Assets Uploaded:** 2 - **Asset IDs:** asset_abc123, asset_def456 - **Created:** 2025-10-14T00:00:00.000Z + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/BrandStoryList' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-get: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /channel-list: post: - tags: [Creatives] - summary: Get creative - operationId: creative_get - description: Get detailed information about a specific creative. + operationId: channel_list + summary: List channels + description: List all available advertising channels and platforms. + tags: + - Channels + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [creativeId] properties: - creativeId: - type: integer - description: Internal database ID of the creative to retrieve + tool: + type: string + enum: + - channel_list + arguments: + $ref: '#/components/schemas/ListChannelsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/ChannelList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-assign: post: - tags: [Creatives] - summary: Update creative - operationId: creative_update - description: Update an existing creative's settings. + operationId: creative_assign + summary: Assign creative + description: Assign a creative to a tactic or media buy. + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [creativeId] properties: - creativeId: - type: integer - description: Internal database ID of the creative to update - name: + tool: type: string - description: New name for the creative - status: - type: string - description: New status for the creative + enum: + - creative_assign + arguments: + $ref: '#/components/schemas/AssignCreativeInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeAssign' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-delete: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-create: post: - tags: [Creatives] - summary: Delete creative - operationId: creative_delete - description: โš ๏ธ DANGER - Permanently delete a creative. + operationId: creative_create + summary: Create creative + description: Create a new creative with assets, copy, and targeting specifications. + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [creativeId] properties: - creativeId: - type: integer - description: Internal database ID of the creative to delete + tool: + type: string + enum: + - creative_create + arguments: + $ref: '#/components/schemas/CreateCreativeInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeGetOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-assign: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-update: post: - tags: [Creatives] - summary: Assign creative to campaign - operationId: creative_assign - description: | - Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents - associated with the campaign via active media buys. Returns auto-sync results including which agents - received the creative and their approval status. + operationId: creative_update + summary: Update creative + description: Update an existing creative with new assets, copy, or specifications. + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [creativeId, campaignId] properties: - creativeId: - type: integer - description: Internal database ID of the creative to assign - campaignId: - type: integer - description: Internal database ID of the campaign to assign creative to + tool: + type: string + enum: + - creative_update + arguments: + $ref: '#/components/schemas/UpdateCreativeInput' + required: + - tool + - arguments responses: '200': - description: Creative assigned successfully with auto-sync results + description: Successful response content: application/json: schema: @@ -1110,383 +1875,689 @@ paths: content: type: array items: - type: object - properties: - type: - type: string - example: text - text: - type: string - description: | - Summary of creative assignment including auto-sync results. - Shows which sales agents received the creative and their approval status. + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeGetOutput' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /creative-sync-sales-agents: - post: - tags: [Creatives] - summary: Sync creative with sales agents - operationId: creative_sync_sales_agents - description: | - Sync a creative to sales agents using smart auto-detection or manual specification. - Features intelligent format matching and recent activity analysis (30-60 day lookback). - Provides detailed sync status and actionable next steps. - requestBody: - required: true - content: - application/json: - schema: - type: object - required: [creativeId] - properties: - creativeId: - type: integer - description: Internal database ID of the creative to sync - autoDetect: - type: object - description: Smart auto-detection settings (default behavior) - properties: - daysBack: - type: number - description: Look at tactics from past N days (default 30, max 90) - minimum: 1 - maximum: 90 - includeActive: - type: boolean - description: Include agents from active campaigns (default true) - campaignId: - type: integer - description: Internal database ID - sync to sales agents used by this campaign's tactics only - preApproval: - type: boolean - description: Request pre-approval before campaign launch (default false) - adcpAgentIds: - type: array - description: Explicitly specify ADCP agent IDs (overrides auto-detection) - items: - type: string - responses: - '200': - $ref: '#/components/responses/ToolResponse' - '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' - '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-delete: post: - tags: [Sales Agents] - summary: List sales agents - operationId: sales_agent_list - description: List all registered sales agents (publishers) for the authenticated customer. + operationId: creative_delete + summary: Delete creative + description: Delete a creative and remove it from any associated tactics or media buys. + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - properties: {} + properties: + tool: + type: string + enum: + - creative_delete + arguments: + $ref: '#/components/schemas/DeleteCreativeInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-get: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-get: post: - tags: [Sales Agents] - summary: Get sales agent - operationId: sales_agent_get - description: Get detailed information about a specific sales agent. + operationId: creative_get + summary: Get creative + description: Get detailed information about a specific creative. + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId] properties: - salesAgentId: + tool: type: string - description: ID of the sales agent to retrieve + enum: + - creative_get + arguments: + $ref: '#/components/schemas/GetCreativeInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeGetOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-register: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-list: post: - tags: [Sales Agents] - summary: Register sales agent - operationId: sales_agent_register - description: Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. + operationId: creative_list + summary: List creatives + description: List all creatives with optional filtering by brand agent or campaign. + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [name, endpointUrl, protocol, authenticationType] properties: - name: - type: string - description: Sales agent name - endpointUrl: - type: string - description: Sales agent endpoint URL - protocol: - type: string - enum: [MCP, A2A] - description: Protocol for endpoint URL calls - authenticationType: - type: string - enum: [API_KEY, OAUTH, NO_AUTH] - description: Authentication type - description: + tool: type: string - description: Sales agent description (optional) - organizationId: - type: string - description: Organization ID (optional - auto-detected from customer if not provided) - authConfig: - type: object - description: Authentication configuration for the sales agent (optional) + enum: + - creative_list + arguments: + $ref: '#/components/schemas/ListCreativesInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeList' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-account-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /creative-sync-sales-agents: post: - tags: [Sales Agents] - summary: List accounts for a sales agent - operationId: sales_agent_account_list - description: List all accounts registered by your organization for a specific sales agent. + operationId: creative_sync_sales_agents + summary: Sync creatives to sales agents + description: Synchronize creatives to connected sales agents (DSPs, publisher platforms). + tags: + - Creatives + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId] properties: - salesAgentId: + tool: type: string - description: ID of the sales agent + enum: + - creative_sync_sales_agents + arguments: + $ref: '#/components/schemas/SyncSalesAgentsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/CreativeSyncSalesAgents' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-account-register: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-create: post: - tags: [Sales Agents] - summary: Register account for sales agent - operationId: sales_agent_account_register - description: Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. + operationId: media_buy_create + summary: Create media buy + description: Create a new media buy with budget, targeting, and creative specifications. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId, accountIdentifier] properties: - salesAgentId: + tool: type: string - description: Sales agent ID - accountIdentifier: - type: string - description: Account identifier - authConfig: - type: object - description: Authentication configuration (credentials, tokens, etc.) - optional + enum: + - media_buy_create + arguments: + $ref: '#/components/schemas/CreateMediaBuyInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyGetOutput' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-unregister: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-update: post: - tags: [Sales Agents] - summary: Unregister sales agent completely - operationId: sales_agent_unregister - description: Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. + operationId: media_buy_update + summary: Update media buy + description: Update an existing media buy with new budget, targeting, or creative assignments. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId, confirm] properties: - salesAgentId: + tool: type: string - description: ID of the sales agent to unregister - confirm: - type: boolean - description: Must be true to confirm this destructive operation + enum: + - media_buy_update + arguments: + $ref: '#/components/schemas/UpdateMediaBuyInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyGetOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-account-unregister: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-delete: post: - tags: [Sales Agents] - summary: Unregister your account with a sales agent - operationId: sales_agent_account_unregister - description: Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. + operationId: media_buy_delete + summary: Delete media buy + description: Delete a media buy and cancel any active placements. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId, confirm] properties: - salesAgentId: + tool: type: string - description: ID of the sales agent to unregister your account from - confirm: - type: boolean - description: Must be true to confirm this destructive operation + enum: + - media_buy_delete + arguments: + $ref: '#/components/schemas/DeleteMediaBuyInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-execute: post: - tags: [Sales Agents] - summary: Update sales agent - operationId: sales_agent_update - description: Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. + operationId: media_buy_execute + summary: Execute media buy + description: Execute a media buy, sending it to the configured sales agents for placement. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId] properties: - salesAgentId: - type: string - description: ID of the sales agent to update - name: - type: string - description: New name - description: - type: string - description: New description - endpointUrl: - type: string - description: New endpoint URL - protocol: + tool: type: string - enum: [REST, MCP, A2A, CUSTOM] - description: New protocol - authenticationType: - type: string - enum: [API_KEY, OAUTH, NO_AUTH] - description: New authentication type - authConfig: - type: object - description: Authentication configuration for the sales agent + enum: + - media_buy_execute + arguments: + $ref: '#/components/schemas/ExecuteMediaBuyInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyExecute' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /sales-agent-account-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-get: post: - tags: [Sales Agents] - summary: Update sales agent account authentication - operationId: sales_agent_account_update - description: Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. + operationId: media_buy_get + summary: Get media buy + description: Get detailed information about a specific media buy. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId, accountIdentifier, authConfig] properties: - salesAgentId: + tool: type: string - description: ID of the sales agent - accountIdentifier: - type: string - description: Account identifier to update - authConfig: - type: object - description: Updated authentication configuration (credentials, tokens, etc.) + enum: + - media_buy_get + arguments: + $ref: '#/components/schemas/GetMediaBuyInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyGetOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-list: post: - tags: [Tactics] - summary: List tactics - operationId: strategy_list - description: List all media buying tactics for the authenticated customer. + operationId: media_buy_list + summary: List media buys + description: List all media buys with optional filtering by brand agent, campaign, or status. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -1494,234 +2565,496 @@ paths: schema: type: object properties: - campaignId: + tool: type: string - description: Optional campaign ID to filter tactics - includeArchived: - type: boolean - description: Include archived tactics (defaults to false) + enum: + - media_buy_list + arguments: + $ref: '#/components/schemas/ListMediaBuysInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-buy-validate-budget: post: - tags: [Tactics] - summary: Create tactic - operationId: strategy_create - description: Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. + operationId: media_buy_validate_budget + summary: Validate media buy budget + description: Validate a media buy budget against campaign constraints and available funds. + tags: + - Media Buys + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [name, campaignId] properties: - name: - type: string - description: Name of the tactic - campaignId: - type: string - description: Campaign ID to link this tactic to (required) - prompt: + tool: type: string - description: Optional tactical brief or prompt for this tactic - channelCodes: - type: array - items: - type: string - enum: [DIGITAL-AUDIO, DISPLAY-WEB, DISPLAY-APP, CTV-BVOD, OLV, DOOH, SOCIAL] - description: Valid channel codes to target (also accepts friendly aliases like audio, web, app, ctv, video which are automatically mapped) - countryCodes: - type: array - items: - type: string - description: Country codes to target (2-digit ISO codes) + enum: + - media_buy_validate_budget + arguments: + $ref: '#/components/schemas/ValidateMediaBuyBudgetInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaBuyValidateBudget' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-get: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /notifications-list: post: - tags: [Tactics] - summary: Get tactic - operationId: strategy_get - description: Get detailed information about a specific tactic. + operationId: notifications_list + summary: List notifications + description: List notifications for the authenticated user with optional filtering by status. + tags: + - Notifications + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [tacticId] properties: - tacticId: + tool: type: string - description: ID of the tactic to retrieve + enum: + - notifications_list + arguments: + $ref: '#/components/schemas/ListNotificationsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/NotificationsList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /notifications-mark-read: post: - tags: [Tactics] - summary: Update tactic - operationId: strategy_update - description: Update an existing tactic's configuration. + operationId: notifications_mark_read + summary: Mark notification as read + description: Mark a specific notification as read. + tags: + - Notifications + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [tacticId] properties: - tacticId: - type: string - description: ID of the tactic to update - name: + tool: type: string - description: New name for the tactic - prompt: - type: string - description: New tactical brief - channelCodes: - type: array - items: - type: string - enum: [DIGITAL-AUDIO, DISPLAY-WEB, DISPLAY-APP, CTV-BVOD, OLV, DOOH, SOCIAL] - description: Updated channel codes (also accepts friendly aliases like audio, web, app, ctv, video) - countryCodes: - type: array - items: - type: string - description: Updated country codes + enum: + - notifications_mark_read + arguments: + $ref: '#/components/schemas/MarkNotificationReadInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/NotificationsMarkRead' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-delete: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /notifications-mark-acknowledged: post: - tags: [Tactics] - summary: Delete tactic - operationId: strategy_delete - description: โš ๏ธ DANGER - Permanently delete a tactic. + operationId: notifications_mark_acknowledged + summary: Mark notification as acknowledged + description: Mark a specific notification as acknowledged. + tags: + - Notifications + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [tacticId] properties: - tacticId: + tool: type: string - description: ID of the tactic to delete + enum: + - notifications_mark_acknowledged + arguments: + $ref: '#/components/schemas/MarkNotificationAcknowledgedInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/NotificationsMarkAcknowledged' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-link-campaign: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /notifications-mark-all-read: post: - tags: [Tactics] - summary: Link campaign to tactic - operationId: strategy_link_campaign - description: Link a campaign to a tactic for budget and execution management. + operationId: notifications_mark_all_read + summary: Mark all notifications as read + description: Mark all notifications for the authenticated user as read. + tags: + - Notifications + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [tacticId, campaignId] properties: - tacticId: + tool: type: string - description: ID of the tactic - campaignId: - type: string - description: ID of the campaign to link + enum: + - notifications_mark_all_read + arguments: + $ref: '#/components/schemas/MarkAllNotificationsReadInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/NotificationsMarkAllRead' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /tactic-unlink-campaign: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-product-discover: post: - tags: [Tactics] - summary: Unlink campaign from tactic - operationId: strategy_unlink_campaign - description: Unlink a campaign from a tactic. + operationId: media_product_discover + summary: Discover media products + description: Discover available media products from connected sales agents based on targeting criteria. + tags: + - Media Products + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [tacticId, campaignId] properties: - tacticId: - type: string - description: ID of the tactic - campaignId: + tool: type: string - description: ID of the campaign to unlink + enum: + - media_product_discover + arguments: + $ref: '#/components/schemas/DiscoverProductsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaProductDiscover' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-buy-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-product-save: post: - tags: [Media Buys] - summary: List media buys - operationId: media_buy_list - description: List all media buys for the authenticated customer. + operationId: media_product_save + summary: Save media product + description: Save a discovered media product for future use in media buys. + tags: + - Media Products + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -1729,251 +3062,425 @@ paths: schema: type: object properties: - tacticId: - type: string - description: Optional tactic ID to filter media buys - campaignId: + tool: type: string - description: Optional campaign ID to filter media buys - includeArchived: - type: boolean - description: Include archived media buys (defaults to false) + enum: + - media_product_save + arguments: + $ref: '#/components/schemas/SaveProductInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaProductSave' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-buy-create: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-product-list: post: - tags: [Media Buys] - summary: Create media buy - operationId: media_buy_create - description: | - Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. - - **Multi-Product Support**: Media buys now support multiple products from different sales agents in a single buy. Each product can have its own budget allocation and pricing. During execution, each unique sales agent will receive a separate ADCP submission. - - **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. + operationId: media_product_list + summary: List media products + description: List saved media products with optional filtering. + tags: + - Media Products + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [tacticId, name, products, budget] properties: - tacticId: - type: string - description: ID of the tactic to execute - name: + tool: type: string - description: Name of the media buy - description: - type: string - description: Optional description of the media buy - products: - type: array - description: Array of products to include in this media buy. At least one product is required. Each product will be validated with its sales agent. - minItems: 1 - items: - type: object - required: [mediaProductId, salesAgentId] - properties: - mediaProductId: - type: string - description: Media product ID from publisher (will be validated with sales agent) - salesAgentId: - type: string - description: Sales agent ID for this product - budgetAmount: - type: number - description: Budget allocated to this specific product (optional, must not exceed total budget when summed across all products) - budgetCurrency: - type: string - description: Currency for this product's budget (defaults to media buy currency) - pricingCpm: - type: number - description: Base CPM price for this product - pricingSignalCost: - type: number - description: Additional signal cost for this product - displayOrder: - type: integer - description: Optional display order for organizing products - budget: - type: object - required: [amount] - properties: - amount: - type: number - description: Total budget amount for this media buy - currency: - type: string - description: Currency code (defaults to USD) - dailyCap: - type: number - description: Optional daily spending cap - pacing: - type: string - enum: [asap, even, front_loaded] - description: Budget pacing tactic (defaults to even) - creativeIds: - type: array - items: - type: string - description: Optional array of creative IDs (database IDs) to assign to this media buy. Creatives must be assigned to the campaign associated with this media buy's tactic. + enum: + - media_product_list + arguments: + $ref: '#/components/schemas/ListProductsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalError' - - /media-buy-get: + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaProductList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /media-product-sync: post: - tags: [Media Buys] - summary: Get media buy - operationId: media_buy_get - description: Get detailed information about a specific media buy. + operationId: media_product_sync + summary: Sync media products + description: Synchronize media product catalog from connected sales agents. + tags: + - Media Products + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [mediaBuyId] properties: - mediaBuyId: + tool: type: string - description: ID of the media buy to retrieve + enum: + - media_product_sync + arguments: + $ref: '#/components/schemas/SyncProductsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/MediaProductSync' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-buy-update: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-get: post: - tags: [Media Buys] - summary: Update media buy - operationId: media_buy_update - description: Update an existing media buy's configuration. + operationId: sales_agent_get + summary: Get sales agent + description: Get detailed information about a specific sales agent (DSP, publisher platform). + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [mediaBuyId] properties: - mediaBuyId: - type: string - description: ID of the media buy to update - name: + tool: type: string - description: New name - budget: - type: object - properties: - amount: - type: number - dailyCap: - type: number - pacing: - type: string - enum: [asap, even, front_loaded] - cpm: - type: number - description: New CPM price - creativeIds: - type: array - items: - type: string - description: Array of creative IDs (database IDs) to assign to this media buy. Replaces existing assignments. Creatives must be assigned to the campaign associated with this media buy's tactic. + enum: + - sales_agent_get + arguments: + $ref: '#/components/schemas/GetSalesAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentGet' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-buy-delete: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-list: post: - tags: [Media Buys] - summary: Delete media buy - operationId: media_buy_delete - description: โš ๏ธ DANGER - Permanently delete a media buy. + operationId: sales_agent_list + summary: List sales agents + description: List all registered sales agents (DSPs, publisher platforms). + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [mediaBuyId] properties: - mediaBuyId: + tool: type: string - description: ID of the media buy to delete + enum: + - sales_agent_list + arguments: + $ref: '#/components/schemas/ListSalesAgentsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-buy-execute: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-register: post: - tags: [Media Buys] - summary: Execute media buy - operationId: media_buy_execute - description: Execute a media buy by deploying it to the publisher platform. + operationId: sales_agent_register + summary: Register sales agent + description: Register a new sales agent (DSP, publisher platform) for media buying. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [mediaBuyId] properties: - mediaBuyId: + tool: type: string - description: ID of the media buy to execute + enum: + - sales_agent_register + arguments: + $ref: '#/components/schemas/RegisterSalesAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentRegister' + required: + - content + - structuredContent + additionalProperties: false '400': - $ref: '#/components/responses/BadRequest' + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /notifications-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-unregister: post: - tags: [Notifications] - summary: List notifications - operationId: notifications_list - description: List notifications for the authenticated user. + operationId: sales_agent_unregister + summary: Unregister sales agent + description: Unregister a sales agent and disconnect it from the platform. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -1981,101 +3488,283 @@ paths: schema: type: object properties: - unreadOnly: - type: boolean - description: Filter to only unread notifications - limit: - type: number - description: Maximum number of notifications to return + tool: + type: string + enum: + - sales_agent_unregister + arguments: + $ref: '#/components/schemas/UnregisterSalesAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentUnregister' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /notifications-mark-read: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-update: post: - tags: [Notifications] - summary: Mark notification as read - operationId: notifications_mark_read - description: Mark a specific notification as read. + operationId: sales_agent_update + summary: Update sales agent + description: Update sales agent configuration and credentials. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [notificationId] properties: - notificationId: + tool: type: string - description: ID of the notification to mark as read + enum: + - sales_agent_update + arguments: + $ref: '#/components/schemas/UpdateSalesAgentInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentUpdate' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /notifications-mark-acknowledged: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-account-list: post: - tags: [Notifications] - summary: Mark notification as acknowledged - operationId: notifications_mark_acknowledged - description: Mark a specific notification as acknowledged. + operationId: sales_agent_account_list + summary: List sales agent accounts + description: List all accounts (seats, advertisers) within a sales agent. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [notificationId] properties: - notificationId: + tool: type: string - description: ID of the notification to mark as acknowledged + enum: + - sales_agent_account_list + arguments: + $ref: '#/components/schemas/ListSalesAgentAccountsInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentAccountList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /notifications-mark-all-read: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-account-register: post: - tags: [Notifications] - summary: Mark all notifications as read - operationId: notifications_mark_all_read - description: Mark all notifications as read for the authenticated user. + operationId: sales_agent_account_register + summary: Register sales agent account + description: Register a new account (seat, advertiser) within a sales agent. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - properties: {} + properties: + tool: + type: string + enum: + - sales_agent_account_register + arguments: + $ref: '#/components/schemas/RegisterSalesAgentAccountInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentAccountRegister' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-product-list: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-account-unregister: post: - tags: [Products] - summary: List media products - operationId: media_product_list - description: List available media products from publishers. + operationId: sales_agent_account_unregister + summary: Unregister sales agent account + description: Unregister an account from a sales agent. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -2083,23 +3772,70 @@ paths: schema: type: object properties: - salesAgentId: + tool: type: string - description: Optional sales agent ID to filter products + enum: + - sales_agent_account_unregister + arguments: + $ref: '#/components/schemas/UnregisterSalesAgentAccountInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' - '401': - $ref: '#/components/responses/Unauthorized' - '500': - $ref: '#/components/responses/InternalError' - - /media-product-discover: - post: - tags: [Products] - summary: Discover media products - operationId: media_product_discover - description: Discover new media products from connected publishers. + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentAccountUnregister' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /sales-agent-account-update: + post: + operationId: sales_agent_account_update + summary: Update sales agent account + description: Update account configuration within a sales agent. + tags: + - Sales Agents + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: @@ -2107,377 +3843,4098 @@ paths: schema: type: object properties: - salesAgentId: + tool: type: string - description: Sales agent ID to discover products from + enum: + - sales_agent_account_update + arguments: + $ref: '#/components/schemas/UpdateSalesAgentAccountInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/SalesAgentAccountUpdate' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - - /media-product-sync: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-create: post: - tags: [Products] - summary: Sync media products - operationId: media_product_sync - description: Synchronize media product inventory with publisher systems. + operationId: tactic_create + summary: Create tactic + description: Create a new tactic defining how to achieve campaign objectives. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. requestBody: required: true content: application/json: schema: type: object - required: [salesAgentId] properties: - salesAgentId: + tool: type: string - description: Sales agent ID to sync products from + enum: + - tactic_create + arguments: + $ref: '#/components/schemas/CreateTacticInput' + required: + - tool + - arguments responses: '200': - $ref: '#/components/responses/ToolResponse' + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticCreate' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' '500': - $ref: '#/components/responses/InternalError' - -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: Bearer token authentication using Scope3 API key - - responses: - ToolResponse: - description: Successful tool execution - content: - application/json: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-update: + post: + operationId: tactic_update + summary: Update tactic + description: Update an existing tactic with new targeting, budget, or creative requirements. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true schema: - type: object - properties: - success: - type: boolean - description: Whether the operation succeeded - message: - type: string - description: Human-readable response message - data: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - tactic_update + arguments: + $ref: '#/components/schemas/UpdateTacticInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: type: object - description: Response data (varies by tool) - - BadRequest: - description: Bad request - invalid parameters - content: - application/json: + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticGetOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-delete: + post: + operationId: tactic_delete + summary: Delete tactic + description: Delete a tactic and all associated media buys. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - tactic_delete + arguments: + $ref: '#/components/schemas/DeleteTacticInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-get: + post: + operationId: tactic_get + summary: Get tactic + description: Get detailed information about a specific tactic. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - tactic_get + arguments: + $ref: '#/components/schemas/GetTacticInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticGetOutput' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-list: + post: + operationId: tactic_list + summary: List tactics + description: List all tactics with optional filtering by brand agent or campaign. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - tactic_list + arguments: + $ref: '#/components/schemas/ListTacticsInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-link-campaign: + post: + operationId: tactic_link_campaign + summary: Link tactic to campaign + description: Link a tactic to a campaign. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - tactic_link_campaign + arguments: + $ref: '#/components/schemas/LinkCampaignToTacticInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticLinkCampaign' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /tactic-unlink-campaign: + post: + operationId: tactic_unlink_campaign + summary: Unlink tactic from campaign + description: Unlink a tactic from a campaign. + tags: + - Tactics + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - tactic_unlink_campaign + arguments: + $ref: '#/components/schemas/UnlinkCampaignFromTacticInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/TacticUnlinkCampaign' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /webhook-register: + post: + operationId: webhook_register + summary: Register webhook + description: Register a webhook to receive real-time notifications about events. + tags: + - Webhooks + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - webhook_register + arguments: + $ref: '#/components/schemas/RegisterWebhookInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/WebhookRegister' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /webhook-list: + post: + operationId: webhook_list + summary: List webhooks + description: List all registered webhooks. + tags: + - Webhooks + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - webhook_list + arguments: + $ref: '#/components/schemas/ListWebhooksInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/WebhookList' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' + /webhook-delete: + post: + operationId: webhook_delete + summary: Delete webhook + description: Delete a registered webhook. + tags: + - Webhooks + security: + - bearerAuth: [] + parameters: + - name: mcp-session-id + in: header + required: true + schema: + type: string + format: uuid + description: >- + MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a + session ID, then reuse it for all subsequent tool requests in the same session. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tool: + type: string + enum: + - webhook_delete + arguments: + $ref: '#/components/schemas/DeleteWebhookInput' + required: + - tool + - arguments + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/MCPContent' + structuredContent: + $ref: '#/components/schemas/WebhookDelete' + required: + - content + - structuredContent + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/BadRequest' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Unauthorized' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/InternalError' +components: + schemas: + ListAssetsInput: + type: object + properties: + brandAgentId: + description: Optional brand agent ID to filter assets + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + ListBrandAgentsInput: + description: Parameters for listing brand agents. Authentication is automatic. + type: object + properties: + where: + description: Prisma-style where clause for filtering agents + type: object + additionalProperties: {} + orderBy: + description: Prisma-style orderBy clause + type: object + additionalProperties: {} + take: + description: Number of records to return + example: 10 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + description: Number of records to skip + example: 0 + type: integer + minimum: 0 + maximum: 9007199254740991 + distinct: + description: Fields to use for distinct selection + type: array + items: + type: string + GetBrandAgentInput: + description: Parameters for retrieving a specific brand agent + type: object + properties: + brandAgentId: + description: The unique identifier for the brand agent + example: 123 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + required: + - brandAgentId + CreateBrandAgentInput: + description: Parameters for creating a new brand agent + type: object + properties: + name: + description: Name of the brand agent (advertiser account) + example: Nike Global Campaigns + type: string + minLength: 1 + maxLength: 255 + description: + description: Optional description of the brand agent + example: Brand agent for Nike global advertising campaigns + type: string + maxLength: 1000 + manifestUrl: + description: URL to the brand manifest + example: https://example.com/brand-manifest + type: string + format: uri + channels: + description: Advertising channels to enable + example: + - app + - display + - ctv + type: array + items: + type: string + enum: + - ctv + - video + - display + - app + - social + countryCodes: + description: Country codes (ISO 3166-1 alpha-2) + example: + - US + - CA + - GB + type: array + items: + type: string + minLength: 2 + maxLength: 2 + languages: + description: Language codes (ISO 639-1) + example: + - en + - es + - fr + type: array + items: + type: string + minLength: 2 + maxLength: 2 + required: + - name + UpdateBrandAgentInput: + description: Parameters for updating a brand agent + type: object + properties: + brandAgentId: + description: The unique identifier for the brand agent + example: 123 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + description: Updated name of the brand agent + type: string + minLength: 1 + maxLength: 255 + description: + description: Updated description + type: string + maxLength: 1000 + manifestUrl: + description: Updated URL to the brand manifest + example: https://example.com/brand-manifest + type: string + format: uri + channels: + description: Updated channels + type: array + items: + type: string + enum: + - ctv + - video + - display + - app + - social + countryCodes: + description: Updated country codes + type: array + items: + type: string + minLength: 2 + maxLength: 2 + languages: + description: Updated language codes + type: array + items: + type: string + minLength: 2 + maxLength: 2 + required: + - brandAgentId + DeleteBrandAgentInput: + description: Parameters for deleting a brand agent + type: object + properties: + brandAgentId: + description: The unique identifier for the brand agent to delete + example: 123 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + required: + - brandAgentId + CreateBrandStandardInput: + type: object + properties: + brandAgentId: + description: Brand agent ID + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + description: Standard name + type: string + minLength: 1 + maxLength: 255 + description: + description: Standard description + type: string + prompt: + description: Brand standards prompt + type: string + minLength: 1 + isPrimary: + description: Whether this is the primary standard + type: boolean + countries: + description: Country codes + type: array + items: + type: string + channels: + description: Channel types + type: array + items: + type: string + enum: + - ctv + - video + - display + - app + - social + brands: + description: Brand names + type: array + items: + type: string + required: + - brandAgentId + - prompt + DeleteBrandStandardInput: + type: object + properties: + brandStandardId: + description: Brand standard ID + type: string + required: + - brandStandardId + ListBrandStandardsInput: + type: object + properties: + where: + description: Prisma-style where clause for filtering standards + type: object + additionalProperties: {} + orderBy: + description: Prisma-style orderBy clause + type: object + additionalProperties: {} + take: + description: Number of records to return + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + description: Number of records to skip + type: integer + minimum: 0 + maximum: 9007199254740991 + distinct: + description: Fields to use for distinct selection + type: array + items: + type: string + CreateBrandStoryInput: + type: object + properties: + brandAgentId: + description: Brand agent ID (bigint or string) + anyOf: + - type: integer + format: int64 + - type: string + name: + description: Story name + type: string + minLength: 1 + maxLength: 255 + description: + description: Story description + type: string + prompt: + description: Brand story prompt + type: string + isPrimary: + description: Whether this is the primary story + type: boolean + channelCodes: + description: Channel codes + type: array + items: + type: string + enum: + - ctv + - video + - display + - app + - social + countryCodes: + description: Country codes + type: array + items: + type: string + brands: + description: Brand names + type: array + items: + type: string + languages: + description: Language codes + type: array + items: + type: string + required: + - brandAgentId + - name + - isPrimary + UpdateBrandStoryInput: + type: object + properties: + name: + description: Story name + type: string + previousModelId: + description: Previous model ID (bigint or string) + anyOf: + - type: integer + format: int64 + - type: string + prompt: + description: Updated brand story prompt + type: string + minLength: 1 + required: + - previousModelId + - prompt + DeleteBrandStoryInput: + type: object + properties: + brandStoryId: + description: Brand story ID + type: string + required: + - brandStoryId + ListBrandStoriesInput: + type: object + properties: + where: + description: Filtering criteria + type: object + additionalProperties: {} + orderBy: + description: Ordering criteria + type: object + additionalProperties: {} + take: + description: Number of records to return + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + description: Number of records to skip + type: integer + minimum: 0 + maximum: 9007199254740991 + distinct: + description: Fields to use for distinct selection + type: array + items: + type: string + ListCampaignsInput: + description: Parameters for listing campaigns + type: object + properties: + brandAgentId: + description: Filter by brand agent ID + example: 123 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + status: + description: Filter by campaign status + type: string + enum: + - ACTIVE + - PAUSED + - ARCHIVED + - DRAFT + limit: + description: Number of results to return + example: 50 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + offset: + description: Number of results to skip for pagination + example: 0 + type: integer + minimum: 0 + maximum: 9007199254740991 + CreateCampaignInput: + description: Parameters for creating a new campaign + type: object + properties: + brandAgentId: + description: Brand agent ID that will own this campaign + example: 123 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + description: Optional name for the campaign (auto-generated if not provided) + example: Summer 2025 Tech Campaign + type: string + minLength: 1 + maxLength: 255 + prompt: + description: >- + Natural language description of campaign requirements. The backend will parse this to extract targeting, + budget, and creative requirements. + example: Create a video campaign targeting tech enthusiasts aged 25-45 with $50k budget + type: string + minLength: 10 + budget: + description: Budget configuration for the campaign + type: object + properties: + total: + type: number + minimum: 0 + exclusiveMinimum: true + currency: + default: USD + type: string + minLength: 3 + maxLength: 3 + dailyCap: + type: number + minimum: 0 + exclusiveMinimum: true + pacing: + type: string + enum: + - EVEN + - ASAP + - FRONTLOADED + required: + - total + startDate: + description: Campaign start date (ISO 8601 format) + example: '2025-01-15T00:00:00Z' + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + endDate: + description: Campaign end date (ISO 8601 format) + example: '2025-03-31T23:59:59Z' + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + scoringWeights: + description: Scoring weights for campaign optimization + type: object + properties: + affinity: + type: number + minimum: 0 + maximum: 1 + outcome: + type: number + minimum: 0 + maximum: 1 + quality: + type: number + minimum: 0 + maximum: 1 + outcomeScoreWindowDays: + description: Number of days for outcome measurement window + example: 30 + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + status: + description: Initial campaign status + type: string + enum: + - ACTIVE + - PAUSED + - ARCHIVED + - DRAFT + required: + - brandAgentId + - prompt + GetCampaignInput: + description: Parameters for retrieving a specific campaign + type: object + properties: + campaignId: + description: The unique identifier for the campaign + example: cmp_987654321 + type: string + minLength: 1 + required: + - campaignId + UpdateCampaignInput: + description: Parameters for updating a campaign + type: object + properties: + campaignId: + description: The unique identifier for the campaign + example: cmp_987654321 + type: string + minLength: 1 + name: + description: Updated campaign name + type: string + minLength: 1 + maxLength: 255 + prompt: + description: Updated campaign prompt + type: string + minLength: 10 + budget: + description: Updated budget configuration + type: object + properties: + total: + type: number + minimum: 0 + exclusiveMinimum: true + currency: + default: USD + type: string + minLength: 3 + maxLength: 3 + dailyCap: + type: number + minimum: 0 + exclusiveMinimum: true + pacing: + type: string + enum: + - EVEN + - ASAP + - FRONTLOADED + startDate: + description: Updated start date + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + endDate: + description: Updated end date + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + scoringWeights: + description: Updated scoring weights + type: object + properties: + affinity: + type: number + minimum: 0 + maximum: 1 + outcome: + type: number + minimum: 0 + maximum: 1 + quality: + type: number + minimum: 0 + maximum: 1 + outcomeScoreWindowDays: + description: Updated outcome score window days + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + status: + description: Updated campaign status + type: string + enum: + - ACTIVE + - PAUSED + - ARCHIVED + - DRAFT + expectedVersion: + description: Expected version for optimistic locking + type: integer + minimum: -9007199254740991 + maximum: 9007199254740991 + required: + - campaignId + DeleteCampaignInput: + description: Parameters for deleting a campaign + type: object + properties: + campaignId: + description: The unique identifier for the campaign to delete + example: cmp_987654321 + type: string + minLength: 1 + required: + - campaignId + GetCampaignSummaryInput: + type: object + properties: + campaignId: + description: Campaign ID + type: string + required: + - campaignId + ListCampaignTacticsInput: + type: object + properties: + campaignId: + description: Campaign ID + type: string + required: + - campaignId + ValidateBriefInput: + type: object + properties: + brief: + description: Campaign brief text + type: string + minLength: 10 + required: + - brief + ListChannelsInput: + type: object + properties: {} + AssignCreativeInput: + type: object + properties: + creativeId: + type: string + campaignId: + type: string + required: + - creativeId + - campaignId + CreateCreativeInput: + type: object + properties: + brandAgentId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + organizationId: + type: string + name: + type: string + minLength: 1 + maxLength: 255 + description: + type: string + formatSource: + type: string + enum: + - ADCP + - CREATIVE_AGENT + - PUBLISHER + formatId: + type: string + mediaUrl: + type: string + assets: + description: >- + Optional: Upload assets inline with the creative. Each asset requires: name, contentType, data (base64), and + assetType. + type: array + items: + type: object + properties: + name: + description: Filename (e.g., banner.png) + type: string + contentType: + description: MIME type (e.g., image/png, image/jpeg) + type: string + data: + description: Base64-encoded file data (without data:image/png;base64, prefix) + format: byte + type: string + assetType: + description: Type of asset + type: string + enum: + - image + - video + - audio + - logo + - font + tags: + description: Optional tags + type: array + items: + type: string + required: + - name + - contentType + - data + - assetType + content: + type: object + additionalProperties: {} + assemblyMethod: + type: string + enum: + - CREATIVE_AGENT + - ACTIVATION + - PUBLISHER + campaignId: + description: Optional campaign ID (object ID) to assign creative to + type: string + version: + type: string + registeredBy: + type: string + required: + - brandAgentId + - name + UpdateCreativeInput: + type: object + properties: + creativeId: + type: string + name: + type: string + description: + type: string + assetIds: + type: array + items: + type: string + required: + - creativeId + DeleteCreativeInput: + type: object + properties: + creativeId: + type: string + required: + - creativeId + GetCreativeInput: + type: object + properties: + creativeId: + type: string + required: + - creativeId + ListCreativesInput: + type: object + properties: + campaignId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + brandAgentId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + formatSource: + type: string + enum: + - ADCP + - CREATIVE_AGENT + - PUBLISHER + status: + type: string + enum: + - ACTIVE + - PAUSED + - ARCHIVED + - DRAFT + take: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + type: integer + minimum: 0 + maximum: 9007199254740991 + SyncSalesAgentsInput: + type: object + properties: + creativeId: + type: string + required: + - creativeId + CreateMediaBuyInput: + type: object + properties: + tacticId: + type: number + name: + type: string + minLength: 1 + description: + type: string + products: + type: array + items: + type: object + properties: + mediaProductId: + type: string + salesAgentId: + type: string + budgetAmount: + type: number + minimum: 0 + exclusiveMinimum: true + budgetCurrency: + type: string + pricingCpm: + type: number + minimum: 0 + exclusiveMinimum: true + pricingSignalCost: + type: number + displayOrder: + type: integer + minimum: -9007199254740991 + maximum: 9007199254740991 + required: + - mediaProductId + - salesAgentId + creativeIds: + type: array + items: + type: string + budget: + type: object + properties: + amount: + type: number + minimum: 0 + exclusiveMinimum: true + currency: + type: string + dailyCap: + type: number + minimum: 0 + exclusiveMinimum: true + pacing: + type: string + enum: + - asap + - even + - front_loaded + required: + - amount + - currency + - pacing + required: + - tacticId + - name + - products + - budget + UpdateMediaBuyInput: + type: object + properties: + mediaBuyId: + type: string + name: + type: string + description: + type: string + budget: + type: object + properties: + amount: + type: number + minimum: 0 + exclusiveMinimum: true + currency: + type: string + dailyCap: + type: number + minimum: 0 + exclusiveMinimum: true + pacing: + type: string + enum: + - asap + - even + - front_loaded + status: + type: string + enum: + - DRAFT + - PENDING_APPROVAL + - ACTIVE + - PAUSED + - COMPLETED + - FAILED + - REJECTED + creativeIds: + type: array + items: + type: string + required: + - mediaBuyId + DeleteMediaBuyInput: + type: object + properties: + mediaBuyId: + type: string + required: + - mediaBuyId + ExecuteMediaBuyInput: + type: object + properties: + mediaBuyId: + type: string + required: + - mediaBuyId + GetMediaBuyInput: + type: object + properties: + mediaBuyId: + type: string + required: + - mediaBuyId + ListMediaBuysInput: + type: object + properties: + tacticId: + type: number + status: + type: string + enum: + - DRAFT + - PENDING_APPROVAL + - ACTIVE + - PAUSED + - COMPLETED + - FAILED + - REJECTED + take: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + type: integer + minimum: 0 + maximum: 9007199254740991 + ValidateMediaBuyBudgetInput: + type: object + properties: + tacticId: + type: number + newBudgetAmount: + type: number + minimum: 0 + exclusiveMinimum: true + required: + - tacticId + - newBudgetAmount + ListNotificationsInput: + type: object + properties: + read: + type: boolean + take: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + type: integer + minimum: 0 + maximum: 9007199254740991 + MarkNotificationReadInput: + type: object + properties: + notificationId: + type: string + required: + - notificationId + MarkNotificationAcknowledgedInput: + type: object + properties: + notificationId: + type: string + required: + - notificationId + MarkAllNotificationsReadInput: + type: object + properties: {} + DiscoverProductsInput: + type: object + properties: + campaignBrief: + type: string + brandManifestUrl: + type: string + deliveryType: + type: string + enum: + - guaranteed + - non_guaranteed + formats: + type: array + items: + type: string + enum: + - audio + - display + - html5 + - native + - video + inventoryType: + type: string + enum: + - premium + - run_of_site + - targeted_package + maxCpm: + type: number + minimum: 0 + exclusiveMinimum: true + minCpm: + type: number + minimum: 0 + exclusiveMinimum: true + publisherIds: + type: array + items: + type: string + salesAgentId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + SaveProductInput: + type: object + properties: + productId: + type: string + name: + type: string + description: + type: string + publisherId: + type: string + publisherName: + type: string + deliveryType: + type: string + enum: + - guaranteed + - non_guaranteed + inventoryType: + type: string + enum: + - premium + - run_of_site + - targeted_package + creativeFormats: + anyOf: + - type: array + items: + type: string + - type: array + items: + type: object + properties: + agent_url: + type: string + id: + type: string + required: + - agent_url + - id + pricingModel: + type: string + enum: + - auction + - fixed_cpm + fixedCpm: + type: number + minimum: 0 + exclusiveMinimum: true + floorCpm: + type: number + minimum: 0 + exclusiveMinimum: true + targetCpm: + type: number + minimum: 0 + exclusiveMinimum: true + pricingOptions: + type: array + items: + type: object + additionalProperties: {} + supportedTargeting: + type: array + items: + type: string + adcpAgentId: + type: string + required: + - productId + - name + - description + - publisherId + - publisherName + - deliveryType + - inventoryType + - pricingModel + ListProductsInput: + type: object + properties: + take: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + type: integer + minimum: 0 + maximum: 9007199254740991 + SyncProductsInput: + type: object + properties: + sourceId: + type: string + required: + - sourceId + GetSalesAgentInput: + type: object + properties: + agentId: + type: string + required: + - agentId + ListSalesAgentsInput: + type: object + properties: {} + RegisterSalesAgentInput: + type: object + properties: + name: + type: string + minLength: 1 + description: + type: string + endpointUrl: + type: string + format: uri + protocol: + type: string + enum: + - MCP + - A2A + authenticationType: + type: string + enum: + - API_KEY + - OAUTH + - NO_AUTH + organizationId: + type: string + authConfig: + type: object + additionalProperties: {} + required: + - name + - endpointUrl + - protocol + - authenticationType + UnregisterSalesAgentInput: + type: object + properties: + agentId: + type: string + required: + - agentId + UpdateSalesAgentInput: + type: object + properties: + agentId: + type: string + name: + type: string + organization: + type: string + required: + - agentId + ListSalesAgentAccountsInput: + type: object + properties: + agentId: + type: string + required: + - agentId + RegisterSalesAgentAccountInput: + type: object + properties: + salesAgentId: + type: string + accountIdentifier: + type: string + authConfig: + type: object + additionalProperties: {} + required: + - salesAgentId + - accountIdentifier + UnregisterSalesAgentAccountInput: + type: object + properties: + accountId: + type: string + required: + - accountId + UpdateSalesAgentAccountInput: + type: object + properties: + accountId: + type: string + accountData: + type: object + additionalProperties: {} + required: + - accountId + - accountData + CreateTacticInput: + type: object + properties: + campaignId: + type: string + name: + type: string + minLength: 1 + prompt: + type: string + channelCodes: + type: array + items: + type: string + enum: + - ctv + - video + - display + - app + - social + countryCodes: + type: array + items: + type: string + required: + - campaignId + - name + UpdateTacticInput: + type: object + properties: + tacticId: + type: number + name: + type: string + prompt: + type: string + channelCodes: + type: array + items: + type: string + enum: + - ctv + - video + - display + - app + - social + countryCodes: + type: array + items: + type: string + required: + - tacticId + DeleteTacticInput: + type: object + properties: + tacticId: + type: number + required: + - tacticId + GetTacticInput: + type: object + properties: + tacticId: + type: number + required: + - tacticId + ListTacticsInput: + type: object + properties: + campaignId: + type: string + take: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + type: integer + minimum: 0 + maximum: 9007199254740991 + LinkCampaignToTacticInput: + type: object + properties: + tacticId: + type: number + campaignId: + type: string + required: + - tacticId + - campaignId + UnlinkCampaignFromTacticInput: + type: object + properties: + tacticId: + type: number + campaignId: + type: string + required: + - tacticId + - campaignId + RegisterWebhookInput: + type: object + properties: + brandAgentId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + endpoint: + type: object + properties: + url: + type: string + format: uri + method: + type: string + enum: + - POST + - PUT + headers: + type: object + additionalProperties: + type: string + authentication: + type: object + properties: + type: + type: string + enum: + - bearer + - basic + - hmac + credentials: + type: string + required: + - type + - credentials + required: + - url + - method + eventTypes: + type: array + items: + type: string + filters: + type: object + properties: + campaigns: + type: array + items: + type: string + tactics: + type: array + items: + type: string + creatives: + type: array + items: + type: string + mediaBuys: + type: array + items: + type: string + metrics: + type: array + items: + type: string + minSeverity: + type: string + enum: + - info + - warning + - critical + retryPolicy: + type: object + properties: + maxRetries: + type: integer + minimum: 0 + maximum: 9007199254740991 + backoffMultiplier: + type: number + minimum: 0 + exclusiveMinimum: true + maxBackoffSeconds: + type: number + minimum: 0 + exclusiveMinimum: true + required: + - endpoint + - eventTypes + ListWebhooksInput: + type: object + properties: + take: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + skip: + type: integer + minimum: 0 + maximum: 9007199254740991 + DeleteWebhookInput: + type: object + properties: + webhookId: + type: string + required: + - webhookId + BrandAgentUpdate: + type: object + properties: + id: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + type: string + description: + type: string + manifestUrl: + type: string + format: uri + customerId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - customerId + - createdAt + - updatedAt + BrandStandardsCreate: + type: object + properties: + id: + type: string + name: + type: string + description: + type: string + countryCodes: + type: array + items: + type: string + channelCodes: + type: array + items: + type: string + brands: + type: array + items: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - countryCodes + - channelCodes + - brands + - createdAt + - updatedAt + CampaignUpdate: + type: object + properties: + id: + type: string + name: + type: string + status: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - status + - createdAt + - updatedAt + CreativeGet: + type: object + properties: + creativeId: + type: string + name: + type: string + status: + type: string + campaignId: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - creativeId + - name + - status + - createdAt + - updatedAt + MediaBuyGet: + type: object + properties: + id: + type: string + tacticId: + type: number + status: + type: string + archivedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - tacticId + - status + - createdAt + - updatedAt + TacticGet: + type: object + properties: + id: + type: number + name: + type: string + prompt: + type: string + campaignIds: + type: array + items: + type: string + channelCodes: + type: array + items: + type: string + countryCodes: + type: array + items: + type: string + mediaBuyCount: + type: integer + minimum: 0 + maximum: 9007199254740991 + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + archivedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - channelCodes + - countryCodes + - createdAt + - updatedAt + MCPContent: + type: object + properties: + type: + type: string + enum: + - text + text: + type: string + required: + - type + - text + additionalProperties: false + BadRequest: + description: Bad request error response + type: object + properties: + error: + type: string + message: + type: string + required: + - error + additionalProperties: false + Unauthorized: + description: Unauthorized error response + type: object + properties: + error: + type: string + message: + type: string + required: + - error + additionalProperties: false + InternalError: + description: Internal server error response + type: object + properties: + error: + type: string + message: + type: string + required: + - error + additionalProperties: false + AssetList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + type: object + properties: + assetId: + type: string + originalFilename: + type: string + assetType: + type: string + size: + type: number + brandAgentId: + type: string + customerId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + signedUrl: + type: string + tags: + type: array + items: + type: string + required: + - assetId + - originalFilename + - assetType + - size + - brandAgentId + - customerId + - signedUrl + additionalProperties: false + required: + - total + - items + additionalProperties: false + BrandAgentList: + type: object + properties: + brandAgents: + type: array + items: + $ref: '#/components/schemas/BrandAgentUpdateOutput' + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - brandAgents + - total + additionalProperties: false + BrandAgentDelete: + type: object + properties: + success: + type: boolean + deletedId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + required: + - success + - deletedId + additionalProperties: false + BrandStandardsDelete: + type: object + properties: + success: + type: boolean + id: + type: string + required: + - success + - id + additionalProperties: false + BrandStandardsList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + $ref: '#/components/schemas/BrandStandardsCreateOutput' + required: + - total + - items + additionalProperties: false + BrandStoryCreate: + type: object + properties: + id: + type: string + name: + type: string + brandAgentId: + type: string + countryCodes: + type: array + items: + type: string + channelCodes: + type: array + items: + type: string + languages: + type: array + items: + type: string + brands: + type: array + items: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - createdAt + - updatedAt + additionalProperties: false + BrandStoryUpdate: + type: object + properties: + id: + type: string + name: + type: string + prompt: + type: string + status: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - createdAt + - updatedAt + additionalProperties: false + BrandStoryDelete: + type: object + properties: + success: + type: boolean + id: + type: string + required: + - success + - id + additionalProperties: false + BrandStoryList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + description: + type: string + status: + type: string + type: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - status + - type + - createdAt + - updatedAt + additionalProperties: false + required: + - total + - items + additionalProperties: false + CampaignList: + type: object + properties: + campaigns: + type: array + items: + $ref: '#/components/schemas/CampaignUpdateOutput' + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - campaigns + - total + additionalProperties: false + CampaignDelete: + type: object + properties: + success: + type: boolean + deletedId: + type: string + required: + - success + - deletedId + additionalProperties: false + CampaignGetSummary: + type: object + properties: + campaignId: + type: string + summary: + type: object + additionalProperties: {} + required: + - campaignId + - summary + additionalProperties: false + CampaignListTactics: + type: object + properties: + tactics: + type: array + items: {} + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - tactics + - total + additionalProperties: false + CampaignValidateBrief: + type: object + properties: + valid: + type: boolean + feedback: + type: string + required: + - valid + additionalProperties: false + ChannelList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + type: object + properties: + channel: + type: string + displayName: + type: string + required: + - channel + - displayName + additionalProperties: false + required: + - total + - items + additionalProperties: false + CreativeAssign: + type: object + properties: + success: + type: boolean + creativeId: + type: string + campaignId: + type: string + required: + - success + - creativeId + - campaignId + additionalProperties: false + CreativeDelete: + type: object + properties: + success: + type: boolean + id: + type: string + required: + - success + - id + additionalProperties: false + CreativeList: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/CreativeGetOutput' + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - items + - total + additionalProperties: false + CreativeSyncSalesAgents: + type: object + properties: + success: + type: boolean + creativeId: + type: string + campaignId: + type: string + required: + - success + - creativeId + additionalProperties: false + MediaBuyDelete: + type: object + properties: + success: + type: boolean + id: + type: string + required: + - success + - id + additionalProperties: false + MediaBuyExecute: + type: object + properties: + success: + type: boolean + mediaBuyId: + type: string + status: + type: string + adcpMediaBuyId: + type: string + adcpStatus: + type: string + required: + - success + - mediaBuyId + - status + additionalProperties: false + MediaBuyList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + $ref: '#/components/schemas/MediaBuyGetOutput' + required: + - total + - items + additionalProperties: false + MediaBuyValidateBudget: + type: object + properties: + valid: + type: boolean + message: + type: string + required: + - valid + additionalProperties: false + NotificationsList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + hasMore: + type: boolean + items: + type: array + items: + type: object + properties: + id: + type: string + type: + type: string + data: + type: object + additionalProperties: {} + read: + type: boolean + acknowledged: + type: boolean + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - type + - data + - read + - acknowledged + - createdAt + additionalProperties: false + required: + - total + - hasMore + - items + additionalProperties: false + NotificationsMarkRead: + type: object + properties: + success: + type: boolean + notificationId: + type: string + required: + - success + - notificationId + additionalProperties: false + NotificationsMarkAcknowledged: + type: object + properties: + success: + type: boolean + notificationId: + type: string + required: + - success + - notificationId + additionalProperties: false + NotificationsMarkAllRead: + type: object + properties: + success: + type: boolean + count: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - success + - count + additionalProperties: false + MediaProductDiscover: + type: object + properties: + success: + type: boolean + productsFound: + type: integer + minimum: 0 + maximum: 9007199254740991 + productsSaved: + type: integer + minimum: 0 + maximum: 9007199254740991 + successfulAgents: + type: integer + minimum: 0 + maximum: 9007199254740991 + failedAgents: + type: integer + minimum: 0 + maximum: 9007199254740991 + products: + type: array + items: + type: object + properties: + productId: + type: string + name: + type: string + publisherName: + type: string + salesAgentId: + type: string + salesAgentName: + type: string + deliveryType: + type: string + enum: + - guaranteed + - non_guaranteed + inventoryType: + type: string + enum: + - premium + - run_of_site + - targeted_package + creativeFormats: + anyOf: + - type: array + items: + type: string + - type: array + items: + type: object + properties: + agent_url: + type: string + id: + type: string + required: + - agent_url + - id + additionalProperties: false + fixedCpm: + type: number + floorCpm: + type: number + targetCpm: + type: number + required: + - productId + - name + - publisherName + - deliveryType + - inventoryType + additionalProperties: false + required: + - success + - productsFound + - productsSaved + - successfulAgents + - failedAgents + - products + additionalProperties: false + MediaProductSave: + type: object + properties: + id: + type: string + productId: + type: string + name: + type: string + publisherId: + type: string + publisherName: + type: string + customerId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - productId + - name + - publisherId + - publisherName + - customerId + - createdAt + - updatedAt + additionalProperties: false + MediaProductList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + type: object + properties: + id: + type: string + productId: + type: string + name: + type: string + salesAgent: + type: string + salesAgentId: + type: string + salesAgentName: + type: string + deliveryType: + type: string + enum: + - guaranteed + - non_guaranteed + format: + type: string + creativeFormats: + anyOf: + - type: array + items: + type: string + - type: array + items: + type: object + properties: + agent_url: + type: string + id: + type: string + required: + - agent_url + - id + additionalProperties: false + required: + - id + - productId + - name + - deliveryType + additionalProperties: false + required: + - total + - items + additionalProperties: false + MediaProductSync: + type: object + properties: + success: + type: boolean + productsSaved: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - success + - productsSaved + additionalProperties: false + SalesAgentGet: + type: object + properties: + id: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + type: string + status: + type: string + relationship: + type: string + endpointUrl: + type: string + protocol: + type: string + authenticationType: + type: string + description: + type: string + customerAccountCount: + type: integer + minimum: 0 + maximum: 9007199254740991 + organizationId: + type: string + registeredBy: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - status + - relationship + - endpointUrl + - protocol + - authenticationType + - customerAccountCount + - createdAt + - updatedAt + additionalProperties: false + SalesAgentList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + type: object + properties: + id: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + type: string + status: + type: string + relationship: + type: string + endpointUrl: + type: string + protocol: + type: string + customerAccountCount: + type: integer + minimum: 0 + maximum: 9007199254740991 + required: + - id + - name + - status + - relationship + - endpointUrl + - protocol + - customerAccountCount + additionalProperties: false + required: + - total + - items + additionalProperties: false + SalesAgentRegister: + type: object + properties: + id: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + type: string + status: + type: string + endpointUrl: + type: string + required: + - id + - name + - status + - endpointUrl + additionalProperties: false + SalesAgentUnregister: + type: object + properties: + success: + type: boolean + id: + type: string + required: + - success + - id + additionalProperties: false + SalesAgentUpdate: + type: object + properties: + id: + type: string + name: + type: string + status: + type: string + required: + - id + - name + - status + additionalProperties: false + SalesAgentAccountList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + type: object + properties: + id: + type: string + accountIdentifier: + type: string + status: + type: string + registeredBy: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - accountIdentifier + - status + - createdAt + - updatedAt + additionalProperties: false + required: + - total + - items + additionalProperties: false + SalesAgentAccountRegister: + type: object + properties: + accountId: + type: string + adcpAgentId: + type: string + status: + type: string + required: + - accountId + - adcpAgentId + - status + additionalProperties: false + SalesAgentAccountUnregister: + type: object + properties: + success: + type: boolean + salesAgentId: + type: string + required: + - success + - salesAgentId + additionalProperties: false + SalesAgentAccountUpdate: + type: object + properties: + id: + type: string + status: + type: string + required: + - id + - status + additionalProperties: false + TacticCreate: + type: object + properties: + id: + type: number + name: + type: string + prompt: + type: string + campaignId: + type: string + channelCodes: + type: array + items: + type: string + countryCodes: + type: array + items: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - campaignId + - channelCodes + - countryCodes + - createdAt + additionalProperties: false + TacticDelete: + type: object + properties: + success: + type: boolean + tacticId: + type: number + required: + - success + - tacticId + additionalProperties: false + TacticList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: + $ref: '#/components/schemas/TacticGetOutput' + required: + - total + - items + additionalProperties: false + TacticLinkCampaign: + type: object + properties: + success: + type: boolean + tacticId: + type: number + campaignId: + type: string + required: + - success + - tacticId + - campaignId + additionalProperties: false + TacticUnlinkCampaign: + type: object + properties: + success: + type: boolean + tacticId: + type: number + campaignId: + type: string + required: + - success + - tacticId + - campaignId + additionalProperties: false + WebhookRegister: + type: object + properties: + id: + type: string + brandAgentId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + endpoint: + type: object + properties: + url: + type: string + method: + type: string + authenticationType: + type: string + required: + - url + - method + additionalProperties: false + eventTypes: + type: array + items: + type: string + filters: + type: object + properties: + campaigns: + type: array + items: + type: string + tactics: + type: array + items: + type: string + creatives: + type: array + items: + type: string + mediaBuys: + type: array + items: + type: string + metrics: + type: array + items: + type: string + minSeverity: + type: string + additionalProperties: false + retryPolicy: + type: object + properties: + maxRetries: + type: integer + minimum: 0 + maximum: 9007199254740991 + backoffMultiplier: + type: number + minimum: 0 + exclusiveMinimum: true + maxBackoffSeconds: + type: number + minimum: 0 + exclusiveMinimum: true + required: + - maxRetries + - backoffMultiplier + - maxBackoffSeconds + additionalProperties: false + status: + type: string + testResult: + type: object + properties: + success: + type: boolean + statusCode: + type: integer + minimum: -9007199254740991 + maximum: 9007199254740991 + error: + type: string + required: + - success + additionalProperties: false + required: + - id + - endpoint + - eventTypes + - retryPolicy + - status + - testResult + additionalProperties: false + WebhookList: + type: object + properties: + total: + type: integer + minimum: 0 + maximum: 9007199254740991 + items: + type: array + items: type: object properties: - error: + id: type: string - description: Error message - details: + status: + type: string + endpoint: type: object - description: Additional error details - - Unauthorized: - description: Unauthorized - invalid or missing authentication - content: - application/json: - schema: - type: object - properties: - error: + properties: + url: + type: string + method: + type: string + authenticationType: + type: string + required: + - url + - method + additionalProperties: false + eventTypes: + type: array + items: + type: string + brandAgentId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + failureCount: + type: integer + minimum: 0 + maximum: 9007199254740991 + lastSuccess: + nullable: true type: string - description: Error message - - NotFound: - description: Resource not found - content: - application/json: - schema: - type: object - properties: - error: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + lastFailure: + nullable: true type: string - description: Error message - - InternalError: - description: Internal server error - content: - application/json: - schema: - type: object - properties: - error: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + createdAt: type: string - description: Error message - - schemas: - AssetUpload: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - status + - endpoint + - eventTypes + - failureCount + - createdAt + additionalProperties: false + required: + - total + - items + additionalProperties: false + WebhookDelete: type: object - required: [name, contentType, data, assetType] properties: - name: - type: string - description: '**REQUIRED**: Original filename' - example: logo.png - contentType: + success: + type: boolean + webhookId: type: string - description: '**REQUIRED**: MIME type' - example: image/png - enum: - - image/png - - image/jpeg - - image/jpg - - image/gif - - image/webp - - video/mp4 - - video/webm - - audio/mp3 - - audio/wav - - font/woff - - font/woff2 - data: - type: string - format: byte - description: '**REQUIRED**: Base64-encoded file data (without data:image/png;base64, prefix)' - example: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg== - assetType: - type: string - enum: [image, video, audio, logo, font] - description: '**REQUIRED**: Type of asset. Must be one of: image, video, audio, logo, font' - example: image - tags: - type: array - items: - type: string - description: Optional tags for organization - example: [brand, header, 2024] - - Budget: + required: + - success + - webhookId + additionalProperties: false + BrandAgentUpdateOutput: type: object - required: [total, currency] properties: - total: + id: type: integer - description: Total budget amount in cents (e.g., 5000000 = $50,000) - currency: + exclusiveMinimum: true + maximum: 9007199254740991 + name: + type: string + description: + type: string + manifestUrl: type: string - enum: [USD, EUR, GBP, CAD, AUD] - description: Budget currency - dailyCap: + format: uri + customerId: type: integer - description: Daily spending limit in cents - pacing: + exclusiveMinimum: true + maximum: 9007199254740991 + createdAt: type: string - enum: [even, accelerated, front_loaded] - description: Budget pacing tactic - - ScoringWeights: - type: object - properties: - affinity: - type: number - minimum: 0 - maximum: 1 - description: Weight for affinity scoring (0-1) - outcome: - type: number - minimum: 0 - maximum: 1 - description: Weight for outcome scoring (0-1) - quality: - type: number - minimum: 0 - maximum: 1 - description: Weight for quality scoring (0-1) - - BrandAgent: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - customerId + - createdAt + - updatedAt + additionalProperties: false + BrandStandardsCreateOutput: type: object - required: [id, name, createdAt, updatedAt] properties: id: type: string - description: Unique brand agent identifier name: type: string - description: Brand agent name description: type: string - description: Brand agent description + countryCodes: + type: array + items: + type: string + channelCodes: + type: array + items: + type: string + brands: + type: array + items: + type: string createdAt: type: string format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ updatedAt: type: string format: date-time - - Campaign: + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - countryCodes + - channelCodes + - brands + - createdAt + - updatedAt + additionalProperties: false + CampaignUpdateOutput: type: object - required: [id, name, prompt, brandAgentId, status, createdAt, updatedAt] properties: id: type: string - description: Unique campaign identifier name: type: string - description: Campaign name - prompt: + status: type: string - description: Natural language campaign description - brandAgentId: + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - status + - createdAt + - updatedAt + additionalProperties: false + CreativeGetOutput: + type: object + properties: + creativeId: + type: string + name: type: string - description: Parent brand agent ID status: type: string - enum: [active, paused, completed, draft] - description: Campaign status - budget: - $ref: '#/components/schemas/Budget' - audienceIds: + campaignId: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - creativeId + - name + - status + - createdAt + - updatedAt + additionalProperties: false + MediaBuyGetOutput: + type: object + properties: + id: + type: string + tacticId: + type: number + status: + type: string + archivedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - tacticId + - status + - createdAt + - updatedAt + additionalProperties: false + TacticGetOutput: + type: object + properties: + id: + type: number + name: + type: string + prompt: + type: string + campaignIds: type: array items: type: string - description: Associated synthetic audience IDs - creativeIds: + channelCodes: + type: array + items: + type: string + countryCodes: type: array items: type: string - description: Associated creative asset IDs + mediaBuyCount: + type: integer + minimum: 0 + maximum: 9007199254740991 createdAt: type: string format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ updatedAt: type: string format: date-time - - Creative: + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + archivedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - channelCodes + - countryCodes + - createdAt + - updatedAt + additionalProperties: false + BrandAgentGet: type: object - required: [id, name, type, url, brandAgentId, createdAt, updatedAt] properties: id: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + name: + type: string + description: + type: string + manifestUrl: type: string - description: Unique creative identifier + format: uri + customerId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - customerId + - createdAt + - updatedAt + additionalProperties: false + BrandAgentCreate: + type: object + properties: + id: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 name: type: string - description: Creative name - type: + description: type: string - enum: [video, image, native, html5] - description: Creative asset type - url: + manifestUrl: type: string format: uri - description: Creative asset URL - brandAgentId: + customerId: + type: integer + exclusiveMinimum: true + maximum: 9007199254740991 + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: type: string - description: Parent brand agent ID - headline: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - customerId + - createdAt + - updatedAt + additionalProperties: false + CampaignCreate: + type: object + properties: + id: type: string - description: Creative headline text - body: + name: type: string - description: Creative body text - cta: + status: type: string - description: Call-to-action text createdAt: type: string format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ updatedAt: type: string format: date-time - - Tactic: + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - status + - createdAt + - updatedAt + additionalProperties: false + CampaignGet: type: object - required: [id, name, campaignId, activityType, tacticType, createdAt, updatedAt] properties: id: type: string - description: Unique tactic identifier name: type: string - description: Tactic name - campaignId: + status: type: string - description: Associated campaign ID - prompt: + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: type: string - description: Tactical brief or prompt - activityType: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - status + - createdAt + - updatedAt + additionalProperties: false + CreativeCreate: + type: object + properties: + creativeId: type: string - enum: [AMP] - description: Activity type (always AMP) - tacticType: + name: + type: string + status: + type: string + campaignId: type: string - enum: [INTELLIGENT_CAMPAIGNS] - description: Tactic type - channelCodes: - type: array - items: - type: string - enum: [DIGITAL-AUDIO, DISPLAY-WEB, DISPLAY-APP, CTV-BVOD, OLV, DOOH, SOCIAL] - description: Target channels (official codes) - countryCodes: - type: array - items: - type: string - description: Target countries createdAt: type: string format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ updatedAt: type: string format: date-time - - MediaBuy: + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - creativeId + - name + - status + - createdAt + - updatedAt + additionalProperties: false + CreativeUpdate: type: object - required: [id, name, tacticId, salesAgentId, mediaProductId, budget, cpm, createdAt, updatedAt] properties: - id: + creativeId: type: string - description: Unique media buy identifier name: type: string - description: Media buy name - description: + status: + type: string + campaignId: + type: string + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - creativeId + - name + - status + - createdAt + - updatedAt + additionalProperties: false + MediaBuyCreate: + type: object + properties: + id: type: string - description: Media buy description tacticId: + type: number + status: type: string - description: Associated tactic ID - salesAgentId: + archivedAt: type: string - description: Publisher/sales agent ID - mediaProductId: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + createdAt: type: string - description: Media product ID - budget: - type: object - properties: - amount: - type: number - currency: - type: string - dailyCap: - type: number - pacing: - type: string - cpm: + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - tacticId + - status + - createdAt + - updatedAt + additionalProperties: false + MediaBuyUpdate: + type: object + properties: + id: + type: string + tacticId: type: number - description: CPM pricing - signalCost: + status: + type: string + archivedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + createdAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + updatedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - tacticId + - status + - createdAt + - updatedAt + additionalProperties: false + TacticUpdate: + type: object + properties: + id: type: number - description: Additional signal cost + name: + type: string + prompt: + type: string + campaignIds: + type: array + items: + type: string + channelCodes: + type: array + items: + type: string + countryCodes: + type: array + items: + type: string + mediaBuyCount: + type: integer + minimum: 0 + maximum: 9007199254740991 createdAt: type: string format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ updatedAt: type: string format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + archivedAt: + type: string + format: date-time + pattern: >- + ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$ + required: + - id + - name + - channelCodes + - countryCodes + - createdAt + - updatedAt + additionalProperties: false + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT diff --git a/src/types/api.ts b/src/types/api.ts index 6ca90f8..ff4517f 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -4,25 +4,12 @@ */ export interface paths { - '/asset-upload': { + '/mcp-initialize': { /** - * Upload creative assets - * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. - * - * **REQUIRED FIELDS:** - * - `brandAgentId`: Brand agent ID for file organization - * - `assets`: Array of assets (each with name, contentType, data, assetType) - * - * Returns signed URLs valid for 1 hour. + * Initialize MCP session + * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. */ - post: operations['asset_upload']; - }; - '/asset-list': { - /** - * List creative assets - * @description List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. - */ - post: operations['asset_list']; + post: operations['mcp_initialize']; }; '/brand-agent-list': { /** @@ -31,13 +18,6 @@ export interface paths { */ post: operations['brand_agent_list']; }; - '/brand-agent-create': { - /** - * Create brand agent - * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. - */ - post: operations['brand_agent_create']; - }; '/brand-agent-get': { /** * Get brand agent @@ -45,73 +25,31 @@ export interface paths { */ post: operations['brand_agent_get']; }; + '/brand-agent-create': { + /** + * Create brand agent + * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + */ + post: operations['brand_agent_create']; + }; '/brand-agent-update': { /** * Update brand agent - * @description Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. + * @description Update an existing brand agent with new information. */ post: operations['brand_agent_update']; }; '/brand-agent-delete': { /** * Delete brand agent - * @description โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. + * @description Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. */ post: operations['brand_agent_delete']; }; - '/brand-standards-list': { - /** - * List brand standards - * @description List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. - */ - post: operations['brand_standards_list']; - }; - '/brand-standards-create': { - /** - * Create brand standard - * @description Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. - */ - post: operations['brand_standards_create']; - }; - '/brand-standards-delete': { - /** - * Delete brand standard - * @description โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. - */ - post: operations['brand_standards_delete']; - }; - '/brand-story-list': { - /** - * List brand stories - * @description List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. - */ - post: operations['brand_story_list']; - }; - '/brand-story-create': { - /** - * Create brand story - * @description Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. - */ - post: operations['brand_story_create']; - }; - '/brand-story-update': { - /** - * Update brand story - * @description Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. - */ - post: operations['brand_story_update']; - }; - '/brand-story-delete': { - /** - * Delete brand story - * @description โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. - */ - post: operations['brand_story_delete']; - }; '/campaign-list': { /** * List campaigns - * @description List campaigns for the authenticated customer, with optional filtering. + * @description List all campaigns with optional filtering by brand agent. */ post: operations['campaign_list']; }; @@ -122,24 +60,31 @@ export interface paths { */ post: operations['campaign_create']; }; + '/campaign-get': { + /** + * Get campaign + * @description Get detailed information about a specific campaign. + */ + post: operations['campaign_get']; + }; '/campaign-update': { /** * Update campaign - * @description Update an existing campaign's settings. + * @description Update an existing campaign with new information. */ post: operations['campaign_update']; }; '/campaign-delete': { /** * Delete campaign - * @description โš ๏ธ DANGER - Permanently delete a campaign and all associated data. + * @description Delete a campaign and all associated resources. */ post: operations['campaign_delete']; }; '/campaign-get-summary': { /** * Get campaign summary - * @description Get detailed summary information about a specific campaign. + * @description Get a high-level summary of a campaign including key metrics and status. */ post: operations['campaign_get_summary']; }; @@ -148,208 +93,154 @@ export interface paths { * List campaign tactics * @description List all tactics associated with a specific campaign. */ - post: operations['campaign_list_strategies']; + post: operations['campaign_list_tactics']; }; '/campaign-validate-brief': { /** * Validate campaign brief - * @description Validate a campaign brief to ensure it contains all necessary information. + * @description Validate a campaign brief to ensure it contains all necessary information for campaign creation. */ post: operations['campaign_validate_brief']; }; - '/channel-list': { - /** - * List channels - * @description List all available advertising channels. - */ - post: operations['channel_list']; - }; - '/creative-list': { - /** - * List creatives - * @description List creatives for the authenticated customer, with optional filtering. - */ - post: operations['creative_list']; - }; - '/creative-create': { - /** - * Create creative - * @description Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. - * - * **Two workflows supported:** - * 1. **Separate upload**: Use asset_upload first, then reference asset IDs in content.assetIds - * 2. **Inline upload**: Upload assets directly in the `assets` array (automatically uploaded and linked) - */ - post: operations['creative_create']; - }; - '/creative-get': { - /** - * Get creative - * @description Get detailed information about a specific creative. - */ - post: operations['creative_get']; - }; - '/creative-update': { - /** - * Update creative - * @description Update an existing creative's settings. - */ - post: operations['creative_update']; - }; - '/creative-delete': { - /** - * Delete creative - * @description โš ๏ธ DANGER - Permanently delete a creative. - */ - post: operations['creative_delete']; - }; - '/creative-assign': { + '/asset-list': { /** - * Assign creative to campaign - * @description Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents - * associated with the campaign via active media buys. Returns auto-sync results including which agents - * received the creative and their approval status. + * List assets + * @description List all uploaded assets with optional filtering by brand agent. */ - post: operations['creative_assign']; + post: operations['asset_list']; }; - '/creative-sync-sales-agents': { + '/brand-standards-create': { /** - * Sync creative with sales agents - * @description Sync a creative to sales agents using smart auto-detection or manual specification. - * Features intelligent format matching and recent activity analysis (30-60 day lookback). - * Provides detailed sync status and actionable next steps. + * Create brand standards + * @description Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. */ - post: operations['creative_sync_sales_agents']; + post: operations['brand_standards_create']; }; - '/sales-agent-list': { + '/brand-standards-delete': { /** - * List sales agents - * @description List all registered sales agents (publishers) for the authenticated customer. + * Delete brand standards + * @description Delete brand standards for a brand agent. */ - post: operations['sales_agent_list']; + post: operations['brand_standards_delete']; }; - '/sales-agent-get': { + '/brand-standards-list': { /** - * Get sales agent - * @description Get detailed information about a specific sales agent. + * List brand standards + * @description List all brand standards with optional filtering by brand agent. */ - post: operations['sales_agent_get']; + post: operations['brand_standards_list']; }; - '/sales-agent-register': { + '/brand-story-create': { /** - * Register sales agent - * @description Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. + * Create brand story + * @description Create a brand story containing the narrative, history, values, and key messaging for a brand agent. */ - post: operations['sales_agent_register']; + post: operations['brand_story_create']; }; - '/sales-agent-account-list': { + '/brand-story-update': { /** - * List accounts for a sales agent - * @description List all accounts registered by your organization for a specific sales agent. + * Update brand story + * @description Update an existing brand story with new information. */ - post: operations['sales_agent_account_list']; + post: operations['brand_story_update']; }; - '/sales-agent-account-register': { + '/brand-story-delete': { /** - * Register account for sales agent - * @description Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. + * Delete brand story + * @description Delete a brand story. */ - post: operations['sales_agent_account_register']; + post: operations['brand_story_delete']; }; - '/sales-agent-unregister': { + '/brand-story-list': { /** - * Unregister sales agent completely - * @description Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. + * List brand stories + * @description List all brand stories with optional filtering by brand agent. */ - post: operations['sales_agent_unregister']; + post: operations['brand_story_list']; }; - '/sales-agent-account-unregister': { + '/channel-list': { /** - * Unregister your account with a sales agent - * @description Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. + * List channels + * @description List all available advertising channels and platforms. */ - post: operations['sales_agent_account_unregister']; + post: operations['channel_list']; }; - '/sales-agent-update': { + '/creative-assign': { /** - * Update sales agent - * @description Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. + * Assign creative + * @description Assign a creative to a tactic or media buy. */ - post: operations['sales_agent_update']; + post: operations['creative_assign']; }; - '/sales-agent-account-update': { + '/creative-create': { /** - * Update sales agent account authentication - * @description Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. + * Create creative + * @description Create a new creative with assets, copy, and targeting specifications. */ - post: operations['sales_agent_account_update']; + post: operations['creative_create']; }; - '/tactic-list': { + '/creative-update': { /** - * List tactics - * @description List all media buying tactics for the authenticated customer. + * Update creative + * @description Update an existing creative with new assets, copy, or specifications. */ - post: operations['strategy_list']; + post: operations['creative_update']; }; - '/tactic-create': { + '/creative-delete': { /** - * Create tactic - * @description Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. + * Delete creative + * @description Delete a creative and remove it from any associated tactics or media buys. */ - post: operations['strategy_create']; + post: operations['creative_delete']; }; - '/tactic-get': { + '/creative-get': { /** - * Get tactic - * @description Get detailed information about a specific tactic. + * Get creative + * @description Get detailed information about a specific creative. */ - post: operations['strategy_get']; + post: operations['creative_get']; }; - '/tactic-update': { + '/creative-list': { /** - * Update tactic - * @description Update an existing tactic's configuration. + * List creatives + * @description List all creatives with optional filtering by brand agent or campaign. */ - post: operations['strategy_update']; + post: operations['creative_list']; }; - '/tactic-delete': { + '/creative-sync-sales-agents': { /** - * Delete tactic - * @description โš ๏ธ DANGER - Permanently delete a tactic. + * Sync creatives to sales agents + * @description Synchronize creatives to connected sales agents (DSPs, publisher platforms). */ - post: operations['strategy_delete']; + post: operations['creative_sync_sales_agents']; }; - '/tactic-link-campaign': { + '/media-buy-create': { /** - * Link campaign to tactic - * @description Link a campaign to a tactic for budget and execution management. + * Create media buy + * @description Create a new media buy with budget, targeting, and creative specifications. */ - post: operations['strategy_link_campaign']; + post: operations['media_buy_create']; }; - '/tactic-unlink-campaign': { + '/media-buy-update': { /** - * Unlink campaign from tactic - * @description Unlink a campaign from a tactic. + * Update media buy + * @description Update an existing media buy with new budget, targeting, or creative assignments. */ - post: operations['strategy_unlink_campaign']; + post: operations['media_buy_update']; }; - '/media-buy-list': { + '/media-buy-delete': { /** - * List media buys - * @description List all media buys for the authenticated customer. + * Delete media buy + * @description Delete a media buy and cancel any active placements. */ - post: operations['media_buy_list']; + post: operations['media_buy_delete']; }; - '/media-buy-create': { + '/media-buy-execute': { /** - * Create media buy - * @description Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. - * - * **Multi-Product Support**: Media buys now support multiple products from different sales agents in a single buy. Each product can have its own budget allocation and pricing. During execution, each unique sales agent will receive a separate ADCP submission. - * - * **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. + * Execute media buy + * @description Execute a media buy, sending it to the configured sales agents for placement. */ - post: operations['media_buy_create']; + post: operations['media_buy_execute']; }; '/media-buy-get': { /** @@ -358,31 +249,24 @@ export interface paths { */ post: operations['media_buy_get']; }; - '/media-buy-update': { - /** - * Update media buy - * @description Update an existing media buy's configuration. - */ - post: operations['media_buy_update']; - }; - '/media-buy-delete': { + '/media-buy-list': { /** - * Delete media buy - * @description โš ๏ธ DANGER - Permanently delete a media buy. + * List media buys + * @description List all media buys with optional filtering by brand agent, campaign, or status. */ - post: operations['media_buy_delete']; + post: operations['media_buy_list']; }; - '/media-buy-execute': { + '/media-buy-validate-budget': { /** - * Execute media buy - * @description Execute a media buy by deploying it to the publisher platform. + * Validate media buy budget + * @description Validate a media buy budget against campaign constraints and available funds. */ - post: operations['media_buy_execute']; + post: operations['media_buy_validate_budget']; }; '/notifications-list': { /** * List notifications - * @description List notifications for the authenticated user. + * @description List notifications for the authenticated user with optional filtering by status. */ post: operations['notifications_list']; }; @@ -403,1878 +287,4697 @@ export interface paths { '/notifications-mark-all-read': { /** * Mark all notifications as read - * @description Mark all notifications as read for the authenticated user. + * @description Mark all notifications for the authenticated user as read. */ post: operations['notifications_mark_all_read']; }; - '/media-product-list': { - /** - * List media products - * @description List available media products from publishers. - */ - post: operations['media_product_list']; - }; '/media-product-discover': { /** * Discover media products - * @description Discover new media products from connected publishers. + * @description Discover available media products from connected sales agents based on targeting criteria. */ post: operations['media_product_discover']; }; + '/media-product-save': { + /** + * Save media product + * @description Save a discovered media product for future use in media buys. + */ + post: operations['media_product_save']; + }; + '/media-product-list': { + /** + * List media products + * @description List saved media products with optional filtering. + */ + post: operations['media_product_list']; + }; '/media-product-sync': { /** * Sync media products - * @description Synchronize media product inventory with publisher systems. + * @description Synchronize media product catalog from connected sales agents. */ post: operations['media_product_sync']; }; -} - -export type webhooks = Record; - -export interface components { - schemas: { - AssetUpload: { - /** - * @description **REQUIRED**: Original filename - * @example logo.png - */ - name: string; - /** - * @description **REQUIRED**: MIME type - * @example image/png - * @enum {string} - */ - contentType: - | 'image/png' - | 'image/jpeg' - | 'image/jpg' - | 'image/gif' - | 'image/webp' - | 'video/mp4' - | 'video/webm' - | 'audio/mp3' - | 'audio/wav' - | 'font/woff' - | 'font/woff2'; - /** - * Format: byte - * @description **REQUIRED**: Base64-encoded file data (without data:image/png;base64, prefix) - * @example iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg== - */ - data: string; - /** - * @description **REQUIRED**: Type of asset. Must be one of: image, video, audio, logo, font - * @example image - * @enum {string} - */ - assetType: 'image' | 'video' | 'audio' | 'logo' | 'font'; - /** - * @description Optional tags for organization - * @example [ - * "brand", - * "header", - * 2024 - * ] - */ - tags?: string[]; - }; - Budget: { - /** @description Total budget amount in cents (e.g., 5000000 = $50,000) */ - total: number; - /** - * @description Budget currency - * @enum {string} - */ - currency: 'USD' | 'EUR' | 'GBP' | 'CAD' | 'AUD'; - /** @description Daily spending limit in cents */ - dailyCap?: number; + '/sales-agent-get': { + /** + * Get sales agent + * @description Get detailed information about a specific sales agent (DSP, publisher platform). + */ + post: operations['sales_agent_get']; + }; + '/sales-agent-list': { + /** + * List sales agents + * @description List all registered sales agents (DSPs, publisher platforms). + */ + post: operations['sales_agent_list']; + }; + '/sales-agent-register': { + /** + * Register sales agent + * @description Register a new sales agent (DSP, publisher platform) for media buying. + */ + post: operations['sales_agent_register']; + }; + '/sales-agent-unregister': { + /** + * Unregister sales agent + * @description Unregister a sales agent and disconnect it from the platform. + */ + post: operations['sales_agent_unregister']; + }; + '/sales-agent-update': { + /** + * Update sales agent + * @description Update sales agent configuration and credentials. + */ + post: operations['sales_agent_update']; + }; + '/sales-agent-account-list': { + /** + * List sales agent accounts + * @description List all accounts (seats, advertisers) within a sales agent. + */ + post: operations['sales_agent_account_list']; + }; + '/sales-agent-account-register': { + /** + * Register sales agent account + * @description Register a new account (seat, advertiser) within a sales agent. + */ + post: operations['sales_agent_account_register']; + }; + '/sales-agent-account-unregister': { + /** + * Unregister sales agent account + * @description Unregister an account from a sales agent. + */ + post: operations['sales_agent_account_unregister']; + }; + '/sales-agent-account-update': { + /** + * Update sales agent account + * @description Update account configuration within a sales agent. + */ + post: operations['sales_agent_account_update']; + }; + '/tactic-create': { + /** + * Create tactic + * @description Create a new tactic defining how to achieve campaign objectives. + */ + post: operations['tactic_create']; + }; + '/tactic-update': { + /** + * Update tactic + * @description Update an existing tactic with new targeting, budget, or creative requirements. + */ + post: operations['tactic_update']; + }; + '/tactic-delete': { + /** + * Delete tactic + * @description Delete a tactic and all associated media buys. + */ + post: operations['tactic_delete']; + }; + '/tactic-get': { + /** + * Get tactic + * @description Get detailed information about a specific tactic. + */ + post: operations['tactic_get']; + }; + '/tactic-list': { + /** + * List tactics + * @description List all tactics with optional filtering by brand agent or campaign. + */ + post: operations['tactic_list']; + }; + '/tactic-link-campaign': { + /** + * Link tactic to campaign + * @description Link a tactic to a campaign. + */ + post: operations['tactic_link_campaign']; + }; + '/tactic-unlink-campaign': { + /** + * Unlink tactic from campaign + * @description Unlink a tactic from a campaign. + */ + post: operations['tactic_unlink_campaign']; + }; + '/webhook-register': { + /** + * Register webhook + * @description Register a webhook to receive real-time notifications about events. + */ + post: operations['webhook_register']; + }; + '/webhook-list': { + /** + * List webhooks + * @description List all registered webhooks. + */ + post: operations['webhook_list']; + }; + '/webhook-delete': { + /** + * Delete webhook + * @description Delete a registered webhook. + */ + post: operations['webhook_delete']; + }; +} + +export type webhooks = Record; + +export interface components { + schemas: { + ListAssetsInput: { + /** @description Optional brand agent ID to filter assets */ + brandAgentId?: number; + }; + /** @description Parameters for listing brand agents. Authentication is automatic. */ + ListBrandAgentsInput: { + /** @description Prisma-style where clause for filtering agents */ + where?: { + [key: string]: unknown; + }; + /** @description Prisma-style orderBy clause */ + orderBy?: { + [key: string]: unknown; + }; /** - * @description Budget pacing tactic - * @enum {string} + * @description Number of records to return + * @example 10 + */ + take?: number; + /** + * @description Number of records to skip + * @example 0 + */ + skip?: number; + /** @description Fields to use for distinct selection */ + distinct?: string[]; + }; + /** @description Parameters for retrieving a specific brand agent */ + GetBrandAgentInput: { + /** + * @description The unique identifier for the brand agent + * @example 123 + */ + brandAgentId: number; + }; + /** @description Parameters for creating a new brand agent */ + CreateBrandAgentInput: { + /** + * @description Name of the brand agent (advertiser account) + * @example Nike Global Campaigns */ - pacing?: 'even' | 'accelerated' | 'front_loaded'; - }; - ScoringWeights: { - /** @description Weight for affinity scoring (0-1) */ - affinity?: number; - /** @description Weight for outcome scoring (0-1) */ - outcome?: number; - /** @description Weight for quality scoring (0-1) */ - quality?: number; - }; - BrandAgent: { - /** @description Unique brand agent identifier */ - id: string; - /** @description Brand agent name */ name: string; - /** @description Brand agent description */ + /** + * @description Optional description of the brand agent + * @example Brand agent for Nike global advertising campaigns + */ description?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; + /** + * Format: uri + * @description URL to the brand manifest + * @example https://example.com/brand-manifest + */ + manifestUrl?: string; + /** + * @description Advertising channels to enable + * @example [ + * "app", + * "display", + * "ctv" + * ] + */ + channels?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; + /** + * @description Country codes (ISO 3166-1 alpha-2) + * @example [ + * "US", + * "CA", + * "GB" + * ] + */ + countryCodes?: string[]; + /** + * @description Language codes (ISO 639-1) + * @example [ + * "en", + * "es", + * "fr" + * ] + */ + languages?: string[]; }; - Campaign: { - /** @description Unique campaign identifier */ - id: string; - /** @description Campaign name */ + /** @description Parameters for updating a brand agent */ + UpdateBrandAgentInput: { + /** + * @description The unique identifier for the brand agent + * @example 123 + */ + brandAgentId: number; + /** @description Updated name of the brand agent */ + name?: string; + /** @description Updated description */ + description?: string; + /** + * Format: uri + * @description Updated URL to the brand manifest + * @example https://example.com/brand-manifest + */ + manifestUrl?: string; + /** @description Updated channels */ + channels?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; + /** @description Updated country codes */ + countryCodes?: string[]; + /** @description Updated language codes */ + languages?: string[]; + }; + /** @description Parameters for deleting a brand agent */ + DeleteBrandAgentInput: { + /** + * @description The unique identifier for the brand agent to delete + * @example 123 + */ + brandAgentId: number; + }; + CreateBrandStandardInput: { + /** @description Brand agent ID */ + brandAgentId: number; + /** @description Standard name */ + name?: string; + /** @description Standard description */ + description?: string; + /** @description Brand standards prompt */ + prompt: string; + /** @description Whether this is the primary standard */ + isPrimary?: boolean; + /** @description Country codes */ + countries?: string[]; + /** @description Channel types */ + channels?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; + /** @description Brand names */ + brands?: string[]; + }; + DeleteBrandStandardInput: { + /** @description Brand standard ID */ + brandStandardId: string; + }; + ListBrandStandardsInput: { + /** @description Prisma-style where clause for filtering standards */ + where?: { + [key: string]: unknown; + }; + /** @description Prisma-style orderBy clause */ + orderBy?: { + [key: string]: unknown; + }; + /** @description Number of records to return */ + take?: number; + /** @description Number of records to skip */ + skip?: number; + /** @description Fields to use for distinct selection */ + distinct?: string[]; + }; + CreateBrandStoryInput: { + /** @description Brand agent ID (bigint or string) */ + brandAgentId: number | string; + /** @description Story name */ name: string; - /** @description Natural language campaign description */ + /** @description Story description */ + description?: string; + /** @description Brand story prompt */ + prompt?: string; + /** @description Whether this is the primary story */ + isPrimary: boolean; + /** @description Channel codes */ + channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; + /** @description Country codes */ + countryCodes?: string[]; + /** @description Brand names */ + brands?: string[]; + /** @description Language codes */ + languages?: string[]; + }; + UpdateBrandStoryInput: { + /** @description Story name */ + name?: string; + /** @description Previous model ID (bigint or string) */ + previousModelId: number | string; + /** @description Updated brand story prompt */ prompt: string; - /** @description Parent brand agent ID */ - brandAgentId: string; + }; + DeleteBrandStoryInput: { + /** @description Brand story ID */ + brandStoryId: string; + }; + ListBrandStoriesInput: { + /** @description Filtering criteria */ + where?: { + [key: string]: unknown; + }; + /** @description Ordering criteria */ + orderBy?: { + [key: string]: unknown; + }; + /** @description Number of records to return */ + take?: number; + /** @description Number of records to skip */ + skip?: number; + /** @description Fields to use for distinct selection */ + distinct?: string[]; + }; + /** @description Parameters for listing campaigns */ + ListCampaignsInput: { + /** + * @description Filter by brand agent ID + * @example 123 + */ + brandAgentId?: number; /** - * @description Campaign status + * @description Filter by campaign status * @enum {string} */ - status: 'active' | 'paused' | 'completed' | 'draft'; - budget?: components['schemas']['Budget']; - /** @description Associated synthetic audience IDs */ - audienceIds?: string[]; - /** @description Associated creative asset IDs */ - creativeIds?: string[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; + /** + * @description Number of results to return + * @example 50 + */ + limit?: number; + /** + * @description Number of results to skip for pagination + * @example 0 + */ + offset?: number; }; - Creative: { - /** @description Unique creative identifier */ - id: string; - /** @description Creative name */ - name: string; + /** @description Parameters for creating a new campaign */ + CreateCampaignInput: { + /** + * @description Brand agent ID that will own this campaign + * @example 123 + */ + brandAgentId: number; + /** + * @description Optional name for the campaign (auto-generated if not provided) + * @example Summer 2025 Tech Campaign + */ + name?: string; + /** + * @description Natural language description of campaign requirements. The backend will parse this to extract targeting, budget, and creative requirements. + * @example Create a video campaign targeting tech enthusiasts aged 25-45 with $50k budget + */ + prompt: string; + /** @description Budget configuration for the campaign */ + budget?: { + total: number; + /** @default USD */ + currency?: string; + dailyCap?: number; + /** @enum {string} */ + pacing?: 'EVEN' | 'ASAP' | 'FRONTLOADED'; + }; + /** + * Format: date-time + * @description Campaign start date (ISO 8601 format) + * @example 2025-01-15T00:00:00Z + */ + startDate?: string; + /** + * Format: date-time + * @description Campaign end date (ISO 8601 format) + * @example 2025-03-31T23:59:59Z + */ + endDate?: string; + /** @description Scoring weights for campaign optimization */ + scoringWeights?: { + affinity?: number; + outcome?: number; + quality?: number; + }; + /** + * @description Number of days for outcome measurement window + * @example 30 + */ + outcomeScoreWindowDays?: number; /** - * @description Creative asset type + * @description Initial campaign status * @enum {string} */ - type: 'video' | 'image' | 'native' | 'html5'; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; + }; + /** @description Parameters for retrieving a specific campaign */ + GetCampaignInput: { /** - * Format: uri - * @description Creative asset URL + * @description The unique identifier for the campaign + * @example cmp_987654321 */ - url: string; - /** @description Parent brand agent ID */ - brandAgentId: string; - /** @description Creative headline text */ - headline?: string; - /** @description Creative body text */ - body?: string; - /** @description Call-to-action text */ - cta?: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; + campaignId: string; }; - Tactic: { - /** @description Unique tactic identifier */ - id: string; - /** @description Tactic name */ - name: string; - /** @description Associated campaign ID */ + /** @description Parameters for updating a campaign */ + UpdateCampaignInput: { + /** + * @description The unique identifier for the campaign + * @example cmp_987654321 + */ campaignId: string; - /** @description Tactical brief or prompt */ + /** @description Updated campaign name */ + name?: string; + /** @description Updated campaign prompt */ prompt?: string; + /** @description Updated budget configuration */ + budget?: { + total?: number; + /** @default USD */ + currency?: string; + dailyCap?: number; + /** @enum {string} */ + pacing?: 'EVEN' | 'ASAP' | 'FRONTLOADED'; + }; /** - * @description Activity type (always AMP) - * @enum {string} + * Format: date-time + * @description Updated start date + */ + startDate?: string; + /** + * Format: date-time + * @description Updated end date */ - activityType: 'AMP'; + endDate?: string; + /** @description Updated scoring weights */ + scoringWeights?: { + affinity?: number; + outcome?: number; + quality?: number; + }; + /** @description Updated outcome score window days */ + outcomeScoreWindowDays?: number; /** - * @description Tactic type + * @description Updated campaign status * @enum {string} */ - tacticType: 'INTELLIGENT_CAMPAIGNS'; - /** @description Target channels (official codes) */ - channelCodes?: ( - | 'DIGITAL-AUDIO' - | 'DISPLAY-WEB' - | 'DISPLAY-APP' - | 'CTV-BVOD' - | 'OLV' - | 'DOOH' - | 'SOCIAL' - )[]; - /** @description Target countries */ - countryCodes?: string[]; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; + /** @description Expected version for optimistic locking */ + expectedVersion?: number; }; - MediaBuy: { - /** @description Unique media buy identifier */ - id: string; - /** @description Media buy name */ + /** @description Parameters for deleting a campaign */ + DeleteCampaignInput: { + /** + * @description The unique identifier for the campaign to delete + * @example cmp_987654321 + */ + campaignId: string; + }; + GetCampaignSummaryInput: { + /** @description Campaign ID */ + campaignId: string; + }; + ListCampaignTacticsInput: { + /** @description Campaign ID */ + campaignId: string; + }; + ValidateBriefInput: { + /** @description Campaign brief text */ + brief: string; + }; + ListChannelsInput: Record; + AssignCreativeInput: { + creativeId: string; + campaignId: string; + }; + CreateCreativeInput: { + brandAgentId: number; + organizationId?: string; name: string; - /** @description Media buy description */ description?: string; - /** @description Associated tactic ID */ - tacticId: string; - /** @description Publisher/sales agent ID */ - salesAgentId: string; - /** @description Media product ID */ - mediaProductId: string; + /** @enum {string} */ + formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; + formatId?: string; + mediaUrl?: string; + /** @description Optional: Upload assets inline with the creative. Each asset requires: name, contentType, data (base64), and assetType. */ + assets?: { + /** @description Filename (e.g., banner.png) */ + name: string; + /** @description MIME type (e.g., image/png, image/jpeg) */ + contentType: string; + /** + * Format: byte + * @description Base64-encoded file data (without data:image/png;base64, prefix) + */ + data: string; + /** + * @description Type of asset + * @enum {string} + */ + assetType: 'image' | 'video' | 'audio' | 'logo' | 'font'; + /** @description Optional tags */ + tags?: string[]; + }[]; + content?: { + [key: string]: unknown; + }; + /** @enum {string} */ + assemblyMethod?: 'CREATIVE_AGENT' | 'ACTIVATION' | 'PUBLISHER'; + /** @description Optional campaign ID (object ID) to assign creative to */ + campaignId?: string; + version?: string; + registeredBy?: string; + }; + UpdateCreativeInput: { + creativeId: string; + name?: string; + description?: string; + assetIds?: string[]; + }; + DeleteCreativeInput: { + creativeId: string; + }; + GetCreativeInput: { + creativeId: string; + }; + ListCreativesInput: { + campaignId?: number; + brandAgentId?: number; + /** @enum {string} */ + formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; + /** @enum {string} */ + status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT'; + take?: number; + skip?: number; + }; + SyncSalesAgentsInput: { + creativeId: string; + }; + CreateMediaBuyInput: { + tacticId: number; + name: string; + description?: string; + products: { + mediaProductId: string; + salesAgentId: string; + budgetAmount?: number; + budgetCurrency?: string; + pricingCpm?: number; + pricingSignalCost?: number; + displayOrder?: number; + }[]; + creativeIds?: string[]; budget: { + amount: number; + currency: string; + dailyCap?: number; + /** @enum {string} */ + pacing: 'asap' | 'even' | 'front_loaded'; + }; + }; + UpdateMediaBuyInput: { + mediaBuyId: string; + name?: string; + description?: string; + budget?: { amount?: number; currency?: string; dailyCap?: number; - pacing?: string; + /** @enum {string} */ + pacing?: 'asap' | 'even' | 'front_loaded'; }; - /** @description CPM pricing */ - cpm: number; - /** @description Additional signal cost */ - signalCost?: number; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; + /** @enum {string} */ + status?: + | 'DRAFT' + | 'PENDING_APPROVAL' + | 'ACTIVE' + | 'PAUSED' + | 'COMPLETED' + | 'FAILED' + | 'REJECTED'; + creativeIds?: string[]; }; - }; - responses: { - /** @description Successful tool execution */ - ToolResponse: { - content: { - 'application/json': { - /** @description Whether the operation succeeded */ - success?: boolean; - /** @description Human-readable response message */ - message?: string; - /** @description Response data (varies by tool) */ - data?: Record; - }; + DeleteMediaBuyInput: { + mediaBuyId: string; + }; + ExecuteMediaBuyInput: { + mediaBuyId: string; + }; + GetMediaBuyInput: { + mediaBuyId: string; + }; + ListMediaBuysInput: { + tacticId?: number; + /** @enum {string} */ + status?: + | 'DRAFT' + | 'PENDING_APPROVAL' + | 'ACTIVE' + | 'PAUSED' + | 'COMPLETED' + | 'FAILED' + | 'REJECTED'; + take?: number; + skip?: number; + }; + ValidateMediaBuyBudgetInput: { + tacticId: number; + newBudgetAmount: number; + }; + ListNotificationsInput: { + read?: boolean; + take?: number; + skip?: number; + }; + MarkNotificationReadInput: { + notificationId: string; + }; + MarkNotificationAcknowledgedInput: { + notificationId: string; + }; + MarkAllNotificationsReadInput: Record; + DiscoverProductsInput: { + campaignBrief?: string; + brandManifestUrl?: string; + /** @enum {string} */ + deliveryType?: 'guaranteed' | 'non_guaranteed'; + formats?: ('audio' | 'display' | 'html5' | 'native' | 'video')[]; + /** @enum {string} */ + inventoryType?: 'premium' | 'run_of_site' | 'targeted_package'; + maxCpm?: number; + minCpm?: number; + publisherIds?: string[]; + salesAgentId?: number; + }; + SaveProductInput: { + productId: string; + name: string; + description: string; + publisherId: string; + publisherName: string; + /** @enum {string} */ + deliveryType: 'guaranteed' | 'non_guaranteed'; + /** @enum {string} */ + inventoryType: 'premium' | 'run_of_site' | 'targeted_package'; + creativeFormats?: + | string[] + | { + agent_url: string; + id: string; + }[]; + /** @enum {string} */ + pricingModel: 'auction' | 'fixed_cpm'; + fixedCpm?: number; + floorCpm?: number; + targetCpm?: number; + pricingOptions?: { + [key: string]: unknown; + }[]; + supportedTargeting?: string[]; + adcpAgentId?: string; + }; + ListProductsInput: { + take?: number; + skip?: number; + }; + SyncProductsInput: { + sourceId: string; + }; + GetSalesAgentInput: { + agentId: string; + }; + ListSalesAgentsInput: Record; + RegisterSalesAgentInput: { + name: string; + description?: string; + /** Format: uri */ + endpointUrl: string; + /** @enum {string} */ + protocol: 'MCP' | 'A2A'; + /** @enum {string} */ + authenticationType: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; + organizationId?: string; + authConfig?: { + [key: string]: unknown; }; }; - /** @description Bad request - invalid parameters */ - BadRequest: { - content: { - 'application/json': { - /** @description Error message */ - error?: string; - /** @description Additional error details */ - details?: Record; - }; + UnregisterSalesAgentInput: { + agentId: string; + }; + UpdateSalesAgentInput: { + agentId: string; + name?: string; + organization?: string; + }; + ListSalesAgentAccountsInput: { + agentId: string; + }; + RegisterSalesAgentAccountInput: { + salesAgentId: string; + accountIdentifier: string; + authConfig?: { + [key: string]: unknown; }; }; - /** @description Unauthorized - invalid or missing authentication */ - Unauthorized: { + UnregisterSalesAgentAccountInput: { + accountId: string; + }; + UpdateSalesAgentAccountInput: { + accountId: string; + accountData: { + [key: string]: unknown; + }; + }; + CreateTacticInput: { + campaignId: string; + name: string; + prompt?: string; + channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; + countryCodes?: string[]; + }; + UpdateTacticInput: { + tacticId: number; + name?: string; + prompt?: string; + channelCodes?: ('ctv' | 'video' | 'display' | 'app' | 'social')[]; + countryCodes?: string[]; + }; + DeleteTacticInput: { + tacticId: number; + }; + GetTacticInput: { + tacticId: number; + }; + ListTacticsInput: { + campaignId?: string; + take?: number; + skip?: number; + }; + LinkCampaignToTacticInput: { + tacticId: number; + campaignId: string; + }; + UnlinkCampaignFromTacticInput: { + tacticId: number; + campaignId: string; + }; + RegisterWebhookInput: { + brandAgentId?: number; + endpoint: { + /** Format: uri */ + url: string; + /** @enum {string} */ + method: 'POST' | 'PUT'; + headers?: { + [key: string]: string; + }; + authentication?: { + /** @enum {string} */ + type: 'bearer' | 'basic' | 'hmac'; + credentials: string; + }; + }; + eventTypes: string[]; + filters?: { + campaigns?: string[]; + tactics?: string[]; + creatives?: string[]; + mediaBuys?: string[]; + metrics?: string[]; + /** @enum {string} */ + minSeverity?: 'info' | 'warning' | 'critical'; + }; + retryPolicy?: { + maxRetries?: number; + backoffMultiplier?: number; + maxBackoffSeconds?: number; + }; + }; + ListWebhooksInput: { + take?: number; + skip?: number; + }; + DeleteWebhookInput: { + webhookId: string; + }; + BrandAgentUpdate: { + id: number; + name: string; + description?: string; + /** Format: uri */ + manifestUrl?: string; + customerId: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + BrandStandardsCreate: { + id: string; + name: string; + description?: string; + countryCodes: string[]; + channelCodes: string[]; + brands: string[]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CampaignUpdate: { + id: string; + name: string; + status: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CreativeGet: { + creativeId: string; + name: string; + status: string; + campaignId?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + MediaBuyGet: { + id: string; + tacticId: number; + status: string; + /** Format: date-time */ + archivedAt?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TacticGet: { + id: number; + name: string; + prompt?: string; + campaignIds?: string[]; + channelCodes: string[]; + countryCodes: string[]; + mediaBuyCount?: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + /** Format: date-time */ + archivedAt?: string; + }; + MCPContent: { + /** @enum {string} */ + type: 'text'; + text: string; + }; + /** @description Bad request error response */ + BadRequest: { + error: string; + message?: string; + }; + /** @description Unauthorized error response */ + Unauthorized: { + error: string; + message?: string; + }; + /** @description Internal server error response */ + InternalError: { + error: string; + message?: string; + }; + AssetList: { + total: number; + items: { + assetId: string; + originalFilename: string; + assetType: string; + size: number; + brandAgentId: string; + customerId: number; + signedUrl: string; + tags?: string[]; + }[]; + }; + BrandAgentList: { + brandAgents: components['schemas']['BrandAgentUpdateOutput'][]; + total: number; + }; + BrandAgentDelete: { + success: boolean; + deletedId: number; + }; + BrandStandardsDelete: { + success: boolean; + id: string; + }; + BrandStandardsList: { + total: number; + items: components['schemas']['BrandStandardsCreateOutput'][]; + }; + BrandStoryCreate: { + id: string; + name: string; + brandAgentId?: string; + countryCodes?: string[]; + channelCodes?: string[]; + languages?: string[]; + brands?: string[]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + BrandStoryUpdate: { + id: string; + name: string; + prompt?: string; + status?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + BrandStoryDelete: { + success: boolean; + id: string; + }; + BrandStoryList: { + total: number; + items: { + id: string; + name: string; + description?: string; + status: string; + type: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }[]; + }; + CampaignList: { + campaigns: components['schemas']['CampaignUpdateOutput'][]; + total: number; + }; + CampaignDelete: { + success: boolean; + deletedId: string; + }; + CampaignGetSummary: { + campaignId: string; + summary: { + [key: string]: unknown; + }; + }; + CampaignListTactics: { + tactics: unknown[]; + total: number; + }; + CampaignValidateBrief: { + valid: boolean; + feedback?: string; + }; + ChannelList: { + total: number; + items: { + channel: string; + displayName: string; + }[]; + }; + CreativeAssign: { + success: boolean; + creativeId: string; + campaignId: string; + }; + CreativeDelete: { + success: boolean; + id: string; + }; + CreativeList: { + items: components['schemas']['CreativeGetOutput'][]; + total: number; + }; + CreativeSyncSalesAgents: { + success: boolean; + creativeId: string; + campaignId?: string; + }; + MediaBuyDelete: { + success: boolean; + id: string; + }; + MediaBuyExecute: { + success: boolean; + mediaBuyId: string; + status: string; + adcpMediaBuyId?: string; + adcpStatus?: string; + }; + MediaBuyList: { + total: number; + items: components['schemas']['MediaBuyGetOutput'][]; + }; + MediaBuyValidateBudget: { + valid: boolean; + message?: string; + }; + NotificationsList: { + total: number; + hasMore: boolean; + items: { + id: string; + type: string; + data: { + [key: string]: unknown; + }; + read: boolean; + acknowledged: boolean; + /** Format: date-time */ + createdAt: string; + }[]; + }; + NotificationsMarkRead: { + success: boolean; + notificationId: string; + }; + NotificationsMarkAcknowledged: { + success: boolean; + notificationId: string; + }; + NotificationsMarkAllRead: { + success: boolean; + count: number; + }; + MediaProductDiscover: { + success: boolean; + productsFound: number; + productsSaved: number; + successfulAgents: number; + failedAgents: number; + products: { + productId: string; + name: string; + publisherName: string; + salesAgentId?: string; + salesAgentName?: string; + /** @enum {string} */ + deliveryType: 'guaranteed' | 'non_guaranteed'; + /** @enum {string} */ + inventoryType: 'premium' | 'run_of_site' | 'targeted_package'; + creativeFormats?: + | string[] + | { + agent_url: string; + id: string; + }[]; + fixedCpm?: number; + floorCpm?: number; + targetCpm?: number; + }[]; + }; + MediaProductSave: { + id: string; + productId: string; + name: string; + publisherId: string; + publisherName: string; + customerId: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + MediaProductList: { + total: number; + items: { + id: string; + productId: string; + name: string; + salesAgent?: string; + salesAgentId?: string; + salesAgentName?: string; + /** @enum {string} */ + deliveryType: 'guaranteed' | 'non_guaranteed'; + format?: string; + creativeFormats?: + | string[] + | { + agent_url: string; + id: string; + }[]; + }[]; + }; + MediaProductSync: { + success: boolean; + productsSaved: number; + }; + SalesAgentGet: { + id: number; + name: string; + status: string; + relationship: string; + endpointUrl: string; + protocol: string; + authenticationType: string; + description?: string; + customerAccountCount: number; + organizationId?: string; + registeredBy?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + SalesAgentList: { + total: number; + items: { + id: number; + name: string; + status: string; + relationship: string; + endpointUrl: string; + protocol: string; + customerAccountCount: number; + }[]; + }; + SalesAgentRegister: { + id: number; + name: string; + status: string; + endpointUrl: string; + }; + SalesAgentUnregister: { + success: boolean; + id: string; + }; + SalesAgentUpdate: { + id: string; + name: string; + status: string; + }; + SalesAgentAccountList: { + total: number; + items: { + id: string; + accountIdentifier: string; + status: string; + registeredBy?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }[]; + }; + SalesAgentAccountRegister: { + accountId: string; + adcpAgentId: string; + status: string; + }; + SalesAgentAccountUnregister: { + success: boolean; + salesAgentId: string; + }; + SalesAgentAccountUpdate: { + id: string; + status: string; + }; + TacticCreate: { + id: number; + name: string; + prompt?: string; + campaignId: string; + channelCodes: string[]; + countryCodes: string[]; + /** Format: date-time */ + createdAt: string; + }; + TacticDelete: { + success: boolean; + tacticId: number; + }; + TacticList: { + total: number; + items: components['schemas']['TacticGetOutput'][]; + }; + TacticLinkCampaign: { + success: boolean; + tacticId: number; + campaignId: string; + }; + TacticUnlinkCampaign: { + success: boolean; + tacticId: number; + campaignId: string; + }; + WebhookRegister: { + id: string; + brandAgentId?: number; + endpoint: { + url: string; + method: string; + authenticationType?: string; + }; + eventTypes: string[]; + filters?: { + campaigns?: string[]; + tactics?: string[]; + creatives?: string[]; + mediaBuys?: string[]; + metrics?: string[]; + minSeverity?: string; + }; + retryPolicy: { + maxRetries: number; + backoffMultiplier: number; + maxBackoffSeconds: number; + }; + status: string; + testResult: { + success: boolean; + statusCode?: number; + error?: string; + }; + }; + WebhookList: { + total: number; + items: { + id: string; + status: string; + endpoint: { + url: string; + method: string; + authenticationType?: string; + }; + eventTypes: string[]; + brandAgentId?: number; + failureCount: number; + /** Format: date-time */ + lastSuccess?: string | null; + /** Format: date-time */ + lastFailure?: string | null; + /** Format: date-time */ + createdAt: string; + }[]; + }; + WebhookDelete: { + success: boolean; + webhookId: string; + }; + BrandAgentUpdateOutput: { + id: number; + name: string; + description?: string; + /** Format: uri */ + manifestUrl?: string; + customerId: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + BrandStandardsCreateOutput: { + id: string; + name: string; + description?: string; + countryCodes: string[]; + channelCodes: string[]; + brands: string[]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CampaignUpdateOutput: { + id: string; + name: string; + status: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CreativeGetOutput: { + creativeId: string; + name: string; + status: string; + campaignId?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + MediaBuyGetOutput: { + id: string; + tacticId: number; + status: string; + /** Format: date-time */ + archivedAt?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TacticGetOutput: { + id: number; + name: string; + prompt?: string; + campaignIds?: string[]; + channelCodes: string[]; + countryCodes: string[]; + mediaBuyCount?: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + /** Format: date-time */ + archivedAt?: string; + }; + BrandAgentGet: { + id: number; + name: string; + description?: string; + /** Format: uri */ + manifestUrl?: string; + customerId: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + BrandAgentCreate: { + id: number; + name: string; + description?: string; + /** Format: uri */ + manifestUrl?: string; + customerId: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CampaignCreate: { + id: string; + name: string; + status: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CampaignGet: { + id: string; + name: string; + status: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CreativeCreate: { + creativeId: string; + name: string; + status: string; + campaignId?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + CreativeUpdate: { + creativeId: string; + name: string; + status: string; + campaignId?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + MediaBuyCreate: { + id: string; + tacticId: number; + status: string; + /** Format: date-time */ + archivedAt?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + MediaBuyUpdate: { + id: string; + tacticId: number; + status: string; + /** Format: date-time */ + archivedAt?: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TacticUpdate: { + id: number; + name: string; + prompt?: string; + campaignIds?: string[]; + channelCodes: string[]; + countryCodes: string[]; + mediaBuyCount?: number; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + /** Format: date-time */ + archivedAt?: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} + +export type $defs = Record; + +export type external = Record; + +export interface operations { + /** + * Initialize MCP session + * @description Initialize a new MCP session. This must be called before using any tools. The session ID should be generated as a UUID and included in the mcp-session-id header for all subsequent requests. + */ + mcp_initialize: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Generate a new UUID for session initialization. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + jsonrpc: '2.0'; + id: string | number; + /** @enum {string} */ + method: 'initialize'; + params: { + /** @example 2024-11-05 */ + protocolVersion: string; + capabilities: Record; + clientInfo: { + name: string; + version: string; + }; + }; + }; + }; + }; + responses: { + /** @description Session initialized successfully */ + 200: { + content: { + 'application/json': { + /** @enum {string} */ + jsonrpc?: '2.0'; + id?: string | number; + result?: { + protocolVersion?: string; + capabilities?: Record; + serverInfo?: { + name?: string; + version?: string; + }; + }; + }; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + }; + }; + /** + * List brand agents + * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. + */ + brand_agent_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_agent_list'; + arguments: components['schemas']['ListBrandAgentsInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandAgentList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Get brand agent + * @description Get detailed information about a specific brand agent (advertiser account) by ID. + */ + brand_agent_get: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_agent_get'; + arguments: components['schemas']['GetBrandAgentInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandAgentUpdateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Create brand agent + * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + */ + brand_agent_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_agent_create'; + arguments: components['schemas']['CreateBrandAgentInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandAgentUpdateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Update brand agent + * @description Update an existing brand agent with new information. + */ + brand_agent_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_agent_update'; + arguments: components['schemas']['UpdateBrandAgentInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandAgentUpdateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Delete brand agent + * @description Delete a brand agent. This will also delete all associated campaigns, creatives, and other resources. + */ + brand_agent_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_agent_delete'; + arguments: components['schemas']['DeleteBrandAgentInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandAgentDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * List campaigns + * @description List all campaigns with optional filtering by brand agent. + */ + campaign_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'campaign_list'; + arguments: components['schemas']['ListCampaignsInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Create campaign + * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. + */ + campaign_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'campaign_create'; + arguments: components['schemas']['CreateCampaignInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignUpdateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Get campaign + * @description Get detailed information about a specific campaign. + */ + campaign_get: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'campaign_get'; + arguments: components['schemas']['GetCampaignInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignUpdateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Update campaign + * @description Update an existing campaign with new information. + */ + campaign_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'campaign_update'; + arguments: components['schemas']['UpdateCampaignInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignUpdateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Delete campaign + * @description Delete a campaign and all associated resources. + */ + campaign_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'campaign_delete'; + arguments: components['schemas']['DeleteCampaignInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Get campaign summary + * @description Get a high-level summary of a campaign including key metrics and status. + */ + campaign_get_summary: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { content: { 'application/json': { - /** @description Error message */ - error?: string; + /** @enum {string} */ + tool: 'campaign_get_summary'; + arguments: components['schemas']['GetCampaignSummaryInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignGetSummary']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; }; }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * List campaign tactics + * @description List all tactics associated with a specific campaign. + */ + campaign_list_tactics: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; }; - /** @description Resource not found */ - NotFound: { + requestBody: { content: { 'application/json': { - /** @description Error message */ - error?: string; + /** @enum {string} */ + tool: 'campaign_list_tactics'; + arguments: components['schemas']['ListCampaignTacticsInput']; }; }; }; - /** @description Internal server error */ - InternalError: { + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignListTactics']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Validate campaign brief + * @description Validate a campaign brief to ensure it contains all necessary information for campaign creation. + */ + campaign_validate_brief: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { content: { 'application/json': { - /** @description Error message */ - error?: string; + /** @enum {string} */ + tool: 'campaign_validate_brief'; + arguments: components['schemas']['ValidateBriefInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CampaignValidateBrief']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * List assets + * @description List all uploaded assets with optional filtering by brand agent. + */ + asset_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'asset_list'; + arguments: components['schemas']['ListAssetsInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['AssetList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Create brand standards + * @description Create brand standards including guidelines, tone of voice, visual requirements, and content rules for a brand agent. + */ + brand_standards_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_standards_create'; + arguments: components['schemas']['CreateBrandStandardInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStandardsCreateOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Delete brand standards + * @description Delete brand standards for a brand agent. + */ + brand_standards_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_standards_delete'; + arguments: components['schemas']['DeleteBrandStandardInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStandardsDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * List brand standards + * @description List all brand standards with optional filtering by brand agent. + */ + brand_standards_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_standards_list'; + arguments: components['schemas']['ListBrandStandardsInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStandardsList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; + }; + }; + /** + * Create brand story + * @description Create a brand story containing the narrative, history, values, and key messaging for a brand agent. + */ + brand_story_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; + requestBody: { + content: { + 'application/json': { + /** @enum {string} */ + tool: 'brand_story_create'; + arguments: components['schemas']['CreateBrandStoryInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStoryCreate']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; }; }; }; }; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} - -export type $defs = Record; - -export type external = Record; - -export interface operations { /** - * Upload creative assets - * @description Upload creative assets (images, videos, audio) to Google Cloud Storage. - * - * **REQUIRED FIELDS:** - * - `brandAgentId`: Brand agent ID for file organization - * - `assets`: Array of assets (each with name, contentType, data, assetType) - * - * Returns signed URLs valid for 1 hour. + * Update brand story + * @description Update an existing brand story with new information. */ - asset_upload: { + brand_story_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** - * @description **REQUIRED**: Brand agent ID for file organization (e.g., brand_agent_123) - * @example brand_agent_abc123 - */ - brandAgentId: string; - /** @description **REQUIRED**: Array of assets to upload. Each asset must have all required fields. */ - assets: components['schemas']['AssetUpload'][]; + /** @enum {string} */ + tool: 'brand_story_update'; + arguments: components['schemas']['UpdateBrandStoryInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStoryUpdate']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List creative assets - * @description List creative assets stored in Google Cloud Storage. Filter by customer and/or brand agent. + * Delete brand story + * @description Delete a brand story. */ - asset_list: { + brand_story_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Optional brand agent ID to filter assets */ - brandAgentId?: string; + /** @enum {string} */ + tool: 'brand_story_delete'; + arguments: components['schemas']['DeleteBrandStoryInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStoryDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List brand agents - * @description List all brand agents (advertiser accounts) for the authenticated customer. Authentication is automatic - no parameters required. + * List brand stories + * @description List all brand stories with optional filtering by brand agent. */ - brand_agent_list: { + brand_story_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { - 'application/json': Record; + 'application/json': { + /** @enum {string} */ + tool: 'brand_story_list'; + arguments: components['schemas']['ListBrandStoriesInput']; + }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['BrandStoryList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Create brand agent - * @description Create a new brand agent (advertiser account). This creates the top-level container that will own campaigns, creatives, audiences, standards, and measurement sources. + * List channels + * @description List all available advertising channels and platforms. */ - brand_agent_create: { + channel_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Name of the brand agent (advertiser account) */ - name: string; - /** @description Optional description of the brand agent */ - description?: string; - /** @description Friendly name for easy identification (e.g., 'Nike' for 'Nike c/o Kinesso') */ - nickname?: string; - /** @description Your internal ID for this brand agent (e.g., client code or account ID) */ - externalId?: string; - /** @description Domains where users will be sent from all campaigns/creatives */ - advertiserDomains?: string[]; + /** @enum {string} */ + tool: 'channel_list'; + arguments: components['schemas']['ListChannelsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['ChannelList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Get brand agent - * @description Get detailed information about a specific brand agent (advertiser account) by ID. + * Assign creative + * @description Assign a creative to a tactic or media buy. */ - brand_agent_get: { + creative_assign: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand agent to retrieve */ - brandAgentId: string; + /** @enum {string} */ + tool: 'creative_assign'; + arguments: components['schemas']['AssignCreativeInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeAssign']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Update brand agent - * @description Update the name or description of an existing brand agent (advertiser account). This only updates metadata - campaigns, creatives, and other resources remain unchanged. + * Create creative + * @description Create a new creative with assets, copy, and targeting specifications. */ - brand_agent_update: { + creative_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand agent to update */ - brandAgentId: string; - /** @description New name for the brand agent */ - name?: string; - /** @description New description for the brand agent */ - description?: string; - /** @description Enable/disable tactic seed data cooperative participation */ - tacticSeedDataCoop?: boolean; + /** @enum {string} */ + tool: 'creative_create'; + arguments: components['schemas']['CreateCreativeInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Delete brand agent - * @description โš ๏ธ DANGER - Permanently delete a brand agent (advertiser account) and ALL associated data including campaigns, creatives, audiences, standards, and measurement sources. This action cannot be undone. + * Update creative + * @description Update an existing creative with new assets, copy, or specifications. */ - brand_agent_delete: { + creative_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand agent to delete permanently */ - brandAgentId: string; + /** @enum {string} */ + tool: 'creative_update'; + arguments: components['schemas']['UpdateCreativeInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List brand standards - * @description List all brand safety standards. Brand standards define safety rules and filtering criteria using AI-powered prompts. + * Delete creative + * @description Delete a creative and remove it from any associated tactics or media buys. */ - brand_standards_list: { + creative_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Optional filtering criteria */ - where?: { - /** @description Filter by name */ - name?: string; - }; - /** @description Optional ordering for results */ - orderBy?: { - /** @enum {string} */ - id?: 'asc' | 'desc'; - /** @enum {string} */ - name?: 'asc' | 'desc'; - }; - /** @description Number of records to return (pagination) */ - take?: number; - /** @description Number of records to skip (pagination) */ - skip?: number; + /** @enum {string} */ + tool: 'creative_delete'; + arguments: components['schemas']['DeleteCreativeInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Create brand standard - * @description Create a new brand safety standard for a brand. The standard uses AI to classify content and enforce brand safety rules based on a natural language prompt. + * Get creative + * @description Get detailed information about a specific creative. */ - brand_standards_create: { + creative_get: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand to create standards for */ - brandAgentId: string; - /** @description Name for the brand standard (optional - defaults to "{Brand Name} Standards") */ - name?: string; - /** @description Natural language prompt defining the brand safety standards, content restrictions, and enforcement rules */ - prompt: string; - /** @description Description for the brand standard */ - description?: string; - /** @description Whether to create the standard as archived */ - isArchived?: boolean; - /** @description List of country codes to target (e.g., ['US', 'CA']) */ - countries?: string[]; - /** @description List of channels to target (e.g., ['web', 'social']) */ - channels?: string[]; - /** @description List of specific brands this applies to */ - brands?: string[]; + /** @enum {string} */ + tool: 'creative_get'; + arguments: components['schemas']['GetCreativeInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Delete brand standard - * @description โš ๏ธ DANGER - Permanently delete a brand standard. This will remove all safety rules and models associated with this standard. + * List creatives + * @description List all creatives with optional filtering by brand agent or campaign. */ - brand_standards_delete: { + creative_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand standard to delete */ - brandStandardId: string; + /** @enum {string} */ + tool: 'creative_list'; + arguments: components['schemas']['ListCreativesInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List brand stories - * @description List all brand stories for a brand. Brand stories are AI-powered target audience definitions using natural language prompts. + * Sync creatives to sales agents + * @description Synchronize creatives to connected sales agents (DSPs, publisher platforms). */ - brand_story_list: { + creative_sync_sales_agents: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand to list brand stories for */ - brandAgentId: string; + /** @enum {string} */ + tool: 'creative_sync_sales_agents'; + arguments: components['schemas']['SyncSalesAgentsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['CreativeSyncSalesAgents']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Create brand story - * @description Create a new brand story for a brand. Brand stories are AI-powered target audience definitions that use natural language prompts to define audience profiles, demographics, and behavioral characteristics. + * Create media buy + * @description Create a new media buy with budget, targeting, and creative specifications. */ - brand_story_create: { + media_buy_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand to create a brand story for */ - brandAgentId: string; - /** @description Name for the brand story (e.g., 'Tech Enthusiasts', 'Luxury Shoppers') */ - name: string; - /** @description Natural language prompt defining the target audience profile, demographics, and behavioral characteristics */ - prompt: string; - /** @description List of country codes to target (e.g., ['US', 'CA']) */ - countries?: string[]; - /** @description List of channels to target (e.g., ['web', 'social']) */ - channels?: string[]; - /** @description List of language codes to target (e.g., ['en', 'es']) */ - languages?: string[]; - /** @description List of specific brands this applies to */ - brands?: string[]; + /** @enum {string} */ + tool: 'media_buy_create'; + arguments: components['schemas']['CreateMediaBuyInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; }; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; }; /** - * Update brand story - * @description Update the audience definition prompt of an existing brand story. This creates a new model version with the updated definition. + * Update media buy + * @description Update an existing media buy with new budget, targeting, or creative assignments. */ - brand_story_update: { + media_buy_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand story to update */ - brandStoryId: string; - /** @description New audience definition prompt */ - prompt: string; + /** @enum {string} */ + tool: 'media_buy_update'; + arguments: components['schemas']['UpdateMediaBuyInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Delete brand story - * @description โš ๏ธ DANGER - Permanently delete a brand story. This will remove all audience definitions and models associated with this story. + * Delete media buy + * @description Delete a media buy and cancel any active placements. */ - brand_story_delete: { + media_buy_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the brand story to delete */ - brandStoryId: string; + /** @enum {string} */ + tool: 'media_buy_delete'; + arguments: components['schemas']['DeleteMediaBuyInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List campaigns - * @description List campaigns for the authenticated customer, with optional filtering. + * Execute media buy + * @description Execute a media buy, sending it to the configured sales agents for placement. */ - campaign_list: { + media_buy_execute: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Optional brand agent ID to filter campaigns */ - brandAgentId?: string; - /** - * @description Optional status filter - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; - /** @description Maximum number of campaigns to return (default 100) */ - limit?: number; - /** @description Number of campaigns to skip for pagination */ - offset?: number; + /** @enum {string} */ + tool: 'media_buy_execute'; + arguments: components['schemas']['ExecuteMediaBuyInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyExecute']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Create campaign - * @description Create a new campaign with natural language prompt. The backend will parse the prompt to extract targeting, budget, and creative requirements. + * Get media buy + * @description Get detailed information about a specific media buy. */ - campaign_create: { - requestBody: { - content: { - 'application/json': { - /** @description Optional brand agent ID that will own this campaign */ - brandAgentId?: string; - /** @description Optional name for the campaign (auto-generated if not provided) */ - name?: string; - /** @description Natural language description of campaign requirements (e.g., 'Create a video campaign targeting tech enthusiasts with $50k budget') */ - prompt: string; - budget?: components['schemas']['Budget']; - /** - * Format: date-time - * @description Campaign start date (ISO 8601 format) - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date (ISO 8601 format) - */ - endDate?: string; - scoringWeights?: components['schemas']['ScoringWeights']; - /** @description Days for outcome measurement window */ - outcomeScoreWindowDays?: number; - /** @description Array of segment IDs to associate with campaign */ - segmentIds?: string[]; - /** @description Array of deal IDs to associate with campaign */ - dealIds?: string[]; - /** - * @description Campaign visibility setting - * @enum {string} - */ - visibility?: 'PUBLIC' | 'PRIVATE'; - /** - * @description How the campaign was created - * @enum {string} - */ - creationType?: 'MANUAL' | 'AUTO_SYNC'; - /** - * @description Initial campaign status - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; - }; - }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + media_buy_get: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; }; - }; - /** - * Update campaign - * @description Update an existing campaign's settings. - */ - campaign_update: { requestBody: { content: { 'application/json': { - /** @description ID of the campaign to update */ - campaignId: string; - /** @description New name for the campaign */ - name?: string; - /** @description Updated natural language campaign requirements */ - prompt?: string; - /** - * @description New status for the campaign - * @enum {string} - */ - status?: 'ACTIVE' | 'PAUSED' | 'ARCHIVED'; - budget?: components['schemas']['Budget']; - /** - * Format: date-time - * @description Campaign start date (ISO 8601 format) - */ - startDate?: string; - /** - * Format: date-time - * @description Campaign end date (ISO 8601 format) - */ - endDate?: string; - /** @description Scoring weights configuration */ - scoringWeights?: { - /** @description Weight for affinity scoring (0-1) */ - affinity?: number; - /** @description Weight for outcome scoring (0-1) */ - outcome?: number; - /** @description Weight for quality scoring (0-1) */ - quality?: number; - }; - /** @description Days for outcome measurement window */ - outcomeScoreWindowDays?: number; - /** @description Array of segment IDs to associate with campaign */ - segmentIds?: string[]; - /** @description Array of deal IDs to associate with campaign */ - dealIds?: string[]; - /** - * @description Campaign visibility setting - * @enum {string} - */ - visibility?: 'PUBLIC' | 'PRIVATE'; - }; - }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @enum {string} */ + tool: 'media_buy_get'; + arguments: components['schemas']['GetMediaBuyInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Delete campaign - * @description โš ๏ธ DANGER - Permanently delete a campaign and all associated data. + * List media buys + * @description List all media buys with optional filtering by brand agent, campaign, or status. */ - campaign_delete: { + media_buy_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the campaign to delete */ - campaignId: string; - /** @description If true, permanently delete the campaign. Default false (soft delete/archive) */ - hardDelete?: boolean; + /** @enum {string} */ + tool: 'media_buy_list'; + arguments: components['schemas']['ListMediaBuysInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Get campaign summary - * @description Get detailed summary information about a specific campaign. + * Validate media buy budget + * @description Validate a media buy budget against campaign constraints and available funds. */ - campaign_get_summary: { + media_buy_validate_budget: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the campaign to retrieve */ - campaignId: string; + /** @enum {string} */ + tool: 'media_buy_validate_budget'; + arguments: components['schemas']['ValidateMediaBuyBudgetInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaBuyValidateBudget']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List campaign tactics - * @description List all tactics associated with a specific campaign. + * List notifications + * @description List notifications for the authenticated user with optional filtering by status. */ - campaign_list_strategies: { + notifications_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the campaign to list tactics for */ - campaignId: string; - /** @description Include archived tactics (defaults to false) */ - includeArchived?: boolean; + /** @enum {string} */ + tool: 'notifications_list'; + arguments: components['schemas']['ListNotificationsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['NotificationsList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Validate campaign brief - * @description Validate a campaign brief to ensure it contains all necessary information. + * Mark notification as read + * @description Mark a specific notification as read. */ - campaign_validate_brief: { + notifications_mark_read: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Campaign brief to validate */ - brief: string; - /** @description Optional brand agent ID for context-aware validation */ - brandAgentId?: string; - /** - * @description Minimum quality score required to pass validation - * @default 70 - */ - threshold?: number; + /** @enum {string} */ + tool: 'notifications_mark_read'; + arguments: components['schemas']['MarkNotificationReadInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['NotificationsMarkRead']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List channels - * @description List all available advertising channels. + * Mark notification as acknowledged + * @description Mark a specific notification as acknowledged. */ - channel_list: { + notifications_mark_acknowledged: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { - 'application/json': Record; + 'application/json': { + /** @enum {string} */ + tool: 'notifications_mark_acknowledged'; + arguments: components['schemas']['MarkNotificationAcknowledgedInput']; + }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['NotificationsMarkAcknowledged']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List creatives - * @description List creatives for the authenticated customer, with optional filtering. + * Mark all notifications as read + * @description Mark all notifications for the authenticated user as read. */ - creative_list: { + notifications_mark_all_read: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Optional internal brand agent ID to filter creatives */ - brandAgentId?: number; - /** @description Optional internal campaign ID to filter creatives */ - campaignId?: number; + /** @enum {string} */ + tool: 'notifications_mark_all_read'; + arguments: components['schemas']['MarkAllNotificationsReadInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['NotificationsMarkAllRead']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Create creative - * @description Create a new creative with specified details. Supports various format sources (ADCP, CREATIVE_AGENT, PUBLISHER) and assembly methods. - * - * **Two workflows supported:** - * 1. **Separate upload**: Use asset_upload first, then reference asset IDs in content.assetIds - * 2. **Inline upload**: Upload assets directly in the `assets` array (automatically uploaded and linked) + * Discover media products + * @description Discover available media products from connected sales agents based on targeting criteria. */ - creative_create: { - requestBody: { - content: { - 'application/json': { - /** - * @description **REQUIRED**: Internal database ID of the brand agent that will own this creative - * @example 1 - */ - brandAgentId: number; - /** @description Optional internal database ID of the organization */ - organizationId?: number; - /** - * @description **REQUIRED**: Name for the creative - * @example Banner Ad 970x250 - */ - name: string; - /** - * @description Optional description of the creative - * @example Display banner for homepage - */ - description?: string; - /** - * @description Format source type - * @example ADCP - * @enum {string} - */ - formatSource?: 'ADCP' | 'CREATIVE_AGENT' | 'PUBLISHER'; - /** - * @description Format identifier (e.g., "display_970x250", "video/mp4") - * @example display_970x250 - */ - formatId?: string; - /** - * @description URL to the creative media file (video, image, etc.) - * @example https://example.com/banner.png - */ - mediaUrl?: string; - /** @description Optional: Upload assets inline with the creative. Automatically uploaded to GCS and linked. */ - assets?: components['schemas']['AssetUpload'][]; - /** @description Creative content as JSON. Can include assetIds (existing or from inline upload), htmlSnippet, vastTag, etc. */ - content?: { - /** - * @description Array of existing asset IDs (from previous asset_upload). Inline uploaded assets are automatically added to this. - * @example [ - * "asset_abc123", - * "asset_def456" - * ] - */ - assetIds?: string[]; - /** - * @description HTML5 creative snippet - * @example
Ad content
- */ - htmlSnippet?: string; - /** @description VAST XML tag for video ads */ - vastTag?: string; - }; - /** - * @description Assembly method - * @example ACTIVATION - * @enum {string} - */ - assemblyMethod?: 'CREATIVE_AGENT' | 'ACTIVATION' | 'PUBLISHER'; - /** - * @description Optional internal database ID of campaign to assign creative to - * @example 1 - */ - campaignId?: number; - }; - }; - }; - responses: { - /** @description Creative created successfully */ - 200: { - content: { - 'application/json': { - /** @example true */ - success?: boolean; - /** - * @description Success message with creative details including creativeId (external string ID for use in media_buy_create/update), internal ID, and uploaded assets (if any) - * @example โœ… **Creative Created Successfully!** - * - * **Creative ID:** newcreativevideo_xntthe4w (use this for media_buy_create/update) - * **Internal ID:** 16 - * **Name:** My Creative - * **Status:** PENDING - * **Assets Uploaded:** 2 - * **Asset IDs:** asset_abc123, asset_def456 - * **Created:** 2025-10-14T00:00:00.000Z - */ - message?: string; - }; - }; - }; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + media_product_discover: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; }; - }; - /** - * Get creative - * @description Get detailed information about a specific creative. - */ - creative_get: { requestBody: { content: { 'application/json': { - /** @description Internal database ID of the creative to retrieve */ - creativeId: number; + /** @enum {string} */ + tool: 'media_product_discover'; + arguments: components['schemas']['DiscoverProductsInput']; + }; + }; + }; + responses: { + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaProductDiscover']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; }; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; }; /** - * Update creative - * @description Update an existing creative's settings. + * Save media product + * @description Save a discovered media product for future use in media buys. */ - creative_update: { + media_product_save: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Internal database ID of the creative to update */ - creativeId: number; - /** @description New name for the creative */ - name?: string; - /** @description New status for the creative */ - status?: string; + /** @enum {string} */ + tool: 'media_product_save'; + arguments: components['schemas']['SaveProductInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaProductSave']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Delete creative - * @description โš ๏ธ DANGER - Permanently delete a creative. + * List media products + * @description List saved media products with optional filtering. */ - creative_delete: { + media_product_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Internal database ID of the creative to delete */ - creativeId: number; + /** @enum {string} */ + tool: 'media_product_list'; + arguments: components['schemas']['ListProductsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaProductList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Assign creative to campaign - * @description Assign a creative to a campaign. Automatically discovers and syncs the creative to all sales agents - * associated with the campaign via active media buys. Returns auto-sync results including which agents - * received the creative and their approval status. + * Sync media products + * @description Synchronize media product catalog from connected sales agents. */ - creative_assign: { + media_product_sync: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Internal database ID of the creative to assign */ - creativeId: number; - /** @description Internal database ID of the campaign to assign creative to */ - campaignId: number; + /** @enum {string} */ + tool: 'media_product_sync'; + arguments: components['schemas']['SyncProductsInput']; }; }; }; responses: { - /** @description Creative assigned successfully with auto-sync results */ + /** @description Successful response */ 200: { content: { 'application/json': { - content?: { - /** @example text */ - type?: string; - /** - * @description Summary of creative assignment including auto-sync results. - * Shows which sales agents received the creative and their approval status. - */ - text?: string; - }[]; + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['MediaProductSync']; }; }; }; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Sync creative with sales agents - * @description Sync a creative to sales agents using smart auto-detection or manual specification. - * Features intelligent format matching and recent activity analysis (30-60 day lookback). - * Provides detailed sync status and actionable next steps. + * Get sales agent + * @description Get detailed information about a specific sales agent (DSP, publisher platform). */ - creative_sync_sales_agents: { + sales_agent_get: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Internal database ID of the creative to sync */ - creativeId: number; - /** @description Smart auto-detection settings (default behavior) */ - autoDetect?: { - /** @description Look at tactics from past N days (default 30, max 90) */ - daysBack?: number; - /** @description Include agents from active campaigns (default true) */ - includeActive?: boolean; - }; - /** @description Internal database ID - sync to sales agents used by this campaign's tactics only */ - campaignId?: number; - /** @description Request pre-approval before campaign launch (default false) */ - preApproval?: boolean; - /** @description Explicitly specify ADCP agent IDs (overrides auto-detection) */ - adcpAgentIds?: string[]; + /** @enum {string} */ + tool: 'sales_agent_get'; + arguments: components['schemas']['GetSalesAgentInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentGet']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** * List sales agents - * @description List all registered sales agents (publishers) for the authenticated customer. + * @description List all registered sales agents (DSPs, publisher platforms). */ sales_agent_list: { - requestBody: { - content: { - 'application/json': Record; + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Get sales agent - * @description Get detailed information about a specific sales agent. - */ - sales_agent_get: { requestBody: { content: { 'application/json': { - /** @description ID of the sales agent to retrieve */ - salesAgentId: string; + /** @enum {string} */ + tool: 'sales_agent_list'; + arguments: components['schemas']['ListSalesAgentsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** * Register sales agent - * @description Register a new sales agent. Creates a row in the adcp_agent table. Organization ID is auto-detected from customer if not provided. + * @description Register a new sales agent (DSP, publisher platform) for media buying. */ sales_agent_register: { - requestBody: { - content: { - 'application/json': { - /** @description Sales agent name */ - name: string; - /** @description Sales agent endpoint URL */ - endpointUrl: string; - /** - * @description Protocol for endpoint URL calls - * @enum {string} - */ - protocol: 'MCP' | 'A2A'; - /** - * @description Authentication type - * @enum {string} - */ - authenticationType: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; - /** @description Sales agent description (optional) */ - description?: string; - /** @description Organization ID (optional - auto-detected from customer if not provided) */ - organizationId?: string; - /** @description Authentication configuration for the sales agent (optional) */ - authConfig?: Record; - }; + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; - }; - /** - * List accounts for a sales agent - * @description List all accounts registered by your organization for a specific sales agent. - */ - sales_agent_account_list: { requestBody: { content: { 'application/json': { - /** @description ID of the sales agent */ - salesAgentId: string; + /** @enum {string} */ + tool: 'sales_agent_register'; + arguments: components['schemas']['RegisterSalesAgentInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Register account for sales agent - * @description Register your organization's account to an existing sales agent. This allows you to access the sales agent's inventory and services. - */ - sales_agent_account_register: { - requestBody: { - content: { - 'application/json': { - /** @description Sales agent ID */ - salesAgentId: string; - /** @description Account identifier */ - accountIdentifier: string; - /** @description Authentication configuration (credentials, tokens, etc.) - optional */ - authConfig?: Record; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentRegister']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; }; }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; }; }; /** - * Unregister sales agent completely - * @description Completely unregister a sales agent - deactivates ALL customer accounts and disables the agent itself. Only the owner can perform this action. + * Unregister sales agent + * @description Unregister a sales agent and disconnect it from the platform. */ sales_agent_unregister: { - requestBody: { - content: { - 'application/json': { - /** @description ID of the sales agent to unregister */ - salesAgentId: string; - /** @description Must be true to confirm this destructive operation */ - confirm: boolean; - }; + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Unregister your account with a sales agent - * @description Unregister (deactivate) your organization's account with a sales agent. This only deactivates your account but doesn't affect the sales agent or other customers' accounts. - */ - sales_agent_account_unregister: { requestBody: { content: { 'application/json': { - /** @description ID of the sales agent to unregister your account from */ - salesAgentId: string; - /** @description Must be true to confirm this destructive operation */ - confirm: boolean; + /** @enum {string} */ + tool: 'sales_agent_unregister'; + arguments: components['schemas']['UnregisterSalesAgentInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentUnregister']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** * Update sales agent - * @description Update a sales agent's core settings like name, description, or endpoint URL. Only the owner can perform this action. + * @description Update sales agent configuration and credentials. */ sales_agent_update: { - requestBody: { - content: { - 'application/json': { - /** @description ID of the sales agent to update */ - salesAgentId: string; - /** @description New name */ - name?: string; - /** @description New description */ - description?: string; - /** @description New endpoint URL */ - endpointUrl?: string; - /** - * @description New protocol - * @enum {string} - */ - protocol?: 'REST' | 'MCP' | 'A2A' | 'CUSTOM'; - /** - * @description New authentication type - * @enum {string} - */ - authenticationType?: 'API_KEY' | 'OAUTH' | 'NO_AUTH'; - /** @description Authentication configuration for the sales agent */ - authConfig?: Record; - }; + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Update sales agent account authentication - * @description Update your organization's account authentication configuration for a sales agent. This endpoint only handles authentication updates. - */ - sales_agent_account_update: { requestBody: { content: { 'application/json': { - /** @description ID of the sales agent */ - salesAgentId: string; - /** @description Account identifier to update */ - accountIdentifier: string; - /** @description Updated authentication configuration (credentials, tokens, etc.) */ - authConfig: Record; + /** @enum {string} */ + tool: 'sales_agent_update'; + arguments: components['schemas']['UpdateSalesAgentInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; - }; - /** - * List tactics - * @description List all media buying tactics for the authenticated customer. - */ - strategy_list: { - requestBody: { - content: { - 'application/json': { - /** @description Optional campaign ID to filter tactics */ - campaignId?: string; - /** @description Include archived tactics (defaults to false) */ - includeArchived?: boolean; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentUpdate']; + }; }; }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Create tactic - * @description Create a new AMP media buy tactic for executing media buys with publishers. Tactics are automatically configured as activityType=AMP and tacticType=INTELLIGENT_CAMPAIGNS. Use channel_list to see valid channel codes. - */ - strategy_create: { - requestBody: { - content: { - 'application/json': { - /** @description Name of the tactic */ - name: string; - /** @description Campaign ID to link this tactic to (required) */ - campaignId: string; - /** @description Optional tactical brief or prompt for this tactic */ - prompt?: string; - /** @description Valid channel codes to target (also accepts friendly aliases like audio, web, app, ctv, video which are automatically mapped) */ - channelCodes?: ( - | 'DIGITAL-AUDIO' - | 'DISPLAY-WEB' - | 'DISPLAY-APP' - | 'CTV-BVOD' - | 'OLV' - | 'DOOH' - | 'SOCIAL' - )[]; - /** @description Country codes to target (2-digit ISO codes) */ - countryCodes?: string[]; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; }; }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Get tactic - * @description Get detailed information about a specific tactic. - */ - strategy_get: { - requestBody: { - content: { - 'application/json': { - /** @description ID of the tactic to retrieve */ - tacticId: string; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; }; }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Update tactic - * @description Update an existing tactic's configuration. - */ - strategy_update: { - requestBody: { - content: { - 'application/json': { - /** @description ID of the tactic to update */ - tacticId: string; - /** @description New name for the tactic */ - name?: string; - /** @description New tactical brief */ - prompt?: string; - /** @description Updated channel codes (also accepts friendly aliases like audio, web, app, ctv, video) */ - channelCodes?: ( - | 'DIGITAL-AUDIO' - | 'DISPLAY-WEB' - | 'DISPLAY-APP' - | 'CTV-BVOD' - | 'OLV' - | 'DOOH' - | 'SOCIAL' - )[]; - /** @description Updated country codes */ - countryCodes?: string[]; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; }; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; - }; }; /** - * Delete tactic - * @description โš ๏ธ DANGER - Permanently delete a tactic. + * List sales agent accounts + * @description List all accounts (seats, advertisers) within a sales agent. */ - strategy_delete: { + sales_agent_account_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the tactic to delete */ - tacticId: string; + /** @enum {string} */ + tool: 'sales_agent_account_list'; + arguments: components['schemas']['ListSalesAgentAccountsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentAccountList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Link campaign to tactic - * @description Link a campaign to a tactic for budget and execution management. + * Register sales agent account + * @description Register a new account (seat, advertiser) within a sales agent. */ - strategy_link_campaign: { + sales_agent_account_register: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the tactic */ - tacticId: string; - /** @description ID of the campaign to link */ - campaignId: string; + /** @enum {string} */ + tool: 'sales_agent_account_register'; + arguments: components['schemas']['RegisterSalesAgentAccountInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentAccountRegister']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Unlink campaign from tactic - * @description Unlink a campaign from a tactic. + * Unregister sales agent account + * @description Unregister an account from a sales agent. */ - strategy_unlink_campaign: { + sales_agent_account_unregister: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the tactic */ - tacticId: string; - /** @description ID of the campaign to unlink */ - campaignId: string; + /** @enum {string} */ + tool: 'sales_agent_account_unregister'; + arguments: components['schemas']['UnregisterSalesAgentAccountInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentAccountUnregister']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List media buys - * @description List all media buys for the authenticated customer. + * Update sales agent account + * @description Update account configuration within a sales agent. */ - media_buy_list: { + sales_agent_account_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Optional tactic ID to filter media buys */ - tacticId?: string; - /** @description Optional campaign ID to filter media buys */ - campaignId?: string; - /** @description Include archived media buys (defaults to false) */ - includeArchived?: boolean; + /** @enum {string} */ + tool: 'sales_agent_account_update'; + arguments: components['schemas']['UpdateSalesAgentAccountInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; - }; - /** - * Create media buy - * @description Create a new media buy to execute a tactic with one or more publisher products. A media buy represents the actual execution of a tactic with budget allocation and pricing. - * - * **Multi-Product Support**: Media buys now support multiple products from different sales agents in a single buy. Each product can have its own budget allocation and pricing. During execution, each unique sales agent will receive a separate ADCP submission. - * - * **Budget Validation**: The sum of product budget allocations must not exceed the total media buy budget. The system will validate this at creation time and show warnings if budget is under-allocated. - */ - media_buy_create: { - requestBody: { - content: { - 'application/json': { - /** @description ID of the tactic to execute */ - tacticId: string; - /** @description Name of the media buy */ - name: string; - /** @description Optional description of the media buy */ - description?: string; - /** @description Array of products to include in this media buy. At least one product is required. Each product will be validated with its sales agent. */ - products: { - /** @description Media product ID from publisher (will be validated with sales agent) */ - mediaProductId: string; - /** @description Sales agent ID for this product */ - salesAgentId: string; - /** @description Budget allocated to this specific product (optional, must not exceed total budget when summed across all products) */ - budgetAmount?: number; - /** @description Currency for this product's budget (defaults to media buy currency) */ - budgetCurrency?: string; - /** @description Base CPM price for this product */ - pricingCpm?: number; - /** @description Additional signal cost for this product */ - pricingSignalCost?: number; - /** @description Optional display order for organizing products */ - displayOrder?: number; - }[]; - budget: { - /** @description Total budget amount for this media buy */ - amount: number; - /** @description Currency code (defaults to USD) */ - currency?: string; - /** @description Optional daily spending cap */ - dailyCap?: number; - /** - * @description Budget pacing tactic (defaults to even) - * @enum {string} - */ - pacing?: 'asap' | 'even' | 'front_loaded'; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['SalesAgentAccountUpdate']; }; - /** @description Optional array of creative IDs (database IDs) to assign to this media buy. Creatives must be assigned to the campaign associated with this media buy's tactic. */ - creativeIds?: string[]; }; }; - }; - responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Get media buy - * @description Get detailed information about a specific media buy. + * Create tactic + * @description Create a new tactic defining how to achieve campaign objectives. */ - media_buy_get: { + tactic_create: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the media buy to retrieve */ - mediaBuyId: string; + /** @enum {string} */ + tool: 'tactic_create'; + arguments: components['schemas']['CreateTacticInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticCreate']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Update media buy - * @description Update an existing media buy's configuration. + * Update tactic + * @description Update an existing tactic with new targeting, budget, or creative requirements. */ - media_buy_update: { + tactic_update: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the media buy to update */ - mediaBuyId: string; - /** @description New name */ - name?: string; - budget?: { - amount?: number; - dailyCap?: number; - /** @enum {string} */ - pacing?: 'asap' | 'even' | 'front_loaded'; - }; - /** @description New CPM price */ - cpm?: number; - /** @description Array of creative IDs (database IDs) to assign to this media buy. Replaces existing assignments. Creatives must be assigned to the campaign associated with this media buy's tactic. */ - creativeIds?: string[]; + /** @enum {string} */ + tool: 'tactic_update'; + arguments: components['schemas']['UpdateTacticInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Delete media buy - * @description โš ๏ธ DANGER - Permanently delete a media buy. + * Delete tactic + * @description Delete a tactic and all associated media buys. */ - media_buy_delete: { + tactic_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the media buy to delete */ - mediaBuyId: string; + /** @enum {string} */ + tool: 'tactic_delete'; + arguments: components['schemas']['DeleteTacticInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Execute media buy - * @description Execute a media buy by deploying it to the publisher platform. + * Get tactic + * @description Get detailed information about a specific tactic. */ - media_buy_execute: { + tactic_get: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the media buy to execute */ - mediaBuyId: string; + /** @enum {string} */ + tool: 'tactic_get'; + arguments: components['schemas']['GetTacticInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 400: components['responses']['BadRequest']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticGetOutput']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * List notifications - * @description List notifications for the authenticated user. + * List tactics + * @description List all tactics with optional filtering by brand agent or campaign. */ - notifications_list: { + tactic_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Filter to only unread notifications */ - unreadOnly?: boolean; - /** @description Maximum number of notifications to return */ - limit?: number; + /** @enum {string} */ + tool: 'tactic_list'; + arguments: components['schemas']['ListTacticsInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Mark notification as read - * @description Mark a specific notification as read. + * Link tactic to campaign + * @description Link a tactic to a campaign. */ - notifications_mark_read: { + tactic_link_campaign: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the notification to mark as read */ - notificationId: string; + /** @enum {string} */ + tool: 'tactic_link_campaign'; + arguments: components['schemas']['LinkCampaignToTacticInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticLinkCampaign']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Mark notification as acknowledged - * @description Mark a specific notification as acknowledged. + * Unlink tactic from campaign + * @description Unlink a tactic from a campaign. */ - notifications_mark_acknowledged: { + tactic_unlink_campaign: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description ID of the notification to mark as acknowledged */ - notificationId: string; + /** @enum {string} */ + tool: 'tactic_unlink_campaign'; + arguments: components['schemas']['UnlinkCampaignFromTacticInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['TacticUnlinkCampaign']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Mark all notifications as read - * @description Mark all notifications as read for the authenticated user. + * Register webhook + * @description Register a webhook to receive real-time notifications about events. */ - notifications_mark_all_read: { - requestBody: { - content: { - 'application/json': Record; + webhook_register: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; }; }; - responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; - }; - }; - /** - * List media products - * @description List available media products from publishers. - */ - media_product_list: { requestBody: { content: { 'application/json': { - /** @description Optional sales agent ID to filter products */ - salesAgentId?: string; + /** @enum {string} */ + tool: 'webhook_register'; + arguments: components['schemas']['RegisterWebhookInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['WebhookRegister']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Discover media products - * @description Discover new media products from connected publishers. + * List webhooks + * @description List all registered webhooks. */ - media_product_discover: { + webhook_list: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Sales agent ID to discover products from */ - salesAgentId?: string; + /** @enum {string} */ + tool: 'webhook_list'; + arguments: components['schemas']['ListWebhooksInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['WebhookList']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; /** - * Sync media products - * @description Synchronize media product inventory with publisher systems. + * Delete webhook + * @description Delete a registered webhook. */ - media_product_sync: { + webhook_delete: { + parameters: { + header: { + /** @description MCP session identifier (UUID). Initialize your session using the /mcp-initialize endpoint first to obtain a session ID, then reuse it for all subsequent tool requests in the same session. */ + 'mcp-session-id': string; + }; + }; requestBody: { content: { 'application/json': { - /** @description Sales agent ID to sync products from */ - salesAgentId: string; + /** @enum {string} */ + tool: 'webhook_delete'; + arguments: components['schemas']['DeleteWebhookInput']; }; }; }; responses: { - 200: components['responses']['ToolResponse']; - 401: components['responses']['Unauthorized']; - 404: components['responses']['NotFound']; - 500: components['responses']['InternalError']; + /** @description Successful response */ + 200: { + content: { + 'application/json': { + content: components['schemas']['MCPContent'][]; + structuredContent: components['schemas']['WebhookDelete']; + }; + }; + }; + /** @description Bad request */ + 400: { + content: { + 'application/json': components['schemas']['BadRequest']; + }; + }; + /** @description Unauthorized */ + 401: { + content: { + 'application/json': components['schemas']['Unauthorized']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['InternalError']; + }; + }; }; }; }