@absol-labs/agent 0.7.3 → 0.9.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 (80) hide show
  1. package/README.md +19 -4
  2. package/dist/discovery/registry.d.ts +110 -305
  3. package/dist/discovery/registry.d.ts.map +1 -1
  4. package/dist/discovery/registry.js +141 -318
  5. package/dist/discovery/registry.js.map +1 -1
  6. package/dist/frameworks/agentkit.d.ts.map +1 -1
  7. package/dist/frameworks/agentkit.js +23 -6
  8. package/dist/frameworks/agentkit.js.map +1 -1
  9. package/dist/gateway/caller-auth-gateway.d.ts +103 -2
  10. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  11. package/dist/gateway/caller-auth-gateway.js +176 -19
  12. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  13. package/dist/gateway/http-server.d.ts +12 -0
  14. package/dist/gateway/http-server.d.ts.map +1 -1
  15. package/dist/gateway/http-server.js +45 -1
  16. package/dist/gateway/http-server.js.map +1 -1
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/wallet/autonomous-wallet-store.d.ts +123 -0
  22. package/dist/wallet/autonomous-wallet-store.d.ts.map +1 -0
  23. package/dist/wallet/autonomous-wallet-store.js +318 -0
  24. package/dist/wallet/autonomous-wallet-store.js.map +1 -0
  25. package/dist/wallet/autonomous-wallet.d.ts +14 -39
  26. package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
  27. package/dist/wallet/autonomous-wallet.js +12 -145
  28. package/dist/wallet/autonomous-wallet.js.map +1 -1
  29. package/dist/wallet/cdp-sdk.d.ts +23 -0
  30. package/dist/wallet/cdp-sdk.d.ts.map +1 -0
  31. package/dist/wallet/cdp-sdk.js +27 -0
  32. package/dist/wallet/cdp-sdk.js.map +1 -0
  33. package/dist/wallet/encrypted-file-credential-store.d.ts +41 -0
  34. package/dist/wallet/encrypted-file-credential-store.d.ts.map +1 -0
  35. package/dist/wallet/encrypted-file-credential-store.js +221 -0
  36. package/dist/wallet/encrypted-file-credential-store.js.map +1 -0
  37. package/dist/wallet/provider.d.ts +1 -1
  38. package/dist/wallet/provider.d.ts.map +1 -1
  39. package/dist/wallet/provider.js +8 -3
  40. package/dist/wallet/provider.js.map +1 -1
  41. package/dist/wallet/secret-service-probe.d.ts +56 -0
  42. package/dist/wallet/secret-service-probe.d.ts.map +1 -0
  43. package/dist/wallet/secret-service-probe.js +407 -0
  44. package/dist/wallet/secret-service-probe.js.map +1 -0
  45. package/dist/zktls/reclaim-js-sdk.d.ts +24 -0
  46. package/dist/zktls/reclaim-js-sdk.d.ts.map +1 -0
  47. package/dist/zktls/reclaim-js-sdk.js +29 -0
  48. package/dist/zktls/reclaim-js-sdk.js.map +1 -0
  49. package/dist/zktls/reclaim.d.ts +14 -2
  50. package/dist/zktls/reclaim.d.ts.map +1 -1
  51. package/dist/zktls/reclaim.js +29 -6
  52. package/dist/zktls/reclaim.js.map +1 -1
  53. package/dist/zktls/t2-delivery-proof.d.ts +8 -1
  54. package/dist/zktls/t2-delivery-proof.d.ts.map +1 -1
  55. package/dist/zktls/t2-delivery-proof.js +22 -6
  56. package/dist/zktls/t2-delivery-proof.js.map +1 -1
  57. package/docs/agent-layer.md +150 -0
  58. package/docs/autonomous-privy-wallet.md +133 -0
  59. package/docs/crewai.md +70 -0
  60. package/docs/eliza.md +109 -0
  61. package/docs/langchain.md +63 -0
  62. package/docs/mcp-hosted.md +137 -0
  63. package/docs/privy-embedded-wallet.md +102 -0
  64. package/docs/quickstart.md +370 -0
  65. package/docs/threat-model.md +160 -0
  66. package/package.json +19 -6
  67. package/src/discovery/registry.ts +242 -414
  68. package/src/frameworks/agentkit.ts +24 -5
  69. package/src/gateway/caller-auth-gateway.ts +281 -15
  70. package/src/gateway/http-server.ts +64 -0
  71. package/src/index.ts +24 -0
  72. package/src/wallet/autonomous-wallet-store.ts +487 -0
  73. package/src/wallet/autonomous-wallet.ts +57 -224
  74. package/src/wallet/cdp-sdk.ts +33 -0
  75. package/src/wallet/encrypted-file-credential-store.ts +341 -0
  76. package/src/wallet/provider.ts +16 -9
  77. package/src/wallet/secret-service-probe.ts +487 -0
  78. package/src/zktls/reclaim-js-sdk.ts +50 -0
  79. package/src/zktls/reclaim.ts +57 -23
  80. package/src/zktls/t2-delivery-proof.ts +28 -10
