thumbgate 1.4.1 → 1.4.3
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/.claude-plugin/README.md +45 -34
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +3 -3
- package/.well-known/llms.txt +1 -1
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +26 -2
- package/adapters/README.md +4 -1
- package/adapters/chatgpt/INSTALL.md +39 -19
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/codex/config.toml +2 -2
- package/adapters/mcp/server-stdio.js +10 -4
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/perplexity/.mcp.json +36 -0
- package/adapters/perplexity/config.toml +16 -0
- package/adapters/perplexity/opencode.json +29 -0
- package/bin/cli.js +246 -90
- package/config/mcp-allowlists.json +11 -3
- package/package.json +28 -13
- package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-codex-bridge/.mcp.json +1 -1
- package/plugins/codex-profile/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-profile/.mcp.json +1 -1
- package/plugins/codex-profile/INSTALL.md +1 -1
- package/plugins/codex-profile/README.md +1 -1
- package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +1 -1
- package/plugins/opencode-profile/INSTALL.md +1 -1
- package/public/index.html +121 -24
- package/public/llm-context.md +17 -1
- package/scripts/ai-search-visibility.js +10 -36
- package/scripts/audit-trail.js +25 -15
- package/scripts/auto-wire-hooks.js +127 -0
- package/scripts/cli-demo.js +102 -0
- package/scripts/cli-schema.js +285 -0
- package/scripts/cli-status.js +166 -0
- package/scripts/cross-encoder-reranker.js +235 -0
- package/scripts/explore-subcommands.js +277 -0
- package/scripts/explore.js +569 -0
- package/scripts/feedback-loop.js +20 -6
- package/scripts/lesson-inference.js +27 -2
- package/scripts/lesson-reranker.js +263 -0
- package/scripts/lesson-retrieval.js +34 -17
- package/scripts/lesson-search.js +69 -0
- package/scripts/perplexity-client.js +210 -0
- package/scripts/perplexity-command-center.js +644 -0
- package/scripts/perplexity-marketing.js +17 -29
- package/scripts/prove-packaged-runtime.js +5 -4
- package/scripts/ralph-mode-ci.js +122 -19
- package/scripts/reflector-agent.js +2 -2
- package/scripts/session-analyzer.js +533 -0
- package/scripts/social-analytics/db/marketing-db.js +179 -0
- package/scripts/social-analytics/db/schema.sql +23 -0
- package/scripts/social-analytics/generate-instagram-card.js +31 -5
- package/scripts/social-analytics/generate-slides.js +268 -0
- package/scripts/social-analytics/post-video.js +316 -0
- package/scripts/social-analytics/publishers/zernio.js +52 -23
- package/scripts/statusline-local-stats.js +3 -1
- package/scripts/statusline.sh +15 -10
- package/scripts/thumbgate-bench.js +494 -0
- package/src/api/server.js +65 -1
- package/scripts/social-analytics/db/analytics.sqlite +0 -0
package/src/api/server.js
CHANGED
|
@@ -5,6 +5,37 @@ const fs = require('fs');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const pkg = require('../../package.json');
|
|
7
7
|
|
|
8
|
+
const POSTHOG_API_PATHS = new Set(['/capture', '/batch', '/decide', '/e', '/engage']);
|
|
9
|
+
const POSTHOG_INGEST_HOST = 'us.i.posthog.com';
|
|
10
|
+
const POSTHOG_STATIC_PATH_PREFIX = '/static/';
|
|
11
|
+
|
|
12
|
+
function getPosthogProxyPath(pathname) {
|
|
13
|
+
return pathname.slice('/ingest'.length) || '/';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isExactOrChildPath(pathname, basePath) {
|
|
17
|
+
return pathname === basePath || pathname.startsWith(`${basePath}/`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isAllowedPosthogProxyPath(pathname) {
|
|
21
|
+
if (pathname === '/') return true;
|
|
22
|
+
if (pathname.startsWith(POSTHOG_STATIC_PATH_PREFIX)) return true;
|
|
23
|
+
return Array.from(POSTHOG_API_PATHS).some((basePath) => isExactOrChildPath(pathname, basePath));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function buildPosthogProxyRequestOptions(req, posthogPath, search) {
|
|
27
|
+
return {
|
|
28
|
+
protocol: 'https:',
|
|
29
|
+
hostname: POSTHOG_INGEST_HOST,
|
|
30
|
+
path: `${posthogPath}${search || ''}`,
|
|
31
|
+
method: req.method,
|
|
32
|
+
headers: {
|
|
33
|
+
...req.headers,
|
|
34
|
+
host: POSTHOG_INGEST_HOST,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
8
39
|
const {
|
|
9
40
|
captureFeedback,
|
|
10
41
|
analyzeFeedback,
|
|
@@ -2354,6 +2385,29 @@ function createApiServer() {
|
|
|
2354
2385
|
const requestFeedbackDir = requestFeedbackPaths.FEEDBACK_DIR;
|
|
2355
2386
|
const requestSafeDataDir = getSafeDataDir(req, parsed);
|
|
2356
2387
|
|
|
2388
|
+
// PostHog reverse proxy -- bypasses ad blockers.
|
|
2389
|
+
// Only allow known PostHog API paths to prevent SSRF (CodeQL js/request-forgery).
|
|
2390
|
+
if (pathname.startsWith('/ingest')) {
|
|
2391
|
+
const posthogPath = getPosthogProxyPath(pathname);
|
|
2392
|
+
if (!isAllowedPosthogProxyPath(posthogPath)) {
|
|
2393
|
+
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
2394
|
+
res.end('Forbidden');
|
|
2395
|
+
return;
|
|
2396
|
+
}
|
|
2397
|
+
let body = '';
|
|
2398
|
+
req.on('data', chunk => { body += chunk; });
|
|
2399
|
+
req.on('end', () => {
|
|
2400
|
+
const proxyReq = https.request(buildPosthogProxyRequestOptions(req, posthogPath, parsed.search), (proxyRes) => {
|
|
2401
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
2402
|
+
proxyRes.pipe(res);
|
|
2403
|
+
});
|
|
2404
|
+
proxyReq.on('error', () => { res.writeHead(502); res.end(); });
|
|
2405
|
+
if (body) proxyReq.write(body);
|
|
2406
|
+
proxyReq.end();
|
|
2407
|
+
});
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2357
2411
|
// Public MCP endpoint — responds to Smithery registry scanning and MCP initialize
|
|
2358
2412
|
// The initialize handshake is unauthenticated; subsequent tool calls require Bearer auth
|
|
2359
2413
|
if (pathname === '/mcp') {
|
|
@@ -3770,7 +3824,14 @@ async function addContext(){
|
|
|
3770
3824
|
return;
|
|
3771
3825
|
}
|
|
3772
3826
|
|
|
3773
|
-
|
|
3827
|
+
// Operator key is allowed to bypass the general admin gate for its dedicated endpoint
|
|
3828
|
+
const _reqToken = extractApiKey(req);
|
|
3829
|
+
const isOperatorBillingRequest = Boolean(expectedOperatorKey)
|
|
3830
|
+
&& _reqToken === expectedOperatorKey
|
|
3831
|
+
&& req.method === 'GET'
|
|
3832
|
+
&& pathname === '/v1/billing/summary';
|
|
3833
|
+
|
|
3834
|
+
if (!isOperatorBillingRequest && !isAuthorized(req, expectedApiKey)) {
|
|
3774
3835
|
sendProblem(res, {
|
|
3775
3836
|
type: PROBLEM_TYPES.UNAUTHORIZED,
|
|
3776
3837
|
title: 'Unauthorized',
|
|
@@ -5014,6 +5075,9 @@ module.exports = {
|
|
|
5014
5075
|
startServer,
|
|
5015
5076
|
__test__: {
|
|
5016
5077
|
buildCheckoutFallbackUrl,
|
|
5078
|
+
buildPosthogProxyRequestOptions,
|
|
5079
|
+
getPosthogProxyPath,
|
|
5080
|
+
isAllowedPosthogProxyPath,
|
|
5017
5081
|
renderSitemapXml,
|
|
5018
5082
|
},
|
|
5019
5083
|
};
|
|
File without changes
|