@absol-labs/agent 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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +196 -0
  3. package/dist/discovery/registry.d.ts +68 -0
  4. package/dist/discovery/registry.d.ts.map +1 -0
  5. package/dist/discovery/registry.js +148 -0
  6. package/dist/discovery/registry.js.map +1 -0
  7. package/dist/frameworks/agentkit.d.ts +158 -0
  8. package/dist/frameworks/agentkit.d.ts.map +1 -0
  9. package/dist/frameworks/agentkit.js +339 -0
  10. package/dist/frameworks/agentkit.js.map +1 -0
  11. package/dist/frameworks/crewai.d.ts +19 -0
  12. package/dist/frameworks/crewai.d.ts.map +1 -0
  13. package/dist/frameworks/crewai.js +73 -0
  14. package/dist/frameworks/crewai.js.map +1 -0
  15. package/dist/frameworks/eliza.d.ts +393 -0
  16. package/dist/frameworks/eliza.d.ts.map +1 -0
  17. package/dist/frameworks/eliza.js +542 -0
  18. package/dist/frameworks/eliza.js.map +1 -0
  19. package/dist/frameworks/langchain.d.ts +31 -0
  20. package/dist/frameworks/langchain.d.ts.map +1 -0
  21. package/dist/frameworks/langchain.js +206 -0
  22. package/dist/frameworks/langchain.js.map +1 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +16 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/mandates/env.d.ts +51 -0
  28. package/dist/mandates/env.d.ts.map +1 -0
  29. package/dist/mandates/env.js +148 -0
  30. package/dist/mandates/env.js.map +1 -0
  31. package/dist/mandates/mandate.d.ts +214 -0
  32. package/dist/mandates/mandate.d.ts.map +1 -0
  33. package/dist/mandates/mandate.js +172 -0
  34. package/dist/mandates/mandate.js.map +1 -0
  35. package/dist/mcp/http-server.d.ts +2 -0
  36. package/dist/mcp/http-server.d.ts.map +1 -0
  37. package/dist/mcp/http-server.js +32 -0
  38. package/dist/mcp/http-server.js.map +1 -0
  39. package/dist/mcp/http.d.ts +114 -0
  40. package/dist/mcp/http.d.ts.map +1 -0
  41. package/dist/mcp/http.js +428 -0
  42. package/dist/mcp/http.js.map +1 -0
  43. package/dist/mcp/server.d.ts +119 -0
  44. package/dist/mcp/server.d.ts.map +1 -0
  45. package/dist/mcp/server.js +679 -0
  46. package/dist/mcp/server.js.map +1 -0
  47. package/dist/mcp/stdio.d.ts +2 -0
  48. package/dist/mcp/stdio.d.ts.map +1 -0
  49. package/dist/mcp/stdio.js +6 -0
  50. package/dist/mcp/stdio.js.map +1 -0
  51. package/dist/sdk/client.d.ts +78 -0
  52. package/dist/sdk/client.d.ts.map +1 -0
  53. package/dist/sdk/client.js +99 -0
  54. package/dist/sdk/client.js.map +1 -0
  55. package/dist/wallet/provider.d.ts +51 -0
  56. package/dist/wallet/provider.d.ts.map +1 -0
  57. package/dist/wallet/provider.js +107 -0
  58. package/dist/wallet/provider.js.map +1 -0
  59. package/dist/x402/facilitator.d.ts +315 -0
  60. package/dist/x402/facilitator.d.ts.map +1 -0
  61. package/dist/x402/facilitator.js +194 -0
  62. package/dist/x402/facilitator.js.map +1 -0
  63. package/dist/zktls/reclaim.d.ts +137 -0
  64. package/dist/zktls/reclaim.d.ts.map +1 -0
  65. package/dist/zktls/reclaim.js +245 -0
  66. package/dist/zktls/reclaim.js.map +1 -0
  67. package/package.json +86 -0
  68. package/src/discovery/registry.ts +255 -0
  69. package/src/frameworks/agentkit.ts +537 -0
  70. package/src/frameworks/crewai.ts +102 -0
  71. package/src/frameworks/eliza.ts +776 -0
  72. package/src/frameworks/langchain.ts +325 -0
  73. package/src/index.ts +179 -0
  74. package/src/mandates/env.ts +222 -0
  75. package/src/mandates/mandate.ts +280 -0
  76. package/src/mcp/http-server.ts +38 -0
  77. package/src/mcp/http.ts +620 -0
  78. package/src/mcp/server.ts +1006 -0
  79. package/src/mcp/stdio.ts +8 -0
  80. package/src/sdk/client.ts +222 -0
  81. package/src/wallet/provider.ts +197 -0
  82. package/src/x402/facilitator.ts +336 -0
  83. package/src/zktls/reclaim.ts +424 -0
