@blockrun/clawrouter 0.10.5 → 0.10.6
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/dist/cli.js +169 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +80 -1
- package/dist/index.js +245 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -738,6 +738,10 @@ type UsageEntry = {
|
|
|
738
738
|
baselineCost: number;
|
|
739
739
|
savings: number;
|
|
740
740
|
latencyMs: number;
|
|
741
|
+
/** Partner service ID (e.g., "x_users_lookup") — only set for partner API calls */
|
|
742
|
+
partnerId?: string;
|
|
743
|
+
/** Partner service name (e.g., "AttentionVC") — only set for partner API calls */
|
|
744
|
+
service?: string;
|
|
741
745
|
};
|
|
742
746
|
/**
|
|
743
747
|
* Log a usage entry as a JSON line.
|
|
@@ -991,6 +995,81 @@ declare function getStats(days?: number): Promise<AggregatedStats>;
|
|
|
991
995
|
*/
|
|
992
996
|
declare function formatStatsAscii(stats: AggregatedStats): string;
|
|
993
997
|
|
|
998
|
+
/**
|
|
999
|
+
* Partner Service Registry
|
|
1000
|
+
*
|
|
1001
|
+
* Defines available partner APIs that can be called through ClawRouter's proxy.
|
|
1002
|
+
* Partners provide specialized data (Twitter/X, etc.) via x402 micropayments.
|
|
1003
|
+
* The same wallet used for LLM calls pays for partner API calls — zero extra setup.
|
|
1004
|
+
*/
|
|
1005
|
+
type PartnerServiceParam = {
|
|
1006
|
+
name: string;
|
|
1007
|
+
type: "string" | "string[]" | "number";
|
|
1008
|
+
description: string;
|
|
1009
|
+
required: boolean;
|
|
1010
|
+
};
|
|
1011
|
+
type PartnerServiceDefinition = {
|
|
1012
|
+
/** Unique service ID used in tool names: blockrun_{id} */
|
|
1013
|
+
id: string;
|
|
1014
|
+
/** Human-readable name */
|
|
1015
|
+
name: string;
|
|
1016
|
+
/** Partner providing this service */
|
|
1017
|
+
partner: string;
|
|
1018
|
+
/** Short description for tool listing */
|
|
1019
|
+
description: string;
|
|
1020
|
+
/** Proxy path (relative to /v1) */
|
|
1021
|
+
proxyPath: string;
|
|
1022
|
+
/** HTTP method */
|
|
1023
|
+
method: "GET" | "POST";
|
|
1024
|
+
/** Parameters for the tool's JSON Schema */
|
|
1025
|
+
params: PartnerServiceParam[];
|
|
1026
|
+
/** Pricing info for display */
|
|
1027
|
+
pricing: {
|
|
1028
|
+
perUnit: string;
|
|
1029
|
+
unit: string;
|
|
1030
|
+
minimum: string;
|
|
1031
|
+
maximum: string;
|
|
1032
|
+
};
|
|
1033
|
+
/** Example usage for help text */
|
|
1034
|
+
example: {
|
|
1035
|
+
input: Record<string, unknown>;
|
|
1036
|
+
description: string;
|
|
1037
|
+
};
|
|
1038
|
+
};
|
|
1039
|
+
/**
|
|
1040
|
+
* All registered partner services.
|
|
1041
|
+
* New partners are added here — the rest of the system picks them up automatically.
|
|
1042
|
+
*/
|
|
1043
|
+
declare const PARTNER_SERVICES: PartnerServiceDefinition[];
|
|
1044
|
+
/**
|
|
1045
|
+
* Get a partner service by ID.
|
|
1046
|
+
*/
|
|
1047
|
+
declare function getPartnerService(id: string): PartnerServiceDefinition | undefined;
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* Partner Tool Builder
|
|
1051
|
+
*
|
|
1052
|
+
* Converts partner service definitions into OpenClaw tool definitions.
|
|
1053
|
+
* Each tool's execute() calls through the local proxy which handles
|
|
1054
|
+
* x402 payment transparently using the same wallet.
|
|
1055
|
+
*/
|
|
1056
|
+
/** OpenClaw tool definition shape (duck-typed) */
|
|
1057
|
+
type PartnerToolDefinition = {
|
|
1058
|
+
name: string;
|
|
1059
|
+
description: string;
|
|
1060
|
+
inputSchema: {
|
|
1061
|
+
type: "object";
|
|
1062
|
+
properties: Record<string, unknown>;
|
|
1063
|
+
required: string[];
|
|
1064
|
+
};
|
|
1065
|
+
execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
1066
|
+
};
|
|
1067
|
+
/**
|
|
1068
|
+
* Build OpenClaw tool definitions for all registered partner services.
|
|
1069
|
+
* @param proxyBaseUrl - Local proxy base URL (e.g., "http://127.0.0.1:8402")
|
|
1070
|
+
*/
|
|
1071
|
+
declare function buildPartnerTools(proxyBaseUrl: string): PartnerToolDefinition[];
|
|
1072
|
+
|
|
994
1073
|
/**
|
|
995
1074
|
* @blockrun/clawrouter
|
|
996
1075
|
*
|
|
@@ -1012,4 +1091,4 @@ declare function formatStatsAscii(stats: AggregatedStats): string;
|
|
|
1012
1091
|
|
|
1013
1092
|
declare const plugin: OpenClawPluginDefinition;
|
|
1014
1093
|
|
|
1015
|
-
export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedLLMResponse, type CachedPaymentParams, type CachedResponse, DEFAULT_RETRY_CONFIG, DEFAULT_ROUTING_CONFIG, DEFAULT_SESSION_CONFIG, type DailyStats, EmptyWalletError, InsufficientFundsError, type InsufficientFundsInfo, type LowBalanceInfo, MODEL_ALIASES, OPENCLAW_MODELS, PaymentCache, type PaymentFetchResult, type PreAuthParams, type ProxyHandle, type ProxyOptions, RequestDeduplicator, ResponseCache, type ResponseCacheConfig, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SessionConfig, type SessionEntry, SessionStore, type SufficiencyResult, type Tier, type UsageEntry, blockrunProvider, buildProviderModels, calculateModelCost, createPaymentFetch, plugin as default, fetchWithRetry, formatStatsAscii, getAgenticModels, getFallbackChain, getFallbackChainFiltered, getModelContextWindow, getProxyPort, getSessionId, getStats, isAgenticModel, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, logUsage, resolveModelAlias, route, startProxy };
|
|
1094
|
+
export { type AggregatedStats, BALANCE_THRESHOLDS, BLOCKRUN_MODELS, type BalanceInfo, BalanceMonitor, type CachedLLMResponse, type CachedPaymentParams, type CachedResponse, DEFAULT_RETRY_CONFIG, DEFAULT_ROUTING_CONFIG, DEFAULT_SESSION_CONFIG, type DailyStats, EmptyWalletError, InsufficientFundsError, type InsufficientFundsInfo, type LowBalanceInfo, MODEL_ALIASES, OPENCLAW_MODELS, PARTNER_SERVICES, type PartnerServiceDefinition, type PartnerToolDefinition, PaymentCache, type PaymentFetchResult, type PreAuthParams, type ProxyHandle, type ProxyOptions, RequestDeduplicator, ResponseCache, type ResponseCacheConfig, type RetryConfig, type RoutingConfig, type RoutingDecision, RpcError, type SessionConfig, type SessionEntry, SessionStore, type SufficiencyResult, type Tier, type UsageEntry, blockrunProvider, buildPartnerTools, buildProviderModels, calculateModelCost, createPaymentFetch, plugin as default, fetchWithRetry, formatStatsAscii, getAgenticModels, getFallbackChain, getFallbackChainFiltered, getModelContextWindow, getPartnerService, getProxyPort, getSessionId, getStats, isAgenticModel, isBalanceError, isEmptyWalletError, isInsufficientFundsError, isRetryable, isRpcError, logUsage, resolveModelAlias, route, startProxy };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,126 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/partners/registry.ts
|
|
12
|
+
function getPartnerService(id) {
|
|
13
|
+
return PARTNER_SERVICES.find((s) => s.id === id);
|
|
14
|
+
}
|
|
15
|
+
var PARTNER_SERVICES;
|
|
16
|
+
var init_registry = __esm({
|
|
17
|
+
"src/partners/registry.ts"() {
|
|
18
|
+
"use strict";
|
|
19
|
+
PARTNER_SERVICES = [
|
|
20
|
+
{
|
|
21
|
+
id: "x_users_lookup",
|
|
22
|
+
name: "Twitter/X User Lookup",
|
|
23
|
+
partner: "AttentionVC",
|
|
24
|
+
description: "Look up Twitter/X user profiles by username. Returns follower counts, verification status, bio, and more. Accepts up to 100 usernames per request.",
|
|
25
|
+
proxyPath: "/x/users/lookup",
|
|
26
|
+
method: "POST",
|
|
27
|
+
params: [
|
|
28
|
+
{
|
|
29
|
+
name: "usernames",
|
|
30
|
+
type: "string[]",
|
|
31
|
+
description: 'Array of Twitter/X usernames to look up (without @ prefix). Example: ["elonmusk", "naval"]',
|
|
32
|
+
required: true
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
pricing: {
|
|
36
|
+
perUnit: "$0.001",
|
|
37
|
+
unit: "user",
|
|
38
|
+
minimum: "$0.01 (10 users)",
|
|
39
|
+
maximum: "$0.10 (100 users)"
|
|
40
|
+
},
|
|
41
|
+
example: {
|
|
42
|
+
input: { usernames: ["elonmusk", "naval", "balaboris"] },
|
|
43
|
+
description: "Look up 3 Twitter/X user profiles"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// src/partners/tools.ts
|
|
51
|
+
function buildTool(service, proxyBaseUrl) {
|
|
52
|
+
const properties = {};
|
|
53
|
+
const required = [];
|
|
54
|
+
for (const param of service.params) {
|
|
55
|
+
const prop = {
|
|
56
|
+
description: param.description
|
|
57
|
+
};
|
|
58
|
+
if (param.type === "string[]") {
|
|
59
|
+
prop.type = "array";
|
|
60
|
+
prop.items = { type: "string" };
|
|
61
|
+
} else {
|
|
62
|
+
prop.type = param.type;
|
|
63
|
+
}
|
|
64
|
+
properties[param.name] = prop;
|
|
65
|
+
if (param.required) {
|
|
66
|
+
required.push(param.name);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
name: `blockrun_${service.id}`,
|
|
71
|
+
description: [
|
|
72
|
+
service.description,
|
|
73
|
+
"",
|
|
74
|
+
`Partner: ${service.partner}`,
|
|
75
|
+
`Pricing: ${service.pricing.perUnit} per ${service.pricing.unit} (min: ${service.pricing.minimum}, max: ${service.pricing.maximum})`
|
|
76
|
+
].join("\n"),
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties,
|
|
80
|
+
required
|
|
81
|
+
},
|
|
82
|
+
execute: async (args) => {
|
|
83
|
+
const url = `${proxyBaseUrl}/v1${service.proxyPath}`;
|
|
84
|
+
const response = await fetch(url, {
|
|
85
|
+
method: service.method,
|
|
86
|
+
headers: { "Content-Type": "application/json" },
|
|
87
|
+
body: JSON.stringify(args)
|
|
88
|
+
});
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
const errText = await response.text().catch(() => "");
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Partner API error (${response.status}): ${errText || response.statusText}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
return response.json();
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function buildPartnerTools(proxyBaseUrl) {
|
|
100
|
+
return PARTNER_SERVICES.map((service) => buildTool(service, proxyBaseUrl));
|
|
101
|
+
}
|
|
102
|
+
var init_tools = __esm({
|
|
103
|
+
"src/partners/tools.ts"() {
|
|
104
|
+
"use strict";
|
|
105
|
+
init_registry();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// src/partners/index.ts
|
|
110
|
+
var partners_exports = {};
|
|
111
|
+
__export(partners_exports, {
|
|
112
|
+
PARTNER_SERVICES: () => PARTNER_SERVICES,
|
|
113
|
+
buildPartnerTools: () => buildPartnerTools,
|
|
114
|
+
getPartnerService: () => getPartnerService
|
|
115
|
+
});
|
|
116
|
+
var init_partners = __esm({
|
|
117
|
+
"src/partners/index.ts"() {
|
|
118
|
+
"use strict";
|
|
119
|
+
init_registry();
|
|
120
|
+
init_tools();
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
1
124
|
// src/models.ts
|
|
2
125
|
var MODEL_ALIASES = {
|
|
3
126
|
// Claude - use newest versions (4.6)
|
|
@@ -2635,7 +2758,7 @@ function formatStatsAscii(stats) {
|
|
|
2635
2758
|
lines.push(`\u2551 Avg Latency: ${stats.avgLatencyMs.toFixed(0)}ms`.padEnd(61) + "\u2551");
|
|
2636
2759
|
lines.push("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563");
|
|
2637
2760
|
lines.push("\u2551 Routing by Tier: \u2551");
|
|
2638
|
-
const knownTiers = ["SIMPLE", "MEDIUM", "COMPLEX", "REASONING"];
|
|
2761
|
+
const knownTiers = ["SIMPLE", "MEDIUM", "COMPLEX", "REASONING", "DIRECT"];
|
|
2639
2762
|
const allTiers = Object.keys(stats.byTier);
|
|
2640
2763
|
const otherTiers = allTiers.filter((t) => !knownTiers.includes(t));
|
|
2641
2764
|
const tierOrder = [...knownTiers.filter((t) => stats.byTier[t]), ...otherTiers];
|
|
@@ -4745,6 +4868,63 @@ function estimateAmount(modelId, bodyLength, maxTokens) {
|
|
|
4745
4868
|
const amountMicros = Math.max(100, Math.ceil(costUsd * 1.2 * 1e6));
|
|
4746
4869
|
return amountMicros.toString();
|
|
4747
4870
|
}
|
|
4871
|
+
async function proxyPartnerRequest(req, res, apiBase, payFetch) {
|
|
4872
|
+
const startTime = Date.now();
|
|
4873
|
+
const upstreamUrl = `${apiBase}${req.url}`;
|
|
4874
|
+
const bodyChunks = [];
|
|
4875
|
+
for await (const chunk of req) {
|
|
4876
|
+
bodyChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
4877
|
+
}
|
|
4878
|
+
const body = Buffer.concat(bodyChunks);
|
|
4879
|
+
const headers = {};
|
|
4880
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
4881
|
+
if (key === "host" || key === "connection" || key === "transfer-encoding" || key === "content-length")
|
|
4882
|
+
continue;
|
|
4883
|
+
if (typeof value === "string") headers[key] = value;
|
|
4884
|
+
}
|
|
4885
|
+
if (!headers["content-type"]) headers["content-type"] = "application/json";
|
|
4886
|
+
headers["user-agent"] = USER_AGENT;
|
|
4887
|
+
console.log(`[ClawRouter] Partner request: ${req.method} ${req.url}`);
|
|
4888
|
+
const upstream = await payFetch(upstreamUrl, {
|
|
4889
|
+
method: req.method ?? "POST",
|
|
4890
|
+
headers,
|
|
4891
|
+
body: body.length > 0 ? new Uint8Array(body) : void 0
|
|
4892
|
+
});
|
|
4893
|
+
const responseHeaders = {};
|
|
4894
|
+
upstream.headers.forEach((value, key) => {
|
|
4895
|
+
if (key === "transfer-encoding" || key === "connection" || key === "content-encoding") return;
|
|
4896
|
+
responseHeaders[key] = value;
|
|
4897
|
+
});
|
|
4898
|
+
res.writeHead(upstream.status, responseHeaders);
|
|
4899
|
+
if (upstream.body) {
|
|
4900
|
+
const reader = upstream.body.getReader();
|
|
4901
|
+
try {
|
|
4902
|
+
while (true) {
|
|
4903
|
+
const { done, value } = await reader.read();
|
|
4904
|
+
if (done) break;
|
|
4905
|
+
safeWrite(res, Buffer.from(value));
|
|
4906
|
+
}
|
|
4907
|
+
} finally {
|
|
4908
|
+
reader.releaseLock();
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
res.end();
|
|
4912
|
+
const latencyMs = Date.now() - startTime;
|
|
4913
|
+
console.log(`[ClawRouter] Partner response: ${upstream.status} (${latencyMs}ms)`);
|
|
4914
|
+
logUsage({
|
|
4915
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4916
|
+
model: "partner",
|
|
4917
|
+
tier: "PARTNER",
|
|
4918
|
+
cost: 0,
|
|
4919
|
+
// Actual cost handled by x402 settlement
|
|
4920
|
+
baselineCost: 0,
|
|
4921
|
+
savings: 0,
|
|
4922
|
+
latencyMs,
|
|
4923
|
+
partnerId: (req.url?.split("?")[0] ?? "").replace(/^\/v1\//, "").replace(/\//g, "_") || "unknown",
|
|
4924
|
+
service: "partner"
|
|
4925
|
+
}).catch(() => {
|
|
4926
|
+
});
|
|
4927
|
+
}
|
|
4748
4928
|
async function startProxy(options) {
|
|
4749
4929
|
const apiBase = options.apiBase ?? BLOCKRUN_API;
|
|
4750
4930
|
const listenPort = options.port ?? getProxyPort();
|
|
@@ -4855,6 +5035,23 @@ async function startProxy(options) {
|
|
|
4855
5035
|
res.end(JSON.stringify({ object: "list", data: models }));
|
|
4856
5036
|
return;
|
|
4857
5037
|
}
|
|
5038
|
+
if (req.url?.match(/^\/v1\/(?:x|partner)\//)) {
|
|
5039
|
+
try {
|
|
5040
|
+
await proxyPartnerRequest(req, res, apiBase, payFetch);
|
|
5041
|
+
} catch (err) {
|
|
5042
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
5043
|
+
options.onError?.(error);
|
|
5044
|
+
if (!res.headersSent) {
|
|
5045
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
5046
|
+
res.end(
|
|
5047
|
+
JSON.stringify({
|
|
5048
|
+
error: { message: `Partner proxy error: ${error.message}`, type: "partner_error" }
|
|
5049
|
+
})
|
|
5050
|
+
);
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5053
|
+
return;
|
|
5054
|
+
}
|
|
4858
5055
|
if (!req.url?.startsWith("/v1")) {
|
|
4859
5056
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
4860
5057
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
@@ -5717,10 +5914,11 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5717
5914
|
}
|
|
5718
5915
|
throw err;
|
|
5719
5916
|
}
|
|
5720
|
-
|
|
5917
|
+
const logModel = routingDecision?.model ?? modelId;
|
|
5918
|
+
if (logModel) {
|
|
5721
5919
|
const estimatedInputTokens = Math.ceil(body.length / 4);
|
|
5722
5920
|
const accurateCosts = calculateModelCost(
|
|
5723
|
-
|
|
5921
|
+
logModel,
|
|
5724
5922
|
routerOpts.modelPricing,
|
|
5725
5923
|
estimatedInputTokens,
|
|
5726
5924
|
maxTokens,
|
|
@@ -5730,8 +5928,8 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5730
5928
|
const baselineWithBuffer = accurateCosts.baselineCost * 1.2;
|
|
5731
5929
|
const entry = {
|
|
5732
5930
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5733
|
-
model:
|
|
5734
|
-
tier: routingDecision
|
|
5931
|
+
model: logModel,
|
|
5932
|
+
tier: routingDecision?.tier ?? "DIRECT",
|
|
5735
5933
|
cost: costWithBuffer,
|
|
5736
5934
|
baselineCost: baselineWithBuffer,
|
|
5737
5935
|
savings: accurateCosts.savings,
|
|
@@ -5869,6 +6067,7 @@ function isRetryable(errorOrResponse, config) {
|
|
|
5869
6067
|
}
|
|
5870
6068
|
|
|
5871
6069
|
// src/index.ts
|
|
6070
|
+
init_partners();
|
|
5872
6071
|
async function waitForProxyHealth(port, timeoutMs = 3e3) {
|
|
5873
6072
|
const start = Date.now();
|
|
5874
6073
|
while (Date.now() - start < timeoutMs) {
|
|
@@ -6314,6 +6513,44 @@ var plugin = {
|
|
|
6314
6513
|
models: OPENCLAW_MODELS
|
|
6315
6514
|
};
|
|
6316
6515
|
api.logger.info("BlockRun provider registered (30+ models via x402)");
|
|
6516
|
+
try {
|
|
6517
|
+
const { buildPartnerTools: buildPartnerTools2, PARTNER_SERVICES: PARTNER_SERVICES2 } = await Promise.resolve().then(() => (init_partners(), partners_exports));
|
|
6518
|
+
const proxyBaseUrl = `http://127.0.0.1:${runtimePort}`;
|
|
6519
|
+
const partnerTools = buildPartnerTools2(proxyBaseUrl);
|
|
6520
|
+
for (const tool of partnerTools) {
|
|
6521
|
+
api.registerTool(tool);
|
|
6522
|
+
}
|
|
6523
|
+
if (partnerTools.length > 0) {
|
|
6524
|
+
api.logger.info(`Registered ${partnerTools.length} partner tool(s): ${partnerTools.map((t) => t.name).join(", ")}`);
|
|
6525
|
+
}
|
|
6526
|
+
api.registerCommand({
|
|
6527
|
+
name: "partners",
|
|
6528
|
+
description: "List available partner APIs and pricing",
|
|
6529
|
+
acceptsArgs: false,
|
|
6530
|
+
requireAuth: false,
|
|
6531
|
+
handler: async () => {
|
|
6532
|
+
if (PARTNER_SERVICES2.length === 0) {
|
|
6533
|
+
return { text: "No partner APIs available." };
|
|
6534
|
+
}
|
|
6535
|
+
const lines = [
|
|
6536
|
+
"**Partner APIs** (paid via your ClawRouter wallet)",
|
|
6537
|
+
""
|
|
6538
|
+
];
|
|
6539
|
+
for (const svc of PARTNER_SERVICES2) {
|
|
6540
|
+
lines.push(`**${svc.name}** (${svc.partner})`);
|
|
6541
|
+
lines.push(` ${svc.description}`);
|
|
6542
|
+
lines.push(` Tool: \`${`blockrun_${svc.id}`}\``);
|
|
6543
|
+
lines.push(` Pricing: ${svc.pricing.perUnit} per ${svc.pricing.unit} (min ${svc.pricing.minimum}, max ${svc.pricing.maximum})`);
|
|
6544
|
+
lines.push("");
|
|
6545
|
+
}
|
|
6546
|
+
return { text: lines.join("\n") };
|
|
6547
|
+
}
|
|
6548
|
+
});
|
|
6549
|
+
} catch (err) {
|
|
6550
|
+
api.logger.warn(
|
|
6551
|
+
`Failed to register partner tools: ${err instanceof Error ? err.message : String(err)}`
|
|
6552
|
+
);
|
|
6553
|
+
}
|
|
6317
6554
|
createWalletCommand().then((walletCommand) => {
|
|
6318
6555
|
api.registerCommand(walletCommand);
|
|
6319
6556
|
}).catch((err) => {
|
|
@@ -6388,12 +6625,14 @@ export {
|
|
|
6388
6625
|
InsufficientFundsError,
|
|
6389
6626
|
MODEL_ALIASES,
|
|
6390
6627
|
OPENCLAW_MODELS,
|
|
6628
|
+
PARTNER_SERVICES,
|
|
6391
6629
|
PaymentCache,
|
|
6392
6630
|
RequestDeduplicator,
|
|
6393
6631
|
ResponseCache,
|
|
6394
6632
|
RpcError,
|
|
6395
6633
|
SessionStore,
|
|
6396
6634
|
blockrunProvider,
|
|
6635
|
+
buildPartnerTools,
|
|
6397
6636
|
buildProviderModels,
|
|
6398
6637
|
calculateModelCost,
|
|
6399
6638
|
createPaymentFetch,
|
|
@@ -6404,6 +6643,7 @@ export {
|
|
|
6404
6643
|
getFallbackChain,
|
|
6405
6644
|
getFallbackChainFiltered,
|
|
6406
6645
|
getModelContextWindow,
|
|
6646
|
+
getPartnerService,
|
|
6407
6647
|
getProxyPort,
|
|
6408
6648
|
getSessionId,
|
|
6409
6649
|
getStats,
|