kompass-sdk 0.1.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.
Files changed (205) hide show
  1. package/dist/a2a/agent-card.d.ts +13 -0
  2. package/dist/a2a/agent-card.d.ts.map +1 -0
  3. package/dist/a2a/agent-card.js +52 -0
  4. package/dist/a2a/agent-card.js.map +1 -0
  5. package/dist/a2a/bridge.d.ts +52 -0
  6. package/dist/a2a/bridge.d.ts.map +1 -0
  7. package/dist/a2a/bridge.js +123 -0
  8. package/dist/a2a/bridge.js.map +1 -0
  9. package/dist/a2a/client.d.ts +34 -0
  10. package/dist/a2a/client.d.ts.map +1 -0
  11. package/dist/a2a/client.js +65 -0
  12. package/dist/a2a/client.js.map +1 -0
  13. package/dist/a2a/server.d.ts +17 -0
  14. package/dist/a2a/server.d.ts.map +1 -0
  15. package/dist/a2a/server.js +194 -0
  16. package/dist/a2a/server.js.map +1 -0
  17. package/dist/abi.d.ts +1068 -0
  18. package/dist/abi.d.ts.map +1 -0
  19. package/dist/abi.js +1372 -0
  20. package/dist/abi.js.map +1 -0
  21. package/dist/adapters/agentkit.d.ts +41 -0
  22. package/dist/adapters/agentkit.d.ts.map +1 -0
  23. package/dist/adapters/agentkit.js +67 -0
  24. package/dist/adapters/agentkit.js.map +1 -0
  25. package/dist/adapters/generic.d.ts +35 -0
  26. package/dist/adapters/generic.d.ts.map +1 -0
  27. package/dist/adapters/generic.js +47 -0
  28. package/dist/adapters/generic.js.map +1 -0
  29. package/dist/adapters/index.d.ts +5 -0
  30. package/dist/adapters/index.d.ts.map +1 -0
  31. package/dist/adapters/index.js +5 -0
  32. package/dist/adapters/index.js.map +1 -0
  33. package/dist/adapters/langchain.d.ts +26 -0
  34. package/dist/adapters/langchain.d.ts.map +1 -0
  35. package/dist/adapters/langchain.js +228 -0
  36. package/dist/adapters/langchain.js.map +1 -0
  37. package/dist/adapters/openclaw.d.ts +18 -0
  38. package/dist/adapters/openclaw.d.ts.map +1 -0
  39. package/dist/adapters/openclaw.js +168 -0
  40. package/dist/adapters/openclaw.js.map +1 -0
  41. package/dist/aggregator.d.ts +36 -0
  42. package/dist/aggregator.d.ts.map +1 -0
  43. package/dist/aggregator.js +168 -0
  44. package/dist/aggregator.js.map +1 -0
  45. package/dist/backends/acp.d.ts +29 -0
  46. package/dist/backends/acp.d.ts.map +1 -0
  47. package/dist/backends/acp.js +126 -0
  48. package/dist/backends/acp.js.map +1 -0
  49. package/dist/backends/types.d.ts +59 -0
  50. package/dist/backends/types.d.ts.map +1 -0
  51. package/dist/backends/types.js +2 -0
  52. package/dist/backends/types.js.map +1 -0
  53. package/dist/bridge.d.ts +35 -0
  54. package/dist/bridge.d.ts.map +1 -0
  55. package/dist/bridge.js +192 -0
  56. package/dist/bridge.js.map +1 -0
  57. package/dist/cli.d.ts +12 -0
  58. package/dist/cli.d.ts.map +1 -0
  59. package/dist/cli.js +331 -0
  60. package/dist/cli.js.map +1 -0
  61. package/dist/discover.d.ts +15 -0
  62. package/dist/discover.d.ts.map +1 -0
  63. package/dist/discover.js +163 -0
  64. package/dist/discover.js.map +1 -0
  65. package/dist/escrow.d.ts +45 -0
  66. package/dist/escrow.d.ts.map +1 -0
  67. package/dist/escrow.js +243 -0
  68. package/dist/escrow.js.map +1 -0
  69. package/dist/index.d.ts +63 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +145 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/intents.d.ts +28 -0
  74. package/dist/intents.d.ts.map +1 -0
  75. package/dist/intents.js +111 -0
  76. package/dist/intents.js.map +1 -0
  77. package/dist/matching.d.ts +29 -0
  78. package/dist/matching.d.ts.map +1 -0
  79. package/dist/matching.js +147 -0
  80. package/dist/matching.js.map +1 -0
  81. package/dist/pipelineAbi.d.ts +113 -0
  82. package/dist/pipelineAbi.d.ts.map +1 -0
  83. package/dist/pipelineAbi.js +74 -0
  84. package/dist/pipelineAbi.js.map +1 -0
  85. package/dist/pipelines.d.ts +42 -0
  86. package/dist/pipelines.d.ts.map +1 -0
  87. package/dist/pipelines.js +185 -0
  88. package/dist/pipelines.js.map +1 -0
  89. package/dist/registry.d.ts +36 -0
  90. package/dist/registry.d.ts.map +1 -0
  91. package/dist/registry.js +187 -0
  92. package/dist/registry.js.map +1 -0
  93. package/dist/reputation.d.ts +10 -0
  94. package/dist/reputation.d.ts.map +1 -0
  95. package/dist/reputation.js +33 -0
  96. package/dist/reputation.js.map +1 -0
  97. package/dist/router.d.ts +72 -0
  98. package/dist/router.d.ts.map +1 -0
  99. package/dist/router.js +190 -0
  100. package/dist/router.js.map +1 -0
  101. package/dist/simple.d.ts +160 -0
  102. package/dist/simple.d.ts.map +1 -0
  103. package/dist/simple.js +237 -0
  104. package/dist/simple.js.map +1 -0
  105. package/dist/sources/a2a-wellknown.d.ts +8 -0
  106. package/dist/sources/a2a-wellknown.d.ts.map +1 -0
  107. package/dist/sources/a2a-wellknown.js +104 -0
  108. package/dist/sources/a2a-wellknown.js.map +1 -0
  109. package/dist/sources/acp.d.ts +7 -0
  110. package/dist/sources/acp.d.ts.map +1 -0
  111. package/dist/sources/acp.js +86 -0
  112. package/dist/sources/acp.js.map +1 -0
  113. package/dist/sources/adp.d.ts +7 -0
  114. package/dist/sources/adp.d.ts.map +1 -0
  115. package/dist/sources/adp.js +59 -0
  116. package/dist/sources/adp.js.map +1 -0
  117. package/dist/sources/erc8004.d.ts +7 -0
  118. package/dist/sources/erc8004.d.ts.map +1 -0
  119. package/dist/sources/erc8004.js +150 -0
  120. package/dist/sources/erc8004.js.map +1 -0
  121. package/dist/sources/index.d.ts +17 -0
  122. package/dist/sources/index.d.ts.map +1 -0
  123. package/dist/sources/index.js +35 -0
  124. package/dist/sources/index.js.map +1 -0
  125. package/dist/sources/kompass-registry.d.ts +8 -0
  126. package/dist/sources/kompass-registry.d.ts.map +1 -0
  127. package/dist/sources/kompass-registry.js +62 -0
  128. package/dist/sources/kompass-registry.js.map +1 -0
  129. package/dist/sources/l402-directory.d.ts +7 -0
  130. package/dist/sources/l402-directory.d.ts.map +1 -0
  131. package/dist/sources/l402-directory.js +42 -0
  132. package/dist/sources/l402-directory.js.map +1 -0
  133. package/dist/sources/mcp-registry.d.ts +8 -0
  134. package/dist/sources/mcp-registry.d.ts.map +1 -0
  135. package/dist/sources/mcp-registry.js +85 -0
  136. package/dist/sources/mcp-registry.js.map +1 -0
  137. package/dist/sources/skills.d.ts +8 -0
  138. package/dist/sources/skills.d.ts.map +1 -0
  139. package/dist/sources/skills.js +153 -0
  140. package/dist/sources/skills.js.map +1 -0
  141. package/dist/sources/types.d.ts +72 -0
  142. package/dist/sources/types.d.ts.map +1 -0
  143. package/dist/sources/types.js +8 -0
  144. package/dist/sources/types.js.map +1 -0
  145. package/dist/sources/x402-ecosystem.d.ts +7 -0
  146. package/dist/sources/x402-ecosystem.d.ts.map +1 -0
  147. package/dist/sources/x402-ecosystem.js +78 -0
  148. package/dist/sources/x402-ecosystem.js.map +1 -0
  149. package/dist/types.d.ts +133 -0
  150. package/dist/types.d.ts.map +1 -0
  151. package/dist/types.js +2 -0
  152. package/dist/types.js.map +1 -0
  153. package/dist/unified.d.ts +90 -0
  154. package/dist/unified.d.ts.map +1 -0
  155. package/dist/unified.js +107 -0
  156. package/dist/unified.js.map +1 -0
  157. package/dist/x402.d.ts +30 -0
  158. package/dist/x402.d.ts.map +1 -0
  159. package/dist/x402.js +79 -0
  160. package/dist/x402.js.map +1 -0
  161. package/package.json +61 -0
  162. package/scripts/bootstrap-agents.mjs +246 -0
  163. package/src/.gitkeep +0 -0
  164. package/src/a2a/agent-card.ts +66 -0
  165. package/src/a2a/bridge.ts +168 -0
  166. package/src/a2a/client.ts +92 -0
  167. package/src/a2a/server.ts +234 -0
  168. package/src/abi.ts +1373 -0
  169. package/src/adapters/agentkit.ts +83 -0
  170. package/src/adapters/generic.ts +62 -0
  171. package/src/adapters/index.ts +4 -0
  172. package/src/adapters/langchain.ts +282 -0
  173. package/src/adapters/openclaw.ts +203 -0
  174. package/src/aggregator.ts +203 -0
  175. package/src/backends/acp.ts +199 -0
  176. package/src/backends/types.ts +78 -0
  177. package/src/bridge.ts +263 -0
  178. package/src/cli.ts +397 -0
  179. package/src/discover.ts +187 -0
  180. package/src/escrow.ts +284 -0
  181. package/src/index.ts +245 -0
  182. package/src/intents.ts +166 -0
  183. package/src/matching.ts +192 -0
  184. package/src/pipelineAbi.ts +74 -0
  185. package/src/pipelines.ts +253 -0
  186. package/src/registry.ts +232 -0
  187. package/src/reputation.ts +43 -0
  188. package/src/router.ts +279 -0
  189. package/src/simple.ts +366 -0
  190. package/src/sources/a2a-wellknown.ts +120 -0
  191. package/src/sources/acp.ts +91 -0
  192. package/src/sources/adp.ts +64 -0
  193. package/src/sources/erc8004.ts +166 -0
  194. package/src/sources/index.ts +52 -0
  195. package/src/sources/kompass-registry.ts +67 -0
  196. package/src/sources/l402-directory.ts +51 -0
  197. package/src/sources/mcp-registry.ts +104 -0
  198. package/src/sources/skills.ts +161 -0
  199. package/src/sources/types.ts +82 -0
  200. package/src/sources/x402-ecosystem.ts +86 -0
  201. package/src/types.ts +147 -0
  202. package/src/unified.ts +155 -0
  203. package/src/x402.ts +122 -0
  204. package/tests/pipelineFlow.test.ts +239 -0
  205. package/tsconfig.json +20 -0