@@ -1,5 +1,3 @@
1
- import { createPrivateKey, createPublicKey } from "node:crypto";
2
-
3
1
  import {
4
2
  generateAuthorizationSignature,
5
3
  generateP256KeyPair,
@@ -19,6 +17,16 @@ import {
19
17
  type AutonomousWalletProof,
20
18
  type PreparedPrivyRequest,
21
19
  } from "./autonomous-wallet-protocol.js";
20
+ import {
21
+ AutonomousWalletError,
22
+ assertDurableCredentialStore,
23
+ createDefaultAutonomousWalletStore,
24
+ decodeBase64,
25
+ isRecord,
26
+ validateStoredRecord,
27
+ type AutonomousWalletCredentialStore,
28
+ type AutonomousWalletRecord,
29
+ } from "./autonomous-wallet-store.js";
22
30
 
23
31
  export {
24
32
  AUTONOMOUS_WALLET_CAIP2,
@@ -29,44 +37,39 @@ export {
29
37
  type AutonomousWalletProof,
30
38
  type PreparedPrivyRequest,
31
39
  } from "./autonomous-wallet-protocol.js";
32
- const KEYCHAIN_SERVICE = "com.absol-labs.metrik.autonomous-wallet";
33
- export const METRIK_AUTONOMOUS_WALLET_BROKER_URL =
34
- "https://wallet.137.23.50.249.sslip.io";
35
40
 
36
- export interface AutonomousWalletRecord {
37
- readonly version: typeof AUTONOMOUS_WALLET_VERSION;
38
- readonly appId: string;
39
- readonly brokerUrl: string;
40
- readonly publicKey: string;
41
- /** Base64 PKCS8 P-256 key. This field must only be stored in a secure store. */
42
- readonly privateKey: string;
43
- readonly provisioningNonce: string;
44
- readonly walletId?: string;
45
- readonly address?: Address;
46
- readonly policyId?: string;
47
- readonly createdAt: number;
48
- }
41
+ export {
42
+ AUTONOMOUS_WALLET_KEYCHAIN_SERVICE,
43
+ AutonomousWalletError,
44
+ InMemoryAutonomousWalletStore,
45
+ OsCredentialStore,
46
+ assertDurableCredentialStore,
47
+ createDefaultAutonomousWalletStore,
48
+ type AssertDurableCredentialStoreOptions,
49
+ type AutonomousWalletCredentialStore,
50
+ type AutonomousWalletRecord,
51
+ type CredentialStoreDurability,
52
+ type CredentialStoreDurabilityReport,
53
+ type OsCredentialStoreOptions,
54
+ type SecretEntryFactory,
55
+ type SecretEntryLike,
56
+ } from "./autonomous-wallet-store.js";
49
57
 
50
- export interface AutonomousWalletCredentialStore {
51
- load(key: string): Promise<AutonomousWalletRecord | null>;
52
- save(key: string, record: AutonomousWalletRecord): Promise<void>;
53
- }
58
+ export {
59
+ EncryptedFileCredentialStore,
60
+ METRIK_WALLET_ENCRYPTION_KEY_ENV,
61
+ METRIK_WALLET_STORE_DIR_ENV,
62
+ type EncryptedFileCredentialStoreOptions,
63
+ } from "./encrypted-file-credential-store.js";
54
64
 
55
- export class AutonomousWalletError extends Error {
56
- constructor(
57
- readonly code:
58
- | "invalid-config"
59
- | "store-failure"
60
- | "broker-failure"
61
- | "proof-failure"
62
- | "invalid-response",
63
- message: string,
64
- options?: { readonly cause?: unknown },
65
- ) {
66
- super(message, options);
67
- this.name = "AutonomousWalletError";
68
- }
69
- }
65
+ export {
66
+ probeSecretServiceAvailable,
67
+ type ProbeSecretServiceOptions,
68
+ type SecretServiceProbeResult,
69
+ } from "./secret-service-probe.js";
70
+
71
+ export const METRIK_AUTONOMOUS_WALLET_BROKER_URL =
72
+ "https://wallet.137.23.50.249.sslip.io";
70
73
 
71
74
  /**
72
75
  * Wire adapter for the broker HTTP contract. The only credential sent by this
@@ -166,6 +169,13 @@ export interface ProvisionAutonomousWalletOptions {
166
169
  readonly store?: AutonomousWalletCredentialStore;
167
170
  readonly nowSeconds?: number;
168
171
  readonly nonce?: string;
172
+ /**
173
+ * Opt in to a credential store that does NOT survive a host reboot (process
174
+ * memory, the Linux kernel keyring). Off by default: provisioning refuses a
175
+ * volatile store because the owner key — and therefore any funds the wallet
176
+ * holds — is lost on reboot. Only set this for genuinely ephemeral runs.
177
+ */
178
+ readonly allowVolatileStore?: boolean;
169
179
  }
170
180
 
171
181
  export interface ProvisionMetrikAutonomousWalletOptions {
@@ -173,6 +183,8 @@ export interface ProvisionMetrikAutonomousWalletOptions {
173
183
  readonly brokerUrl?: string;
174
184
  readonly store?: AutonomousWalletCredentialStore;
175
185
  readonly fetchImpl?: typeof fetch;
186
+ /** See {@link ProvisionAutonomousWalletOptions.allowVolatileStore}. */
187
+ readonly allowVolatileStore?: boolean;
176
188
  }
177
189
 
178
190
  /**
@@ -223,6 +235,9 @@ export async function provisionMetrikAutonomousWallet(
223
235
  storeKey: options.storeKey,
224
236
  broker,
225
237
  ...(options.store === undefined ? {} : { store: options.store }),
238
+ ...(options.allowVolatileStore === undefined
239
+ ? {}
240
+ : { allowVolatileStore: options.allowVolatileStore }),
226
241
  });
227
242
  }
228
243
 
@@ -237,6 +252,11 @@ export async function provisionAutonomousWallet(
237
252
  ): Promise<AutonomousWalletRecord> {
238
253
  validateProvisionOptions(options);
239
254
  const store = options.store ?? createDefaultAutonomousWalletStore();
255
+ // Fail closed BEFORE a key is generated or a stored key is handed back: a
256
+ // volatile backend silently loses the owner key (and any funds) on reboot.
257
+ await assertDurableCredentialStore(store, {
258
+ allowVolatileStore: options.allowVolatileStore === true,
259
+ });
240
260
  const existingRaw = await loadRecord(store, options.storeKey);
241
261
  if (existingRaw !== null) {
242
262
  const existing = validateStoredRecord(existingRaw);
@@ -461,72 +481,6 @@ export async function createAutonomousWalletAccount(
461
481
  return createPrivyEmbeddedAccount(config);
462
482
  }
463
483
 
464
- export class InMemoryAutonomousWalletStore implements AutonomousWalletCredentialStore {
465
- private readonly records = new Map<string, AutonomousWalletRecord>();
466
-
467
- async load(key: string): Promise<AutonomousWalletRecord | null> {
468
- return this.records.get(key) ?? null;
469
- }
470
-
471
- async save(key: string, record: AutonomousWalletRecord): Promise<void> {
472
- this.records.set(key, record);
473
- }
474
- }
475
-
476
- /**
477
- * Uses the host OS credential manager. There is intentionally no plaintext
478
- * file fallback: unsupported hosts receive an actionable error instead.
479
- */
480
- export class OsCredentialStore implements AutonomousWalletCredentialStore {
481
- async load(key: string): Promise<AutonomousWalletRecord | null> {
482
- const raw = await this.readSecret(key);
483
- if (raw === null) return null;
484
- try {
485
- return validateStoredRecord(JSON.parse(raw));
486
- } catch (error) {
487
- throw new AutonomousWalletError(
488
- "store-failure",
489
- "OS credential contains invalid wallet data",
490
- { cause: error },
491
- );
492
- }
493
- }
494
-
495
- async save(key: string, record: AutonomousWalletRecord): Promise<void> {
496
- const raw = JSON.stringify(record);
497
- try {
498
- const { AsyncEntry } = await import("@napi-rs/keyring");
499
- await new AsyncEntry(KEYCHAIN_SERVICE, key).setPassword(raw);
500
- return;
501
- } catch (error) {
502
- throw new AutonomousWalletError(
503
- "store-failure",
504
- "OS credential store rejected the autonomous wallet record; no plaintext fallback is allowed",
505
- { cause: error },
506
- );
507
- }
508
- }
509
-
510
- private async readSecret(key: string): Promise<string | null> {
511
- try {
512
- const { AsyncEntry } = await import("@napi-rs/keyring");
513
- return (
514
- (await new AsyncEntry(KEYCHAIN_SERVICE, key).getPassword()) ?? null
515
- );
516
- } catch (error) {
517
- throw new AutonomousWalletError(
518
- "store-failure",
519
- "OS credential store could not read the autonomous wallet record",
520
- { cause: error },
521
- );
522
- }
523
- }
524
- }
525
-
526
- export function createDefaultAutonomousWalletStore(): AutonomousWalletCredentialStore {
527
- return new OsCredentialStore();
528
- }
529
-
530
484
  async function loadRecord(
531
485
  store: AutonomousWalletCredentialStore,
532
486
  key: string,
@@ -612,80 +566,6 @@ function validateExistingRecord(
612
566
  }
613
567
  }
614
568
 
615
- function validateStoredRecord(value: unknown): AutonomousWalletRecord {
616
- if (
617
- !isRecord(value) ||
618
- value.version !== AUTONOMOUS_WALLET_VERSION ||
619
- typeof value.appId !== "string" ||
620
- value.appId.trim() === "" ||
621
- typeof value.brokerUrl !== "string" ||
622
- typeof value.publicKey !== "string" ||
623
- value.publicKey.trim() === "" ||
624
- typeof value.privateKey !== "string" ||
625
- value.privateKey.trim() === "" ||
626
- typeof value.provisioningNonce !== "string" ||
627
- value.provisioningNonce.trim() === "" ||
628
- typeof value.createdAt !== "number" ||
629
- !Number.isSafeInteger(value.createdAt)
630
- ) {
631
- throw new AutonomousWalletError(
632
- "store-failure",
633
- "OS credential contains an invalid autonomous wallet record",
634
- );
635
- }
636
- if (
637
- value.walletId !== undefined &&
638
- (typeof value.walletId !== "string" || value.walletId.trim() === "")
639
- ) {
640
- throw new AutonomousWalletError(
641
- "store-failure",
642
- "OS credential contains an invalid wallet id",
643
- );
644
- }
645
- if (
646
- value.policyId !== undefined &&
647
- (typeof value.policyId !== "string" || value.policyId.trim() === "")
648
- ) {
649
- throw new AutonomousWalletError(
650
- "store-failure",
651
- "OS credential contains an invalid policy id",
652
- );
653
- }
654
- if (
655
- value.address !== undefined &&
656
- (typeof value.address !== "string" ||
657
- !/^0x[0-9a-fA-F]{40}$/.test(value.address))
658
- ) {
659
- throw new AutonomousWalletError(
660
- "store-failure",
661
- "OS credential contains an invalid wallet address",
662
- );
663
- }
664
- try {
665
- validateP256KeyPair(value.publicKey, value.privateKey);
666
- } catch (error) {
667
- throw new AutonomousWalletError(
668
- "store-failure",
669
- "OS credential contains invalid P-256 key material",
670
- { cause: error },
671
- );
672
- }
673
- return {
674
- version: AUTONOMOUS_WALLET_VERSION,
675
- appId: value.appId,
676
- brokerUrl: value.brokerUrl,
677
- publicKey: value.publicKey,
678
- privateKey: value.privateKey,
679
- provisioningNonce: value.provisioningNonce,
680
- ...(value.walletId === undefined ? {} : { walletId: value.walletId }),
681
- ...(value.address === undefined
682
- ? {}
683
- : { address: getAddress(value.address) }),
684
- ...(value.policyId === undefined ? {} : { policyId: value.policyId }),
685
- createdAt: value.createdAt,
686
- };
687
- }
688
-
689
569
  function normalizeBrokerUrl(value: string): string {
690
570
  const url = new URL(value);
691
571
  url.search = "";
@@ -699,49 +579,6 @@ function cryptoRandomNonce(): string {
699
579
  return Buffer.from(bytes).toString("base64url");
700
580
  }
701
581
 
702
- function decodeBase64(value: string): Uint8Array {
703
- if (!/^[A-Za-z0-9+/]+={0,2}$/.test(value) || value.length % 4 === 1) {
704
- throw new AutonomousWalletError(
705
- "invalid-response",
706
- "broker returned invalid proof payload encoding",
707
- );
708
- }
709
- const decoded = Buffer.from(value, "base64");
710
- if (decoded.length === 0 || decoded.toString("base64") !== value) {
711
- throw new AutonomousWalletError(
712
- "invalid-response",
713
- "broker returned an empty proof payload",
714
- );
715
- }
716
- return new Uint8Array(decoded);
717
- }
718
-
719
- function validateP256KeyPair(publicKey: string, privateKey: string): void {
720
- const publicObject = createPublicKey({
721
- key: Buffer.from(decodeBase64(publicKey)),
722
- format: "der",
723
- type: "spki",
724
- });
725
- const privateObject = createPrivateKey({
726
- key: Buffer.from(decodeBase64(privateKey)),
727
- format: "der",
728
- type: "pkcs8",
729
- });
730
- if (
731
- publicObject.asymmetricKeyType !== "ec" ||
732
- publicObject.asymmetricKeyDetails?.namedCurve !== "prime256v1" ||
733
- privateObject.asymmetricKeyType !== "ec" ||
734
- privateObject.asymmetricKeyDetails?.namedCurve !== "prime256v1"
735
- ) {
736
- throw new Error("key material is not P-256");
737
- }
738
- const derived = createPublicKey(privateObject)
739
- .export({ format: "der", type: "spki" })
740
- .toString("base64");
741
- if (derived !== publicKey)
742
- throw new Error("public key does not match private key");
743
- }
744
-
745
582
  function validateProvisionResponse(value: unknown): {
746
583
  readonly walletId: string;
747
584
  readonly address: Address;
@@ -804,10 +641,6 @@ function validatePreparedResponse(value: unknown): PreparedPrivyRequest {
804
641
  };
805
642
  }
806
643
 
807
- function isRecord(value: unknown): value is Record<string, unknown> {
808
- return typeof value === "object" && value !== null && !Array.isArray(value);
809
- }
810
-
811
644
  function bigintJson(_key: string, value: unknown): unknown {
812
645
  return typeof value === "bigint" ? `0x${value.toString(16)}` : value;
813
646
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `@coinbase/cdp-sdk` is an OPTIONAL peer dependency: only consumers that use the
3
+ * Coinbase CDP wallet path need it, and it carries a very large transitive graph
4
+ * (it was the main contributor to the 18 -> ~515 package jump a consumer saw just
5
+ * for hiring and invoking a service). The top-level "@absol-labs/agent" barrel
6
+ * DOES reach `./provider.ts`, so that module must import the SDK's TYPES only
7
+ * (`import type`, erased at compile time) and load the runtime module lazily
8
+ * through this loader at the point of first use.
9
+ *
10
+ * This is the same contract as `../zktls/reclaim-js-sdk.ts`, and it is enforced
11
+ * by the barrel-reachability guard in `test/flat-install.test.ts`: a static value
12
+ * import of an optional peer from any barrel-reachable module fails that test.
13
+ *
14
+ * Deliberately NOT a top-level `await import(...)` (the pattern used by
15
+ * `../frameworks/agentkit.ts`): those modules are not barrel-reachable, this one
16
+ * is, and a top-level await would re-introduce the hard dependency at
17
+ * barrel-import time — precisely the regression that issue #79 was filed for.
18
+ */
19
+
20
+ type CdpSdkModule = typeof import("@coinbase/cdp-sdk");
21
+
22
+ let modulePromise: Promise<CdpSdkModule> | undefined;
23
+
24
+ /** Memoized lazy load with an actionable missing-peer error. */
25
+ export async function loadCdpSdk(): Promise<CdpSdkModule> {
26
+ modulePromise ??= import("@coinbase/cdp-sdk").catch((error: unknown) => {
27
+ throw new Error(
28
+ "@absol-labs/agent CDP wallet support requires the optional peer dependency '@coinbase/cdp-sdk'. Install it with `npm install @coinbase/cdp-sdk`, or use a different wallet mode (the autonomous Privy wallet and an injected account both work without it).",
29
+ { cause: error },
30
+ );
31
+ });
32
+ return await modulePromise;
33
+ }