hive-intelligence 1.14.0 → 1.16.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 +4 -3
- package/agent-skills/packs/hive/SKILL.md +2 -2
- package/agent-skills/packs/hive-prediction-markets/SKILL.md +9 -8
- package/build/{api-client-POBN6Y5S.js → api-client-MK3CVNCH.js} +2 -2
- package/build/{auth-6XVL5CE3.js → auth-TZQC54EJ.js} +1 -1
- package/build/{call-args-BUB6YNHW.js → call-args-4YRVKOLV.js} +2 -2
- package/build/{chunk-ZSPPJW4G.js → chunk-4U4IL5KA.js} +15 -1
- package/build/{chunk-KQVPKTEO.js → chunk-AVTIJGWS.js} +2 -2
- package/build/{chunk-SMVHHINA.js → chunk-B53GNIWW.js} +1 -1
- package/build/chunk-MYSS5SBE.js +71 -0
- package/build/{chunk-YLHNUAFT.js → chunk-O5YKCM67.js} +22 -6
- package/build/{chunk-APBLB62S.js → chunk-PODCJTBV.js} +1 -1
- package/build/{chunk-C4BFUIEB.js → chunk-QSKFAT7Z.js} +2141 -915
- package/build/{chunk-RNVZIPNY.js → chunk-VO6NWVJD.js} +1 -1
- package/build/{chunk-AZFOTKS2.js → chunk-WZ2NMSV3.js} +1 -1
- package/build/cli.js +31 -29
- package/build/{doctor-FPB5TEBU.js → doctor-UKOGXRSW.js} +4 -4
- package/build/{errors-YQAVCXXO.js → errors-BPXK3KCR.js} +1 -1
- package/build/{feedback-G2DFCCI6.js → feedback-6XX2R75U.js} +2 -2
- package/build/{init-all-UDWHV2ER.js → init-all-XDQRGJ3D.js} +1 -1
- package/build/{mcpServer-RGUKLIP2.js → mcpServer-77FPS534.js} +2 -1
- package/build/monitor-worker.js +4 -154
- package/build/release.json +4 -4
- package/build/{routing-4VKAVRYR.js → routing-S7DPEROC.js} +2 -2
- package/build/{serve-46DQ37YQ.js → serve-2NIEUCJN.js} +6 -4
- package/build/server.js +116 -105
- package/build/stdio.js +2 -1
- package/build/{tools-K2P77L4T.js → tools-NSHQSUIK.js} +5 -5
- package/build/{uninstall-I6ERJ2ED.js → uninstall-CECLA5YZ.js} +2 -2
- package/build/{watch-BUSEPVDM.js → watch-4VHBLAL6.js} +3 -3
- package/package.json +5 -15
package/build/server.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getWalletStatus,
|
|
9
9
|
refundCredits,
|
|
10
10
|
refundSettled
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-B53GNIWW.js";
|
|
12
12
|
import {
|
|
13
13
|
CategoryEndpoints,
|
|
14
14
|
HERO_TOOL_NAMES,
|
|
@@ -43,19 +43,12 @@ import {
|
|
|
43
43
|
getAllWrappedEndpoints,
|
|
44
44
|
getAnalyticsWriter,
|
|
45
45
|
getAvailableApis,
|
|
46
|
-
getCorsAllowedOrigins,
|
|
47
|
-
getCredentialedRateLimitMax,
|
|
48
|
-
getCsvEnv,
|
|
49
|
-
getEnvVar,
|
|
50
46
|
getMcpCreditCost,
|
|
51
47
|
getMcpProtocolCanaryHistory,
|
|
52
|
-
getNodeEnv,
|
|
53
48
|
getOAuthLifecycleCanaryHistory,
|
|
54
49
|
getOAuthRuntimeConfig,
|
|
55
|
-
getPort,
|
|
56
50
|
getProviderCanaryHistory,
|
|
57
51
|
getProviderRuntimeStatus,
|
|
58
|
-
getRateLimitMax,
|
|
59
52
|
getRedisClient,
|
|
60
53
|
getRootVisibleToolCount,
|
|
61
54
|
getSharedClients,
|
|
@@ -71,12 +64,11 @@ import {
|
|
|
71
64
|
isEndpointInvokerName,
|
|
72
65
|
isFreeWriteEndpoint,
|
|
73
66
|
isHiveOAuthAccessToken,
|
|
74
|
-
|
|
67
|
+
isHostedKeysConfigured,
|
|
68
|
+
isHostedKeysRequired,
|
|
75
69
|
isRedisAvailable,
|
|
76
70
|
isRedisConfigured,
|
|
77
71
|
isSupabaseConfigured,
|
|
78
|
-
isUnkeyConfigured,
|
|
79
|
-
isUnkeyRequired,
|
|
80
72
|
listKeys,
|
|
81
73
|
materializeSubjectContext,
|
|
82
74
|
normalizeInvokeArgs,
|
|
@@ -105,11 +97,22 @@ import {
|
|
|
105
97
|
validateEndpointArgs,
|
|
106
98
|
verifyApiKey,
|
|
107
99
|
waitForRedisAvailability
|
|
108
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-QSKFAT7Z.js";
|
|
109
101
|
import {
|
|
110
102
|
HIVE_AGENT_SKILLS
|
|
111
103
|
} from "./chunk-QYK3EWTE.js";
|
|
112
104
|
import "./chunk-EPF36Q3Z.js";
|
|
105
|
+
import {
|
|
106
|
+
getCorsAllowedOrigins,
|
|
107
|
+
getCredentialedRateLimitMax,
|
|
108
|
+
getCsvEnv,
|
|
109
|
+
getEnvVar,
|
|
110
|
+
getNodeEnv,
|
|
111
|
+
getPort,
|
|
112
|
+
getRateLimitMax,
|
|
113
|
+
isProduction,
|
|
114
|
+
loadEnvFile
|
|
115
|
+
} from "./chunk-MYSS5SBE.js";
|
|
113
116
|
import {
|
|
114
117
|
PUBLIC_MCP_REGISTRY_ID,
|
|
115
118
|
SERVER_NAME,
|
|
@@ -743,9 +746,6 @@ var require_ipaddr = __commonJS({
|
|
|
743
746
|
}
|
|
744
747
|
});
|
|
745
748
|
|
|
746
|
-
// src/server.ts
|
|
747
|
-
import dotenv from "dotenv";
|
|
748
|
-
|
|
749
749
|
// src/config/trustProxy.ts
|
|
750
750
|
var DEFAULT_TRUSTED_PROXY_ADDRESSES = "34.102.187.55";
|
|
751
751
|
function resolveTrustedProxies(raw = getEnvVar("TRUSTED_PROXY_ADDRESSES")) {
|
|
@@ -757,7 +757,6 @@ function resolveTrustedProxies(raw = getEnvVar("TRUSTED_PROXY_ADDRESSES")) {
|
|
|
757
757
|
import { randomUUID as randomUUID4, timingSafeEqual as timingSafeEqual6 } from "crypto";
|
|
758
758
|
import { resolve } from "path";
|
|
759
759
|
import { fileURLToPath } from "url";
|
|
760
|
-
import { createRequire as createNodeRequire } from "module";
|
|
761
760
|
import express2 from "express";
|
|
762
761
|
import compression from "compression";
|
|
763
762
|
import cors from "cors";
|
|
@@ -768,7 +767,56 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
768
767
|
// src/middleware/rate-limit.ts
|
|
769
768
|
import { timingSafeEqual } from "crypto";
|
|
770
769
|
import rateLimit from "express-rate-limit";
|
|
771
|
-
|
|
770
|
+
|
|
771
|
+
// src/utils/redisRateLimitStore.ts
|
|
772
|
+
var INCREMENT_SCRIPT = `
|
|
773
|
+
local windowMs = tonumber(ARGV[1])
|
|
774
|
+
local timeToExpire = redis.call("PTTL", KEYS[1])
|
|
775
|
+
if timeToExpire <= 0 then
|
|
776
|
+
redis.call("SET", KEYS[1], 1, "PX", windowMs)
|
|
777
|
+
return { 1, windowMs }
|
|
778
|
+
end
|
|
779
|
+
local totalHits = redis.call("INCR", KEYS[1])
|
|
780
|
+
return { totalHits, timeToExpire }
|
|
781
|
+
`;
|
|
782
|
+
var RedisRateLimitStore = class {
|
|
783
|
+
constructor(redis, prefix, onError) {
|
|
784
|
+
this.redis = redis;
|
|
785
|
+
this.prefix = prefix;
|
|
786
|
+
this.onError = onError;
|
|
787
|
+
}
|
|
788
|
+
redis;
|
|
789
|
+
prefix;
|
|
790
|
+
onError;
|
|
791
|
+
windowMs = 6e4;
|
|
792
|
+
init(options) {
|
|
793
|
+
this.windowMs = options.windowMs;
|
|
794
|
+
}
|
|
795
|
+
async increment(key) {
|
|
796
|
+
try {
|
|
797
|
+
const [totalHits, timeToExpire] = await this.redis.call(
|
|
798
|
+
"EVAL",
|
|
799
|
+
INCREMENT_SCRIPT,
|
|
800
|
+
"1",
|
|
801
|
+
this.prefix + key,
|
|
802
|
+
String(this.windowMs)
|
|
803
|
+
);
|
|
804
|
+
return {
|
|
805
|
+
totalHits: Number(totalHits),
|
|
806
|
+
resetTime: new Date(Date.now() + Number(timeToExpire))
|
|
807
|
+
};
|
|
808
|
+
} catch (error) {
|
|
809
|
+
this.onError?.(error);
|
|
810
|
+
throw error;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
async decrement(key) {
|
|
814
|
+
await this.redis.call("DECR", this.prefix + key);
|
|
815
|
+
}
|
|
816
|
+
async resetKey(key) {
|
|
817
|
+
await this.redis.call("DEL", this.prefix + key);
|
|
818
|
+
}
|
|
819
|
+
};
|
|
772
820
|
|
|
773
821
|
// src/utils/api-errors.ts
|
|
774
822
|
function apiError(type, code, message, opts) {
|
|
@@ -874,13 +922,15 @@ var createIpRateLimiter = (opts = {}) => {
|
|
|
874
922
|
secureLogger.info("[rate-limit] Redis configured; connection pending", {});
|
|
875
923
|
}
|
|
876
924
|
const storeConfig = redisClient ? {
|
|
877
|
-
store:
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
925
|
+
// Surface store failures without spamming: one line per minute is
|
|
926
|
+
// enough to alert on, and the request still proceeds via
|
|
927
|
+
// passOnStoreError below. The store rethrows so express-rate-limit
|
|
928
|
+
// applies that policy itself.
|
|
929
|
+
store: new RedisRateLimitStore(
|
|
930
|
+
redisClient,
|
|
931
|
+
lane === "credentialed" ? "rl:ip:cred:" : "rl:ip:",
|
|
932
|
+
noteRateLimitStoreError
|
|
933
|
+
)
|
|
884
934
|
} : {};
|
|
885
935
|
return rateLimit({
|
|
886
936
|
...storeConfig,
|
|
@@ -2573,10 +2623,10 @@ function attachVerifiedContext(req, res, key, result, quotaRemaining, rateDecisi
|
|
|
2573
2623
|
authReq.apiKey = key;
|
|
2574
2624
|
authReq.apiKeyEnvironment = getKeyEnvironment(key);
|
|
2575
2625
|
authReq.userId = result.userId;
|
|
2576
|
-
authReq.
|
|
2626
|
+
authReq.apiKeyId = result.keyId;
|
|
2577
2627
|
authReq.quotaRemaining = quotaRemaining ?? void 0;
|
|
2578
2628
|
authReq.ratelimitRemaining = rateDecision.remaining;
|
|
2579
|
-
authReq.
|
|
2629
|
+
authReq.apiKeyResult = result;
|
|
2580
2630
|
if (quotaRemaining !== void 0) {
|
|
2581
2631
|
res.setHeader(
|
|
2582
2632
|
"X-Quota-Remaining",
|
|
@@ -2593,7 +2643,7 @@ function deferApiKeyCreditDebit(req, _res, next) {
|
|
|
2593
2643
|
async function debitApiKeyCreditForExecution(req, res) {
|
|
2594
2644
|
const authReq = req;
|
|
2595
2645
|
if (authReq.creditDebitValidated !== true) return;
|
|
2596
|
-
const result = authReq.
|
|
2646
|
+
const result = authReq.apiKeyResult;
|
|
2597
2647
|
if (!result || !authReq.userId) return;
|
|
2598
2648
|
try {
|
|
2599
2649
|
const idempotencyKey = authReq.creditDebitIdempotencyKey ?? randomUUID();
|
|
@@ -2602,7 +2652,7 @@ async function debitApiKeyCreditForExecution(req, res) {
|
|
|
2602
2652
|
cost: REQUEST_COST,
|
|
2603
2653
|
idempotencyKey,
|
|
2604
2654
|
requestId: req.requestId,
|
|
2605
|
-
keyId: authReq.
|
|
2655
|
+
keyId: authReq.apiKeyId
|
|
2606
2656
|
});
|
|
2607
2657
|
if (consumeResult.code === "insufficient") {
|
|
2608
2658
|
res.setHeader("X-Quota-Remaining", String(consumeResult.balance ?? 0));
|
|
@@ -2614,9 +2664,9 @@ async function debitApiKeyCreditForExecution(req, res) {
|
|
|
2614
2664
|
};
|
|
2615
2665
|
}
|
|
2616
2666
|
if (consumeResult.code === "no_wallet") {
|
|
2617
|
-
secureLogger.warn("consume_credits returned no_wallet for valid
|
|
2667
|
+
secureLogger.warn("consume_credits returned no_wallet for a valid API key", {
|
|
2618
2668
|
userId: authReq.userId,
|
|
2619
|
-
keyId: authReq.
|
|
2669
|
+
keyId: authReq.apiKeyId
|
|
2620
2670
|
});
|
|
2621
2671
|
return {
|
|
2622
2672
|
type: "authentication_error",
|
|
@@ -2680,28 +2730,28 @@ function getRestAnalyticsTags(req) {
|
|
|
2680
2730
|
}
|
|
2681
2731
|
if (isProduction() && !getEnvVar("HIVE_API_KEYS")) {
|
|
2682
2732
|
secureLogger.warn(
|
|
2683
|
-
"HIVE_API_KEYS not set in production \u2014 protected routes will be unavailable unless
|
|
2733
|
+
"HIVE_API_KEYS not set in production \u2014 protected routes will be unavailable unless hosted keys are configured",
|
|
2684
2734
|
{}
|
|
2685
2735
|
);
|
|
2686
2736
|
}
|
|
2687
2737
|
function requireApiKey(req, res, next) {
|
|
2688
2738
|
const key = req.headers["x-api-key"] ?? (req.headers.authorization?.startsWith("Bearer ") ? req.headers.authorization.slice(7) : void 0);
|
|
2689
|
-
if (
|
|
2739
|
+
if (isHostedKeysRequired() && !isHostedKeysConfigured()) {
|
|
2690
2740
|
secureLogger.warn(
|
|
2691
|
-
"HIVE_AUTH_BACKEND=
|
|
2741
|
+
"HIVE_AUTH_BACKEND=hosted but SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY is missing. Rejecting request.",
|
|
2692
2742
|
{ ip: req.ip }
|
|
2693
2743
|
);
|
|
2694
2744
|
res.status(503).json(
|
|
2695
2745
|
apiError(
|
|
2696
2746
|
"internal_error",
|
|
2697
2747
|
"AUTH_NOT_CONFIGURED",
|
|
2698
|
-
"
|
|
2748
|
+
"Hosted API key authentication is selected but not configured. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY, or set HIVE_AUTH_BACKEND=static with HIVE_API_KEYS.",
|
|
2699
2749
|
{ requestId: req.requestId }
|
|
2700
2750
|
)
|
|
2701
2751
|
);
|
|
2702
2752
|
return;
|
|
2703
2753
|
}
|
|
2704
|
-
if (
|
|
2754
|
+
if (isHostedKeysConfigured()) {
|
|
2705
2755
|
if (!key) {
|
|
2706
2756
|
res.status(401).json(
|
|
2707
2757
|
apiError(
|
|
@@ -2790,7 +2840,7 @@ function requireApiKey(req, res, next) {
|
|
|
2790
2840
|
}
|
|
2791
2841
|
if (consumeResult.code === "no_wallet") {
|
|
2792
2842
|
secureLogger.warn(
|
|
2793
|
-
"consume_credits returned no_wallet for valid
|
|
2843
|
+
"consume_credits returned no_wallet for a valid API key",
|
|
2794
2844
|
{ userId: result.userId, keyId: result.keyId }
|
|
2795
2845
|
);
|
|
2796
2846
|
res.status(403).json(
|
|
@@ -2827,7 +2877,7 @@ function requireApiKey(req, res, next) {
|
|
|
2827
2877
|
}
|
|
2828
2878
|
}).catch((err) => {
|
|
2829
2879
|
secureLogger.error(
|
|
2830
|
-
"
|
|
2880
|
+
"API key verification failed \u2014 rejecting request",
|
|
2831
2881
|
err,
|
|
2832
2882
|
{
|
|
2833
2883
|
ip: req.ip
|
|
@@ -2847,14 +2897,14 @@ function requireApiKey(req, res, next) {
|
|
|
2847
2897
|
const validKeys = getValidKeySet();
|
|
2848
2898
|
if (validKeys.size === 0) {
|
|
2849
2899
|
secureLogger.warn(
|
|
2850
|
-
"No API key backend configured (HIVE_API_KEYS /
|
|
2900
|
+
"No API key backend configured (HIVE_API_KEYS / hosted keys). Rejecting request.",
|
|
2851
2901
|
{ ip: req.ip }
|
|
2852
2902
|
);
|
|
2853
2903
|
res.status(503).json(
|
|
2854
2904
|
apiError(
|
|
2855
2905
|
"internal_error",
|
|
2856
2906
|
"AUTH_NOT_CONFIGURED",
|
|
2857
|
-
"API key authentication is not configured. Set HIVE_API_KEYS or
|
|
2907
|
+
"API key authentication is not configured. Set HIVE_API_KEYS, or SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY for hosted keys.",
|
|
2858
2908
|
{ requestId: req.requestId }
|
|
2859
2909
|
)
|
|
2860
2910
|
);
|
|
@@ -3522,14 +3572,14 @@ var SIGNED_SUBJECT_HEADERS = [
|
|
|
3522
3572
|
var SIGNATURE_PAYLOAD = 'METHOD + "\\n" + PATH + "\\n" + TENANT_ID + "\\n" + END_USER_ID + "\\n" + TIMESTAMP + ("\\n" + BODY_SHA256 when X-Hive-Subject-Body-Sha256 is sent)';
|
|
3523
3573
|
function buildB2BReadinessPayload(args) {
|
|
3524
3574
|
const meta = args.verifyResult?.meta;
|
|
3525
|
-
const b2bEnabled = args.authBackend === "
|
|
3526
|
-
const secretConfigured = args.authBackend === "
|
|
3575
|
+
const b2bEnabled = args.authBackend === "hosted" ? isB2BSubjectsEnabled(meta) : false;
|
|
3576
|
+
const secretConfigured = args.authBackend === "hosted" && b2bEnabled ? hasSubjectSigningSecret(meta) : false;
|
|
3527
3577
|
const warnings = [];
|
|
3528
3578
|
let mode;
|
|
3529
3579
|
if (args.authBackend === "static") {
|
|
3530
3580
|
mode = "static_key";
|
|
3531
3581
|
warnings.push(
|
|
3532
|
-
"Static HIVE_API_KEYS authentication does not provide a Hive owner user_id or per-key B2B subject metadata. Use
|
|
3582
|
+
"Static HIVE_API_KEYS authentication does not provide a Hive owner user_id or per-key B2B subject metadata. Use hosted Hive keys for partner/end-user state isolation."
|
|
3533
3583
|
);
|
|
3534
3584
|
} else if (b2bEnabled) {
|
|
3535
3585
|
mode = "b2b_enabled";
|
|
@@ -3545,7 +3595,7 @@ function buildB2BReadinessPayload(args) {
|
|
|
3545
3595
|
);
|
|
3546
3596
|
}
|
|
3547
3597
|
return {
|
|
3548
|
-
b2b_adapter_ready: args.authBackend === "
|
|
3598
|
+
b2b_adapter_ready: args.authBackend === "hosted" && b2bEnabled && secretConfigured,
|
|
3549
3599
|
mode,
|
|
3550
3600
|
auth_backend: args.authBackend,
|
|
3551
3601
|
api_key: {
|
|
@@ -3558,7 +3608,7 @@ function buildB2BReadinessPayload(args) {
|
|
|
3558
3608
|
subject_signing_secret_configured: secretConfigured
|
|
3559
3609
|
},
|
|
3560
3610
|
state: {
|
|
3561
|
-
stateful_tools_supported: args.authBackend === "
|
|
3611
|
+
stateful_tools_supported: args.authBackend === "hosted",
|
|
3562
3612
|
direct_user_subject: "default_self",
|
|
3563
3613
|
signed_subjects_required_for_stateful_writes: b2bEnabled,
|
|
3564
3614
|
isolation_boundary: "owner_user_id + subject_id"
|
|
@@ -3609,17 +3659,17 @@ router5.get(
|
|
|
3609
3659
|
)
|
|
3610
3660
|
);
|
|
3611
3661
|
}
|
|
3612
|
-
if (
|
|
3662
|
+
if (isHostedKeysRequired() && !isHostedKeysConfigured()) {
|
|
3613
3663
|
return res.status(503).json(
|
|
3614
3664
|
apiError(
|
|
3615
3665
|
"internal_error",
|
|
3616
3666
|
"AUTH_NOT_CONFIGURED",
|
|
3617
|
-
"
|
|
3667
|
+
"Hosted API key authentication is selected but not configured. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY, or set HIVE_AUTH_BACKEND=static with HIVE_API_KEYS.",
|
|
3618
3668
|
{ requestId: req.requestId }
|
|
3619
3669
|
)
|
|
3620
3670
|
);
|
|
3621
3671
|
}
|
|
3622
|
-
if (
|
|
3672
|
+
if (isHostedKeysConfigured()) {
|
|
3623
3673
|
const result = await verifyApiKey(key, [
|
|
3624
3674
|
"service=hive",
|
|
3625
3675
|
"transport=rest",
|
|
@@ -3652,7 +3702,7 @@ router5.get(
|
|
|
3652
3702
|
return res.json({
|
|
3653
3703
|
ok: true,
|
|
3654
3704
|
data: buildB2BReadinessPayload({
|
|
3655
|
-
authBackend: "
|
|
3705
|
+
authBackend: "hosted",
|
|
3656
3706
|
verifyResult: result,
|
|
3657
3707
|
// Optional in the payload: a plan lookup failure must not fail the
|
|
3658
3708
|
// readiness check, so it omits plan_id instead.
|
|
@@ -3666,7 +3716,7 @@ router5.get(
|
|
|
3666
3716
|
apiError(
|
|
3667
3717
|
"internal_error",
|
|
3668
3718
|
"AUTH_NOT_CONFIGURED",
|
|
3669
|
-
"API key authentication is not configured. Set HIVE_API_KEYS or
|
|
3719
|
+
"API key authentication is not configured. Set HIVE_API_KEYS, or SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY for hosted keys.",
|
|
3670
3720
|
{ requestId: req.requestId }
|
|
3671
3721
|
)
|
|
3672
3722
|
);
|
|
@@ -4040,12 +4090,12 @@ var BILLING_UNAVAILABLE = apiError(
|
|
|
4040
4090
|
function requireBillingPrincipal(req, res, next) {
|
|
4041
4091
|
const apiKeyHeader = req.headers["x-api-key"];
|
|
4042
4092
|
if (typeof apiKeyHeader === "string" && apiKeyHeader.length > 0) {
|
|
4043
|
-
if (!
|
|
4093
|
+
if (!isHostedKeysConfigured()) {
|
|
4044
4094
|
res.status(503).json(
|
|
4045
4095
|
apiError(
|
|
4046
4096
|
"internal_error",
|
|
4047
4097
|
"AUTH_NOT_CONFIGURED",
|
|
4048
|
-
"API-key billing requires
|
|
4098
|
+
"API-key billing requires hosted Hive keys. Next action: sign in to the dashboard and upgrade from the billing tab."
|
|
4049
4099
|
)
|
|
4050
4100
|
);
|
|
4051
4101
|
return;
|
|
@@ -5832,7 +5882,6 @@ function buildServerCard() {
|
|
|
5832
5882
|
import { timingSafeEqual as timingSafeEqual5 } from "crypto";
|
|
5833
5883
|
import express from "express";
|
|
5834
5884
|
import rateLimit2 from "express-rate-limit";
|
|
5835
|
-
import RedisStore2 from "rate-limit-redis";
|
|
5836
5885
|
import { z as z4 } from "zod";
|
|
5837
5886
|
import {
|
|
5838
5887
|
createOAuthMetadata,
|
|
@@ -5873,15 +5922,7 @@ function metadataHeaders(res) {
|
|
|
5873
5922
|
function oauthRateLimitOptions(prefix) {
|
|
5874
5923
|
const redis = getRedisClient();
|
|
5875
5924
|
return {
|
|
5876
|
-
...redis ? {
|
|
5877
|
-
store: new RedisStore2({
|
|
5878
|
-
sendCommand: ((...args) => redis.call(
|
|
5879
|
-
args[0],
|
|
5880
|
-
...args.slice(1)
|
|
5881
|
-
)),
|
|
5882
|
-
prefix
|
|
5883
|
-
})
|
|
5884
|
-
} : {},
|
|
5925
|
+
...redis ? { store: new RedisRateLimitStore(redis, prefix) } : {},
|
|
5885
5926
|
keyGenerator: (req) => ipRateLimitKeyFromRequest(req)
|
|
5886
5927
|
};
|
|
5887
5928
|
}
|
|
@@ -6617,7 +6658,7 @@ async function recordOAuthFirstMaterialReceipt(input, overrides = {}) {
|
|
|
6617
6658
|
}
|
|
6618
6659
|
|
|
6619
6660
|
// src/server.ts
|
|
6620
|
-
|
|
6661
|
+
loadEnvFile();
|
|
6621
6662
|
var isShuttingDown = false;
|
|
6622
6663
|
var activeRequests = 0;
|
|
6623
6664
|
var app = express2();
|
|
@@ -6628,6 +6669,10 @@ function createHttpApp() {
|
|
|
6628
6669
|
}
|
|
6629
6670
|
app.set("trust proxy", resolveTrustedProxies());
|
|
6630
6671
|
app.use(requestIdMiddleware);
|
|
6672
|
+
app.use((_req, res, next) => {
|
|
6673
|
+
res.setHeader("X-Robots-Tag", "noindex, nofollow");
|
|
6674
|
+
next();
|
|
6675
|
+
});
|
|
6631
6676
|
app.use((_req, res, next) => {
|
|
6632
6677
|
if (isShuttingDown) {
|
|
6633
6678
|
res.setHeader("Connection", "close");
|
|
@@ -7015,15 +7060,15 @@ function extractApiKey(req) {
|
|
|
7015
7060
|
}
|
|
7016
7061
|
async function validateMcpApiKey(req) {
|
|
7017
7062
|
const key = extractApiKey(req);
|
|
7018
|
-
if (
|
|
7063
|
+
if (isHostedKeysRequired() && !isHostedKeysConfigured()) {
|
|
7019
7064
|
return {
|
|
7020
7065
|
ok: false,
|
|
7021
7066
|
code: "AUTH_NOT_CONFIGURED",
|
|
7022
7067
|
retryable: false,
|
|
7023
|
-
error: "
|
|
7068
|
+
error: "Hosted API key authentication is selected but not configured. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY, or set HIVE_AUTH_BACKEND=static with HIVE_API_KEYS."
|
|
7024
7069
|
};
|
|
7025
7070
|
}
|
|
7026
|
-
if (
|
|
7071
|
+
if (isHostedKeysConfigured()) {
|
|
7027
7072
|
if (!key)
|
|
7028
7073
|
return {
|
|
7029
7074
|
ok: false,
|
|
@@ -7035,10 +7080,10 @@ async function validateMcpApiKey(req) {
|
|
|
7035
7080
|
try {
|
|
7036
7081
|
result = await withTimeout(
|
|
7037
7082
|
verifyApiKey(key, getMcpAnalyticsTags(req)),
|
|
7038
|
-
|
|
7083
|
+
2e3
|
|
7039
7084
|
);
|
|
7040
7085
|
} catch (err) {
|
|
7041
|
-
secureLogger.warn("MCP
|
|
7086
|
+
secureLogger.warn("MCP verifyApiKey timeout/failure", {
|
|
7042
7087
|
error: err instanceof Error ? err.message : String(err)
|
|
7043
7088
|
});
|
|
7044
7089
|
return {
|
|
@@ -7341,8 +7386,8 @@ async function resolveRestSubjectContextMiddleware(req, res, next) {
|
|
|
7341
7386
|
const requiresSignedSubject = isHiveStatefulWriteTool(hiveToolName);
|
|
7342
7387
|
const subject = await resolveSubjectContext({
|
|
7343
7388
|
userId: authReq.userId,
|
|
7344
|
-
keyId: authReq.
|
|
7345
|
-
keyMeta: authReq.
|
|
7389
|
+
keyId: authReq.apiKeyId,
|
|
7390
|
+
keyMeta: authReq.apiKeyResult?.meta,
|
|
7346
7391
|
method: req.method,
|
|
7347
7392
|
path: req.path,
|
|
7348
7393
|
// The official B2B adapter signs both reads and writes. Writes require a
|
|
@@ -8558,7 +8603,7 @@ app.post(
|
|
|
8558
8603
|
toolName: endpoint.tool.name,
|
|
8559
8604
|
userId: authReq.userId,
|
|
8560
8605
|
subjectContext: authReq.hiveSubjectContext,
|
|
8561
|
-
keyId: authReq.
|
|
8606
|
+
keyId: authReq.apiKeyId,
|
|
8562
8607
|
// REST is the API-key transport; OAuth tokens are MCP-only.
|
|
8563
8608
|
authMethod: "api_key",
|
|
8564
8609
|
requestId: req.requestId
|
|
@@ -8662,42 +8707,8 @@ app.post("/api/v1/telemetry", (req, res) => {
|
|
|
8662
8707
|
app.get("/api/openapi.json", (_req, res) => {
|
|
8663
8708
|
res.json(generateOpenApiSpec());
|
|
8664
8709
|
});
|
|
8665
|
-
var require2 = createNodeRequire(import.meta.url);
|
|
8666
|
-
var swaggerUiAssetPath = require2("swagger-ui-dist/absolute-path.js")();
|
|
8667
|
-
app.use(
|
|
8668
|
-
"/docs/assets",
|
|
8669
|
-
express2.static(swaggerUiAssetPath, {
|
|
8670
|
-
dotfiles: "deny",
|
|
8671
|
-
fallthrough: false,
|
|
8672
|
-
immutable: true,
|
|
8673
|
-
index: false,
|
|
8674
|
-
maxAge: "1y"
|
|
8675
|
-
})
|
|
8676
|
-
);
|
|
8677
8710
|
app.get("/docs", (_req, res) => {
|
|
8678
|
-
|
|
8679
|
-
res.setHeader("Content-Type", "text/html");
|
|
8680
|
-
res.send(`<!DOCTYPE html>
|
|
8681
|
-
<html lang="en">
|
|
8682
|
-
<head>
|
|
8683
|
-
<meta charset="UTF-8">
|
|
8684
|
-
<title>Hive API Docs</title>
|
|
8685
|
-
<link rel="stylesheet" href="/docs/assets/swagger-ui.css">
|
|
8686
|
-
</head>
|
|
8687
|
-
<body>
|
|
8688
|
-
<div id="swagger-ui"></div>
|
|
8689
|
-
<script src="/docs/assets/swagger-ui-bundle.js"></script>
|
|
8690
|
-
<script nonce="${nonce}">
|
|
8691
|
-
SwaggerUIBundle({
|
|
8692
|
-
url: '/api/openapi.json',
|
|
8693
|
-
dom_id: '#swagger-ui',
|
|
8694
|
-
deepLinking: true,
|
|
8695
|
-
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
|
8696
|
-
layout: 'BaseLayout',
|
|
8697
|
-
});
|
|
8698
|
-
</script>
|
|
8699
|
-
</body>
|
|
8700
|
-
</html>`);
|
|
8711
|
+
res.redirect(301, "https://docs.hiveintelligence.xyz");
|
|
8701
8712
|
});
|
|
8702
8713
|
app.get("/", (_req, res) => {
|
|
8703
8714
|
res.json({
|
package/build/stdio.js
CHANGED
|
@@ -6,9 +6,10 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
createHiveMcpServer,
|
|
8
8
|
secureLogger
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QSKFAT7Z.js";
|
|
10
10
|
import "./chunk-QYK3EWTE.js";
|
|
11
11
|
import "./chunk-EPF36Q3Z.js";
|
|
12
|
+
import "./chunk-MYSS5SBE.js";
|
|
12
13
|
import {
|
|
13
14
|
SERVER_NAME,
|
|
14
15
|
SERVER_VERSION
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
fetchToolCatalog
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VO6NWVJD.js";
|
|
5
5
|
import {
|
|
6
6
|
canonicalParamName,
|
|
7
7
|
describeParameters
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-WZ2NMSV3.js";
|
|
9
|
+
import "./chunk-4U4IL5KA.js";
|
|
10
10
|
import "./chunk-ZXKFJQDE.js";
|
|
11
11
|
import {
|
|
12
12
|
info,
|
|
@@ -25,7 +25,7 @@ async function loadToolCatalog() {
|
|
|
25
25
|
const response = await fetchToolCatalog();
|
|
26
26
|
if (!response.ok) {
|
|
27
27
|
const msg = response.error && typeof response.error === "object" && "message" in response.error ? String(response.error.message) : "Failed to fetch tool catalog";
|
|
28
|
-
const { CliError } = await import("./errors-
|
|
28
|
+
const { CliError } = await import("./errors-BPXK3KCR.js");
|
|
29
29
|
const { outputError } = await import("./output-BBHBJI32.js");
|
|
30
30
|
await outputError(new CliError("API_ERROR", msg, "Check: hive doctor"), {});
|
|
31
31
|
return [];
|
|
@@ -177,7 +177,7 @@ async function toolInfo(name, reservedNames = /* @__PURE__ */ new Set()) {
|
|
|
177
177
|
const allTools = await loadToolCatalog();
|
|
178
178
|
const tool = allTools.find((t) => t.name === name);
|
|
179
179
|
if (!tool) {
|
|
180
|
-
const { CliError, suggestSimilarTools } = await import("./errors-
|
|
180
|
+
const { CliError, suggestSimilarTools } = await import("./errors-BPXK3KCR.js");
|
|
181
181
|
const { outputError } = await import("./output-BBHBJI32.js");
|
|
182
182
|
const similar = suggestSimilarTools(
|
|
183
183
|
name,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-5J4CWTI5.js";
|
|
6
6
|
import {
|
|
7
7
|
removeRecordedRoutingBlocks
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PODCJTBV.js";
|
|
9
9
|
import {
|
|
10
10
|
removeClaudeCodeUserConfig,
|
|
11
11
|
removeClaudeDesktopConfig,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
removeVscodeConfig,
|
|
16
16
|
removeWindsurfConfig
|
|
17
17
|
} from "./chunk-QDZ7MAVN.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-4U4IL5KA.js";
|
|
19
19
|
import "./chunk-QYK3EWTE.js";
|
|
20
20
|
import {
|
|
21
21
|
bold,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
executeTool
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-O5YKCM67.js";
|
|
5
5
|
import "./chunk-XN3T6YOG.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-VO6NWVJD.js";
|
|
7
7
|
import "./chunk-RU6QOFHH.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-4U4IL5KA.js";
|
|
9
9
|
import "./chunk-EPF36Q3Z.js";
|
|
10
10
|
import "./chunk-ZXKFJQDE.js";
|
|
11
11
|
import "./chunk-ZDXMZPC6.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hive-intelligence",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "Evidence-backed crypto due diligence for AI agents, with sources, freshness, and a runtime receipt on every call.",
|
|
5
5
|
"mcpName": "xyz.hiveintelligence/mcp",
|
|
6
6
|
"type": "module",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"inspector": "npx @modelcontextprotocol/inspector --cli --config '{\"mcpServers\":{\"hive\":{\"url\":\"http://localhost:8080/mcp\"}}}'",
|
|
21
21
|
"start:http": "tsx src/server.ts",
|
|
22
22
|
"dev:http": "tsx src/server.ts",
|
|
23
|
-
"start": "
|
|
24
|
-
"dev": "
|
|
23
|
+
"start": "SERVER_MODE=MCP tsx src/stdio.ts",
|
|
24
|
+
"dev": "SERVER_MODE=MCP tsx src/stdio.ts",
|
|
25
25
|
"test": "vitest run",
|
|
26
26
|
"test:client": "npm --workspace hive-mcp-client run test",
|
|
27
27
|
"test:watch": "vitest",
|
|
@@ -128,30 +128,19 @@
|
|
|
128
128
|
"node": ">=22.12.0"
|
|
129
129
|
},
|
|
130
130
|
"dependencies": {
|
|
131
|
-
"@cloudflare/cabidela": "^0.2.4",
|
|
132
131
|
"@coingecko/coingecko-typescript": "^8.0.0",
|
|
133
132
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
134
133
|
"@supabase/supabase-js": "^2.115.0",
|
|
135
|
-
"@types/compression": "^1.8.1",
|
|
136
|
-
"@unkey/api": "2.5.0",
|
|
137
134
|
"ajv": "^8.18.0",
|
|
138
135
|
"ajv-formats": "^3.0.1",
|
|
139
|
-
"axios": "^1.20.0",
|
|
140
136
|
"ccxt": "^4.5.77",
|
|
141
137
|
"commander": "^15.0.0",
|
|
142
138
|
"compression": "^1.8.2",
|
|
143
139
|
"cors": "2.8.6",
|
|
144
|
-
"dotenv": "17.4.2",
|
|
145
140
|
"express": "^5.2.1",
|
|
146
141
|
"express-rate-limit": "^8.5.2",
|
|
147
|
-
"fastest-levenshtein": "^1.0.16",
|
|
148
142
|
"helmet": "^8.2.0",
|
|
149
143
|
"ioredis": "^5.11.1",
|
|
150
|
-
"ora": "^9.4.1",
|
|
151
|
-
"rate-limit-redis": "^5.0.0",
|
|
152
|
-
"swagger-ui-dist": "5.32.8",
|
|
153
|
-
"tsx": "4.23.0",
|
|
154
|
-
"winston": "3.19.0",
|
|
155
144
|
"zod": "^4.6.7"
|
|
156
145
|
},
|
|
157
146
|
"overrides": {
|
|
@@ -168,13 +157,14 @@
|
|
|
168
157
|
"source-map-js": "1.2.2"
|
|
169
158
|
},
|
|
170
159
|
"devDependencies": {
|
|
160
|
+
"@types/compression": "^1.8.1",
|
|
171
161
|
"@types/cors": "^2.8.19",
|
|
172
162
|
"@types/express": "^5.0.6",
|
|
173
163
|
"@types/node": "^24.13.3",
|
|
174
164
|
"@vitest/coverage-v8": "4.1.11",
|
|
175
|
-
"cross-env": "10.1.0",
|
|
176
165
|
"github-actionlint": "1.7.12",
|
|
177
166
|
"tsup": "8.5.1",
|
|
167
|
+
"tsx": "4.23.0",
|
|
178
168
|
"typescript": "^7.0.2",
|
|
179
169
|
"vitest": "^4.1.11"
|
|
180
170
|
},
|