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
@@ -0,0 +1,253 @@
1
+ import { type Address, type Hex, keccak256, parseEventLogs, toHex } from "viem";
2
+ import type { AgentProfile, KompassConfig, TxResult } from "./types.js";
3
+ import type { IntentRoute, AgentCapabilityRole, YieldIntent } from "./intents.js";
4
+ import { PipelineOrchestratorAbi, Erc20ApproveAbi } from "./pipelineAbi.js";
5
+
6
+ export type PipelineSettlementMode = "escrow" | "x402";
7
+
8
+ export interface YieldPipelineSubtask {
9
+ role: AgentCapabilityRole;
10
+ provider: Address;
11
+ evaluator: Address;
12
+ budget: bigint;
13
+ description: string;
14
+ dependencies: number[];
15
+ settlementMode: PipelineSettlementMode;
16
+ agent: AgentProfile;
17
+ }
18
+
19
+ export interface YieldPipelinePlan {
20
+ token: Address;
21
+ intentHash: Hex;
22
+ intentSummary: string;
23
+ subtasks: YieldPipelineSubtask[];
24
+ offchainSteps: Array<{
25
+ role: AgentCapabilityRole;
26
+ description: string;
27
+ endpointX402: string;
28
+ agent: AgentProfile;
29
+ }>;
30
+ }
31
+
32
+ export interface CreatePipelineOptions {
33
+ token?: Address;
34
+ autoApprove?: boolean;
35
+ autoActivate?: boolean;
36
+ }
37
+
38
+ export interface CreatePipelineResult extends TxResult {
39
+ pipelineId: bigint;
40
+ approveTxHash?: Hex;
41
+ fundTxHash: Hex;
42
+ activateTxHash?: Hex;
43
+ }
44
+
45
+ function requireWallet(config: KompassConfig) {
46
+ if (!config.walletClient) {
47
+ throw new Error("WalletClient required for pipeline creation");
48
+ }
49
+ return config.walletClient;
50
+ }
51
+
52
+ function requirePipelineAddress(config: KompassConfig): Address {
53
+ if (!config.pipelineAddress) {
54
+ throw new Error("pipelineAddress is required in KompassConfig for pipeline operations");
55
+ }
56
+ return config.pipelineAddress;
57
+ }
58
+
59
+ function roleLabel(role: AgentCapabilityRole): string {
60
+ switch (role) {
61
+ case "research":
62
+ return "research";
63
+ case "premium-data":
64
+ return "premium data";
65
+ case "risk":
66
+ return "risk review";
67
+ case "execution":
68
+ return "execution";
69
+ }
70
+ }
71
+
72
+ function inferSettlementMode(agent: AgentProfile, role: AgentCapabilityRole): PipelineSettlementMode {
73
+ if (role === "premium-data") return "x402";
74
+ if (agent.paymentMode === "x402" && !agent.endpointX402) return "x402";
75
+ return "escrow";
76
+ }
77
+
78
+ function fallbackBudget(agent: AgentProfile, role: AgentCapabilityRole, intent: YieldIntent): bigint {
79
+ const basisPoints =
80
+ role === "premium-data" ? 50n :
81
+ role === "research" ? 125n :
82
+ role === "risk" ? 100n :
83
+ 150n;
84
+ return (intent.amount * basisPoints) / 10_000n;
85
+ }
86
+
87
+ export function buildYieldPipelinePlan(route: IntentRoute, options: { token: Address }): YieldPipelinePlan {
88
+ const riskAgent = route.steps.find((step) => step.role === "risk")?.agent;
89
+ const onchainSubtasks: YieldPipelineSubtask[] = [];
90
+ const offchainSteps: YieldPipelinePlan["offchainSteps"] = [];
91
+ const stepIndexByRole = new Map<AgentCapabilityRole, number>();
92
+
93
+ for (const step of route.steps) {
94
+ if (!step.agent) continue;
95
+
96
+ const settlementMode = inferSettlementMode(step.agent, step.role);
97
+ const budget = step.agent.pricingRate
98
+ ? BigInt(step.agent.pricingRate)
99
+ : fallbackBudget(step.agent, step.role, route.intent);
100
+
101
+ if (settlementMode === "x402") {
102
+ offchainSteps.push({
103
+ role: step.role,
104
+ description: `Use ${step.agent.ensName || step.agent.id} for ${roleLabel(step.role)} over x402 before escrow execution.`,
105
+ endpointX402: step.agent.endpointX402,
106
+ agent: step.agent,
107
+ });
108
+ continue;
109
+ }
110
+
111
+ const dependencies: number[] = [];
112
+ const previousResearch = stepIndexByRole.get("research");
113
+ const previousRisk = stepIndexByRole.get("risk");
114
+
115
+ if (step.role === "risk" && previousResearch !== undefined) {
116
+ dependencies.push(previousResearch);
117
+ }
118
+
119
+ if (step.role === "execution") {
120
+ if (previousRisk !== undefined) {
121
+ dependencies.push(previousRisk);
122
+ } else if (previousResearch !== undefined) {
123
+ dependencies.push(previousResearch);
124
+ }
125
+ }
126
+
127
+ const evaluator = riskAgent?.id ?? step.agent.id;
128
+
129
+ onchainSubtasks.push({
130
+ role: step.role,
131
+ provider: step.agent.id,
132
+ evaluator,
133
+ budget,
134
+ description: `${step.title}: ${step.summary}`,
135
+ dependencies,
136
+ settlementMode,
137
+ agent: step.agent,
138
+ });
139
+ stepIndexByRole.set(step.role, onchainSubtasks.length - 1);
140
+ }
141
+
142
+ return {
143
+ token: options.token,
144
+ intentHash: keccak256(toHex(route.summary)),
145
+ intentSummary: route.summary,
146
+ subtasks: onchainSubtasks,
147
+ offchainSteps,
148
+ };
149
+ }
150
+
151
+ export async function createYieldPipeline(
152
+ config: KompassConfig,
153
+ route: IntentRoute,
154
+ options: CreatePipelineOptions = {}
155
+ ): Promise<CreatePipelineResult> {
156
+ const wallet = requireWallet(config);
157
+ const pipelineAddress = requirePipelineAddress(config);
158
+ const token = options.token ?? config.paymentTokenAddress;
159
+
160
+ if (!token) {
161
+ throw new Error("paymentTokenAddress is required in KompassConfig or createYieldPipeline options");
162
+ }
163
+
164
+ const plan = buildYieldPipelinePlan(route, { token });
165
+ if (plan.subtasks.length === 0) {
166
+ throw new Error("No escrow-capable subtasks were generated for this intent route");
167
+ }
168
+
169
+ const hookAddress = config.defaultHookAddress;
170
+ const createTxHash = hookAddress
171
+ ? await wallet.writeContract({
172
+ address: pipelineAddress,
173
+ abi: PipelineOrchestratorAbi,
174
+ functionName: "createPipelineWithHook",
175
+ args: [token, plan.intentHash, hookAddress],
176
+ })
177
+ : await wallet.writeContract({
178
+ address: pipelineAddress,
179
+ abi: PipelineOrchestratorAbi,
180
+ functionName: "createPipeline",
181
+ args: [token, plan.intentHash],
182
+ });
183
+
184
+ const createReceipt = await config.publicClient.waitForTransactionReceipt({ hash: createTxHash });
185
+ const events = parseEventLogs({
186
+ abi: PipelineOrchestratorAbi,
187
+ logs: createReceipt.logs,
188
+ eventName: "PipelineCreated",
189
+ });
190
+
191
+ if (events.length === 0) {
192
+ throw new Error("PipelineCreated event not found in receipt");
193
+ }
194
+
195
+ const pipelineId = events[0].args.pipelineId;
196
+
197
+ for (const subtask of plan.subtasks) {
198
+ const descriptionHash = keccak256(toHex(subtask.description));
199
+ const addTxHash = await wallet.writeContract({
200
+ address: pipelineAddress,
201
+ abi: PipelineOrchestratorAbi,
202
+ functionName: "addSubTask",
203
+ args: [
204
+ pipelineId,
205
+ subtask.provider,
206
+ subtask.evaluator,
207
+ subtask.budget,
208
+ descriptionHash,
209
+ subtask.dependencies.map((dependency) => BigInt(dependency)),
210
+ ],
211
+ });
212
+ await config.publicClient.waitForTransactionReceipt({ hash: addTxHash });
213
+ }
214
+
215
+ let approveTxHash: Hex | undefined;
216
+ const totalBudget = plan.subtasks.reduce((sum, subtask) => sum + subtask.budget, 0n);
217
+ if (options.autoApprove ?? true) {
218
+ approveTxHash = await wallet.writeContract({
219
+ address: token,
220
+ abi: Erc20ApproveAbi,
221
+ functionName: "approve",
222
+ args: [pipelineAddress, totalBudget],
223
+ });
224
+ await config.publicClient.waitForTransactionReceipt({ hash: approveTxHash });
225
+ }
226
+
227
+ const fundTxHash = await wallet.writeContract({
228
+ address: pipelineAddress,
229
+ abi: PipelineOrchestratorAbi,
230
+ functionName: "fundPipeline",
231
+ args: [pipelineId],
232
+ });
233
+ await config.publicClient.waitForTransactionReceipt({ hash: fundTxHash });
234
+
235
+ let activateTxHash: Hex | undefined;
236
+ if (options.autoActivate ?? true) {
237
+ activateTxHash = await wallet.writeContract({
238
+ address: pipelineAddress,
239
+ abi: PipelineOrchestratorAbi,
240
+ functionName: "activateNextTasks",
241
+ args: [pipelineId],
242
+ });
243
+ await config.publicClient.waitForTransactionReceipt({ hash: activateTxHash });
244
+ }
245
+
246
+ return {
247
+ txHash: createTxHash,
248
+ pipelineId,
249
+ approveTxHash,
250
+ fundTxHash,
251
+ activateTxHash,
252
+ };
253
+ }
@@ -0,0 +1,232 @@
1
+ import { encodePacked, type Hex } from "viem";
2
+ import { KompassRegistryAbi } from "./abi.js";
3
+ import type { KompassConfig, RegisterProfile, TxResult } from "./types.js";
4
+
5
+ /** ENS text record key mapping */
6
+ const RECORD_KEYS: Record<string, string> = {
7
+ ensName: "com.kompass.identity.name",
8
+ agentType: "com.kompass.type",
9
+ categories: "com.kompass.categories",
10
+ erc8004Id: "com.kompass.erc8004.id",
11
+ identityVerification: "com.kompass.identity.verification",
12
+ paymentMode: "com.kompass.payment.mode",
13
+ pricingModel: "com.kompass.pricing.model",
14
+ pricingRate: "com.kompass.pricing.rate",
15
+ pricingToken: "com.kompass.pricing.token",
16
+ endpointMcp: "com.kompass.endpoint.mcp",
17
+ endpointA2a: "com.kompass.endpoint.a2a",
18
+ endpointX402: "com.kompass.endpoint.x402",
19
+ evaluatorDomains: "com.kompass.evaluator.domains",
20
+ description: "com.kompass.description",
21
+ };
22
+
23
+ /** ENS L2 Resolver ABI (just setText) */
24
+ const resolverAbi = [
25
+ {
26
+ type: "function",
27
+ name: "setText",
28
+ inputs: [
29
+ { name: "node", type: "bytes32" },
30
+ { name: "key", type: "string" },
31
+ { name: "value", type: "string" },
32
+ ],
33
+ outputs: [],
34
+ stateMutability: "nonpayable",
35
+ },
36
+ ] as const;
37
+
38
+ function requireWallet(config: KompassConfig) {
39
+ if (!config.walletClient) {
40
+ throw new Error("WalletClient required for write operations");
41
+ }
42
+ return config.walletClient;
43
+ }
44
+
45
+ // ── ENSIP-25 Helpers ────────────────────────────────────
46
+
47
+ /**
48
+ * Compute the ENSIP-25 text record key for an agent.
49
+ *
50
+ * Format: `agent-registration[<registryIdentifier>][<agentId>]`
51
+ * Where registryIdentifier = encodePacked(chainId, registryType, registryAddress)
52
+ *
53
+ * @see https://docs.ens.domains/ensip/25
54
+ */
55
+ export function computeENSIP25Key(
56
+ chainId: bigint,
57
+ registryAddress: `0x${string}`,
58
+ agentId: string,
59
+ registryType: number = 0x01 // ERC-8004
60
+ ): string {
61
+ const registryIdentifier = encodePacked(
62
+ ["uint256", "uint8", "address"],
63
+ [chainId, registryType, registryAddress as `0x${string}`]
64
+ );
65
+ return `agent-registration[${registryIdentifier}][${agentId}]`;
66
+ }
67
+
68
+ /**
69
+ * Set the ENSIP-25 text record on an agent's ENS name.
70
+ * Creates bidirectional verification: ENS name → on-chain agent identity.
71
+ */
72
+ export async function setENSIP25Record(
73
+ config: KompassConfig,
74
+ ensNode: Hex,
75
+ agentId: string,
76
+ chainId: bigint = 84532n // Base Sepolia
77
+ ): Promise<TxResult> {
78
+ const wallet = requireWallet(config);
79
+
80
+ const resolverAddress = await config.publicClient.readContract({
81
+ address: config.registryAddress,
82
+ abi: KompassRegistryAbi,
83
+ functionName: "resolver",
84
+ });
85
+
86
+ const key = computeENSIP25Key(
87
+ chainId,
88
+ config.reputationRegistryAddress,
89
+ agentId
90
+ );
91
+
92
+ const txHash = await wallet.writeContract({
93
+ address: resolverAddress,
94
+ abi: resolverAbi,
95
+ functionName: "setText",
96
+ args: [ensNode, key, "1"],
97
+ });
98
+ await config.publicClient.waitForTransactionReceipt({ hash: txHash });
99
+
100
+ return { txHash };
101
+ }
102
+
103
+ /**
104
+ * Register an agent with the Kompass protocol.
105
+ *
106
+ * Flow:
107
+ * 1. Set ENS text records on the L2 resolver (from the agent's wallet)
108
+ * 2. Call registerAgent(ensNode) on the registry contract
109
+ *
110
+ * The caller must own the Basename identified by ensNode.
111
+ */
112
+ export async function register(config: KompassConfig, profile: RegisterProfile): Promise<TxResult> {
113
+ const wallet = requireWallet(config);
114
+
115
+ // Step 1: Read the resolver address from the registry contract
116
+ const resolverAddress = await config.publicClient.readContract({
117
+ address: config.registryAddress,
118
+ abi: KompassRegistryAbi,
119
+ functionName: "resolver",
120
+ });
121
+
122
+ // Step 2: Set ENS text records on the resolver
123
+ for (const [field, key] of Object.entries(RECORD_KEYS)) {
124
+ const value = profile[field as keyof RegisterProfile];
125
+ if (value !== undefined && typeof value === "string" && value !== "") {
126
+ const setTxHash = await wallet.writeContract({
127
+ address: resolverAddress,
128
+ abi: resolverAbi,
129
+ functionName: "setText",
130
+ args: [profile.ensNode, key, value],
131
+ });
132
+ await config.publicClient.waitForTransactionReceipt({ hash: setTxHash });
133
+ }
134
+ }
135
+
136
+ if (profile.identityVerification) {
137
+ const verificationTxHash = await wallet.writeContract({
138
+ address: resolverAddress,
139
+ abi: resolverAbi,
140
+ functionName: "setText",
141
+ args: [profile.ensNode, profile.identityVerification, "verified"],
142
+ });
143
+ await config.publicClient.waitForTransactionReceipt({ hash: verificationTxHash });
144
+ }
145
+
146
+ // Step 3: Register the agent on the registry contract
147
+ const txHash = await wallet.writeContract({
148
+ address: config.registryAddress,
149
+ abi: KompassRegistryAbi,
150
+ functionName: "registerAgent",
151
+ args: [profile.ensNode],
152
+ });
153
+ await config.publicClient.waitForTransactionReceipt({ hash: txHash });
154
+
155
+ // Step 4: Set ENSIP-25 text record for bidirectional agent verification
156
+ // Uses the ERC-8004 agent ID from the profile if available
157
+ if (profile.erc8004Id) {
158
+ try {
159
+ await setENSIP25Record(config, profile.ensNode, profile.erc8004Id);
160
+ } catch (err) {
161
+ // Non-critical: registration succeeded, ENSIP-25 is bonus
162
+ console.warn("ENSIP-25 text record failed (non-critical):", err);
163
+ }
164
+ }
165
+
166
+ return { txHash };
167
+ }
168
+
169
+ /**
170
+ * Update an agent's ENS text records.
171
+ * Only updates the fields that are provided (non-undefined).
172
+ */
173
+ export async function updateProfile(
174
+ config: KompassConfig,
175
+ ensNode: Hex,
176
+ updates: Partial<Omit<RegisterProfile, "ensNode">>
177
+ ): Promise<TxResult> {
178
+ const wallet = requireWallet(config);
179
+
180
+ const resolverAddress = await config.publicClient.readContract({
181
+ address: config.registryAddress,
182
+ abi: KompassRegistryAbi,
183
+ functionName: "resolver",
184
+ });
185
+
186
+ let lastTxHash: Hex = "0x" as Hex;
187
+
188
+ for (const [field, key] of Object.entries(RECORD_KEYS)) {
189
+ const value = updates[field as keyof typeof updates];
190
+ if (value !== undefined && typeof value === "string") {
191
+ lastTxHash = await wallet.writeContract({
192
+ address: resolverAddress,
193
+ abi: resolverAbi,
194
+ functionName: "setText",
195
+ args: [ensNode, key, value],
196
+ });
197
+ await config.publicClient.waitForTransactionReceipt({ hash: lastTxHash });
198
+ }
199
+ }
200
+
201
+ if (typeof updates.identityVerification === "string" && updates.identityVerification !== "") {
202
+ lastTxHash = await wallet.writeContract({
203
+ address: resolverAddress,
204
+ abi: resolverAbi,
205
+ functionName: "setText",
206
+ args: [ensNode, updates.identityVerification, "verified"],
207
+ });
208
+ await config.publicClient.waitForTransactionReceipt({ hash: lastTxHash });
209
+ }
210
+
211
+ if (lastTxHash === "0x") {
212
+ throw new Error("No fields provided to update");
213
+ }
214
+
215
+ return { txHash: lastTxHash };
216
+ }
217
+
218
+ /**
219
+ * Deregister an agent from the protocol.
220
+ */
221
+ export async function deregister(config: KompassConfig): Promise<TxResult> {
222
+ const wallet = requireWallet(config);
223
+
224
+ const txHash = await wallet.writeContract({
225
+ address: config.registryAddress,
226
+ abi: KompassRegistryAbi,
227
+ functionName: "deregister",
228
+ });
229
+ await config.publicClient.waitForTransactionReceipt({ hash: txHash });
230
+
231
+ return { txHash };
232
+ }
@@ -0,0 +1,43 @@
1
+ import type { Address } from "viem";
2
+ import { ERC8004ReputationAbi } from "./abi.js";
3
+ import type { KompassConfig, ReputationSummary } from "./types.js";
4
+
5
+ /**
6
+ * Get reputation summary for an agent from the ERC-8004 Reputation Registry.
7
+ *
8
+ * @param agentId - The ERC-8004 agent ID (uint256)
9
+ * @param tag1 - Optional primary tag filter (e.g., "job-completed")
10
+ * @param tag2 - Optional secondary tag filter
11
+ */
12
+ export async function getReputation(
13
+ config: KompassConfig,
14
+ agentId: bigint,
15
+ tag1: string = "",
16
+ tag2: string = ""
17
+ ): Promise<ReputationSummary> {
18
+ // First get all clients who have given feedback
19
+ const clients = await config.publicClient.readContract({
20
+ address: config.reputationRegistryAddress,
21
+ abi: ERC8004ReputationAbi,
22
+ functionName: "getClients",
23
+ args: [agentId],
24
+ });
25
+
26
+ if ((clients as Address[]).length === 0) {
27
+ return { count: 0n, summaryValue: 0n, summaryValueDecimals: 0 };
28
+ }
29
+
30
+ // Get summary across all clients
31
+ const [count, summaryValue, summaryValueDecimals] = await config.publicClient.readContract({
32
+ address: config.reputationRegistryAddress,
33
+ abi: ERC8004ReputationAbi,
34
+ functionName: "getSummary",
35
+ args: [agentId, clients as Address[], tag1, tag2],
36
+ });
37
+
38
+ return {
39
+ count: BigInt(count),
40
+ summaryValue: BigInt(summaryValue),
41
+ summaryValueDecimals: Number(summaryValueDecimals),
42
+ };
43
+ }