mcp-scraper 0.36.0 → 0.37.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/bin/api-server.cjs +766 -168
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +52 -8
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +5 -5
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +3 -3
- package/dist/chunk-3LWYPAU5.js +7 -0
- package/dist/chunk-3LWYPAU5.js.map +1 -0
- package/dist/{chunk-IFYER7O4.js → chunk-CSCD2HNS.js} +132 -2
- package/dist/chunk-CSCD2HNS.js.map +1 -0
- package/dist/{chunk-D7LM5QZN.js → chunk-FSAXLDB3.js} +2 -2
- package/dist/{chunk-5RULXBJ7.js → chunk-JK2FRDAP.js} +55 -11
- package/dist/{chunk-5RULXBJ7.js.map → chunk-JK2FRDAP.js.map} +1 -1
- package/dist/{chunk-ANCGXUQJ.js → chunk-LOPKN3YL.js} +2 -2
- package/dist/{chunk-E5UEELA7.js → chunk-MA5JBAUZ.js} +2 -2
- package/dist/{chunk-AN3VQARU.js → chunk-PUJFYJXB.js} +2 -2
- package/dist/{chunk-4ZIJ3BKZ.js → chunk-PWPUKR5U.js} +4 -2
- package/dist/{chunk-4ZIJ3BKZ.js.map → chunk-PWPUKR5U.js.map} +1 -1
- package/dist/{chunk-O2MCWFXQ.js → chunk-Q35WZJJK.js} +3 -3
- package/dist/{db-N6MPVMEF.js → db-N3YECFWR.js} +6 -2
- package/dist/{extract-bundle-M4SDJG3V.js → extract-bundle-346R6MXD.js} +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{location-data-repository-Z4NQOU5Y.js → location-data-repository-O2VII3ON.js} +3 -3
- package/dist/{server-ZIGAFKOL.js → server-QKDDEBVQ.js} +500 -99
- package/dist/server-QKDDEBVQ.js.map +1 -0
- package/dist/{site-extract-repository-PGQZNW6V.js → site-extract-repository-I3VM6WXN.js} +4 -4
- package/dist/{worker-EBB6CTGW.js → worker-TTFXPPDK.js} +6 -6
- package/docs/mcp-tool-manifest.generated.json +182 -6
- package/package.json +2 -2
- package/dist/chunk-4HO66323.js +0 -7
- package/dist/chunk-4HO66323.js.map +0 -1
- package/dist/chunk-IFYER7O4.js.map +0 -1
- package/dist/server-ZIGAFKOL.js.map +0 -1
- /package/dist/{chunk-D7LM5QZN.js.map → chunk-FSAXLDB3.js.map} +0 -0
- /package/dist/{chunk-ANCGXUQJ.js.map → chunk-LOPKN3YL.js.map} +0 -0
- /package/dist/{chunk-E5UEELA7.js.map → chunk-MA5JBAUZ.js.map} +0 -0
- /package/dist/{chunk-AN3VQARU.js.map → chunk-PUJFYJXB.js.map} +0 -0
- /package/dist/{chunk-O2MCWFXQ.js.map → chunk-Q35WZJJK.js.map} +0 -0
- /package/dist/{db-N6MPVMEF.js.map → db-N3YECFWR.js.map} +0 -0
- /package/dist/{extract-bundle-M4SDJG3V.js.map → extract-bundle-346R6MXD.js.map} +0 -0
- /package/dist/{location-data-repository-Z4NQOU5Y.js.map → location-data-repository-O2VII3ON.js.map} +0 -0
- /package/dist/{site-extract-repository-PGQZNW6V.js.map → site-extract-repository-I3VM6WXN.js.map} +0 -0
- /package/dist/{worker-EBB6CTGW.js.map → worker-TTFXPPDK.js.map} +0 -0
package/dist/bin/api-server.cjs
CHANGED
|
@@ -3601,6 +3601,7 @@ var init_url_utils = __esm({
|
|
|
3601
3601
|
// src/api/db.ts
|
|
3602
3602
|
var db_exports = {};
|
|
3603
3603
|
__export(db_exports, {
|
|
3604
|
+
CORE_SCHEMA_VERSION: () => CORE_SCHEMA_VERSION,
|
|
3604
3605
|
CREDIT_LOT_TTL: () => CREDIT_LOT_TTL,
|
|
3605
3606
|
SiteAuditJobRowSchema: () => SiteAuditJobRowSchema,
|
|
3606
3607
|
SiteAuditPhaseLogRowSchema: () => SiteAuditPhaseLogRowSchema,
|
|
@@ -3626,6 +3627,7 @@ __export(db_exports, {
|
|
|
3626
3627
|
createWorkflowRun: () => createWorkflowRun,
|
|
3627
3628
|
createWorkflowSchedule: () => createWorkflowSchedule,
|
|
3628
3629
|
creditMc: () => creditMc,
|
|
3630
|
+
creditMcIdempotent: () => creditMcIdempotent,
|
|
3629
3631
|
deactivateUser: () => deactivateUser,
|
|
3630
3632
|
debitMc: () => debitMc,
|
|
3631
3633
|
debitMcIdempotent: () => debitMcIdempotent,
|
|
@@ -4081,6 +4083,50 @@ async function migrate() {
|
|
|
4081
4083
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
4082
4084
|
)
|
|
4083
4085
|
`);
|
|
4086
|
+
await db.execute(`
|
|
4087
|
+
CREATE TABLE IF NOT EXISTS billing_credits (
|
|
4088
|
+
idempotency_key TEXT PRIMARY KEY,
|
|
4089
|
+
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
4090
|
+
amount_mc INTEGER NOT NULL,
|
|
4091
|
+
operation TEXT NOT NULL,
|
|
4092
|
+
description TEXT,
|
|
4093
|
+
status TEXT NOT NULL DEFAULT 'claimed',
|
|
4094
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
4095
|
+
applied_at TEXT
|
|
4096
|
+
)
|
|
4097
|
+
`);
|
|
4098
|
+
await db.execute(`CREATE INDEX IF NOT EXISTS billing_credits_user_status ON billing_credits(user_id, status)`);
|
|
4099
|
+
await db.execute(`
|
|
4100
|
+
CREATE TABLE IF NOT EXISTS admin_credit_adjustments (
|
|
4101
|
+
reference TEXT PRIMARY KEY,
|
|
4102
|
+
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
4103
|
+
direction TEXT NOT NULL,
|
|
4104
|
+
amount_mc INTEGER NOT NULL,
|
|
4105
|
+
reason TEXT NOT NULL,
|
|
4106
|
+
actor TEXT NOT NULL,
|
|
4107
|
+
status TEXT NOT NULL DEFAULT 'applied',
|
|
4108
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
4109
|
+
updated_at TEXT
|
|
4110
|
+
)
|
|
4111
|
+
`);
|
|
4112
|
+
await db.execute(`CREATE INDEX IF NOT EXISTS admin_credit_adjustments_user_created ON admin_credit_adjustments(user_id, created_at)`);
|
|
4113
|
+
await db.execute(`
|
|
4114
|
+
CREATE TABLE IF NOT EXISTS admin_credit_adjustment_events (
|
|
4115
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4116
|
+
reference TEXT NOT NULL REFERENCES admin_credit_adjustments(reference),
|
|
4117
|
+
seq INTEGER NOT NULL,
|
|
4118
|
+
kind TEXT NOT NULL,
|
|
4119
|
+
from_amount_mc INTEGER,
|
|
4120
|
+
to_amount_mc INTEGER,
|
|
4121
|
+
from_reason TEXT,
|
|
4122
|
+
to_reason TEXT,
|
|
4123
|
+
moved_mc INTEGER NOT NULL DEFAULT 0,
|
|
4124
|
+
actor TEXT NOT NULL,
|
|
4125
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
4126
|
+
UNIQUE (reference, seq)
|
|
4127
|
+
)
|
|
4128
|
+
`);
|
|
4129
|
+
await db.execute(`CREATE INDEX IF NOT EXISTS admin_credit_adjustment_events_reference ON admin_credit_adjustment_events(reference)`);
|
|
4084
4130
|
await db.execute(`
|
|
4085
4131
|
CREATE TABLE IF NOT EXISTS site_audit_jobs (
|
|
4086
4132
|
id TEXT PRIMARY KEY,
|
|
@@ -5592,6 +5638,84 @@ async function creditMc(userId, mc, operation, description, stripePaymentIntent,
|
|
|
5592
5638
|
const res = await db.execute({ sql: "SELECT balance_mc FROM users WHERE id = ?", args: [userId] });
|
|
5593
5639
|
return Number(res.rows[0]?.balance_mc ?? 0);
|
|
5594
5640
|
}
|
|
5641
|
+
async function creditMcIdempotent(userId, mc, operation, description, idempotencyKey2, options) {
|
|
5642
|
+
if (!Number.isSafeInteger(mc) || mc <= 0) throw new Error("idempotent credit amount must be a positive integer");
|
|
5643
|
+
if (!idempotencyKey2 || idempotencyKey2.length > 500) throw new Error("idempotent credit key is required and must be bounded");
|
|
5644
|
+
const db = getDb();
|
|
5645
|
+
await ensureMigrated(userId);
|
|
5646
|
+
let neverExpires = options?.neverExpires;
|
|
5647
|
+
if (neverExpires === void 0) {
|
|
5648
|
+
const tier = await db.execute({ sql: "SELECT subscription_tier FROM users WHERE id = ? LIMIT 1", args: [userId] });
|
|
5649
|
+
neverExpires = String(tier.rows[0]?.subscription_tier ?? "").startsWith("sonic");
|
|
5650
|
+
}
|
|
5651
|
+
const expiry = neverExpires ? "9999-12-31 23:59:59" : null;
|
|
5652
|
+
const readBalance = async () => {
|
|
5653
|
+
const res = await db.execute({ sql: "SELECT balance_mc FROM users WHERE id = ?", args: [userId] });
|
|
5654
|
+
return Number(res.rows[0]?.balance_mc ?? 0);
|
|
5655
|
+
};
|
|
5656
|
+
let results;
|
|
5657
|
+
try {
|
|
5658
|
+
results = await db.batch([
|
|
5659
|
+
{
|
|
5660
|
+
sql: "INSERT OR IGNORE INTO billing_credits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",
|
|
5661
|
+
args: [idempotencyKey2, userId, mc, operation, description]
|
|
5662
|
+
},
|
|
5663
|
+
{
|
|
5664
|
+
sql: "UPDATE billing_credits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed'",
|
|
5665
|
+
args: [idempotencyKey2, userId, mc, operation, description]
|
|
5666
|
+
},
|
|
5667
|
+
{
|
|
5668
|
+
sql: `INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
|
|
5669
|
+
SELECT user_id, amount_mc, amount_mc, operation, NULL, COALESCE(?, datetime('now', ?)), ?
|
|
5670
|
+
FROM billing_credits
|
|
5671
|
+
WHERE idempotency_key = ? AND status = 'applying'`,
|
|
5672
|
+
args: [expiry, CREDIT_LOT_TTL, neverExpires ? 1 : 0, idempotencyKey2]
|
|
5673
|
+
},
|
|
5674
|
+
{
|
|
5675
|
+
sql: `UPDATE users
|
|
5676
|
+
SET balance_mc = balance_mc + COALESCE((
|
|
5677
|
+
SELECT amount_mc FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'
|
|
5678
|
+
), 0)
|
|
5679
|
+
WHERE id = ?`,
|
|
5680
|
+
args: [idempotencyKey2, userId]
|
|
5681
|
+
},
|
|
5682
|
+
{
|
|
5683
|
+
sql: "INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'",
|
|
5684
|
+
args: [idempotencyKey2]
|
|
5685
|
+
},
|
|
5686
|
+
{
|
|
5687
|
+
sql: "UPDATE billing_credits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",
|
|
5688
|
+
args: [idempotencyKey2]
|
|
5689
|
+
}
|
|
5690
|
+
], "write");
|
|
5691
|
+
} catch (error) {
|
|
5692
|
+
try {
|
|
5693
|
+
const recovered = await db.execute({
|
|
5694
|
+
sql: "SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",
|
|
5695
|
+
args: [idempotencyKey2]
|
|
5696
|
+
});
|
|
5697
|
+
const row2 = recovered.rows[0];
|
|
5698
|
+
if (row2 && Number(row2.user_id) === userId && Number(row2.amount_mc) === mc && String(row2.operation) === operation && String(row2.description) === description) {
|
|
5699
|
+
return { ok: true, balance_mc: await readBalance(), duplicate: true };
|
|
5700
|
+
}
|
|
5701
|
+
} catch {
|
|
5702
|
+
}
|
|
5703
|
+
throw error;
|
|
5704
|
+
}
|
|
5705
|
+
const claim = await db.execute({
|
|
5706
|
+
sql: "SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",
|
|
5707
|
+
args: [idempotencyKey2]
|
|
5708
|
+
});
|
|
5709
|
+
const row = claim.rows[0];
|
|
5710
|
+
if (!row || Number(row.user_id) !== userId || Number(row.amount_mc) !== mc || String(row.operation) !== operation || String(row.description) !== description) {
|
|
5711
|
+
throw new Error("idempotent credit key conflicts with another credit");
|
|
5712
|
+
}
|
|
5713
|
+
return {
|
|
5714
|
+
ok: String(row.status) === "applied",
|
|
5715
|
+
balance_mc: await readBalance(),
|
|
5716
|
+
duplicate: results[1]?.rowsAffected === 0 && String(row.status) === "applied"
|
|
5717
|
+
};
|
|
5718
|
+
}
|
|
5595
5719
|
async function ledgerExistsForOperation(userId, operation) {
|
|
5596
5720
|
const res = await getDb().execute({
|
|
5597
5721
|
sql: "SELECT 1 FROM ledger WHERE user_id = ? AND operation = ? LIMIT 1",
|
|
@@ -6138,9 +6262,12 @@ var init_db = __esm({
|
|
|
6138
6262
|
DB_TOKEN = process.env.TURSO_AUTH_TOKEN;
|
|
6139
6263
|
_db = null;
|
|
6140
6264
|
_rateLimitSchemaReady = false;
|
|
6141
|
-
CORE_SCHEMA_VERSION = "2026-07-
|
|
6265
|
+
CORE_SCHEMA_VERSION = "2026-07-28.1";
|
|
6142
6266
|
CORE_SCHEMA_TABLES = [
|
|
6267
|
+
"admin_credit_adjustment_events",
|
|
6268
|
+
"admin_credit_adjustments",
|
|
6143
6269
|
"billing_authorizations",
|
|
6270
|
+
"billing_credits",
|
|
6144
6271
|
"billing_debits",
|
|
6145
6272
|
"billing_debit_allocations",
|
|
6146
6273
|
"billing_events",
|
|
@@ -6174,7 +6301,10 @@ var init_db = __esm({
|
|
|
6174
6301
|
"workflow_webhook_deliveries"
|
|
6175
6302
|
];
|
|
6176
6303
|
CORE_SCHEMA_INDEXES = [
|
|
6304
|
+
"admin_credit_adjustment_events_reference",
|
|
6305
|
+
"admin_credit_adjustments_user_created",
|
|
6177
6306
|
"billing_authorizations_user_status",
|
|
6307
|
+
"billing_credits_user_status",
|
|
6178
6308
|
"billing_debits_user_status",
|
|
6179
6309
|
"billing_events_authorization",
|
|
6180
6310
|
"billing_events_user_created_at",
|
|
@@ -11196,7 +11326,9 @@ var init_rates = __esm({
|
|
|
11196
11326
|
SITE_AUDIT_LLM: "site_audit_llm",
|
|
11197
11327
|
SCHEDULED_RUN: "scheduled_run",
|
|
11198
11328
|
CONNECTED_USAGE: "connected_usage",
|
|
11199
|
-
CONNECTED_ACCOUNT_FEE: "connected_account_fee"
|
|
11329
|
+
CONNECTED_ACCOUNT_FEE: "connected_account_fee",
|
|
11330
|
+
ADMIN_GRANT: "admin_grant",
|
|
11331
|
+
ADMIN_REVOKE: "admin_revoke"
|
|
11200
11332
|
};
|
|
11201
11333
|
MEMORY_AI_MARGIN_MULTIPLE = 3;
|
|
11202
11334
|
SITE_AUDIT_LLM_MARGIN_MULTIPLE = 1.5;
|
|
@@ -28017,6 +28149,427 @@ var init_google_ads_routes = __esm({
|
|
|
28017
28149
|
}
|
|
28018
28150
|
});
|
|
28019
28151
|
|
|
28152
|
+
// src/api/admin-auth.ts
|
|
28153
|
+
var import_factory5, adminAuth;
|
|
28154
|
+
var init_admin_auth = __esm({
|
|
28155
|
+
"src/api/admin-auth.ts"() {
|
|
28156
|
+
"use strict";
|
|
28157
|
+
import_factory5 = require("hono/factory");
|
|
28158
|
+
adminAuth = (0, import_factory5.createMiddleware)(async (c, next) => {
|
|
28159
|
+
const configured = process.env.ADMIN_KEY?.trim();
|
|
28160
|
+
const key = c.req.header("x-admin-key")?.trim();
|
|
28161
|
+
if (!configured) return c.json({ error: "Admin access disabled" }, 503);
|
|
28162
|
+
if (!key || key !== configured) return c.json({ error: "Unauthorized" }, 401);
|
|
28163
|
+
return next();
|
|
28164
|
+
});
|
|
28165
|
+
}
|
|
28166
|
+
});
|
|
28167
|
+
|
|
28168
|
+
// src/api/admin-credits.ts
|
|
28169
|
+
function toCredits(mc) {
|
|
28170
|
+
return mc / MC_PER_CREDIT;
|
|
28171
|
+
}
|
|
28172
|
+
function creditsToMc(credits) {
|
|
28173
|
+
return Math.round(credits * MC_PER_CREDIT);
|
|
28174
|
+
}
|
|
28175
|
+
function validateCredits(credits, confirmLarge) {
|
|
28176
|
+
if (typeof credits !== "number" || !Number.isFinite(credits) || !Number.isInteger(credits)) {
|
|
28177
|
+
throw new AdminCreditError(400, "credits must be a whole number");
|
|
28178
|
+
}
|
|
28179
|
+
if (credits < MIN_ADJUSTMENT_CREDITS) {
|
|
28180
|
+
throw new AdminCreditError(400, `credits must be at least ${MIN_ADJUSTMENT_CREDITS}`);
|
|
28181
|
+
}
|
|
28182
|
+
if (credits > MAX_ADJUSTMENT_CREDITS) {
|
|
28183
|
+
throw new AdminCreditError(400, `credits exceeds the hard ceiling of ${MAX_ADJUSTMENT_CREDITS.toLocaleString()}`);
|
|
28184
|
+
}
|
|
28185
|
+
if (credits > LARGE_ADJUSTMENT_CREDITS && !confirmLarge) {
|
|
28186
|
+
throw new AdminCreditError(422, `adjustments over ${LARGE_ADJUSTMENT_CREDITS.toLocaleString()} credits require confirmLarge: true`, {
|
|
28187
|
+
credits,
|
|
28188
|
+
threshold: LARGE_ADJUSTMENT_CREDITS
|
|
28189
|
+
});
|
|
28190
|
+
}
|
|
28191
|
+
return credits;
|
|
28192
|
+
}
|
|
28193
|
+
function validateReason(reason) {
|
|
28194
|
+
const trimmed = typeof reason === "string" ? reason.trim() : "";
|
|
28195
|
+
if (trimmed.length < MIN_REASON_LENGTH) {
|
|
28196
|
+
throw new AdminCreditError(400, `reason must be at least ${MIN_REASON_LENGTH} characters`);
|
|
28197
|
+
}
|
|
28198
|
+
if (trimmed.length > MAX_REASON_LENGTH) {
|
|
28199
|
+
throw new AdminCreditError(400, `reason must be at most ${MAX_REASON_LENGTH} characters`);
|
|
28200
|
+
}
|
|
28201
|
+
return trimmed;
|
|
28202
|
+
}
|
|
28203
|
+
function validateActor(actor) {
|
|
28204
|
+
const trimmed = typeof actor === "string" ? actor.trim() : "";
|
|
28205
|
+
if (!trimmed) throw new AdminCreditError(400, "actor is required so the adjustment records who made it");
|
|
28206
|
+
if (trimmed.length > MAX_ACTOR_LENGTH) {
|
|
28207
|
+
throw new AdminCreditError(400, `actor must be at most ${MAX_ACTOR_LENGTH} characters`);
|
|
28208
|
+
}
|
|
28209
|
+
return trimmed;
|
|
28210
|
+
}
|
|
28211
|
+
function validateDirection(direction) {
|
|
28212
|
+
if (direction !== "grant" && direction !== "revoke") {
|
|
28213
|
+
throw new AdminCreditError(400, "direction must be either 'grant' or 'revoke'");
|
|
28214
|
+
}
|
|
28215
|
+
return direction;
|
|
28216
|
+
}
|
|
28217
|
+
async function resolveUser2(target) {
|
|
28218
|
+
const email = target.email?.trim().toLowerCase();
|
|
28219
|
+
if (!email && target.userId == null) {
|
|
28220
|
+
throw new AdminCreditError(400, "Provide either email or userId");
|
|
28221
|
+
}
|
|
28222
|
+
const user = email ? await getUserByEmail(email) : await getUserById(target.userId);
|
|
28223
|
+
if (user) return user;
|
|
28224
|
+
const probe = await getDb().execute(
|
|
28225
|
+
email ? { sql: "SELECT active FROM users WHERE email = ? LIMIT 1", args: [email] } : { sql: "SELECT active FROM users WHERE id = ? LIMIT 1", args: [target.userId] }
|
|
28226
|
+
);
|
|
28227
|
+
if (probe.rows.length > 0) {
|
|
28228
|
+
throw new AdminCreditError(409, "Account is deactivated; reactivate it before adjusting credits");
|
|
28229
|
+
}
|
|
28230
|
+
throw new AdminCreditError(404, "No account found for that email or id");
|
|
28231
|
+
}
|
|
28232
|
+
async function moveCredits(userId, direction, mc, reason, key) {
|
|
28233
|
+
if (direction === "grant") {
|
|
28234
|
+
const res2 = await creditMcIdempotent(userId, mc, LedgerOperation.ADMIN_GRANT, reason, key);
|
|
28235
|
+
if (!res2.ok) throw new AdminCreditError(409, "Grant could not be applied");
|
|
28236
|
+
return;
|
|
28237
|
+
}
|
|
28238
|
+
const res = await debitMcIdempotent(userId, mc, LedgerOperation.ADMIN_REVOKE, reason, key);
|
|
28239
|
+
if (!res.ok) {
|
|
28240
|
+
const balance = await reconcileBalanceMc(userId);
|
|
28241
|
+
throw new AdminCreditError(409, "Account does not have enough credits for this revoke", {
|
|
28242
|
+
requested_credits: toCredits(mc),
|
|
28243
|
+
available_credits: toCredits(balance)
|
|
28244
|
+
});
|
|
28245
|
+
}
|
|
28246
|
+
}
|
|
28247
|
+
function flip(direction) {
|
|
28248
|
+
return direction === "grant" ? "revoke" : "grant";
|
|
28249
|
+
}
|
|
28250
|
+
async function loadAdjustment(reference) {
|
|
28251
|
+
const db = getDb();
|
|
28252
|
+
const res = await db.execute({
|
|
28253
|
+
sql: `SELECT a.reference, a.user_id, a.direction, a.amount_mc, a.reason, a.actor, a.status, a.created_at, a.updated_at, u.email
|
|
28254
|
+
FROM admin_credit_adjustments a JOIN users u ON u.id = a.user_id
|
|
28255
|
+
WHERE a.reference = ? LIMIT 1`,
|
|
28256
|
+
args: [reference]
|
|
28257
|
+
});
|
|
28258
|
+
const row = res.rows[0];
|
|
28259
|
+
if (!row) throw new AdminCreditError(404, `No adjustment found with reference ${reference}`);
|
|
28260
|
+
const events = await db.execute({
|
|
28261
|
+
sql: `SELECT seq, kind, from_amount_mc, to_amount_mc, from_reason, to_reason, moved_mc, actor, created_at
|
|
28262
|
+
FROM admin_credit_adjustment_events WHERE reference = ? ORDER BY seq ASC`,
|
|
28263
|
+
args: [reference]
|
|
28264
|
+
});
|
|
28265
|
+
return {
|
|
28266
|
+
reference: String(row.reference),
|
|
28267
|
+
user_id: Number(row.user_id),
|
|
28268
|
+
user_email: String(row.email),
|
|
28269
|
+
direction: String(row.direction),
|
|
28270
|
+
credits: toCredits(Number(row.amount_mc)),
|
|
28271
|
+
amount_mc: Number(row.amount_mc),
|
|
28272
|
+
reason: String(row.reason),
|
|
28273
|
+
actor: String(row.actor),
|
|
28274
|
+
status: String(row.status),
|
|
28275
|
+
created_at: String(row.created_at),
|
|
28276
|
+
updated_at: row.updated_at == null ? null : String(row.updated_at),
|
|
28277
|
+
history: events.rows.map((e) => ({
|
|
28278
|
+
seq: Number(e.seq),
|
|
28279
|
+
kind: String(e.kind),
|
|
28280
|
+
from_credits: e.from_amount_mc == null ? null : toCredits(Number(e.from_amount_mc)),
|
|
28281
|
+
to_credits: e.to_amount_mc == null ? null : toCredits(Number(e.to_amount_mc)),
|
|
28282
|
+
from_reason: e.from_reason == null ? null : String(e.from_reason),
|
|
28283
|
+
to_reason: e.to_reason == null ? null : String(e.to_reason),
|
|
28284
|
+
moved_credits: toCredits(Number(e.moved_mc ?? 0)),
|
|
28285
|
+
actor: String(e.actor),
|
|
28286
|
+
created_at: String(e.created_at)
|
|
28287
|
+
}))
|
|
28288
|
+
};
|
|
28289
|
+
}
|
|
28290
|
+
async function nextSeq(reference) {
|
|
28291
|
+
const res = await getDb().execute({
|
|
28292
|
+
sql: "SELECT COALESCE(MAX(seq), 0) AS max_seq FROM admin_credit_adjustment_events WHERE reference = ?",
|
|
28293
|
+
args: [reference]
|
|
28294
|
+
});
|
|
28295
|
+
return Number(res.rows[0]?.max_seq ?? 0) + 1;
|
|
28296
|
+
}
|
|
28297
|
+
async function applyAdjustment(input) {
|
|
28298
|
+
const direction = validateDirection(input.direction);
|
|
28299
|
+
const credits = validateCredits(input.credits, input.confirmLarge === true);
|
|
28300
|
+
const reason = validateReason(input.reason);
|
|
28301
|
+
const actor = validateActor(input.actor);
|
|
28302
|
+
const reference = input.reference?.trim() || `adj_${(0, import_node_crypto15.randomUUID)()}`;
|
|
28303
|
+
if (reference.length > 120) throw new AdminCreditError(400, "reference must be at most 120 characters");
|
|
28304
|
+
const db = getDb();
|
|
28305
|
+
const existing = await db.execute({
|
|
28306
|
+
sql: "SELECT reference, user_id, direction, amount_mc FROM admin_credit_adjustments WHERE reference = ? LIMIT 1",
|
|
28307
|
+
args: [reference]
|
|
28308
|
+
});
|
|
28309
|
+
if (existing.rows.length > 0) {
|
|
28310
|
+
const prior = existing.rows[0];
|
|
28311
|
+
if (String(prior.direction) !== direction || Number(prior.amount_mc) !== creditsToMc(credits)) {
|
|
28312
|
+
throw new AdminCreditError(409, "reference already exists with different values; use the edit endpoint to change it");
|
|
28313
|
+
}
|
|
28314
|
+
return loadAdjustment(reference);
|
|
28315
|
+
}
|
|
28316
|
+
const user = await resolveUser2({ email: input.email, userId: input.userId });
|
|
28317
|
+
const mc = creditsToMc(credits);
|
|
28318
|
+
await moveCredits(user.id, direction, mc, reason, `${reference}:1`);
|
|
28319
|
+
await db.batch([
|
|
28320
|
+
{
|
|
28321
|
+
sql: `INSERT OR IGNORE INTO admin_credit_adjustments (reference, user_id, direction, amount_mc, reason, actor, status)
|
|
28322
|
+
VALUES (?, ?, ?, ?, ?, ?, 'applied')`,
|
|
28323
|
+
args: [reference, user.id, direction, mc, reason, actor]
|
|
28324
|
+
},
|
|
28325
|
+
{
|
|
28326
|
+
sql: `INSERT OR IGNORE INTO admin_credit_adjustment_events (reference, seq, kind, from_amount_mc, to_amount_mc, from_reason, to_reason, moved_mc, actor)
|
|
28327
|
+
VALUES (?, 1, 'created', NULL, ?, NULL, ?, ?, ?)`,
|
|
28328
|
+
args: [reference, mc, reason, mc, actor]
|
|
28329
|
+
}
|
|
28330
|
+
], "write");
|
|
28331
|
+
return loadAdjustment(reference);
|
|
28332
|
+
}
|
|
28333
|
+
async function editAdjustment(input) {
|
|
28334
|
+
const actor = validateActor(input.actor);
|
|
28335
|
+
const current = await loadAdjustment(input.reference);
|
|
28336
|
+
if (current.status === "reversed") {
|
|
28337
|
+
throw new AdminCreditError(409, "This adjustment was reversed and can no longer be edited");
|
|
28338
|
+
}
|
|
28339
|
+
if (input.credits === void 0 && input.reason === void 0) {
|
|
28340
|
+
throw new AdminCreditError(400, "Provide credits, reason, or both");
|
|
28341
|
+
}
|
|
28342
|
+
const db = getDb();
|
|
28343
|
+
if (input.reason !== void 0) {
|
|
28344
|
+
const reason = validateReason(input.reason);
|
|
28345
|
+
if (reason !== current.reason) {
|
|
28346
|
+
const seq = await nextSeq(current.reference);
|
|
28347
|
+
await db.batch([
|
|
28348
|
+
{
|
|
28349
|
+
sql: "UPDATE admin_credit_adjustments SET reason = ?, updated_at = datetime('now') WHERE reference = ?",
|
|
28350
|
+
args: [reason, current.reference]
|
|
28351
|
+
},
|
|
28352
|
+
{
|
|
28353
|
+
sql: `INSERT INTO admin_credit_adjustment_events (reference, seq, kind, from_reason, to_reason, moved_mc, actor)
|
|
28354
|
+
VALUES (?, ?, 'reason_edited', ?, ?, 0, ?)`,
|
|
28355
|
+
args: [current.reference, seq, current.reason, reason, actor]
|
|
28356
|
+
}
|
|
28357
|
+
], "write");
|
|
28358
|
+
}
|
|
28359
|
+
}
|
|
28360
|
+
if (input.credits !== void 0) {
|
|
28361
|
+
const credits = validateCredits(input.credits, input.confirmLarge === true);
|
|
28362
|
+
const targetMc = creditsToMc(credits);
|
|
28363
|
+
if (targetMc !== current.amount_mc) {
|
|
28364
|
+
const deltaMc = targetMc - current.amount_mc;
|
|
28365
|
+
const moveDirection = deltaMc > 0 ? current.direction : flip(current.direction);
|
|
28366
|
+
const moveMc = Math.abs(deltaMc);
|
|
28367
|
+
const seq = await nextSeq(current.reference);
|
|
28368
|
+
const reason = input.reason !== void 0 ? validateReason(input.reason) : current.reason;
|
|
28369
|
+
await moveCredits(current.user_id, moveDirection, moveMc, `edit ${current.reference}: ${reason}`, `${current.reference}:${seq}`);
|
|
28370
|
+
await db.batch([
|
|
28371
|
+
{
|
|
28372
|
+
sql: "UPDATE admin_credit_adjustments SET amount_mc = ?, updated_at = datetime('now') WHERE reference = ?",
|
|
28373
|
+
args: [targetMc, current.reference]
|
|
28374
|
+
},
|
|
28375
|
+
{
|
|
28376
|
+
sql: `INSERT INTO admin_credit_adjustment_events (reference, seq, kind, from_amount_mc, to_amount_mc, moved_mc, actor)
|
|
28377
|
+
VALUES (?, ?, 'amount_edited', ?, ?, ?, ?)`,
|
|
28378
|
+
args: [current.reference, seq, current.amount_mc, targetMc, moveMc, actor]
|
|
28379
|
+
}
|
|
28380
|
+
], "write");
|
|
28381
|
+
}
|
|
28382
|
+
}
|
|
28383
|
+
return loadAdjustment(input.reference);
|
|
28384
|
+
}
|
|
28385
|
+
async function reverseAdjustment(reference, actor) {
|
|
28386
|
+
const validActor = validateActor(actor);
|
|
28387
|
+
const current = await loadAdjustment(reference);
|
|
28388
|
+
if (current.status === "reversed") return current;
|
|
28389
|
+
const seq = await nextSeq(reference);
|
|
28390
|
+
if (current.amount_mc > 0) {
|
|
28391
|
+
await moveCredits(current.user_id, flip(current.direction), current.amount_mc, `reverse ${reference}: ${current.reason}`, `${reference}:${seq}`);
|
|
28392
|
+
}
|
|
28393
|
+
await getDb().batch([
|
|
28394
|
+
{
|
|
28395
|
+
sql: "UPDATE admin_credit_adjustments SET status = 'reversed', updated_at = datetime('now') WHERE reference = ?",
|
|
28396
|
+
args: [reference]
|
|
28397
|
+
},
|
|
28398
|
+
{
|
|
28399
|
+
sql: `INSERT INTO admin_credit_adjustment_events (reference, seq, kind, from_amount_mc, to_amount_mc, moved_mc, actor)
|
|
28400
|
+
VALUES (?, ?, 'reversed', ?, 0, ?, ?)`,
|
|
28401
|
+
args: [reference, seq, current.amount_mc, current.amount_mc, validActor]
|
|
28402
|
+
}
|
|
28403
|
+
], "write");
|
|
28404
|
+
return loadAdjustment(reference);
|
|
28405
|
+
}
|
|
28406
|
+
async function lookupAccount(target, limit = 20) {
|
|
28407
|
+
const user = await resolveUser2(target);
|
|
28408
|
+
const db = getDb();
|
|
28409
|
+
const balanceMc = await reconcileBalanceMc(user.id, user.balance_mc);
|
|
28410
|
+
const lots = await db.execute({
|
|
28411
|
+
sql: `SELECT COUNT(*) AS n, COALESCE(SUM(remaining_mc), 0) AS mc, MIN(expires_at) AS next_expiry
|
|
28412
|
+
FROM credit_lots
|
|
28413
|
+
WHERE user_id = ? AND remaining_mc > 0 AND (never_expires = 1 OR expires_at > datetime('now'))`,
|
|
28414
|
+
args: [user.id]
|
|
28415
|
+
});
|
|
28416
|
+
const refs = await db.execute({
|
|
28417
|
+
sql: "SELECT reference FROM admin_credit_adjustments WHERE user_id = ? ORDER BY created_at DESC, rowid DESC LIMIT ?",
|
|
28418
|
+
args: [user.id, limit]
|
|
28419
|
+
});
|
|
28420
|
+
const adjustments = await Promise.all(refs.rows.map((r) => loadAdjustment(String(r.reference))));
|
|
28421
|
+
const ledger = await db.execute({
|
|
28422
|
+
sql: "SELECT created_at, operation, amount_mc, description FROM ledger WHERE user_id = ? ORDER BY id DESC LIMIT ?",
|
|
28423
|
+
args: [user.id, limit]
|
|
28424
|
+
});
|
|
28425
|
+
return {
|
|
28426
|
+
user: {
|
|
28427
|
+
id: user.id,
|
|
28428
|
+
email: user.email,
|
|
28429
|
+
active: Boolean(user.active),
|
|
28430
|
+
balance_credits: toCredits(balanceMc),
|
|
28431
|
+
balance_mc: balanceMc
|
|
28432
|
+
},
|
|
28433
|
+
lots: {
|
|
28434
|
+
active_lots: Number(lots.rows[0]?.n ?? 0),
|
|
28435
|
+
active_credits: toCredits(Number(lots.rows[0]?.mc ?? 0)),
|
|
28436
|
+
next_expiry: lots.rows[0]?.next_expiry == null ? null : String(lots.rows[0].next_expiry)
|
|
28437
|
+
},
|
|
28438
|
+
adjustments,
|
|
28439
|
+
recent_ledger: ledger.rows.map((r) => ({
|
|
28440
|
+
created_at: String(r.created_at),
|
|
28441
|
+
operation: String(r.operation),
|
|
28442
|
+
credits: toCredits(Number(r.amount_mc)),
|
|
28443
|
+
description: r.description == null ? null : String(r.description)
|
|
28444
|
+
}))
|
|
28445
|
+
};
|
|
28446
|
+
}
|
|
28447
|
+
var import_node_crypto15, MIN_ADJUSTMENT_CREDITS, LARGE_ADJUSTMENT_CREDITS, MAX_ADJUSTMENT_CREDITS, MIN_REASON_LENGTH, MAX_REASON_LENGTH, MAX_ACTOR_LENGTH, AdminCreditError;
|
|
28448
|
+
var init_admin_credits = __esm({
|
|
28449
|
+
"src/api/admin-credits.ts"() {
|
|
28450
|
+
"use strict";
|
|
28451
|
+
import_node_crypto15 = require("crypto");
|
|
28452
|
+
init_db();
|
|
28453
|
+
init_rates();
|
|
28454
|
+
MIN_ADJUSTMENT_CREDITS = 1;
|
|
28455
|
+
LARGE_ADJUSTMENT_CREDITS = 1e5;
|
|
28456
|
+
MAX_ADJUSTMENT_CREDITS = 1e7;
|
|
28457
|
+
MIN_REASON_LENGTH = 3;
|
|
28458
|
+
MAX_REASON_LENGTH = 500;
|
|
28459
|
+
MAX_ACTOR_LENGTH = 120;
|
|
28460
|
+
AdminCreditError = class extends Error {
|
|
28461
|
+
constructor(status, message, detail) {
|
|
28462
|
+
super(message);
|
|
28463
|
+
this.status = status;
|
|
28464
|
+
this.detail = detail;
|
|
28465
|
+
this.name = "AdminCreditError";
|
|
28466
|
+
}
|
|
28467
|
+
status;
|
|
28468
|
+
detail;
|
|
28469
|
+
};
|
|
28470
|
+
}
|
|
28471
|
+
});
|
|
28472
|
+
|
|
28473
|
+
// src/api/admin-credit-routes.ts
|
|
28474
|
+
function fail(c, err) {
|
|
28475
|
+
if (err instanceof AdminCreditError) {
|
|
28476
|
+
return c.json({ error: err.message, ...err.detail ?? {} }, err.status);
|
|
28477
|
+
}
|
|
28478
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
28479
|
+
if (message.includes("conflicts with another")) {
|
|
28480
|
+
return c.json({ error: "A concurrent adjustment used the same key; re-read the account and retry" }, 409);
|
|
28481
|
+
}
|
|
28482
|
+
console.error("[admin/credits] unexpected failure:", message);
|
|
28483
|
+
return c.json({ error: "Adjustment failed" }, 500);
|
|
28484
|
+
}
|
|
28485
|
+
async function readBody(c) {
|
|
28486
|
+
try {
|
|
28487
|
+
const parsed = await c.req.json();
|
|
28488
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
28489
|
+
} catch {
|
|
28490
|
+
return {};
|
|
28491
|
+
}
|
|
28492
|
+
}
|
|
28493
|
+
function targetFrom(query) {
|
|
28494
|
+
const email = query.email?.trim();
|
|
28495
|
+
const idRaw = query.userId?.trim();
|
|
28496
|
+
const userId = idRaw ? Number(idRaw) : void 0;
|
|
28497
|
+
if (userId !== void 0 && !Number.isInteger(userId)) {
|
|
28498
|
+
throw new AdminCreditError(400, "userId must be an integer");
|
|
28499
|
+
}
|
|
28500
|
+
return { email: email || void 0, userId };
|
|
28501
|
+
}
|
|
28502
|
+
var import_hono9, adminCreditsApp;
|
|
28503
|
+
var init_admin_credit_routes = __esm({
|
|
28504
|
+
"src/api/admin-credit-routes.ts"() {
|
|
28505
|
+
"use strict";
|
|
28506
|
+
import_hono9 = require("hono");
|
|
28507
|
+
init_admin_auth();
|
|
28508
|
+
init_admin_credits();
|
|
28509
|
+
adminCreditsApp = new import_hono9.Hono();
|
|
28510
|
+
adminCreditsApp.use("*", adminAuth);
|
|
28511
|
+
adminCreditsApp.post("/adjust", async (c) => {
|
|
28512
|
+
try {
|
|
28513
|
+
const body = await readBody(c);
|
|
28514
|
+
const record = await applyAdjustment({
|
|
28515
|
+
email: typeof body.email === "string" ? body.email : void 0,
|
|
28516
|
+
userId: typeof body.userId === "number" ? body.userId : void 0,
|
|
28517
|
+
direction: body.direction,
|
|
28518
|
+
credits: body.credits,
|
|
28519
|
+
reason: body.reason,
|
|
28520
|
+
actor: body.actor,
|
|
28521
|
+
reference: typeof body.reference === "string" ? body.reference : void 0,
|
|
28522
|
+
confirmLarge: body.confirmLarge === true
|
|
28523
|
+
});
|
|
28524
|
+
return c.json({ ok: true, adjustment: record });
|
|
28525
|
+
} catch (err) {
|
|
28526
|
+
return fail(c, err);
|
|
28527
|
+
}
|
|
28528
|
+
});
|
|
28529
|
+
adminCreditsApp.post("/adjustments/:reference/edit", async (c) => {
|
|
28530
|
+
try {
|
|
28531
|
+
const body = await readBody(c);
|
|
28532
|
+
const record = await editAdjustment({
|
|
28533
|
+
reference: c.req.param("reference"),
|
|
28534
|
+
credits: typeof body.credits === "number" ? body.credits : void 0,
|
|
28535
|
+
reason: typeof body.reason === "string" ? body.reason : void 0,
|
|
28536
|
+
actor: body.actor,
|
|
28537
|
+
confirmLarge: body.confirmLarge === true
|
|
28538
|
+
});
|
|
28539
|
+
return c.json({ ok: true, adjustment: record });
|
|
28540
|
+
} catch (err) {
|
|
28541
|
+
return fail(c, err);
|
|
28542
|
+
}
|
|
28543
|
+
});
|
|
28544
|
+
adminCreditsApp.post("/adjustments/:reference/reverse", async (c) => {
|
|
28545
|
+
try {
|
|
28546
|
+
const body = await readBody(c);
|
|
28547
|
+
const record = await reverseAdjustment(c.req.param("reference"), body.actor);
|
|
28548
|
+
return c.json({ ok: true, adjustment: record });
|
|
28549
|
+
} catch (err) {
|
|
28550
|
+
return fail(c, err);
|
|
28551
|
+
}
|
|
28552
|
+
});
|
|
28553
|
+
adminCreditsApp.get("/adjustments/:reference", async (c) => {
|
|
28554
|
+
try {
|
|
28555
|
+
return c.json({ ok: true, adjustment: await loadAdjustment(c.req.param("reference")) });
|
|
28556
|
+
} catch (err) {
|
|
28557
|
+
return fail(c, err);
|
|
28558
|
+
}
|
|
28559
|
+
});
|
|
28560
|
+
adminCreditsApp.get("/lookup", async (c) => {
|
|
28561
|
+
try {
|
|
28562
|
+
const target = targetFrom(c.req.query());
|
|
28563
|
+
const limitRaw = c.req.query("limit");
|
|
28564
|
+
const limit = limitRaw ? Math.min(Math.max(Number(limitRaw), 1), 100) : 20;
|
|
28565
|
+
return c.json({ ok: true, ...await lookupAccount(target, limit) });
|
|
28566
|
+
} catch (err) {
|
|
28567
|
+
return fail(c, err);
|
|
28568
|
+
}
|
|
28569
|
+
});
|
|
28570
|
+
}
|
|
28571
|
+
});
|
|
28572
|
+
|
|
28020
28573
|
// src/extractor/InstagramContentExtractor.ts
|
|
28021
28574
|
function htmlDecode2(value) {
|
|
28022
28575
|
return value.replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -28470,11 +29023,11 @@ function trackFilename(track, index, shortcode) {
|
|
|
28470
29023
|
const bitrate = track.bitrate ? `-${track.bitrate}` : "";
|
|
28471
29024
|
return `${label}-${type}-${index}${bitrate}.mp4`;
|
|
28472
29025
|
}
|
|
28473
|
-
var
|
|
29026
|
+
var import_hono10, import_zod23, import_node_fs7, import_node_os8, import_node_path11, import_node_child_process2, InstagramProfileContentBodySchema, InstagramMediaTypeSchema, InstagramMediaDownloadBodySchema, instagramApp;
|
|
28474
29027
|
var init_instagram_routes = __esm({
|
|
28475
29028
|
"src/api/instagram-routes.ts"() {
|
|
28476
29029
|
"use strict";
|
|
28477
|
-
|
|
29030
|
+
import_hono10 = require("hono");
|
|
28478
29031
|
import_zod23 = require("zod");
|
|
28479
29032
|
import_node_fs7 = require("fs");
|
|
28480
29033
|
import_node_os8 = require("os");
|
|
@@ -28515,7 +29068,7 @@ var init_instagram_routes = __esm({
|
|
|
28515
29068
|
includeTranscript: import_zod23.z.boolean().default(false),
|
|
28516
29069
|
mux: import_zod23.z.boolean().default(true)
|
|
28517
29070
|
});
|
|
28518
|
-
instagramApp = new
|
|
29071
|
+
instagramApp = new import_hono10.Hono();
|
|
28519
29072
|
instagramApp.post("/profile-content", createApiKeyAuth(), async (c) => {
|
|
28520
29073
|
const raw = await c.req.json().catch(() => ({}));
|
|
28521
29074
|
const parsed = InstagramProfileContentBodySchema.safeParse(raw);
|
|
@@ -30971,11 +31524,11 @@ async function scrapeOldRedditWithRetries(url, script, accept) {
|
|
|
30971
31524
|
}
|
|
30972
31525
|
return null;
|
|
30973
31526
|
}
|
|
30974
|
-
var
|
|
31527
|
+
var import_hono11, import_zod24, RedditThreadBodySchema, RedditTrendingBodySchema, PARSE_REDDIT, redditApp, TRENDING_SOFT_DEADLINE_MS, TRENDING_SCRAPE_CONCURRENCY;
|
|
30975
31528
|
var init_reddit_routes = __esm({
|
|
30976
31529
|
"src/api/reddit-routes.ts"() {
|
|
30977
31530
|
"use strict";
|
|
30978
|
-
|
|
31531
|
+
import_hono11 = require("hono");
|
|
30979
31532
|
import_zod24 = require("zod");
|
|
30980
31533
|
init_backup_proxy();
|
|
30981
31534
|
init_BrowserDriver();
|
|
@@ -31024,7 +31577,7 @@ var init_reddit_routes = __esm({
|
|
|
31024
31577
|
});
|
|
31025
31578
|
return { title: title, author: author, score: score, postBody: postBody, blocked: blocked, numComments: comments.length, comments: comments };
|
|
31026
31579
|
})()`;
|
|
31027
|
-
redditApp = new
|
|
31580
|
+
redditApp = new import_hono11.Hono();
|
|
31028
31581
|
redditApp.post("/thread", createApiKeyAuth(), async (c) => {
|
|
31029
31582
|
const raw = await c.req.json().catch(() => ({}));
|
|
31030
31583
|
const parsed = RedditThreadBodySchema.safeParse(raw);
|
|
@@ -31233,11 +31786,11 @@ function invalidRequest5(message) {
|
|
|
31233
31786
|
function tiersFor(frames) {
|
|
31234
31787
|
return Math.ceil(Math.min(Math.max(frames, 1), 480) / 120);
|
|
31235
31788
|
}
|
|
31236
|
-
var
|
|
31789
|
+
var import_hono12, import_zod25, videoApp, AnalyzeBodySchema;
|
|
31237
31790
|
var init_video_routes = __esm({
|
|
31238
31791
|
"src/api/video-routes.ts"() {
|
|
31239
31792
|
"use strict";
|
|
31240
|
-
|
|
31793
|
+
import_hono12 = require("hono");
|
|
31241
31794
|
import_zod25 = require("zod");
|
|
31242
31795
|
init_db();
|
|
31243
31796
|
init_rates();
|
|
@@ -31245,7 +31798,7 @@ var init_video_routes = __esm({
|
|
|
31245
31798
|
init_memory();
|
|
31246
31799
|
init_cost_telemetry();
|
|
31247
31800
|
init_cost_context();
|
|
31248
|
-
videoApp = new
|
|
31801
|
+
videoApp = new import_hono12.Hono();
|
|
31249
31802
|
AnalyzeBodySchema = import_zod25.z.object({
|
|
31250
31803
|
sourceUrl: import_zod25.z.string().trim().url("sourceUrl must be a direct video file URL"),
|
|
31251
31804
|
intervalS: import_zod25.z.number().min(1).max(30).optional(),
|
|
@@ -32002,11 +32555,11 @@ function mapsErrorResponse(c, err, errorCode) {
|
|
|
32002
32555
|
retryable
|
|
32003
32556
|
}, retryable ? 503 : 500);
|
|
32004
32557
|
}
|
|
32005
|
-
var
|
|
32558
|
+
var import_hono13, mapsApp;
|
|
32006
32559
|
var init_maps_routes = __esm({
|
|
32007
32560
|
"src/api/maps-routes.ts"() {
|
|
32008
32561
|
"use strict";
|
|
32009
|
-
|
|
32562
|
+
import_hono13 = require("hono");
|
|
32010
32563
|
init_db();
|
|
32011
32564
|
init_rates();
|
|
32012
32565
|
init_MapsExtractor();
|
|
@@ -32017,7 +32570,7 @@ var init_maps_routes = __esm({
|
|
|
32017
32570
|
init_browser_service_env();
|
|
32018
32571
|
init_maps_search_rotation();
|
|
32019
32572
|
init_concurrency_gates();
|
|
32020
|
-
mapsApp = new
|
|
32573
|
+
mapsApp = new import_hono13.Hono();
|
|
32021
32574
|
mapsApp.post("/search", createApiKeyAuth(), async (c) => {
|
|
32022
32575
|
const user = c.get("user");
|
|
32023
32576
|
const body = await c.req.json().catch(() => ({}));
|
|
@@ -32221,11 +32774,11 @@ async function extractReviewCards(page) {
|
|
|
32221
32774
|
});
|
|
32222
32775
|
});
|
|
32223
32776
|
}
|
|
32224
|
-
var
|
|
32777
|
+
var import_hono14, import_zod27, TrustpilotReviewsBodySchema, trustpilotApp;
|
|
32225
32778
|
var init_trustpilot_routes = __esm({
|
|
32226
32779
|
"src/api/trustpilot-routes.ts"() {
|
|
32227
32780
|
"use strict";
|
|
32228
|
-
|
|
32781
|
+
import_hono14 = require("hono");
|
|
32229
32782
|
import_zod27 = require("zod");
|
|
32230
32783
|
init_BrowserDriver();
|
|
32231
32784
|
init_browser_service_env();
|
|
@@ -32237,7 +32790,7 @@ var init_trustpilot_routes = __esm({
|
|
|
32237
32790
|
domain: import_zod27.z.string().trim().min(1, "domain is required"),
|
|
32238
32791
|
maxPages: import_zod27.z.number().int().min(1).max(50).default(5)
|
|
32239
32792
|
});
|
|
32240
|
-
trustpilotApp = new
|
|
32793
|
+
trustpilotApp = new import_hono14.Hono();
|
|
32241
32794
|
trustpilotApp.post("/reviews", createApiKeyAuth(), async (c) => {
|
|
32242
32795
|
const raw = await c.req.json().catch(() => ({}));
|
|
32243
32796
|
const parsed = TrustpilotReviewsBodySchema.safeParse(raw);
|
|
@@ -32423,11 +32976,11 @@ async function extractG2ReviewCards(page) {
|
|
|
32423
32976
|
});
|
|
32424
32977
|
});
|
|
32425
32978
|
}
|
|
32426
|
-
var
|
|
32979
|
+
var import_hono15, import_zod28, G2ReviewsBodySchema, g2App;
|
|
32427
32980
|
var init_g2_routes = __esm({
|
|
32428
32981
|
"src/api/g2-routes.ts"() {
|
|
32429
32982
|
"use strict";
|
|
32430
|
-
|
|
32983
|
+
import_hono15 = require("hono");
|
|
32431
32984
|
import_zod28 = require("zod");
|
|
32432
32985
|
init_backup_proxy();
|
|
32433
32986
|
init_BrowserDriver();
|
|
@@ -32441,7 +32994,7 @@ var init_g2_routes = __esm({
|
|
|
32441
32994
|
product: import_zod28.z.string().trim().min(1, "product is required"),
|
|
32442
32995
|
maxPages: import_zod28.z.number().int().min(1).max(50).default(5)
|
|
32443
32996
|
});
|
|
32444
|
-
g2App = new
|
|
32997
|
+
g2App = new import_hono15.Hono();
|
|
32445
32998
|
g2App.post("/reviews", createApiKeyAuth(), async (c) => {
|
|
32446
32999
|
const raw = await c.req.json().catch(() => ({}));
|
|
32447
33000
|
const parsed = G2ReviewsBodySchema.safeParse(raw);
|
|
@@ -32549,7 +33102,7 @@ function retryDelaySeconds(attempts) {
|
|
|
32549
33102
|
}
|
|
32550
33103
|
async function dispatchPendingDirectoryWorkflows(limit = 25) {
|
|
32551
33104
|
const rows = await claimDirectoryWorkflowOutbox({
|
|
32552
|
-
workerId: `directory-dispatch-${process.pid}-${(0,
|
|
33105
|
+
workerId: `directory-dispatch-${process.pid}-${(0, import_node_crypto16.randomUUID)().slice(0, 8)}`,
|
|
32553
33106
|
limit
|
|
32554
33107
|
});
|
|
32555
33108
|
const result = { claimed: rows.length, dispatched: 0, failed: 0 };
|
|
@@ -32571,11 +33124,11 @@ async function dispatchPendingDirectoryWorkflows(limit = 25) {
|
|
|
32571
33124
|
}
|
|
32572
33125
|
return result;
|
|
32573
33126
|
}
|
|
32574
|
-
var
|
|
33127
|
+
var import_node_crypto16;
|
|
32575
33128
|
var init_directory_workflow_dispatch = __esm({
|
|
32576
33129
|
"src/api/directory-workflow-dispatch.ts"() {
|
|
32577
33130
|
"use strict";
|
|
32578
|
-
|
|
33131
|
+
import_node_crypto16 = require("crypto");
|
|
32579
33132
|
init_client();
|
|
32580
33133
|
init_directory_workflow_repository();
|
|
32581
33134
|
}
|
|
@@ -32587,7 +33140,7 @@ function safeOptions(options) {
|
|
|
32587
33140
|
return safe2;
|
|
32588
33141
|
}
|
|
32589
33142
|
function requestFingerprint(options) {
|
|
32590
|
-
return (0,
|
|
33143
|
+
return (0, import_node_crypto17.createHash)("sha256").update(JSON.stringify(safeOptions(options))).digest("hex");
|
|
32591
33144
|
}
|
|
32592
33145
|
function idempotencyKey(raw) {
|
|
32593
33146
|
if (raw !== void 0) {
|
|
@@ -32596,14 +33149,14 @@ function idempotencyKey(raw) {
|
|
|
32596
33149
|
if (trimmed.length > 500) return { ok: false, message: "Idempotency-Key must be 500 characters or fewer." };
|
|
32597
33150
|
return { ok: true, key: trimmed };
|
|
32598
33151
|
}
|
|
32599
|
-
return { ok: true, key: `directory-${(0,
|
|
33152
|
+
return { ok: true, key: `directory-${(0, import_node_crypto17.randomUUID)()}` };
|
|
32600
33153
|
}
|
|
32601
33154
|
function debitKeyFor(userId, responseKey) {
|
|
32602
|
-
const digest = (0,
|
|
33155
|
+
const digest = (0, import_node_crypto17.createHash)("sha256").update(String(userId)).update("\0").update(responseKey).digest("hex");
|
|
32603
33156
|
return `directory-workflow:${userId}:${digest}`;
|
|
32604
33157
|
}
|
|
32605
33158
|
function jobId() {
|
|
32606
|
-
return `dir_${(0,
|
|
33159
|
+
return `dir_${(0, import_node_crypto17.randomUUID)().replace(/-/g, "")}`;
|
|
32607
33160
|
}
|
|
32608
33161
|
function publicStatus(job, result) {
|
|
32609
33162
|
if (job.status === "failed") return "failed";
|
|
@@ -32712,7 +33265,7 @@ async function runSynchronously(c, user, options, plan, responseKey) {
|
|
|
32712
33265
|
const csv = renderDirectoryWorkflowCsv(result);
|
|
32713
33266
|
const artifact = await createDirectoryCsvArtifact({
|
|
32714
33267
|
ownerId: String(user.id),
|
|
32715
|
-
jobId: (0,
|
|
33268
|
+
jobId: (0, import_node_crypto17.createHash)("sha256").update(debitKey2).digest("hex").slice(0, 32),
|
|
32716
33269
|
createdAt: result.extractedAt,
|
|
32717
33270
|
filename: `${options.state}-${options.query}-directory.csv`,
|
|
32718
33271
|
csv,
|
|
@@ -32768,12 +33321,12 @@ async function runSynchronously(c, user, options, plan, responseKey) {
|
|
|
32768
33321
|
await releaseConcurrencyGate(gate.lockId);
|
|
32769
33322
|
}
|
|
32770
33323
|
}
|
|
32771
|
-
var
|
|
33324
|
+
var import_node_crypto17, import_hono16, directoryApp;
|
|
32772
33325
|
var init_directory_routes = __esm({
|
|
32773
33326
|
"src/api/directory-routes.ts"() {
|
|
32774
33327
|
"use strict";
|
|
32775
|
-
|
|
32776
|
-
|
|
33328
|
+
import_node_crypto17 = require("crypto");
|
|
33329
|
+
import_hono16 = require("hono");
|
|
32777
33330
|
init_api_auth();
|
|
32778
33331
|
init_db();
|
|
32779
33332
|
init_rates();
|
|
@@ -32785,7 +33338,7 @@ var init_directory_routes = __esm({
|
|
|
32785
33338
|
init_directory_workflow_repository();
|
|
32786
33339
|
init_directory_artifacts();
|
|
32787
33340
|
init_directory_workflow_dispatch();
|
|
32788
|
-
directoryApp = new
|
|
33341
|
+
directoryApp = new import_hono16.Hono();
|
|
32789
33342
|
directoryApp.post("/run", createApiKeyAuth(), async (c) => {
|
|
32790
33343
|
const user = c.get("user");
|
|
32791
33344
|
const body = await c.req.json().catch(() => ({}));
|
|
@@ -32993,11 +33546,11 @@ async function readHostedLocationCsv(sourceUrl) {
|
|
|
32993
33546
|
const bytes = await readResponseBodyWithLimit(response, LOCATION_IMPORT_MAX_BYTES);
|
|
32994
33547
|
return bytes.toString("utf8");
|
|
32995
33548
|
}
|
|
32996
|
-
var
|
|
33549
|
+
var import_hono17, import_zod29, LOCATION_IMPORT_MAX_BYTES, LOCATION_IMPORT_TIMEOUT_MS, marketQuerySchema, importSchema, censusSyncSchema, locationDataApp;
|
|
32997
33550
|
var init_location_data_routes = __esm({
|
|
32998
33551
|
"src/api/location-data-routes.ts"() {
|
|
32999
33552
|
"use strict";
|
|
33000
|
-
|
|
33553
|
+
import_hono17 = require("hono");
|
|
33001
33554
|
import_zod29 = require("zod");
|
|
33002
33555
|
init_api_auth();
|
|
33003
33556
|
init_url_utils();
|
|
@@ -33022,7 +33575,7 @@ var init_location_data_routes = __esm({
|
|
|
33022
33575
|
sourceUrl: import_zod29.z.string().url().max(2e3).optional()
|
|
33023
33576
|
});
|
|
33024
33577
|
censusSyncSchema = import_zod29.z.object({ state: import_zod29.z.string().trim().min(2).max(40) });
|
|
33025
|
-
locationDataApp = new
|
|
33578
|
+
locationDataApp = new import_hono17.Hono();
|
|
33026
33579
|
locationDataApp.get("/markets", createApiKeyAuth(), async (c) => {
|
|
33027
33580
|
const parsed = marketQuerySchema.safeParse(c.req.query());
|
|
33028
33581
|
if (!parsed.success) {
|
|
@@ -35193,7 +35746,7 @@ async function readManifestFromSummary(summary) {
|
|
|
35193
35746
|
function webhookSignature(body, timestamp2) {
|
|
35194
35747
|
const secret2 = process.env.MCP_SCRAPER_WEBHOOK_SECRET?.trim();
|
|
35195
35748
|
if (!secret2) return null;
|
|
35196
|
-
return (0,
|
|
35749
|
+
return (0, import_node_crypto18.createHmac)("sha256", secret2).update(`${timestamp2}.${body}`).digest("hex");
|
|
35197
35750
|
}
|
|
35198
35751
|
async function deliverWorkflowWebhook(input) {
|
|
35199
35752
|
if (!input.webhookUrl) return;
|
|
@@ -35400,13 +35953,13 @@ async function dispatchDueWorkflowSchedules(apiUrl, limit = 3) {
|
|
|
35400
35953
|
}
|
|
35401
35954
|
return { dispatched: results.length, results };
|
|
35402
35955
|
}
|
|
35403
|
-
var
|
|
35956
|
+
var import_node_crypto18, import_promises12, import_hono18, import_zod36, workflowApp, WorkflowInputSchema, WorkflowIdSchema, CadenceSchema, ScheduleStatusSchema, RunBodySchema, ScheduleCreateSchema, SchedulePatchSchema, TERMINAL_RUN_STATUSES;
|
|
35404
35957
|
var init_workflow_routes = __esm({
|
|
35405
35958
|
"src/api/workflow-routes.ts"() {
|
|
35406
35959
|
"use strict";
|
|
35407
|
-
|
|
35960
|
+
import_node_crypto18 = require("crypto");
|
|
35408
35961
|
import_promises12 = require("fs/promises");
|
|
35409
|
-
|
|
35962
|
+
import_hono18 = require("hono");
|
|
35410
35963
|
import_zod36 = require("zod");
|
|
35411
35964
|
init_artifact_writer();
|
|
35412
35965
|
init_registry2();
|
|
@@ -35414,7 +35967,7 @@ var init_workflow_routes = __esm({
|
|
|
35414
35967
|
init_db();
|
|
35415
35968
|
init_url_utils();
|
|
35416
35969
|
init_concurrency_gates();
|
|
35417
|
-
workflowApp = new
|
|
35970
|
+
workflowApp = new import_hono18.Hono();
|
|
35418
35971
|
WorkflowInputSchema = import_zod36.z.record(import_zod36.z.unknown()).default({});
|
|
35419
35972
|
WorkflowIdSchema = import_zod36.z.string().min(1);
|
|
35420
35973
|
CadenceSchema = import_zod36.z.enum(["daily", "weekly", "monthly"]);
|
|
@@ -35685,7 +36238,7 @@ var init_workflow_routes = __esm({
|
|
|
35685
36238
|
// src/serp-intelligence/page-snapshot-extractor.ts
|
|
35686
36239
|
function sha256(value) {
|
|
35687
36240
|
if (!value) return null;
|
|
35688
|
-
return (0,
|
|
36241
|
+
return (0, import_node_crypto19.createHash)("sha256").update(value).digest("hex");
|
|
35689
36242
|
}
|
|
35690
36243
|
function countWords(markdown) {
|
|
35691
36244
|
const matches = markdown.trim().match(/\b[\p{L}\p{N}][\p{L}\p{N}'-]*\b/gu);
|
|
@@ -35985,11 +36538,11 @@ async function capturePageSnapshots(targets, options = {}) {
|
|
|
35985
36538
|
}
|
|
35986
36539
|
};
|
|
35987
36540
|
}
|
|
35988
|
-
var
|
|
36541
|
+
var import_node_crypto19, import_p_limit5, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_CONCURRENCY, DEFAULT_MAX_CONTENT_CHARS;
|
|
35989
36542
|
var init_page_snapshot_extractor = __esm({
|
|
35990
36543
|
"src/serp-intelligence/page-snapshot-extractor.ts"() {
|
|
35991
36544
|
"use strict";
|
|
35992
|
-
|
|
36545
|
+
import_node_crypto19 = require("crypto");
|
|
35993
36546
|
import_p_limit5 = __toESM(require("p-limit"), 1);
|
|
35994
36547
|
init_kpo_extractor();
|
|
35995
36548
|
init_url_utils();
|
|
@@ -36596,21 +37149,21 @@ async function logRequestEventBestEffort(input) {
|
|
|
36596
37149
|
}
|
|
36597
37150
|
}
|
|
36598
37151
|
function captureBillingKeys(userId, suppliedKey, body) {
|
|
36599
|
-
const responseKey = suppliedKey?.trim() || (0,
|
|
36600
|
-
const requestFingerprint2 = (0,
|
|
36601
|
-
const keyDigest = (0,
|
|
37152
|
+
const responseKey = suppliedKey?.trim() || (0, import_node_crypto20.randomUUID)();
|
|
37153
|
+
const requestFingerprint2 = (0, import_node_crypto20.createHash)("sha256").update(JSON.stringify(body)).digest("hex");
|
|
37154
|
+
const keyDigest = (0, import_node_crypto20.createHash)("sha256").update(String(userId)).update("\0").update(responseKey).digest("hex");
|
|
36602
37155
|
return {
|
|
36603
37156
|
responseKey,
|
|
36604
37157
|
debitKey: `serp-capture:${userId}:${keyDigest}`,
|
|
36605
37158
|
debitDescription: `${body.query} [request:${requestFingerprint2}]`
|
|
36606
37159
|
};
|
|
36607
37160
|
}
|
|
36608
|
-
var
|
|
37161
|
+
var import_hono19, import_node_crypto20, SERP_INTELLIGENCE_RATE_LIMIT, SERP_INTELLIGENCE_RATE_WINDOW_SECONDS, POST_CAPTURE_ROUTE_LABEL, POST_PAGE_SNAPSHOTS_ROUTE_LABEL, SERP_CAPTURE_BILLING_SOURCE, serpIntelligenceApp;
|
|
36609
37162
|
var init_serp_intelligence_routes = __esm({
|
|
36610
37163
|
"src/api/serp-intelligence-routes.ts"() {
|
|
36611
37164
|
"use strict";
|
|
36612
|
-
|
|
36613
|
-
|
|
37165
|
+
import_hono19 = require("hono");
|
|
37166
|
+
import_node_crypto20 = require("crypto");
|
|
36614
37167
|
init_browser_service_env();
|
|
36615
37168
|
init_page_snapshot_extractor();
|
|
36616
37169
|
init_serp_capture_service();
|
|
@@ -36625,7 +37178,7 @@ var init_serp_intelligence_routes = __esm({
|
|
|
36625
37178
|
POST_CAPTURE_ROUTE_LABEL = "POST /capture";
|
|
36626
37179
|
POST_PAGE_SNAPSHOTS_ROUTE_LABEL = "POST /page-snapshots";
|
|
36627
37180
|
SERP_CAPTURE_BILLING_SOURCE = "serp_intelligence_capture";
|
|
36628
|
-
serpIntelligenceApp = new
|
|
37181
|
+
serpIntelligenceApp = new import_hono19.Hono();
|
|
36629
37182
|
serpIntelligenceApp.use("*", createApiKeyAuth());
|
|
36630
37183
|
serpIntelligenceApp.post("/capture", async (c) => {
|
|
36631
37184
|
void POST_CAPTURE_ROUTE_LABEL;
|
|
@@ -36847,7 +37400,7 @@ var PACKAGE_VERSION;
|
|
|
36847
37400
|
var init_version = __esm({
|
|
36848
37401
|
"src/version.ts"() {
|
|
36849
37402
|
"use strict";
|
|
36850
|
-
PACKAGE_VERSION = "0.
|
|
37403
|
+
PACKAGE_VERSION = "0.37.0";
|
|
36851
37404
|
}
|
|
36852
37405
|
});
|
|
36853
37406
|
|
|
@@ -39372,7 +39925,7 @@ var init_rank_tracker_blueprint = __esm({
|
|
|
39372
39925
|
|
|
39373
39926
|
// src/mcp/paa-mcp-server.ts
|
|
39374
39927
|
function hashOwnerId(callerKey) {
|
|
39375
|
-
return (0,
|
|
39928
|
+
return (0, import_node_crypto21.createHash)("sha256").update(callerKey).digest("hex").slice(0, 24);
|
|
39376
39929
|
}
|
|
39377
39930
|
function liveWebToolAnnotations(title) {
|
|
39378
39931
|
return {
|
|
@@ -39865,14 +40418,14 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
39865
40418
|
annotations: { title: "Set Scheduled Action Connections", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
39866
40419
|
}, async (input) => executor.setScheduledActionConnections(input));
|
|
39867
40420
|
}
|
|
39868
|
-
var import_mcp, import_node_fs10, import_node_path14,
|
|
40421
|
+
var import_mcp, import_node_fs10, import_node_path14, import_node_crypto21;
|
|
39869
40422
|
var init_paa_mcp_server = __esm({
|
|
39870
40423
|
"src/mcp/paa-mcp-server.ts"() {
|
|
39871
40424
|
"use strict";
|
|
39872
40425
|
import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
39873
40426
|
import_node_fs10 = require("fs");
|
|
39874
40427
|
import_node_path14 = require("path");
|
|
39875
|
-
|
|
40428
|
+
import_node_crypto21 = require("crypto");
|
|
39876
40429
|
init_version();
|
|
39877
40430
|
init_mcp_response_formatter();
|
|
39878
40431
|
init_server_instructions();
|
|
@@ -39942,11 +40495,11 @@ function withDefaultHostedProfile(input) {
|
|
|
39942
40495
|
...typeof saveProfileChanges === "boolean" ? { saveProfileChanges } : {}
|
|
39943
40496
|
};
|
|
39944
40497
|
}
|
|
39945
|
-
var
|
|
40498
|
+
var import_node_crypto22, HttpMcpToolExecutor;
|
|
39946
40499
|
var init_http_mcp_tool_executor = __esm({
|
|
39947
40500
|
"src/mcp/http-mcp-tool-executor.ts"() {
|
|
39948
40501
|
"use strict";
|
|
39949
|
-
|
|
40502
|
+
import_node_crypto22 = require("crypto");
|
|
39950
40503
|
init_harvest_timeout();
|
|
39951
40504
|
init_browser_service_env();
|
|
39952
40505
|
HttpMcpToolExecutor = class {
|
|
@@ -40006,13 +40559,13 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
40006
40559
|
}
|
|
40007
40560
|
}
|
|
40008
40561
|
async callConnectedMutation(path6, body, timeoutMs = this.timeoutMs) {
|
|
40009
|
-
const fingerprint = (0,
|
|
40562
|
+
const fingerprint = (0, import_node_crypto22.createHash)("sha256").update("POST").update("\0").update(path6).update("\0").update(JSON.stringify(body)).digest("hex");
|
|
40010
40563
|
const now = Date.now();
|
|
40011
40564
|
for (const [pendingFingerprint, pendingEntry] of this.pendingConnectedMutationKeys) {
|
|
40012
40565
|
if (pendingEntry.expiresAt <= now) this.pendingConnectedMutationKeys.delete(pendingFingerprint);
|
|
40013
40566
|
}
|
|
40014
40567
|
const pending = this.pendingConnectedMutationKeys.get(fingerprint);
|
|
40015
|
-
const idempotencyKey2 = pending && pending.expiresAt > now ? pending.key : (0,
|
|
40568
|
+
const idempotencyKey2 = pending && pending.expiresAt > now ? pending.key : (0, import_node_crypto22.randomUUID)();
|
|
40016
40569
|
this.pendingConnectedMutationKeys.set(fingerprint, {
|
|
40017
40570
|
key: idempotencyKey2,
|
|
40018
40571
|
expiresAt: now + 15 * 6e4
|
|
@@ -40026,13 +40579,13 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
40026
40579
|
return result;
|
|
40027
40580
|
}
|
|
40028
40581
|
async callDirectoryWorkflowStart(body, explicitIdempotencyKey) {
|
|
40029
|
-
const idempotencyKey2 = `mcp-directory-${(0,
|
|
40582
|
+
const idempotencyKey2 = `mcp-directory-${(0, import_node_crypto22.createHash)("sha256").update(explicitIdempotencyKey).digest("hex")}`;
|
|
40030
40583
|
return this.call("/directory/run", body, this.timeoutMs, "POST", {
|
|
40031
40584
|
"Idempotency-Key": idempotencyKey2
|
|
40032
40585
|
});
|
|
40033
40586
|
}
|
|
40034
40587
|
async callSiteExtractStart(toolName, body, explicitIdempotencyKey) {
|
|
40035
|
-
const idempotencyKey2 = `mcp-site-${(0,
|
|
40588
|
+
const idempotencyKey2 = `mcp-site-${(0, import_node_crypto22.createHash)("sha256").update(toolName).update("\0").update(explicitIdempotencyKey).digest("hex")}`;
|
|
40036
40589
|
return this.call("/extract-site", body, this.timeoutMs, "POST", {
|
|
40037
40590
|
"Idempotency-Key": idempotencyKey2
|
|
40038
40591
|
});
|
|
@@ -40293,13 +40846,13 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
40293
40846
|
}, void 0, "PUT");
|
|
40294
40847
|
}
|
|
40295
40848
|
async captureSerpSnapshot(input) {
|
|
40296
|
-
const fingerprint = (0,
|
|
40849
|
+
const fingerprint = (0, import_node_crypto22.createHash)("sha256").update(JSON.stringify(input)).digest("hex");
|
|
40297
40850
|
const now = Date.now();
|
|
40298
40851
|
for (const [pendingFingerprint, pendingEntry] of this.pendingSerpCaptureBillingKeys) {
|
|
40299
40852
|
if (pendingEntry.expiresAt <= now) this.pendingSerpCaptureBillingKeys.delete(pendingFingerprint);
|
|
40300
40853
|
}
|
|
40301
40854
|
const pending = this.pendingSerpCaptureBillingKeys.get(fingerprint);
|
|
40302
|
-
const idempotencyKey2 = pending && pending.expiresAt > now ? pending.key : (0,
|
|
40855
|
+
const idempotencyKey2 = pending && pending.expiresAt > now ? pending.key : (0, import_node_crypto22.randomUUID)();
|
|
40303
40856
|
this.pendingSerpCaptureBillingKeys.set(fingerprint, {
|
|
40304
40857
|
key: idempotencyKey2,
|
|
40305
40858
|
expiresAt: now + 15 * 6e4
|
|
@@ -41930,7 +42483,7 @@ var init_browser_agent_mcp_server = __esm({
|
|
|
41930
42483
|
});
|
|
41931
42484
|
|
|
41932
42485
|
// src/mcp/memory-tool-schemas.ts
|
|
41933
|
-
var import_zod40, AcceptShareSchema, ApproveSenderSchema, DeclineShareSchema, GetChatLinkSchema, GetVaultAppLinkSchema, InboxSettingsSchema, InviteAccountSchema, issueKeyTool_scopeShape, IssueKeySchema, ListApprovedSendersSchema, ListKeysSchema, NoteInboxSchema, RemoveApprovedSenderSchema, RevokeChatLinkSchema, RevokeKeySchema, RevokeShareSchema, RevokeVaultAppLinkSchema, SetAgentIdentitySchema, SetScopeSchema, ShareNoteSchema, ShareVaultSchema, SwapVaultSchema, SwitchAccountSchema, UnlinkShareSchema, memoryCaptureTool_notePropsSchema, MemoryCaptureSchema, MemoryQuestionsSchema, PrepareMemoryWriteSchema, validateMemoryWriteTool_notePropsSchema, ValidateMemoryWriteSchema, CreateChannelSchema, GetMessageNoteSchema, ListChannelMembersSchema, ListChannelMessagesSchema, MyMentionsSchema, PollChannelSchema, PostMessageSchema, ReactMessageSchema, RemoveChannelMemberSchema, ReplyMessageSchema, factHistoryTool_entryShape, FactHistorySchema, recordFactTool_factShape, RecordFactSchema, NoteBacklinksSchema, GraphPathSchema, GraphUniverseSchema, LibraryIngestSchema, bulkDeleteNotesTool_FilterSchema, BulkDeleteNotesSchema, DeleteNoteSchema, ExportSchema, getTool_notePropsSchema, GetSchema, ListSchema, putTool_notePropsSchema, PutSchema, searchTool_primitiveValue, SearchSchema, SuggestSchema, UploadSchema, TemporalRecallSchema, CreateScheduledActionSchema, DeleteScheduledActionSchema, GetScheduleLinkSchema, GetScheduleStatusSchema, ListScheduledActionsSchema, PauseScheduledActionSchema, ProposeScheduledActionSchema, ResumeScheduledActionSchema, RevokeScheduleLinkSchema, SetScheduleDefaultsSchema, SetScheduleEntitlementSchema, CostUsageSchema, StorageUsageSchema, CreateTableSchema, deleteTableRowsTool_FilterSchema, DeleteTableRowsSchema, DescribeTableSchema, DropTableSchema, InsertTableRowsSchema, ListTablesSchema, queryTableTool_FilterSchema, QueryTableSchema, ListTagsSchema, ResolveTagsSchema, UpsertTagSchema, AddVaultSchema, CreateSecureVaultSchema, DeleteVaultSchema, GetVaultContractSchema, ListSharedWithMeSchema, ListVaultsSchema, ProvisionDefaultsSchema, RouteMemorySchema, VideoAnalyzeStartSchema, VideoAnalyzeStatusSchema, CreateWebhookSchema, ListWebhooksSchema, RevokeWebhookSchema, MEMORY_TOOL_SCHEMAS;
|
|
42486
|
+
var import_zod40, AcceptShareSchema, ApproveSenderSchema, DeclineShareSchema, GetChatLinkSchema, GetVaultAppLinkSchema, InboxSettingsSchema, InviteAccountSchema, issueKeyTool_scopeShape, IssueKeySchema, ListApprovedSendersSchema, ListKeysSchema, NoteInboxSchema, RemoveApprovedSenderSchema, RevokeChatLinkSchema, RevokeKeySchema, RevokeShareSchema, RevokeVaultAppLinkSchema, SetAgentIdentitySchema, SetScopeSchema, ShareNoteSchema, ShareVaultSchema, SwapVaultSchema, SwitchAccountSchema, UnlinkShareSchema, memoryCaptureTool_notePropsSchema, MemoryCaptureSchema, MemoryQuestionsSchema, PrepareMemoryWriteSchema, validateMemoryWriteTool_notePropsSchema, ValidateMemoryWriteSchema, CreateChannelSchema, GetMessageNoteSchema, ListChannelMembersSchema, ListChannelMessagesSchema, MyMentionsSchema, PollChannelSchema, PostMessageSchema, ReactMessageSchema, RemoveChannelMemberSchema, ReplyMessageSchema, factHistoryTool_entryShape, FactHistorySchema, recordFactTool_factShape, RecordFactSchema, NoteBacklinksSchema, GraphPathSchema, GraphUniverseSchema, LibraryIngestSchema, bulkDeleteNotesTool_FilterSchema, BulkDeleteNotesSchema, DeleteNoteSchema, ExportSchema, getTool_notePropsSchema, GetSchema, ListSchema, putTool_notePropsSchema, PutSchema, searchTool_primitiveValue, SearchSchema, SuggestSchema, UploadSchema, TemporalRecallSchema, CreateScheduledActionSchema, DeleteScheduledActionSchema, GetScheduleLinkSchema, GetScheduleStatusSchema, ListScheduledActionsSchema, PauseScheduledActionSchema, ProposeScheduledActionSchema, ResumeScheduledActionSchema, RevokeScheduleLinkSchema, SetScheduleDefaultsSchema, SetScheduleEntitlementSchema, CostUsageSchema, StorageUsageSchema, CreateTableSchema, deleteTableRowsTool_FilterSchema, DeleteTableRowsSchema, DescribeTableSchema, DropTableSchema, InsertTableRowsSchema, ListTablesSchema, queryTableTool_FilterSchema, QueryTableSchema, ListTagsSchema, MergeTagsSchema, ResolveTagsSchema, UpsertTagSchema, AddVaultSchema, CreateSecureVaultSchema, DeleteVaultSchema, GetVaultContractSchema, ListSharedWithMeSchema, ListVaultsSchema, ProvisionDefaultsSchema, RouteMemorySchema, VideoAnalyzeStartSchema, VideoAnalyzeStatusSchema, CreateWebhookSchema, ListWebhooksSchema, RevokeWebhookSchema, MEMORY_TOOL_SCHEMAS;
|
|
41934
42487
|
var init_memory_tool_schemas = __esm({
|
|
41935
42488
|
"src/mcp/memory-tool-schemas.ts"() {
|
|
41936
42489
|
"use strict";
|
|
@@ -42508,14 +43061,20 @@ var init_memory_tool_schemas = __esm({
|
|
|
42508
43061
|
content: import_zod40.z.string().min(1),
|
|
42509
43062
|
props: memoryCaptureTool_notePropsSchema,
|
|
42510
43063
|
baseRevision: import_zod40.z.number().optional(),
|
|
42511
|
-
tagDecisions: import_zod40.z.array(import_zod40.z.object({ tag: import_zod40.z.string().min(1), central: import_zod40.z.boolean(), reusable: import_zod40.z.boolean(), description: import_zod40.z.string().optional() })).max(8).optional().describe("Required justification for any tag that does not already exist.
|
|
43064
|
+
tagDecisions: import_zod40.z.array(import_zod40.z.object({ tag: import_zod40.z.string().min(1), central: import_zod40.z.boolean(), reusable: import_zod40.z.boolean(), description: import_zod40.z.string().optional(), acceptCanonical: import_zod40.z.string().optional().describe("Reuse this existing tag instead of the proposed one, confirming a candidate returned by an earlier review. The proposed spelling is recorded as its alias.") })).max(8).optional().describe("Required justification for any tag that does not already exist. Tags resolve against the account's existing vocabulary; new tags require a one-line description.")
|
|
42512
43065
|
},
|
|
42513
43066
|
output: {
|
|
42514
43067
|
ok: import_zod40.z.boolean(),
|
|
42515
43068
|
valid: import_zod40.z.boolean().optional(),
|
|
42516
43069
|
errors: import_zod40.z.array(import_zod40.z.string()).optional(),
|
|
42517
43070
|
warnings: import_zod40.z.array(import_zod40.z.string()).optional(),
|
|
42518
|
-
tagResolutions: import_zod40.z.array(import_zod40.z.object({
|
|
43071
|
+
tagResolutions: import_zod40.z.array(import_zod40.z.object({
|
|
43072
|
+
candidate: import_zod40.z.string(),
|
|
43073
|
+
action: import_zod40.z.enum(["reuse", "review", "create", "omit"]),
|
|
43074
|
+
tag: import_zod40.z.string().optional(),
|
|
43075
|
+
candidates: import_zod40.z.array(import_zod40.z.object({ tag: import_zod40.z.string(), matchedVia: import_zod40.z.string(), score: import_zod40.z.number(), description: import_zod40.z.string().nullable() })).optional(),
|
|
43076
|
+
reason: import_zod40.z.string()
|
|
43077
|
+
})).optional(),
|
|
42519
43078
|
note: import_zod40.z.object({ path: import_zod40.z.string(), title: import_zod40.z.string(), updatedAt: import_zod40.z.string(), revision: import_zod40.z.number() }).optional(),
|
|
42520
43079
|
indexed: import_zod40.z.number().optional(),
|
|
42521
43080
|
verified: import_zod40.z.object({ contentBytes: import_zod40.z.number(), propsPersisted: import_zod40.z.boolean(), revision: import_zod40.z.number() }).optional(),
|
|
@@ -43027,7 +43586,8 @@ var init_memory_tool_schemas = __esm({
|
|
|
43027
43586
|
source: import_zod40.z.string().min(1).describe("Provenance of the content, e.g. a URL or tool name. Must be non-empty."),
|
|
43028
43587
|
capturedAt: import_zod40.z.string().optional().describe("ISO-8601 capture timestamp. Optional; defaults to now. Also seeds the deterministic storage path."),
|
|
43029
43588
|
summary: import_zod40.z.string().optional().describe("Retrieval-ready source summary. Optional; a provenance summary is generated when omitted."),
|
|
43030
|
-
tags: import_zod40.z.array(import_zod40.z.string()).max(8).optional().describe("Reviewed canonical tags.
|
|
43589
|
+
tags: import_zod40.z.array(import_zod40.z.string()).max(8).optional().describe("Reviewed canonical tags. Tags resolve against the account's existing vocabulary; new tags require a one-line description. When omitted, only deterministic source-provenance tags are recorded."),
|
|
43590
|
+
tagDescriptions: import_zod40.z.record(import_zod40.z.string()).optional().describe("One-line meaning for any supplied tag that is new to the account, keyed by tag."),
|
|
43031
43591
|
related: import_zod40.z.array(import_zod40.z.string()).optional().describe("Reviewed same-vault Library note paths."),
|
|
43032
43592
|
relatedVaultNotes: import_zod40.z.array(import_zod40.z.string()).optional().describe("Reviewed cross-vault references in Vault::path.md form."),
|
|
43033
43593
|
localVaultPath: import_zod40.z.string().optional().describe("Filesystem root to also mirror the item to. Optional; falls back to MEMORY_LOCAL_VAULT_ROOT env when set.")
|
|
@@ -43274,7 +43834,8 @@ var init_memory_tool_schemas = __esm({
|
|
|
43274
43834
|
title: import_zod40.z.string().optional().describe("Optional human-readable title; defaults are derived from the path when omitted."),
|
|
43275
43835
|
content: import_zod40.z.string().min(1).describe("The full note body to store and index for semantic search. Must be non-empty."),
|
|
43276
43836
|
props: putTool_notePropsSchema.optional().describe("Obsidian note primitives plus vault-specific template fields. On edits, supplied fields patch the stored props instead of replacing the whole object; pass an empty array to deliberately clear a link list. Type/domain/folder also steer routing when no vault is given."),
|
|
43277
|
-
baseRevision: import_zod40.z.number().optional().describe("Revision the edit is based on (from a prior get/put). When provided, the write only applies if the note is still at this revision; otherwise it is rejected as a conflict instead of silently overwriting a concurrent edit. Omit for last-write-wins (fine for solo notes).")
|
|
43837
|
+
baseRevision: import_zod40.z.number().optional().describe("Revision the edit is based on (from a prior get/put). When provided, the write only applies if the note is still at this revision; otherwise it is rejected as a conflict instead of silently overwriting a concurrent edit. Omit for last-write-wins (fine for solo notes)."),
|
|
43838
|
+
tagDescriptions: import_zod40.z.record(import_zod40.z.string()).optional().describe("One-line meaning for any tag in props.tags that is new to the account, keyed by tag. Tags resolve against the account's existing vocabulary; new tags require a one-line description.")
|
|
43278
43839
|
},
|
|
43279
43840
|
output: {
|
|
43280
43841
|
ok: import_zod40.z.boolean().describe("True when the note was stored; false on auth/scope error, empty content, or a revision conflict."),
|
|
@@ -43953,16 +44514,51 @@ var init_memory_tool_schemas = __esm({
|
|
|
43953
44514
|
},
|
|
43954
44515
|
annotations: { title: "List Memory Tags", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
43955
44516
|
};
|
|
44517
|
+
MergeTagsSchema = {
|
|
44518
|
+
id: "merge-memory-tags",
|
|
44519
|
+
upstreamName: "mergeTagsTool",
|
|
44520
|
+
description: 'Collapse a duplicate tag into the canonical one across the whole account: every note using "from" is retagged to "into", "from" is recorded as an alias of "into", and the duplicate is removed from the vocabulary. Use when list-memory-tags shows two spellings of one concept. Irreversible; requires write scope.',
|
|
44521
|
+
input: {
|
|
44522
|
+
from: import_zod40.z.string().min(1).describe("The duplicate tag to retire."),
|
|
44523
|
+
into: import_zod40.z.string().min(1).describe('The canonical tag to keep. Every note using "from" is retagged to this.')
|
|
44524
|
+
},
|
|
44525
|
+
output: {
|
|
44526
|
+
ok: import_zod40.z.boolean(),
|
|
44527
|
+
from: import_zod40.z.string().optional(),
|
|
44528
|
+
into: import_zod40.z.string().optional(),
|
|
44529
|
+
notesRetagged: import_zod40.z.number().optional(),
|
|
44530
|
+
aliases: import_zod40.z.array(import_zod40.z.string()).optional(),
|
|
44531
|
+
descriptionCopied: import_zod40.z.boolean().optional(),
|
|
44532
|
+
error: import_zod40.z.string().optional()
|
|
44533
|
+
},
|
|
44534
|
+
annotations: { title: "Merge Memory Tags", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
|
|
44535
|
+
};
|
|
43956
44536
|
ResolveTagsSchema = {
|
|
43957
44537
|
id: "resolve-memory-tags",
|
|
43958
44538
|
upstreamName: "resolveTagsTool",
|
|
43959
|
-
description: "Resolve proposed concepts against the live tag vocabulary. Always inspect the complete vocabulary with list-memory-tags first. Returns reuse, create, or omit
|
|
44539
|
+
description: "Resolve proposed concepts against the live tag vocabulary. Always inspect the complete vocabulary with list-memory-tags first. Returns reuse, review, create, or omit: spelling and singular/plural variants resolve to the canonical tag silently, while close and semantically related tags come back as ranked candidates for you to choose from. A new tag is appropriate only when no equivalent exists and the concept is central and reusable.",
|
|
43960
44540
|
input: {
|
|
43961
|
-
candidates: import_zod40.z.array(import_zod40.z.object({ tag: import_zod40.z.string().min(1), central: import_zod40.z.boolean().optional(), reusable: import_zod40.z.boolean().optional(), description: import_zod40.z.string().optional() })).min(1).max(20)
|
|
44541
|
+
candidates: import_zod40.z.array(import_zod40.z.object({ tag: import_zod40.z.string().min(1), central: import_zod40.z.boolean().optional(), reusable: import_zod40.z.boolean().optional(), description: import_zod40.z.string().optional() })).min(1).max(20),
|
|
44542
|
+
accept: import_zod40.z.record(import_zod40.z.string()).optional().describe("Confirm a candidate returned by an earlier review, as {proposedTag: canonicalTag}. The proposed spelling is recorded as an alias of the canonical tag so the same judgement is never re-litigated.")
|
|
43962
44543
|
},
|
|
43963
44544
|
output: {
|
|
43964
44545
|
ok: import_zod40.z.boolean(),
|
|
43965
|
-
resolutions: import_zod40.z.array(import_zod40.z.object({
|
|
44546
|
+
resolutions: import_zod40.z.array(import_zod40.z.object({
|
|
44547
|
+
candidate: import_zod40.z.string(),
|
|
44548
|
+
normalized: import_zod40.z.string(),
|
|
44549
|
+
action: import_zod40.z.enum(["reuse", "review", "create", "omit"]),
|
|
44550
|
+
tag: import_zod40.z.string().optional(),
|
|
44551
|
+
matchedBy: import_zod40.z.enum(["exact", "alias", "near"]).optional(),
|
|
44552
|
+
matchedVia: import_zod40.z.enum(["key", "alias", "stem", "trigram", "embedding"]).optional(),
|
|
44553
|
+
score: import_zod40.z.number().optional(),
|
|
44554
|
+
candidates: import_zod40.z.array(import_zod40.z.object({
|
|
44555
|
+
tag: import_zod40.z.string(),
|
|
44556
|
+
matchedVia: import_zod40.z.enum(["key", "alias", "stem", "trigram", "embedding"]),
|
|
44557
|
+
score: import_zod40.z.number(),
|
|
44558
|
+
description: import_zod40.z.string().nullable()
|
|
44559
|
+
})).optional().describe("Ranked existing tags to choose from when action is review. Nothing is merged automatically."),
|
|
44560
|
+
reason: import_zod40.z.string()
|
|
44561
|
+
})).optional(),
|
|
43966
44562
|
error: import_zod40.z.string().optional()
|
|
43967
44563
|
},
|
|
43968
44564
|
annotations: { title: "Resolve Memory Tags", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
@@ -44345,6 +44941,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
44345
44941
|
ListTablesSchema,
|
|
44346
44942
|
QueryTableSchema,
|
|
44347
44943
|
ListTagsSchema,
|
|
44944
|
+
MergeTagsSchema,
|
|
44348
44945
|
ResolveTagsSchema,
|
|
44349
44946
|
UpsertTagSchema,
|
|
44350
44947
|
AddVaultSchema,
|
|
@@ -44811,8 +45408,12 @@ function registerWriteCutovers() {
|
|
|
44811
45408
|
const result = await import_upsert_tag.upsertTagTool.execute({ ...input, apiKey }, {});
|
|
44812
45409
|
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
44813
45410
|
});
|
|
45411
|
+
registerCutover("mergeTagsTool", async (input, apiKey) => {
|
|
45412
|
+
const result = await import_merge_tags.mergeTagsTool.execute({ ...input, apiKey }, {});
|
|
45413
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
45414
|
+
});
|
|
44814
45415
|
}
|
|
44815
|
-
var import_accept_share, import_approve_sender, import_decline_share, import_inbox_settings, import_remove_approved_sender, import_revoke_share, import_set_agent_identity, import_share_note, import_share_vault, import_swap_vault, import_switch_account, import_unlink_share, import_memory_questions, import_create_channel, import_list_channel_messages, import_poll_channel, import_post_message, import_react_message, import_remove_channel_member, import_reply_message, import_record_fact, import_library_ingest, import_delete_note, import_put, import_upload, import_delete_scheduled_action, import_pause_scheduled_action, import_resume_scheduled_action, import_table_create, import_table_delete_rows, import_table_drop, import_table_insert_rows, import_add_vault, import_delete_vault, import_memory_capture, import_upsert_tag, registered2;
|
|
45416
|
+
var import_accept_share, import_approve_sender, import_decline_share, import_inbox_settings, import_remove_approved_sender, import_revoke_share, import_set_agent_identity, import_share_note, import_share_vault, import_swap_vault, import_switch_account, import_unlink_share, import_memory_questions, import_create_channel, import_list_channel_messages, import_poll_channel, import_post_message, import_react_message, import_remove_channel_member, import_reply_message, import_record_fact, import_library_ingest, import_delete_note, import_put, import_upload, import_delete_scheduled_action, import_pause_scheduled_action, import_resume_scheduled_action, import_table_create, import_table_delete_rows, import_table_drop, import_table_insert_rows, import_add_vault, import_delete_vault, import_memory_capture, import_upsert_tag, import_merge_tags, registered2;
|
|
44816
45417
|
var init_writes = __esm({
|
|
44817
45418
|
"src/mcp/memory-cutover/writes.ts"() {
|
|
44818
45419
|
"use strict";
|
|
@@ -44853,6 +45454,7 @@ var init_writes = __esm({
|
|
|
44853
45454
|
import_delete_vault = require("mcpscraper-memory-tools/tools/vaults/delete-vault");
|
|
44854
45455
|
import_memory_capture = require("mcpscraper-memory-tools/tools/capture/memory-capture");
|
|
44855
45456
|
import_upsert_tag = require("mcpscraper-memory-tools/tools/tags/upsert-tag");
|
|
45457
|
+
import_merge_tags = require("mcpscraper-memory-tools/tools/tags/merge-tags");
|
|
44856
45458
|
registered2 = false;
|
|
44857
45459
|
}
|
|
44858
45460
|
});
|
|
@@ -45085,11 +45687,11 @@ async function requireMcpCallerKey(c) {
|
|
|
45085
45687
|
if (!user) return mcpAuthError();
|
|
45086
45688
|
return { key: callerKey, user };
|
|
45087
45689
|
}
|
|
45088
|
-
var
|
|
45690
|
+
var import_hono20, import_webStandardStreamableHttp, mcpApp;
|
|
45089
45691
|
var init_mcp_routes = __esm({
|
|
45090
45692
|
"src/mcp/mcp-routes.ts"() {
|
|
45091
45693
|
"use strict";
|
|
45092
|
-
|
|
45694
|
+
import_hono20 = require("hono");
|
|
45093
45695
|
import_webStandardStreamableHttp = require("@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js");
|
|
45094
45696
|
init_paa_mcp_server();
|
|
45095
45697
|
init_http_mcp_tool_executor();
|
|
@@ -45111,7 +45713,7 @@ var init_mcp_routes = __esm({
|
|
|
45111
45713
|
registerCrossServiceCutovers();
|
|
45112
45714
|
registerVideoCutovers();
|
|
45113
45715
|
configureReportSaving(false);
|
|
45114
|
-
mcpApp = new
|
|
45716
|
+
mcpApp = new import_hono20.Hono();
|
|
45115
45717
|
mcpApp.all("/", async (c) => {
|
|
45116
45718
|
try {
|
|
45117
45719
|
const keyOrError = await requireMcpCallerKey(c);
|
|
@@ -45267,7 +45869,7 @@ async function runBrowserAgentMigration() {
|
|
|
45267
45869
|
}
|
|
45268
45870
|
async function createExtensionRow(input) {
|
|
45269
45871
|
const db = getDb();
|
|
45270
|
-
const id = `bext_${(0,
|
|
45872
|
+
const id = `bext_${(0, import_node_crypto23.randomUUID)().replace(/-/g, "").slice(0, 20)}`;
|
|
45271
45873
|
await db.execute({
|
|
45272
45874
|
sql: `INSERT INTO browser_agent_extensions (id, user_id, name, backend_id, backend_name, source, source_url, size_bytes)
|
|
45273
45875
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
@@ -45302,7 +45904,7 @@ async function deleteExtensionRow(userId, name) {
|
|
|
45302
45904
|
}
|
|
45303
45905
|
async function createAuthConnectionRow(input) {
|
|
45304
45906
|
const db = getDb();
|
|
45305
|
-
const connectionId = `authc_${(0,
|
|
45907
|
+
const connectionId = `authc_${(0, import_node_crypto23.randomUUID)().replace(/-/g, "").slice(0, 20)}`;
|
|
45306
45908
|
await db.execute({
|
|
45307
45909
|
sql: `INSERT INTO browser_auth_connections (connection_id, domain, profile, account_email, note, status, browser_agent_session_id)
|
|
45308
45910
|
VALUES (?, ?, ?, ?, ?, 'NEEDS_AUTH', ?)`,
|
|
@@ -45387,7 +45989,7 @@ async function deleteProfileLabel(userId, profile) {
|
|
|
45387
45989
|
}
|
|
45388
45990
|
async function createSessionRow(input) {
|
|
45389
45991
|
const db = getDb();
|
|
45390
|
-
const id = `bas_${(0,
|
|
45992
|
+
const id = `bas_${(0, import_node_crypto23.randomUUID)().replace(/-/g, "").slice(0, 20)}`;
|
|
45391
45993
|
await db.execute({
|
|
45392
45994
|
sql: `INSERT INTO browser_agent_sessions (id, runtime_session_id, live_view_url, cdp_ws_url, status, label, user_id, concurrency_lock_id, last_action_at)
|
|
45393
45995
|
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, datetime('now'))`,
|
|
@@ -45456,7 +46058,7 @@ async function recordAction(input) {
|
|
|
45456
46058
|
sql: `INSERT INTO browser_agent_actions (id, session_id, type, params_json, ok, error)
|
|
45457
46059
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
45458
46060
|
args: [
|
|
45459
|
-
`baa_${(0,
|
|
46061
|
+
`baa_${(0, import_node_crypto23.randomUUID)().replace(/-/g, "").slice(0, 20)}`,
|
|
45460
46062
|
input.sessionId,
|
|
45461
46063
|
input.type,
|
|
45462
46064
|
input.params == null ? null : JSON.stringify(input.params),
|
|
@@ -45496,11 +46098,11 @@ async function listReplayRows(sessionId) {
|
|
|
45496
46098
|
});
|
|
45497
46099
|
return res.rows;
|
|
45498
46100
|
}
|
|
45499
|
-
var
|
|
46101
|
+
var import_node_crypto23, _ready2, _migrationPromise2;
|
|
45500
46102
|
var init_browser_agent_db = __esm({
|
|
45501
46103
|
"src/api/browser-agent-db.ts"() {
|
|
45502
46104
|
"use strict";
|
|
45503
|
-
|
|
46105
|
+
import_node_crypto23 = require("crypto");
|
|
45504
46106
|
init_db();
|
|
45505
46107
|
_ready2 = false;
|
|
45506
46108
|
_migrationPromise2 = null;
|
|
@@ -46755,7 +47357,7 @@ async function loadOpenSession(id, userId) {
|
|
|
46755
47357
|
return row;
|
|
46756
47358
|
}
|
|
46757
47359
|
function buildBrowserAgentRoutes() {
|
|
46758
|
-
const app2 = new
|
|
47360
|
+
const app2 = new import_hono21.Hono();
|
|
46759
47361
|
app2.use("*", async (c, next) => {
|
|
46760
47362
|
await migrateBrowserAgent();
|
|
46761
47363
|
return next();
|
|
@@ -47256,7 +47858,7 @@ function buildBrowserAgentRoutes() {
|
|
|
47256
47858
|
}
|
|
47257
47859
|
const existing = await getExtensionRow(user.id, name);
|
|
47258
47860
|
if (existing) return c.json({ error: `an extension named "${name}" already exists \u2014 delete it first or pick another name` }, 409);
|
|
47259
|
-
const backendName = `u${user.id}_${(0,
|
|
47861
|
+
const backendName = `u${user.id}_${(0, import_node_crypto24.randomUUID)().replace(/-/g, "")}`;
|
|
47260
47862
|
try {
|
|
47261
47863
|
const imported = await importExtensionFromStore(storeUrl, backendName);
|
|
47262
47864
|
const row = await createExtensionRow({
|
|
@@ -47315,12 +47917,12 @@ function buildBrowserAgentRoutes() {
|
|
|
47315
47917
|
});
|
|
47316
47918
|
return app2;
|
|
47317
47919
|
}
|
|
47318
|
-
var
|
|
47920
|
+
var import_node_crypto24, import_hono21, auth, DEFAULT_BROWSER_SESSION_LOCK_TTL_SECONDS, EXTENSION_NAME_RE;
|
|
47319
47921
|
var init_browser_agent_routes = __esm({
|
|
47320
47922
|
"src/api/browser-agent-routes.ts"() {
|
|
47321
47923
|
"use strict";
|
|
47322
|
-
|
|
47323
|
-
|
|
47924
|
+
import_node_crypto24 = require("crypto");
|
|
47925
|
+
import_hono21 = require("hono");
|
|
47324
47926
|
init_api_auth();
|
|
47325
47927
|
init_errors();
|
|
47326
47928
|
init_db();
|
|
@@ -47628,7 +48230,7 @@ function linePriceId(line) {
|
|
|
47628
48230
|
const l = line;
|
|
47629
48231
|
return l?.price?.id ?? l?.pricing?.price_details?.price ?? l?.plan?.id;
|
|
47630
48232
|
}
|
|
47631
|
-
async function
|
|
48233
|
+
async function resolveUser3(customerId, emailFallback) {
|
|
47632
48234
|
let user = await getUserByStripeCustomerId(customerId);
|
|
47633
48235
|
if (user) return user;
|
|
47634
48236
|
if (!emailFallback) return void 0;
|
|
@@ -47636,18 +48238,18 @@ async function resolveUser2(customerId, emailFallback) {
|
|
|
47636
48238
|
if (user) await setStripeCustomerId(user.id, customerId);
|
|
47637
48239
|
return user;
|
|
47638
48240
|
}
|
|
47639
|
-
var import_stripe,
|
|
48241
|
+
var import_stripe, import_hono22, stripe, stripeApp;
|
|
47640
48242
|
var init_stripe_routes = __esm({
|
|
47641
48243
|
"src/api/stripe-routes.ts"() {
|
|
47642
48244
|
"use strict";
|
|
47643
48245
|
import_stripe = __toESM(require("stripe"), 1);
|
|
47644
|
-
|
|
48246
|
+
import_hono22 = require("hono");
|
|
47645
48247
|
init_db();
|
|
47646
48248
|
init_rates();
|
|
47647
48249
|
init_memory();
|
|
47648
48250
|
init_connected_account_billing();
|
|
47649
48251
|
stripe = new import_stripe.default(process.env.STRIPE_SECRET_KEY, { apiVersion: "2026-02-25.clover" });
|
|
47650
|
-
stripeApp = new
|
|
48252
|
+
stripeApp = new import_hono22.Hono();
|
|
47651
48253
|
stripeApp.post("/webhooks", async (c) => {
|
|
47652
48254
|
const sig = c.req.header("stripe-signature");
|
|
47653
48255
|
const body = await c.req.text();
|
|
@@ -47673,7 +48275,7 @@ var init_stripe_routes = __esm({
|
|
|
47673
48275
|
const tierPriceId = liveBasePlanPriceId ?? invoice.lines.data.map(linePriceId).find((id) => id && id in SUBSCRIPTION_TIERS);
|
|
47674
48276
|
const tier = tierPriceId ? SUBSCRIPTION_TIERS[tierPriceId] : void 0;
|
|
47675
48277
|
if (tier) {
|
|
47676
|
-
const user = await
|
|
48278
|
+
const user = await resolveUser3(invoice.customer, invoice.customer_email ?? void 0);
|
|
47677
48279
|
if (user && invoice.id && !await ledgerExistsForStripePI(invoice.id)) {
|
|
47678
48280
|
await creditMc(user.id, tier.credits_mc, LedgerOperation.SUBSCRIPTION, `${tier.label} subscription credits`, invoice.id, { neverExpires: tier.credits_never_expire });
|
|
47679
48281
|
await setSubscriptionTier(user.id, tier.tier, tier.concurrency, subId ?? user.subscription_id);
|
|
@@ -47693,7 +48295,7 @@ var init_stripe_routes = __esm({
|
|
|
47693
48295
|
const priceId = findBasePlanItem(sub)?.price?.id ?? sub.items.data[0]?.price?.id;
|
|
47694
48296
|
if (priceId && priceId in MEMORY_PLANS) {
|
|
47695
48297
|
const mem = MEMORY_PLANS[priceId];
|
|
47696
|
-
const user2 = await
|
|
48298
|
+
const user2 = await resolveUser3(sub.customer, sub.customer_email);
|
|
47697
48299
|
if (user2) {
|
|
47698
48300
|
const live = sub.status === "active" || sub.status === "trialing";
|
|
47699
48301
|
const newMemoryPlan = live ? mem.plan : "free";
|
|
@@ -47775,7 +48377,7 @@ async function getKeys() {
|
|
|
47775
48377
|
const privateKey = await (0, import_jose2.importPKCS8)(pem, "RS256", { extractable: true });
|
|
47776
48378
|
const full = await (0, import_jose2.exportJWK)(privateKey);
|
|
47777
48379
|
const publicJwk = { kty: full.kty, n: full.n, e: full.e };
|
|
47778
|
-
const kid = (0,
|
|
48380
|
+
const kid = (0, import_node_crypto25.createHash)("sha256").update(JSON.stringify({ e: publicJwk.e, kty: publicJwk.kty, n: publicJwk.n })).digest("base64url").slice(0, 16);
|
|
47779
48381
|
publicJwk.kid = kid;
|
|
47780
48382
|
publicJwk.alg = "RS256";
|
|
47781
48383
|
publicJwk.use = "sig";
|
|
@@ -47954,23 +48556,23 @@ async function validateAuthRequest(p) {
|
|
|
47954
48556
|
}
|
|
47955
48557
|
function pkceMatches(verifier, challenge) {
|
|
47956
48558
|
if (!verifier) return false;
|
|
47957
|
-
const computed = (0,
|
|
48559
|
+
const computed = (0, import_node_crypto25.createHash)("sha256").update(verifier).digest("base64url");
|
|
47958
48560
|
return computed === challenge;
|
|
47959
48561
|
}
|
|
47960
48562
|
async function mintAccessToken(identity, scope, plan, audience) {
|
|
47961
48563
|
const { privateKey, kid } = await getKeys();
|
|
47962
|
-
return new import_jose2.SignJWT({ scope, plan }).setProtectedHeader({ alg: "RS256", kid }).setIssuer(ISSUER).setSubject(identity).setAudience(audience).setIssuedAt().setJti((0,
|
|
48564
|
+
return new import_jose2.SignJWT({ scope, plan }).setProtectedHeader({ alg: "RS256", kid }).setIssuer(ISSUER).setSubject(identity).setAudience(audience).setIssuedAt().setJti((0, import_node_crypto25.randomUUID)()).setExpirationTime(`${ACCESS_TTL_SECONDS}s`).sign(privateKey);
|
|
47963
48565
|
}
|
|
47964
48566
|
function tokenErrorResponse(c, error, description, status) {
|
|
47965
48567
|
return c.json({ error, error_description: description }, status);
|
|
47966
48568
|
}
|
|
47967
|
-
var
|
|
48569
|
+
var import_hono23, import_cookie, import_node_crypto25, import_jose2, ISSUER, RESOURCE, SCRAPER_RESOURCE, MEMORY_SCOPES, SCRAPER_SCOPES, SUPPORTED_SCOPES, ACCESS_TTL_SECONDS, REFRESH_TTL_SECONDS, CODE_TTL_SECONDS, ROTATION_GRACE_SECONDS, secureCookies, sessionCookieOptions, cachedKeys, oauthApp;
|
|
47968
48570
|
var init_oauth_routes = __esm({
|
|
47969
48571
|
"src/api/oauth-routes.ts"() {
|
|
47970
48572
|
"use strict";
|
|
47971
|
-
|
|
48573
|
+
import_hono23 = require("hono");
|
|
47972
48574
|
import_cookie = require("hono/cookie");
|
|
47973
|
-
|
|
48575
|
+
import_node_crypto25 = require("crypto");
|
|
47974
48576
|
import_jose2 = require("jose");
|
|
47975
48577
|
init_session();
|
|
47976
48578
|
init_db();
|
|
@@ -47995,7 +48597,7 @@ var init_oauth_routes = __esm({
|
|
|
47995
48597
|
sameSite: "Lax"
|
|
47996
48598
|
};
|
|
47997
48599
|
cachedKeys = null;
|
|
47998
|
-
oauthApp = new
|
|
48600
|
+
oauthApp = new import_hono23.Hono();
|
|
47999
48601
|
oauthApp.use("*", async (c, next) => {
|
|
48000
48602
|
c.header("Access-Control-Allow-Origin", "*");
|
|
48001
48603
|
c.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -48056,7 +48658,7 @@ var init_oauth_routes = __esm({
|
|
|
48056
48658
|
}
|
|
48057
48659
|
}
|
|
48058
48660
|
const clientName = typeof body.client_name === "string" ? body.client_name : null;
|
|
48059
|
-
const clientId = `client_${(0,
|
|
48661
|
+
const clientId = `client_${(0, import_node_crypto25.randomBytes)(16).toString("hex")}`;
|
|
48060
48662
|
await registerClient(clientId, redirectUris, clientName);
|
|
48061
48663
|
console.log("[oauth-dcr] register OK client_id=%s redirect_uris=%s", clientId, JSON.stringify(redirectUris));
|
|
48062
48664
|
return c.json({
|
|
@@ -48109,7 +48711,7 @@ var init_oauth_routes = __esm({
|
|
|
48109
48711
|
if (action === "deny") return redirectWithError(p.redirect_uri, p.state, "access_denied");
|
|
48110
48712
|
if (action !== "approve") return c.text("unsupported action", 400);
|
|
48111
48713
|
const scope = negotiateScope(p.scope, user, p.resource);
|
|
48112
|
-
const code = `code_${(0,
|
|
48714
|
+
const code = `code_${(0, import_node_crypto25.randomBytes)(32).toString("base64url")}`;
|
|
48113
48715
|
const expiresAt = new Date(Date.now() + CODE_TTL_SECONDS * 1e3).toISOString();
|
|
48114
48716
|
await putCode({
|
|
48115
48717
|
code,
|
|
@@ -48148,7 +48750,7 @@ var init_oauth_routes = __esm({
|
|
|
48148
48750
|
const plan = user ? resolvePlan(user) : "free";
|
|
48149
48751
|
const audience = record.resource ?? RESOURCE();
|
|
48150
48752
|
const accessToken = await mintAccessToken(record.identity, record.scope, plan, audience);
|
|
48151
|
-
const refreshToken = `rt_${(0,
|
|
48753
|
+
const refreshToken = `rt_${(0, import_node_crypto25.randomBytes)(40).toString("base64url")}`;
|
|
48152
48754
|
await putRefresh({
|
|
48153
48755
|
refresh_token: refreshToken,
|
|
48154
48756
|
client_id: clientId,
|
|
@@ -48178,7 +48780,7 @@ var init_oauth_routes = __esm({
|
|
|
48178
48780
|
const plan = user ? resolvePlan(user) : "free";
|
|
48179
48781
|
const audience = record.resource ?? RESOURCE();
|
|
48180
48782
|
const accessToken = await mintAccessToken(record.identity, record.scope, plan, audience);
|
|
48181
|
-
const nextRefresh = `rt_${(0,
|
|
48783
|
+
const nextRefresh = `rt_${(0, import_node_crypto25.randomBytes)(40).toString("base64url")}`;
|
|
48182
48784
|
await rotateRefresh(refreshToken, {
|
|
48183
48785
|
refresh_token: nextRefresh,
|
|
48184
48786
|
client_id: record.client_id,
|
|
@@ -48740,13 +49342,13 @@ loadChannels();
|
|
|
48740
49342
|
</body>
|
|
48741
49343
|
</html>`;
|
|
48742
49344
|
}
|
|
48743
|
-
var
|
|
49345
|
+
var import_hono24, chatApp;
|
|
48744
49346
|
var init_chat_routes = __esm({
|
|
48745
49347
|
"src/api/chat-routes.ts"() {
|
|
48746
49348
|
"use strict";
|
|
48747
|
-
|
|
49349
|
+
import_hono24 = require("hono");
|
|
48748
49350
|
init_memory();
|
|
48749
|
-
chatApp = new
|
|
49351
|
+
chatApp = new import_hono24.Hono();
|
|
48750
49352
|
chatApp.get("/api/channels", async (c) => {
|
|
48751
49353
|
const token = c.req.query("token");
|
|
48752
49354
|
if (!tokenOk(token)) return jsonError("missing or malformed token", 401);
|
|
@@ -49030,11 +49632,11 @@ async function readVault(vault, token) {
|
|
|
49030
49632
|
if (failed && !failed.ok) throw new Error(failed.error ?? `unable to read ${vault} record`);
|
|
49031
49633
|
return notes.filter((result) => result.ok && !!result.note).map((result) => workspaceRecord(vault, result.note));
|
|
49032
49634
|
}
|
|
49033
|
-
var
|
|
49635
|
+
var import_hono25, VAULTS, PROJECT_TYPES, PROJECT_KIND_BY_TYPE, PROJECT_TYPE_BY_KIND, MAX_VAULT_RECORDS, MAX_MEMORY_READ_CONCURRENCY, MAX_MEMORY_READ_ATTEMPTS, vaultApp;
|
|
49034
49636
|
var init_vault_routes = __esm({
|
|
49035
49637
|
"src/api/vault-routes.ts"() {
|
|
49036
49638
|
"use strict";
|
|
49037
|
-
|
|
49639
|
+
import_hono25 = require("hono");
|
|
49038
49640
|
init_memory();
|
|
49039
49641
|
VAULTS = ["People", "Organizations", "Deals", "Projects", "Tasks", "Communications", "Calendar"];
|
|
49040
49642
|
PROJECT_TYPES = ["codebase", "personal", "work", "client"];
|
|
@@ -49054,7 +49656,7 @@ var init_vault_routes = __esm({
|
|
|
49054
49656
|
MAX_VAULT_RECORDS = 200;
|
|
49055
49657
|
MAX_MEMORY_READ_CONCURRENCY = 4;
|
|
49056
49658
|
MAX_MEMORY_READ_ATTEMPTS = 3;
|
|
49057
|
-
vaultApp = new
|
|
49659
|
+
vaultApp = new import_hono25.Hono();
|
|
49058
49660
|
vaultApp.use("/api/*", async (c, next) => {
|
|
49059
49661
|
cors(c);
|
|
49060
49662
|
if (c.req.method === "OPTIONS") return c.body(null, 204);
|
|
@@ -49518,13 +50120,13 @@ loadActions();
|
|
|
49518
50120
|
</body>
|
|
49519
50121
|
</html>`;
|
|
49520
50122
|
}
|
|
49521
|
-
var
|
|
50123
|
+
var import_hono26, scheduleApp;
|
|
49522
50124
|
var init_schedule_routes = __esm({
|
|
49523
50125
|
"src/api/schedule-routes.ts"() {
|
|
49524
50126
|
"use strict";
|
|
49525
|
-
|
|
50127
|
+
import_hono26 = require("hono");
|
|
49526
50128
|
init_memory();
|
|
49527
|
-
scheduleApp = new
|
|
50129
|
+
scheduleApp = new import_hono26.Hono();
|
|
49528
50130
|
scheduleApp.get("/api/status", async (c) => {
|
|
49529
50131
|
const token = c.req.query("token");
|
|
49530
50132
|
if (!tokenOk2(token)) return jsonError2("missing or malformed token", 401);
|
|
@@ -49598,7 +50200,7 @@ function quoteUntrusted(value) {
|
|
|
49598
50200
|
return clean2.split("\n").map((line) => `> ${line}`).join("\n");
|
|
49599
50201
|
}
|
|
49600
50202
|
function shortHash(value, length = 24) {
|
|
49601
|
-
return (0,
|
|
50203
|
+
return (0, import_node_crypto26.createHash)("sha256").update(value).digest("hex").slice(0, length);
|
|
49602
50204
|
}
|
|
49603
50205
|
function safePathPart(value) {
|
|
49604
50206
|
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48) || "contact";
|
|
@@ -50086,11 +50688,11 @@ async function captureSupportMessage(memoryKey, email, options) {
|
|
|
50086
50688
|
direction: options.direction
|
|
50087
50689
|
};
|
|
50088
50690
|
}
|
|
50089
|
-
var
|
|
50691
|
+
var import_node_crypto26, SUPPORT_TAGS, ISSUE_TAGS;
|
|
50090
50692
|
var init_resend_support_thread = __esm({
|
|
50091
50693
|
"src/api/resend-support-thread.ts"() {
|
|
50092
50694
|
"use strict";
|
|
50093
|
-
|
|
50695
|
+
import_node_crypto26 = require("crypto");
|
|
50094
50696
|
init_memory();
|
|
50095
50697
|
SUPPORT_TAGS = [
|
|
50096
50698
|
{
|
|
@@ -50219,17 +50821,17 @@ async function relayOperatorReply(resend, email, customerEmail, threadAddress, n
|
|
|
50219
50821
|
if (sent.error) throw new Error(`support reply relay failed: ${sent.error.message}`);
|
|
50220
50822
|
return sent.data.id;
|
|
50221
50823
|
}
|
|
50222
|
-
var
|
|
50824
|
+
var import_hono27, import_resend, SUPPORT_ADDRESS, DMARC_ADDRESS, FORWARD_FROM, resendInboundApp;
|
|
50223
50825
|
var init_resend_inbound_routes = __esm({
|
|
50224
50826
|
"src/api/resend-inbound-routes.ts"() {
|
|
50225
50827
|
"use strict";
|
|
50226
|
-
|
|
50828
|
+
import_hono27 = require("hono");
|
|
50227
50829
|
import_resend = require("resend");
|
|
50228
50830
|
init_resend_support_thread();
|
|
50229
50831
|
SUPPORT_ADDRESS = "support@mcpscraper.dev";
|
|
50230
50832
|
DMARC_ADDRESS = "dmarc@mcpscraper.dev";
|
|
50231
50833
|
FORWARD_FROM = "MCP Scraper Support <support@updates.mcpscraper.dev>";
|
|
50232
|
-
resendInboundApp = new
|
|
50834
|
+
resendInboundApp = new import_hono27.Hono();
|
|
50233
50835
|
resendInboundApp.post("/webhooks", async (c) => {
|
|
50234
50836
|
const apiKey = process.env.RESEND_API_KEY?.trim();
|
|
50235
50837
|
const webhookSecret = process.env.RESEND_WEBHOOK_SECRET?.trim();
|
|
@@ -50486,7 +51088,7 @@ var init_site_extract_reconciliation = __esm({
|
|
|
50486
51088
|
|
|
50487
51089
|
// src/api/page-diff.ts
|
|
50488
51090
|
function sha256Hex(value) {
|
|
50489
|
-
return (0,
|
|
51091
|
+
return (0, import_node_crypto27.createHash)("sha256").update(value).digest("hex");
|
|
50490
51092
|
}
|
|
50491
51093
|
function truncateForStorage(value, maxChars = MAX_SNAPSHOT_CONTENT_CHARS) {
|
|
50492
51094
|
if (value.length <= maxChars) return { value, truncated: false };
|
|
@@ -50543,11 +51145,11 @@ function diffPageContent(oldContent, newContent) {
|
|
|
50543
51145
|
totalChangedLineCount
|
|
50544
51146
|
};
|
|
50545
51147
|
}
|
|
50546
|
-
var
|
|
51148
|
+
var import_node_crypto27, import_diff, MAX_SNAPSHOT_CONTENT_CHARS, MAX_DIFF_HUNKS, MAX_DIFF_LINES_PER_RESPONSE;
|
|
50547
51149
|
var init_page_diff = __esm({
|
|
50548
51150
|
"src/api/page-diff.ts"() {
|
|
50549
51151
|
"use strict";
|
|
50550
|
-
|
|
51152
|
+
import_node_crypto27 = require("crypto");
|
|
50551
51153
|
import_diff = require("diff");
|
|
50552
51154
|
MAX_SNAPSHOT_CONTENT_CHARS = 25e4;
|
|
50553
51155
|
MAX_DIFF_HUNKS = 200;
|
|
@@ -50624,7 +51226,7 @@ function canonicalJson(value) {
|
|
|
50624
51226
|
return JSON.stringify(value);
|
|
50625
51227
|
}
|
|
50626
51228
|
function sha2562(value) {
|
|
50627
|
-
return (0,
|
|
51229
|
+
return (0, import_node_crypto28.createHash)("sha256").update(value).digest("hex");
|
|
50628
51230
|
}
|
|
50629
51231
|
function sensitiveKey(key) {
|
|
50630
51232
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -50839,11 +51441,11 @@ async function importServiceConnectionToMemory(identity, input, dependencies) {
|
|
|
50839
51441
|
...!searchReady ? { warning: "The snapshot was stored, but no search chunks were indexed yet." } : {}
|
|
50840
51442
|
};
|
|
50841
51443
|
}
|
|
50842
|
-
var
|
|
51444
|
+
var import_node_crypto28, CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES, CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES, CONNECTION_MEMORY_IMPORT_MAX_STRING_CHARS, CONNECTION_MEMORY_IMPORT_MAX_DEPTH, ConnectionMemoryImportError;
|
|
50843
51445
|
var init_connection_memory_import = __esm({
|
|
50844
51446
|
"src/api/connection-memory-import.ts"() {
|
|
50845
51447
|
"use strict";
|
|
50846
|
-
|
|
51448
|
+
import_node_crypto28 = require("crypto");
|
|
50847
51449
|
init_slugify();
|
|
50848
51450
|
CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES = 64 * 1024;
|
|
50849
51451
|
CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES = 1e6;
|
|
@@ -51017,7 +51619,7 @@ function finitePositive(value, fallback) {
|
|
|
51017
51619
|
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
51018
51620
|
}
|
|
51019
51621
|
async function collectConnectedDataExport(args) {
|
|
51020
|
-
const exportId = (0,
|
|
51622
|
+
const exportId = (0, import_node_crypto29.randomUUID)();
|
|
51021
51623
|
const now = args.now ?? Date.now;
|
|
51022
51624
|
const startedAt = now();
|
|
51023
51625
|
const budgetMs = finitePositive(CONNECTED_DATA_EXPORT_BUDGET_MS, 24e4);
|
|
@@ -51127,11 +51729,11 @@ ${lines.length ? `${lines.join("\n")}
|
|
|
51127
51729
|
untrustedContent: true
|
|
51128
51730
|
};
|
|
51129
51731
|
}
|
|
51130
|
-
var
|
|
51732
|
+
var import_node_crypto29, CONNECTED_DATA_INLINE_BUDGET_BYTES, CONNECTED_DATA_MAX_EXPORT_BYTES, CONNECTED_DATA_EXPORT_BUDGET_MS, CONNECTED_DATA_PAGE_START_HEADROOM_MS, CONNECTED_DATA_DATASETS, ConnectedDataExportValidationError;
|
|
51131
51733
|
var init_connected_data_export = __esm({
|
|
51132
51734
|
"src/api/connected-data-export.ts"() {
|
|
51133
51735
|
"use strict";
|
|
51134
|
-
|
|
51736
|
+
import_node_crypto29 = require("crypto");
|
|
51135
51737
|
CONNECTED_DATA_INLINE_BUDGET_BYTES = Number(
|
|
51136
51738
|
process.env.MCP_SCRAPER_CONNECTED_DATA_INLINE_BUDGET_BYTES ?? 5e4
|
|
51137
51739
|
);
|
|
@@ -51244,7 +51846,7 @@ async function exportSearchConsoleTableData(args) {
|
|
|
51244
51846
|
offset += rows.length;
|
|
51245
51847
|
if (stoppedForBytes || rows.length < limit || offset >= matchedRows) break;
|
|
51246
51848
|
}
|
|
51247
|
-
const exportId = (0,
|
|
51849
|
+
const exportId = (0, import_node_crypto30.randomUUID)();
|
|
51248
51850
|
const artifact = await args.writeArtifact({
|
|
51249
51851
|
ownerId: args.ownerId,
|
|
51250
51852
|
exportId,
|
|
@@ -51266,11 +51868,11 @@ async function exportSearchConsoleTableData(args) {
|
|
|
51266
51868
|
warnings
|
|
51267
51869
|
};
|
|
51268
51870
|
}
|
|
51269
|
-
var
|
|
51871
|
+
var import_node_crypto30, SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS, SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE, SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES, SEARCH_CONSOLE_TABLE_COLUMNS, SearchConsoleTableExportValidationError;
|
|
51270
51872
|
var init_search_console_table_export = __esm({
|
|
51271
51873
|
"src/api/search-console-table-export.ts"() {
|
|
51272
51874
|
"use strict";
|
|
51273
|
-
|
|
51875
|
+
import_node_crypto30 = require("crypto");
|
|
51274
51876
|
SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS = 5e4;
|
|
51275
51877
|
SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE = 2e3;
|
|
51276
51878
|
SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES = 50 * 1024 * 1024;
|
|
@@ -51698,7 +52300,7 @@ async function reconcileDiscoveredNangoConnections(identity, discovered) {
|
|
|
51698
52300
|
updated_at = excluded.updated_at
|
|
51699
52301
|
`,
|
|
51700
52302
|
args: [
|
|
51701
|
-
(0,
|
|
52303
|
+
(0, import_node_crypto31.randomUUID)(),
|
|
51702
52304
|
userId,
|
|
51703
52305
|
connection.providerConfigKey,
|
|
51704
52306
|
connection.provider,
|
|
@@ -51769,7 +52371,7 @@ async function recordServiceConnectionHealth(args) {
|
|
|
51769
52371
|
});
|
|
51770
52372
|
await getDb().execute({
|
|
51771
52373
|
sql: `INSERT INTO service_connection_health_events (id, connection_id, operational_status, failure_code, retryable, evidence_source) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
51772
|
-
args: [(0,
|
|
52374
|
+
args: [(0, import_node_crypto31.randomUUID)(), args.connectionId, args.operationalStatus, args.failureCode ?? null, args.retryable == null ? null : args.retryable ? 1 : 0, args.evidenceSource]
|
|
51773
52375
|
});
|
|
51774
52376
|
}
|
|
51775
52377
|
async function setServiceConnectionActions(identity, connectionId, enabled) {
|
|
@@ -51809,7 +52411,7 @@ async function claimServiceConnectionAction(args) {
|
|
|
51809
52411
|
if (!connection) throw new Error("service_connection_not_found");
|
|
51810
52412
|
const inserted = await getDb().execute({
|
|
51811
52413
|
sql: `INSERT OR IGNORE INTO service_connection_action_audit (id, connection_id, user_id, tool, request_id, status) VALUES (?, ?, ?, ?, ?, 'started')`,
|
|
51812
|
-
args: [(0,
|
|
52414
|
+
args: [(0, import_node_crypto31.randomUUID)(), connection.id, connection.userId, args.tool, args.requestId]
|
|
51813
52415
|
});
|
|
51814
52416
|
if (Number(inserted.rowsAffected ?? 0) === 1) return { claimed: true };
|
|
51815
52417
|
const existing = await getDb().execute({
|
|
@@ -51822,11 +52424,11 @@ async function claimServiceConnectionAction(args) {
|
|
|
51822
52424
|
errorCode: typeof existing.rows[0]?.error_code === "string" ? existing.rows[0].error_code : null
|
|
51823
52425
|
};
|
|
51824
52426
|
}
|
|
51825
|
-
var
|
|
52427
|
+
var import_node_crypto31, schemaReady2, schemaDb3;
|
|
51826
52428
|
var init_service_connections = __esm({
|
|
51827
52429
|
"src/api/service-connections.ts"() {
|
|
51828
52430
|
"use strict";
|
|
51829
|
-
|
|
52431
|
+
import_node_crypto31 = require("crypto");
|
|
51830
52432
|
init_db();
|
|
51831
52433
|
schemaReady2 = null;
|
|
51832
52434
|
schemaDb3 = null;
|
|
@@ -52143,7 +52745,7 @@ async function listNangoToolsDirect(identity, connectionId) {
|
|
|
52143
52745
|
});
|
|
52144
52746
|
const readTools = tools.filter((tool) => classifyTool(tool) === "read").map((tool) => tool.name);
|
|
52145
52747
|
const actionTools = tools.filter((tool) => classifyTool(tool) === "action").map((tool) => tool.name);
|
|
52146
|
-
const revision = (0,
|
|
52748
|
+
const revision = (0, import_node_crypto32.createHash)("sha256").update(JSON.stringify(tools.map((tool) => ({ name: tool.name, inputSchema: tool.inputSchema })))).digest("hex");
|
|
52147
52749
|
await updateServiceConnectionTools(connection.id, readTools, actionTools, revision);
|
|
52148
52750
|
const refreshed = await getOwnedServiceConnection(identity, connection.id);
|
|
52149
52751
|
return { connection: refreshed ?? { ...connection, readTools, actionTools, toolRevision: revision }, tools };
|
|
@@ -52163,8 +52765,8 @@ async function callNangoToolDirect(args) {
|
|
|
52163
52765
|
identity: args.identity,
|
|
52164
52766
|
ratePolicyVersion: CONNECTED_USAGE_RATE_POLICY_VERSION
|
|
52165
52767
|
});
|
|
52166
|
-
const requestId = args.requestId?.trim() || (0,
|
|
52167
|
-
const idempotencyKey2 = `main-nango:${(0,
|
|
52768
|
+
const requestId = args.requestId?.trim() || (0, import_node_crypto32.randomUUID)();
|
|
52769
|
+
const idempotencyKey2 = `main-nango:${(0, import_node_crypto32.createHash)("sha256").update(args.identity.toLowerCase()).update("\0").update(connection.id).update("\0").update(args.tool).update("\0").update(requestId).digest("hex")}`;
|
|
52168
52770
|
const startedAt = /* @__PURE__ */ new Date();
|
|
52169
52771
|
const started = performance.now();
|
|
52170
52772
|
let result;
|
|
@@ -52189,7 +52791,7 @@ async function callNangoToolDirect(args) {
|
|
|
52189
52791
|
toolName: args.tool,
|
|
52190
52792
|
operationKind: args.operationKind ?? args.classification,
|
|
52191
52793
|
outcome: providerError ? "error" : "partial",
|
|
52192
|
-
requestId: requestId.length <= 200 ? requestId : (0,
|
|
52794
|
+
requestId: requestId.length <= 200 ? requestId : (0, import_node_crypto32.createHash)("sha256").update(requestId).digest("hex"),
|
|
52193
52795
|
startedAt: startedAt.toISOString(),
|
|
52194
52796
|
completedAt: completedAt.toISOString()
|
|
52195
52797
|
}
|
|
@@ -52226,15 +52828,15 @@ async function describeNangoToolDirect(identity, connectionId, toolName) {
|
|
|
52226
52828
|
providerContractHash: MAIN_INTEGRATION_CONTRACT_HASH,
|
|
52227
52829
|
protocolVersion: null,
|
|
52228
52830
|
schemaSource: "live_tools_list",
|
|
52229
|
-
schemaHash: (0,
|
|
52831
|
+
schemaHash: (0, import_node_crypto32.createHash)("sha256").update(JSON.stringify(projected)).digest("hex"),
|
|
52230
52832
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
52231
52833
|
};
|
|
52232
52834
|
}
|
|
52233
|
-
var
|
|
52835
|
+
var import_node_crypto32, import_client9, import_streamableHttp, DEFAULT_NANGO_MCP_URL, NANGO_TIMEOUT_MS, NANGO_CONNECTION_PAGE_SIZE, NANGO_CONNECTION_MAX_PAGES, MAIN_INTEGRATION_CONTRACT_VERSION, MAIN_INTEGRATION_CONTRACT_HASH, MainNangoTransportError;
|
|
52234
52836
|
var init_main_nango_transport = __esm({
|
|
52235
52837
|
"src/api/main-nango-transport.ts"() {
|
|
52236
52838
|
"use strict";
|
|
52237
|
-
|
|
52839
|
+
import_node_crypto32 = require("crypto");
|
|
52238
52840
|
import_client9 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
52239
52841
|
import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
52240
52842
|
init_service_connections();
|
|
@@ -52856,7 +53458,7 @@ async function setScheduleConnectionActionsEnabled(identity, connectionId, enabl
|
|
|
52856
53458
|
return data.connection.actionsEnabled === true;
|
|
52857
53459
|
}
|
|
52858
53460
|
async function callScheduleConnectionAction(identity, connectionId, input, tool, idempotencyKey2) {
|
|
52859
|
-
const requestId = `main-connected-action:${(0,
|
|
53461
|
+
const requestId = `main-connected-action:${(0, import_node_crypto33.createHash)("sha256").update(identity).update("\0").update(idempotencyKey2?.trim() || (0, import_node_crypto33.randomUUID)()).digest("hex")}`;
|
|
52860
53462
|
if (mainOwnsIntegrations()) {
|
|
52861
53463
|
const selectedTool = tool?.trim();
|
|
52862
53464
|
if (!selectedTool) throw new NangoControlError("An action tool is required.", 400, "invalid_request", false);
|
|
@@ -52998,7 +53600,7 @@ function canonicalJson2(value) {
|
|
|
52998
53600
|
return JSON.stringify(value);
|
|
52999
53601
|
}
|
|
53000
53602
|
function projectedToolSchemaHash(tool) {
|
|
53001
|
-
return (0,
|
|
53603
|
+
return (0, import_node_crypto33.createHash)("sha256").update(canonicalJson2(tool)).digest("hex");
|
|
53002
53604
|
}
|
|
53003
53605
|
async function describeNangoTool(identity, connectionId, tool, fresh) {
|
|
53004
53606
|
if (mainOwnsIntegrations()) {
|
|
@@ -53259,11 +53861,11 @@ async function callMainOwnedExportPage(identity, input) {
|
|
|
53259
53861
|
untrustedContent: true
|
|
53260
53862
|
};
|
|
53261
53863
|
}
|
|
53262
|
-
var
|
|
53864
|
+
var import_node_crypto33, DEFAULT_NANGO_CONTROL_URL, DISABLED_NANGO_TOOLS, CONNECTION_SYNC_REQUIRED_TOOLS, CONNECTION_SYNC_OPTIONAL_TOOLS, NangoControlError, ScheduleConnectionValidationError, SAFE_CONTROL_ERROR_CODES, FIXED_CONTROL_ERROR_MESSAGES, CONTROL_ERROR_CODE_ALIASES;
|
|
53263
53865
|
var init_nango_control = __esm({
|
|
53264
53866
|
"src/api/nango-control.ts"() {
|
|
53265
53867
|
"use strict";
|
|
53266
|
-
|
|
53868
|
+
import_node_crypto33 = require("crypto");
|
|
53267
53869
|
init_connected_data_export();
|
|
53268
53870
|
init_main_nango_transport();
|
|
53269
53871
|
init_service_connections();
|
|
@@ -53731,8 +54333,8 @@ function signingSecret() {
|
|
|
53731
54333
|
return secret2;
|
|
53732
54334
|
}
|
|
53733
54335
|
function schedulerIntegrationSignature(args) {
|
|
53734
|
-
const bodyHash = (0,
|
|
53735
|
-
return (0,
|
|
54336
|
+
const bodyHash = (0, import_node_crypto34.createHash)("sha256").update(args.body).digest("hex");
|
|
54337
|
+
return (0, import_node_crypto34.createHmac)("sha256", args.secret).update(`${args.method.toUpperCase()}
|
|
53736
54338
|
${args.path}
|
|
53737
54339
|
${args.timestamp}
|
|
53738
54340
|
${args.nonce}
|
|
@@ -53779,17 +54381,17 @@ async function verifySchedulerIntegrationRequest(request, rawBody) {
|
|
|
53779
54381
|
});
|
|
53780
54382
|
const suppliedBytes = Buffer.from(signature, "hex");
|
|
53781
54383
|
const expectedBytes = Buffer.from(expected, "hex");
|
|
53782
|
-
if (suppliedBytes.length !== expectedBytes.length || !(0,
|
|
54384
|
+
if (suppliedBytes.length !== expectedBytes.length || !(0, import_node_crypto34.timingSafeEqual)(suppliedBytes, expectedBytes)) {
|
|
53783
54385
|
throw new SchedulerIntegrationAuthError("invalid_signature");
|
|
53784
54386
|
}
|
|
53785
54387
|
await claimNonce(nonce, timestampMs);
|
|
53786
54388
|
return { requestId };
|
|
53787
54389
|
}
|
|
53788
|
-
var
|
|
54390
|
+
var import_node_crypto34, MAX_CLOCK_SKEW_MS, SchedulerIntegrationAuthError;
|
|
53789
54391
|
var init_scheduler_integration_auth = __esm({
|
|
53790
54392
|
"src/api/scheduler-integration-auth.ts"() {
|
|
53791
54393
|
"use strict";
|
|
53792
|
-
|
|
54394
|
+
import_node_crypto34 = require("crypto");
|
|
53793
54395
|
init_db();
|
|
53794
54396
|
init_service_connections();
|
|
53795
54397
|
MAX_CLOCK_SKEW_MS = 5 * 60 * 1e3;
|
|
@@ -54284,7 +54886,7 @@ async function chargeTierChangeNow(stripeClient, subscriptionId, customerId) {
|
|
|
54284
54886
|
return { ok: false, amountDue: 0, error: err instanceof Error ? err.message : "Unable to charge the plan change immediately." };
|
|
54285
54887
|
}
|
|
54286
54888
|
}
|
|
54287
|
-
var import_resend2,
|
|
54889
|
+
var import_resend2, import_hono28, import_hono29, import_factory7, import_cookie2, import_stripe2, secureCookies2, isProduction2, sessionCookieOptions2, requireAllowedOrigin, auth2, sessionAuth, requireIntegrationsTier, requirePaidSchedulingTier, app, STRIPE_API_VERSION, SYNC_HARVEST_TIMEOUT_OVERRIDE_MS;
|
|
54288
54890
|
var init_server = __esm({
|
|
54289
54891
|
"src/api/server.ts"() {
|
|
54290
54892
|
"use strict";
|
|
@@ -54302,8 +54904,8 @@ var init_server = __esm({
|
|
|
54302
54904
|
init_media_extractor();
|
|
54303
54905
|
init_site_mapper();
|
|
54304
54906
|
init_site_extractor();
|
|
54305
|
-
|
|
54306
|
-
|
|
54907
|
+
import_hono28 = require("hono");
|
|
54908
|
+
import_hono29 = require("inngest/hono");
|
|
54307
54909
|
init_client();
|
|
54308
54910
|
init_site_audit();
|
|
54309
54911
|
init_site_extract();
|
|
@@ -54321,6 +54923,8 @@ var init_server = __esm({
|
|
|
54321
54923
|
init_screenshot_routes();
|
|
54322
54924
|
init_facebook_ad_routes();
|
|
54323
54925
|
init_google_ads_routes();
|
|
54926
|
+
init_admin_auth();
|
|
54927
|
+
init_admin_credit_routes();
|
|
54324
54928
|
init_instagram_routes();
|
|
54325
54929
|
init_reddit_routes();
|
|
54326
54930
|
init_video_routes();
|
|
@@ -54346,7 +54950,7 @@ var init_server = __esm({
|
|
|
54346
54950
|
init_schedule_routes();
|
|
54347
54951
|
init_resend_inbound_routes();
|
|
54348
54952
|
init_site_audit_worker();
|
|
54349
|
-
|
|
54953
|
+
import_factory7 = require("hono/factory");
|
|
54350
54954
|
import_cookie2 = require("hono/cookie");
|
|
54351
54955
|
init_db();
|
|
54352
54956
|
import_stripe2 = __toESM(require("stripe"), 1);
|
|
@@ -54386,13 +54990,13 @@ var init_server = __esm({
|
|
|
54386
54990
|
maxAge: 60 * 60 * 24 * 30,
|
|
54387
54991
|
sameSite: "Strict"
|
|
54388
54992
|
};
|
|
54389
|
-
requireAllowedOrigin = (0,
|
|
54993
|
+
requireAllowedOrigin = (0, import_factory7.createMiddleware)(async (c, next) => {
|
|
54390
54994
|
const origin = c.req.header("origin");
|
|
54391
54995
|
if (!origin) return next();
|
|
54392
54996
|
if (!configuredOrigins().has(origin)) return c.json({ error: "Origin not allowed" }, 403);
|
|
54393
54997
|
return next();
|
|
54394
54998
|
});
|
|
54395
|
-
auth2 = (0,
|
|
54999
|
+
auth2 = (0, import_factory7.createMiddleware)(async (c, next) => {
|
|
54396
55000
|
const key = c.req.header("x-api-key");
|
|
54397
55001
|
if (!key) return c.json({ error: "Missing API key" }, 401);
|
|
54398
55002
|
const user = await getUserByApiKey(key);
|
|
@@ -54402,14 +55006,7 @@ var init_server = __esm({
|
|
|
54402
55006
|
c.set("user", { ...refreshed, balance_mc: balanceMc });
|
|
54403
55007
|
return next();
|
|
54404
55008
|
});
|
|
54405
|
-
|
|
54406
|
-
const configured = process.env.ADMIN_KEY?.trim();
|
|
54407
|
-
const key = c.req.header("x-admin-key")?.trim();
|
|
54408
|
-
if (!configured) return c.json({ error: "Admin access disabled" }, 503);
|
|
54409
|
-
if (!key || key !== configured) return c.json({ error: "Unauthorized" }, 401);
|
|
54410
|
-
return next();
|
|
54411
|
-
});
|
|
54412
|
-
sessionAuth = (0, import_factory6.createMiddleware)(async (c, next) => {
|
|
55009
|
+
sessionAuth = (0, import_factory7.createMiddleware)(async (c, next) => {
|
|
54413
55010
|
const token = (0, import_cookie2.getCookie)(c, "session");
|
|
54414
55011
|
if (!token) return c.json({ error: "Not authenticated" }, 401);
|
|
54415
55012
|
const userId = verifySession(token);
|
|
@@ -54421,7 +55018,7 @@ var init_server = __esm({
|
|
|
54421
55018
|
c.set("sessionUser", { ...refreshed, balance_mc: balanceMc });
|
|
54422
55019
|
return next();
|
|
54423
55020
|
});
|
|
54424
|
-
requireIntegrationsTier = (0,
|
|
55021
|
+
requireIntegrationsTier = (0, import_factory7.createMiddleware)(async (c, next) => {
|
|
54425
55022
|
const user = c.get("user");
|
|
54426
55023
|
if (!user.subscription_tier) {
|
|
54427
55024
|
return c.json({
|
|
@@ -54432,12 +55029,12 @@ var init_server = __esm({
|
|
|
54432
55029
|
}
|
|
54433
55030
|
return next();
|
|
54434
55031
|
});
|
|
54435
|
-
requirePaidSchedulingTier = (0,
|
|
55032
|
+
requirePaidSchedulingTier = (0, import_factory7.createMiddleware)(async (c, next) => {
|
|
54436
55033
|
const user = c.get("user");
|
|
54437
55034
|
if (!hasPaidSchedulingAccess(user)) return c.json(paidPlanRequiredPayload(), 403);
|
|
54438
55035
|
return next();
|
|
54439
55036
|
});
|
|
54440
|
-
app = new
|
|
55037
|
+
app = new import_hono28.Hono();
|
|
54441
55038
|
STRIPE_API_VERSION = "2026-02-25.clover";
|
|
54442
55039
|
app.use("*", async (c, next) => {
|
|
54443
55040
|
await next();
|
|
@@ -56864,7 +57461,8 @@ var init_server = __esm({
|
|
|
56864
57461
|
const bundle = stored.find((a) => a.contentType === "application/zip" || a.filename?.endsWith(".zip"));
|
|
56865
57462
|
return c.json({ ok: true, jobId: jobId2, artifacts: stored.length, settlement, bundleUrl: bundle?.url ?? null, bundleBytes: bundle?.bytes ?? null });
|
|
56866
57463
|
});
|
|
56867
|
-
app.on(["GET", "POST", "PUT"], "/api/inngest", (0,
|
|
57464
|
+
app.on(["GET", "POST", "PUT"], "/api/inngest", (0, import_hono29.serve)({ client: inngest, functions: [siteAuditFn, siteExtractFn, directoryWorkflowFn] }));
|
|
57465
|
+
app.route("/admin/credits", adminCreditsApp);
|
|
56868
57466
|
app.route("/api/internal/site-architecture-auditor", siteAuditApp);
|
|
56869
57467
|
app.route("/api/internal/memory", internalMemoryApp);
|
|
56870
57468
|
app.route("/api/internal/billing", internalBillingApp);
|