@gravity-ai/api 1.1.3 → 1.1.5

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/dist/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,13 +30,320 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // package.json
34
+ var require_package = __commonJS({
35
+ "package.json"(exports2, module2) {
36
+ module2.exports = {
37
+ name: "@gravity-ai/api",
38
+ version: "1.1.5",
39
+ description: "Gravity JS SDK for retrieving targeted advertisements",
40
+ main: "dist/index.js",
41
+ module: "dist/index.mjs",
42
+ types: "dist/index.d.ts",
43
+ files: [
44
+ "dist"
45
+ ],
46
+ exports: {
47
+ ".": {
48
+ types: "./dist/index.d.ts",
49
+ require: "./dist/index.js",
50
+ import: "./dist/index.mjs"
51
+ },
52
+ "./opentui": {
53
+ types: "./dist/opentui.d.ts",
54
+ require: "./dist/opentui.js",
55
+ import: "./dist/opentui.mjs"
56
+ }
57
+ },
58
+ scripts: {
59
+ build: "tsup index.ts opentui.ts --format cjs,esm --dts",
60
+ clean: "rm -rf dist",
61
+ dev: "tsup index.ts opentui.ts --format cjs,esm --watch --dts",
62
+ lint: "tsc --noEmit",
63
+ test: "vitest run",
64
+ prepublishOnly: "npm run clean && npm run build",
65
+ "version:patch": "npm version patch",
66
+ "version:minor": "npm version minor",
67
+ "version:major": "npm version major",
68
+ "publish:patch": "npm run version:patch && npm publish",
69
+ "publish:minor": "npm run version:minor && npm publish",
70
+ "publish:major": "npm run version:major && npm publish"
71
+ },
72
+ keywords: [
73
+ "gravity",
74
+ "advertising",
75
+ "api",
76
+ "client",
77
+ "ads",
78
+ "typescript",
79
+ "contextual-advertising",
80
+ "ai-ads"
81
+ ],
82
+ author: "Gravity Team",
83
+ license: "MIT",
84
+ homepage: "https://github.com/Try-Gravity/gravity-js#readme",
85
+ repository: {
86
+ type: "git",
87
+ url: "git+https://github.com/Try-Gravity/gravity-js.git",
88
+ directory: "packages/api"
89
+ },
90
+ bugs: {
91
+ url: "https://github.com/Try-Gravity/gravity-js/issues"
92
+ },
93
+ publishConfig: {
94
+ access: "public"
95
+ },
96
+ engines: {
97
+ node: ">=18.0.0"
98
+ },
99
+ peerDependencies: {
100
+ "@opentui/core": ">=0.1.0"
101
+ },
102
+ peerDependenciesMeta: {
103
+ "@opentui/core": {
104
+ optional: true
105
+ }
106
+ },
107
+ dependencies: {
108
+ axios: "^1.13.2"
109
+ },
110
+ devDependencies: {
111
+ "@opentui/core": "^0.1.80",
112
+ tsup: "^8.0.1",
113
+ typescript: "^5.3.3",
114
+ vitest: "^1.2.1"
115
+ }
116
+ };
117
+ }
118
+ });
119
+
30
120
  // index.ts
31
121
  var index_exports = {};
32
122
  __export(index_exports, {
33
- Client: () => Client
123
+ Client: () => Client,
124
+ Gravity: () => Gravity,
125
+ extractClientIp: () => extractClientIp,
126
+ gravityAds: () => gravityAds,
127
+ gravityContext: () => gravityContext,
128
+ toGravityMessages: () => toGravityMessages
34
129
  });
35
130
  module.exports = __toCommonJS(index_exports);
36
131
 
