kompass-sdk 0.4.0 → 0.6.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 +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/router.d.ts +3 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +49 -18
- package/dist/router.js.map +1 -1
- package/dist/sources/l402-directory.d.ts +3 -2
- package/dist/sources/l402-directory.d.ts.map +1 -1
- package/dist/sources/l402-directory.js +57 -32
- package/dist/sources/l402-directory.js.map +1 -1
- package/dist/sources/skills.d.ts +5 -2
- package/dist/sources/skills.d.ts.map +1 -1
- package/dist/sources/skills.js +82 -105
- package/dist/sources/skills.js.map +1 -1
- package/dist/sources/x402-ecosystem.d.ts +3 -2
- package/dist/sources/x402-ecosystem.d.ts.map +1 -1
- package/dist/sources/x402-ecosystem.js +69 -55
- package/dist/sources/x402-ecosystem.js.map +1 -1
- package/dist/unified.d.ts +2 -0
- package/dist/unified.d.ts.map +1 -1
- package/dist/unified.js +1 -1
- package/dist/unified.js.map +1 -1
- package/dist/wallet/handlers/acp.d.ts.map +1 -1
- package/dist/wallet/handlers/acp.js +41 -6
- package/dist/wallet/handlers/acp.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +12 -2
- package/src/router.ts +52 -19
- package/src/sources/l402-directory.ts +56 -36
- package/src/sources/skills.ts +82 -111
- package/src/sources/x402-ecosystem.ts +75 -58
- package/src/unified.ts +3 -1
- package/src/wallet/handlers/acp.ts +51 -6
|
@@ -1,86 +1,103 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* x402 Ecosystem Source Adapter
|
|
3
|
-
*
|
|
2
|
+
* x402/L402/MPP Ecosystem Source Adapter
|
|
3
|
+
* Searches 402index.io — protocol-agnostic directory of 15,000+ paid API endpoints
|
|
4
|
+
* Covers x402, L402, and MPP endpoints
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import type { SourceAdapter, UnifiedAgent, SourceSearchOptions } from "./types.js";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
const KNOWN_X402_SERVICES = [
|
|
10
|
-
{ name: "OpenRouter", url: "https://openrouter.ai", description: "LLM API access with USDC payments", categories: ["ai", "llm"] },
|
|
11
|
-
{ name: "Dexter AI", url: "https://dexterai.com", description: "x402 facilitator on Solana. 38M+ settlements", categories: ["defi", "trading"] },
|
|
12
|
-
{ name: "AgentCash", url: "https://agentcash.dev", description: "One balance, every paid API. Multi-protocol agent wallet", categories: ["payments", "tools"] },
|
|
13
|
-
{ name: "Allium", url: "https://allium.so", description: "Blockchain data APIs with x402 payments", categories: ["data", "analytics"] },
|
|
14
|
-
{ name: "Kompass Data Provider", url: "http://localhost:4021", description: "DeFi yield data, token prices, risk scores via x402", categories: ["defi", "data"] },
|
|
15
|
-
{ name: "Wurk", url: "https://wurk.fun", description: "Agent job board with x402 integration", categories: ["jobs", "tools"] },
|
|
16
|
-
{ name: "Tavily", url: "https://tavily.com", description: "AI-powered web search API", categories: ["search", "data"] },
|
|
17
|
-
{ name: "ASSAY", url: "https://assayaudit.com", description: "Agent evaluation and auditing service", categories: ["audit", "trust"] },
|
|
18
|
-
{ name: "Zentiece", url: "https://zentiece.com", description: "Agent with x402 payments + ORBIT burns", categories: ["defi", "trading"] },
|
|
19
|
-
{ name: "AlgoVoi", url: "https://algovoi.com", description: "x402 integration on Algorand", categories: ["defi", "tools"] },
|
|
20
|
-
{ name: "LibertAI", url: "https://libertai.io", description: "Autonomous agents on Aleph Cloud with x402", categories: ["ai", "compute"] },
|
|
21
|
-
{ name: "Handshake_58", url: "https://handshake58.com", description: "Streaming AI agent payment channels", categories: ["payments"] },
|
|
22
|
-
];
|
|
9
|
+
const INDEX_API = "https://402index.io/api/v1/services";
|
|
23
10
|
|
|
24
11
|
export const x402EcosystemAdapter: SourceAdapter = {
|
|
25
12
|
name: "x402-ecosystem",
|
|
26
|
-
displayName: "x402
|
|
13
|
+
displayName: "402 Index (x402 + L402 + MPP)",
|
|
27
14
|
|
|
28
15
|
async search(query: string, options?: SourceSearchOptions): Promise<UnifiedAgent[]> {
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
const limit = options?.limit ?? 20;
|
|
17
|
+
const timeout = options?.timeout ?? 10000;
|
|
18
|
+
|
|
31
19
|
try {
|
|
32
|
-
const
|
|
33
|
-
|
|
20
|
+
const url = new URL(INDEX_API);
|
|
21
|
+
if (query) url.searchParams.set("q", query);
|
|
22
|
+
url.searchParams.set("limit", String(limit));
|
|
23
|
+
url.searchParams.set("health", "healthy");
|
|
24
|
+
url.searchParams.set("sort", "reliability");
|
|
25
|
+
|
|
26
|
+
const res = await fetch(url.toString(), {
|
|
27
|
+
signal: AbortSignal.timeout(timeout),
|
|
34
28
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
29
|
+
|
|
30
|
+
if (!res.ok) return [];
|
|
31
|
+
|
|
32
|
+
const data = await res.json();
|
|
33
|
+
const services = data.services ?? data.data ?? data;
|
|
34
|
+
|
|
35
|
+
if (!Array.isArray(services)) return [];
|
|
36
|
+
|
|
37
|
+
return services.slice(0, limit).map(mapService);
|
|
43
38
|
} catch {
|
|
44
|
-
|
|
39
|
+
return [];
|
|
45
40
|
}
|
|
46
|
-
|
|
47
|
-
const allServices = [...KNOWN_X402_SERVICES, ...dynamicServices];
|
|
48
|
-
const lower = query.toLowerCase();
|
|
49
|
-
|
|
50
|
-
return allServices
|
|
51
|
-
.filter((s) => {
|
|
52
|
-
if (!query) return true;
|
|
53
|
-
return (
|
|
54
|
-
s.name.toLowerCase().includes(lower) ||
|
|
55
|
-
s.description.toLowerCase().includes(lower) ||
|
|
56
|
-
s.categories.some((c) => lower.includes(c))
|
|
57
|
-
);
|
|
58
|
-
})
|
|
59
|
-
.slice(0, options?.limit ?? 50)
|
|
60
|
-
.map(mapX402Service);
|
|
61
41
|
},
|
|
62
42
|
|
|
63
43
|
async ping(): Promise<boolean> {
|
|
64
|
-
|
|
44
|
+
try {
|
|
45
|
+
const res = await fetch(`${INDEX_API}?limit=1`, {
|
|
46
|
+
signal: AbortSignal.timeout(5000),
|
|
47
|
+
});
|
|
48
|
+
return res.ok;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
65
52
|
},
|
|
66
53
|
};
|
|
67
54
|
|
|
68
|
-
function
|
|
55
|
+
function mapService(service: any): UnifiedAgent {
|
|
56
|
+
const protocol = mapProtocol(service.protocol);
|
|
57
|
+
|
|
69
58
|
return {
|
|
70
|
-
id: `x402-ecosystem:${service.
|
|
71
|
-
nativeId: service.name,
|
|
72
|
-
name: service.name,
|
|
73
|
-
description: service.description,
|
|
74
|
-
categories: service.
|
|
75
|
-
capabilities: [service.description],
|
|
59
|
+
id: `x402-ecosystem:${service.id ?? service.url}`,
|
|
60
|
+
nativeId: service.id ?? service.name,
|
|
61
|
+
name: cleanName(service.name ?? "Unknown Service"),
|
|
62
|
+
description: cleanDescription(service.description ?? ""),
|
|
63
|
+
categories: service.category ? service.category.split("/").map((c: string) => c.trim()) : ["general"],
|
|
64
|
+
capabilities: [service.description ?? service.name ?? ""].filter(Boolean),
|
|
76
65
|
source: "x402-ecosystem",
|
|
77
|
-
protocol
|
|
66
|
+
protocol,
|
|
78
67
|
endpoints: {
|
|
79
|
-
x402: service.url,
|
|
68
|
+
x402: protocol === "x402" ? service.url : undefined,
|
|
69
|
+
l402: protocol === "l402" ? service.url : undefined,
|
|
80
70
|
http: service.url,
|
|
81
71
|
},
|
|
82
|
-
pricing: {
|
|
83
|
-
|
|
72
|
+
pricing: {
|
|
73
|
+
model: "per-call",
|
|
74
|
+
amount: service.price_usd ? String(service.price_usd) : service.price_sats ? `${service.price_sats} sats` : undefined,
|
|
75
|
+
currency: service.payment_asset ?? (protocol === "l402" ? "sats" : "USDC"),
|
|
76
|
+
},
|
|
77
|
+
reputation: service.reliability_score ? {
|
|
78
|
+
score: service.reliability_score,
|
|
79
|
+
count: service.uptime_30d ? Math.round(service.uptime_30d * 100) : 0,
|
|
80
|
+
source: "402index",
|
|
81
|
+
} : undefined,
|
|
82
|
+
verified: service.x402_payment_valid === 1 || service.health_status === "healthy",
|
|
83
|
+
lastSeen: service.last_checked ? new Date(service.last_checked).getTime() : undefined,
|
|
84
84
|
raw: service,
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
|
|
88
|
+
function mapProtocol(protocol: string): "x402" | "l402" | "http" {
|
|
89
|
+
switch (protocol?.toLowerCase()) {
|
|
90
|
+
case "x402": return "x402";
|
|
91
|
+
case "l402": return "l402";
|
|
92
|
+
case "mpp": return "x402"; // MPP uses same HTTP 402 pattern
|
|
93
|
+
default: return "x402";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function cleanName(name: string): string {
|
|
98
|
+
return name.replace(/^\s+|\s+$/g, "").split("\n")[0].trim().slice(0, 100);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function cleanDescription(desc: string): string {
|
|
102
|
+
return desc.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ").slice(0, 300);
|
|
103
|
+
}
|
package/src/unified.ts
CHANGED
|
@@ -28,6 +28,8 @@ export interface UnifiedConfig {
|
|
|
28
28
|
kompassConfig?: any;
|
|
29
29
|
/** ERC-8004 reputation writer config (writes feedback after executions) */
|
|
30
30
|
reputationWriter?: ReputationWriterConfig;
|
|
31
|
+
/** Kompass wallet for payments */
|
|
32
|
+
wallet?: any;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
export interface FindOptions {
|
|
@@ -59,7 +61,7 @@ export class KompassUnified {
|
|
|
59
61
|
this.config = config;
|
|
60
62
|
this.aggregator = new Aggregator(adapters);
|
|
61
63
|
this.bridge = bridge;
|
|
62
|
-
this.router = new CapabilityRouter(this.aggregator, this.bridge, config?.reputationWriter);
|
|
64
|
+
this.router = new CapabilityRouter(this.aggregator, this.bridge, config?.reputationWriter, config?.wallet);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
static async create(config?: UnifiedConfig): Promise<KompassUnified> {
|
|
@@ -54,7 +54,7 @@ export async function handleACPPayment(
|
|
|
54
54
|
[
|
|
55
55
|
"acp", "job", "create",
|
|
56
56
|
walletAddress,
|
|
57
|
-
String(offering.id),
|
|
57
|
+
String(offering.name ?? offering.id),
|
|
58
58
|
"--requirements", requirements,
|
|
59
59
|
"--isAutomated", "true",
|
|
60
60
|
"--json",
|
|
@@ -67,19 +67,64 @@ export async function handleACPPayment(
|
|
|
67
67
|
);
|
|
68
68
|
|
|
69
69
|
const jobData = JSON.parse(stdout.trim());
|
|
70
|
+
const jobId = jobData.data?.jobId ?? jobData.jobId ?? jobData.id;
|
|
71
|
+
|
|
72
|
+
console.log(`[Kompass] ACP job #${jobId} created with ${agent.name}. Polling for completion...`);
|
|
73
|
+
|
|
74
|
+
// Poll for completion (max 2 minutes)
|
|
75
|
+
const maxWait = 120_000;
|
|
76
|
+
const pollInterval = 10_000;
|
|
77
|
+
const start = Date.now();
|
|
78
|
+
let finalPhase = "created";
|
|
79
|
+
let deliverable: any = null;
|
|
80
|
+
|
|
81
|
+
while (Date.now() - start < maxWait) {
|
|
82
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const { stdout: statusOut } = await execFileAsync(
|
|
86
|
+
"npx",
|
|
87
|
+
["acp", "job", "status", String(jobId), "--json"],
|
|
88
|
+
{ cwd: "/tmp/openclaw-acp", timeout: 15000, env: { ...process.env, NODE_NO_WARNINGS: "1" } }
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const statusData = JSON.parse(statusOut.trim());
|
|
92
|
+
finalPhase = statusData.phase ?? "unknown";
|
|
93
|
+
console.log(`[Kompass] Job #${jobId} phase: ${finalPhase}`);
|
|
94
|
+
|
|
95
|
+
if (finalPhase === "COMPLETED") {
|
|
96
|
+
deliverable = statusData.deliverable;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
if (finalPhase === "REJECTED" || finalPhase === "EXPIRED" || finalPhase === "CANCELLED") {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
// Status check failed, keep polling
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (finalPhase === "COMPLETED" && deliverable) {
|
|
108
|
+
return {
|
|
109
|
+
success: true,
|
|
110
|
+
deliverable,
|
|
111
|
+
jobId: String(jobId),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
70
114
|
|
|
71
115
|
return {
|
|
72
|
-
success:
|
|
116
|
+
success: finalPhase === "COMPLETED",
|
|
73
117
|
deliverable: {
|
|
74
118
|
type: "acp-escrow",
|
|
75
|
-
jobId:
|
|
76
|
-
|
|
77
|
-
message: "
|
|
119
|
+
jobId: String(jobId),
|
|
120
|
+
phase: finalPhase,
|
|
121
|
+
message: finalPhase === "COMPLETED" ? "Job completed" : `Job ended with phase: ${finalPhase}`,
|
|
78
122
|
offering: offering.name,
|
|
79
123
|
price: offering.price,
|
|
80
124
|
agent: agent.name,
|
|
125
|
+
deliverable,
|
|
81
126
|
},
|
|
82
|
-
jobId: String(
|
|
127
|
+
jobId: String(jobId),
|
|
83
128
|
};
|
|
84
129
|
} catch (err) {
|
|
85
130
|
const message = err instanceof Error ? err.message : String(err);
|