@posthog/ai 8.13.5 → 8.13.7

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.
@@ -3,7 +3,7 @@ let _google_adk = require("@google/adk");
3
3
  let uuid = require("uuid");
4
4
  let _posthog_core = require("@posthog/core");
5
5
  //#region package.json
6
- var version = "8.13.5";
6
+ var version = "8.13.7";
7
7
  //#endregion
8
8
  //#region src/captureAiEvent.ts
9
9
  /** @internal */
@@ -2,7 +2,7 @@ import { BasePlugin } from "@google/adk";
2
2
  import { v4 } from "uuid";
3
3
  import { toJsonSafeValue, uuidv7 } from "@posthog/core";
4
4
  //#region package.json
5
- var version = "8.13.5";
5
+ var version = "8.13.7";
6
6
  //#endregion
7
7
  //#region src/captureAiEvent.ts
8
8
  /** @internal */
@@ -367,7 +367,7 @@ function addDefaults(params) {
367
367
  }
368
368
  //#endregion
369
369
  //#region package.json
370
- var version = "8.13.5";
370
+ var version = "8.13.7";
371
371
  //#endregion
372
372
  //#region src/serializeError.ts
373
373
  const DEFAULT_MAX_DEPTH = 3;
@@ -340,7 +340,7 @@ function addDefaults(params) {
340
340
  }
341
341
  //#endregion
342
342
  //#region package.json
343
- var version = "8.13.5";
343
+ var version = "8.13.7";
344
344
  //#endregion
345
345
  //#region src/serializeError.ts
346
346
  const DEFAULT_MAX_DEPTH = 3;
@@ -3,7 +3,7 @@ let _anthropic_ai_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
3
3
  let uuid = require("uuid");
4
4
  let _posthog_core = require("@posthog/core");
5
5
  //#region package.json
6
- var version = "8.13.5";
6
+ var version = "8.13.7";
7
7
  //#endregion
8
8
  //#region src/captureAiEvent.ts
9
9
  /** @internal */
@@ -2,7 +2,7 @@ import { SYSTEM_PROMPT_DYNAMIC_BOUNDARY, query as query$1 } from "@anthropic-ai/
2
2
  import { v4 } from "uuid";
3
3
  import { toJsonSafeValue, uuidv7 } from "@posthog/core";
4
4
  //#region package.json
5
- var version = "8.13.5";
5
+ var version = "8.13.7";
6
6
  //#endregion
7
7
  //#region src/captureAiEvent.ts
8
8
  /** @internal */
@@ -439,7 +439,7 @@ function addDefaults(params) {
439
439
  }
440
440
  //#endregion
441
441
  //#region package.json
442
- var version = "8.13.5";
442
+ var version = "8.13.7";
443
443
  //#endregion
444
444
  //#region src/serializeError.ts
445
445
  const DEFAULT_MAX_DEPTH = 3;
@@ -435,7 +435,7 @@ function addDefaults(params) {
435
435
  }
436
436
  //#endregion
437
437
  //#region package.json
438
- var version = "8.13.5";
438
+ var version = "8.13.7";
439
439
  //#endregion
440
440
  //#region src/serializeError.ts
441
441
  const DEFAULT_MAX_DEPTH = 3;
package/dist/index.cjs CHANGED
@@ -396,7 +396,7 @@ function sanitizeValues(obj) {
396
396
  }
397
397
  //#endregion
398
398
  //#region package.json
399
- var version = "8.13.5";
399
+ var version = "8.13.7";
400
400
  //#endregion
401
401
  //#region src/serializeError.ts
402
402
  const DEFAULT_MAX_DEPTH = 3;
@@ -1091,6 +1091,7 @@ const DEFAULT_PROMPTS_HOST = "https://us.posthog.com";
1091
1091
  const MAX_PROMPT_LIST_PAGES = 100;
1092
1092
  const DEFAULT_REFETCH_COOLDOWN_SECONDS = 60;