132
+ // ads.ts
133
+ var DEFAULT_GRAVITY_API = "https://server.trygravity.ai/api/v1/ad";
134
+ var DEFAULT_TIMEOUT_MS = 3e3;
135
+ function toGravityMessages(messages, maxTurns = 2) {
136
+ if (!messages || messages.length === 0) return [];
137
+ return messages.slice(-maxTurns).map((m) => ({
138
+ role: m.role,
139
+ content: m.content
140
+ }));
141
+ }
142
+ function extractClientIp(req) {
143
+ if (!req) return void 0;
144
+ const headers = req.headers || {};
145
+ const forwarded = headers["x-forwarded-for"] || headers["x-real-ip"];
146
+ if (forwarded) {
147
+ const first = (typeof forwarded === "string" ? forwarded : forwarded[0])?.split(",")[0]?.trim();
148
+ if (first) return first;
149
+ }
150
+ if (req.socket?.remoteAddress) return req.socket.remoteAddress;
151
+ if (req.connection?.remoteAddress) return req.connection.remoteAddress;
152
+ if (req.ip) return req.ip;
153
+ return void 0;
154
+ }
155
+ async function gravityAds(req, messages, placements, opts = {}) {
156
+ const apiKey = opts.apiKey || (typeof process !== "undefined" ? process.env?.GRAVITY_API_KEY : void 0);
157
+ const gravityApi = opts.gravityApi || DEFAULT_GRAVITY_API;
158
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
159
+ if (!apiKey) {
160
+ return { ads: [], status: 0, elapsed: "0", requestBody: null };
161
+ }
162
+ const ctx = req?.body?.gravity_context;
163
+ const clientUser = ctx?.user || {};
164
+ const clientDevice = ctx?.device || {};
165
+ const clientIp = extractClientIp(req);
166
+ const body = {
167
+ messages: toGravityMessages(messages),
168
+ sessionId: ctx?.sessionId,
169
+ placements,
170
+ user: {
171
+ ...clientUser,
172
+ id: clientUser.id || clientUser.userId || "anonymous"
173
+ },
174
+ device: {
175
+ ...clientDevice,
176
+ ...clientIp ? { ip: clientIp } : {}
177
+ }
178
+ };
179
+ body.relevancy = opts.relevancy ?? 0.2;
180
+ body.testAd = opts.production === true ? false : true;
181
+ if (opts.excludedTopics) body.excludedTopics = opts.excludedTopics;
182
+ const start = performance.now();
183
+ try {
184
+ const res = await fetch(gravityApi, {
185
+ method: "POST",
186
+ headers: {
187
+ "Content-Type": "application/json",
188
+ Authorization: `Bearer ${apiKey}`
189
+ },
190
+ body: JSON.stringify(body),
191
+ signal: AbortSignal.timeout(timeoutMs)
192
+ });
193
+ const elapsed = (performance.now() - start).toFixed(0);
194
+ if (res.status === 204) {
195
+ return { ads: [], status: 204, elapsed, requestBody: body };
196
+ }
197
+ if (!res.ok) {
198
+ const errText = await res.text().catch(() => "");
199
+ return {
200
+ ads: [],
201
+ status: res.status,
202
+ elapsed,
203
+ error: errText,
204
+ requestBody: body
205
+ };
206
+ }
207
+ const data = await res.json();
208
+ const ads = Array.isArray(data) ? data : [data];
209
+ return { ads, status: res.status, elapsed, requestBody: body };
210
+ } catch (err) {
211
+ const elapsed = (performance.now() - start).toFixed(0);
212
+ const error = err instanceof Error ? err.name === "TimeoutError" ? `Timeout (${timeoutMs}ms)` : err.message : String(err);
213
+ return { ads: [], status: 0, elapsed, error, requestBody: body };
214
+ }
215
+ }
216
+
217
+ // gravity.ts
218
+ var Gravity = class {
219
+ /**
220
+ * @param opts - Configuration applied to every `getAds()` call.
221
+ *
222
+ * | Option | Type | Default | Description |
223
+ * |--------|------|---------|-------------|
224
+ * | `apiKey` | `string` | `process.env.GRAVITY_API_KEY` | Gravity API key |
225
+ * | `production` | `boolean` | `false` | `true` = real ads. `false` = test ads (no billing). |
226
+ * | `relevancy` | `number` | `0.2` | Minimum relevancy threshold (0-1) |
227
+ * | `timeoutMs` | `number` | `3000` | Request timeout in ms |
228
+ * | `excludedTopics` | `string[]` | — | Topics to exclude from ad matching |
229
+ * | `gravityApi` | `string` | production URL | Custom API endpoint |
230
+ */
231
+ constructor(opts = {}) {
232
+ this.opts = opts;
233
+ }
234
+ /**
235
+ * Fetch ads from the Gravity API. **Never throws.**
236
+ *
237
+ * Reads `gravity_context` from `req.body` (sent by the client via
238
+ * `gravityContext()`), extracts the end-user's IP from request headers,
239
+ * and calls the Gravity ad endpoint.
240
+ *
241
+ * @param req - Server request object (Express, Fastify, Next.js, etc.)
242
+ * @param messages - Conversation `[{ role, content }]` — last 2 turns sent
243
+ * @param placements - Ad slots, e.g. `[{ placement: "below_response", placement_id: "main" }]`
244
+ * @param overrides - Per-call overrides that merge on top of constructor config
245
+ * @returns `{ ads, status, elapsed, requestBody, error? }` — always resolves
246
+ */
247
+ async getAds(req, messages, placements, overrides = {}) {
248
+ return gravityAds(req, messages, placements, {
249
+ ...this.opts,
250
+ ...overrides
251
+ });
252
+ }
253
+ };
254
+
255
+ // context.ts
256
+ function gravityContext(overrides) {
257
+ if (!overrides?.sessionId) {
258
+ throw new Error("gravityContext() requires sessionId");
259
+ }
260
+ if (!overrides?.user?.userId) {
261
+ throw new Error("gravityContext() requires user.userId");
262
+ }
263
+ const isBrowser = typeof window !== "undefined" && typeof navigator !== "undefined";
264
+ const device = isBrowser ? browserDevice() : nodeDevice();
265
+ if (overrides.device) {
266
+ Object.assign(device, overrides.device);
267
+ }
268
+ const { userId, ...restUser } = overrides.user;
269
+ return {
270
+ sessionId: overrides.sessionId,
271
+ user: { ...restUser, id: userId },
272
+ device
273
+ };
274
+ }
275
+ function browserDevice() {
276
+ const nav = typeof navigator !== "undefined" ? navigator : void 0;
277
+ const win = typeof window !== "undefined" ? window : void 0;
278
+ return {
279
+ ua: nav?.userAgent || "",
280
+ browser: "web",
281
+ device_type: /Mobi|Android/i.test(nav?.userAgent || "") ? "mobile" : "desktop",
282
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
283
+ locale: Intl.DateTimeFormat().resolvedOptions().locale,
284
+ language: nav?.language || "en",
285
+ screen_width: win?.screen?.width,
286
+ screen_height: win?.screen?.height,
287
+ viewport_width: win?.innerWidth,
288
+ viewport_height: win?.innerHeight,
289
+ platform: nav?.platform || "web"
290
+ };
291
+ }
292
+ function nodeDevice() {
293
+ let os;
294
+ try {
295
+ os = require("os");
296
+ } catch {
297
+ }
298
+ const runtimeTag = (() => {
299
+ if (typeof globalThis !== "undefined") {
300
+ const g = globalThis;
301
+ if (g.Bun && typeof g.Bun === "object" && "version" in g.Bun) {
302
+ return `Bun/${g.Bun.version}`;
303
+ }
304
+ if (g.Deno && typeof g.Deno === "object") {
305
+ const deno = g.Deno;
306
+ const ver = deno.version;
307
+ return `Deno/${ver?.deno || "unknown"}`;
308
+ }
309
+ }
310
+ if (typeof process !== "undefined" && process.versions?.node) {
311
+ return `Node/${process.versions.node}`;
312
+ }
313
+ return "unknown";
314
+ })();
315
+ const cols = typeof process !== "undefined" ? process.stdout?.columns || 80 : 80;
316
+ const rows = typeof process !== "undefined" ? process.stdout?.rows || 24 : 24;
317
+ const env = typeof process !== "undefined" ? process.env : {};
318
+ return {
319
+ ua: `gravity-js/${PKG_VERSION} (${os?.type() || "unknown"} ${os?.arch() || "unknown"}; ${runtimeTag})`,
320
+ os: os ? `${os.type()} ${os.release()}` : void 0,
321
+ browser: "cli",
322
+ device_type: env.CI ? "server" : "desktop",
323
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
324
+ locale: Intl.DateTimeFormat().resolvedOptions().locale,
325
+ language: env.LANG?.split(".")[0]?.replace("_", "-") || "en",
326
+ platform: typeof process !== "undefined" ? process.platform : void 0,
327
+ arch: os?.arch(),
328
+ screen_width: cols,
329
+ screen_height: rows,
330
+ viewport_width: cols,
331
+ viewport_height: rows,
332
+ runtime: runtimeTag,
333
+ term_program: env.TERM_PROGRAM || void 0,
334
+ term: env.TERM || void 0,
335
+ colorterm: env.COLORTERM || void 0,
336
+ is_ci: !!env.CI
337
+ };
338
+ }
339
+ var PKG_VERSION = (() => {
340
+ try {
341
+ return require_package().version;
342
+ } catch {
343
+ return "0.0.0";
344
+ }
345
+ })();
346
+
37
347
  // client.ts
