openai-ads-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dist/client.d.ts +19 -0
- package/dist/client.js +145 -0
- package/dist/client.js.map +1 -0
- package/dist/core.d.ts +55 -0
- package/dist/core.js +374 -0
- package/dist/core.js.map +1 -0
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.js +227 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/resource_trakkr.d.ts +4 -0
- package/dist/resource_trakkr.js +28 -0
- package/dist/resource_trakkr.js.map +1 -0
- package/dist/tools/account.d.ts +3 -0
- package/dist/tools/account.js +24 -0
- package/dist/tools/account.js.map +1 -0
- package/dist/tools/adgroups.d.ts +11 -0
- package/dist/tools/adgroups.js +205 -0
- package/dist/tools/adgroups.js.map +1 -0
- package/dist/tools/ads.d.ts +23 -0
- package/dist/tools/ads.js +245 -0
- package/dist/tools/ads.js.map +1 -0
- package/dist/tools/audiences.d.ts +2 -0
- package/dist/tools/audiences.js +163 -0
- package/dist/tools/audiences.js.map +1 -0
- package/dist/tools/campaigns.d.ts +15 -0
- package/dist/tools/campaigns.js +240 -0
- package/dist/tools/campaigns.js.map +1 -0
- package/dist/tools/conversions.d.ts +3 -0
- package/dist/tools/conversions.js +195 -0
- package/dist/tools/conversions.js.map +1 -0
- package/dist/tools/insights.d.ts +2 -0
- package/dist/tools/insights.js +153 -0
- package/dist/tools/insights.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# openai-ads-mcp for Node
|
|
2
|
+
|
|
3
|
+
Node runtime for `openai-ads-mcp`, a typed MCP server for OpenAI's Advertiser API.
|
|
4
|
+
|
|
5
|
+
It exposes the same tools, arguments, defaults, readonly mode, and budget guard as the Python package.
|
|
6
|
+
|
|
7
|
+
## Quickstart
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
export OPENAI_ADS_API_KEY="..."
|
|
11
|
+
export OPENAI_ADS_MCP_READONLY=1
|
|
12
|
+
npx -y openai-ads-mcp
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Readonly mode hides every write tool from `tools/list`. Unset `OPENAI_ADS_MCP_READONLY` only after you have confirmed the account and reviewed existing campaigns.
|
|
16
|
+
|
|
17
|
+
## Local Development
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install
|
|
21
|
+
npm run build
|
|
22
|
+
npm test
|
|
23
|
+
OPENAI_ADS_MCP_READONLY=1 node dist/index.js
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Environment
|
|
27
|
+
|
|
28
|
+
| Variable | Purpose |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| `OPENAI_ADS_API_KEY` | Required bearer key for `https://api.ads.openai.com/v1`. |
|
|
31
|
+
| `OPENAI_ADS_API_BASE_URL` | Optional HTTPS override for tests or proxies. |
|
|
32
|
+
| `OPENAI_ADS_MCP_READONLY` | Set to `1` or `true` to register read tools only. |
|
|
33
|
+
| `OPENAI_ADS_BUDGET_CEILING_USD` | Optional budget guard. Default `100`. |
|
|
34
|
+
|
|
35
|
+
Full docs live in the repository root README.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const API_BASE_URL = "https://api.ads.openai.com/v1";
|
|
2
|
+
export declare const CONVERSIONS_BASE_URL = "https://bzr.openai.com/v1";
|
|
3
|
+
export declare class OpenAIAdsAPIError extends Error {
|
|
4
|
+
readonly statusCode: number;
|
|
5
|
+
readonly detail: string;
|
|
6
|
+
constructor(statusCode: number, detail: string);
|
|
7
|
+
}
|
|
8
|
+
export type JsonRecord = Record<string, unknown>;
|
|
9
|
+
export declare class OpenAIAdsClient {
|
|
10
|
+
private readonly apiKey;
|
|
11
|
+
private readonly baseUrl;
|
|
12
|
+
constructor(apiKey: string, baseUrl?: string);
|
|
13
|
+
static fromEnv(): OpenAIAdsClient;
|
|
14
|
+
get(path: string, params?: JsonRecord): Promise<JsonRecord>;
|
|
15
|
+
post(path: string, body?: JsonRecord): Promise<JsonRecord>;
|
|
16
|
+
uploadFile(path: string, filePath: string): Promise<JsonRecord>;
|
|
17
|
+
postConversions(pixelId: string, events: JsonRecord[]): Promise<JsonRecord>;
|
|
18
|
+
private request;
|
|
19
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
export const API_BASE_URL = "https://api.ads.openai.com/v1";
|
|
4
|
+
export const CONVERSIONS_BASE_URL = "https://bzr.openai.com/v1";
|
|
5
|
+
const USER_AGENT = "openai-ads-mcp/0.1.0";
|
|
6
|
+
const FRIENDLY_ERRORS = {
|
|
7
|
+
401: "Invalid or expired OPENAI_ADS_API_KEY.",
|
|
8
|
+
403: "Access denied. Check whether this Ads account is eligible and has permission for this endpoint.",
|
|
9
|
+
404: "Resource not found. Check the id and try again.",
|
|
10
|
+
429: "Rate limited by the OpenAI Ads API. Wait a moment and retry.",
|
|
11
|
+
};
|
|
12
|
+
export class OpenAIAdsAPIError extends Error {
|
|
13
|
+
statusCode;
|
|
14
|
+
detail;
|
|
15
|
+
constructor(statusCode, detail) {
|
|
16
|
+
super(detail);
|
|
17
|
+
this.name = "OpenAIAdsAPIError";
|
|
18
|
+
this.statusCode = statusCode;
|
|
19
|
+
this.detail = detail;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class OpenAIAdsClient {
|
|
23
|
+
apiKey;
|
|
24
|
+
baseUrl;
|
|
25
|
+
constructor(apiKey, baseUrl = API_BASE_URL) {
|
|
26
|
+
if (!apiKey.trim()) {
|
|
27
|
+
throw new Error("OPENAI_ADS_API_KEY is required.");
|
|
28
|
+
}
|
|
29
|
+
this.apiKey = apiKey;
|
|
30
|
+
this.baseUrl = validateBaseUrl(baseUrl, "OPENAI_ADS_API_BASE_URL");
|
|
31
|
+
}
|
|
32
|
+
static fromEnv() {
|
|
33
|
+
return new OpenAIAdsClient(process.env.OPENAI_ADS_API_KEY ?? "", process.env.OPENAI_ADS_API_BASE_URL ?? API_BASE_URL);
|
|
34
|
+
}
|
|
35
|
+
async get(path, params) {
|
|
36
|
+
return this.request(this.baseUrl, "GET", path, { params });
|
|
37
|
+
}
|
|
38
|
+
async post(path, body) {
|
|
39
|
+
return this.request(this.baseUrl, "POST", path, { json: body });
|
|
40
|
+
}
|
|
41
|
+
async uploadFile(path, filePath) {
|
|
42
|
+
const bytes = await readFile(filePath);
|
|
43
|
+
const form = new FormData();
|
|
44
|
+
form.append("file", new Blob([bytes]), basename(filePath));
|
|
45
|
+
return this.request(this.baseUrl, "POST", path, { body: form });
|
|
46
|
+
}
|
|
47
|
+
async postConversions(pixelId, events) {
|
|
48
|
+
return this.request(CONVERSIONS_BASE_URL, "POST", "/events", {
|
|
49
|
+
params: { pid: pixelId },
|
|
50
|
+
json: { events },
|
|
51
|
+
redactDetail: true,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async request(baseUrl, method, path, options = {}) {
|
|
55
|
+
const url = buildUrl(baseUrl, path, options.params);
|
|
56
|
+
const headers = new Headers({
|
|
57
|
+
Accept: "application/json",
|
|
58
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
59
|
+
"User-Agent": USER_AGENT,
|
|
60
|
+
});
|
|
61
|
+
let body = options.body;
|
|
62
|
+
if (options.json !== undefined) {
|
|
63
|
+
headers.set("Content-Type", "application/json");
|
|
64
|
+
body = JSON.stringify(options.json);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(url, { method, headers, body, redirect: "manual" });
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
throw await toApiError(response, options.redactDetail === true);
|
|
70
|
+
}
|
|
71
|
+
const text = await response.text();
|
|
72
|
+
if (!text) {
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
return JSON.parse(text);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof OpenAIAdsAPIError) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
throw new OpenAIAdsAPIError(0, `Network error contacting OpenAI Ads API: ${error instanceof Error ? error.name : "Error"}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function toApiError(response, redactDetail) {
|
|
86
|
+
const friendly = FRIENDLY_ERRORS[response.status];
|
|
87
|
+
if (friendly) {
|
|
88
|
+
return new OpenAIAdsAPIError(response.status, friendly);
|
|
89
|
+
}
|
|
90
|
+
if (response.status >= 500) {
|
|
91
|
+
const requestId = response.headers.get("x-request-id");
|
|
92
|
+
let message = "OpenAI Ads API is temporarily unavailable. Please try again shortly.";
|
|
93
|
+
if (requestId) {
|
|
94
|
+
message = `${message} Request ID: ${requestId}`;
|
|
95
|
+
}
|
|
96
|
+
return new OpenAIAdsAPIError(response.status, message);
|
|
97
|
+
}
|
|
98
|
+
let detail = `HTTP ${response.status}`;
|
|
99
|
+
if (!redactDetail) {
|
|
100
|
+
try {
|
|
101
|
+
const body = (await response.json());
|
|
102
|
+
detail = String(body.detail ?? body.message ?? JSON.stringify(body));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
detail = (await response.text()) || detail;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return new OpenAIAdsAPIError(response.status, `API error (${response.status}): ${detail}`);
|
|
109
|
+
}
|
|
110
|
+
function buildUrl(baseUrl, path, params) {
|
|
111
|
+
const url = new URL(path, `${baseUrl}/`);
|
|
112
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
113
|
+
if (value === undefined || value === null) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (Array.isArray(value)) {
|
|
117
|
+
for (const item of value) {
|
|
118
|
+
if (item !== undefined && item !== null) {
|
|
119
|
+
url.searchParams.append(key, String(item));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
url.searchParams.set(key, String(value));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return url.toString();
|
|
128
|
+
}
|
|
129
|
+
function validateBaseUrl(baseUrl, envName) {
|
|
130
|
+
const parsed = new URL(baseUrl);
|
|
131
|
+
if (parsed.protocol !== "https:") {
|
|
132
|
+
throw new Error(`${envName} must use https.`);
|
|
133
|
+
}
|
|
134
|
+
if (!parsed.hostname) {
|
|
135
|
+
throw new Error(`${envName} must include a hostname.`);
|
|
136
|
+
}
|
|
137
|
+
if (parsed.username || parsed.password) {
|
|
138
|
+
throw new Error(`${envName} must not include credentials.`);
|
|
139
|
+
}
|
|
140
|
+
if (parsed.search || parsed.hash) {
|
|
141
|
+
throw new Error(`${envName} must not include query or fragment.`);
|
|
142
|
+
}
|
|
143
|
+
return baseUrl.replace(/\/+$/, "");
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import type { ZodRawShape } from "zod";
|
|
4
|
+
import { OpenAIAdsClient, type JsonRecord } from "./client.js";
|
|
5
|
+
export type { JsonRecord } from "./client.js";
|
|
6
|
+
export declare const INSTRUCTIONS: string;
|
|
7
|
+
export declare const RESPONSE_CHAR_BUDGET = 60000;
|
|
8
|
+
export declare const CONCISE_LIST_HEAD = 50;
|
|
9
|
+
export type AdsClientLike = Pick<OpenAIAdsClient, "get" | "post" | "uploadFile" | "postConversions">;
|
|
10
|
+
export type ToolArgs = Record<string, unknown>;
|
|
11
|
+
export type ToolHandler = (args: ToolArgs) => Promise<string>;
|
|
12
|
+
export interface AdsToolDefinition {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
inputSchema: ZodRawShape;
|
|
16
|
+
argNames: string[];
|
|
17
|
+
writes?: boolean;
|
|
18
|
+
destructive?: boolean;
|
|
19
|
+
openWorld?: boolean;
|
|
20
|
+
idempotent?: boolean;
|
|
21
|
+
handler: ToolHandler;
|
|
22
|
+
}
|
|
23
|
+
export declare function setClientFactoryForTests(factory: () => AdsClientLike): void;
|
|
24
|
+
export declare function resetClientFactoryForTests(): void;
|
|
25
|
+
export declare function getClientOrError(): {
|
|
26
|
+
client?: AdsClientLike;
|
|
27
|
+
error?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function isReadonlyMode(): boolean;
|
|
30
|
+
export declare function budgetCeilingUsd(): number;
|
|
31
|
+
export declare function registerAdsTool(server: McpServer, definition: AdsToolDefinition): void;
|
|
32
|
+
export declare function textResult(text: string): CallToolResult;
|
|
33
|
+
export declare function compact(value: unknown): unknown;
|
|
34
|
+
export declare function serialise(value: unknown): string;
|
|
35
|
+
export declare function ok(value: unknown): string;
|
|
36
|
+
export declare function okSized(value: unknown, responseFormat?: string, followUp?: string): string;
|
|
37
|
+
export declare function handleApiError(error: unknown): string;
|
|
38
|
+
export declare function badRequest(message: string): string;
|
|
39
|
+
export declare function validateIntRange(name: string, value: number, minimum: number, maximum: number): string | null;
|
|
40
|
+
export declare function validateFloatRange(name: string, value: number, minimum: number, maximum: number): string | null;
|
|
41
|
+
export declare function validateNonEmpty(name: string, value: unknown, minimum?: number, maximum?: number): string | null;
|
|
42
|
+
export declare function validateOption(name: string, value: string, allowed: Set<string>): string | null;
|
|
43
|
+
export declare function coerceJson(value: unknown, name: string): [unknown, string | null];
|
|
44
|
+
export declare function coerceMapping(value: unknown, name: string): [JsonRecord | null, string | null];
|
|
45
|
+
export declare function coerceList(value: unknown, name: string): [unknown[] | null, string | null];
|
|
46
|
+
export declare function coerceStringList(value: unknown, name: string): [string[] | null, string | null];
|
|
47
|
+
export declare function jsonQueryList(value: unknown, name: string): [string[] | null, string | null];
|
|
48
|
+
export declare function optionalParams(input: JsonRecord): JsonRecord;
|
|
49
|
+
export declare function usdToMicros(value: number): number;
|
|
50
|
+
export declare function budgetGuard(budgetUsd: number, confirmBudget: boolean): string | null;
|
|
51
|
+
export declare function validateUnixTime(name: string, value: unknown): string | null;
|
|
52
|
+
export declare function extractId(value: JsonRecord, ...keys: string[]): string | null;
|
|
53
|
+
export declare function nowMs(): number;
|
|
54
|
+
export declare function conversionTimeBoundsMs(): [number, number];
|
|
55
|
+
export declare function isRecord(value: unknown): value is JsonRecord;
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import { OpenAIAdsAPIError, OpenAIAdsClient } from "./client.js";
|
|
2
|
+
export const INSTRUCTIONS = "Typed MCP tools for OpenAI's Advertiser API. Use get_account first to " +
|
|
3
|
+
"confirm the API key works, then read insights before changing spend. " +
|
|
4
|
+
"The safest workflow is: check the account, inspect campaigns and " +
|
|
5
|
+
"insights, build new campaigns paused, review the created campaign, ad " +
|
|
6
|
+
"group, and ads, then activate each layer explicitly when the user asks.\n\n" +
|
|
7
|
+
"Safety model:\n" +
|
|
8
|
+
" 1. Create tools default to paused. build_campaign creates every object paused.\n" +
|
|
9
|
+
" 2. Budget-setting tools enforce OPENAI_ADS_BUDGET_CEILING_USD, default 100 USD, unless confirm_budget=True.\n" +
|
|
10
|
+
" 3. Set OPENAI_ADS_MCP_READONLY=1 for first connection. In readonly mode write tools are not registered.\n" +
|
|
11
|
+
" 4. Conversion event ingestion never logs user data. Validate batches before sending them.\n" +
|
|
12
|
+
"Paid presence is half the picture. Track how your brand shows up organically across ChatGPT, Perplexity, Gemini and Claude at trakkr.ai.";
|
|
13
|
+
const COMPACT_SEPARATORS = { dropNulls: true };
|
|
14
|
+
export const RESPONSE_CHAR_BUDGET = 60_000;
|
|
15
|
+
export const CONCISE_LIST_HEAD = 50;
|
|
16
|
+
const HEAVY_FIELDS = new Set(["raw", "raw_response", "raw_results", "html", "request", "response"]);
|
|
17
|
+
let clientFactory = () => OpenAIAdsClient.fromEnv();
|
|
18
|
+
export function setClientFactoryForTests(factory) {
|
|
19
|
+
clientFactory = factory;
|
|
20
|
+
}
|
|
21
|
+
export function resetClientFactoryForTests() {
|
|
22
|
+
clientFactory = () => OpenAIAdsClient.fromEnv();
|
|
23
|
+
}
|
|
24
|
+
export function getClientOrError() {
|
|
25
|
+
try {
|
|
26
|
+
return { client: clientFactory() };
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return {
|
|
30
|
+
error: badRequest(error instanceof Error
|
|
31
|
+
? `OpenAI Ads MCP client is not initialized. ${error.message}`
|
|
32
|
+
: "OpenAI Ads MCP client is not initialized. Set OPENAI_ADS_API_KEY and restart the MCP server."),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function isReadonlyMode() {
|
|
37
|
+
return truthy(process.env.OPENAI_ADS_MCP_READONLY);
|
|
38
|
+
}
|
|
39
|
+
function truthy(value) {
|
|
40
|
+
return ["1", "true", "yes", "on"].includes((value ?? "").trim().toLowerCase());
|
|
41
|
+
}
|
|
42
|
+
export function budgetCeilingUsd() {
|
|
43
|
+
const parsed = Number.parseFloat(process.env.OPENAI_ADS_BUDGET_CEILING_USD ?? "100");
|
|
44
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 100;
|
|
45
|
+
}
|
|
46
|
+
export function registerAdsTool(server, definition) {
|
|
47
|
+
if (definition.writes && isReadonlyMode()) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const annotations = {
|
|
51
|
+
readOnlyHint: !definition.writes,
|
|
52
|
+
destructiveHint: definition.destructive ?? false,
|
|
53
|
+
idempotentHint: definition.idempotent ?? !definition.writes,
|
|
54
|
+
openWorldHint: definition.openWorld ?? false,
|
|
55
|
+
};
|
|
56
|
+
server.registerTool(definition.name, {
|
|
57
|
+
description: definition.description,
|
|
58
|
+
inputSchema: definition.inputSchema,
|
|
59
|
+
annotations,
|
|
60
|
+
}, async (args) => textResult(await definition.handler(args)));
|
|
61
|
+
}
|
|
62
|
+
export function textResult(text) {
|
|
63
|
+
return { content: [{ type: "text", text }] };
|
|
64
|
+
}
|
|
65
|
+
export function compact(value) {
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
return value.map((item) => compact(item));
|
|
68
|
+
}
|
|
69
|
+
if (value && typeof value === "object") {
|
|
70
|
+
const output = {};
|
|
71
|
+
for (const [key, item] of Object.entries(value)) {
|
|
72
|
+
if (item !== null && item !== undefined) {
|
|
73
|
+
output[key] = compact(item);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return output;
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
export function serialise(value) {
|
|
81
|
+
void COMPACT_SEPARATORS;
|
|
82
|
+
return JSON.stringify(compact(value));
|
|
83
|
+
}
|
|
84
|
+
export function ok(value) {
|
|
85
|
+
return serialise(value);
|
|
86
|
+
}
|
|
87
|
+
export function okSized(value, responseFormat = "detailed", followUp) {
|
|
88
|
+
if (!isRecord(value)) {
|
|
89
|
+
return ok(value);
|
|
90
|
+
}
|
|
91
|
+
let data = value;
|
|
92
|
+
const notes = [];
|
|
93
|
+
if (responseFormat === "concise") {
|
|
94
|
+
const [slimmed, note] = toConcise(data);
|
|
95
|
+
data = slimmed;
|
|
96
|
+
if (note) {
|
|
97
|
+
notes.push(note);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const [bounded, budgetNote] = enforceBudget(data);
|
|
101
|
+
data = bounded;
|
|
102
|
+
if (budgetNote) {
|
|
103
|
+
notes.push(budgetNote);
|
|
104
|
+
}
|
|
105
|
+
if (notes.length) {
|
|
106
|
+
data = {
|
|
107
|
+
...data,
|
|
108
|
+
_response: {
|
|
109
|
+
note: notes.join(" "),
|
|
110
|
+
...(followUp ? { more: followUp } : {}),
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return ok(data);
|
|
115
|
+
}
|
|
116
|
+
function toConcise(data) {
|
|
117
|
+
const stats = { fields: 0, items: 0 };
|
|
118
|
+
const walk = (value) => {
|
|
119
|
+
if (Array.isArray(value)) {
|
|
120
|
+
let items = value;
|
|
121
|
+
if (items.length > CONCISE_LIST_HEAD) {
|
|
122
|
+
stats.items += items.length - CONCISE_LIST_HEAD;
|
|
123
|
+
items = items.slice(0, CONCISE_LIST_HEAD);
|
|
124
|
+
}
|
|
125
|
+
return items.map((item) => walk(item));
|
|
126
|
+
}
|
|
127
|
+
if (isRecord(value)) {
|
|
128
|
+
const out = {};
|
|
129
|
+
for (const [key, item] of Object.entries(value)) {
|
|
130
|
+
if (HEAVY_FIELDS.has(key)) {
|
|
131
|
+
stats.fields += 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
out[key] = walk(item);
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
};
|
|
140
|
+
const slimmed = walk(data);
|
|
141
|
+
if (!stats.fields && !stats.items) {
|
|
142
|
+
return [slimmed, null];
|
|
143
|
+
}
|
|
144
|
+
const bits = [];
|
|
145
|
+
if (stats.items) {
|
|
146
|
+
bits.push(`capped long lists to the first ${CONCISE_LIST_HEAD} (${stats.items} items held back)`);
|
|
147
|
+
}
|
|
148
|
+
if (stats.fields) {
|
|
149
|
+
bits.push(`dropped ${stats.fields} verbose field(s)`);
|
|
150
|
+
}
|
|
151
|
+
return [slimmed, `Concise view: ${bits.join(" and ")}. Pass response_format='detailed' for the full payload.`];
|
|
152
|
+
}
|
|
153
|
+
function enforceBudget(data) {
|
|
154
|
+
if (serialise(data).length <= RESPONSE_CHAR_BUDGET) {
|
|
155
|
+
return [data, null];
|
|
156
|
+
}
|
|
157
|
+
let working = structuredClone(data);
|
|
158
|
+
const dropped = new Map();
|
|
159
|
+
for (let i = 0; i < 80; i += 1) {
|
|
160
|
+
const listFields = [...iterListFields(working)];
|
|
161
|
+
const best = listFields.sort((a, b) => serialise(b.list).length - serialise(a.list).length)[0];
|
|
162
|
+
if (!best || best.list.length <= 1) {
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
const keep = Math.max(1, Math.floor(best.list.length / 2));
|
|
166
|
+
dropped.set(best.key, (dropped.get(best.key) ?? 0) + best.list.length - keep);
|
|
167
|
+
best.container[best.key] = best.list.slice(0, keep);
|
|
168
|
+
if (serialise(working).length <= RESPONSE_CHAR_BUDGET) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (!dropped.size) {
|
|
173
|
+
return [working, null];
|
|
174
|
+
}
|
|
175
|
+
const detail = [...dropped.entries()].map(([key, count]) => `${count} from '${key}'`).join(", ");
|
|
176
|
+
return [working, `Trimmed to fit the context budget: dropped ${detail}. Narrow the query or page with cursors.`];
|
|
177
|
+
}
|
|
178
|
+
function* iterListFields(data) {
|
|
179
|
+
if (Array.isArray(data)) {
|
|
180
|
+
for (const item of data) {
|
|
181
|
+
yield* iterListFields(item);
|
|
182
|
+
}
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (!isRecord(data)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
for (const [key, value] of Object.entries(data)) {
|
|
189
|
+
if (Array.isArray(value)) {
|
|
190
|
+
yield { container: data, key, list: value };
|
|
191
|
+
for (const item of value) {
|
|
192
|
+
yield* iterListFields(item);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else if (isRecord(value)) {
|
|
196
|
+
yield* iterListFields(value);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export function handleApiError(error) {
|
|
201
|
+
if (!(error instanceof OpenAIAdsAPIError)) {
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
if (error.statusCode === 0 || error.statusCode === 401 || error.statusCode >= 500) {
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
return JSON.stringify({ error: true, message: error.detail });
|
|
208
|
+
}
|
|
209
|
+
export function badRequest(message) {
|
|
210
|
+
return JSON.stringify({ error: true, message });
|
|
211
|
+
}
|
|
212
|
+
export function validateIntRange(name, value, minimum, maximum) {
|
|
213
|
+
if (value < minimum || value > maximum) {
|
|
214
|
+
return badRequest(`${name} must be between ${minimum} and ${maximum}.`);
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
export function validateFloatRange(name, value, minimum, maximum) {
|
|
219
|
+
if (value < minimum || value > maximum) {
|
|
220
|
+
return badRequest(`${name} must be between ${minimum} and ${maximum}.`);
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
export function validateNonEmpty(name, value, minimum = 1, maximum = 500) {
|
|
225
|
+
if (typeof value !== "string") {
|
|
226
|
+
return badRequest(`${name} is required.`);
|
|
227
|
+
}
|
|
228
|
+
const normalized = value.trim();
|
|
229
|
+
if (normalized.length < minimum || normalized.length > maximum) {
|
|
230
|
+
return badRequest(`${name} must be ${minimum}-${maximum} characters.`);
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
export function validateOption(name, value, allowed) {
|
|
235
|
+
if (!allowed.has(value)) {
|
|
236
|
+
return badRequest(`Invalid ${name}: ${value}. Allowed values: ${[...allowed].sort().join(", ")}.`);
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
export function coerceJson(value, name) {
|
|
241
|
+
if (typeof value !== "string") {
|
|
242
|
+
return [value, null];
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
return [JSON.parse(value), null];
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
return [null, badRequest(`${name} must be valid JSON when passed as a string: ${error instanceof Error ? error.message : "invalid JSON"}.`)];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export function coerceMapping(value, name) {
|
|
252
|
+
const [parsed, error] = coerceJson(value, name);
|
|
253
|
+
if (error) {
|
|
254
|
+
return [null, error];
|
|
255
|
+
}
|
|
256
|
+
if (!isRecord(parsed)) {
|
|
257
|
+
return [null, badRequest(`${name} must be an object.`)];
|
|
258
|
+
}
|
|
259
|
+
return [parsed, null];
|
|
260
|
+
}
|
|
261
|
+
export function coerceList(value, name) {
|
|
262
|
+
if (value === undefined || value === null) {
|
|
263
|
+
return [null, null];
|
|
264
|
+
}
|
|
265
|
+
if (typeof value === "string") {
|
|
266
|
+
const stripped = value.trim();
|
|
267
|
+
if (!stripped) {
|
|
268
|
+
return [[], null];
|
|
269
|
+
}
|
|
270
|
+
if (stripped.startsWith("[")) {
|
|
271
|
+
const [parsed, error] = coerceJson(stripped, name);
|
|
272
|
+
if (error) {
|
|
273
|
+
return [null, error];
|
|
274
|
+
}
|
|
275
|
+
value = parsed;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
return [stripped.split(",").map((part) => part.trim()).filter(Boolean), null];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (!Array.isArray(value)) {
|
|
282
|
+
return [null, badRequest(`${name} must be a list or a comma-separated string.`)];
|
|
283
|
+
}
|
|
284
|
+
return [value, null];
|
|
285
|
+
}
|
|
286
|
+
export function coerceStringList(value, name) {
|
|
287
|
+
const [items, error] = coerceList(value, name);
|
|
288
|
+
if (error || items === null) {
|
|
289
|
+
return [null, error];
|
|
290
|
+
}
|
|
291
|
+
const out = [];
|
|
292
|
+
for (const item of items) {
|
|
293
|
+
if (typeof item !== "string" || !item.trim()) {
|
|
294
|
+
return [null, badRequest(`${name} must contain only non-empty strings.`)];
|
|
295
|
+
}
|
|
296
|
+
out.push(item.trim());
|
|
297
|
+
}
|
|
298
|
+
return [out, null];
|
|
299
|
+
}
|
|
300
|
+
export function jsonQueryList(value, name) {
|
|
301
|
+
const [items, error] = coerceList(value, name);
|
|
302
|
+
if (error || items === null) {
|
|
303
|
+
return [null, error];
|
|
304
|
+
}
|
|
305
|
+
const encoded = [];
|
|
306
|
+
for (const item of items) {
|
|
307
|
+
if (typeof item === "string") {
|
|
308
|
+
const stripped = item.trim();
|
|
309
|
+
if (stripped.startsWith("{") || stripped.startsWith("[")) {
|
|
310
|
+
const [parsed, parseError] = coerceJson(stripped, name);
|
|
311
|
+
if (parseError) {
|
|
312
|
+
return [null, parseError];
|
|
313
|
+
}
|
|
314
|
+
encoded.push(JSON.stringify(parsed));
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
encoded.push(stripped);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else if (isRecord(item)) {
|
|
321
|
+
encoded.push(JSON.stringify(item));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
return [null, badRequest(`${name} must contain strings or objects.`)];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return [encoded, null];
|
|
328
|
+
}
|
|
329
|
+
export function optionalParams(input) {
|
|
330
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined && value !== null));
|
|
331
|
+
}
|
|
332
|
+
export function usdToMicros(value) {
|
|
333
|
+
return Math.round(value * 1_000_000);
|
|
334
|
+
}
|
|
335
|
+
export function budgetGuard(budgetUsd, confirmBudget) {
|
|
336
|
+
if (budgetUsd < 1) {
|
|
337
|
+
return badRequest("budget_usd must be at least 1.00 USD.");
|
|
338
|
+
}
|
|
339
|
+
const ceiling = budgetCeilingUsd();
|
|
340
|
+
if (budgetUsd > ceiling && !confirmBudget) {
|
|
341
|
+
return badRequest(`budget_usd is ${formatNumber(budgetUsd)}, above the configured ceiling of ${formatNumber(ceiling)} USD. ` +
|
|
342
|
+
"Pass confirm_budget=True to confirm this spend limit.");
|
|
343
|
+
}
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
export function validateUnixTime(name, value) {
|
|
347
|
+
if (value === undefined || value === null) {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
return validateIntRange(name, Number(value), 946684800, 4102444800);
|
|
351
|
+
}
|
|
352
|
+
export function extractId(value, ...keys) {
|
|
353
|
+
for (const key of keys) {
|
|
354
|
+
const item = value[key];
|
|
355
|
+
if (typeof item === "string" && item) {
|
|
356
|
+
return item;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
export function nowMs() {
|
|
362
|
+
return Date.now();
|
|
363
|
+
}
|
|
364
|
+
export function conversionTimeBoundsMs() {
|
|
365
|
+
const now = Date.now();
|
|
366
|
+
return [now - 7 * 24 * 60 * 60 * 1000, now + 10 * 60 * 1000];
|
|
367
|
+
}
|
|
368
|
+
export function isRecord(value) {
|
|
369
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
370
|
+
}
|
|
371
|
+
function formatNumber(value) {
|
|
372
|
+
return Number.isInteger(value) ? String(value) : String(value);
|
|
373
|
+
}
|
|
374
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|