apptvty 0.1.5 → 0.2.1
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 +37 -17
- package/dist/chunk-GMQN6656.mjs +1096 -0
- package/dist/chunk-GMQN6656.mjs.map +1 -0
- package/dist/{chunk-OZAZWZNO.mjs → chunk-JNM4IJDR.mjs} +63 -34
- package/dist/chunk-JNM4IJDR.mjs.map +1 -0
- package/dist/chunk-OZT7PIDN.mjs +178 -0
- package/dist/chunk-OZT7PIDN.mjs.map +1 -0
- package/dist/cli.js +94 -9
- package/dist/index.d.mts +138 -20
- package/dist/index.d.ts +138 -20
- package/dist/index.js +389 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -3
- package/dist/middleware/express.d.mts +24 -5
- package/dist/middleware/express.d.ts +24 -5
- package/dist/middleware/express.js +675 -7
- package/dist/middleware/express.js.map +1 -1
- package/dist/middleware/express.mjs +4 -2
- package/dist/middleware/nextjs.d.mts +29 -6
- package/dist/middleware/nextjs.d.ts +29 -6
- package/dist/middleware/nextjs.js +640 -33
- package/dist/middleware/nextjs.js.map +1 -1
- package/dist/middleware/nextjs.mjs +4 -2
- package/dist/setup.d.mts +9 -0
- package/dist/setup.d.ts +9 -0
- package/dist/setup.js +6 -2
- package/dist/setup.js.map +1 -1
- package/dist/setup.mjs +6 -2
- package/dist/setup.mjs.map +1 -1
- package/dist/{types-C1oUTCsT.d.mts → types-Zt2qHOrW.d.mts} +122 -2
- package/dist/{types-C1oUTCsT.d.ts → types-Zt2qHOrW.d.ts} +122 -2
- package/package.json +1 -1
- package/dist/chunk-3ITWIW4P.mjs +0 -87
- package/dist/chunk-3ITWIW4P.mjs.map +0 -1
- package/dist/chunk-JVOMOEEL.mjs +0 -509
- package/dist/chunk-JVOMOEEL.mjs.map +0 -1
- package/dist/chunk-OZAZWZNO.mjs.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,8 @@ async function register(options) {
|
|
|
22
22
|
body: JSON.stringify({
|
|
23
23
|
domain: options.domain,
|
|
24
24
|
framework: options.framework ?? "other",
|
|
25
|
-
agent_id: options.agentId
|
|
25
|
+
agent_id: options.agentId,
|
|
26
|
+
...options.email && { email: options.email }
|
|
26
27
|
}),
|
|
27
28
|
signal: AbortSignal.timeout(2e4)
|
|
28
29
|
});
|
|
@@ -39,15 +40,18 @@ async function register(options) {
|
|
|
39
40
|
apiKey: data.api_key,
|
|
40
41
|
companyId: data.company_id,
|
|
41
42
|
walletAddress: data.wallet_address ?? null,
|
|
43
|
+
platformDepositAddress: data.platform_deposit_address ?? null,
|
|
42
44
|
dashboardUrl: data.dashboard_url,
|
|
43
45
|
claimTokenExpiresAt: data.claim_token_expires_at,
|
|
44
46
|
trialEndsAt: data.trial_ends_at,
|
|
47
|
+
email: data.email ?? null,
|
|
45
48
|
setup: {
|
|
46
49
|
envVars: data.setup?.env_vars ?? {
|
|
47
50
|
APPTVTY_SITE_ID: data.site_id,
|
|
48
51
|
APPTVTY_API_KEY: data.api_key
|
|
49
52
|
},
|
|
50
|
-
files: data.setup?.files
|
|
53
|
+
files: data.setup?.files,
|
|
54
|
+
x402: data.setup?.x402
|
|
51
55
|
}
|
|
52
56
|
};
|
|
53
57
|
}
|
|
@@ -85,7 +89,8 @@ async function migrate(options) {
|
|
|
85
89
|
var args = process.argv.slice(2);
|
|
86
90
|
var rawCmd = args[0];
|
|
87
91
|
var isMigrate = rawCmd === "migrate";
|
|
88
|
-
var
|
|
92
|
+
var isCreateSuperuser = rawCmd === "create-superuser";
|
|
93
|
+
var cmdArgs = isMigrate || isCreateSuperuser ? args.slice(1) : args;
|
|
89
94
|
function getFlag(name, from = cmdArgs) {
|
|
90
95
|
const idx = from.indexOf(`--${name}`);
|
|
91
96
|
return idx !== -1 ? from[idx + 1] : void 0;
|
|
@@ -94,6 +99,7 @@ var isNonInteractive = cmdArgs.includes("--non-interactive") || cmdArgs.includes
|
|
|
94
99
|
var flagDomain = getFlag("domain");
|
|
95
100
|
var flagFramework = getFlag("framework");
|
|
96
101
|
var flagApiUrl = getFlag("api-url");
|
|
102
|
+
var flagEmail = getFlag("email");
|
|
97
103
|
function detectFramework() {
|
|
98
104
|
try {
|
|
99
105
|
const pkg = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), "package.json"), "utf-8"));
|
|
@@ -186,7 +192,11 @@ function loadEnvVars() {
|
|
|
186
192
|
const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.+?)\s*$/);
|
|
187
193
|
if (m) out[m[1]] = m[2].replace(/^["']|["']$/g, "").trim();
|
|
188
194
|
}
|
|
189
|
-
return {
|
|
195
|
+
return {
|
|
196
|
+
siteId: out.APPTVTY_SITE_ID,
|
|
197
|
+
apiKey: out.APPTVTY_API_KEY,
|
|
198
|
+
claimToken: out.APPTVTY_CLAIM_TOKEN
|
|
199
|
+
};
|
|
190
200
|
}
|
|
191
201
|
async function runInit() {
|
|
192
202
|
const framework = flagFramework ?? detectFramework();
|
|
@@ -201,6 +211,10 @@ async function runInit() {
|
|
|
201
211
|
if (!domain && !isNonInteractive) {
|
|
202
212
|
domain = await prompt(" Enter your site domain (e.g. mysite.com): ");
|
|
203
213
|
}
|
|
214
|
+
let email = flagEmail ?? "";
|
|
215
|
+
if (!email && !isNonInteractive) {
|
|
216
|
+
email = await prompt(" Enter your email to claim this account (optional, press Enter to skip): ");
|
|
217
|
+
}
|
|
204
218
|
if (!domain) {
|
|
205
219
|
if (isNonInteractive) {
|
|
206
220
|
process.stdout.write(JSON.stringify({ error: "domain is required (use --domain)" }) + "\n");
|
|
@@ -218,7 +232,8 @@ async function runInit() {
|
|
|
218
232
|
domain,
|
|
219
233
|
framework,
|
|
220
234
|
agentId: "apptvty-cli",
|
|
221
|
-
apiUrl: flagApiUrl
|
|
235
|
+
apiUrl: flagApiUrl,
|
|
236
|
+
...email && { email }
|
|
222
237
|
});
|
|
223
238
|
} catch (err) {
|
|
224
239
|
const msg = err instanceof RegistrationError ? err.message : String(err);
|
|
@@ -253,9 +268,12 @@ async function runInit() {
|
|
|
253
268
|
company_id: result.companyId,
|
|
254
269
|
wallet_address: result.walletAddress,
|
|
255
270
|
dashboard_url: result.dashboardUrl,
|
|
271
|
+
claim_token_expires_at: result.claimTokenExpiresAt,
|
|
256
272
|
trial_ends_at: result.trialEndsAt,
|
|
273
|
+
email: result.email ?? null,
|
|
257
274
|
env_file: envFile,
|
|
258
|
-
env_vars: result.setup.envVars
|
|
275
|
+
env_vars: result.setup.envVars,
|
|
276
|
+
x402: result.setup.x402
|
|
259
277
|
}) + "\n"
|
|
260
278
|
);
|
|
261
279
|
return;
|
|
@@ -264,6 +282,9 @@ async function runInit() {
|
|
|
264
282
|
if (result.walletAddress) {
|
|
265
283
|
console.log(` \u2713 Wallet created: ${result.walletAddress}`);
|
|
266
284
|
}
|
|
285
|
+
if (email) {
|
|
286
|
+
console.log(` \u2713 Email linked: ${email}`);
|
|
287
|
+
}
|
|
267
288
|
console.log(` \u2713 Credentials written: ${envFile}`);
|
|
268
289
|
if (scaffolded.length > 0) {
|
|
269
290
|
for (const f of scaffolded) {
|
|
@@ -274,21 +295,83 @@ async function runInit() {
|
|
|
274
295
|
console.log("\n middleware.ts");
|
|
275
296
|
console.log(" import { withApptvty } from 'apptvty/nextjs';");
|
|
276
297
|
console.log(" export default withApptvty({ apiKey: process.env.APPTVTY_API_KEY!, siteId: process.env.APPTVTY_SITE_ID! });");
|
|
298
|
+
console.log(" export default withApptvty({ apiKey: process.env.APPTVTY_API_KEY!, siteId: process.env.APPTVTY_SITE_ID! });");
|
|
277
299
|
console.log(" export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] };");
|
|
278
|
-
console.log("\n app/query/route.ts");
|
|
300
|
+
console.log("\n app/query/route.ts (Agent Interface)");
|
|
279
301
|
console.log(" import { createNextjsQueryHandler } from 'apptvty/nextjs';");
|
|
280
302
|
console.log(" export const GET = createNextjsQueryHandler({ apiKey: process.env.APPTVTY_API_KEY!, siteId: process.env.APPTVTY_SITE_ID! });");
|
|
303
|
+
console.log("\n app/api/apptvty/logs/route.ts (Maintainer Dashboard)");
|
|
304
|
+
console.log(" import { createNextjsDashboardHandler } from 'apptvty/nextjs';");
|
|
305
|
+
console.log(" export const GET = createNextjsDashboardHandler({ apiKey: process.env.APPTVTY_API_KEY!, siteId: process.env.APPTVTY_SITE_ID! });");
|
|
281
306
|
}
|
|
282
307
|
console.log("\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
283
308
|
console.log(" Free trial active \u2014 24 hours from now.");
|
|
284
|
-
|
|
309
|
+
if (result.setup.x402) {
|
|
310
|
+
console.log(` \u2713 Agent-native payments (X402): ${result.setup.x402.chain}/${result.setup.x402.currency}`);
|
|
311
|
+
if (result.platformDepositAddress) {
|
|
312
|
+
console.log(` \u2713 Platform Deposit Address: ${result.platformDepositAddress}`);
|
|
313
|
+
console.log(" (Send USDC here to fund ad campaigns autonomously)");
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
console.log(` \u2713 Trial expires: ${result.trialEndsAt}`);
|
|
317
|
+
console.log("");
|
|
318
|
+
if (email) {
|
|
319
|
+
console.log(` A claim link has been sent to: ${email}`);
|
|
320
|
+
console.log(" Or open the link below to access your dashboard:");
|
|
321
|
+
} else {
|
|
322
|
+
console.log(" No email provided \u2014 click the link below to claim your account.");
|
|
323
|
+
console.log(" (This link expires in 30 days. Save it now.)");
|
|
324
|
+
}
|
|
285
325
|
console.log("");
|
|
286
|
-
console.log(" Open the dashboard to log in before the trial ends:");
|
|
287
326
|
console.log(` ${result.dashboardUrl}`);
|
|
288
327
|
console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
289
328
|
console.log(" After the trial expires, this site's API key will stop working.");
|
|
329
|
+
console.log(" Advertisers: Deposit USDC to the address above, then fund via:");
|
|
330
|
+
console.log(" GET /v1/wallet/sync?tx_hash=<your_transaction_hash>");
|
|
290
331
|
console.log(" Log in once to keep your credentials and continue receiving analytics.\n");
|
|
291
332
|
}
|
|
333
|
+
async function runCreateSuperuser() {
|
|
334
|
+
console.log("\n \u{1F680} Apptvty \u2014 Create Superuser\n");
|
|
335
|
+
const { claimToken } = loadEnvVars();
|
|
336
|
+
if (!claimToken) {
|
|
337
|
+
console.error("\n \u2716 Error: APPTVTY_CLAIM_TOKEN not found in .env.local or .env");
|
|
338
|
+
console.log(" Please run `npx apptvty init` first to initialize your site.\n");
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
const email = await prompt(" Email: ");
|
|
342
|
+
const password = await prompt(" Password: ");
|
|
343
|
+
const name = await prompt(" Full Name (optional): ");
|
|
344
|
+
const apiUrl = flagApiUrl || "https://api.apptvty.com";
|
|
345
|
+
try {
|
|
346
|
+
const response = await fetch(`${apiUrl}/v1/auth/claim`, {
|
|
347
|
+
method: "POST",
|
|
348
|
+
headers: {
|
|
349
|
+
"Content-Type": "application/json"
|
|
350
|
+
},
|
|
351
|
+
body: JSON.stringify({
|
|
352
|
+
claim_token: claimToken,
|
|
353
|
+
email,
|
|
354
|
+
password,
|
|
355
|
+
name
|
|
356
|
+
})
|
|
357
|
+
});
|
|
358
|
+
const result = await response.json();
|
|
359
|
+
if (!response.ok) {
|
|
360
|
+
console.error(`
|
|
361
|
+
\u2716 Error: ${result.message || result.error?.message || response.statusText}`);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
console.log("\n \u2713 Superuser created successfully!");
|
|
365
|
+
console.log(` \u2713 Email: ${result.user.email}`);
|
|
366
|
+
console.log(` \u2713 Company: ${result.company.name}
|
|
367
|
+
`);
|
|
368
|
+
console.log(" You can now log in at https://dashboard.apptvty.com\n");
|
|
369
|
+
} catch (err) {
|
|
370
|
+
console.error(`
|
|
371
|
+
\u2716 Network error: ${err.message}`);
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
292
375
|
async function runMigrate() {
|
|
293
376
|
const { siteId, apiKey } = loadEnvVars();
|
|
294
377
|
if (!siteId || !apiKey) {
|
|
@@ -332,6 +415,8 @@ async function runMigrate() {
|
|
|
332
415
|
async function main() {
|
|
333
416
|
if (isMigrate) {
|
|
334
417
|
await runMigrate();
|
|
418
|
+
} else if (isCreateSuperuser) {
|
|
419
|
+
await runCreateSuperuser();
|
|
335
420
|
} else {
|
|
336
421
|
await runInit();
|
|
337
422
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,25 +1,47 @@
|
|
|
1
|
-
import { A as ApptvtyConfig, R as RequestLogEntry, Q as QueryRequest, B as BackendQueryResponse, P as PageAdsResponse, I as ImpressionLog, S as SiteOverviewStats, D as DailyStat,
|
|
2
|
-
export {
|
|
1
|
+
import { C as CrawlerInfo, A as ApptvtyConfig, R as RequestLogEntry, Q as QueryRequest, B as BackendQueryResponse, P as PageAdsResponse, I as ImpressionLog, S as SiteOverviewStats, D as DailyStat, a as RecentActivityItem, b as RecentQueryItem, c as CrawlerBreakdown, d as SiteWalletInfo, e as CreateCampaignParams, f as CampaignRecord, U as UpdateCampaignParams, g as InsufficientBalanceError, h as AgentQueryResponse, i as QueryEndpointDiscovery, j as AgentErrorResponse } from './types-Zt2qHOrW.mjs';
|
|
2
|
+
export { k as CampaignStatus, l as PageAd, m as QuerySource, n as SponsoredAd } from './types-Zt2qHOrW.mjs';
|
|
3
3
|
export { createNextjsQueryHandler, withApptvty } from './middleware/nextjs.mjs';
|
|
4
4
|
export { createExpressMiddleware, createExpressQueryHandler } from './middleware/express.mjs';
|
|
5
5
|
import 'next/server';
|
|
6
6
|
import 'node:http';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Lightweight AI crawler detection.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* - Impression logging (/v1/impressions) — triggers billing for ads
|
|
11
|
+
* This is the single source of truth for crawler classification in the SDK.
|
|
12
|
+
* The backend (Python analytics API and TypeScript handlers) should eventually
|
|
13
|
+
* consume this same list rather than maintaining separate copies.
|
|
15
14
|
*/
|
|
16
15
|
|
|
16
|
+
declare function detectCrawler(userAgent: string): CrawlerInfo;
|
|
17
|
+
/** Returns the list of all known crawlers for reference (e.g. for agents.txt generation) */
|
|
18
|
+
declare function getKnownCrawlerNames(): string[];
|
|
19
|
+
interface ScraperServiceInfo {
|
|
20
|
+
isScraperService: boolean;
|
|
21
|
+
/** Identifier of the matched service, or null if not a scraper service. */
|
|
22
|
+
name: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Detect whether the request comes from a known content-extraction scraper service
|
|
26
|
+
* (Jina, FireCrawl, Cloudflare Browser Rendering, etc.) rather than a direct AI crawler.
|
|
27
|
+
*
|
|
28
|
+
* Use this alongside detectCrawler() — scraper services are a distinct category:
|
|
29
|
+
* they proxy on behalf of an AI consumer but apply their own readability transform.
|
|
30
|
+
*/
|
|
31
|
+
declare function detectScraperService(userAgent: string): ScraperServiceInfo;
|
|
32
|
+
|
|
17
33
|
declare class ApptvtyClient {
|
|
18
34
|
private readonly baseUrl;
|
|
19
35
|
private readonly apiKey;
|
|
20
36
|
private readonly siteId;
|
|
21
37
|
private readonly debug;
|
|
38
|
+
private x402Token?;
|
|
22
39
|
constructor(config: ApptvtyConfig);
|
|
40
|
+
/**
|
|
41
|
+
* Set the X402 (LSAT) token for subsequent requests.
|
|
42
|
+
* This is called after the agent has successfully paid an X402 challenge.
|
|
43
|
+
*/
|
|
44
|
+
setX402Token(macaroon: string, preimage: string): void;
|
|
23
45
|
/**
|
|
24
46
|
* Send a batch of request log entries to the Apptvty ingestion API.
|
|
25
47
|
* Called by the logger's auto-flush — not called directly by user code.
|
|
@@ -61,6 +83,10 @@ declare class ApptvtyClient {
|
|
|
61
83
|
days: number;
|
|
62
84
|
stats: DailyStat[];
|
|
63
85
|
}>;
|
|
86
|
+
/** Get recent activity logs (last 48h). */
|
|
87
|
+
getRecentActivity(siteId: string, limit?: number, offset?: number): Promise<RecentActivityItem[]>;
|
|
88
|
+
/** Get recent agent queries. */
|
|
89
|
+
getRecentQueries(siteId: string, limit?: number, offset?: number): Promise<RecentQueryItem[]>;
|
|
64
90
|
/** Get crawler breakdown by type (default 30 days). */
|
|
65
91
|
getSiteCrawlers(days?: number): Promise<{
|
|
66
92
|
days: number;
|
|
@@ -76,7 +102,87 @@ declare class ApptvtyClient {
|
|
|
76
102
|
}>;
|
|
77
103
|
/** Get wallet balance and earnings. */
|
|
78
104
|
getSiteWallet(): Promise<SiteWalletInfo>;
|
|
105
|
+
/**
|
|
106
|
+
* Create an ad campaign. The campaign goes live immediately once the wallet
|
|
107
|
+
* has sufficient balance.
|
|
108
|
+
*
|
|
109
|
+
* If the wallet balance is too low, throws `ApptvtyInsufficientBalanceError`
|
|
110
|
+
* which includes deposit instructions so the agent can fund the wallet and retry.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // Site-based: ad copy derived from your site's crawled content
|
|
114
|
+
* const campaign = await client.createCampaign({
|
|
115
|
+
* name: 'My Kubernetes Blog',
|
|
116
|
+
* advertiser_site_id: 'site_abc123',
|
|
117
|
+
* keywords: ['kubernetes', 'devops', 'containers'],
|
|
118
|
+
* categories: ['technology'],
|
|
119
|
+
* bid_per_view_usdc: 0.001,
|
|
120
|
+
* daily_budget_usdc: 1.0,
|
|
121
|
+
* total_budget_usdc: 20.0,
|
|
122
|
+
* });
|
|
123
|
+
*
|
|
124
|
+
* // Static: manually written ad copy
|
|
125
|
+
* const campaign = await client.createCampaign({
|
|
126
|
+
* name: 'My Blog — Static',
|
|
127
|
+
* ad_text: 'Deep dives on Kubernetes, written by practitioners.',
|
|
128
|
+
* landing_url: 'https://myblog.com',
|
|
129
|
+
* keywords: ['kubernetes', 'devops'],
|
|
130
|
+
* categories: ['technology'],
|
|
131
|
+
* bid_per_view_usdc: 0.001,
|
|
132
|
+
* daily_budget_usdc: 1.0,
|
|
133
|
+
* total_budget_usdc: 10.0,
|
|
134
|
+
* });
|
|
135
|
+
*/
|
|
136
|
+
createCampaign(params: CreateCampaignParams): Promise<CampaignRecord>;
|
|
137
|
+
/**
|
|
138
|
+
* List all campaigns for this account.
|
|
139
|
+
* Also returns the schema (valid categories, minimum bid) so the agent
|
|
140
|
+
* knows valid field values without guessing.
|
|
141
|
+
*/
|
|
142
|
+
listCampaigns(): Promise<{
|
|
143
|
+
campaigns: CampaignRecord[];
|
|
144
|
+
total: number;
|
|
145
|
+
schema: {
|
|
146
|
+
valid_categories: string[];
|
|
147
|
+
valid_statuses: string[];
|
|
148
|
+
bid_per_view_usdc_minimum: number;
|
|
149
|
+
};
|
|
150
|
+
}>;
|
|
151
|
+
/**
|
|
152
|
+
* Get a single campaign by ID, including current spend and impression count.
|
|
153
|
+
* `budget_remaining_usdc` tells the agent how much budget is left before
|
|
154
|
+
* the campaign auto-pauses.
|
|
155
|
+
*/
|
|
156
|
+
getCampaign(campaignId: string): Promise<CampaignRecord>;
|
|
157
|
+
/**
|
|
158
|
+
* Partially update a campaign. Only fields present in `params` are changed.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* // Pause a campaign
|
|
162
|
+
* await client.updateCampaign(id, { status: 'paused' });
|
|
163
|
+
*
|
|
164
|
+
* // Increase bid and daily budget
|
|
165
|
+
* await client.updateCampaign(id, { bid_per_view_usdc: 0.002, daily_budget_usdc: 5.0 });
|
|
166
|
+
*/
|
|
167
|
+
updateCampaign(campaignId: string, params: UpdateCampaignParams): Promise<CampaignRecord>;
|
|
168
|
+
/**
|
|
169
|
+
* Pause a campaign immediately. Equivalent to updateCampaign(id, { status: 'paused' }).
|
|
170
|
+
* Campaigns are never deleted — billing history is retained.
|
|
171
|
+
*/
|
|
172
|
+
pauseCampaign(campaignId: string): Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Resume a paused campaign.
|
|
175
|
+
*/
|
|
176
|
+
resumeCampaign(campaignId: string): Promise<void>;
|
|
79
177
|
private get;
|
|
178
|
+
private patch;
|
|
179
|
+
private delete;
|
|
180
|
+
/**
|
|
181
|
+
* Settle an X402 challenge from the site's own USDC wallet balance.
|
|
182
|
+
* Called automatically when `post()` receives a 402 with an X402 header.
|
|
183
|
+
* Returns the preimage on success, or throws if the wallet balance is too low.
|
|
184
|
+
*/
|
|
185
|
+
private payX402Challenge;
|
|
80
186
|
private post;
|
|
81
187
|
private log;
|
|
82
188
|
private warn;
|
|
@@ -87,6 +193,30 @@ declare class ApptvtyApiError extends Error {
|
|
|
87
193
|
readonly body: string;
|
|
88
194
|
constructor(statusCode: number, path: string, body: string);
|
|
89
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Thrown by createCampaign() when the wallet balance is too low.
|
|
198
|
+
*
|
|
199
|
+
* The `details` property contains everything needed to fund the wallet
|
|
200
|
+
* autonomously and retry — the agent can inspect `details.deposit.address`
|
|
201
|
+
* and send USDC on Base without human intervention.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* import { ApptvtyInsufficientBalanceError } from 'apptvty';
|
|
205
|
+
*
|
|
206
|
+
* try {
|
|
207
|
+
* await client.createCampaign(params);
|
|
208
|
+
* } catch (err) {
|
|
209
|
+
* if (err instanceof ApptvtyInsufficientBalanceError) {
|
|
210
|
+
* const { shortfall_usdc, deposit } = err.details;
|
|
211
|
+
* // Agent can now: send shortfall_usdc USDC to deposit.address on deposit.chain
|
|
212
|
+
* // Then retry createCampaign
|
|
213
|
+
* }
|
|
214
|
+
* }
|
|
215
|
+
*/
|
|
216
|
+
declare class ApptvtyInsufficientBalanceError extends Error {
|
|
217
|
+
readonly details: InsufficientBalanceError | undefined;
|
|
218
|
+
constructor(details: InsufficientBalanceError | undefined);
|
|
219
|
+
}
|
|
90
220
|
|
|
91
221
|
/**
|
|
92
222
|
* Batched request logger.
|
|
@@ -122,18 +252,6 @@ declare class RequestLogger {
|
|
|
122
252
|
private log;
|
|
123
253
|
}
|
|
124
254
|
|
|
125
|
-
/**
|
|
126
|
-
* Lightweight AI crawler detection.
|
|
127
|
-
*
|
|
128
|
-
* This is the single source of truth for crawler classification in the SDK.
|
|
129
|
-
* The backend (Python analytics API and TypeScript handlers) should eventually
|
|
130
|
-
* consume this same list rather than maintaining separate copies.
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
declare function detectCrawler(userAgent: string): CrawlerInfo;
|
|
134
|
-
/** Returns the list of all known crawlers for reference (e.g. for agents.txt generation) */
|
|
135
|
-
declare function getKnownCrawlerNames(): string[];
|
|
136
|
-
|
|
137
255
|
/**
|
|
138
256
|
* Framework-agnostic query endpoint handler.
|
|
139
257
|
*
|
|
@@ -167,4 +285,4 @@ interface QueryHandlerResponse {
|
|
|
167
285
|
}
|
|
168
286
|
declare function createQueryHandler(client: ApptvtyClient, config: ApptvtyConfig): (req: QueryHandlerRequest) => Promise<QueryHandlerResponse>;
|
|
169
287
|
|
|
170
|
-
export { AgentErrorResponse, AgentQueryResponse, ApptvtyApiError, ApptvtyClient, ApptvtyConfig, CrawlerBreakdown, CrawlerInfo, DailyStat, ImpressionLog, PageAdsResponse, QueryEndpointDiscovery, RecentActivityItem, RecentQueryItem, RequestLogEntry, RequestLogger, SiteOverviewStats, SiteWalletInfo, createQueryHandler, detectCrawler, getKnownCrawlerNames };
|
|
288
|
+
export { AgentErrorResponse, AgentQueryResponse, ApptvtyApiError, ApptvtyClient, ApptvtyConfig, ApptvtyInsufficientBalanceError, CampaignRecord, CrawlerBreakdown, CrawlerInfo, CreateCampaignParams, DailyStat, ImpressionLog, InsufficientBalanceError, PageAdsResponse, QueryEndpointDiscovery, RecentActivityItem, RecentQueryItem, RequestLogEntry, RequestLogger, type ScraperServiceInfo, SiteOverviewStats, SiteWalletInfo, UpdateCampaignParams, createQueryHandler, detectCrawler, detectScraperService, getKnownCrawlerNames };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,47 @@
|
|
|
1
|
-
import { A as ApptvtyConfig, R as RequestLogEntry, Q as QueryRequest, B as BackendQueryResponse, P as PageAdsResponse, I as ImpressionLog, S as SiteOverviewStats, D as DailyStat,
|
|
2
|
-
export {
|
|
1
|
+
import { C as CrawlerInfo, A as ApptvtyConfig, R as RequestLogEntry, Q as QueryRequest, B as BackendQueryResponse, P as PageAdsResponse, I as ImpressionLog, S as SiteOverviewStats, D as DailyStat, a as RecentActivityItem, b as RecentQueryItem, c as CrawlerBreakdown, d as SiteWalletInfo, e as CreateCampaignParams, f as CampaignRecord, U as UpdateCampaignParams, g as InsufficientBalanceError, h as AgentQueryResponse, i as QueryEndpointDiscovery, j as AgentErrorResponse } from './types-Zt2qHOrW.js';
|
|
2
|
+
export { k as CampaignStatus, l as PageAd, m as QuerySource, n as SponsoredAd } from './types-Zt2qHOrW.js';
|
|
3
3
|
export { createNextjsQueryHandler, withApptvty } from './middleware/nextjs.js';
|
|
4
4
|
export { createExpressMiddleware, createExpressQueryHandler } from './middleware/express.js';
|
|
5
5
|
import 'next/server';
|
|
6
6
|
import 'node:http';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Lightweight AI crawler detection.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* - Impression logging (/v1/impressions) — triggers billing for ads
|
|
11
|
+
* This is the single source of truth for crawler classification in the SDK.
|
|
12
|
+
* The backend (Python analytics API and TypeScript handlers) should eventually
|
|
13
|
+
* consume this same list rather than maintaining separate copies.
|
|
15
14
|
*/
|
|
16
15
|
|
|
16
|
+
declare function detectCrawler(userAgent: string): CrawlerInfo;
|
|
17
|
+
/** Returns the list of all known crawlers for reference (e.g. for agents.txt generation) */
|
|
18
|
+
declare function getKnownCrawlerNames(): string[];
|
|
19
|
+
interface ScraperServiceInfo {
|
|
20
|
+
isScraperService: boolean;
|
|
21
|
+
/** Identifier of the matched service, or null if not a scraper service. */
|
|
22
|
+
name: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Detect whether the request comes from a known content-extraction scraper service
|
|
26
|
+
* (Jina, FireCrawl, Cloudflare Browser Rendering, etc.) rather than a direct AI crawler.
|
|
27
|
+
*
|
|
28
|
+
* Use this alongside detectCrawler() — scraper services are a distinct category:
|
|
29
|
+
* they proxy on behalf of an AI consumer but apply their own readability transform.
|
|
30
|
+
*/
|
|
31
|
+
declare function detectScraperService(userAgent: string): ScraperServiceInfo;
|
|
32
|
+
|
|
17
33
|
declare class ApptvtyClient {
|
|
18
34
|
private readonly baseUrl;
|
|
19
35
|
private readonly apiKey;
|
|
20
36
|
private readonly siteId;
|
|
21
37
|
private readonly debug;
|
|
38
|
+
private x402Token?;
|
|
22
39
|
constructor(config: ApptvtyConfig);
|
|
40
|
+
/**
|
|
41
|
+
* Set the X402 (LSAT) token for subsequent requests.
|
|
42
|
+
* This is called after the agent has successfully paid an X402 challenge.
|
|
43
|
+
*/
|
|
44
|
+
setX402Token(macaroon: string, preimage: string): void;
|
|
23
45
|
/**
|
|
24
46
|
* Send a batch of request log entries to the Apptvty ingestion API.
|
|
25
47
|
* Called by the logger's auto-flush — not called directly by user code.
|
|
@@ -61,6 +83,10 @@ declare class ApptvtyClient {
|
|
|
61
83
|
days: number;
|
|
62
84
|
stats: DailyStat[];
|
|
63
85
|
}>;
|
|
86
|
+
/** Get recent activity logs (last 48h). */
|
|
87
|
+
getRecentActivity(siteId: string, limit?: number, offset?: number): Promise<RecentActivityItem[]>;
|
|
88
|
+
/** Get recent agent queries. */
|
|
89
|
+
getRecentQueries(siteId: string, limit?: number, offset?: number): Promise<RecentQueryItem[]>;
|
|
64
90
|
/** Get crawler breakdown by type (default 30 days). */
|
|
65
91
|
getSiteCrawlers(days?: number): Promise<{
|
|
66
92
|
days: number;
|
|
@@ -76,7 +102,87 @@ declare class ApptvtyClient {
|
|
|
76
102
|
}>;
|
|
77
103
|
/** Get wallet balance and earnings. */
|
|
78
104
|
getSiteWallet(): Promise<SiteWalletInfo>;
|
|
105
|
+
/**
|
|
106
|
+
* Create an ad campaign. The campaign goes live immediately once the wallet
|
|
107
|
+
* has sufficient balance.
|
|
108
|
+
*
|
|
109
|
+
* If the wallet balance is too low, throws `ApptvtyInsufficientBalanceError`
|
|
110
|
+
* which includes deposit instructions so the agent can fund the wallet and retry.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // Site-based: ad copy derived from your site's crawled content
|
|
114
|
+
* const campaign = await client.createCampaign({
|
|
115
|
+
* name: 'My Kubernetes Blog',
|
|
116
|
+
* advertiser_site_id: 'site_abc123',
|
|
117
|
+
* keywords: ['kubernetes', 'devops', 'containers'],
|
|
118
|
+
* categories: ['technology'],
|
|
119
|
+
* bid_per_view_usdc: 0.001,
|
|
120
|
+
* daily_budget_usdc: 1.0,
|
|
121
|
+
* total_budget_usdc: 20.0,
|
|
122
|
+
* });
|
|
123
|
+
*
|
|
124
|
+
* // Static: manually written ad copy
|
|
125
|
+
* const campaign = await client.createCampaign({
|
|
126
|
+
* name: 'My Blog — Static',
|
|
127
|
+
* ad_text: 'Deep dives on Kubernetes, written by practitioners.',
|
|
128
|
+
* landing_url: 'https://myblog.com',
|
|
129
|
+
* keywords: ['kubernetes', 'devops'],
|
|
130
|
+
* categories: ['technology'],
|
|
131
|
+
* bid_per_view_usdc: 0.001,
|
|
132
|
+
* daily_budget_usdc: 1.0,
|
|
133
|
+
* total_budget_usdc: 10.0,
|
|
134
|
+
* });
|
|
135
|
+
*/
|
|
136
|
+
createCampaign(params: CreateCampaignParams): Promise<CampaignRecord>;
|
|
137
|
+
/**
|
|
138
|
+
* List all campaigns for this account.
|
|
139
|
+
* Also returns the schema (valid categories, minimum bid) so the agent
|
|
140
|
+
* knows valid field values without guessing.
|
|
141
|
+
*/
|
|
142
|
+
listCampaigns(): Promise<{
|
|
143
|
+
campaigns: CampaignRecord[];
|
|
144
|
+
total: number;
|
|
145
|
+
schema: {
|
|
146
|
+
valid_categories: string[];
|
|
147
|
+
valid_statuses: string[];
|
|
148
|
+
bid_per_view_usdc_minimum: number;
|
|
149
|
+
};
|
|
150
|
+
}>;
|
|
151
|
+
/**
|
|
152
|
+
* Get a single campaign by ID, including current spend and impression count.
|
|
153
|
+
* `budget_remaining_usdc` tells the agent how much budget is left before
|
|
154
|
+
* the campaign auto-pauses.
|
|
155
|
+
*/
|
|
156
|
+
getCampaign(campaignId: string): Promise<CampaignRecord>;
|
|
157
|
+
/**
|
|
158
|
+
* Partially update a campaign. Only fields present in `params` are changed.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* // Pause a campaign
|
|
162
|
+
* await client.updateCampaign(id, { status: 'paused' });
|
|
163
|
+
*
|
|
164
|
+
* // Increase bid and daily budget
|
|
165
|
+
* await client.updateCampaign(id, { bid_per_view_usdc: 0.002, daily_budget_usdc: 5.0 });
|
|
166
|
+
*/
|
|
167
|
+
updateCampaign(campaignId: string, params: UpdateCampaignParams): Promise<CampaignRecord>;
|
|
168
|
+
/**
|
|
169
|
+
* Pause a campaign immediately. Equivalent to updateCampaign(id, { status: 'paused' }).
|
|
170
|
+
* Campaigns are never deleted — billing history is retained.
|
|
171
|
+
*/
|
|
172
|
+
pauseCampaign(campaignId: string): Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Resume a paused campaign.
|
|
175
|
+
*/
|
|
176
|
+
resumeCampaign(campaignId: string): Promise<void>;
|
|
79
177
|
private get;
|
|
178
|
+
private patch;
|
|
179
|
+
private delete;
|
|
180
|
+
/**
|
|
181
|
+
* Settle an X402 challenge from the site's own USDC wallet balance.
|
|
182
|
+
* Called automatically when `post()` receives a 402 with an X402 header.
|
|
183
|
+
* Returns the preimage on success, or throws if the wallet balance is too low.
|
|
184
|
+
*/
|
|
185
|
+
private payX402Challenge;
|
|
80
186
|
private post;
|
|
81
187
|
private log;
|
|
82
188
|
private warn;
|
|
@@ -87,6 +193,30 @@ declare class ApptvtyApiError extends Error {
|
|
|
87
193
|
readonly body: string;
|
|
88
194
|
constructor(statusCode: number, path: string, body: string);
|
|
89
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Thrown by createCampaign() when the wallet balance is too low.
|
|
198
|
+
*
|
|
199
|
+
* The `details` property contains everything needed to fund the wallet
|
|
200
|
+
* autonomously and retry — the agent can inspect `details.deposit.address`
|
|
201
|
+
* and send USDC on Base without human intervention.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* import { ApptvtyInsufficientBalanceError } from 'apptvty';
|
|
205
|
+
*
|
|
206
|
+
* try {
|
|
207
|
+
* await client.createCampaign(params);
|
|
208
|
+
* } catch (err) {
|
|
209
|
+
* if (err instanceof ApptvtyInsufficientBalanceError) {
|
|
210
|
+
* const { shortfall_usdc, deposit } = err.details;
|
|
211
|
+
* // Agent can now: send shortfall_usdc USDC to deposit.address on deposit.chain
|
|
212
|
+
* // Then retry createCampaign
|
|
213
|
+
* }
|
|
214
|
+
* }
|
|
215
|
+
*/
|
|
216
|
+
declare class ApptvtyInsufficientBalanceError extends Error {
|
|
217
|
+
readonly details: InsufficientBalanceError | undefined;
|
|
218
|
+
constructor(details: InsufficientBalanceError | undefined);
|
|
219
|
+
}
|
|
90
220
|
|
|
91
221
|
/**
|
|
92
222
|
* Batched request logger.
|
|
@@ -122,18 +252,6 @@ declare class RequestLogger {
|
|
|
122
252
|
private log;
|
|
123
253
|
}
|
|
124
254
|
|
|
125
|
-
/**
|
|
126
|
-
* Lightweight AI crawler detection.
|
|
127
|
-
*
|
|
128
|
-
* This is the single source of truth for crawler classification in the SDK.
|
|
129
|
-
* The backend (Python analytics API and TypeScript handlers) should eventually
|
|
130
|
-
* consume this same list rather than maintaining separate copies.
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
declare function detectCrawler(userAgent: string): CrawlerInfo;
|
|
134
|
-
/** Returns the list of all known crawlers for reference (e.g. for agents.txt generation) */
|
|
135
|
-
declare function getKnownCrawlerNames(): string[];
|
|
136
|
-
|
|
137
255
|
/**
|
|
138
256
|
* Framework-agnostic query endpoint handler.
|
|
139
257
|
*
|
|
@@ -167,4 +285,4 @@ interface QueryHandlerResponse {
|
|
|
167
285
|
}
|
|
168
286
|
declare function createQueryHandler(client: ApptvtyClient, config: ApptvtyConfig): (req: QueryHandlerRequest) => Promise<QueryHandlerResponse>;
|
|
169
287
|
|
|
170
|
-
export { AgentErrorResponse, AgentQueryResponse, ApptvtyApiError, ApptvtyClient, ApptvtyConfig, CrawlerBreakdown, CrawlerInfo, DailyStat, ImpressionLog, PageAdsResponse, QueryEndpointDiscovery, RecentActivityItem, RecentQueryItem, RequestLogEntry, RequestLogger, SiteOverviewStats, SiteWalletInfo, createQueryHandler, detectCrawler, getKnownCrawlerNames };
|
|
288
|
+
export { AgentErrorResponse, AgentQueryResponse, ApptvtyApiError, ApptvtyClient, ApptvtyConfig, ApptvtyInsufficientBalanceError, CampaignRecord, CrawlerBreakdown, CrawlerInfo, CreateCampaignParams, DailyStat, ImpressionLog, InsufficientBalanceError, PageAdsResponse, QueryEndpointDiscovery, RecentActivityItem, RecentQueryItem, RequestLogEntry, RequestLogger, type ScraperServiceInfo, SiteOverviewStats, SiteWalletInfo, UpdateCampaignParams, createQueryHandler, detectCrawler, detectScraperService, getKnownCrawlerNames };
|