apptvty 0.2.4 → 0.3.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 +1 -1
- package/dist/{chunk-QERJ6LJA.mjs → chunk-4WO7W6JR.mjs} +33 -8
- package/dist/chunk-4WO7W6JR.mjs.map +1 -0
- package/dist/{chunk-WBHRLAUR.mjs → chunk-A6GFTPJ5.mjs} +84 -40
- package/dist/chunk-A6GFTPJ5.mjs.map +1 -0
- package/dist/{chunk-JILPRROG.mjs → chunk-EFCEIG74.mjs} +6 -6
- package/dist/{chunk-JILPRROG.mjs.map → chunk-EFCEIG74.mjs.map} +1 -1
- package/dist/cli.js +27 -6
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +77 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/middleware/express.d.mts +1 -1
- package/dist/middleware/express.d.ts +1 -1
- package/dist/middleware/express.js +87 -43
- package/dist/middleware/express.js.map +1 -1
- package/dist/middleware/express.mjs +2 -2
- package/dist/middleware/nextjs.d.mts +3 -3
- package/dist/middleware/nextjs.d.ts +3 -3
- package/dist/middleware/nextjs.js +114 -45
- package/dist/middleware/nextjs.js.map +1 -1
- package/dist/middleware/nextjs.mjs +2 -2
- package/dist/setup.d.mts +12 -1
- package/dist/setup.d.ts +12 -1
- package/dist/setup.js +43 -0
- package/dist/setup.js.map +1 -1
- package/dist/setup.mjs +41 -0
- package/dist/setup.mjs.map +1 -1
- package/dist/{types-Zt2qHOrW.d.mts → types-DwAWwqqD.d.mts} +36 -15
- package/dist/{types-Zt2qHOrW.d.ts → types-DwAWwqqD.d.ts} +36 -15
- package/package.json +1 -1
- package/dist/chunk-QERJ6LJA.mjs.map +0 -1
- package/dist/chunk-WBHRLAUR.mjs.map +0 -1
|
@@ -352,7 +352,7 @@ var ApptvtyClient = class {
|
|
|
352
352
|
this.log("X402 challenge auto-paid from wallet, retrying request");
|
|
353
353
|
return this.post(path, body);
|
|
354
354
|
}
|
|
355
|
-
let dashboardUrl = "https://dashboard.apptvty.com/login";
|
|
355
|
+
let dashboardUrl = (typeof process !== "undefined" ? process.env?.DASHBOARD_URL : void 0) ?? "https://dashboard.apptvty.com/login";
|
|
356
356
|
try {
|
|
357
357
|
const json = JSON.parse(text);
|
|
358
358
|
dashboardUrl = json?.error?.details?.dashboard_url ?? dashboardUrl;
|
|
@@ -534,7 +534,7 @@ var RequestLogger = class {
|
|
|
534
534
|
this.client = client;
|
|
535
535
|
this.queue = [];
|
|
536
536
|
this.timer = null;
|
|
537
|
-
this.
|
|
537
|
+
this.activeFlushPromise = null;
|
|
538
538
|
this.batchSize = config.batchSize ?? 50;
|
|
539
539
|
this.debug = config.debug ?? false;
|
|
540
540
|
const interval = config.flushInterval ?? 5e3;
|
|
@@ -559,21 +559,31 @@ var RequestLogger = class {
|
|
|
559
559
|
/** Enqueue a single log entry. Non-blocking. */
|
|
560
560
|
enqueue(entry) {
|
|
561
561
|
this.queue.push(entry);
|
|
562
|
-
|
|
563
|
-
void this.flush();
|
|
564
|
-
}
|
|
562
|
+
void this.flush();
|
|
565
563
|
}
|
|
566
|
-
/** Flush the current queue to the API. */
|
|
564
|
+
/** Flush the current queue to the API. Returns the active Promise so Edge runtimes can wait. */
|
|
567
565
|
async flush() {
|
|
568
|
-
if (this.
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
await this.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
this.flushing = false;
|
|
566
|
+
if (this.queue.length === 0) {
|
|
567
|
+
return this.activeFlushPromise || Promise.resolve();
|
|
568
|
+
}
|
|
569
|
+
if (this.activeFlushPromise) {
|
|
570
|
+
await this.activeFlushPromise;
|
|
571
|
+
if (this.queue.length > 0) return this.flush();
|
|
572
|
+
return Promise.resolve();
|
|
576
573
|
}
|
|
574
|
+
const batch = this.queue.splice(0, this.batchSize);
|
|
575
|
+
this.activeFlushPromise = (async () => {
|
|
576
|
+
try {
|
|
577
|
+
await this.client.sendLogs(batch);
|
|
578
|
+
} catch {
|
|
579
|
+
} finally {
|
|
580
|
+
this.activeFlushPromise = null;
|
|
581
|
+
if (this.queue.length > 0) {
|
|
582
|
+
void this.flush();
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
})();
|
|
586
|
+
return this.activeFlushPromise;
|
|
577
587
|
}
|
|
578
588
|
/**
|
|
579
589
|
* Synchronous-ish flush for process shutdown.
|
|
@@ -664,7 +674,7 @@ function createQueryHandler(client, config) {
|
|
|
664
674
|
if (trimmedQuery.length > 500) {
|
|
665
675
|
return errorResponse(400, "QUERY_TOO_LONG", "Query must be 500 characters or fewer");
|
|
666
676
|
}
|
|
667
|
-
const requestId = crypto.randomUUID();
|
|
677
|
+
const requestId = globalThis.crypto.randomUUID();
|
|
668
678
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
669
679
|
const startMs = Date.now();
|
|
670
680
|
const surfaceAds = req.surface_ads !== false;
|
|
@@ -692,16 +702,21 @@ function createQueryHandler(client, config) {
|
|
|
692
702
|
return errorResponse(502, "UPSTREAM_ERROR", "Could not retrieve an answer at this time");
|
|
693
703
|
}
|
|
694
704
|
const responseTimeMs = Date.now() - startMs;
|
|
695
|
-
const ads = backendResponse.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
+
const ads = backendResponse.related_resources ? Array.isArray(backendResponse.related_resources) ? backendResponse.related_resources : [backendResponse.related_resources] : [];
|
|
706
|
+
if (ads.length > 0) {
|
|
707
|
+
await Promise.all(
|
|
708
|
+
ads.map(
|
|
709
|
+
(ad) => client.logImpression({
|
|
710
|
+
impression_id: ad.impression_id,
|
|
711
|
+
site_id: config.siteId,
|
|
712
|
+
query: trimmedQuery,
|
|
713
|
+
agent_ua: req.userAgent,
|
|
714
|
+
agent_ip: req.ipAddress,
|
|
715
|
+
timestamp
|
|
716
|
+
}).catch(() => {
|
|
717
|
+
})
|
|
718
|
+
)
|
|
719
|
+
);
|
|
705
720
|
}
|
|
706
721
|
const agentResponse = {
|
|
707
722
|
success: true,
|
|
@@ -710,7 +725,7 @@ function createQueryHandler(client, config) {
|
|
|
710
725
|
answer: backendResponse.answer,
|
|
711
726
|
sources: backendResponse.sources,
|
|
712
727
|
confidence: backendResponse.confidence,
|
|
713
|
-
...backendResponse.
|
|
728
|
+
...backendResponse.related_resources && { related_resources: backendResponse.related_resources },
|
|
714
729
|
metadata: {
|
|
715
730
|
request_id: requestId,
|
|
716
731
|
response_time_ms: responseTimeMs,
|
|
@@ -728,7 +743,7 @@ function errorResponse(status, code, message) {
|
|
|
728
743
|
error: {
|
|
729
744
|
code,
|
|
730
745
|
message,
|
|
731
|
-
request_id: crypto.randomUUID(),
|
|
746
|
+
request_id: globalThis.crypto.randomUUID(),
|
|
732
747
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
733
748
|
}
|
|
734
749
|
};
|
|
@@ -747,20 +762,49 @@ function getOrigin(url) {
|
|
|
747
762
|
function createDashboardHandler(client, config) {
|
|
748
763
|
return async function handleDashboard(req) {
|
|
749
764
|
const { path, method, authHeader } = req;
|
|
750
|
-
if (config.dashboardSecret) {
|
|
751
|
-
const url2 = new URL(path, "http://localhost");
|
|
752
|
-
const secretParam = url2.searchParams.get("secret");
|
|
753
|
-
const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.substring(7) : null;
|
|
754
|
-
const isAuthorized = secretParam === config.dashboardSecret || bearerToken === config.dashboardSecret;
|
|
755
|
-
if (!isAuthorized) {
|
|
756
|
-
return jsonResponse(401, {
|
|
757
|
-
error: "Unauthorized",
|
|
758
|
-
message: "Dashboard access requires a valid secret. Please set APPTVTY_DASHBOARD_SECRET."
|
|
759
|
-
});
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
765
|
const url = new URL(path, "http://localhost");
|
|
763
766
|
const cleanPath = url.pathname;
|
|
767
|
+
if (cleanPath.includes("/api/apptvty/verify")) {
|
|
768
|
+
const challenge = url.searchParams.get("challenge");
|
|
769
|
+
if (!challenge) {
|
|
770
|
+
return jsonResponse(400, { error: "Challenge required" });
|
|
771
|
+
}
|
|
772
|
+
const encoder = new TextEncoder();
|
|
773
|
+
const keyData = encoder.encode(config.apiKey);
|
|
774
|
+
const cryptoKey = await globalThis.crypto.subtle.importKey(
|
|
775
|
+
"raw",
|
|
776
|
+
keyData,
|
|
777
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
778
|
+
false,
|
|
779
|
+
["sign"]
|
|
780
|
+
);
|
|
781
|
+
const prefixedChallenge = `apptvty_verify_challenge:${challenge}`;
|
|
782
|
+
const signatureBuffer = await globalThis.crypto.subtle.sign("HMAC", cryptoKey, encoder.encode(prefixedChallenge));
|
|
783
|
+
const signature = Array.from(new Uint8Array(signatureBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
784
|
+
return jsonResponse(200, {
|
|
785
|
+
site_id: config.siteId,
|
|
786
|
+
verified: true,
|
|
787
|
+
signature
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
if (!config.dashboardSecret) {
|
|
791
|
+
return jsonResponse(401, {
|
|
792
|
+
error: "Unauthorized",
|
|
793
|
+
message: "Dashboard access is disabled because APPTVTY_DASHBOARD_SECRET is not configured."
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
const secretParam = url.searchParams.get("secret");
|
|
797
|
+
const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.substring(7) : null;
|
|
798
|
+
const isAuthorized = secretParam === config.dashboardSecret || bearerToken === config.dashboardSecret;
|
|
799
|
+
if (!isAuthorized) {
|
|
800
|
+
return jsonResponse(401, {
|
|
801
|
+
error: "Unauthorized",
|
|
802
|
+
message: "Invalid dashboard secret. Please provide a valid secret to access."
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
if (config.debug) {
|
|
806
|
+
console.error(`[apptvty] DashboardHandler: path=${path}, cleanPath=${cleanPath}`);
|
|
807
|
+
}
|
|
764
808
|
if (cleanPath.includes("/api/overview")) {
|
|
765
809
|
const data = await client.getSiteStats();
|
|
766
810
|
return jsonResponse(200, data);
|
|
@@ -1191,13 +1235,13 @@ function createExpressMiddleware(config) {
|
|
|
1191
1235
|
const entry = {
|
|
1192
1236
|
site_id: config.siteId,
|
|
1193
1237
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1194
|
-
|
|
1195
|
-
path,
|
|
1196
|
-
|
|
1238
|
+
request_method: req.method ?? "GET",
|
|
1239
|
+
request_path: path,
|
|
1240
|
+
response_status: res.statusCode,
|
|
1197
1241
|
response_time_ms: Date.now() - startMs,
|
|
1198
1242
|
ip_address: ipAddress,
|
|
1199
1243
|
user_agent: userAgent,
|
|
1200
|
-
|
|
1244
|
+
referrer: req.headers["referer"] ?? null,
|
|
1201
1245
|
is_ai_crawler: crawlerInfo.isAi,
|
|
1202
1246
|
crawler_type: crawlerInfo.name,
|
|
1203
1247
|
crawler_organization: crawlerInfo.organization,
|