package/src/bridge.ts ADDED
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Kompass Protocol Bridge
3
+ * Routes hire/interact requests to the correct protocol handler
4
+ */
5
+
6
+ import type { UnifiedAgent, AgentProtocol } from "./sources/types.js";
7
+
8
+ export interface BridgeHireOptions {
9
+ task: string;
10
+ budget?: bigint;
11
+ timeout?: number;
12
+ payload?: Record<string, unknown>;
13
+ }
14
+
15
+ export interface BridgeHireResult {
16
+ success: boolean;
17
+ protocol: AgentProtocol;
18
+ agent: UnifiedAgent;
19
+ jobId?: string;
20
+ deliverable?: unknown;
21
+ txHash?: string;
22
+ error?: string;
23
+ durationMs: number;
24
+ }
25
+
26
+ export class ProtocolBridge {
27
+ private acpBackend?: any; // AcpEscrowBackend if available
28
+
29
+ constructor(options?: { acpBackend?: any }) {
30
+ this.acpBackend = options?.acpBackend;
31
+ }
32
+
33
+ async hire(agent: UnifiedAgent, options: BridgeHireOptions): Promise<BridgeHireResult> {
34
+ const start = Date.now();
35
+
36
+ try {
37
+ switch (agent.protocol) {
38
+ case "acp":
39
+ return await this.hireViaAcp(agent, options, start);
40
+ case "x402":
41
+ return await this.hireViaX402(agent, options, start);
42
+ case "mcp":
43
+ return await this.hireViaMcp(agent, options, start);
44
+ case "a2a":
45
+ return await this.hireViaA2A(agent, options, start);
46
+ case "http":
47
+ return await this.hireViaHttp(agent, options, start);
48
+ case "l402":
49
+ return await this.hireViaL402(agent, options, start);
50
+ default:
51
+ return {
52
+ success: false,
53
+ protocol: agent.protocol,
54
+ agent,
55
+ error: `Unsupported protocol: ${agent.protocol}`,
56
+ durationMs: Date.now() - start,
57
+ };
58
+ }
59
+ } catch (err) {
60
+ return {
61
+ success: false,
62
+ protocol: agent.protocol,
63
+ agent,
64
+ error: err instanceof Error ? err.message : String(err),
65
+ durationMs: Date.now() - start,
66
+ };
67
+ }
68
+ }
69
+
70
+ private async hireViaAcp(
71
+ agent: UnifiedAgent,
72
+ options: BridgeHireOptions,
73
+ start: number
74
+ ): Promise<BridgeHireResult> {
75
+ if (!this.acpBackend) {
76
+ return {
77
+ success: false, protocol: "acp", agent,
78
+ error: "ACP backend not configured. Initialize KompassUnified with ACP credentials.",
79
+ durationMs: Date.now() - start,
80
+ };
81
+ }
82
+
83
+ const offering = (agent.raw as any)?.jobs?.[0] ?? (agent.raw as any)?.jobOfferings?.[0];
84
+ if (!offering) {
85
+ return {
86
+ success: false, protocol: "acp", agent,
87
+ error: "Agent has no job offerings on ACP",
88
+ durationMs: Date.now() - start,
89
+ };
90
+ }
91
+
92
+ const job = await this.acpBackend.hireAgent(
93
+ agent,
94
+ offering.id,
95
+ { description: options.task, ...options.payload },
96
+ options.budget
97
+ );
98
+
99
+ const result = await this.acpBackend.waitForResult(
100
+ job.jobId,
101
+ options.timeout ?? 300_000
102
+ );
103
+
104
+ return {
105
+ success: result.phase === "COMPLETED",
106
+ protocol: "acp",
107
+ agent,
108
+ jobId: result.jobId,
109
+ deliverable: result.deliverable,
110
+ txHash: result.txHash,
111
+ durationMs: Date.now() - start,
112
+ };
113
+ }
114
+
115
+ private async hireViaX402(
116
+ agent: UnifiedAgent,
117
+ options: BridgeHireOptions,
118
+ start: number
119
+ ): Promise<BridgeHireResult> {
120
+ const endpoint = agent.endpoints.x402;
121
+ if (!endpoint) {
122
+ return {
123
+ success: false, protocol: "x402", agent,
124
+ error: "No x402 endpoint",
125
+ durationMs: Date.now() - start,
126
+ };
127
+ }
128
+
129
+ // Simple HTTP POST — in production would use @x402/fetch for payment
130
+ const res = await fetch(endpoint, {
131
+ method: "POST",
132
+ headers: { "Content-Type": "application/json" },
133
+ body: JSON.stringify({ task: options.task, ...options.payload }),
134
+ signal: AbortSignal.timeout(options.timeout ?? 30000),
135
+ });
136
+
137
+ if (res.status === 402) {
138
+ // Payment required — return the requirement info
139
+ const paymentHeader = res.headers.get("PAYMENT-REQUIRED") ?? res.headers.get("payment-required");
140
+ return {
141
+ success: false, protocol: "x402", agent,
142
+ error: `Payment required: ${paymentHeader ?? "x402 payment needed"}`,
143
+ deliverable: { paymentRequired: true, header: paymentHeader },
144
+ durationMs: Date.now() - start,
145
+ };
146
+ }
147
+
148
+ const data = await res.json().catch(() => null);
149
+ return {
150
+ success: res.ok,
151
+ protocol: "x402",
152
+ agent,
153
+ deliverable: data,
154
+ durationMs: Date.now() - start,
155
+ };
156
+ }
157
+
158
+ private async hireViaMcp(
159
+ agent: UnifiedAgent,
160
+ options: BridgeHireOptions,
161
+ start: number
162
+ ): Promise<BridgeHireResult> {
163
+ // MCP servers expose tools — we'd need to connect and call specific tools
164
+ // For hackathon, we return the connection info
165
+ return {
166
+ success: true,
167
+ protocol: "mcp",
168
+ agent,
169
+ deliverable: {
170
+ type: "mcp-server",
171
+ endpoint: agent.endpoints.mcp,
172
+ message: "MCP server available. Connect via MCP client to use tools.",
173
+ tools: agent.capabilities,
174
+ },
175
+ durationMs: Date.now() - start,
176
+ };
177
+ }
178
+
179
+ private async hireViaA2A(
180
+ agent: UnifiedAgent,
181
+ options: BridgeHireOptions,
182
+ start: number
183
+ ): Promise<BridgeHireResult> {
184
+ const endpoint = agent.endpoints.a2a;
185
+ if (!endpoint) {
186
+ return {
187
+ success: false, protocol: "a2a", agent,
188
+ error: "No A2A endpoint",
189
+ durationMs: Date.now() - start,
190
+ };
191
+ }
192
+
193
+ // A2A protocol: POST task to agent's endpoint
194
+ const res = await fetch(endpoint, {
195
+ method: "POST",
196
+ headers: { "Content-Type": "application/json" },
197
+ body: JSON.stringify({
198
+ jsonrpc: "2.0",
199
+ method: "tasks/send",
200
+ params: {
201
+ message: { role: "user", parts: [{ type: "text", text: options.task }] },
202
+ },
203
+ }),
204
+ signal: AbortSignal.timeout(options.timeout ?? 30000),
205
+ });
206
+
207
+ const data = await res.json().catch(() => null);
208
+ return {
209
+ success: res.ok,
210
+ protocol: "a2a",
211
+ agent,
212
+ deliverable: data,
213
+ durationMs: Date.now() - start,
214
+ };
215
+ }
216
+
217
+ private async hireViaHttp(
218
+ agent: UnifiedAgent,
219
+ options: BridgeHireOptions,
220
+ start: number
221
+ ): Promise<BridgeHireResult> {
222
+ const endpoint = agent.endpoints.http;
223
+ if (!endpoint) {
224
+ return {
225
+ success: false, protocol: "http", agent,
226
+ error: "No HTTP endpoint",
227
+ durationMs: Date.now() - start,
228
+ };
229
+ }
230
+
231
+ const res = await fetch(endpoint, {
232
+ method: "POST",
233
+ headers: { "Content-Type": "application/json" },
234
+ body: JSON.stringify({ task: options.task, ...options.payload }),
235
+ signal: AbortSignal.timeout(options.timeout ?? 30000),
236
+ });
237
+
238
+ const data = await res.json().catch(() => null);
239
+ return {
240
+ success: res.ok,
241
+ protocol: "http",
242
+ agent,
243
+ deliverable: data,
244
+ durationMs: Date.now() - start,
245
+ };
246
+ }
247
+
248
+ private async hireViaL402(
249
+ agent: UnifiedAgent,
250
+ options: BridgeHireOptions,
251
+ start: number
252
+ ): Promise<BridgeHireResult> {
253
+ // L402 requires Lightning payment — return info for now
254
+ return {
255
+ success: false,
256
+ protocol: "l402",
257
+ agent,
258
+ error: "L402 Lightning payment required. Use a Lightning wallet to pay the invoice.",
259
+ deliverable: { endpoint: agent.endpoints.l402, paymentType: "lightning" },
260
+ durationMs: Date.now() - start,
261
+ };
262
+ }
263
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,397 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Kompass CLI — Agent Commerce from the Command Line
5
+ *
6
+ * Usage:
7
+ * npx kompass discover "yield research"
8
+ * npx kompass hire "Find best yield on Base" --budget 1
9
+ * npx kompass accept-jobs --capabilities "defi,yield"
10
+ * npx kompass reputation 0x...
11
+ */
12
+
13
+ import { Command } from "commander";
14
+ import { KompassSimple } from "./simple.js";
15
+ import { createAllSources } from "./sources/index.js";
16
+ import { Aggregator } from "./aggregator.js";
17
+
18
+ const program = new Command();
19
+
20
+ program
21
+ .name("kompass")
22
+ .description("Kompass — The intelligence layer for agent commerce on Base")
23
+ .version("1.0.0");
24
+
25
+ // ── Helper ───────────────────────────────────────────────
26
+
27
+ function getConfig() {
28
+ const privateKey = process.env.KOMPASS_PRIVATE_KEY ?? process.env.PRIVATE_KEY;
29
+ if (!privateKey) {
30
+ console.error("Error: Set KOMPASS_PRIVATE_KEY or PRIVATE_KEY env var");
31
+ process.exit(1);
32
+ }
33
+ return {
34
+ privateKey,
35
+ network: (process.env.KOMPASS_NETWORK ?? "base-sepolia") as "base-sepolia" | "base",
36
+ acpEntityAddress: process.env.ACP_ENTITY_ADDRESS,
37
+ acpWalletAddress: process.env.ACP_WALLET_ADDRESS,
38
+ indexerUrl: process.env.KOMPASS_INDEXER_URL,
39
+ reputationRegistryAddress: process.env.ERC8004_REPUTATION_REGISTRY as `0x${string}` | undefined,
40
+ rpcUrl: process.env.KOMPASS_RPC_URL ?? process.env.BASE_SEPOLIA_RPC,
41
+ };
42
+ }
43
+
44
+ // ── Commands ─────────────────────────────────────────────
45
+
46
+ program
47
+ .command("discover <query>")
48
+ .description("Search for agents on the ACP marketplace with Kompass reputation filtering")
49
+ .option("-l, --limit <n>", "max results", "10")
50
+ .option("--online", "only show online agents")
51
+ .action(async (query: string, opts: { limit: string; online?: boolean }) => {
52
+ const kompass = await KompassSimple.create(getConfig());
53
+ const agents = await kompass.discover(query, { limit: parseInt(opts.limit) });
54
+
55
+ if (agents.length === 0) {
56
+ console.log("No agents found.");
57
+ return;
58
+ }
59
+
60
+ console.log(`\nFound ${agents.length} agents:\n`);
61
+ for (const agent of agents) {
62
+ console.log(` ${agent.name} (${agent.address.slice(0, 10)}...)`);
63
+ console.log(` ${agent.description.slice(0, 100)}`);
64
+ console.log(` Categories: ${agent.categories.join(", ") || "—"}`);
65
+ console.log(` Offerings: ${agent.offerings.length}`);
66
+ if (agent.metrics?.successRate !== undefined) {
67
+ console.log(` Success rate: ${(agent.metrics.successRate * 100).toFixed(0)}%`);
68
+ }
69
+ console.log();
70
+ }
71
+ });
72
+
73
+ program
74
+ .command("hire <task>")
75
+ .description("Hire an agent to complete a task via ACP escrow")
76
+ .option("-b, --budget <usdc>", "max budget in USDC", "1")
77
+ .option("-r, --min-reputation <score>", "minimum ERC-8004 reputation score", "0")
78
+ .option("-t, --timeout <seconds>", "timeout in seconds", "300")
79
+ .option("--json", "output as JSON")
80
+ .action(
81
+ async (
82
+ task: string,
83
+ opts: { budget: string; minReputation: string; timeout: string; json?: boolean }
84
+ ) => {
85
+ const kompass = await KompassSimple.create(getConfig());
86
+
87
+ console.log(`\nHiring agent for: "${task}"`);
88
+ console.log(`Budget: $${opts.budget} USDC | Min reputation: ${opts.minReputation}\n`);
89
+
90
+ const result = await kompass.hireAgent({
91
+ task,
92
+ maxBudget: BigInt(Math.round(parseFloat(opts.budget) * 1_000_000)),
93
+ minReputation: parseInt(opts.minReputation),
94
+ timeoutMs: parseInt(opts.timeout) * 1000,
95
+ });
96
+
97
+ if (opts.json) {
98
+ console.log(JSON.stringify(result, null, 2));
99
+ } else {
100
+ console.log(`Agent: ${result.agent.name}`);
101
+ console.log(`Job ID: ${result.jobId}`);
102
+ console.log(`Phase: ${result.phase}`);
103
+ console.log(`Reputation checked: ${result.reputationChecked}`);
104
+ if (result.txHash) console.log(`TX: ${result.txHash}`);
105
+ console.log(`\nDeliverable:`);
106
+ console.log(
107
+ typeof result.deliverable === "string"
108
+ ? result.deliverable
109
+ : JSON.stringify(result.deliverable, null, 2)
110
+ );
111
+ }
112
+ }
113
+ );
114
+
115
+ program
116
+ .command("orchestrate <intent>")
117
+ .description("Orchestrate a multi-agent pipeline for a complex intent")
118
+ .option("-b, --budget <usdc>", "total budget in USDC", "5")
119
+ .option("--risk <level>", "risk tolerance: conservative, balanced, aggressive", "balanced")
120
+ .option("--json", "output as JSON")
121
+ .action(
122
+ async (
123
+ intent: string,
124
+ opts: { budget: string; risk: string; json?: boolean }
125
+ ) => {
126
+ const kompass = await KompassSimple.create(getConfig());
127
+
128
+ console.log(`\nOrchestrating: "${intent}"`);
129
+ console.log(`Budget: $${opts.budget} USDC | Risk: ${opts.risk}\n`);
130
+
131
+ const result = await kompass.orchestrate({
132
+ intent,
133
+ riskTolerance: opts.risk as "conservative" | "balanced" | "aggressive",
134
+ budget: BigInt(Math.round(parseFloat(opts.budget) * 1_000_000)),
135
+ });
136
+
137
+ if (opts.json) {
138
+ console.log(JSON.stringify(result, null, 2));
139
+ } else {
140
+ console.log(`Completed ${result.completedSteps}/${result.steps.length} steps`);
141
+ console.log(`Total cost: $${result.totalCostUSDC} USDC\n`);
142
+ for (const step of result.steps) {
143
+ const status = step.skipped ? "SKIPPED" : "DONE";
144
+ const agent = step.agent?.name ?? "—";
145
+ console.log(` [${status}] ${step.role}: ${agent}`);
146
+ if (step.reason) console.log(` Reason: ${step.reason}`);
147
+ }
148
+ }
149
+ }
150
+ );
151
+
152
+ program
153
+ .command("accept-jobs")
154
+ .description("Start listening for incoming ACP jobs")
155
+ .option("-c, --capabilities <list>", "comma-separated capabilities", "general")
156
+ .action(async (opts: { capabilities: string }) => {
157
+ const kompass = await KompassSimple.create(getConfig());
158
+ const capabilities = opts.capabilities.split(",").map((s) => s.trim());
159
+
160
+ console.log(`\nListening for jobs: ${capabilities.join(", ")}`);
161
+ console.log("Press Ctrl+C to stop.\n");
162
+
163
+ await kompass.acceptJobs({
164
+ capabilities,
165
+ handler: async (job) => {
166
+ console.log(`\nReceived job: ${job.jobId}`);
167
+ console.log(` Description: ${job.description}`);
168
+ console.log(` Budget: ${job.budget}`);
169
+ // Default handler just acknowledges
170
+ return { status: "received", jobId: job.jobId, message: "Job acknowledged" };
171
+ },
172
+ });
173
+
174
+ // Keep alive
175
+ await new Promise(() => {});
176
+ });
177
+
178
+ program
179
+ .command("balance")
180
+ .description("Check your wallet balance")
181
+ .action(async () => {
182
+ const config = getConfig();
183
+ const { privateKeyToAccount } = await import("viem/accounts");
184
+ const { createPublicClient, http, formatEther, formatUnits } = await import("viem");
185
+ const { baseSepolia } = await import("viem/chains");
186
+
187
+ const account = privateKeyToAccount(config.privateKey as `0x${string}`);
188
+ const client = createPublicClient({
189
+ chain: baseSepolia,
190
+ transport: http(config.rpcUrl ?? "https://sepolia.base.org"),
191
+ });
192
+
193
+ const eth = await client.getBalance({ address: account.address });
194
+ console.log(`\nAddress: ${account.address}`);
195
+ console.log(`ETH: ${formatEther(eth)}`);
196
+ console.log(`Backend: ACP (Virtuals Protocol)`);
197
+ });
198
+
199
+ // ── Core Command: Do ─────────────────────────────────────
200
+
201
+ program
202
+ .command("do <task>")
203
+ .description("Get any job done — finds the right capability across all protocols and executes it")
204
+ .option("-b, --budget <usd>", "max budget in USD", "1")
205
+ .option("-c, --cost <preference>", "cheapest | balanced | best-quality", "balanced")
206
+ .option("-p, --protocol <protocol>", "prefer specific protocol (acp, x402, mcp, skill)")
207
+ .option("--dry-run", "show options without executing")
208
+ .option("--json", "output as JSON")
209
+ .action(
210
+ async (
211
+ task: string,
212
+ opts: { budget: string; cost: string; protocol?: string; dryRun?: boolean; json?: boolean }
213
+ ) => {
214
+ const { KompassUnified } = await import("./unified.js");
215
+ const kompass = await KompassUnified.create();
216
+
217
+ if (!opts.json) {
218
+ console.log(`\n⚡ Kompass: Getting it done — "${task}"\n`);
219
+ }
220
+
221
+ const result = await kompass.do({
222
+ task,
223
+ maxBudgetUSD: parseFloat(opts.budget),
224
+ costPreference: opts.cost as any,
225
+ preferProtocol: opts.protocol,
226
+ dryRun: opts.dryRun,
227
+ });
228
+
229
+ if (opts.json) {
230
+ console.log(JSON.stringify(result, null, 2));
231
+ return;
232
+ }
233
+
234
+ console.log(`Sources queried: ${result.discovery.sourcesQueried} (${result.discovery.queryTimeMs}ms)`);
235
+ console.log(`Options found: ${result.options.length}\n`);
236
+
237
+ if (result.options.length > 0) {
238
+ console.log("Top options:");
239
+ for (const opt of result.options.slice(0, 5)) {
240
+ const cost = opt.estimatedCost !== null ? `$${opt.estimatedCost}` : "unknown";
241
+ console.log(` [${opt.protocol.toUpperCase()}] ${opt.agent.name} (${opt.source}) — ${cost}`);
242
+ console.log(` ${opt.why}`);
243
+ }
244
+ }
245
+
246
+ if (result.selected) {
247
+ console.log(`\n${opts.dryRun ? "Would select" : "Selected"}: ${result.selected.agent.name} [${result.selected.protocol}]`);
248
+ console.log(`Reasoning: ${result.reasoning}`);
249
+ }
250
+
251
+ if (result.execution) {
252
+ console.log(`\nExecution: ${result.execution.success ? "✅ Success" : "❌ Failed"}`);
253
+ if (result.execution.error) console.log(`Error: ${result.execution.error}`);
254
+ if (result.execution.deliverable) {
255
+ console.log(`\nDeliverable:`);
256
+ console.log(typeof result.execution.deliverable === "string"
257
+ ? result.execution.deliverable.slice(0, 500)
258
+ : JSON.stringify(result.execution.deliverable, null, 2).slice(0, 500));
259
+ }
260
+ }
261
+
262
+ console.log();
263
+ }
264
+ );
265
+
266
+ // ── A2A Server Command ───────────────────────────────────
267
+
268
+ program
269
+ .command("serve")
270
+ .description("Start Kompass as an A2A-compatible agent server")
271
+ .option("-p, --port <port>", "port to listen on", "3000")
272
+ .action(async (opts: { port: string }) => {
273
+ const { startA2AServer } = await import("./a2a/server.js");
274
+ const { KompassUnified } = await import("./unified.js");
275
+ const kompass = await KompassUnified.create();
276
+ await startA2AServer({ port: parseInt(opts.port), kompass });
277
+ });
278
+
279
+ program
280
+ .command("coordinate <intent>")
281
+ .description("Coordinate multiple agents across protocols via A2A")
282
+ .option("--steps <roles>", "comma-separated roles", "research,analysis")
283
+ .option("--json", "output as JSON")
284
+ .action(async (intent: string, opts: { steps: string; json?: boolean }) => {
285
+ const { KompassUnified } = await import("./unified.js");
286
+ const { A2ABridge } = await import("./a2a/bridge.js");
287
+ const { ProtocolBridge } = await import("./bridge.js");
288
+
289
+ const kompass = await KompassUnified.create();
290
+ const bridge = new A2ABridge(new ProtocolBridge());
291
+
292
+ const roles = opts.steps.split(",").map((r) => r.trim());
293
+ const steps = roles.map((role, i) => ({
294
+ id: role,
295
+ role,
296
+ query: `${role} ${intent}`,
297
+ dependsOn: i > 0 ? roles[i - 1] : undefined,
298
+ }));
299
+
300
+ console.log(`\n🔗 Coordinating ${roles.length} agents for: "${intent}"\n`);
301
+
302
+ const result = await bridge.coordinate(steps, async (query) => {
303
+ const found = await kompass.find(query, { limit: 3 });
304
+ return found.agents[0] ?? null;
305
+ });
306
+
307
+ if (opts.json) {
308
+ console.log(JSON.stringify(result, null, 2));
309
+ } else {
310
+ for (const step of result.steps) {
311
+ const status = step.success ? "✅" : step.skipped ? "⏭️" : "❌";
312
+ const agent = step.agent ? `${step.agent.name} [${step.agent.protocol}]` : "no agent";
313
+ console.log(` ${status} ${step.role}: ${agent}`);
314
+ if (step.error) console.log(` Error: ${step.error}`);
315
+ }
316
+ console.log(`\n${result.completedCount}/${result.totalCount} steps completed\n`);
317
+ }
318
+ });
319
+
320
+ // ── Universal Discovery Commands ─────────────────────────
321
+
322
+ program
323
+ .command("find <query>")
324
+ .description("Search for agents across ALL registries (ACP, MCP, ERC-8004, x402, A2A, L402)")
325
+ .option("-l, --limit <n>", "max results", "20")
326
+ .option("-s, --source <sources...>", "filter by source (e.g., acp mcp-registry x402-ecosystem)")
327
+ .option("--json", "output as JSON")
328
+ .action(async (query: string, opts: { limit: string; source?: string[]; json?: boolean }) => {
329
+ console.log(`\n🔍 Searching across all agent registries for: "${query}"\n`);
330
+
331
+ const sources = createAllSources();
332
+ const aggregator = new Aggregator(sources);
333
+
334
+ const result = await aggregator.search(query, {
335
+ limit: parseInt(opts.limit),
336
+ sources: opts.source,
337
+ });
338
+
339
+ if (opts.json) {
340
+ console.log(JSON.stringify(result, null, 2));
341
+ return;
342
+ }
343
+
344
+ // Print source stats
345
+ console.log("Sources queried:");
346
+ for (const src of result.sources) {
347
+ const status = src.error ? `❌ ${src.error}` : `✅ ${src.count} agents`;
348
+ console.log(` ${src.name.padEnd(20)} ${status} (${src.durationMs}ms)`);
349
+ }
350
+
351
+ console.log(`\nFound ${result.totalFound} agents (${result.deduplicated} duplicates removed)`);
352
+ console.log(`Query time: ${result.queryTimeMs}ms\n`);
353
+
354
+ if (result.agents.length === 0) {
355
+ console.log("No agents found.");
356
+ return;
357
+ }
358
+
359
+ console.log("─".repeat(80));
360
+ for (const agent of result.agents) {
361
+ const score = (agent as any)._score ?? 0;
362
+ const rep = agent.reputation ? ` | rep: ${agent.reputation.score}/${agent.reputation.count}` : "";
363
+ const price = agent.pricing?.amount ? ` | $${agent.pricing.amount} ${agent.pricing.currency ?? ""}` : "";
364
+ const protocol = agent.protocol.toUpperCase();
365
+
366
+ console.log(` [${protocol}] ${agent.name} (${agent.source})`);
367
+ console.log(` ${agent.description.slice(0, 120)}`);
368
+ console.log(` Categories: ${agent.categories.join(", ")} | Score: ${score}${rep}${price}`);
369
+ if (agent.endpoints.x402) console.log(` x402: ${agent.endpoints.x402}`);
370
+ if (agent.endpoints.mcp) console.log(` MCP: ${agent.endpoints.mcp}`);
371
+ console.log();
372
+ }
373
+ console.log("─".repeat(80));
374
+ });
375
+
376
+ program
377
+ .command("sources")
378
+ .description("List all available discovery sources and their health status")
379
+ .action(async () => {
380
+ console.log("\n📡 Checking discovery sources...\n");
381
+
382
+ const sources = createAllSources();
383
+ const aggregator = new Aggregator(sources);
384
+ const health = await aggregator.healthCheck();
385
+
386
+ for (const src of health) {
387
+ const status = src.healthy ? "🟢 ONLINE" : "🔴 OFFLINE";
388
+ console.log(` ${status} ${src.displayName} (${src.name})`);
389
+ }
390
+
391
+ const online = health.filter((h) => h.healthy).length;
392
+ console.log(`\n${online}/${health.length} sources online\n`);
393
+ });
394
+
395
+ // ── Run ──────────────────────────────────────────────────
396
+
397
+ program.parse();