@@ -0,0 +1,336 @@
1
+ import type { StreamProofClientConfig } from "@absol-labs/sdk";
2
+ import { z } from "zod";
3
+
4
+ import {
5
+ signedSpendMandateSchema,
6
+ type SignedSpendMandate,
7
+ } from "../mandates/mandate.js";
8
+ import {
9
+ VerifiedStreamAgentClient,
10
+ type VerifiedStreamAgentOpener,
11
+ } from "../sdk/client.js";
12
+ import {
13
+ type ConsumerDeliveryProofService,
14
+ type HttpsResponseMatch,
15
+ type HttpsResponseRedaction,
16
+ type VerifiedConsumedHttpsResponseProof,
17
+ } from "../zktls/reclaim.js";
18
+
19
+ export const X402_SCHEME = "streamproof-verified-stream" as const;
20
+
21
+ const addressSchema = z.string().regex(/^0x[0-9a-fA-F]{40}$/);
22
+ const bytes32Schema = z.string().regex(/^0x[0-9a-fA-F]{64}$/);
23
+
24
+ export const verifiedStreamRequirementsSchema = z.object({
25
+ operator: addressSchema,
26
+ serviceRef: bytes32Schema,
27
+ chainId: z.number().int().positive(),
28
+ escrow: addressSchema,
29
+ ratePerSecondUsdc: z.bigint().positive(),
30
+ maxDurationSeconds: z.number().int().positive(),
31
+ maxBudgetUsdc: z.bigint().positive(),
32
+ });
33
+
34
+ export interface VerifiedStreamRequirements extends z.infer<
35
+ typeof verifiedStreamRequirementsSchema
36
+ > {}
37
+
38
+ export const x402StreamChallengeSchema = z.object({
39
+ scheme: z.literal(X402_SCHEME),
40
+ requirements: verifiedStreamRequirementsSchema,
41
+ });
42
+
43
+ export interface X402StreamChallenge extends z.infer<
44
+ typeof x402StreamChallengeSchema
45
+ > {}
46
+
47
+ export const x402OpenPayloadSchema = z.object({
48
+ challenge: x402StreamChallengeSchema,
49
+ signedMandate: signedSpendMandateSchema,
50
+ });
51
+
52
+ export interface X402OpenPayload extends z.infer<
53
+ typeof x402OpenPayloadSchema
54
+ > {}
55
+
56
+ export interface X402Facilitator {
57
+ /** Build the 402 challenge a server returns to prompt a verified stream. */
58
+ challenge(req: VerifiedStreamRequirements): X402StreamChallenge;
59
+ /** Verify + open the stream from an agent's signed payment payload. */
60
+ open(payloadHeader: string): Promise<{ streamId: `0x${string}` }>;
61
+ /** Prove the HTTPS response consumed after opening a verified stream. */
62
+ proveConsumedHttpsResponse(
63
+ input: X402ConsumedHttpsResponseProofInput,
64
+ ): Promise<VerifiedConsumedHttpsResponseProof>;
65
+ }
66
+
67
+ export interface X402ConsumedHttpsResponseProofInput {
68
+ readonly signedMandate: SignedSpendMandate;
69
+ readonly streamId?: `0x${string}`;
70
+ readonly operator?: `0x${string}`;
71
+ readonly serviceRef?: `0x${string}`;
72
+ readonly url: string;
73
+ readonly method?: "GET" | "POST" | "PUT";
74
+ readonly headers?: Record<string, string>;
75
+ readonly body?: string;
76
+ readonly secretHeaders?: Record<string, string>;
77
+ readonly responseMatches: readonly HttpsResponseMatch[];
78
+ readonly responseRedactions?: readonly HttpsResponseRedaction[];
79
+ readonly cookie?: string;
80
+ readonly secretParamValues?: Record<string, string>;
81
+ readonly geoLocation?: string;
82
+ readonly useTee?: boolean;
83
+ readonly zkEngine?: "snarkjs" | "stwo";
84
+ }
85
+
86
+ export interface VerifiedStreamFacilitatorOptions {
87
+ readonly sdkConfig: StreamProofClientConfig;
88
+ readonly createAgentClient?: (
89
+ config: StreamProofClientConfig,
90
+ ) => VerifiedStreamAgentOpener;
91
+ readonly deliveryProofs?: ConsumerDeliveryProofService;
92
+ readonly nowSeconds?: () => number;
93
+ readonly resolveSpentSoFarUsdc?: (
94
+ signedMandate: SignedSpendMandate,
95
+ ) => bigint | Promise<bigint>;
96
+ readonly resolveRevokedMandateIds?: (
97
+ signedMandate: SignedSpendMandate,
98
+ ) => Iterable<`0x${string}`> | Promise<Iterable<`0x${string}`>>;
99
+ }
100
+
101
+ const warnedFacilitatorGaps = new Set<string>();
102
+
103
+ /** Emits a stderr warning at most once per process for a given key. */
104
+ function warnFacilitatorOnce(key: string, message: string): void {
105
+ if (warnedFacilitatorGaps.has(key)) {
106
+ return;
107
+ }
108
+ warnedFacilitatorGaps.add(key);
109
+ console.error(message);
110
+ }
111
+
112
+ export class X402PayloadError extends Error {
113
+ constructor(message: string) {
114
+ super(message);
115
+ this.name = "X402PayloadError";
116
+ }
117
+ }
118
+
119
+ export class SettlementTargetMismatchError extends Error {
120
+ constructor(message: string) {
121
+ super(message);
122
+ this.name = "SettlementTargetMismatchError";
123
+ }
124
+ }
125
+
126
+ export class DeliveryProofUnavailableError extends Error {
127
+ constructor(message: string) {
128
+ super(message);
129
+ this.name = "DeliveryProofUnavailableError";
130
+ }
131
+ }
132
+
133
+ export class VerifiedStreamX402Facilitator implements X402Facilitator {
134
+ private readonly agentClient: VerifiedStreamAgentOpener;
135
+ private readonly deliveryProofs: ConsumerDeliveryProofService | undefined;
136
+ private readonly sdkConfig: StreamProofClientConfig;
137
+ private readonly nowSeconds: () => number;
138
+ private readonly resolveSpentSoFarUsdc: (
139
+ signedMandate: SignedSpendMandate,
140
+ ) => bigint | Promise<bigint>;
141
+ private readonly resolveRevokedMandateIds: (
142
+ signedMandate: SignedSpendMandate,
143
+ ) => Iterable<`0x${string}`> | Promise<Iterable<`0x${string}`>>;
144
+
145
+ constructor(options: VerifiedStreamFacilitatorOptions) {
146
+ this.sdkConfig = options.sdkConfig;
147
+ this.agentClient = (options.createAgentClient ?? defaultAgentClientFactory)(
148
+ options.sdkConfig,
149
+ );
150
+ this.deliveryProofs = options.deliveryProofs;
151
+ this.nowSeconds =
152
+ options.nowSeconds ?? (() => Math.floor(Date.now() / 1000));
153
+ this.resolveSpentSoFarUsdc = options.resolveSpentSoFarUsdc ?? (() => 0n);
154
+ this.resolveRevokedMandateIds =
155
+ options.resolveRevokedMandateIds ?? (() => []);
156
+
157
+ // Fail-loud on the two mandate controls that require external state. This
158
+ // facilitator is stateless (no stream registry), so it cannot enforce the
159
+ // cumulative-cap or revocation without a wired resolver. Warn once so a
160
+ // deployment never silently ships with maxTotalUsdc / revocation disabled.
161
+ if (options.resolveSpentSoFarUsdc === undefined) {
162
+ warnFacilitatorOnce(
163
+ "x402-spent",
164
+ "[metrik] x402 facilitator: no resolveSpentSoFarUsdc wired — the mandate cumulative cap (maxTotalUsdc) is NOT enforced across streams (per-stream/rate/duration/operator/expiry still are).",
165
+ );
166
+ }
167
+ if (options.resolveRevokedMandateIds === undefined) {
168
+ warnFacilitatorOnce(
169
+ "x402-revocation",
170
+ "[metrik] x402 facilitator: no resolveRevokedMandateIds wired — revoked mandates will NOT be rejected until you wire a revocation store.",
171
+ );
172
+ }
173
+ }
174
+
175
+ challenge(req: VerifiedStreamRequirements): X402StreamChallenge {
176
+ const requirements = verifiedStreamRequirementsSchema.parse(req);
177
+ assertSettlementTarget(requirements, this.sdkConfig);
178
+ return { scheme: X402_SCHEME, requirements };
179
+ }
180
+
181
+ async open(payloadHeader: string): Promise<{ streamId: `0x${string}` }> {
182
+ const payload = parseX402PayloadHeader(payloadHeader);
183
+ assertSettlementTarget(payload.challenge.requirements, this.sdkConfig);
184
+
185
+ const spentSoFarUsdc = await this.resolveSpentSoFarUsdc(
186
+ payload.signedMandate,
187
+ );
188
+ const revokedMandateIds = await this.resolveRevokedMandateIds(
189
+ payload.signedMandate,
190
+ );
191
+
192
+ const result = await this.agentClient.openVerifiedStream({
193
+ operator: payload.challenge.requirements.operator as `0x${string}`,
194
+ serviceRef: payload.challenge.requirements.serviceRef as `0x${string}`,
195
+ budgetUsdc: payload.challenge.requirements.maxBudgetUsdc,
196
+ ratePerSecondUsdc: payload.challenge.requirements.ratePerSecondUsdc,
197
+ maxDurationSeconds: payload.challenge.requirements.maxDurationSeconds,
198
+ signedMandate: payload.signedMandate,
199
+ spentSoFarUsdc,
200
+ nowSeconds: this.nowSeconds(),
201
+ revokedMandateIds,
202
+ });
203
+
204
+ return { streamId: result.streamId };
205
+ }
206
+
207
+ async proveConsumedHttpsResponse(
208
+ input: X402ConsumedHttpsResponseProofInput,
209
+ ): Promise<VerifiedConsumedHttpsResponseProof> {
210
+ if (this.deliveryProofs === undefined) {
211
+ throw new DeliveryProofUnavailableError(
212
+ "zkTLS delivery proofs are not configured on this x402 facilitator",
213
+ );
214
+ }
215
+
216
+ return await this.deliveryProofs.proveConsumedHttpsResponse({
217
+ url: input.url,
218
+ ...(input.method === undefined ? {} : { method: input.method }),
219
+ ...(input.headers === undefined ? {} : { headers: input.headers }),
220
+ ...(input.body === undefined ? {} : { body: input.body }),
221
+ ...(input.secretHeaders === undefined
222
+ ? {}
223
+ : { secretHeaders: input.secretHeaders }),
224
+ responseMatches: input.responseMatches,
225
+ ...(input.responseRedactions === undefined
226
+ ? {}
227
+ : { responseRedactions: input.responseRedactions }),
228
+ ...(input.cookie === undefined ? {} : { cookie: input.cookie }),
229
+ ...(input.secretParamValues === undefined
230
+ ? {}
231
+ : { secretParamValues: input.secretParamValues }),
232
+ ...(input.geoLocation === undefined
233
+ ? {}
234
+ : { geoLocation: input.geoLocation }),
235
+ ...(input.useTee === undefined ? {} : { useTee: input.useTee }),
236
+ ...(input.zkEngine === undefined ? {} : { zkEngine: input.zkEngine }),
237
+ delivery: {
238
+ owner: input.signedMandate.owner as `0x${string}`,
239
+ mandateId: input.signedMandate.mandateId as `0x${string}`,
240
+ ...(input.streamId === undefined ? {} : { streamId: input.streamId }),
241
+ ...(input.operator === undefined ? {} : { operator: input.operator }),
242
+ ...(input.serviceRef === undefined
243
+ ? {}
244
+ : { serviceRef: input.serviceRef }),
245
+ },
246
+ });
247
+ }
248
+ }
249
+
250
+ export function encodeX402PayloadHeader(payload: X402OpenPayload): string {
251
+ const parsed = x402OpenPayloadSchema.parse(payload);
252
+ const token = Buffer.from(stringifyX402Payload(parsed)).toString("base64url");
253
+ return `${X402_SCHEME} ${token}`;
254
+ }
255
+
256
+ export function parseX402ChallengeJson(value: unknown): X402StreamChallenge {
257
+ const parsed = x402StreamChallengeSchema.safeParse(reviveBigInts(value));
258
+ if (!parsed.success) {
259
+ throw new X402PayloadError(
260
+ parsed.error.issues.map((issue) => issue.message).join("; "),
261
+ );
262
+ }
263
+ return parsed.data;
264
+ }
265
+
266
+ export function parseX402PayloadHeader(payloadHeader: string): X402OpenPayload {
267
+ const [scheme, token] = payloadHeader.split(" ", 2);
268
+ if (scheme !== X402_SCHEME || token === undefined || token.trim() === "") {
269
+ throw new X402PayloadError("invalid x402 verified-stream payload header");
270
+ }
271
+
272
+ let decoded: unknown;
273
+ try {
274
+ decoded = JSON.parse(Buffer.from(token, "base64url").toString("utf8"));
275
+ } catch (error) {
276
+ throw new X402PayloadError(
277
+ `invalid x402 verified-stream payload encoding: ${
278
+ error instanceof Error ? error.message : String(error)
279
+ }`,
280
+ );
281
+ }
282
+
283
+ const parsed = x402OpenPayloadSchema.safeParse(reviveBigInts(decoded));
284
+ if (!parsed.success) {
285
+ throw new X402PayloadError(
286
+ parsed.error.issues.map((issue) => issue.message).join("; "),
287
+ );
288
+ }
289
+ return parsed.data;
290
+ }
291
+
292
+ function defaultAgentClientFactory(
293
+ config: StreamProofClientConfig,
294
+ ): VerifiedStreamAgentOpener {
295
+ return new VerifiedStreamAgentClient(config);
296
+ }
297
+
298
+ function assertSettlementTarget(
299
+ requirements: VerifiedStreamRequirements,
300
+ sdkConfig: StreamProofClientConfig,
301
+ ): void {
302
+ if (requirements.chainId !== sdkConfig.chain.id) {
303
+ throw new SettlementTargetMismatchError(
304
+ `challenge chainId ${requirements.chainId} does not match configured chain ${sdkConfig.chain.id}`,
305
+ );
306
+ }
307
+ if (requirements.escrow.toLowerCase() !== sdkConfig.escrow.toLowerCase()) {
308
+ throw new SettlementTargetMismatchError(
309
+ `challenge escrow ${requirements.escrow} does not match configured escrow ${sdkConfig.escrow}`,
310
+ );
311
+ }
312
+ }
313
+
314
+ function stringifyX402Payload(payload: X402OpenPayload): string {
315
+ return JSON.stringify(payload, (_key, value) =>
316
+ typeof value === "bigint" ? `${value.toString()}n` : value,
317
+ );
318
+ }
319
+
320
+ function reviveBigInts(value: unknown): unknown {
321
+ if (Array.isArray(value)) {
322
+ return value.map((entry) => reviveBigInts(entry));
323
+ }
324
+
325
+ if (typeof value === "string" && /^\d+n$/.test(value)) {
326
+ return BigInt(value.slice(0, -1));
327
+ }
328
+
329
+ if (typeof value === "object" && value !== null) {
330
+ return Object.fromEntries(
331
+ Object.entries(value).map(([key, entry]) => [key, reviveBigInts(entry)]),
332
+ );
333
+ }
334
+
335
+ return value;
336
+ }