38
348
  var import_axios = __toESM(require("axios"));
39
349
  var DEFAULT_ENDPOINT = "https://server.trygravity.ai";
@@ -138,7 +448,7 @@ var Client = class {
138
448
  excludedTopics: params.excludedTopics ?? this.excludedTopics,
139
449
  relevancy: params.relevancy ?? this.relevancy
140
450
  };
141
- const response = await this.axios.post("/api/v1/ad/contextual", body);
451
+ const response = await this.axios.post("/api/v1/ad", body);
142
452
  if (response.status === 204) {
143
453
  return null;
144
454
  }
@@ -186,5 +496,10 @@ var Client = class {
186
496
  };
187
497
  // Annotate the CommonJS export names for ESM import in node:
188
498
  0 && (module.exports = {
189
- Client
499
+ Client,
500
+ Gravity,
501
+ extractClientIp,
502
+ gravityAds,
503
+ gravityContext,
504
+ toGravityMessages
190
505
  });
package/dist/index.mjs CHANGED
@@ -1,3 +1,310 @@
1
+ import {
2
+ __commonJS,
3
+ __require
4
+ } from "./chunk-EBO3CZXG.mjs";
5
+
6
+ // package.json
7
+ var require_package = __commonJS({
8
+ "package.json"(exports, module) {
9
+ module.exports = {
10
+ name: "@gravity-ai/api",
11
+ version: "1.1.5",
12
+ description: "Gravity JS SDK for retrieving targeted advertisements",
13
+ main: "dist/index.js",
14
+ module: "dist/index.mjs",
15
+ types: "dist/index.d.ts",
16
+ files: [
17
+ "dist"
18
+ ],
19
+ exports: {
20
+ ".": {
21
+ types: "./dist/index.d.ts",
22
+ require: "./dist/index.js",
23
+ import: "./dist/index.mjs"
24
+ },
25
+ "./opentui": {
26
+ types: "./dist/opentui.d.ts",
27
+ require: "./dist/opentui.js",
28
+ import: "./dist/opentui.mjs"
29
+ }
30
+ },
31
+ scripts: {
32
+ build: "tsup index.ts opentui.ts --format cjs,esm --dts",
33
+ clean: "rm -rf dist",
34
+ dev: "tsup index.ts opentui.ts --format cjs,esm --watch --dts",
35
+ lint: "tsc --noEmit",
36
+ test: "vitest run",
37
+ prepublishOnly: "npm run clean && npm run build",
38
+ "version:patch": "npm version patch",
39
+ "version:minor": "npm version minor",
40
+ "version:major": "npm version major",
41
+ "publish:patch": "npm run version:patch && npm publish",
42
+ "publish:minor": "npm run version:minor && npm publish",
43
+ "publish:major": "npm run version:major && npm publish"
44
+ },
45
+ keywords: [
46
+ "gravity",
47
+ "advertising",
48
+ "api",
49
+ "client",
50
+ "ads",
51
+ "typescript",
52
+ "contextual-advertising",
53
+ "ai-ads"
54
+ ],
55
+ author: "Gravity Team",
56
+ license: "MIT",
57
+ homepage: "https://github.com/Try-Gravity/gravity-js#readme",
58
+ repository: {
59
+ type: "git",
60
+ url: "git+https://github.com/Try-Gravity/gravity-js.git",
61
+ directory: "packages/api"
62
+ },
63
+ bugs: {
64
+ url: "https://github.com/Try-Gravity/gravity-js/issues"
65
+ },
66
+ publishConfig: {
67
+ access: "public"
68
+ },
69
+ engines: {
70
+ node: ">=18.0.0"
71
+ },
72
+ peerDependencies: {
73
+ "@opentui/core": ">=0.1.0"
74
+ },
75
+ peerDependenciesMeta: {
76
+ "@opentui/core": {
77
+ optional: true
78
+ }
79
+ },
80
+ dependencies: {
81
+ axios: "^1.13.2"
82
+ },
83
+ devDependencies: {
84
+ "@opentui/core": "^0.1.80",
85
+ tsup: "^8.0.1",
86
+ typescript: "^5.3.3",
87
+ vitest: "^1.2.1"
88
+ }
89
+ };
90
+ }
91
+ });
92
+
93
+ // ads.ts
94
+ var DEFAULT_GRAVITY_API = "https://server.trygravity.ai/api/v1/ad";
95
+ var DEFAULT_TIMEOUT_MS = 3e3;
96
+ function toGravityMessages(messages, maxTurns = 2) {
97
+ if (!messages || messages.length === 0) return [];
98
+ return messages.slice(-maxTurns).map((m) => ({
99
+ role: m.role,
100
+ content: m.content
101
+ }));
102
+ }
103
+ function extractClientIp(req) {
104
+ if (!req) return void 0;
105
+ const headers = req.headers || {};
106
+ const forwarded = headers["x-forwarded-for"] || headers["x-real-ip"];
107
+ if (forwarded) {
108
+ const first = (typeof forwarded === "string" ? forwarded : forwarded[0])?.split(",")[0]?.trim();
109
+ if (first) return first;
110
+ }
111
+ if (req.socket?.remoteAddress) return req.socket.remoteAddress;
112
+ if (req.connection?.remoteAddress) return req.connection.remoteAddress;
113
+ if (req.ip) return req.ip;
114
+ return void 0;
115
+ }
116
+ async function gravityAds(req, messages, placements, opts = {}) {
117
+ const apiKey = opts.apiKey || (typeof process !== "undefined" ? process.env?.GRAVITY_API_KEY : void 0);
118
+ const gravityApi = opts.gravityApi || DEFAULT_GRAVITY_API;
119
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
120
+ if (!apiKey) {
121
+ return { ads: [], status: 0, elapsed: "0", requestBody: null };
122
+ }
123
+ const ctx = req?.body?.gravity_context;
124
+ const clientUser = ctx?.user || {};
125
+ const clientDevice = ctx?.device || {};
126
+ const clientIp = extractClientIp(req);
127
+ const body = {
128
+ messages: toGravityMessages(messages),
129
+ sessionId: ctx?.sessionId,
130
+ placements,
131
+ user: {
132
+ ...clientUser,
133
+ id: clientUser.id || clientUser.userId || "anonymous"
134
+ },
135
+ device: {
136
+ ...clientDevice,
137
+ ...clientIp ? { ip: clientIp } : {}
138
+ }
139
+ };
140
+ body.relevancy = opts.relevancy ?? 0.2;
141
+ body.testAd = opts.production === true ? false : true;
142
+ if (opts.excludedTopics) body.excludedTopics = opts.excludedTopics;
143
+ const start = performance.now();
144
+ try {
145
+ const res = await fetch(gravityApi, {
146
+ method: "POST",
147
+ headers: {
148
+ "Content-Type": "application/json",
149
+ Authorization: `Bearer ${apiKey}`
150
+ },
151
+ body: JSON.stringify(body),
152
+ signal: AbortSignal.timeout(timeoutMs)
153
+ });
154
+ const elapsed = (performance.now() - start).toFixed(0);
155
+ if (res.status === 204) {
156
+ return { ads: [], status: 204, elapsed, requestBody: body };
157
+ }
158
+ if (!res.ok) {
159
+ const errText = await res.text().catch(() => "");
160
+ return {
161
+ ads: [],
162
+ status: res.status,
163
+ elapsed,
164
+ error: errText,
165
+ requestBody: body
166
+ };
167
+ }
168
+ const data = await res.json();
169
+ const ads = Array.isArray(data) ? data : [data];
170
+ return { ads, status: res.status, elapsed, requestBody: body };
171
+ } catch (err) {
172
+ const elapsed = (performance.now() - start).toFixed(0);
173
+ const error = err instanceof Error ? err.name === "TimeoutError" ? `Timeout (${timeoutMs}ms)` : err.message : String(err);
174
+ return { ads: [], status: 0, elapsed, error, requestBody: body };
175
+ }
176
+ }
177
+
178
+ // gravity.ts
179
+ var Gravity = class {
180
+ /**
181
+ * @param opts - Configuration applied to every `getAds()` call.
182
+ *
183
+ * | Option | Type | Default | Description |
184
+ * |--------|------|---------|-------------|
185
+ * | `apiKey` | `string` | `process.env.GRAVITY_API_KEY` | Gravity API key |
186
+ * | `production` | `boolean` | `false` | `true` = real ads. `false` = test ads (no billing). |
187
+ * | `relevancy` | `number` | `0.2` | Minimum relevancy threshold (0-1) |
188
+ * | `timeoutMs` | `number` | `3000` | Request timeout in ms |
189
+ * | `excludedTopics` | `string[]` | — | Topics to exclude from ad matching |
190
+ * | `gravityApi` | `string` | production URL | Custom API endpoint |
191
+ */
192
+ constructor(opts = {}) {
193
+ this.opts = opts;
194
+ }
195
+ /**
196
+ * Fetch ads from the Gravity API. **Never throws.**
197
+ *
198
+ * Reads `gravity_context` from `req.body` (sent by the client via
199
+ * `gravityContext()`), extracts the end-user's IP from request headers,
200
+ * and calls the Gravity ad endpoint.
201
+ *
202
+ * @param req - Server request object (Express, Fastify, Next.js, etc.)
203
+ * @param messages - Conversation `[{ role, content }]` — last 2 turns sent
204
+ * @param placements - Ad slots, e.g. `[{ placement: "below_response", placement_id: "main" }]`
205
+ * @param overrides - Per-call overrides that merge on top of constructor config
206
+ * @returns `{ ads, status, elapsed, requestBody, error? }` — always resolves
207
+ */
208
+ async getAds(req, messages, placements, overrides = {}) {
209
+ return gravityAds(req, messages, placements, {
210
+ ...this.opts,
211
+ ...overrides
212
+ });
213
+ }
214
+ };
215
+
216
+ // context.ts
217
+ function gravityContext(overrides) {
218
+ if (!overrides?.sessionId) {
219
+ throw new Error("gravityContext() requires sessionId");
220
+ }
221
+ if (!overrides?.user?.userId) {
222
+ throw new Error("gravityContext() requires user.userId");
223
+ }
224
+ const isBrowser = typeof window !== "undefined" && typeof navigator !== "undefined";
225
+ const device = isBrowser ? browserDevice() : nodeDevice();
226
+ if (overrides.device) {
227
+ Object.assign(device, overrides.device);
228
+ }
229
+ const { userId, ...restUser } = overrides.user;
230
+ return {
231
+ sessionId: overrides.sessionId,
232
+ user: { ...restUser, id: userId },
233
+ device
234
+ };
235
+ }
236
+ function browserDevice() {
237
+ const nav = typeof navigator !== "undefined" ? navigator : void 0;
238
+ const win = typeof window !== "undefined" ? window : void 0;
239
+ return {
240
+ ua: nav?.userAgent || "",
241
+ browser: "web",
242
+ device_type: /Mobi|Android/i.test(nav?.userAgent || "") ? "mobile" : "desktop",
243
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
244
+ locale: Intl.DateTimeFormat().resolvedOptions().locale,
245
+ language: nav?.language || "en",
246
+ screen_width: win?.screen?.width,
247
+ screen_height: win?.screen?.height,
248
+ viewport_width: win?.innerWidth,
249
+ viewport_height: win?.innerHeight,
250
+ platform: nav?.platform || "web"
251
+ };
252
+ }
253
+ function nodeDevice() {
254
+ let os;
255
+ try {
256
+ os = __require("os");
257
+ } catch {
258
+ }
259
+ const runtimeTag = (() => {
260
+ if (typeof globalThis !== "undefined") {
261
+ const g = globalThis;
262
+ if (g.Bun && typeof g.Bun === "object" && "version" in g.Bun) {
263
+ return `Bun/${g.Bun.version}`;
264
+ }
265
+ if (g.Deno && typeof g.Deno === "object") {
266
+ const deno = g.Deno;
267
+ const ver = deno.version;
268
+ return `Deno/${ver?.deno || "unknown"}`;
269
+ }
270
+ }
271
+ if (typeof process !== "undefined" && process.versions?.node) {
272
+ return `Node/${process.versions.node}`;
273
+ }
274
+ return "unknown";
275
+ })();
276
+ const cols = typeof process !== "undefined" ? process.stdout?.columns || 80 : 80;
277
+ const rows = typeof process !== "undefined" ? process.stdout?.rows || 24 : 24;
278
+ const env = typeof process !== "undefined" ? process.env : {};
279
+ return {
280
+ ua: `gravity-js/${PKG_VERSION} (${os?.type() || "unknown"} ${os?.arch() || "unknown"}; ${runtimeTag})`,
281
+ os: os ? `${os.type()} ${os.release()}` : void 0,
282
+ browser: "cli",
283
+ device_type: env.CI ? "server" : "desktop",
284
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
285
+ locale: Intl.DateTimeFormat().resolvedOptions().locale,
286
+ language: env.LANG?.split(".")[0]?.replace("_", "-") || "en",
287
+ platform: typeof process !== "undefined" ? process.platform : void 0,
288
+ arch: os?.arch(),
289
+ screen_width: cols,
290
+ screen_height: rows,
291
+ viewport_width: cols,
292
+ viewport_height: rows,
293
+ runtime: runtimeTag,
294
+ term_program: env.TERM_PROGRAM || void 0,
295
+ term: env.TERM || void 0,
296
+ colorterm: env.COLORTERM || void 0,
297
+ is_ci: !!env.CI
298
+ };
299
+ }
300
+ var PKG_VERSION = (() => {
301
+ try {
302
+ return require_package().version;
303
+ } catch {
304
+ return "0.0.0";
305
+ }
306
+ })();
307
+
1
308
  // client.ts
2
309
  import axios from "axios";
3
310
  var DEFAULT_ENDPOINT = "https://server.trygravity.ai";
@@ -102,7 +409,7 @@ var Client = class {
102
409
  excludedTopics: params.excludedTopics ?? this.excludedTopics,
103
410
  relevancy: params.relevancy ?? this.relevancy
104
411
  };
105
- const response = await this.axios.post("/api/v1/ad/contextual", body);
412
+ const response = await this.axios.post("/api/v1/ad", body);
106
413
  if (response.status === 204) {
107
414
  return null;
108
415
  }
@@ -149,5 +456,10 @@ var Client = class {
149
456
  }
150
457
  };
151
458
  export {
152
- Client
459
+ Client,
460
+ Gravity,
461
+ extractClientIp,
462
+ gravityAds,
463
+ gravityContext,
464
+ toGravityMessages
153
465
  };