@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,8 @@
1
+ import { startVerifiedStreamMcpServerStdio } from "./server.js";
2
+
3
+ startVerifiedStreamMcpServerStdio().catch((error) => {
4
+ console.error(
5
+ error instanceof Error ? error.message : "failed to start MCP server",
6
+ );
7
+ process.exit(1);
8
+ });
@@ -0,0 +1,222 @@
1
+ import {
2
+ StreamProofClient,
3
+ type HireComputeResult,
4
+ type StreamProofClientConfig,
5
+ type StreamProofStream,
6
+ } from "@absol-labs/sdk";
7
+
8
+ import {
9
+ checkMandate,
10
+ verifyMandateOwnerSignature,
11
+ type HireRequest,
12
+ type MandateDecision,
13
+ type SignedSpendMandate,
14
+ } from "../mandates/mandate.js";
15
+
16
+ export interface OpenVerifiedStreamInput {
17
+ readonly operator: `0x${string}`;
18
+ readonly serviceRef: `0x${string}`;
19
+ readonly budgetUsdc: bigint;
20
+ readonly ratePerSecondUsdc: bigint;
21
+ readonly maxDurationSeconds: number;
22
+ readonly signedMandate: SignedSpendMandate;
23
+ readonly spentSoFarUsdc: bigint;
24
+ readonly nowSeconds: number;
25
+ readonly revokedMandateIds?: Iterable<`0x${string}`>;
26
+ }
27
+
28
+ export interface StreamStatusView {
29
+ readonly stream: StreamProofStream;
30
+ readonly claimable: bigint;
31
+ readonly reclaimable: bigint;
32
+ }
33
+
34
+ export interface ReclaimVerifiedStreamOptions {
35
+ readonly closeFirst?: boolean;
36
+ }
37
+
38
+ export interface ReclaimVerifiedStreamResult {
39
+ readonly closeResult: StreamProofTransactionResult | null;
40
+ readonly reclaimResult: StreamProofTransactionResult;
41
+ }
42
+
43
+ export type StreamProofTransactionResult = Awaited<
44
+ ReturnType<StreamProofClient["claim"]>
45
+ >;
46
+
47
+ export interface MandateAuthorizedStreamActionInput {
48
+ readonly streamId: `0x${string}`;
49
+ readonly signedMandate: SignedSpendMandate;
50
+ readonly spentSoFarUsdc: bigint;
51
+ readonly nowSeconds: number;
52
+ readonly revokedMandateIds?: Iterable<`0x${string}`>;
53
+ }
54
+
55
+ export interface ReclaimAuthorizedStreamInput
56
+ extends MandateAuthorizedStreamActionInput, ReclaimVerifiedStreamOptions {}
57
+
58
+ export interface AgentSdkClient {
59
+ hireAkashCompute(input: {
60
+ readonly operator: `0x${string}`;
61
+ readonly serviceRef: `0x${string}`;
62
+ readonly budgetUsdc: bigint;
63
+ readonly ratePerSecond: bigint;
64
+ readonly maxDurationSeconds: number;
65
+ }): Promise<HireComputeResult>;
66
+ getStream(streamId: `0x${string}`): Promise<StreamProofStream>;
67
+ claimable(streamId: `0x${string}`): Promise<bigint>;
68
+ reclaimable(streamId: `0x${string}`): Promise<bigint>;
69
+ claim(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
70
+ close(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
71
+ reclaim(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
72
+ }
73
+
74
+ export type AgentSdkClientFactory = (
75
+ config: StreamProofClientConfig,
76
+ ) => AgentSdkClient;
77
+
78
+ export interface VerifiedStreamAgentOpener {
79
+ openVerifiedStream(
80
+ input: OpenVerifiedStreamInput,
81
+ ): Promise<HireComputeResult>;
82
+ }
83
+
84
+ export class MandateDeniedError extends Error {
85
+ readonly reason: NonNullable<MandateDecision["reason"]>;
86
+
87
+ constructor(reason: NonNullable<MandateDecision["reason"]>) {
88
+ super(`mandate denied: ${reason}`);
89
+ this.name = "MandateDeniedError";
90
+ this.reason = reason;
91
+ }
92
+ }
93
+
94
+ export class VerifiedStreamAgentClient implements VerifiedStreamAgentOpener {
95
+ private readonly sdkClient: AgentSdkClient;
96
+
97
+ constructor(
98
+ config: StreamProofClientConfig,
99
+ options: { readonly createSdkClient?: AgentSdkClientFactory } = {},
100
+ ) {
101
+ this.sdkClient = (options.createSdkClient ?? defaultSdkClientFactory)(
102
+ config,
103
+ );
104
+ }
105
+
106
+ async openVerifiedStream(
107
+ input: OpenVerifiedStreamInput,
108
+ ): Promise<HireComputeResult> {
109
+ const decision = await checkMandate(
110
+ input.signedMandate,
111
+ toHireRequest(input),
112
+ input.spentSoFarUsdc,
113
+ {
114
+ nowSeconds: input.nowSeconds,
115
+ ...(input.revokedMandateIds === undefined
116
+ ? {}
117
+ : { revokedMandateIds: input.revokedMandateIds }),
118
+ },
119
+ );
120
+ if (!decision.allowed) {
121
+ throw new MandateDeniedError(decision.reason ?? "mandate-expired");
122
+ }
123
+
124
+ return await this.sdkClient.hireAkashCompute({
125
+ operator: input.operator,
126
+ serviceRef: input.serviceRef,
127
+ budgetUsdc: input.budgetUsdc,
128
+ ratePerSecond: input.ratePerSecondUsdc,
129
+ maxDurationSeconds: input.maxDurationSeconds,
130
+ });
131
+ }
132
+
133
+ async getStreamStatus(streamId: `0x${string}`): Promise<StreamStatusView> {
134
+ const [stream, claimable, reclaimable] = await Promise.all([
135
+ this.sdkClient.getStream(streamId),
136
+ this.sdkClient.claimable(streamId),
137
+ this.sdkClient.reclaimable(streamId),
138
+ ]);
139
+
140
+ return { stream, claimable, reclaimable };
141
+ }
142
+
143
+ async claimStream(
144
+ input: MandateAuthorizedStreamActionInput,
145
+ ): Promise<StreamProofTransactionResult> {
146
+ await this.authorizeExistingStreamAction(input);
147
+ return await this.sdkClient.claim(input.streamId);
148
+ }
149
+
150
+ async closeStream(
151
+ input: MandateAuthorizedStreamActionInput,
152
+ ): Promise<StreamProofTransactionResult> {
153
+ await this.authorizeBuyerRecovery(input);
154
+ return await this.sdkClient.close(input.streamId);
155
+ }
156
+
157
+ async reclaimStream(
158
+ input: ReclaimAuthorizedStreamInput,
159
+ ): Promise<ReclaimVerifiedStreamResult> {
160
+ await this.authorizeBuyerRecovery(input);
161
+ const closeResult = input.closeFirst
162
+ ? await this.sdkClient.close(input.streamId)
163
+ : null;
164
+ const reclaimResult = await this.sdkClient.reclaim(input.streamId);
165
+ return { closeResult, reclaimResult };
166
+ }
167
+
168
+ /**
169
+ * Authorizes a BUYER-RECOVERY action (close / reclaim). These only return
170
+ * unspent funds to the buyer or stop payment, so they are authorized on
171
+ * mandate-owner signature ALONE — never gated by expiry, revocation, or caps,
172
+ * which would otherwise let a lapsed mandate strand the buyer's own funds.
173
+ */
174
+ private async authorizeBuyerRecovery(
175
+ input: MandateAuthorizedStreamActionInput,
176
+ ): Promise<void> {
177
+ const decision = await verifyMandateOwnerSignature(input.signedMandate);
178
+ if (!decision.allowed) {
179
+ throw new MandateDeniedError(decision.reason ?? "invalid-signature");
180
+ }
181
+ }
182
+
183
+ private async authorizeExistingStreamAction(
184
+ input: MandateAuthorizedStreamActionInput,
185
+ ): Promise<void> {
186
+ const stream = await this.sdkClient.getStream(input.streamId);
187
+ const decision = await checkMandate(
188
+ input.signedMandate,
189
+ {
190
+ operator: stream.operator as `0x${string}`,
191
+ budgetUsdc: 0n,
192
+ ratePerSecondUsdc: 0n,
193
+ maxDurationSeconds: 0,
194
+ },
195
+ input.spentSoFarUsdc,
196
+ {
197
+ nowSeconds: input.nowSeconds,
198
+ ...(input.revokedMandateIds === undefined
199
+ ? {}
200
+ : { revokedMandateIds: input.revokedMandateIds }),
201
+ },
202
+ );
203
+ if (!decision.allowed) {
204
+ throw new MandateDeniedError(decision.reason ?? "mandate-expired");
205
+ }
206
+ }
207
+ }
208
+
209
+ function defaultSdkClientFactory(
210
+ config: StreamProofClientConfig,
211
+ ): AgentSdkClient {
212
+ return new StreamProofClient(config);
213
+ }
214
+
215
+ function toHireRequest(input: OpenVerifiedStreamInput): HireRequest {
216
+ return {
217
+ operator: input.operator,
218
+ budgetUsdc: input.budgetUsdc,
219
+ ratePerSecondUsdc: input.ratePerSecondUsdc,
220
+ maxDurationSeconds: input.maxDurationSeconds,
221
+ };
222
+ }
@@ -0,0 +1,197 @@
1
+ import { type StreamProofClientConfig } from "@absol-labs/sdk";
2
+ import {
3
+ CdpClient,
4
+ type EvmServerAccount,
5
+ type EvmSmartAccount,
6
+ } from "@coinbase/cdp-sdk";
7
+ import type { Account } from "viem";
8
+ import { privateKeyToAccount, toAccount } from "viem/accounts";
9
+ import { z } from "zod";
10
+
11
+ import {
12
+ VerifiedStreamAgentClient,
13
+ type AgentSdkClientFactory,
14
+ } from "../sdk/client.js";
15
+
16
+ const privateKeySchema = z
17
+ .string()
18
+ .regex(/^0x[0-9a-fA-F]{64}$/, "must be a 32-byte private key");
19
+ const booleanStringSchema = z
20
+ .enum(["true", "false", "1", "0"])
21
+ .transform((value) => value === "true" || value === "1");
22
+
23
+ const cdpWalletEnvSchema = z.object({
24
+ CDP_API_KEY_ID: z.string().min(1, "CDP_API_KEY_ID is required"),
25
+ CDP_API_KEY_SECRET: z.string().min(1, "CDP_API_KEY_SECRET is required"),
26
+ CDP_WALLET_SECRET: z.string().min(1, "CDP_WALLET_SECRET is required"),
27
+ METRIK_AGENT_CDP_OWNER_NAME: z
28
+ .string()
29
+ .min(1, "METRIK_AGENT_CDP_OWNER_NAME is required"),
30
+ METRIK_AGENT_CDP_SMART_ACCOUNT_NAME: z.string().optional(),
31
+ METRIK_AGENT_CDP_CREATE_SMART_ACCOUNT: booleanStringSchema.optional(),
32
+ });
33
+
34
+ export class AgentWalletConfigError extends Error {
35
+ constructor(message: string) {
36
+ super(message);
37
+ this.name = "AgentWalletConfigError";
38
+ }
39
+ }
40
+
41
+ export interface CdpWalletConfig {
42
+ readonly apiKeyId?: string;
43
+ readonly apiKeySecret?: string;
44
+ readonly walletSecret?: string;
45
+ readonly ownerName: string;
46
+ readonly smartAccountName?: string;
47
+ readonly createSmartAccount?: boolean;
48
+ }
49
+
50
+ export type AgentWalletInput =
51
+ | {
52
+ readonly injectedAccount: Account;
53
+ }
54
+ | {
55
+ readonly cdp: CdpWalletConfig;
56
+ };
57
+
58
+ export interface ResolvedAgentWallet {
59
+ readonly source: "injected" | "cdp";
60
+ readonly account: Account;
61
+ readonly cdpOwner?: EvmServerAccount;
62
+ readonly smartAccount?: EvmSmartAccount;
63
+ }
64
+
65
+ export interface CdpClientLike {
66
+ readonly evm: {
67
+ getOrCreateAccount(options: {
68
+ readonly name: string;
69
+ }): Promise<EvmServerAccount>;
70
+ getOrCreateSmartAccount(options: {
71
+ readonly name: string;
72
+ readonly owner: EvmServerAccount;
73
+ }): Promise<EvmSmartAccount>;
74
+ };
75
+ }
76
+
77
+ export interface ResolveAgentWalletOptions {
78
+ readonly createCdpClient?: (config: CdpWalletConfig) => CdpClientLike;
79
+ }
80
+
81
+ export interface CreateWalletBackedAgentClientOptions extends ResolveAgentWalletOptions {
82
+ readonly createSdkClient?: AgentSdkClientFactory;
83
+ }
84
+
85
+ export interface WalletBackedAgentClient {
86
+ readonly wallet: ResolvedAgentWallet;
87
+ readonly agentClient: VerifiedStreamAgentClient;
88
+ }
89
+
90
+ export async function resolveAgentWallet(
91
+ input: AgentWalletInput,
92
+ options: ResolveAgentWalletOptions = {},
93
+ ): Promise<ResolvedAgentWallet> {
94
+ if ("injectedAccount" in input) {
95
+ return {
96
+ source: "injected",
97
+ account: input.injectedAccount,
98
+ };
99
+ }
100
+
101
+ const cdpClient = (options.createCdpClient ?? defaultCdpClientFactory)(
102
+ input.cdp,
103
+ );
104
+ const owner = await cdpClient.evm.getOrCreateAccount({
105
+ name: input.cdp.ownerName,
106
+ });
107
+ const smartAccount = input.cdp.createSmartAccount
108
+ ? await cdpClient.evm.getOrCreateSmartAccount({
109
+ name: input.cdp.smartAccountName ?? `${input.cdp.ownerName}-smart`,
110
+ owner,
111
+ })
112
+ : undefined;
113
+
114
+ return {
115
+ source: "cdp",
116
+ account: toAccount(owner),
117
+ cdpOwner: owner,
118
+ ...(smartAccount === undefined ? {} : { smartAccount }),
119
+ };
120
+ }
121
+
122
+ export async function createWalletBackedAgentClient(
123
+ sdkConfig: StreamProofClientConfig,
124
+ walletInput: AgentWalletInput,
125
+ options: CreateWalletBackedAgentClientOptions = {},
126
+ ): Promise<WalletBackedAgentClient> {
127
+ const wallet = await resolveAgentWallet(walletInput, options);
128
+ const agentClient = new VerifiedStreamAgentClient(
129
+ {
130
+ ...sdkConfig,
131
+ account: wallet.account,
132
+ },
133
+ {
134
+ ...(options.createSdkClient === undefined
135
+ ? {}
136
+ : { createSdkClient: options.createSdkClient }),
137
+ },
138
+ );
139
+
140
+ return { wallet, agentClient };
141
+ }
142
+
143
+ export function parseAgentWalletEnv(
144
+ env: NodeJS.ProcessEnv = process.env,
145
+ ): AgentWalletInput {
146
+ if (env.METRIK_AGENT_PRIVATE_KEY !== undefined) {
147
+ const privateKey = privateKeySchema.safeParse(env.METRIK_AGENT_PRIVATE_KEY);
148
+ if (!privateKey.success) {
149
+ throw new AgentWalletConfigError(
150
+ privateKey.error.issues.map((issue) => issue.message).join("; "),
151
+ );
152
+ }
153
+
154
+ return {
155
+ injectedAccount: privateKeyToAccount(privateKey.data as `0x${string}`),
156
+ };
157
+ }
158
+
159
+ const parsed = cdpWalletEnvSchema.safeParse(env);
160
+ if (!parsed.success) {
161
+ throw new AgentWalletConfigError(
162
+ parsed.error.issues.map((issue) => issue.message).join("; "),
163
+ );
164
+ }
165
+
166
+ return {
167
+ cdp: {
168
+ apiKeyId: parsed.data.CDP_API_KEY_ID,
169
+ apiKeySecret: parsed.data.CDP_API_KEY_SECRET,
170
+ walletSecret: parsed.data.CDP_WALLET_SECRET,
171
+ ownerName: parsed.data.METRIK_AGENT_CDP_OWNER_NAME,
172
+ ...(parsed.data.METRIK_AGENT_CDP_SMART_ACCOUNT_NAME === undefined
173
+ ? {}
174
+ : {
175
+ smartAccountName: parsed.data.METRIK_AGENT_CDP_SMART_ACCOUNT_NAME,
176
+ }),
177
+ ...(parsed.data.METRIK_AGENT_CDP_CREATE_SMART_ACCOUNT === undefined
178
+ ? {}
179
+ : {
180
+ createSmartAccount:
181
+ parsed.data.METRIK_AGENT_CDP_CREATE_SMART_ACCOUNT,
182
+ }),
183
+ },
184
+ };
185
+ }
186
+
187
+ function defaultCdpClientFactory(config: CdpWalletConfig): CdpClientLike {
188
+ return new CdpClient({
189
+ ...(config.apiKeyId === undefined ? {} : { apiKeyId: config.apiKeyId }),
190
+ ...(config.apiKeySecret === undefined
191
+ ? {}
192
+ : { apiKeySecret: config.apiKeySecret }),
193
+ ...(config.walletSecret === undefined
194
+ ? {}
195
+ : { walletSecret: config.walletSecret }),
196
+ });
197
+ }