kompass-sdk 0.14.0 → 0.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/dist/cli.js +0 -0
- package/dist/matching.d.ts.map +1 -1
- package/dist/matching.js +8 -0
- package/dist/matching.js.map +1 -1
- package/dist/sources/acp.d.ts +1 -1
- package/dist/sources/acp.d.ts.map +1 -1
- package/dist/sources/acp.js +27 -17
- package/dist/sources/acp.js.map +1 -1
- package/dist/sources/bankr.d.ts +8 -0
- package/dist/sources/bankr.d.ts.map +1 -0
- package/dist/sources/bankr.js +79 -0
- package/dist/sources/bankr.js.map +1 -0
- package/dist/sources/index.d.ts.map +1 -1
- package/dist/sources/index.js +6 -0
- package/dist/sources/index.js.map +1 -1
- package/dist/sources/locus.d.ts +12 -0
- package/dist/sources/locus.d.ts.map +1 -0
- package/dist/sources/locus.js +134 -0
- package/dist/sources/locus.js.map +1 -0
- package/dist/sources/olas.d.ts +12 -0
- package/dist/sources/olas.d.ts.map +1 -0
- package/dist/sources/olas.js +143 -0
- package/dist/sources/olas.js.map +1 -0
- package/dist/sources/openserv.d.ts +8 -0
- package/dist/sources/openserv.d.ts.map +1 -0
- package/dist/sources/openserv.js +76 -0
- package/dist/sources/openserv.js.map +1 -0
- package/dist/sources/types.d.ts +1 -1
- package/dist/sources/types.d.ts.map +1 -1
- package/dist/wallet/bridge.d.ts +1 -0
- package/dist/wallet/bridge.d.ts.map +1 -1
- package/dist/wallet/bridge.js +31 -5
- package/dist/wallet/bridge.js.map +1 -1
- package/dist/wallet/handlers/acp.d.ts.map +1 -1
- package/dist/wallet/handlers/acp.js +59 -3
- package/dist/wallet/handlers/acp.js.map +1 -1
- package/dist/wallet/handlers/bankr.d.ts +13 -0
- package/dist/wallet/handlers/bankr.d.ts.map +1 -0
- package/dist/wallet/handlers/bankr.js +88 -0
- package/dist/wallet/handlers/bankr.js.map +1 -0
- package/dist/wallet/handlers/locus.d.ts +21 -0
- package/dist/wallet/handlers/locus.d.ts.map +1 -0
- package/dist/wallet/handlers/locus.js +220 -0
- package/dist/wallet/handlers/locus.js.map +1 -0
- package/dist/wallet/payment-router.d.ts.map +1 -1
- package/dist/wallet/payment-router.js +12 -0
- package/dist/wallet/payment-router.js.map +1 -1
- package/package.json +1 -1
- package/src/matching.ts +9 -0
- package/src/sources/acp.ts +29 -20
- package/src/sources/bankr.ts +87 -0
- package/src/sources/index.ts +6 -0
- package/src/sources/locus.ts +156 -0
- package/src/sources/olas.ts +171 -0
- package/src/sources/types.ts +4 -1
- package/src/wallet/bridge.ts +33 -6
- package/src/wallet/handlers/acp.ts +69 -3
- package/src/wallet/handlers/bankr.ts +108 -0
- package/src/wallet/handlers/locus.ts +262 -0
- package/src/wallet/payment-router.ts +14 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locus Payment Handler
|
|
3
|
+
* Calls Locus wrapped APIs — pay-per-use via USDC on Base.
|
|
4
|
+
* No upstream API keys needed — Locus proxies the call and charges the wallet.
|
|
5
|
+
*
|
|
6
|
+
* Flow:
|
|
7
|
+
* 1. Get or create Locus API key (self-register if needed)
|
|
8
|
+
* 2. Wait for wallet deployment
|
|
9
|
+
* 3. Call the wrapped API endpoint
|
|
10
|
+
* 4. Locus charges USDC from wallet, returns response
|
|
11
|
+
*
|
|
12
|
+
* Docs: https://beta.paywithlocus.com/skill.md
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { KompassWallet } from "../index.js";
|
|
16
|
+
import type { UnifiedAgent } from "../../sources/types.js";
|
|
17
|
+
|
|
18
|
+
const LOCUS_API = "https://beta-api.paywithlocus.com/api";
|
|
19
|
+
|
|
20
|
+
export async function handleLocusPayment(
|
|
21
|
+
wallet: KompassWallet,
|
|
22
|
+
agent: UnifiedAgent,
|
|
23
|
+
task: string,
|
|
24
|
+
): Promise<{ success: boolean; deliverable?: unknown; txHash?: string }> {
|
|
25
|
+
let apiKey = process.env.LOCUS_API_KEY;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Step 1: Self-register if no API key
|
|
29
|
+
if (!apiKey) {
|
|
30
|
+
const walletAddress = wallet.getAddress();
|
|
31
|
+
const registerRes = await fetch(`${LOCUS_API}/register`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
wallet_address: walletAddress,
|
|
36
|
+
agent_name: "kompass-agent",
|
|
37
|
+
}),
|
|
38
|
+
signal: AbortSignal.timeout(15000),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!registerRes.ok) {
|
|
42
|
+
const errBody = await registerRes.text().catch(() => "");
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
deliverable: {
|
|
46
|
+
error: `Locus registration failed: ${registerRes.status}`,
|
|
47
|
+
details: errBody,
|
|
48
|
+
hint: "Set LOCUS_API_KEY env var or fund a Locus wallet at paywithlocus.com",
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const registerData = await registerRes.json();
|
|
54
|
+
apiKey = registerData.data?.apiKey;
|
|
55
|
+
|
|
56
|
+
if (!apiKey) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
deliverable: { error: "Locus registration did not return an API key" },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Wait for wallet deployment
|
|
64
|
+
for (let i = 0; i < 10; i++) {
|
|
65
|
+
const statusRes = await fetch(`${LOCUS_API}/status`, {
|
|
66
|
+
headers: { "Authorization": `Bearer ${apiKey}` },
|
|
67
|
+
signal: AbortSignal.timeout(5000),
|
|
68
|
+
}).catch(() => null);
|
|
69
|
+
|
|
70
|
+
if (statusRes?.ok) {
|
|
71
|
+
const statusData = await statusRes.json();
|
|
72
|
+
if (statusData.data?.walletStatus === "deployed") break;
|
|
73
|
+
}
|
|
74
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const headers: Record<string, string> = {
|
|
79
|
+
"Content-Type": "application/json",
|
|
80
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Step 2: Determine if this is a wrapped API call or a direct payment
|
|
84
|
+
const rawData = agent.raw as any;
|
|
85
|
+
const isWrappedApi = rawData?.type === "locus-wrapped-api";
|
|
86
|
+
|
|
87
|
+
if (isWrappedApi) {
|
|
88
|
+
// Call the wrapped API directly
|
|
89
|
+
// The endpoint URL is like: /api/wrapped/{provider}/{endpoint}
|
|
90
|
+
// We need to figure out the best endpoint for the task
|
|
91
|
+
const provider = rawData.provider;
|
|
92
|
+
const availableEndpoints = rawData.endpoints as string[] || [];
|
|
93
|
+
|
|
94
|
+
// Pick the best endpoint and build the right params for each provider
|
|
95
|
+
const { endpoint, params } = buildLocusRequest(provider, availableEndpoints, task);
|
|
96
|
+
|
|
97
|
+
const callUrl = `${LOCUS_API}/wrapped/${provider}/${endpoint}`;
|
|
98
|
+
|
|
99
|
+
const callRes = await fetch(callUrl, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers,
|
|
102
|
+
body: JSON.stringify(params),
|
|
103
|
+
signal: AbortSignal.timeout(30000),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (!callRes.ok) {
|
|
107
|
+
const errBody = await callRes.text().catch(() => "");
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
deliverable: {
|
|
111
|
+
error: `Locus wrapped API call failed: ${callRes.status}`,
|
|
112
|
+
provider,
|
|
113
|
+
endpoint,
|
|
114
|
+
details: errBody,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const result = await callRes.json();
|
|
120
|
+
return {
|
|
121
|
+
success: true,
|
|
122
|
+
deliverable: result,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Step 3: Direct USDC payment to agent address
|
|
127
|
+
const toAddress = agent.endpoints.acp?.walletAddress ?? agent.endpoints.http;
|
|
128
|
+
const amount = agent.pricing?.amount ?? "0.01";
|
|
129
|
+
|
|
130
|
+
if (!toAddress || !toAddress.startsWith("0x")) {
|
|
131
|
+
return {
|
|
132
|
+
success: false,
|
|
133
|
+
deliverable: { error: "No valid target address for Locus payment" },
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const sendRes = await fetch(`${LOCUS_API}/pay/send`, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers,
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
to_address: toAddress,
|
|
142
|
+
amount: parseFloat(amount),
|
|
143
|
+
memo: `Kompass task: ${task.slice(0, 100)}`,
|
|
144
|
+
}),
|
|
145
|
+
signal: AbortSignal.timeout(30000),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (!sendRes.ok) {
|
|
149
|
+
const errBody = await sendRes.text().catch(() => "");
|
|
150
|
+
return {
|
|
151
|
+
success: false,
|
|
152
|
+
deliverable: { error: `Locus payment failed: ${sendRes.status}`, details: errBody },
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const sendData = await sendRes.json();
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
success: true,
|
|
160
|
+
deliverable: sendData,
|
|
161
|
+
txHash: sendData.data?.tx_hash ?? sendData.data?.transaction_id,
|
|
162
|
+
};
|
|
163
|
+
} catch (err) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
deliverable: { error: err instanceof Error ? err.message : String(err) },
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Build the right endpoint and params for each Locus wrapped API provider.
|
|
173
|
+
* Each provider has different input formats — this maps the natural language task
|
|
174
|
+
* to the correct API call based on the provider's docs.
|
|
175
|
+
*/
|
|
176
|
+
function buildLocusRequest(
|
|
177
|
+
provider: string,
|
|
178
|
+
endpoints: string[],
|
|
179
|
+
task: string,
|
|
180
|
+
): { endpoint: string; params: Record<string, unknown> } {
|
|
181
|
+
// Extract URLs from task
|
|
182
|
+
const urlMatch = task.match(/https?:\/\/[^\s"']+/);
|
|
183
|
+
const url = urlMatch?.[0];
|
|
184
|
+
|
|
185
|
+
switch (provider) {
|
|
186
|
+
// Web scraping providers — need "url" param
|
|
187
|
+
case "firecrawl":
|
|
188
|
+
return { endpoint: url ? "scrape" : "search", params: url ? { url } : { query: task } };
|
|
189
|
+
case "abstract-web-scraping":
|
|
190
|
+
return { endpoint: "scrape", params: { url: url || task } };
|
|
191
|
+
case "diffbot":
|
|
192
|
+
return { endpoint: "analyze", params: { url: url || task } };
|
|
193
|
+
case "tavily":
|
|
194
|
+
return { endpoint: url ? "extract" : "search", params: url ? { urls: [url] } : { query: task } };
|
|
195
|
+
|
|
196
|
+
// Search providers — need "query" or "q" param
|
|
197
|
+
case "brave":
|
|
198
|
+
return { endpoint: "web-search", params: { q: task } };
|
|
199
|
+
case "exa":
|
|
200
|
+
return { endpoint: "search", params: { query: task } };
|
|
201
|
+
case "perplexity":
|
|
202
|
+
return { endpoint: "sonar-chat", params: { messages: [{ role: "user", content: task }] } };
|
|
203
|
+
|
|
204
|
+
// Crypto / Finance
|
|
205
|
+
case "coingecko": {
|
|
206
|
+
// Extract coin name from task
|
|
207
|
+
const coins = ["bitcoin", "ethereum", "solana", "base", "usdc"];
|
|
208
|
+
const coin = coins.find(c => task.toLowerCase().includes(c)) || "ethereum";
|
|
209
|
+
const coinId = coin === "eth" ? "ethereum" : coin;
|
|
210
|
+
return { endpoint: "simple-price", params: { ids: coinId, vs_currencies: "usd" } };
|
|
211
|
+
}
|
|
212
|
+
case "alphavantage":
|
|
213
|
+
return { endpoint: "global-quote", params: { symbol: task.match(/[A-Z]{1,5}/)?.[0] || "ETH" } };
|
|
214
|
+
|
|
215
|
+
// LLM providers — need "messages" or "prompt"
|
|
216
|
+
case "openai":
|
|
217
|
+
case "anthropic":
|
|
218
|
+
case "gemini":
|
|
219
|
+
case "deepseek":
|
|
220
|
+
case "grok":
|
|
221
|
+
case "groq":
|
|
222
|
+
case "mistral":
|
|
223
|
+
return { endpoint: "chat", params: { messages: [{ role: "user", content: task }] } };
|
|
224
|
+
|
|
225
|
+
// Image/Media generation
|
|
226
|
+
case "fal":
|
|
227
|
+
return { endpoint: "generate", params: { prompt: task } };
|
|
228
|
+
case "stability-ai":
|
|
229
|
+
return { endpoint: "generate-core", params: { prompt: task } };
|
|
230
|
+
case "replicate":
|
|
231
|
+
return { endpoint: "run-model", params: { input: { prompt: task } } };
|
|
232
|
+
case "suno":
|
|
233
|
+
return { endpoint: "generate-music", params: { prompt: task } };
|
|
234
|
+
|
|
235
|
+
// Code execution
|
|
236
|
+
case "judge0":
|
|
237
|
+
return { endpoint: "execute-code", params: { source_code: task, language_id: 63 } }; // 63 = JavaScript
|
|
238
|
+
|
|
239
|
+
// Screenshot
|
|
240
|
+
case "screenshotone":
|
|
241
|
+
return { endpoint: "take-screenshot", params: { url: url || task } };
|
|
242
|
+
|
|
243
|
+
// Social
|
|
244
|
+
case "x":
|
|
245
|
+
return { endpoint: "search-recent-tweets", params: { query: task } };
|
|
246
|
+
|
|
247
|
+
// Knowledge
|
|
248
|
+
case "wolframalpha":
|
|
249
|
+
return { endpoint: "short-answer", params: { input: task } };
|
|
250
|
+
|
|
251
|
+
// Security
|
|
252
|
+
case "virustotal":
|
|
253
|
+
return { endpoint: url ? "url-report" : "domain-report", params: url ? { resource: url } : { domain: task } };
|
|
254
|
+
|
|
255
|
+
// Default — try common param names
|
|
256
|
+
default:
|
|
257
|
+
return {
|
|
258
|
+
endpoint: endpoints[0]?.toLowerCase().replace(/\s+/g, "-") || "search",
|
|
259
|
+
params: { query: task, prompt: task, q: task, input: task },
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
@@ -11,6 +11,8 @@ import { handleL402Payment } from "./handlers/l402.js";
|
|
|
11
11
|
import { handleMPPPayment } from "./handlers/mpp.js";
|
|
12
12
|
import { handleNanopayment } from "./handlers/nanopayments.js";
|
|
13
13
|
import { handleFreePayment } from "./handlers/free.js";
|
|
14
|
+
import { handleBankrPayment } from "./handlers/bankr.js";
|
|
15
|
+
import { handleLocusPayment } from "./handlers/locus.js";
|
|
14
16
|
import { ensureSufficientBalance } from "./bridge.js";
|
|
15
17
|
|
|
16
18
|
export interface PaymentResult {
|
|
@@ -72,6 +74,16 @@ export async function routePayment(
|
|
|
72
74
|
return { ...result, protocol: "circle-nanopayments", costUSDC: parseFloat(agent.pricing?.amount ?? "0") };
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
case "bankr": {
|
|
78
|
+
const result = await handleBankrPayment(wallet, agent, task);
|
|
79
|
+
return { ...result, protocol: "bankr", costUSDC: parseFloat(agent.pricing?.amount ?? "0") };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case "locus": {
|
|
83
|
+
const result = await handleLocusPayment(wallet, agent, task);
|
|
84
|
+
return { ...result, protocol: "locus", costUSDC: parseFloat(agent.pricing?.amount ?? "0") };
|
|
85
|
+
}
|
|
86
|
+
|
|
75
87
|
case "free":
|
|
76
88
|
case "mcp": {
|
|
77
89
|
// MCP servers and free tools — try to execute directly
|
|
@@ -130,6 +142,8 @@ function determinePaymentProtocol(agent: UnifiedAgent): string {
|
|
|
130
142
|
case "l402-directory": return "l402";
|
|
131
143
|
case "mcp-registry": return "free";
|
|
132
144
|
case "skills-registry": return "free";
|
|
145
|
+
case "bankr": return "bankr";
|
|
146
|
+
case "locus": return "locus";
|
|
133
147
|
default: return agent.protocol === "onchain" ? "acp" : "free";
|
|
134
148
|
}
|
|
135
149
|
}
|