1093
1093
  const MAX_REFETCH_COOLDOWN_SECONDS = 3600;
1094
+ const FETCH_TIMEOUT_MS = 1e4;
1094
1095
  function normalizeApiKey(value) {
1095
1096
  return typeof value === "string" ? value.trim() : "";
1096
1097
  }
@@ -1126,6 +1127,30 @@ function isPromptApiResponse(data) {
1126
1127
  const record = data;
1127
1128
  return typeof record.prompt === "string" && typeof record.name === "string" && typeof record.version === "number" && (record.label === void 0 || typeof record.label === "string");
1128
1129
  }
1130
+ /**
1131
+ * GET with the client's timeout. The timer is cleared only after the body is
1132
+ * read, so a response whose headers arrive but whose body stalls still times out.
1133
+ */
1134
+ async function fetchJsonWithTimeout(url, personalApiKey, timeoutReference) {
1135
+ const controller = new AbortController();
1136
+ const timer = setTimeout(() => controller.abort(new PromptFetchError(`[PostHog Prompts] Timed out fetching ${timeoutReference} after ${FETCH_TIMEOUT_MS}ms`)), FETCH_TIMEOUT_MS);
1137
+ try {
1138
+ const response = await fetch(url, {
1139
+ method: "GET",
1140
+ headers: { Authorization: `Bearer ${personalApiKey}` },
1141
+ signal: controller.signal
1142
+ });
1143
+ return {
1144
+ response,
1145
+ data: response.ok ? await response.json() : void 0
1146
+ };
1147
+ } catch (error) {
1148
+ if (controller.signal.aborted) throw controller.signal.reason;
1149
+ throw error;
1150
+ } finally {
1151
+ clearTimeout(timer);
1152
+ }
1153
+ }
1129
1154
  function isSameOrigin(url, host) {
1130
1155
  try {
1131
1156
  return new URL(url).origin === new URL(host).origin;
@@ -1205,6 +1230,7 @@ function isPromptsWithPostHog(options) {
1205
1230
  var Prompts = class {
1206
1231
  constructor(options) {
1207
1232
  this.cache = /* @__PURE__ */ new Map();
1233
+ this.inFlight = /* @__PURE__ */ new Map();
1208
1234
  this.defaultCacheTtlSeconds = options.defaultCacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS;
1209
1235
  if (isPromptsWithPostHog(options)) {
1210
1236
  this.personalApiKey = options.posthog.options.personalApiKey ?? "";
@@ -1349,7 +1375,7 @@ var Prompts = class {
1349
1375
  };
1350
1376
  }
1351
1377
  try {
1352
- const fetched = await this.fetchPromptFromApi(name, version, label);
1378
+ const fetched = await this.fetchPromptOnce(name, version, label);
1353
1379
  if (label !== void 0 && fetched.label !== label) console.warn(`[PostHog Prompts] Requested label "${label}" for prompt "${name}" but the server resolved ${fetched.label === void 0 ? "no label" : `"${fetched.label}"`}. It may not support prompt labels yet and returned the latest version instead.`);
1354
1380
  this.getOrCreatePromptCache(name).set(cacheEntryKey, {
1355
1381
  ...fetched,
@@ -1373,6 +1399,20 @@ var Prompts = class {
1373
1399
  throw error;
1374
1400
  }
1375
1401
  }
1402
+ fetchPromptOnce(name, version, label) {
1403
+ const inFlightKey = JSON.stringify([
1404
+ name,
1405
+ version ?? null,
1406
+ label ?? null
1407
+ ]);
1408
+ const pending = this.inFlight.get(inFlightKey);
1409
+ if (pending !== void 0) return pending;
1410
+ const request = this.fetchPromptFromApi(name, version, label).finally(() => {
1411
+ this.inFlight.delete(inFlightKey);
1412
+ });
1413
+ this.inFlight.set(inFlightKey, request);
1414
+ return request;
1415
+ }
1376
1416
  readCacheEntry(cached) {
1377
1417
  const { fetchedAt: _fetchedAt, retryNotBefore: _retryNotBefore, ...cachedResult } = cached;
1378
1418
  return {
@@ -1439,15 +1479,11 @@ var Prompts = class {
1439
1479
  let pages = 0;
1440
1480
  while (url !== void 0) {
1441
1481
  if (pages >= MAX_PROMPT_LIST_PAGES) throw new Error(`[PostHog Prompts] ${reference} spans more than ${MAX_PROMPT_LIST_PAGES} pages. Refusing to return an incomplete result.`);
1442
- const response = await fetch(url, {
1443
- method: "GET",
1444
- headers: { Authorization: `Bearer ${this.personalApiKey}` }
1445
- });
1482
+ const { response, data } = await fetchJsonWithTimeout(url, this.personalApiKey, reference);
1446
1483
  if (!response.ok) {
1447
1484
  if (response.status === 403) throw new Error(`[PostHog Prompts] Access denied for ${reference}. Check that your personalApiKey has the correct permissions and the LLM prompts feature is enabled.`);
1448
1485
  throw new PromptFetchError(`[PostHog Prompts] Failed to fetch ${reference}: HTTP ${response.status}`, response.status === 429 ? parseRetryAfterSeconds(response.headers?.get("Retry-After")) : void 0);
1449
1486
  }
1450
- const data = await response.json();
1451
1487
  if (typeof data !== "object" || data === null || !Array.isArray(data.results)) throw new Error(`[PostHog Prompts] Invalid response format for ${reference}`);
1452
1488
  rows.push(...data.results);
1453
1489
  const nextUrl = data.next;
@@ -1464,17 +1500,12 @@ var Prompts = class {
1464
1500
  const versionQuery = version === void 0 ? "" : `&version=${encodeURIComponent(String(version))}`;
1465
1501
  const labelQuery = label === void 0 ? "" : `&label=${encodeURIComponent(label)}`;
1466
1502
  const promptReference = this.getPromptReference(name, version, label);
1467
- const url = `${this.host}/api/environments/@current/llm_prompts/name/${encodedPromptName}/?token=${encodedProjectApiKey}${versionQuery}${labelQuery}`;
1468
- const response = await fetch(url, {
1469
- method: "GET",
1470
- headers: { Authorization: `Bearer ${this.personalApiKey}` }
1471
- });
1503
+ const { response, data } = await fetchJsonWithTimeout(`${this.host}/api/environments/@current/llm_prompts/name/${encodedPromptName}/?token=${encodedProjectApiKey}${versionQuery}${labelQuery}`, this.personalApiKey, `prompt ${promptReference}`);
1472
1504
  if (!response.ok) {
1473
1505
  if (response.status === 404) throw new Error(`[PostHog Prompts] Prompt ${promptReference} not found`);
1474
1506
  if (response.status === 403) throw new Error(`[PostHog Prompts] Access denied for prompt ${promptReference}. Check that your personalApiKey has the correct permissions and the LLM prompts feature is enabled.`);
1475
1507
  throw new PromptFetchError(`[PostHog Prompts] Failed to fetch prompt ${promptReference}: HTTP ${response.status}`, response.status === 429 ? parseRetryAfterSeconds(response.headers?.get("Retry-After")) : void 0);
1476
1508
  }
1477
- const data = await response.json();
1478
1509
  if (!isPromptApiResponse(data)) throw new Error(`[PostHog Prompts] Invalid response format for prompt ${promptReference}`);
1479
1510
  return {
1480
1511
  prompt: data.prompt,
@@ -1487,6 +1518,7 @@ var Prompts = class {
1487
1518
  };
1488
1519
  //#endregion
1489
1520
  exports.AIEvent = AIEvent;
1521
+ exports.PromptFetchError = PromptFetchError;
1490
1522
  exports.Prompts = Prompts;
1491
1523
  exports.captureAiGeneration = captureAiGeneration;
1492
1524
  exports.withTracing = wrapVercelLanguageModel;