@hol-org/rb-client 0.1.172 → 0.1.173

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.
package/dist/index.cjs CHANGED
@@ -57,11 +57,10 @@ __export(src_exports, {
57
57
  });
58
58
  module.exports = __toCommonJS(src_exports);
59
59
 
60
- // ../../src/services/registry-broker/client/encryption.ts
61
- var path = __toESM(require("path"), 1);
62
- var import_buffer = require("buffer");
63
- var import_crypto = require("crypto");
64
- var import_secp256k1 = require("@noble/curves/secp256k1.js");
60
+ // ../../src/services/registry-broker/client/base-client.ts
61
+ var import_buffer4 = require("buffer");
62
+ var import_secp256k12 = require("@noble/curves/secp256k1.js");
63
+ var import_zod3 = require("zod");
65
64
 
66
65
  // ../../src/services/registry-broker/schemas.ts
67
66
  var import_zod2 = require("zod");
@@ -1641,296 +1640,182 @@ var skillVerificationDomainProofVerifyResponseSchema = import_zod2.z.object({
1641
1640
  signal: skillVerificationDomainProofSignalSchema
1642
1641
  }).passthrough();
1643
1642
 
1644
- // ../../src/utils/is-browser.ts
1645
- var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
1646
-
1647
- // ../../src/utils/dynamic-import.ts
1648
- var nodeRequire;
1649
- function isModuleNotFound(specifier, error) {
1650
- if (!error || typeof error !== "object") {
1643
+ // ../../src/services/registry-broker/client/chat-history.ts
1644
+ var import_buffer = require("buffer");
1645
+ function identitiesMatch(a, b) {
1646
+ if (!a && !b) {
1647
+ return true;
1648
+ }
1649
+ if (!a || !b) {
1651
1650
  return false;
1652
1651
  }
1653
- const code = Reflect.get(error, "code");
1654
- const message = Reflect.get(error, "message");
1655
- const messageText = typeof message === "string" ? message : "";
1656
- if (typeof code === "string" && code.includes("MODULE_NOT_FOUND")) {
1657
- return messageText.includes(specifier);
1652
+ if (a.uaid && b.uaid && a.uaid.toLowerCase() === b.uaid.toLowerCase()) {
1653
+ return true;
1658
1654
  }
1659
- if (messageText) {
1660
- const lowered = messageText.toLowerCase();
1661
- if (lowered.includes("cannot find module") || lowered.includes("module not found") || lowered.includes("cannot find package")) {
1662
- return lowered.includes(specifier.toLowerCase());
1663
- }
1655
+ if (a.ledgerAccountId && b.ledgerAccountId && a.ledgerAccountId.toLowerCase() === b.ledgerAccountId.toLowerCase()) {
1656
+ return true;
1657
+ }
1658
+ if (a.userId && b.userId && a.userId === b.userId) {
1659
+ return true;
1660
+ }
1661
+ if (a.email && b.email && a.email.toLowerCase() === b.email.toLowerCase()) {
1662
+ return true;
1664
1663
  }
1665
1664
  return false;
1666
1665
  }
1667
- async function resolveNodeRequire() {
1668
- if (nodeRequire !== void 0) {
1669
- return nodeRequire;
1666
+ async function fetchHistorySnapshot(conversationContexts, client, sessionId, options) {
1667
+ if (!sessionId || sessionId.trim().length === 0) {
1668
+ throw new Error("sessionId is required to fetch chat history");
1670
1669
  }
1671
- if (isBrowser) {
1672
- nodeRequire = null;
1673
- return nodeRequire;
1670
+ const raw = await client.requestJson(
1671
+ `/chat/session/${encodeURIComponent(sessionId)}/history`,
1672
+ {
1673
+ method: "GET"
1674
+ }
1675
+ );
1676
+ const snapshot = client.parseWithSchema(
1677
+ raw,
1678
+ chatHistorySnapshotResponseSchema,
1679
+ "chat history snapshot response"
1680
+ );
1681
+ return attachDecryptedHistory(
1682
+ conversationContexts,
1683
+ client,
1684
+ sessionId,
1685
+ snapshot,
1686
+ options
1687
+ );
1688
+ }
1689
+ function attachDecryptedHistory(conversationContexts, client, sessionId, snapshot, options) {
1690
+ const shouldDecrypt = options?.decrypt !== void 0 ? options.decrypt : client.encryptionOptions?.autoDecryptHistory === true;
1691
+ if (!shouldDecrypt) {
1692
+ return snapshot;
1674
1693
  }
1675
- try {
1676
- const globalObject = typeof global !== "undefined" ? global : globalThis;
1677
- const req = globalObject.process?.mainModule?.require ?? globalObject.require;
1678
- nodeRequire = typeof req === "function" && typeof req.resolve === "function" ? req : null;
1679
- } catch {
1680
- nodeRequire = null;
1694
+ const requiresContext = snapshot.history.some(
1695
+ (entry) => Boolean(entry.cipherEnvelope)
1696
+ );
1697
+ if (!requiresContext) {
1698
+ return {
1699
+ ...snapshot,
1700
+ decryptedHistory: snapshot.history.map((entry) => ({
1701
+ entry,
1702
+ plaintext: entry.content
1703
+ }))
1704
+ };
1681
1705
  }
1682
- return nodeRequire;
1706
+ const context = resolveDecryptionContext(
1707
+ conversationContexts,
1708
+ client,
1709
+ sessionId,
1710
+ options
1711
+ );
1712
+ if (!context) {
1713
+ throw new Error(
1714
+ "Unable to decrypt chat history: encryption context unavailable"
1715
+ );
1716
+ }
1717
+ const decryptedHistory = snapshot.history.map((entry) => ({
1718
+ entry,
1719
+ plaintext: decryptHistoryEntryFromContext(client, entry, context)
1720
+ }));
1721
+ return { ...snapshot, decryptedHistory };
1683
1722
  }
1684
- async function dynamicImport(specifier) {
1685
- try {
1686
- return await import(specifier);
1687
- } catch (error) {
1688
- if (isModuleNotFound(specifier, error)) {
1689
- return null;
1690
- }
1691
- throw error;
1723
+ function registerConversationContextForEncryption(conversationContexts, context) {
1724
+ const normalized = {
1725
+ sessionId: context.sessionId,
1726
+ sharedSecret: import_buffer.Buffer.from(context.sharedSecret),
1727
+ identity: context.identity ? { ...context.identity } : void 0
1728
+ };
1729
+ const entries = conversationContexts.get(context.sessionId) ?? [];
1730
+ const existingIndex = entries.findIndex(
1731
+ (existing) => identitiesMatch(existing.identity, normalized.identity)
1732
+ );
1733
+ if (existingIndex >= 0) {
1734
+ entries[existingIndex] = normalized;
1735
+ } else {
1736
+ entries.push(normalized);
1692
1737
  }
1738
+ conversationContexts.set(context.sessionId, entries);
1693
1739
  }
1694
- async function optionalImport(specifier, options = {}) {
1695
- if (isBrowser) {
1696
- return dynamicImport(specifier);
1740
+ function resolveDecryptionContext(conversationContexts, client, sessionId, options) {
1741
+ if (options?.sharedSecret) {
1742
+ return {
1743
+ sessionId,
1744
+ sharedSecret: client.normalizeSharedSecret(options.sharedSecret),
1745
+ identity: options.identity
1746
+ };
1697
1747
  }
1698
- if (!options.preferImport) {
1699
- const requireFn = await resolveNodeRequire();
1700
- if (requireFn) {
1701
- try {
1702
- return requireFn(specifier);
1703
- } catch (error) {
1704
- if (!isModuleNotFound(specifier, error)) {
1705
- throw error;
1706
- }
1707
- }
1748
+ const contexts = conversationContexts.get(sessionId);
1749
+ if (!contexts || contexts.length === 0) {
1750
+ return null;
1751
+ }
1752
+ if (options?.identity) {
1753
+ const match = contexts.find(
1754
+ (context) => identitiesMatch(context.identity, options.identity)
1755
+ );
1756
+ if (match) {
1757
+ return match;
1708
1758
  }
1709
1759
  }
1710
- return dynamicImport(specifier);
1760
+ return contexts[0];
1711
1761
  }
1712
- function optionalImportSync(specifier) {
1713
- if (isBrowser) {
1714
- return null;
1762
+ function decryptHistoryEntryFromContext(client, entry, context) {
1763
+ const envelope = entry.cipherEnvelope;
1764
+ if (!envelope) {
1765
+ return entry.content;
1715
1766
  }
1767
+ const secret = import_buffer.Buffer.from(context.sharedSecret);
1716
1768
  try {
1717
- const globalObject = typeof global !== "undefined" ? global : globalThis;
1718
- const req = globalObject.process?.mainModule?.require ?? globalObject.require;
1719
- if (typeof req === "function" && typeof req.resolve === "function") {
1720
- return req(specifier);
1721
- }
1722
- } catch (error) {
1723
- if (!isModuleNotFound(specifier, error)) {
1724
- throw error;
1725
- }
1769
+ return client.encryption.decryptCipherEnvelope({
1770
+ envelope,
1771
+ sharedSecret: secret
1772
+ });
1773
+ } catch (_error) {
1774
+ return null;
1726
1775
  }
1727
- return null;
1728
1776
  }
1729
1777
 
1730
- // ../../src/services/registry-broker/client/encryption.ts
1731
- var getFs = async () => {
1732
- const fsModule = await optionalImport("node:fs");
1733
- if (fsModule && typeof fsModule.existsSync === "function" && typeof fsModule.readFileSync === "function" && typeof fsModule.writeFileSync === "function" && typeof fsModule.appendFileSync === "function") {
1734
- return fsModule;
1778
+ // ../../src/services/registry-broker/client/utils.ts
1779
+ var DEFAULT_USER_AGENT = "@hol-org/rb-client";
1780
+ var DEFAULT_PROGRESS_INTERVAL_MS = 1500;
1781
+ var DEFAULT_PROGRESS_TIMEOUT_MS = 5 * 60 * 1e3;
1782
+ var DEFAULT_BASE_URL = "https://hol.org/registry/api/v1";
1783
+ var JSON_CONTENT_TYPE = /application\/json/i;
1784
+ var DEFAULT_HISTORY_TOP_UP_HBAR = 0.25;
1785
+ var MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS = 1;
1786
+ var stripTrailingSlashes = (value) => {
1787
+ let end = value.length;
1788
+ while (end > 0 && value.charCodeAt(end - 1) === 47) {
1789
+ end -= 1;
1735
1790
  }
1736
- return null;
1791
+ return end === value.length ? value : value.slice(0, end);
1737
1792
  };
1738
- async function registerEncryptionKey(client, payload) {
1739
- const raw = await client.requestJson("/encryption/keys", {
1740
- method: "POST",
1741
- headers: { "content-type": "application/json" },
1742
- body: payload
1743
- });
1744
- return client.parseWithSchema(
1745
- raw,
1746
- registerEncryptionKeyResponseSchema,
1747
- "register encryption key response"
1748
- );
1749
- }
1750
- function normalizeAutoRegisterIdentity(config) {
1751
- const identity = {};
1752
- if (config.uaid) {
1753
- identity.uaid = config.uaid;
1754
- }
1755
- if (config.ledgerAccountId) {
1756
- identity.ledgerAccountId = config.ledgerAccountId;
1757
- if (config.ledgerNetwork) {
1758
- identity.ledgerNetwork = config.ledgerNetwork;
1759
- }
1793
+ var createAbortError = () => typeof DOMException === "function" ? new DOMException("Aborted", "AbortError") : new Error("The operation was aborted");
1794
+ var normaliseHeaderName = (name) => name.trim().toLowerCase();
1795
+ var isBrowserRuntime = () => typeof window !== "undefined" && typeof window.fetch === "function";
1796
+ var toJsonValue = (value) => {
1797
+ if (value === null) {
1798
+ return null;
1760
1799
  }
1761
- if (config.email) {
1762
- identity.email = config.email;
1800
+ if (value instanceof Date) {
1801
+ return value.toISOString();
1763
1802
  }
1764
- if (identity.uaid || identity.ledgerAccountId || identity.email) {
1765
- return identity;
1803
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1804
+ return value;
1766
1805
  }
1767
- return null;
1768
- }
1769
- function derivePublicKeyFromPrivateKey(client, privateKey) {
1770
- const normalized = client.hexToBuffer(privateKey);
1771
- const publicKey = import_secp256k1.secp256k1.getPublicKey(normalized, true);
1772
- return import_buffer.Buffer.from(publicKey).toString("hex");
1773
- }
1774
- async function resolveAutoRegisterKeyMaterial(client, config) {
1775
- if (config.publicKey?.trim()) {
1776
- return { publicKey: config.publicKey.trim() };
1806
+ if (Array.isArray(value)) {
1807
+ return value.map((item) => item === void 0 ? null : toJsonValue(item));
1777
1808
  }
1778
- let privateKey = config.privateKey?.trim();
1779
- const envVar = config.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
1780
- if (!privateKey && envVar && process?.env?.[envVar]?.trim()) {
1781
- privateKey = process.env[envVar]?.trim();
1782
- }
1783
- if (!privateKey && config.generateIfMissing) {
1784
- const pair = await client.generateEncryptionKeyPair({
1785
- keyType: config.keyType ?? "secp256k1",
1786
- envVar,
1787
- envPath: config.envPath,
1788
- overwrite: config.overwriteEnv
1789
- });
1790
- return { publicKey: pair.publicKey, privateKey: pair.privateKey };
1791
- }
1792
- if (privateKey) {
1793
- const publicKey = derivePublicKeyFromPrivateKey(client, privateKey);
1794
- return { publicKey, privateKey };
1795
- }
1796
- return null;
1797
- }
1798
- async function autoRegisterEncryptionKey(client, config) {
1799
- const identity = normalizeAutoRegisterIdentity(config);
1800
- if (!identity) {
1801
- throw new Error(
1802
- "Auto-registration requires uaid, ledgerAccountId, or email"
1803
- );
1804
- }
1805
- const material = await resolveAutoRegisterKeyMaterial(client, config);
1806
- if (!material) {
1807
- throw new Error(
1808
- "Unable to resolve encryption public key for auto-registration"
1809
- );
1810
- }
1811
- await registerEncryptionKey(client, {
1812
- keyType: config.keyType ?? "secp256k1",
1813
- publicKey: material.publicKey,
1814
- ...identity
1815
- });
1816
- return material;
1817
- }
1818
- async function ensureAgentEncryptionKey(client, options) {
1819
- return autoRegisterEncryptionKey(client, {
1820
- ...options,
1821
- uaid: options.uaid,
1822
- enabled: true
1823
- });
1824
- }
1825
- function createEncryptionApi(client) {
1826
- return {
1827
- registerKey: (payload) => registerEncryptionKey(client, payload),
1828
- generateEphemeralKeyPair: () => client.createEphemeralKeyPair(),
1829
- deriveSharedSecret: (options) => client.deriveSharedSecret(options),
1830
- encryptCipherEnvelope: (options) => client.buildCipherEnvelope(options),
1831
- decryptCipherEnvelope: (options) => client.openCipherEnvelope(options),
1832
- ensureAgentKey: (options) => ensureAgentEncryptionKey(client, options)
1833
- };
1834
- }
1835
- async function bootstrapEncryptionOptions(client, options) {
1836
- if (!options?.autoRegister || options.autoRegister.enabled === false) {
1837
- return null;
1838
- }
1839
- return autoRegisterEncryptionKey(client, options.autoRegister);
1840
- }
1841
- async function generateEncryptionKeyPair(client, options = {}) {
1842
- client.assertNodeRuntime("generateEncryptionKeyPair");
1843
- const keyType = options.keyType ?? "secp256k1";
1844
- if (keyType !== "secp256k1") {
1845
- throw new Error("Only secp256k1 key generation is supported currently");
1846
- }
1847
- const privateKeyBytes = (0, import_crypto.randomBytes)(32);
1848
- const privateKey = import_buffer.Buffer.from(privateKeyBytes).toString("hex");
1849
- const publicKeyBytes = import_secp256k1.secp256k1.getPublicKey(privateKeyBytes, true);
1850
- const publicKey = import_buffer.Buffer.from(publicKeyBytes).toString("hex");
1851
- const envVar = options.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
1852
- const resolvedPath = options.envPath ? path.resolve(options.envPath) : void 0;
1853
- if (resolvedPath) {
1854
- const fsModule = await getFs();
1855
- if (!fsModule) {
1856
- throw new Error(
1857
- "File system module is not available; cannot write encryption key env file"
1858
- );
1859
- }
1860
- const envLine = `${envVar}=${privateKey}`;
1861
- if (fsModule.existsSync(resolvedPath)) {
1862
- const content = fsModule.readFileSync(resolvedPath, "utf-8");
1863
- const lineRegex = new RegExp(`^${envVar}=.*$`, "m");
1864
- if (lineRegex.test(content)) {
1865
- if (!options.overwrite) {
1866
- throw new Error(
1867
- `${envVar} already exists in ${resolvedPath}; set overwrite=true to replace it`
1868
- );
1869
- }
1870
- const updated = content.replace(lineRegex, envLine);
1871
- fsModule.writeFileSync(resolvedPath, updated);
1872
- } else {
1873
- const needsNewline = !content.endsWith("\n");
1874
- fsModule.appendFileSync(
1875
- resolvedPath,
1876
- `${needsNewline ? "\n" : ""}${envLine}
1877
- `
1878
- );
1879
- }
1880
- } else {
1881
- fsModule.writeFileSync(resolvedPath, `${envLine}
1882
- `);
1883
- }
1884
- }
1885
- return {
1886
- privateKey,
1887
- publicKey,
1888
- envPath: resolvedPath,
1889
- envVar
1890
- };
1891
- }
1892
-
1893
- // ../../src/services/registry-broker/client/utils.ts
1894
- var DEFAULT_USER_AGENT = "@hol-org/rb-client";
1895
- var DEFAULT_PROGRESS_INTERVAL_MS = 1500;
1896
- var DEFAULT_PROGRESS_TIMEOUT_MS = 5 * 60 * 1e3;
1897
- var DEFAULT_BASE_URL = "https://hol.org/registry/api/v1";
1898
- var JSON_CONTENT_TYPE = /application\/json/i;
1899
- var DEFAULT_HISTORY_TOP_UP_HBAR = 0.25;
1900
- var MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS = 1;
1901
- var stripTrailingSlashes = (value) => {
1902
- let end = value.length;
1903
- while (end > 0 && value.charCodeAt(end - 1) === 47) {
1904
- end -= 1;
1905
- }
1906
- return end === value.length ? value : value.slice(0, end);
1907
- };
1908
- var createAbortError = () => typeof DOMException === "function" ? new DOMException("Aborted", "AbortError") : new Error("The operation was aborted");
1909
- var normaliseHeaderName = (name) => name.trim().toLowerCase();
1910
- var isBrowserRuntime = () => typeof window !== "undefined" && typeof window.fetch === "function";
1911
- var toJsonValue = (value) => {
1912
- if (value === null) {
1913
- return null;
1914
- }
1915
- if (value instanceof Date) {
1916
- return value.toISOString();
1917
- }
1918
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1919
- return value;
1920
- }
1921
- if (Array.isArray(value)) {
1922
- return value.map((item) => item === void 0 ? null : toJsonValue(item));
1923
- }
1924
- if (typeof value === "object") {
1925
- const result = {};
1926
- Object.entries(value).forEach(
1927
- ([key, entryValue]) => {
1928
- if (entryValue !== void 0) {
1929
- result[key] = toJsonValue(entryValue);
1930
- }
1931
- }
1932
- );
1933
- return result;
1809
+ if (typeof value === "object") {
1810
+ const result = {};
1811
+ Object.entries(value).forEach(
1812
+ ([key, entryValue]) => {
1813
+ if (entryValue !== void 0) {
1814
+ result[key] = toJsonValue(entryValue);
1815
+ }
1816
+ }
1817
+ );
1818
+ return result;
1934
1819
  }
1935
1820
  throw new TypeError("Only JSON-compatible values are supported");
1936
1821
  };
@@ -2113,1926 +1998,2091 @@ function buildSearchQuery(params) {
2113
1998
  return queryString.length > 0 ? `?${queryString}` : "";
2114
1999
  }
2115
2000
 
2116
- // ../../src/services/registry-broker/client/errors.ts
2117
- var RegistryBrokerError = class extends Error {
2118
- constructor(message, details) {
2119
- super(message);
2120
- this.status = details.status;
2121
- this.statusText = details.statusText;
2122
- this.body = details.body;
2123
- }
2124
- };
2125
- var RegistryBrokerParseError = class extends Error {
2126
- constructor(message, cause, rawValue) {
2127
- super(message);
2128
- this.cause = cause;
2129
- this.rawValue = rawValue;
2001
+ // ../../src/services/registry-broker/client/encrypted-chat-manager.ts
2002
+ var EncryptionUnavailableError = class extends Error {
2003
+ constructor(sessionId, summary) {
2004
+ super("Encryption is not enabled for this session");
2005
+ this.sessionId = sessionId;
2006
+ this.summary = summary;
2130
2007
  }
2131
2008
  };
2132
-
2133
- // ../../src/services/registry-broker/client/search.ts
2134
- function buildVectorFallbackSearchParams(request) {
2135
- const params = {
2136
- q: request.query
2137
- };
2138
- let effectiveLimit;
2139
- if (typeof request.limit === "number" && Number.isFinite(request.limit)) {
2140
- effectiveLimit = request.limit;
2141
- params.limit = request.limit;
2142
- }
2143
- if (typeof request.offset === "number" && Number.isFinite(request.offset) && request.offset > 0) {
2144
- const limit = effectiveLimit && effectiveLimit > 0 ? effectiveLimit : 20;
2145
- params.limit = limit;
2146
- params.page = Math.floor(request.offset / limit) + 1;
2147
- }
2148
- if (request.filter?.registry) {
2149
- params.registry = request.filter.registry;
2009
+ var EncryptedChatManager = class {
2010
+ constructor(client) {
2011
+ this.client = client;
2150
2012
  }
2151
- if (request.filter?.protocols?.length) {
2152
- params.protocols = [...request.filter.protocols];
2013
+ registerConversationContext(context) {
2014
+ this.client.registerConversationContextForEncryption(context);
2153
2015
  }
2154
- if (request.filter?.adapter?.length) {
2155
- params.adapters = [...request.filter.adapter];
2016
+ async startSession(options) {
2017
+ await this.client.encryptionReady();
2018
+ const session = await this.client.chat.createSession({
2019
+ uaid: options.uaid,
2020
+ senderUaid: options.senderUaid,
2021
+ encryptionRequested: true,
2022
+ historyTtlSeconds: options.historyTtlSeconds,
2023
+ auth: options.auth
2024
+ });
2025
+ options.onSessionCreated?.(session.sessionId);
2026
+ const summary = session.encryption;
2027
+ if (!summary?.enabled) {
2028
+ throw new EncryptionUnavailableError(
2029
+ session.sessionId,
2030
+ session.encryption ?? null
2031
+ );
2032
+ }
2033
+ const handle = await this.establishRequesterContext({
2034
+ sessionId: session.sessionId,
2035
+ summary,
2036
+ senderUaid: options.senderUaid,
2037
+ handshakeTimeoutMs: options.handshakeTimeoutMs,
2038
+ pollIntervalMs: options.pollIntervalMs
2039
+ });
2040
+ return handle;
2156
2041
  }
2157
- if (request.filter?.capabilities?.length) {
2158
- params.capabilities = request.filter.capabilities.map(
2159
- (value) => typeof value === "number" ? value.toString(10) : value
2042
+ async acceptSession(options) {
2043
+ await this.client.encryptionReady();
2044
+ const summary = await this.waitForEncryptionSummary(
2045
+ options.sessionId,
2046
+ options.handshakeTimeoutMs,
2047
+ options.pollIntervalMs
2160
2048
  );
2049
+ const handle = await this.establishResponderContext({
2050
+ sessionId: options.sessionId,
2051
+ summary,
2052
+ responderUaid: options.responderUaid,
2053
+ handshakeTimeoutMs: options.handshakeTimeoutMs,
2054
+ pollIntervalMs: options.pollIntervalMs
2055
+ });
2056
+ return handle;
2161
2057
  }
2162
- if (request.filter?.type) {
2163
- params.type = request.filter.type;
2164
- }
2165
- return params;
2166
- }
2167
- function convertSearchResultToVectorResponse(result) {
2168
- const hits = result.hits.map((agent) => ({
2169
- agent,
2170
- score: 0,
2171
- highlights: {}
2172
- }));
2173
- const total = result.total;
2174
- const limit = result.limit;
2175
- const page = result.page;
2176
- const totalVisible = page * limit;
2177
- const limited = total > totalVisible || page > 1;
2178
- return {
2179
- hits,
2180
- total,
2181
- took: 0,
2182
- totalAvailable: total,
2183
- visible: hits.length,
2184
- limited,
2185
- credits_used: 0
2186
- };
2187
- }
2188
- async function search(client, params = {}) {
2189
- const query = buildSearchQuery(params);
2190
- const raw = await client.requestJson(`/search${query}`, {
2191
- method: "GET"
2192
- });
2193
- return client.parseWithSchema(raw, searchResponseSchema, "search response");
2194
- }
2195
- async function delegate(client, request) {
2196
- const raw = await client.requestJson("/delegate", {
2197
- method: "POST",
2198
- body: request,
2199
- headers: { "content-type": "application/json" }
2200
- });
2201
- return client.parseWithSchema(
2202
- raw,
2203
- delegationPlanResponseSchema,
2204
- "delegate response"
2205
- );
2206
- }
2207
- async function stats(client) {
2208
- const raw = await client.requestJson("/stats", { method: "GET" });
2209
- return client.parseWithSchema(raw, statsResponseSchema, "stats response");
2210
- }
2211
- async function registries(client) {
2212
- const raw = await client.requestJson("/registries", {
2213
- method: "GET"
2214
- });
2215
- return client.parseWithSchema(
2216
- raw,
2217
- registriesResponseSchema,
2218
- "registries response"
2219
- );
2220
- }
2221
- async function getAdditionalRegistries(client) {
2222
- const raw = await client.requestJson(
2223
- "/register/additional-registries",
2224
- {
2225
- method: "GET"
2058
+ async establishRequesterContext(params) {
2059
+ const keyPair = this.client.encryption.generateEphemeralKeyPair();
2060
+ await this.client.chat.submitEncryptionHandshake(params.sessionId, {
2061
+ role: "requester",
2062
+ keyType: "secp256k1",
2063
+ ephemeralPublicKey: keyPair.publicKey,
2064
+ uaid: params.senderUaid ?? params.summary.requester?.uaid ?? void 0
2065
+ });
2066
+ const { summary, record } = await this.waitForHandshakeCompletion(
2067
+ params.sessionId,
2068
+ params.handshakeTimeoutMs,
2069
+ params.pollIntervalMs
2070
+ );
2071
+ const responderKey = record.responder?.ephemeralPublicKey;
2072
+ if (!responderKey) {
2073
+ throw new Error("Responder handshake was not completed in time");
2226
2074
  }
2227
- );
2228
- return client.parseWithSchema(
2229
- raw,
2230
- additionalRegistryCatalogResponseSchema,
2231
- "additional registry catalog response"
2232
- );
2233
- }
2234
- async function popularSearches(client) {
2235
- const raw = await client.requestJson("/popular", {
2236
- method: "GET"
2237
- });
2238
- return client.parseWithSchema(
2239
- raw,
2240
- popularResponseSchema,
2241
- "popular searches response"
2242
- );
2243
- }
2244
- async function listProtocols(client) {
2245
- const raw = await client.requestJson("/protocols", {
2246
- method: "GET"
2247
- });
2248
- return client.parseWithSchema(
2249
- raw,
2250
- protocolsResponseSchema,
2251
- "protocols response"
2252
- );
2253
- }
2254
- async function detectProtocol(client, message) {
2255
- const raw = await client.requestJson("/detect-protocol", {
2256
- method: "POST",
2257
- body: { message },
2258
- headers: { "content-type": "application/json" }
2259
- });
2260
- return client.parseWithSchema(
2261
- raw,
2262
- detectProtocolResponseSchema,
2263
- "detect protocol response"
2264
- );
2265
- }
2266
- async function registrySearchByNamespace(client, registry, query) {
2267
- const params = new URLSearchParams();
2268
- if (query) {
2269
- params.set("q", query);
2075
+ const sharedSecret = this.client.encryption.deriveSharedSecret({
2076
+ privateKey: keyPair.privateKey,
2077
+ peerPublicKey: responderKey
2078
+ }).subarray();
2079
+ const recipients = this.buildRecipients(summary);
2080
+ return this.createHandle({
2081
+ sessionId: params.sessionId,
2082
+ sharedSecret,
2083
+ summary,
2084
+ recipients,
2085
+ identity: summary.requester ?? void 0
2086
+ });
2270
2087
  }
2271
- const suffix = params.size > 0 ? `?${params.toString()}` : "";
2272
- const raw = await client.requestJson(
2273
- `/registries/${encodeURIComponent(registry)}/search${suffix}`,
2274
- {
2275
- method: "GET"
2276
- }
2277
- );
2278
- return client.parseWithSchema(
2279
- raw,
2280
- registrySearchByNamespaceSchema,
2281
- "registry search response"
2282
- );
2283
- }
2284
- async function vectorSearch(client, request) {
2285
- try {
2286
- const raw = await client.requestJson("/search", {
2287
- method: "POST",
2288
- body: request,
2289
- headers: { "content-type": "application/json" }
2088
+ async establishResponderContext(params) {
2089
+ const keyPair = this.client.encryption.generateEphemeralKeyPair();
2090
+ await this.client.chat.submitEncryptionHandshake(params.sessionId, {
2091
+ role: "responder",
2092
+ keyType: "secp256k1",
2093
+ ephemeralPublicKey: keyPair.publicKey,
2094
+ uaid: params.responderUaid ?? params.summary.responder?.uaid ?? void 0
2290
2095
  });
2291
- return client.parseWithSchema(
2292
- raw,
2293
- vectorSearchResponseSchema,
2294
- "vector search response"
2096
+ const { summary, record } = await this.waitForHandshakeCompletion(
2097
+ params.sessionId,
2098
+ params.handshakeTimeoutMs,
2099
+ params.pollIntervalMs
2295
2100
  );
2296
- } catch (error) {
2297
- if (error instanceof RegistryBrokerError && error.status === 501) {
2298
- const fallback = await search(
2299
- client,
2300
- buildVectorFallbackSearchParams(request)
2301
- );
2302
- return convertSearchResultToVectorResponse(fallback);
2101
+ const requesterKey = record.requester?.ephemeralPublicKey;
2102
+ if (!requesterKey) {
2103
+ throw new Error("Requester handshake was not detected in time");
2303
2104
  }
2304
- throw error;
2305
- }
2306
- }
2307
- async function searchStatus(client) {
2308
- const raw = await client.requestJson("/search/status", {
2309
- method: "GET"
2310
- });
2311
- return client.parseWithSchema(
2312
- raw,
2313
- searchStatusResponseSchema,
2314
- "search status response"
2315
- );
2316
- }
2317
- async function websocketStats(client) {
2318
- const raw = await client.requestJson("/websocket/stats", {
2319
- method: "GET"
2320
- });
2321
- return client.parseWithSchema(
2322
- raw,
2323
- websocketStatsResponseSchema,
2324
- "websocket stats response"
2325
- );
2326
- }
2327
- async function metricsSummary(client) {
2328
- const raw = await client.requestJson("/metrics", {
2329
- method: "GET"
2330
- });
2331
- return client.parseWithSchema(
2332
- raw,
2333
- metricsSummaryResponseSchema,
2334
- "metrics summary response"
2335
- );
2336
- }
2337
- async function facets(client, adapter) {
2338
- const params = new URLSearchParams();
2339
- if (adapter) {
2340
- params.set("adapter", adapter);
2105
+ const sharedSecret = this.client.encryption.deriveSharedSecret({
2106
+ privateKey: keyPair.privateKey,
2107
+ peerPublicKey: requesterKey
2108
+ }).subarray();
2109
+ const recipients = this.buildRecipients(summary);
2110
+ return this.createHandle({
2111
+ sessionId: params.sessionId,
2112
+ sharedSecret,
2113
+ summary,
2114
+ recipients,
2115
+ identity: summary.responder ?? void 0
2116
+ });
2341
2117
  }
2342
- const suffix = params.size > 0 ? `?${params.toString()}` : "";
2343
- const raw = await client.requestJson(`/search/facets${suffix}`, {
2344
- method: "GET"
2345
- });
2346
- return client.parseWithSchema(
2347
- raw,
2348
- searchFacetsResponseSchema,
2349
- "search facets response"
2350
- );
2351
- }
2352
-
2353
- // ../../src/services/registry-broker/client/adapters.ts
2354
- async function adapters(client) {
2355
- const raw = await client.requestJson("/adapters", {
2356
- method: "GET"
2357
- });
2358
- return client.parseWithSchema(
2359
- raw,
2360
- adaptersResponseSchema,
2361
- "adapters response"
2362
- );
2363
- }
2364
- async function adaptersDetailed(client) {
2365
- const raw = await client.requestJson("/adapters/details", {
2366
- method: "GET"
2367
- });
2368
- return client.parseWithSchema(
2369
- raw,
2370
- adapterDetailsResponseSchema,
2371
- "adapter details response"
2372
- );
2373
- }
2374
- async function adapterRegistryCategories(client) {
2375
- const raw = await client.requestJson(
2376
- "/adapters/registry/categories",
2377
- {
2378
- method: "GET"
2118
+ async waitForHandshakeCompletion(sessionId, timeoutMs = 3e4, pollIntervalMs = 1e3) {
2119
+ const deadline = Date.now() + timeoutMs;
2120
+ while (true) {
2121
+ const status = await this.client.chat.getEncryptionStatus(sessionId);
2122
+ const summary = status.encryption;
2123
+ const record = summary?.handshake;
2124
+ if (summary && record && record.status === "complete") {
2125
+ return { summary, record };
2126
+ }
2127
+ if (Date.now() >= deadline) {
2128
+ throw new Error("Timed out waiting for encrypted handshake completion");
2129
+ }
2130
+ await this.delay(pollIntervalMs);
2379
2131
  }
2380
- );
2381
- return client.parseWithSchema(
2382
- raw,
2383
- adapterRegistryCategoriesResponseSchema,
2384
- "adapter registry categories response"
2385
- );
2386
- }
2387
- async function adapterRegistryAdapters(client, filters = {}) {
2388
- const params = new URLSearchParams();
2389
- if (filters.category) {
2390
- params.set("category", filters.category);
2391
2132
  }
2392
- if (filters.entity) {
2393
- params.set("entity", filters.entity);
2394
- }
2395
- if (filters.keywords?.length) {
2396
- params.set("keywords", filters.keywords.join(","));
2397
- }
2398
- if (filters.query) {
2399
- params.set("query", filters.query);
2400
- }
2401
- if (typeof filters.limit === "number") {
2402
- params.set("limit", String(filters.limit));
2403
- }
2404
- if (typeof filters.offset === "number") {
2405
- params.set("offset", String(filters.offset));
2406
- }
2407
- const suffix = params.size > 0 ? `?${params.toString()}` : "";
2408
- const raw = await client.requestJson(
2409
- `/adapters/registry/adapters${suffix}`,
2410
- {
2411
- method: "GET"
2412
- }
2413
- );
2414
- return client.parseWithSchema(
2415
- raw,
2416
- adapterRegistryAdaptersResponseSchema,
2417
- "adapter registry adapters response"
2418
- );
2419
- }
2420
- async function createAdapterRegistryCategory(client, payload) {
2421
- const raw = await client.requestJson(
2422
- "/adapters/registry/categories",
2423
- {
2424
- method: "POST",
2425
- headers: { "content-type": "application/json" },
2426
- body: toJsonObject(payload)
2133
+ async waitForEncryptionSummary(sessionId, _timeoutMs = 3e4, _pollIntervalMs = 1e3) {
2134
+ const status = await this.client.chat.getEncryptionStatus(sessionId);
2135
+ if (!status.encryption?.enabled) {
2136
+ throw new EncryptionUnavailableError(
2137
+ sessionId,
2138
+ status.encryption ?? null
2139
+ );
2427
2140
  }
2428
- );
2429
- const parsed = client.parseWithSchema(
2430
- raw,
2431
- adapterRegistryCreateCategoryResponseSchema,
2432
- "adapter registry create category response"
2433
- );
2434
- return parsed.category;
2435
- }
2436
- async function submitAdapterRegistryAdapter(client, payload) {
2437
- const raw = await client.requestJson(
2438
- "/adapters/registry/adapters",
2439
- {
2440
- method: "POST",
2441
- headers: { "content-type": "application/json" },
2442
- body: toJsonObject(payload)
2141
+ return status.encryption;
2142
+ }
2143
+ buildRecipients(summary) {
2144
+ const candidates = [summary.requester, summary.responder].filter(Boolean);
2145
+ const normalized = candidates.map((candidate) => {
2146
+ if (!candidate) {
2147
+ return null;
2148
+ }
2149
+ const recipient = {};
2150
+ if (candidate.uaid) {
2151
+ recipient.uaid = candidate.uaid;
2152
+ }
2153
+ if (candidate.ledgerAccountId) {
2154
+ recipient.ledgerAccountId = candidate.ledgerAccountId;
2155
+ }
2156
+ if (candidate.userId) {
2157
+ recipient.userId = candidate.userId;
2158
+ }
2159
+ if (candidate.email) {
2160
+ recipient.email = candidate.email;
2161
+ }
2162
+ return recipient;
2163
+ }).filter(
2164
+ (entry) => Boolean(
2165
+ entry?.uaid || entry?.ledgerAccountId || entry?.userId || entry?.email
2166
+ )
2167
+ );
2168
+ if (normalized.length > 0) {
2169
+ return normalized;
2443
2170
  }
2444
- );
2445
- return client.parseWithSchema(
2446
- raw,
2447
- adapterRegistrySubmitAdapterAcceptedResponseSchema,
2448
- "adapter registry submit adapter response"
2449
- );
2450
- }
2451
- async function adapterRegistrySubmissionStatus(client, submissionId) {
2452
- const raw = await client.requestJson(
2453
- `/adapters/registry/submissions/${encodeURIComponent(submissionId)}`,
2454
- {
2455
- method: "GET"
2171
+ if (summary.responder?.uaid) {
2172
+ return [{ uaid: summary.responder.uaid }];
2456
2173
  }
2457
- );
2458
- return client.parseWithSchema(
2459
- raw,
2460
- adapterRegistrySubmissionStatusResponseSchema,
2461
- "adapter registry submission status response"
2462
- );
2463
- }
2464
-
2465
- // ../../src/services/registry-broker/client/credits.ts
2466
- async function loadX402Dependencies(client) {
2467
- const [{ default: axios }, x402Axios, x402Types] = await Promise.all([
2468
- import("axios"),
2469
- optionalImport("x402-axios"),
2470
- optionalImport("x402/types")
2471
- ]);
2472
- if (!x402Axios || !x402Types) {
2473
- throw new Error(
2474
- "x402-axios and x402/types are required for X402 flows. Install them to enable ledger payments."
2475
- );
2174
+ return [];
2476
2175
  }
2477
- const withPaymentInterceptor = x402Axios.withPaymentInterceptor;
2478
- const decodePaymentResponse = x402Axios.decodeXPaymentResponse;
2479
- const createX402Signer = x402Types.createSigner;
2480
- const createPaymentClient = (walletClient) => {
2481
- const axiosClient = axios.create({
2482
- baseURL: client.baseUrl,
2483
- headers: {
2484
- ...client.getDefaultHeaders(),
2485
- "content-type": "application/json"
2176
+ createHandle(context) {
2177
+ const sharedSecret = context.sharedSecret;
2178
+ const uaid = context.summary.requester?.uaid ?? context.summary.responder?.uaid ?? context.identity?.uaid;
2179
+ const decryptHistoryEntry = (entry) => this.decryptEntry(entry, context.identity, sharedSecret);
2180
+ const fetchHistory = async (options) => {
2181
+ const snapshot = await this.client.fetchHistorySnapshot(
2182
+ context.sessionId,
2183
+ options
2184
+ );
2185
+ if (snapshot.decryptedHistory) {
2186
+ return snapshot.decryptedHistory;
2486
2187
  }
2188
+ return snapshot.history.map((entry) => ({
2189
+ entry,
2190
+ plaintext: decryptHistoryEntry(entry)
2191
+ }));
2192
+ };
2193
+ const handle = {
2194
+ sessionId: context.sessionId,
2195
+ mode: "encrypted",
2196
+ summary: context.summary,
2197
+ send: async (options) => {
2198
+ const recipients = options.recipients ?? context.recipients;
2199
+ return this.client.chat.sendMessage({
2200
+ sessionId: context.sessionId,
2201
+ message: options.message ?? "[ciphertext omitted]",
2202
+ streaming: options.streaming,
2203
+ auth: options.auth,
2204
+ uaid,
2205
+ encryption: {
2206
+ plaintext: options.plaintext,
2207
+ sharedSecret: Buffer.from(sharedSecret),
2208
+ recipients
2209
+ }
2210
+ });
2211
+ },
2212
+ decryptHistoryEntry,
2213
+ fetchHistory
2214
+ };
2215
+ this.registerConversationContext({
2216
+ sessionId: context.sessionId,
2217
+ sharedSecret,
2218
+ identity: context.identity
2487
2219
  });
2488
- const paymentClient = withPaymentInterceptor(axiosClient, walletClient);
2489
- return paymentClient;
2490
- };
2491
- return { createPaymentClient, decodePaymentResponse, createX402Signer };
2492
- }
2493
- function calculateHbarAmountParam(hbarAmount) {
2494
- const tinybars = Math.ceil(hbarAmount * 1e8);
2495
- if (tinybars <= 0) {
2496
- throw new Error("Calculated purchase amount must be positive");
2220
+ return handle;
2497
2221
  }
2498
- return tinybars / 1e8;
2499
- }
2500
- async function purchaseCreditsWithHbar(client, params) {
2501
- const body = {
2502
- accountId: params.accountId,
2503
- payerKey: params.privateKey,
2504
- hbarAmount: calculateHbarAmountParam(params.hbarAmount)
2505
- };
2506
- if (params.memo) {
2507
- body.memo = params.memo;
2222
+ decryptEntry(entry, identity, fallbackSecret) {
2223
+ const envelope = entry.cipherEnvelope;
2224
+ if (!envelope) {
2225
+ return null;
2226
+ }
2227
+ const secret = Buffer.from(fallbackSecret);
2228
+ try {
2229
+ return this.client.encryption.decryptCipherEnvelope({
2230
+ envelope,
2231
+ sharedSecret: secret
2232
+ });
2233
+ } catch (_error) {
2234
+ return null;
2235
+ }
2236
+ }
2237
+ recipientMatches(candidate, target) {
2238
+ if (target.uaid && candidate.uaid?.toLowerCase() === target.uaid.toLowerCase()) {
2239
+ return true;
2240
+ }
2241
+ if (target.ledgerAccountId && candidate.ledgerAccountId?.toLowerCase() === target.ledgerAccountId.toLowerCase()) {
2242
+ return true;
2243
+ }
2244
+ if (target.userId && candidate.userId === target.userId) {
2245
+ return true;
2246
+ }
2247
+ if (target.email && candidate.email?.toLowerCase() === target.email.toLowerCase()) {
2248
+ return true;
2249
+ }
2250
+ return false;
2508
2251
  }
2509
- if (params.metadata) {
2510
- body.metadata = params.metadata;
2252
+ async delay(ms) {
2253
+ if (ms <= 0) {
2254
+ return;
2255
+ }
2256
+ await new Promise((resolve) => setTimeout(resolve, ms));
2511
2257
  }
2512
- const raw = await client.requestJson("/credits/purchase", {
2513
- method: "POST",
2514
- headers: { "content-type": "application/json" },
2515
- body
2516
- });
2517
- return client.parseWithSchema(
2518
- raw,
2519
- creditPurchaseResponseSchema,
2520
- "credit purchase response"
2521
- );
2522
- }
2523
- async function getX402Minimums(client) {
2524
- const raw = await client.requestJson(
2525
- "/credits/purchase/x402/minimums",
2526
- { method: "GET" }
2527
- );
2528
- return client.parseWithSchema(
2529
- raw,
2530
- x402MinimumsResponseSchema,
2531
- "x402 minimums response"
2532
- );
2258
+ };
2259
+
2260
+ // ../../src/services/registry-broker/client/chat.ts
2261
+ function createChatApi(client, encryptedManager) {
2262
+ return {
2263
+ start: (options) => client.startChat(options),
2264
+ createSession: (payload) => client.createSession(payload),
2265
+ sendMessage: (payload) => client.sendMessage(payload),
2266
+ endSession: (sessionId) => client.endSession(sessionId),
2267
+ getHistory: (sessionId, options) => client.fetchHistorySnapshot(sessionId, options),
2268
+ compactHistory: (payload) => client.compactHistory(payload),
2269
+ getEncryptionStatus: (sessionId) => client.fetchEncryptionStatus(sessionId),
2270
+ submitEncryptionHandshake: (sessionId, payload) => client.postEncryptionHandshake(sessionId, payload),
2271
+ startConversation: (options) => client.startConversation(options),
2272
+ acceptConversation: (options) => client.acceptConversation(options),
2273
+ createEncryptedSession: (options) => encryptedManager.startSession(options),
2274
+ acceptEncryptedSession: (options) => encryptedManager.acceptSession(options)
2275
+ };
2533
2276
  }
2534
- async function purchaseCreditsWithX402(client, params) {
2535
- const { createPaymentClient, decodePaymentResponse } = await loadX402Dependencies(client);
2536
- if (!Number.isFinite(params.credits) || params.credits <= 0) {
2537
- throw new Error("credits must be a positive number");
2277
+ async function createSession(client, payload, allowHistoryAutoTopUp = true) {
2278
+ const body = {};
2279
+ if ("uaid" in payload && payload.uaid) {
2280
+ body.uaid = payload.uaid;
2538
2281
  }
2539
- if (params.usdAmount !== void 0 && (!Number.isFinite(params.usdAmount) || params.usdAmount <= 0)) {
2540
- throw new Error("usdAmount must be a positive number when provided");
2282
+ if ("agentUrl" in payload && payload.agentUrl) {
2283
+ body.agentUrl = payload.agentUrl;
2541
2284
  }
2542
- const body = {
2543
- accountId: params.accountId,
2544
- credits: params.credits
2545
- };
2546
- if (params.usdAmount !== void 0) {
2547
- body.usdAmount = params.usdAmount;
2285
+ if (payload.auth) {
2286
+ body.auth = serialiseAuthConfig(payload.auth);
2548
2287
  }
2549
- if (params.description) {
2550
- body.description = params.description;
2288
+ if (payload.historyTtlSeconds !== void 0) {
2289
+ body.historyTtlSeconds = payload.historyTtlSeconds;
2551
2290
  }
2552
- if (params.metadata) {
2553
- body.metadata = params.metadata;
2291
+ if (payload.encryptionRequested !== void 0) {
2292
+ body.encryptionRequested = payload.encryptionRequested;
2554
2293
  }
2555
- const paymentClient = createPaymentClient(params.walletClient);
2556
- const response = await paymentClient.post("/credits/purchase/x402", body);
2557
- const parsed = client.parseWithSchema(
2558
- response.data,
2559
- x402CreditPurchaseResponseSchema,
2560
- "x402 credit purchase response"
2561
- );
2562
- const responseHeaders = response.headers ?? {};
2563
- const paymentHeader = typeof responseHeaders["x-payment-response"] === "string" ? responseHeaders["x-payment-response"] : void 0;
2564
- const decodedPayment = paymentHeader !== void 0 ? decodePaymentResponse(paymentHeader) : void 0;
2565
- return {
2566
- ...parsed,
2567
- paymentResponseHeader: paymentHeader,
2568
- paymentResponse: decodedPayment
2569
- };
2570
- }
2571
- async function buyCreditsWithX402(client, params) {
2572
- const network = params.network ?? "base";
2573
- const { createX402Signer } = await loadX402Dependencies(client);
2574
- const normalizedKey = normalizeHexPrivateKey(params.evmPrivateKey);
2575
- const walletClient = await createX402Signer(network, normalizedKey);
2576
- return purchaseCreditsWithX402(client, {
2577
- accountId: params.accountId,
2578
- credits: params.credits,
2579
- usdAmount: params.usdAmount,
2580
- description: params.description,
2581
- metadata: params.metadata,
2582
- walletClient
2583
- });
2584
- }
2585
-
2586
- // ../../src/services/registry-broker/client/agents.ts
2587
- async function performRegisterAgent(client, payload) {
2588
- const raw = await client.requestJson("/register", {
2589
- method: "POST",
2590
- body: serialiseAgentRegistrationRequest(payload),
2591
- headers: { "content-type": "application/json" }
2592
- });
2593
- return client.parseWithSchema(
2594
- raw,
2595
- registerAgentResponseSchema,
2596
- "register agent response"
2597
- );
2598
- }
2599
- function calculateHbarAmount(creditsToPurchase, creditsPerHbar) {
2600
- if (creditsPerHbar <= 0) {
2601
- throw new Error("creditsPerHbar must be positive");
2294
+ if (payload.senderUaid) {
2295
+ body.senderUaid = payload.senderUaid;
2602
2296
  }
2603
- if (creditsToPurchase <= 0) {
2604
- throw new Error("creditsToPurchase must be positive");
2297
+ try {
2298
+ const raw = await client.requestJson("/chat/session", {
2299
+ method: "POST",
2300
+ body,
2301
+ headers: { "content-type": "application/json" }
2302
+ });
2303
+ return client.parseWithSchema(
2304
+ raw,
2305
+ createSessionResponseSchema,
2306
+ "chat session response"
2307
+ );
2308
+ } catch (error) {
2309
+ const maybeError = error instanceof Error ? error : null;
2310
+ if (allowHistoryAutoTopUp && client.shouldAutoTopUpHistory(payload, maybeError)) {
2311
+ await client.executeHistoryAutoTopUp("chat.session");
2312
+ return createSession(client, payload, false);
2313
+ }
2314
+ throw error;
2605
2315
  }
2606
- const rawHbar = creditsToPurchase / creditsPerHbar;
2607
- const tinybars = Math.ceil(rawHbar * 1e8);
2608
- return tinybars / 1e8;
2609
2316
  }
2610
- function resolveCreditsToPurchase(shortfallCredits) {
2611
- if (!Number.isFinite(shortfallCredits) || shortfallCredits <= 0) {
2612
- return 0;
2317
+ async function startChat(client, encryptedManager, options) {
2318
+ if ("uaid" in options && options.uaid) {
2319
+ return startConversation(client, encryptedManager, {
2320
+ uaid: options.uaid,
2321
+ senderUaid: options.senderUaid,
2322
+ historyTtlSeconds: options.historyTtlSeconds,
2323
+ auth: options.auth,
2324
+ encryption: options.encryption,
2325
+ onSessionCreated: options.onSessionCreated
2326
+ });
2613
2327
  }
2614
- return Math.max(
2615
- Math.ceil(shortfallCredits),
2616
- MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS
2617
- );
2328
+ if ("agentUrl" in options && options.agentUrl) {
2329
+ const session = await createSession(client, {
2330
+ agentUrl: options.agentUrl,
2331
+ auth: options.auth,
2332
+ historyTtlSeconds: options.historyTtlSeconds,
2333
+ senderUaid: options.senderUaid
2334
+ });
2335
+ options.onSessionCreated?.(session.sessionId);
2336
+ return createPlaintextConversationHandle(
2337
+ client,
2338
+ session.sessionId,
2339
+ session.encryption ?? null,
2340
+ options.auth,
2341
+ { agentUrl: options.agentUrl, uaid: options.uaid }
2342
+ );
2343
+ }
2344
+ throw new Error("startChat requires either uaid or agentUrl");
2618
2345
  }
2619
- async function ensureCreditsForRegistration(client, payload, autoTopUp) {
2620
- const details = autoTopUp ?? null;
2621
- if (!details) {
2622
- return;
2346
+ async function startConversation(client, encryptedManager, options) {
2347
+ const preference = options.encryption?.preference ?? "preferred";
2348
+ const requestEncryption = preference !== "disabled";
2349
+ if (!requestEncryption) {
2350
+ const session = await createSession(client, {
2351
+ uaid: options.uaid,
2352
+ auth: options.auth,
2353
+ historyTtlSeconds: options.historyTtlSeconds,
2354
+ senderUaid: options.senderUaid,
2355
+ encryptionRequested: false
2356
+ });
2357
+ options.onSessionCreated?.(session.sessionId);
2358
+ return createPlaintextConversationHandle(
2359
+ client,
2360
+ session.sessionId,
2361
+ session.encryption ?? null,
2362
+ options.auth,
2363
+ { uaid: options.uaid }
2364
+ );
2623
2365
  }
2624
- if (!details.accountId || !details.accountId.trim()) {
2625
- throw new Error("autoTopUp.accountId is required");
2366
+ try {
2367
+ const handle = await encryptedManager.startSession({
2368
+ uaid: options.uaid,
2369
+ senderUaid: options.senderUaid,
2370
+ historyTtlSeconds: options.historyTtlSeconds,
2371
+ handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
2372
+ pollIntervalMs: options.encryption?.pollIntervalMs,
2373
+ onSessionCreated: (sessionId) => {
2374
+ options.onSessionCreated?.(sessionId);
2375
+ },
2376
+ auth: options.auth
2377
+ });
2378
+ return handle;
2379
+ } catch (error) {
2380
+ if (error instanceof EncryptionUnavailableError) {
2381
+ if (preference === "required") {
2382
+ throw error;
2383
+ }
2384
+ return createPlaintextConversationHandle(
2385
+ client,
2386
+ error.sessionId,
2387
+ error.summary ?? null,
2388
+ options.auth,
2389
+ { uaid: options.uaid }
2390
+ );
2391
+ }
2392
+ throw error;
2626
2393
  }
2627
- if (!details.privateKey || !details.privateKey.trim()) {
2628
- throw new Error("autoTopUp.privateKey is required");
2394
+ }
2395
+ async function acceptConversation(client, encryptedManager, options) {
2396
+ const preference = options.encryption?.preference ?? "preferred";
2397
+ if (preference === "disabled") {
2398
+ return createPlaintextConversationHandle(client, options.sessionId, null);
2629
2399
  }
2630
- for (let attempt = 0; attempt < 3; attempt += 1) {
2631
- const quote = await getRegistrationQuote(client, payload);
2632
- const shortfall = quote.shortfallCredits ?? 0;
2633
- if (shortfall <= 0) {
2634
- return;
2635
- }
2636
- const creditsToPurchase = resolveCreditsToPurchase(shortfall);
2637
- if (creditsToPurchase <= 0) {
2638
- return;
2400
+ try {
2401
+ const handle = await encryptedManager.acceptSession({
2402
+ sessionId: options.sessionId,
2403
+ responderUaid: options.responderUaid,
2404
+ handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
2405
+ pollIntervalMs: options.encryption?.pollIntervalMs
2406
+ });
2407
+ return handle;
2408
+ } catch (error) {
2409
+ if (error instanceof EncryptionUnavailableError && preference !== "required") {
2410
+ return createPlaintextConversationHandle(
2411
+ client,
2412
+ options.sessionId,
2413
+ null,
2414
+ void 0,
2415
+ { uaid: options.responderUaid }
2416
+ );
2639
2417
  }
2640
- const creditsPerHbar = quote.creditsPerHbar ?? null;
2641
- if (!creditsPerHbar || creditsPerHbar <= 0) {
2642
- throw new Error("Unable to determine credits per HBAR for auto top-up");
2418
+ throw error;
2419
+ }
2420
+ }
2421
+ function createPlaintextConversationHandle(client, sessionId, summary, defaultAuth, context) {
2422
+ const uaid = context?.uaid?.trim();
2423
+ const agentUrl = context?.agentUrl?.trim();
2424
+ const fetchHistory = async (options) => {
2425
+ const snapshot = await client.fetchHistorySnapshot(sessionId, options);
2426
+ if (snapshot.decryptedHistory) {
2427
+ return snapshot.decryptedHistory;
2643
2428
  }
2644
- const hbarAmount = calculateHbarAmount(creditsToPurchase, creditsPerHbar);
2645
- await purchaseCreditsWithHbar(client, {
2646
- accountId: details.accountId.trim(),
2647
- privateKey: details.privateKey.trim(),
2648
- hbarAmount,
2649
- memo: details.memo ?? "Registry Broker auto top-up",
2650
- metadata: {
2651
- shortfallCredits: shortfall,
2652
- requiredCredits: quote.requiredCredits,
2653
- purchasedCredits: creditsToPurchase
2429
+ return snapshot.history.map((entry) => ({
2430
+ entry,
2431
+ plaintext: entry.content
2432
+ }));
2433
+ };
2434
+ return {
2435
+ sessionId,
2436
+ mode: "plaintext",
2437
+ summary: summary ?? null,
2438
+ send: async (options) => {
2439
+ const plaintext = options.plaintext;
2440
+ if (!plaintext || plaintext.trim().length === 0) {
2441
+ throw new Error("plaintext is required for chat messages");
2654
2442
  }
2655
- });
2443
+ const message = options.message ?? plaintext;
2444
+ return sendMessage(client, {
2445
+ sessionId,
2446
+ message,
2447
+ streaming: options.streaming,
2448
+ auth: options.auth ?? defaultAuth,
2449
+ uaid,
2450
+ agentUrl
2451
+ });
2452
+ },
2453
+ decryptHistoryEntry: (entry) => entry.content,
2454
+ fetchHistory
2455
+ };
2456
+ }
2457
+ async function compactHistory(client, payload) {
2458
+ if (!payload.sessionId || payload.sessionId.trim().length === 0) {
2459
+ throw new Error("sessionId is required to compact chat history");
2656
2460
  }
2657
- const finalQuote = await getRegistrationQuote(client, payload);
2658
- if ((finalQuote.shortfallCredits ?? 0) > 0) {
2659
- throw new Error("Unable to purchase sufficient credits for registration");
2461
+ const body = {};
2462
+ if (typeof payload.preserveEntries === "number" && Number.isFinite(payload.preserveEntries) && payload.preserveEntries >= 0) {
2463
+ body.preserveEntries = Math.floor(payload.preserveEntries);
2660
2464
  }
2661
- }
2662
- async function resolveUaid(client, uaid) {
2663
2465
  const raw = await client.requestJson(
2664
- `/resolve/${encodeURIComponent(uaid)}`,
2466
+ `/chat/session/${encodeURIComponent(payload.sessionId)}/compact`,
2665
2467
  {
2666
- method: "GET"
2468
+ method: "POST",
2469
+ headers: { "content-type": "application/json" },
2470
+ body
2667
2471
  }
2668
2472
  );
2669
2473
  return client.parseWithSchema(
2670
2474
  raw,
2671
- resolveResponseSchema,
2672
- "resolve UAID response"
2475
+ chatHistoryCompactionResponseSchema,
2476
+ "chat history compaction response"
2673
2477
  );
2674
2478
  }
2675
- async function registerAgent(client, payload, options) {
2676
- const autoTopUp = options?.autoTopUp ?? client.registrationAutoTopUp;
2677
- if (!autoTopUp) {
2678
- return performRegisterAgent(client, payload);
2479
+ async function fetchEncryptionStatus(client, sessionId) {
2480
+ if (!sessionId || sessionId.trim().length === 0) {
2481
+ throw new Error("sessionId is required for encryption status");
2679
2482
  }
2680
- await ensureCreditsForRegistration(client, payload, autoTopUp);
2681
- let retried = false;
2682
- while (true) {
2683
- try {
2684
- return await performRegisterAgent(client, payload);
2685
- } catch (error) {
2686
- const shortfall = client.extractInsufficientCreditsDetails(error);
2687
- if (shortfall && !retried) {
2688
- await ensureCreditsForRegistration(client, payload, autoTopUp);
2689
- retried = true;
2690
- continue;
2691
- }
2692
- throw error;
2483
+ const raw = await client.requestJson(
2484
+ `/chat/session/${encodeURIComponent(sessionId)}/encryption`,
2485
+ {
2486
+ method: "GET"
2693
2487
  }
2694
- }
2695
- }
2696
- async function getRegistrationQuote(client, payload) {
2697
- const raw = await client.requestJson("/register/quote", {
2698
- method: "POST",
2699
- body: serialiseAgentRegistrationRequest(payload),
2700
- headers: { "content-type": "application/json" }
2701
- });
2488
+ );
2702
2489
  return client.parseWithSchema(
2703
2490
  raw,
2704
- registrationQuoteResponseSchema,
2705
- "registration quote response"
2491
+ sessionEncryptionStatusResponseSchema,
2492
+ "session encryption status response"
2706
2493
  );
2707
2494
  }
2708
- async function updateAgent(client, uaid, payload) {
2495
+ async function postEncryptionHandshake(client, sessionId, payload) {
2496
+ if (!sessionId || sessionId.trim().length === 0) {
2497
+ throw new Error("sessionId is required for encryption handshake");
2498
+ }
2709
2499
  const raw = await client.requestJson(
2710
- `/register/${encodeURIComponent(uaid)}`,
2500
+ `/chat/session/${encodeURIComponent(sessionId)}/encryption-handshake`,
2711
2501
  {
2712
- method: "PUT",
2713
- body: serialiseAgentRegistrationRequest(payload),
2714
- headers: { "content-type": "application/json" }
2502
+ method: "POST",
2503
+ headers: { "content-type": "application/json" },
2504
+ body: {
2505
+ role: payload.role,
2506
+ keyType: payload.keyType,
2507
+ ephemeralPublicKey: payload.ephemeralPublicKey,
2508
+ longTermPublicKey: payload.longTermPublicKey,
2509
+ signature: payload.signature,
2510
+ uaid: payload.uaid,
2511
+ userId: payload.userId,
2512
+ ledgerAccountId: payload.ledgerAccountId,
2513
+ metadata: payload.metadata
2514
+ }
2715
2515
  }
2716
2516
  );
2717
- return client.parseWithSchema(
2517
+ const response = client.parseWithSchema(
2718
2518
  raw,
2719
- registerAgentResponseSchema,
2720
- "update agent response"
2519
+ encryptionHandshakeResponseSchema,
2520
+ "encryption handshake response"
2721
2521
  );
2522
+ return response.handshake;
2722
2523
  }
2723
- async function getRegistrationProgress(client, attemptId) {
2724
- const normalisedAttemptId = attemptId.trim();
2725
- if (!normalisedAttemptId) {
2726
- throw new Error("attemptId is required");
2524
+ async function sendMessage(client, payload) {
2525
+ const body = {
2526
+ message: payload.message
2527
+ };
2528
+ if (payload.streaming !== void 0) {
2529
+ body.streaming = payload.streaming;
2727
2530
  }
2728
- try {
2729
- const raw = await client.requestJson(
2730
- `/register/progress/${encodeURIComponent(normalisedAttemptId)}`,
2731
- { method: "GET" }
2732
- );
2733
- const parsed = client.parseWithSchema(
2734
- raw,
2735
- registrationProgressResponseSchema,
2736
- "registration progress response"
2737
- );
2738
- return parsed.progress;
2739
- } catch (error) {
2740
- if (error instanceof RegistryBrokerError && error.status === 404) {
2741
- return null;
2742
- }
2743
- throw error;
2531
+ if (payload.auth) {
2532
+ body.auth = serialiseAuthConfig(payload.auth);
2744
2533
  }
2745
- }
2746
- async function waitForRegistrationCompletion(client, attemptId, options = {}) {
2747
- const normalisedAttemptId = attemptId.trim();
2748
- if (!normalisedAttemptId) {
2749
- throw new Error("attemptId is required");
2534
+ if ("uaid" in payload) {
2535
+ body.uaid = payload.uaid;
2750
2536
  }
2751
- const interval = Math.max(
2752
- 250,
2753
- options.intervalMs ?? DEFAULT_PROGRESS_INTERVAL_MS
2754
- );
2755
- const timeoutMs = options.timeoutMs ?? DEFAULT_PROGRESS_TIMEOUT_MS;
2756
- const throwOnFailure = options.throwOnFailure ?? true;
2757
- const signal = options.signal;
2758
- const startedAt = Date.now();
2759
- while (true) {
2760
- if (signal?.aborted) {
2761
- throw createAbortError();
2762
- }
2763
- const progress = await client.getRegistrationProgress(normalisedAttemptId);
2764
- if (progress) {
2765
- options.onProgress?.(progress);
2766
- if (progress.status === "completed") {
2767
- return progress;
2768
- }
2769
- if (progress.status === "partial" || progress.status === "failed") {
2770
- if (throwOnFailure) {
2771
- throw new RegistryBrokerError(
2772
- "Registration did not complete successfully",
2773
- {
2774
- status: 409,
2775
- statusText: progress.status,
2776
- body: progress
2777
- }
2778
- );
2779
- }
2780
- return progress;
2781
- }
2782
- }
2783
- if (Date.now() - startedAt >= timeoutMs) {
2537
+ if ("sessionId" in payload && payload.sessionId) {
2538
+ body.sessionId = payload.sessionId;
2539
+ }
2540
+ if ("agentUrl" in payload && payload.agentUrl) {
2541
+ body.agentUrl = payload.agentUrl;
2542
+ }
2543
+ let cipherEnvelope = payload.cipherEnvelope ?? null;
2544
+ if (payload.encryption) {
2545
+ const sessionIdForEncryption = payload.encryption.sessionId ?? (typeof body.sessionId === "string" ? body.sessionId : void 0);
2546
+ if (!sessionIdForEncryption) {
2784
2547
  throw new Error(
2785
- `Registration progress polling timed out after ${timeoutMs}ms`
2548
+ "sessionId is required when using encrypted chat payloads"
2786
2549
  );
2787
2550
  }
2788
- await client.delay(interval, signal);
2789
- }
2790
- }
2791
- async function validateUaid(client, uaid) {
2792
- const raw = await client.requestJson(
2793
- `/uaids/validate/${encodeURIComponent(uaid)}`,
2794
- {
2795
- method: "GET"
2796
- }
2797
- );
2798
- return client.parseWithSchema(
2799
- raw,
2800
- uaidValidationResponseSchema,
2801
- "UAID validation response"
2802
- );
2803
- }
2804
- async function getUaidConnectionStatus(client, uaid) {
2805
- const raw = await client.requestJson(
2806
- `/uaids/connections/${encodeURIComponent(uaid)}/status`,
2807
- {
2808
- method: "GET"
2551
+ if (!payload.encryption.recipients?.length) {
2552
+ throw new Error("recipients are required for encrypted chat payloads");
2809
2553
  }
2810
- );
2554
+ cipherEnvelope = client.encryption.encryptCipherEnvelope({
2555
+ ...payload.encryption,
2556
+ sessionId: sessionIdForEncryption
2557
+ });
2558
+ }
2559
+ if (cipherEnvelope) {
2560
+ body.cipherEnvelope = toJsonObject(cipherEnvelope);
2561
+ }
2562
+ const raw = await client.requestJson("/chat/message", {
2563
+ method: "POST",
2564
+ body,
2565
+ headers: { "content-type": "application/json" }
2566
+ });
2811
2567
  return client.parseWithSchema(
2812
2568
  raw,
2813
- uaidConnectionStatusSchema,
2814
- "UAID connection status"
2569
+ sendMessageResponseSchema,
2570
+ "chat message response"
2815
2571
  );
2816
2572
  }
2817
- async function closeUaidConnection(client, uaid) {
2818
- await client.request(`/uaids/connections/${encodeURIComponent(uaid)}`, {
2573
+ async function endSession(client, sessionId) {
2574
+ await client.request(`/chat/session/${encodeURIComponent(sessionId)}`, {
2819
2575
  method: "DELETE"
2820
2576
  });
2821
2577
  }
2822
- async function dashboardStats(client) {
2823
- const raw = await client.requestJson("/dashboard/stats", {
2824
- method: "GET"
2825
- });
2826
- return client.parseWithSchema(
2827
- raw,
2828
- dashboardStatsResponseSchema,
2829
- "dashboard stats response"
2830
- );
2831
- }
2832
2578
 
2833
- // ../../src/services/registry-broker/client/ledger-auth.ts
2579
+ // ../../src/services/registry-broker/client/encryption.ts
2834
2580
  var import_buffer2 = require("buffer");
2581
+ var import_secp256k1 = require("@noble/curves/secp256k1.js");
2835
2582
 
2836
- // ../../src/services/registry-broker/ledger-network.ts
2837
- var normalise = (value) => value.trim().toLowerCase();
2838
- var HEDERA_NETWORK_ALIASES = /* @__PURE__ */ new Map([
2839
- ["hedera:mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
2840
- ["mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
2841
- ["hedera-mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
2842
- ["hedera_mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
2843
- ["hedera:testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
2844
- ["testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
2845
- ["hedera-testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
2846
- ["hedera_testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }]
2847
- ]);
2848
- var EVM_NETWORK_CHAIN_IDS = {
2849
- abstract: 2741,
2850
- "abstract-testnet": 11124,
2851
- base: 8453,
2852
- "base-sepolia": 84532,
2853
- avalanche: 43114,
2854
- "avalanche-fuji": 43113,
2855
- iotex: 4689,
2856
- sei: 1329,
2857
- "sei-testnet": 1328,
2858
- polygon: 137,
2859
- "polygon-amoy": 80002,
2860
- peaq: 3338
2861
- };
2862
- var CHAIN_ID_TO_ALIAS = new Map(
2863
- Object.entries(EVM_NETWORK_CHAIN_IDS).map(([alias, id]) => [id, alias])
2864
- );
2865
- var parseChainId = (value) => {
2866
- if (/^eip155:\d+$/i.test(value)) {
2867
- return Number.parseInt(value.split(":")[1], 10);
2868
- }
2869
- if (/^\d+$/.test(value)) {
2870
- return Number.parseInt(value, 10);
2871
- }
2872
- return void 0;
2873
- };
2874
- var normaliseEvmNetwork = (value) => {
2875
- const trimmed = normalise(value);
2876
- let chainId = parseChainId(trimmed);
2877
- let alias;
2878
- if (chainId === void 0) {
2879
- const mapped = EVM_NETWORK_CHAIN_IDS[trimmed];
2880
- if (mapped !== void 0) {
2881
- chainId = mapped;
2882
- alias = trimmed;
2583
+ // ../../src/utils/is-browser.ts
2584
+ var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
2585
+
2586
+ // ../../src/utils/dynamic-import.ts
2587
+ var import_meta = {};
2588
+ var nodeRequire;
2589
+ var isNodeRuntime = () => typeof process !== "undefined" && Boolean(process.versions?.node);
2590
+ function getNodeRequireSync() {
2591
+ try {
2592
+ const moduleNamespace = process.getBuiltinModule?.("module");
2593
+ if (typeof moduleNamespace?.createRequire === "function") {
2594
+ const requireFromModule = moduleNamespace.createRequire(import_meta.url);
2595
+ if (typeof requireFromModule.resolve === "function") {
2596
+ return requireFromModule;
2597
+ }
2883
2598
  }
2884
- } else if (CHAIN_ID_TO_ALIAS.has(chainId)) {
2885
- alias = CHAIN_ID_TO_ALIAS.get(chainId);
2886
- }
2887
- if (chainId === void 0) {
2888
- throw new Error(
2889
- 'Unsupported EVM ledger network. Provide an alias like "base-sepolia" or a canonical eip155:<chainId> string.'
2890
- );
2891
- }
2892
- return {
2893
- canonical: `eip155:${chainId}`,
2894
- kind: "evm",
2895
- chainId,
2896
- legacyName: alias
2897
- };
2898
- };
2899
- var normaliseHederaNetwork = (value) => {
2900
- const trimmed = normalise(value);
2901
- const mapping = HEDERA_NETWORK_ALIASES.get(trimmed);
2902
- if (!mapping) {
2903
- throw new Error(
2904
- 'Unsupported Hedera network. Use hedera:mainnet or hedera:testnet (legacy "mainnet"/"testnet" also accepted).'
2905
- );
2906
- }
2907
- return {
2908
- canonical: mapping.canonical,
2909
- kind: "hedera",
2910
- hederaNetwork: mapping.hederaNetwork
2911
- };
2912
- };
2913
- var canonicalizeLedgerNetwork = (network) => {
2914
- if (typeof network !== "string" || network.trim().length === 0) {
2915
- throw new Error("Ledger network is required.");
2916
- }
2917
- const trimmed = normalise(network);
2918
- if (trimmed.startsWith("hedera:") || trimmed.includes("hedera-") || trimmed.includes("hedera_") || trimmed === "mainnet" || trimmed === "testnet") {
2919
- return normaliseHederaNetwork(trimmed);
2599
+ const globalObject = typeof global !== "undefined" ? global : globalThis;
2600
+ const runtimeRequire = globalObject.process?.mainModule?.require ?? globalObject.require ?? Function('return typeof require === "function" ? require : undefined;')();
2601
+ if (typeof runtimeRequire === "function" && typeof runtimeRequire.resolve === "function") {
2602
+ return runtimeRequire;
2603
+ }
2604
+ } catch {
2605
+ return null;
2920
2606
  }
2921
- return normaliseEvmNetwork(trimmed);
2922
- };
2923
-
2924
- // ../../src/services/registry-broker/private-key-signer.ts
2925
- var unsupported = (method) => new Error(`${method} is not supported by the in-memory signer`);
2926
- var cachedSdk = null;
2927
- var loadHashgraphSdk = () => {
2928
- if (cachedSdk) {
2929
- return cachedSdk;
2607
+ return null;
2608
+ }
2609
+ function isModuleNotFound(specifier, error) {
2610
+ if (!error || typeof error !== "object") {
2611
+ return false;
2930
2612
  }
2931
- const resolved = optionalImportSync("@hashgraph/sdk");
2932
- if (resolved) {
2933
- cachedSdk = resolved;
2934
- return resolved;
2613
+ const code = Reflect.get(error, "code");
2614
+ const message = Reflect.get(error, "message");
2615
+ const messageText = typeof message === "string" ? message : "";
2616
+ if (typeof code === "string" && code.includes("MODULE_NOT_FOUND")) {
2617
+ return messageText.includes(specifier);
2935
2618
  }
2936
- const message = "@hashgraph/sdk is required for ledger signing. Install it as a dependency to enable createPrivateKeySigner.";
2937
- throw new Error(message);
2938
- };
2939
- var loadHashgraphSdkAsync = async () => {
2940
- if (cachedSdk) {
2941
- return cachedSdk;
2619
+ if (messageText) {
2620
+ const lowered = messageText.toLowerCase();
2621
+ if (lowered.includes("cannot find module") || lowered.includes("module not found") || lowered.includes("cannot find package")) {
2622
+ return lowered.includes(specifier.toLowerCase());
2623
+ }
2942
2624
  }
2943
- const resolved = await optionalImport("@hashgraph/sdk");
2944
- if (resolved) {
2945
- cachedSdk = resolved;
2946
- return resolved;
2625
+ return false;
2626
+ }
2627
+ async function resolveNodeRequire() {
2628
+ if (nodeRequire !== void 0) {
2629
+ return nodeRequire;
2947
2630
  }
2948
- const message = "@hashgraph/sdk is required for ledger signing. Install it as a dependency to enable createPrivateKeySigner.";
2949
- throw new Error(message);
2950
- };
2951
- var buildSigner = (sdk, options) => {
2952
- const { AccountId, LedgerId, PrivateKey, SignerSignature } = sdk;
2953
- if (!options.privateKey) {
2954
- throw new Error("privateKey is required to create a ledger signer.");
2631
+ if (isBrowser && !isNodeRuntime()) {
2632
+ nodeRequire = null;
2633
+ return nodeRequire;
2955
2634
  }
2956
- if (!options.accountId) {
2957
- throw new Error("accountId is required to create a ledger signer.");
2635
+ try {
2636
+ nodeRequire = getNodeRequireSync();
2637
+ } catch {
2638
+ nodeRequire = null;
2958
2639
  }
2959
- const accountId = AccountId.fromString(options.accountId);
2960
- const privateKey = PrivateKey.fromString(options.privateKey);
2961
- const ledgerId = LedgerId.fromString(options.network);
2962
- return {
2963
- getLedgerId: () => ledgerId,
2964
- getAccountId: () => accountId,
2965
- getAccountKey: () => privateKey.publicKey,
2966
- getNetwork: () => ({}),
2967
- getMirrorNetwork: () => [],
2968
- sign: async (messages) => Promise.all(
2969
- messages.map(async (message) => {
2970
- const signature = await privateKey.sign(message);
2971
- return new SignerSignature({
2972
- publicKey: privateKey.publicKey,
2973
- signature,
2974
- accountId
2975
- });
2976
- })
2977
- ),
2978
- getAccountBalance: async () => {
2979
- throw unsupported("getAccountBalance");
2980
- },
2981
- getAccountInfo: async () => {
2982
- throw unsupported("getAccountInfo");
2983
- },
2984
- getAccountRecords: async () => {
2985
- throw unsupported("getAccountRecords");
2986
- },
2987
- signTransaction: async (_) => {
2988
- throw unsupported("signTransaction");
2989
- },
2990
- checkTransaction: async (_) => {
2991
- throw unsupported("checkTransaction");
2992
- },
2993
- populateTransaction: async (_) => {
2994
- throw unsupported("populateTransaction");
2995
- },
2996
- call: async (_request) => {
2997
- throw unsupported("call");
2998
- }
2999
- };
3000
- };
3001
- var createPrivateKeySigner = (options) => buildSigner(loadHashgraphSdk(), options);
3002
- var createPrivateKeySignerAsync = async (options) => buildSigner(await loadHashgraphSdkAsync(), options);
3003
-
3004
- // ../../src/services/registry-broker/client/ledger-auth.ts
3005
- async function loadViemAccount(privateKey) {
2640
+ return nodeRequire;
2641
+ }
2642
+ async function dynamicImport(specifier) {
3006
2643
  try {
3007
- const viem = await import("viem/accounts");
3008
- return viem.privateKeyToAccount(privateKey);
3009
- } catch (error) {
3010
- const err = new Error(
3011
- 'EVM ledger authentication requires the optional dependency "viem". Install it to use evmPrivateKey flows.'
2644
+ return await import(
2645
+ /* webpackIgnore: true */
2646
+ specifier
3012
2647
  );
3013
- err.cause = error;
3014
- throw err;
2648
+ } catch (error) {
2649
+ if (isModuleNotFound(specifier, error)) {
2650
+ return null;
2651
+ }
2652
+ throw error;
2653
+ }
2654
+ }
2655
+ async function optionalImport(specifier, options = {}) {
2656
+ if (isBrowser && !isNodeRuntime()) {
2657
+ return dynamicImport(specifier);
2658
+ }
2659
+ if (!options.preferImport) {
2660
+ const requireFn = await resolveNodeRequire();
2661
+ if (requireFn) {
2662
+ try {
2663
+ return requireFn(specifier);
2664
+ } catch (error) {
2665
+ if (!isModuleNotFound(specifier, error)) {
2666
+ throw error;
2667
+ }
2668
+ }
2669
+ }
3015
2670
  }
2671
+ return dynamicImport(specifier);
3016
2672
  }
3017
- async function resolveLedgerAuthSignature(message, options) {
3018
- if (typeof options.sign === "function") {
3019
- const result = await options.sign(message);
3020
- if (!result || typeof result.signature !== "string" || result.signature.length === 0) {
3021
- throw new Error("Custom ledger signer failed to produce a signature.");
2673
+ function optionalImportSync(specifier) {
2674
+ if (isBrowser && !isNodeRuntime()) {
2675
+ return null;
2676
+ }
2677
+ try {
2678
+ const requireFn = getNodeRequireSync();
2679
+ if (requireFn) {
2680
+ return requireFn(specifier);
2681
+ }
2682
+ } catch (error) {
2683
+ if (!isModuleNotFound(specifier, error)) {
2684
+ throw error;
3022
2685
  }
3023
- return result;
3024
2686
  }
3025
- if (!options.signer || typeof options.signer.sign !== "function") {
3026
- throw new Error(
3027
- "Ledger authentication requires a Hedera Signer or custom sign function."
3028
- );
2687
+ return null;
2688
+ }
2689
+
2690
+ // ../../src/services/registry-broker/client/encryption.ts
2691
+ var getFs = async () => {
2692
+ const fsModule = await optionalImport("node:fs") ?? await optionalImport("fs");
2693
+ if (fsModule && typeof fsModule.existsSync === "function" && typeof fsModule.readFileSync === "function" && typeof fsModule.writeFileSync === "function" && typeof fsModule.appendFileSync === "function") {
2694
+ return fsModule;
3029
2695
  }
3030
- const payload = import_buffer2.Buffer.from(message, "utf8");
3031
- const signatures = await options.signer.sign([payload]);
3032
- const signatureEntry = signatures?.[0];
3033
- if (!signatureEntry) {
3034
- throw new Error("Signer did not return any signatures.");
2696
+ return null;
2697
+ };
2698
+ var getNodePath = async () => {
2699
+ const pathModule = await optionalImport("node:path") ?? await optionalImport("path");
2700
+ if (pathModule && typeof pathModule.resolve === "function") {
2701
+ return pathModule;
3035
2702
  }
3036
- let derivedPublicKey;
3037
- if (signatureEntry.publicKey) {
3038
- derivedPublicKey = signatureEntry.publicKey.toString();
3039
- } else if (typeof options.signer.getAccountKey === "function") {
3040
- const accountKey = await options.signer.getAccountKey();
3041
- if (accountKey && typeof accountKey.toString === "function") {
3042
- derivedPublicKey = accountKey.toString();
3043
- }
2703
+ return null;
2704
+ };
2705
+ var getNodeCrypto = async () => {
2706
+ const cryptoModule = await optionalImport("node:crypto") ?? await optionalImport("crypto");
2707
+ if (cryptoModule && typeof cryptoModule.randomBytes === "function") {
2708
+ return cryptoModule;
3044
2709
  }
3045
- return {
3046
- signature: import_buffer2.Buffer.from(signatureEntry.signature).toString("base64"),
3047
- signatureKind: "raw",
3048
- publicKey: derivedPublicKey
3049
- };
3050
- }
3051
- async function createLedgerChallenge(client, payload) {
3052
- const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
3053
- const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
3054
- const raw = await client.requestJson("/auth/ledger/challenge", {
2710
+ return null;
2711
+ };
2712
+ async function registerEncryptionKey(client, payload) {
2713
+ const raw = await client.requestJson("/encryption/keys", {
3055
2714
  method: "POST",
3056
2715
  headers: { "content-type": "application/json" },
3057
- body: {
3058
- accountId: payload.accountId,
3059
- network
3060
- }
2716
+ body: payload
3061
2717
  });
3062
2718
  return client.parseWithSchema(
3063
2719
  raw,
3064
- ledgerChallengeResponseSchema,
3065
- "ledger challenge response"
2720
+ registerEncryptionKeyResponseSchema,
2721
+ "register encryption key response"
3066
2722
  );
3067
2723
  }
3068
- async function verifyLedgerChallenge(client, payload) {
3069
- const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
3070
- const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
3071
- const body = {
3072
- challengeId: payload.challengeId,
3073
- accountId: payload.accountId,
3074
- network,
3075
- signature: payload.signature
3076
- };
3077
- if (payload.signatureKind) {
3078
- body.signatureKind = payload.signatureKind;
2724
+ function normalizeAutoRegisterIdentity(config) {
2725
+ const identity = {};
2726
+ if (config.uaid) {
2727
+ identity.uaid = config.uaid;
3079
2728
  }
3080
- if (payload.publicKey) {
3081
- body.publicKey = payload.publicKey;
2729
+ if (config.ledgerAccountId) {
2730
+ identity.ledgerAccountId = config.ledgerAccountId;
2731
+ if (config.ledgerNetwork) {
2732
+ identity.ledgerNetwork = config.ledgerNetwork;
2733
+ }
3082
2734
  }
3083
- if (typeof payload.expiresInMinutes === "number") {
3084
- body.expiresInMinutes = payload.expiresInMinutes;
2735
+ if (config.email) {
2736
+ identity.email = config.email;
3085
2737
  }
3086
- const raw = await client.requestJson("/auth/ledger/verify", {
3087
- method: "POST",
3088
- headers: { "content-type": "application/json" },
3089
- body
3090
- });
3091
- const result = client.parseWithSchema(
3092
- raw,
3093
- ledgerVerifyResponseSchema,
3094
- "ledger verification response"
3095
- );
3096
- client.setLedgerApiKey(result.key);
3097
- return result;
2738
+ if (identity.uaid || identity.ledgerAccountId || identity.email) {
2739
+ return identity;
2740
+ }
2741
+ return null;
3098
2742
  }
3099
- async function authenticateWithLedger(client, options) {
3100
- const challenge = await client.createLedgerChallenge({
3101
- accountId: options.accountId,
3102
- network: options.network
2743
+ function derivePublicKeyFromPrivateKey(client, privateKey) {
2744
+ const normalized = client.hexToBuffer(privateKey);
2745
+ const publicKey = import_secp256k1.secp256k1.getPublicKey(normalized, true);
2746
+ return import_buffer2.Buffer.from(publicKey).toString("hex");
2747
+ }
2748
+ async function resolveAutoRegisterKeyMaterial(client, config) {
2749
+ if (config.publicKey?.trim()) {
2750
+ return { publicKey: config.publicKey.trim() };
2751
+ }
2752
+ let privateKey = config.privateKey?.trim();
2753
+ const envVar = config.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
2754
+ if (!privateKey && envVar && process?.env?.[envVar]?.trim()) {
2755
+ privateKey = process.env[envVar]?.trim();
2756
+ }
2757
+ if (!privateKey && config.generateIfMissing) {
2758
+ const pair = await client.generateEncryptionKeyPair({
2759
+ keyType: config.keyType ?? "secp256k1",
2760
+ envVar,
2761
+ envPath: config.envPath,
2762
+ overwrite: config.overwriteEnv
2763
+ });
2764
+ return { publicKey: pair.publicKey, privateKey: pair.privateKey };
2765
+ }
2766
+ if (privateKey) {
2767
+ const publicKey = derivePublicKeyFromPrivateKey(client, privateKey);
2768
+ return { publicKey, privateKey };
2769
+ }
2770
+ return null;
2771
+ }
2772
+ async function autoRegisterEncryptionKey(client, config) {
2773
+ const identity = normalizeAutoRegisterIdentity(config);
2774
+ if (!identity) {
2775
+ throw new Error(
2776
+ "Auto-registration requires uaid, ledgerAccountId, or email"
2777
+ );
2778
+ }
2779
+ const material = await resolveAutoRegisterKeyMaterial(client, config);
2780
+ if (!material) {
2781
+ throw new Error(
2782
+ "Unable to resolve encryption public key for auto-registration"
2783
+ );
2784
+ }
2785
+ await registerEncryptionKey(client, {
2786
+ keyType: config.keyType ?? "secp256k1",
2787
+ publicKey: material.publicKey,
2788
+ ...identity
3103
2789
  });
3104
- const signed = await resolveLedgerAuthSignature(challenge.message, options);
3105
- const verification = await client.verifyLedgerChallenge({
3106
- challengeId: challenge.challengeId,
3107
- accountId: options.accountId,
3108
- network: options.network,
3109
- signature: signed.signature,
3110
- signatureKind: signed.signatureKind,
3111
- publicKey: signed.publicKey,
3112
- expiresInMinutes: options.expiresInMinutes
2790
+ return material;
2791
+ }
2792
+ async function ensureAgentEncryptionKey(client, options) {
2793
+ return autoRegisterEncryptionKey(client, {
2794
+ ...options,
2795
+ uaid: options.uaid,
2796
+ enabled: true
3113
2797
  });
3114
- return verification;
3115
2798
  }
3116
- async function authenticateWithLedgerCredentials(client, options) {
3117
- const {
3118
- accountId,
3119
- network,
3120
- signer,
3121
- sign,
3122
- hederaPrivateKey,
3123
- evmPrivateKey,
3124
- expiresInMinutes,
3125
- setAccountHeader = true,
3126
- label,
3127
- logger
3128
- } = options;
3129
- const resolvedNetwork = canonicalizeLedgerNetwork(network);
3130
- const labelSuffix = label ? ` for ${label}` : "";
3131
- const networkPayload = resolvedNetwork.canonical;
3132
- const authOptions = {
3133
- accountId,
3134
- network: networkPayload,
3135
- expiresInMinutes
2799
+ function createEncryptionApi(client) {
2800
+ return {
2801
+ registerKey: (payload) => registerEncryptionKey(client, payload),
2802
+ generateEphemeralKeyPair: () => client.createEphemeralKeyPair(),
2803
+ deriveSharedSecret: (options) => client.deriveSharedSecret(options),
2804
+ encryptCipherEnvelope: (options) => client.buildCipherEnvelope(options),
2805
+ decryptCipherEnvelope: (options) => client.openCipherEnvelope(options),
2806
+ ensureAgentKey: (options) => ensureAgentEncryptionKey(client, options)
3136
2807
  };
3137
- if (sign) {
3138
- authOptions.sign = sign;
3139
- } else if (signer) {
3140
- authOptions.signer = signer;
3141
- } else if (hederaPrivateKey) {
3142
- if (resolvedNetwork.kind !== "hedera" || !resolvedNetwork.hederaNetwork) {
2808
+ }
2809
+ async function bootstrapEncryptionOptions(client, options) {
2810
+ if (!options?.autoRegister || options.autoRegister.enabled === false) {
2811
+ return null;
2812
+ }
2813
+ return autoRegisterEncryptionKey(client, options.autoRegister);
2814
+ }
2815
+ async function generateEncryptionKeyPair(client, options = {}) {
2816
+ client.assertNodeRuntime("generateEncryptionKeyPair");
2817
+ const keyType = options.keyType ?? "secp256k1";
2818
+ if (keyType !== "secp256k1") {
2819
+ throw new Error("Only secp256k1 key generation is supported currently");
2820
+ }
2821
+ const cryptoModule = await getNodeCrypto();
2822
+ if (!cryptoModule) {
2823
+ throw new Error(
2824
+ "Node.js crypto module is not available; cannot generate encryption key pair"
2825
+ );
2826
+ }
2827
+ const privateKeyBytes = cryptoModule.randomBytes(32);
2828
+ const privateKey = import_buffer2.Buffer.from(privateKeyBytes).toString("hex");
2829
+ const publicKeyBytes = import_secp256k1.secp256k1.getPublicKey(privateKeyBytes, true);
2830
+ const publicKey = import_buffer2.Buffer.from(publicKeyBytes).toString("hex");
2831
+ const envVar = options.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
2832
+ const pathModule = options.envPath ? await getNodePath() : null;
2833
+ const resolvedPath = options.envPath && pathModule ? pathModule.resolve(options.envPath) : void 0;
2834
+ if (options.envPath && !resolvedPath) {
2835
+ throw new Error(
2836
+ "Node.js path module is not available; cannot resolve encryption key env path"
2837
+ );
2838
+ }
2839
+ if (resolvedPath) {
2840
+ const fsModule = await getFs();
2841
+ if (!fsModule) {
3143
2842
  throw new Error(
3144
- "hederaPrivateKey can only be used with hedera:mainnet or hedera:testnet networks."
2843
+ "File system module is not available; cannot write encryption key env file"
3145
2844
  );
3146
2845
  }
3147
- authOptions.signer = await createPrivateKeySignerAsync({
3148
- accountId,
3149
- privateKey: hederaPrivateKey,
3150
- network: resolvedNetwork.hederaNetwork
3151
- });
3152
- } else if (evmPrivateKey) {
3153
- if (resolvedNetwork.kind !== "evm") {
3154
- throw new Error(
3155
- "evmPrivateKey can only be used with CAIP-2 EVM networks (eip155:<chainId>)."
3156
- );
2846
+ const envLine = `${envVar}=${privateKey}`;
2847
+ if (fsModule.existsSync(resolvedPath)) {
2848
+ const content = fsModule.readFileSync(resolvedPath, "utf-8");
2849
+ const lineRegex = new RegExp(`^${envVar}=.*$`, "m");
2850
+ if (lineRegex.test(content)) {
2851
+ if (!options.overwrite) {
2852
+ throw new Error(
2853
+ `${envVar} already exists in ${resolvedPath}; set overwrite=true to replace it`
2854
+ );
2855
+ }
2856
+ const updated = content.replace(lineRegex, envLine);
2857
+ fsModule.writeFileSync(resolvedPath, updated);
2858
+ } else {
2859
+ const needsNewline = !content.endsWith("\n");
2860
+ fsModule.appendFileSync(
2861
+ resolvedPath,
2862
+ `${needsNewline ? "\n" : ""}${envLine}
2863
+ `
2864
+ );
2865
+ }
2866
+ } else {
2867
+ fsModule.writeFileSync(resolvedPath, `${envLine}
2868
+ `);
3157
2869
  }
3158
- const formattedKey = evmPrivateKey.startsWith("0x") ? evmPrivateKey : `0x${evmPrivateKey}`;
3159
- const account = await loadViemAccount(formattedKey);
3160
- authOptions.sign = async (message) => ({
3161
- signature: await account.signMessage({ message }),
3162
- signatureKind: "evm",
3163
- publicKey: account.publicKey
3164
- });
3165
- } else {
3166
- throw new Error(
3167
- "Provide a signer, sign function, hederaPrivateKey, or evmPrivateKey to authenticate with the ledger."
3168
- );
3169
2870
  }
3170
- logger?.info?.(
3171
- `Authenticating ledger account ${accountId} (${resolvedNetwork.canonical})${labelSuffix}...`
2871
+ return {
2872
+ privateKey,
2873
+ publicKey,
2874
+ envPath: resolvedPath,
2875
+ envVar
2876
+ };
2877
+ }
2878
+
2879
+ // ../../src/services/registry-broker/client/adapters.ts
2880
+ async function adapters(client) {
2881
+ const raw = await client.requestJson("/adapters", {
2882
+ method: "GET"
2883
+ });
2884
+ return client.parseWithSchema(
2885
+ raw,
2886
+ adaptersResponseSchema,
2887
+ "adapters response"
3172
2888
  );
3173
- const verification = await client.authenticateWithLedger(authOptions);
3174
- if (setAccountHeader) {
3175
- client.setDefaultHeader("x-account-id", verification.accountId);
3176
- }
3177
- logger?.info?.(
3178
- `Ledger authentication complete${labelSuffix}. Issued key prefix: ${verification.apiKey.prefix}\u2026${verification.apiKey.lastFour}`
2889
+ }
2890
+ async function adaptersDetailed(client) {
2891
+ const raw = await client.requestJson("/adapters/details", {
2892
+ method: "GET"
2893
+ });
2894
+ return client.parseWithSchema(
2895
+ raw,
2896
+ adapterDetailsResponseSchema,
2897
+ "adapter details response"
3179
2898
  );
3180
- return verification;
3181
2899
  }
3182
-
3183
- // ../../src/services/registry-broker/client/chat-history.ts
3184
- var import_buffer3 = require("buffer");
3185
- function identitiesMatch(a, b) {
3186
- if (!a && !b) {
3187
- return true;
3188
- }
3189
- if (!a || !b) {
3190
- return false;
2900
+ async function adapterRegistryCategories(client) {
2901
+ const raw = await client.requestJson(
2902
+ "/adapters/registry/categories",
2903
+ {
2904
+ method: "GET"
2905
+ }
2906
+ );
2907
+ return client.parseWithSchema(
2908
+ raw,
2909
+ adapterRegistryCategoriesResponseSchema,
2910
+ "adapter registry categories response"
2911
+ );
2912
+ }
2913
+ async function adapterRegistryAdapters(client, filters = {}) {
2914
+ const params = new URLSearchParams();
2915
+ if (filters.category) {
2916
+ params.set("category", filters.category);
3191
2917
  }
3192
- if (a.uaid && b.uaid && a.uaid.toLowerCase() === b.uaid.toLowerCase()) {
3193
- return true;
2918
+ if (filters.entity) {
2919
+ params.set("entity", filters.entity);
3194
2920
  }
3195
- if (a.ledgerAccountId && b.ledgerAccountId && a.ledgerAccountId.toLowerCase() === b.ledgerAccountId.toLowerCase()) {
3196
- return true;
2921
+ if (filters.keywords?.length) {
2922
+ params.set("keywords", filters.keywords.join(","));
3197
2923
  }
3198
- if (a.userId && b.userId && a.userId === b.userId) {
3199
- return true;
2924
+ if (filters.query) {
2925
+ params.set("query", filters.query);
3200
2926
  }
3201
- if (a.email && b.email && a.email.toLowerCase() === b.email.toLowerCase()) {
3202
- return true;
2927
+ if (typeof filters.limit === "number") {
2928
+ params.set("limit", String(filters.limit));
3203
2929
  }
3204
- return false;
3205
- }
3206
- async function fetchHistorySnapshot(conversationContexts, client, sessionId, options) {
3207
- if (!sessionId || sessionId.trim().length === 0) {
3208
- throw new Error("sessionId is required to fetch chat history");
2930
+ if (typeof filters.offset === "number") {
2931
+ params.set("offset", String(filters.offset));
3209
2932
  }
2933
+ const suffix = params.size > 0 ? `?${params.toString()}` : "";
3210
2934
  const raw = await client.requestJson(
3211
- `/chat/session/${encodeURIComponent(sessionId)}/history`,
2935
+ `/adapters/registry/adapters${suffix}`,
3212
2936
  {
3213
2937
  method: "GET"
3214
2938
  }
3215
2939
  );
3216
- const snapshot = client.parseWithSchema(
2940
+ return client.parseWithSchema(
3217
2941
  raw,
3218
- chatHistorySnapshotResponseSchema,
3219
- "chat history snapshot response"
2942
+ adapterRegistryAdaptersResponseSchema,
2943
+ "adapter registry adapters response"
3220
2944
  );
3221
- return attachDecryptedHistory(
3222
- conversationContexts,
3223
- client,
3224
- sessionId,
3225
- snapshot,
3226
- options
2945
+ }
2946
+ async function createAdapterRegistryCategory(client, payload) {
2947
+ const raw = await client.requestJson(
2948
+ "/adapters/registry/categories",
2949
+ {
2950
+ method: "POST",
2951
+ headers: { "content-type": "application/json" },
2952
+ body: toJsonObject(payload)
2953
+ }
3227
2954
  );
2955
+ const parsed = client.parseWithSchema(
2956
+ raw,
2957
+ adapterRegistryCreateCategoryResponseSchema,
2958
+ "adapter registry create category response"
2959
+ );
2960
+ return parsed.category;
3228
2961
  }
3229
- function attachDecryptedHistory(conversationContexts, client, sessionId, snapshot, options) {
3230
- const shouldDecrypt = options?.decrypt !== void 0 ? options.decrypt : client.encryptionOptions?.autoDecryptHistory === true;
3231
- if (!shouldDecrypt) {
3232
- return snapshot;
3233
- }
3234
- const requiresContext = snapshot.history.some(
3235
- (entry) => Boolean(entry.cipherEnvelope)
2962
+ async function submitAdapterRegistryAdapter(client, payload) {
2963
+ const raw = await client.requestJson(
2964
+ "/adapters/registry/adapters",
2965
+ {
2966
+ method: "POST",
2967
+ headers: { "content-type": "application/json" },
2968
+ body: toJsonObject(payload)
2969
+ }
3236
2970
  );
3237
- if (!requiresContext) {
3238
- return {
3239
- ...snapshot,
3240
- decryptedHistory: snapshot.history.map((entry) => ({
3241
- entry,
3242
- plaintext: entry.content
3243
- }))
3244
- };
3245
- }
3246
- const context = resolveDecryptionContext(
3247
- conversationContexts,
3248
- client,
3249
- sessionId,
3250
- options
2971
+ return client.parseWithSchema(
2972
+ raw,
2973
+ adapterRegistrySubmitAdapterAcceptedResponseSchema,
2974
+ "adapter registry submit adapter response"
3251
2975
  );
3252
- if (!context) {
2976
+ }
2977
+ async function adapterRegistrySubmissionStatus(client, submissionId) {
2978
+ const raw = await client.requestJson(
2979
+ `/adapters/registry/submissions/${encodeURIComponent(submissionId)}`,
2980
+ {
2981
+ method: "GET"
2982
+ }
2983
+ );
2984
+ return client.parseWithSchema(
2985
+ raw,
2986
+ adapterRegistrySubmissionStatusResponseSchema,
2987
+ "adapter registry submission status response"
2988
+ );
2989
+ }
2990
+
2991
+ // ../../src/services/registry-broker/client/credits.ts
2992
+ async function loadX402Dependencies(client) {
2993
+ const [{ default: axios }, x402Axios, x402Types] = await Promise.all([
2994
+ import("axios"),
2995
+ optionalImport("x402-axios"),
2996
+ optionalImport("x402/types")
2997
+ ]);
2998
+ if (!x402Axios || !x402Types) {
3253
2999
  throw new Error(
3254
- "Unable to decrypt chat history: encryption context unavailable"
3000
+ "x402-axios and x402/types are required for X402 flows. Install them to enable ledger payments."
3255
3001
  );
3256
3002
  }
3257
- const decryptedHistory = snapshot.history.map((entry) => ({
3258
- entry,
3259
- plaintext: decryptHistoryEntryFromContext(client, entry, context)
3260
- }));
3261
- return { ...snapshot, decryptedHistory };
3003
+ const withPaymentInterceptor = x402Axios.withPaymentInterceptor;
3004
+ const decodePaymentResponse = x402Axios.decodeXPaymentResponse;
3005
+ const createX402Signer = x402Types.createSigner;
3006
+ const createPaymentClient = (walletClient) => {
3007
+ const axiosClient = axios.create({
3008
+ baseURL: client.baseUrl,
3009
+ headers: {
3010
+ ...client.getDefaultHeaders(),
3011
+ "content-type": "application/json"
3012
+ }
3013
+ });
3014
+ const paymentClient = withPaymentInterceptor(axiosClient, walletClient);
3015
+ return paymentClient;
3016
+ };
3017
+ return { createPaymentClient, decodePaymentResponse, createX402Signer };
3262
3018
  }
3263
- function registerConversationContextForEncryption(conversationContexts, context) {
3264
- const normalized = {
3265
- sessionId: context.sessionId,
3266
- sharedSecret: import_buffer3.Buffer.from(context.sharedSecret),
3267
- identity: context.identity ? { ...context.identity } : void 0
3019
+ function calculateHbarAmountParam(hbarAmount) {
3020
+ const tinybars = Math.ceil(hbarAmount * 1e8);
3021
+ if (tinybars <= 0) {
3022
+ throw new Error("Calculated purchase amount must be positive");
3023
+ }
3024
+ return tinybars / 1e8;
3025
+ }
3026
+ async function purchaseCreditsWithHbar(client, params) {
3027
+ const body = {
3028
+ accountId: params.accountId,
3029
+ payerKey: params.privateKey,
3030
+ hbarAmount: calculateHbarAmountParam(params.hbarAmount)
3268
3031
  };
3269
- const entries = conversationContexts.get(context.sessionId) ?? [];
3270
- const existingIndex = entries.findIndex(
3271
- (existing) => identitiesMatch(existing.identity, normalized.identity)
3032
+ if (params.memo) {
3033
+ body.memo = params.memo;
3034
+ }
3035
+ if (params.metadata) {
3036
+ body.metadata = params.metadata;
3037
+ }
3038
+ const raw = await client.requestJson("/credits/purchase", {
3039
+ method: "POST",
3040
+ headers: { "content-type": "application/json" },
3041
+ body
3042
+ });
3043
+ return client.parseWithSchema(
3044
+ raw,
3045
+ creditPurchaseResponseSchema,
3046
+ "credit purchase response"
3047
+ );
3048
+ }
3049
+ async function getX402Minimums(client) {
3050
+ const raw = await client.requestJson(
3051
+ "/credits/purchase/x402/minimums",
3052
+ { method: "GET" }
3053
+ );
3054
+ return client.parseWithSchema(
3055
+ raw,
3056
+ x402MinimumsResponseSchema,
3057
+ "x402 minimums response"
3272
3058
  );
3273
- if (existingIndex >= 0) {
3274
- entries[existingIndex] = normalized;
3275
- } else {
3276
- entries.push(normalized);
3277
- }
3278
- conversationContexts.set(context.sessionId, entries);
3279
3059
  }
3280
- function resolveDecryptionContext(conversationContexts, client, sessionId, options) {
3281
- if (options?.sharedSecret) {
3282
- return {
3283
- sessionId,
3284
- sharedSecret: client.normalizeSharedSecret(options.sharedSecret),
3285
- identity: options.identity
3286
- };
3060
+ async function purchaseCreditsWithX402(client, params) {
3061
+ const { createPaymentClient, decodePaymentResponse } = await loadX402Dependencies(client);
3062
+ if (!Number.isFinite(params.credits) || params.credits <= 0) {
3063
+ throw new Error("credits must be a positive number");
3287
3064
  }
3288
- const contexts = conversationContexts.get(sessionId);
3289
- if (!contexts || contexts.length === 0) {
3290
- return null;
3065
+ if (params.usdAmount !== void 0 && (!Number.isFinite(params.usdAmount) || params.usdAmount <= 0)) {
3066
+ throw new Error("usdAmount must be a positive number when provided");
3291
3067
  }
3292
- if (options?.identity) {
3293
- const match = contexts.find(
3294
- (context) => identitiesMatch(context.identity, options.identity)
3295
- );
3296
- if (match) {
3297
- return match;
3298
- }
3068
+ const body = {
3069
+ accountId: params.accountId,
3070
+ credits: params.credits
3071
+ };
3072
+ if (params.usdAmount !== void 0) {
3073
+ body.usdAmount = params.usdAmount;
3299
3074
  }
3300
- return contexts[0];
3301
- }
3302
- function decryptHistoryEntryFromContext(client, entry, context) {
3303
- const envelope = entry.cipherEnvelope;
3304
- if (!envelope) {
3305
- return entry.content;
3075
+ if (params.description) {
3076
+ body.description = params.description;
3306
3077
  }
3307
- const secret = import_buffer3.Buffer.from(context.sharedSecret);
3308
- try {
3309
- return client.encryption.decryptCipherEnvelope({
3310
- envelope,
3311
- sharedSecret: secret
3312
- });
3313
- } catch (_error) {
3314
- return null;
3078
+ if (params.metadata) {
3079
+ body.metadata = params.metadata;
3315
3080
  }
3081
+ const paymentClient = createPaymentClient(params.walletClient);
3082
+ const response = await paymentClient.post("/credits/purchase/x402", body);
3083
+ const parsed = client.parseWithSchema(
3084
+ response.data,
3085
+ x402CreditPurchaseResponseSchema,
3086
+ "x402 credit purchase response"
3087
+ );
3088
+ const responseHeaders = response.headers ?? {};
3089
+ const paymentHeader = typeof responseHeaders["x-payment-response"] === "string" ? responseHeaders["x-payment-response"] : void 0;
3090
+ const decodedPayment = paymentHeader !== void 0 ? decodePaymentResponse(paymentHeader) : void 0;
3091
+ return {
3092
+ ...parsed,
3093
+ paymentResponseHeader: paymentHeader,
3094
+ paymentResponse: decodedPayment
3095
+ };
3096
+ }
3097
+ async function buyCreditsWithX402(client, params) {
3098
+ const network = params.network ?? "base";
3099
+ const { createX402Signer } = await loadX402Dependencies(client);
3100
+ const normalizedKey = normalizeHexPrivateKey(params.evmPrivateKey);
3101
+ const walletClient = await createX402Signer(network, normalizedKey);
3102
+ return purchaseCreditsWithX402(client, {
3103
+ accountId: params.accountId,
3104
+ credits: params.credits,
3105
+ usdAmount: params.usdAmount,
3106
+ description: params.description,
3107
+ metadata: params.metadata,
3108
+ walletClient
3109
+ });
3316
3110
  }
3317
3111
 
3318
- // ../../src/services/registry-broker/client/encrypted-chat-manager.ts
3319
- var EncryptionUnavailableError = class extends Error {
3320
- constructor(sessionId, summary) {
3321
- super("Encryption is not enabled for this session");
3322
- this.sessionId = sessionId;
3323
- this.summary = summary;
3112
+ // ../../src/services/registry-broker/client/errors.ts
3113
+ var RegistryBrokerError = class extends Error {
3114
+ constructor(message, details) {
3115
+ super(message);
3116
+ this.status = details.status;
3117
+ this.statusText = details.statusText;
3118
+ this.body = details.body;
3324
3119
  }
3325
3120
  };
3326
- var EncryptedChatManager = class {
3327
- constructor(client) {
3328
- this.client = client;
3121
+ var RegistryBrokerParseError = class extends Error {
3122
+ constructor(message, cause, rawValue) {
3123
+ super(message);
3124
+ this.cause = cause;
3125
+ this.rawValue = rawValue;
3329
3126
  }
3330
- registerConversationContext(context) {
3331
- this.client.registerConversationContextForEncryption(context);
3127
+ };
3128
+
3129
+ // ../../src/services/registry-broker/client/agents.ts
3130
+ async function performRegisterAgent(client, payload) {
3131
+ const raw = await client.requestJson("/register", {
3132
+ method: "POST",
3133
+ body: serialiseAgentRegistrationRequest(payload),
3134
+ headers: { "content-type": "application/json" }
3135
+ });
3136
+ return client.parseWithSchema(
3137
+ raw,
3138
+ registerAgentResponseSchema,
3139
+ "register agent response"
3140
+ );
3141
+ }
3142
+ function calculateHbarAmount(creditsToPurchase, creditsPerHbar) {
3143
+ if (creditsPerHbar <= 0) {
3144
+ throw new Error("creditsPerHbar must be positive");
3332
3145
  }
3333
- async startSession(options) {
3334
- await this.client.encryptionReady();
3335
- const session = await this.client.chat.createSession({
3336
- uaid: options.uaid,
3337
- senderUaid: options.senderUaid,
3338
- encryptionRequested: true,
3339
- historyTtlSeconds: options.historyTtlSeconds,
3340
- auth: options.auth
3341
- });
3342
- options.onSessionCreated?.(session.sessionId);
3343
- const summary = session.encryption;
3344
- if (!summary?.enabled) {
3345
- throw new EncryptionUnavailableError(
3346
- session.sessionId,
3347
- session.encryption ?? null
3348
- );
3349
- }
3350
- const handle = await this.establishRequesterContext({
3351
- sessionId: session.sessionId,
3352
- summary,
3353
- senderUaid: options.senderUaid,
3354
- handshakeTimeoutMs: options.handshakeTimeoutMs,
3355
- pollIntervalMs: options.pollIntervalMs
3356
- });
3357
- return handle;
3146
+ if (creditsToPurchase <= 0) {
3147
+ throw new Error("creditsToPurchase must be positive");
3358
3148
  }
3359
- async acceptSession(options) {
3360
- await this.client.encryptionReady();
3361
- const summary = await this.waitForEncryptionSummary(
3362
- options.sessionId,
3363
- options.handshakeTimeoutMs,
3364
- options.pollIntervalMs
3365
- );
3366
- const handle = await this.establishResponderContext({
3367
- sessionId: options.sessionId,
3368
- summary,
3369
- responderUaid: options.responderUaid,
3370
- handshakeTimeoutMs: options.handshakeTimeoutMs,
3371
- pollIntervalMs: options.pollIntervalMs
3372
- });
3373
- return handle;
3149
+ const rawHbar = creditsToPurchase / creditsPerHbar;
3150
+ const tinybars = Math.ceil(rawHbar * 1e8);
3151
+ return tinybars / 1e8;
3152
+ }
3153
+ function resolveCreditsToPurchase(shortfallCredits) {
3154
+ if (!Number.isFinite(shortfallCredits) || shortfallCredits <= 0) {
3155
+ return 0;
3374
3156
  }
3375
- async establishRequesterContext(params) {
3376
- const keyPair = this.client.encryption.generateEphemeralKeyPair();
3377
- await this.client.chat.submitEncryptionHandshake(params.sessionId, {
3378
- role: "requester",
3379
- keyType: "secp256k1",
3380
- ephemeralPublicKey: keyPair.publicKey,
3381
- uaid: params.senderUaid ?? params.summary.requester?.uaid ?? void 0
3382
- });
3383
- const { summary, record } = await this.waitForHandshakeCompletion(
3384
- params.sessionId,
3385
- params.handshakeTimeoutMs,
3386
- params.pollIntervalMs
3387
- );
3388
- const responderKey = record.responder?.ephemeralPublicKey;
3389
- if (!responderKey) {
3390
- throw new Error("Responder handshake was not completed in time");
3391
- }
3392
- const sharedSecret = this.client.encryption.deriveSharedSecret({
3393
- privateKey: keyPair.privateKey,
3394
- peerPublicKey: responderKey
3395
- }).subarray();
3396
- const recipients = this.buildRecipients(summary);
3397
- return this.createHandle({
3398
- sessionId: params.sessionId,
3399
- sharedSecret,
3400
- summary,
3401
- recipients,
3402
- identity: summary.requester ?? void 0
3403
- });
3157
+ return Math.max(
3158
+ Math.ceil(shortfallCredits),
3159
+ MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS
3160
+ );
3161
+ }
3162
+ async function ensureCreditsForRegistration(client, payload, autoTopUp) {
3163
+ const details = autoTopUp ?? null;
3164
+ if (!details) {
3165
+ return;
3404
3166
  }
3405
- async establishResponderContext(params) {
3406
- const keyPair = this.client.encryption.generateEphemeralKeyPair();
3407
- await this.client.chat.submitEncryptionHandshake(params.sessionId, {
3408
- role: "responder",
3409
- keyType: "secp256k1",
3410
- ephemeralPublicKey: keyPair.publicKey,
3411
- uaid: params.responderUaid ?? params.summary.responder?.uaid ?? void 0
3167
+ if (!details.accountId || !details.accountId.trim()) {
3168
+ throw new Error("autoTopUp.accountId is required");
3169
+ }
3170
+ if (!details.privateKey || !details.privateKey.trim()) {
3171
+ throw new Error("autoTopUp.privateKey is required");
3172
+ }
3173
+ for (let attempt = 0; attempt < 3; attempt += 1) {
3174
+ const quote = await getRegistrationQuote(client, payload);
3175
+ const shortfall = quote.shortfallCredits ?? 0;
3176
+ if (shortfall <= 0) {
3177
+ return;
3178
+ }
3179
+ const creditsToPurchase = resolveCreditsToPurchase(shortfall);
3180
+ if (creditsToPurchase <= 0) {
3181
+ return;
3182
+ }
3183
+ const creditsPerHbar = quote.creditsPerHbar ?? null;
3184
+ if (!creditsPerHbar || creditsPerHbar <= 0) {
3185
+ throw new Error("Unable to determine credits per HBAR for auto top-up");
3186
+ }
3187
+ const hbarAmount = calculateHbarAmount(creditsToPurchase, creditsPerHbar);
3188
+ await purchaseCreditsWithHbar(client, {
3189
+ accountId: details.accountId.trim(),
3190
+ privateKey: details.privateKey.trim(),
3191
+ hbarAmount,
3192
+ memo: details.memo ?? "Registry Broker auto top-up",
3193
+ metadata: {
3194
+ shortfallCredits: shortfall,
3195
+ requiredCredits: quote.requiredCredits,
3196
+ purchasedCredits: creditsToPurchase
3197
+ }
3412
3198
  });
3413
- const { summary, record } = await this.waitForHandshakeCompletion(
3414
- params.sessionId,
3415
- params.handshakeTimeoutMs,
3416
- params.pollIntervalMs
3417
- );
3418
- const requesterKey = record.requester?.ephemeralPublicKey;
3419
- if (!requesterKey) {
3420
- throw new Error("Requester handshake was not detected in time");
3199
+ }
3200
+ const finalQuote = await getRegistrationQuote(client, payload);
3201
+ if ((finalQuote.shortfallCredits ?? 0) > 0) {
3202
+ throw new Error("Unable to purchase sufficient credits for registration");
3203
+ }
3204
+ }
3205
+ async function resolveUaid(client, uaid) {
3206
+ const raw = await client.requestJson(
3207
+ `/resolve/${encodeURIComponent(uaid)}`,
3208
+ {
3209
+ method: "GET"
3421
3210
  }
3422
- const sharedSecret = this.client.encryption.deriveSharedSecret({
3423
- privateKey: keyPair.privateKey,
3424
- peerPublicKey: requesterKey
3425
- }).subarray();
3426
- const recipients = this.buildRecipients(summary);
3427
- return this.createHandle({
3428
- sessionId: params.sessionId,
3429
- sharedSecret,
3430
- summary,
3431
- recipients,
3432
- identity: summary.responder ?? void 0
3433
- });
3211
+ );
3212
+ return client.parseWithSchema(
3213
+ raw,
3214
+ resolveResponseSchema,
3215
+ "resolve UAID response"
3216
+ );
3217
+ }
3218
+ async function registerAgent(client, payload, options) {
3219
+ const autoTopUp = options?.autoTopUp ?? client.registrationAutoTopUp;
3220
+ if (!autoTopUp) {
3221
+ return performRegisterAgent(client, payload);
3434
3222
  }
3435
- async waitForHandshakeCompletion(sessionId, timeoutMs = 3e4, pollIntervalMs = 1e3) {
3436
- const deadline = Date.now() + timeoutMs;
3437
- while (true) {
3438
- const status = await this.client.chat.getEncryptionStatus(sessionId);
3439
- const summary = status.encryption;
3440
- const record = summary?.handshake;
3441
- if (summary && record && record.status === "complete") {
3442
- return { summary, record };
3443
- }
3444
- if (Date.now() >= deadline) {
3445
- throw new Error("Timed out waiting for encrypted handshake completion");
3223
+ await ensureCreditsForRegistration(client, payload, autoTopUp);
3224
+ let retried = false;
3225
+ while (true) {
3226
+ try {
3227
+ return await performRegisterAgent(client, payload);
3228
+ } catch (error) {
3229
+ const shortfall = client.extractInsufficientCreditsDetails(error);
3230
+ if (shortfall && !retried) {
3231
+ await ensureCreditsForRegistration(client, payload, autoTopUp);
3232
+ retried = true;
3233
+ continue;
3446
3234
  }
3447
- await this.delay(pollIntervalMs);
3235
+ throw error;
3448
3236
  }
3449
3237
  }
3450
- async waitForEncryptionSummary(sessionId, _timeoutMs = 3e4, _pollIntervalMs = 1e3) {
3451
- const status = await this.client.chat.getEncryptionStatus(sessionId);
3452
- if (!status.encryption?.enabled) {
3453
- throw new EncryptionUnavailableError(
3454
- sessionId,
3455
- status.encryption ?? null
3456
- );
3238
+ }
3239
+ async function getRegistrationQuote(client, payload) {
3240
+ const raw = await client.requestJson("/register/quote", {
3241
+ method: "POST",
3242
+ body: serialiseAgentRegistrationRequest(payload),
3243
+ headers: { "content-type": "application/json" }
3244
+ });
3245
+ return client.parseWithSchema(
3246
+ raw,
3247
+ registrationQuoteResponseSchema,
3248
+ "registration quote response"
3249
+ );
3250
+ }
3251
+ async function updateAgent(client, uaid, payload) {
3252
+ const raw = await client.requestJson(
3253
+ `/register/${encodeURIComponent(uaid)}`,
3254
+ {
3255
+ method: "PUT",
3256
+ body: serialiseAgentRegistrationRequest(payload),
3257
+ headers: { "content-type": "application/json" }
3457
3258
  }
3458
- return status.encryption;
3259
+ );
3260
+ return client.parseWithSchema(
3261
+ raw,
3262
+ registerAgentResponseSchema,
3263
+ "update agent response"
3264
+ );
3265
+ }
3266
+ async function getRegistrationProgress(client, attemptId) {
3267
+ const normalisedAttemptId = attemptId.trim();
3268
+ if (!normalisedAttemptId) {
3269
+ throw new Error("attemptId is required");
3459
3270
  }
3460
- buildRecipients(summary) {
3461
- const candidates = [summary.requester, summary.responder].filter(Boolean);
3462
- const normalized = candidates.map((candidate) => {
3463
- if (!candidate) {
3464
- return null;
3465
- }
3466
- const recipient = {};
3467
- if (candidate.uaid) {
3468
- recipient.uaid = candidate.uaid;
3469
- }
3470
- if (candidate.ledgerAccountId) {
3471
- recipient.ledgerAccountId = candidate.ledgerAccountId;
3472
- }
3473
- if (candidate.userId) {
3474
- recipient.userId = candidate.userId;
3475
- }
3476
- if (candidate.email) {
3477
- recipient.email = candidate.email;
3478
- }
3479
- return recipient;
3480
- }).filter(
3481
- (entry) => Boolean(
3482
- entry?.uaid || entry?.ledgerAccountId || entry?.userId || entry?.email
3483
- )
3271
+ try {
3272
+ const raw = await client.requestJson(
3273
+ `/register/progress/${encodeURIComponent(normalisedAttemptId)}`,
3274
+ { method: "GET" }
3484
3275
  );
3485
- if (normalized.length > 0) {
3486
- return normalized;
3487
- }
3488
- if (summary.responder?.uaid) {
3489
- return [{ uaid: summary.responder.uaid }];
3276
+ const parsed = client.parseWithSchema(
3277
+ raw,
3278
+ registrationProgressResponseSchema,
3279
+ "registration progress response"
3280
+ );
3281
+ return parsed.progress;
3282
+ } catch (error) {
3283
+ if (error instanceof RegistryBrokerError && error.status === 404) {
3284
+ return null;
3490
3285
  }
3491
- return [];
3286
+ throw error;
3492
3287
  }
3493
- createHandle(context) {
3494
- const sharedSecret = context.sharedSecret;
3495
- const uaid = context.summary.requester?.uaid ?? context.summary.responder?.uaid ?? context.identity?.uaid;
3496
- const decryptHistoryEntry = (entry) => this.decryptEntry(entry, context.identity, sharedSecret);
3497
- const fetchHistory = async (options) => {
3498
- const snapshot = await this.client.fetchHistorySnapshot(
3499
- context.sessionId,
3500
- options
3501
- );
3502
- if (snapshot.decryptedHistory) {
3503
- return snapshot.decryptedHistory;
3504
- }
3505
- return snapshot.history.map((entry) => ({
3506
- entry,
3507
- plaintext: decryptHistoryEntry(entry)
3508
- }));
3509
- };
3510
- const handle = {
3511
- sessionId: context.sessionId,
3512
- mode: "encrypted",
3513
- summary: context.summary,
3514
- send: async (options) => {
3515
- const recipients = options.recipients ?? context.recipients;
3516
- return this.client.chat.sendMessage({
3517
- sessionId: context.sessionId,
3518
- message: options.message ?? "[ciphertext omitted]",
3519
- streaming: options.streaming,
3520
- auth: options.auth,
3521
- uaid,
3522
- encryption: {
3523
- plaintext: options.plaintext,
3524
- sharedSecret: Buffer.from(sharedSecret),
3525
- recipients
3526
- }
3527
- });
3528
- },
3529
- decryptHistoryEntry,
3530
- fetchHistory
3531
- };
3532
- this.registerConversationContext({
3533
- sessionId: context.sessionId,
3534
- sharedSecret,
3535
- identity: context.identity
3536
- });
3537
- return handle;
3288
+ }
3289
+ async function waitForRegistrationCompletion(client, attemptId, options = {}) {
3290
+ const normalisedAttemptId = attemptId.trim();
3291
+ if (!normalisedAttemptId) {
3292
+ throw new Error("attemptId is required");
3538
3293
  }
3539
- decryptEntry(entry, identity, fallbackSecret) {
3540
- const envelope = entry.cipherEnvelope;
3541
- if (!envelope) {
3542
- return null;
3294
+ const interval = Math.max(
3295
+ 250,
3296
+ options.intervalMs ?? DEFAULT_PROGRESS_INTERVAL_MS
3297
+ );
3298
+ const timeoutMs = options.timeoutMs ?? DEFAULT_PROGRESS_TIMEOUT_MS;
3299
+ const throwOnFailure = options.throwOnFailure ?? true;
3300
+ const signal = options.signal;
3301
+ const startedAt = Date.now();
3302
+ while (true) {
3303
+ if (signal?.aborted) {
3304
+ throw createAbortError();
3543
3305
  }
3544
- const secret = Buffer.from(fallbackSecret);
3545
- try {
3546
- return this.client.encryption.decryptCipherEnvelope({
3547
- envelope,
3548
- sharedSecret: secret
3549
- });
3550
- } catch (_error) {
3551
- return null;
3306
+ const progress = await client.getRegistrationProgress(normalisedAttemptId);
3307
+ if (progress) {
3308
+ options.onProgress?.(progress);
3309
+ if (progress.status === "completed") {
3310
+ return progress;
3311
+ }
3312
+ if (progress.status === "partial" || progress.status === "failed") {
3313
+ if (throwOnFailure) {
3314
+ throw new RegistryBrokerError(
3315
+ "Registration did not complete successfully",
3316
+ {
3317
+ status: 409,
3318
+ statusText: progress.status,
3319
+ body: progress
3320
+ }
3321
+ );
3322
+ }
3323
+ return progress;
3324
+ }
3325
+ }
3326
+ if (Date.now() - startedAt >= timeoutMs) {
3327
+ throw new Error(
3328
+ `Registration progress polling timed out after ${timeoutMs}ms`
3329
+ );
3552
3330
  }
3331
+ await client.delay(interval, signal);
3553
3332
  }
3554
- recipientMatches(candidate, target) {
3555
- if (target.uaid && candidate.uaid?.toLowerCase() === target.uaid.toLowerCase()) {
3556
- return true;
3333
+ }
3334
+ async function validateUaid(client, uaid) {
3335
+ const raw = await client.requestJson(
3336
+ `/uaids/validate/${encodeURIComponent(uaid)}`,
3337
+ {
3338
+ method: "GET"
3557
3339
  }
3558
- if (target.ledgerAccountId && candidate.ledgerAccountId?.toLowerCase() === target.ledgerAccountId.toLowerCase()) {
3559
- return true;
3340
+ );
3341
+ return client.parseWithSchema(
3342
+ raw,
3343
+ uaidValidationResponseSchema,
3344
+ "UAID validation response"
3345
+ );
3346
+ }
3347
+ async function getUaidConnectionStatus(client, uaid) {
3348
+ const raw = await client.requestJson(
3349
+ `/uaids/connections/${encodeURIComponent(uaid)}/status`,
3350
+ {
3351
+ method: "GET"
3560
3352
  }
3561
- if (target.userId && candidate.userId === target.userId) {
3562
- return true;
3353
+ );
3354
+ return client.parseWithSchema(
3355
+ raw,
3356
+ uaidConnectionStatusSchema,
3357
+ "UAID connection status"
3358
+ );
3359
+ }
3360
+ async function closeUaidConnection(client, uaid) {
3361
+ await client.request(`/uaids/connections/${encodeURIComponent(uaid)}`, {
3362
+ method: "DELETE"
3363
+ });
3364
+ }
3365
+ async function dashboardStats(client) {
3366
+ const raw = await client.requestJson("/dashboard/stats", {
3367
+ method: "GET"
3368
+ });
3369
+ return client.parseWithSchema(
3370
+ raw,
3371
+ dashboardStatsResponseSchema,
3372
+ "dashboard stats response"
3373
+ );
3374
+ }
3375
+
3376
+ // ../../src/services/registry-broker/client/verification.ts
3377
+ async function getVerificationStatus(client, uaid) {
3378
+ const raw = await client.requestJson(
3379
+ `/verification/status/${encodeURIComponent(uaid)}`,
3380
+ { method: "GET" }
3381
+ );
3382
+ return client.parseWithSchema(
3383
+ raw,
3384
+ verificationStatusResponseSchema,
3385
+ "verification status response"
3386
+ );
3387
+ }
3388
+ async function createVerificationChallenge(client, uaid) {
3389
+ const raw = await client.requestJson("/verification/challenge", {
3390
+ method: "POST",
3391
+ headers: { "content-type": "application/json" },
3392
+ body: { uaid }
3393
+ });
3394
+ return client.parseWithSchema(
3395
+ raw,
3396
+ verificationChallengeResponseSchema,
3397
+ "verification challenge response"
3398
+ );
3399
+ }
3400
+ async function getVerificationChallenge(client, challengeId) {
3401
+ const raw = await client.requestJson(
3402
+ `/verification/challenge/${encodeURIComponent(challengeId)}`,
3403
+ { method: "GET" }
3404
+ );
3405
+ return client.parseWithSchema(
3406
+ raw,
3407
+ verificationChallengeDetailsResponseSchema,
3408
+ "verification challenge details response"
3409
+ );
3410
+ }
3411
+ async function verifyVerificationChallenge(client, params) {
3412
+ const raw = await client.requestJson("/verification/verify", {
3413
+ method: "POST",
3414
+ headers: { "content-type": "application/json" },
3415
+ body: {
3416
+ challengeId: params.challengeId,
3417
+ method: params.method ?? "moltbook-post"
3563
3418
  }
3564
- if (target.email && candidate.email?.toLowerCase() === target.email.toLowerCase()) {
3565
- return true;
3419
+ });
3420
+ return client.parseWithSchema(
3421
+ raw,
3422
+ verificationVerifyResponseSchema,
3423
+ "verification verify response"
3424
+ );
3425
+ }
3426
+ async function getVerificationOwnership(client, uaid) {
3427
+ const raw = await client.requestJson(
3428
+ `/verification/ownership/${encodeURIComponent(uaid)}`,
3429
+ { method: "GET" }
3430
+ );
3431
+ return client.parseWithSchema(
3432
+ raw,
3433
+ verificationOwnershipResponseSchema,
3434
+ "verification ownership response"
3435
+ );
3436
+ }
3437
+ async function verifySenderOwnership(client, uaid) {
3438
+ const raw = await client.requestJson(
3439
+ "/verification/verify-sender",
3440
+ {
3441
+ method: "POST",
3442
+ headers: { "content-type": "application/json" },
3443
+ body: { uaid }
3566
3444
  }
3567
- return false;
3568
- }
3569
- async delay(ms) {
3570
- if (ms <= 0) {
3571
- return;
3445
+ );
3446
+ return client.parseWithSchema(
3447
+ raw,
3448
+ verificationVerifySenderResponseSchema,
3449
+ "verification sender response"
3450
+ );
3451
+ }
3452
+ async function verifyUaidDnsTxt(client, payload) {
3453
+ const raw = await client.requestJson("/verification/dns/verify", {
3454
+ method: "POST",
3455
+ headers: { "content-type": "application/json" },
3456
+ body: {
3457
+ uaid: payload.uaid,
3458
+ ...payload.persist !== void 0 ? { persist: payload.persist } : {}
3572
3459
  }
3573
- await new Promise((resolve2) => setTimeout(resolve2, ms));
3460
+ });
3461
+ return client.parseWithSchema(
3462
+ raw,
3463
+ verificationDnsStatusResponseSchema,
3464
+ "verification dns verify response"
3465
+ );
3466
+ }
3467
+ async function getVerificationDnsStatus(client, uaid, query) {
3468
+ const params = new URLSearchParams();
3469
+ if (query?.refresh !== void 0) {
3470
+ params.set("refresh", String(query.refresh));
3574
3471
  }
3575
- };
3576
-
3577
- // ../../src/services/registry-broker/client/chat.ts
3578
- function createChatApi(client, encryptedManager) {
3579
- return {
3580
- start: (options) => client.startChat(options),
3581
- createSession: (payload) => client.createSession(payload),
3582
- sendMessage: (payload) => client.sendMessage(payload),
3583
- endSession: (sessionId) => client.endSession(sessionId),
3584
- getHistory: (sessionId, options) => client.fetchHistorySnapshot(sessionId, options),
3585
- compactHistory: (payload) => client.compactHistory(payload),
3586
- getEncryptionStatus: (sessionId) => client.fetchEncryptionStatus(sessionId),
3587
- submitEncryptionHandshake: (sessionId, payload) => client.postEncryptionHandshake(sessionId, payload),
3588
- startConversation: (options) => client.startConversation(options),
3589
- acceptConversation: (options) => client.acceptConversation(options),
3590
- createEncryptedSession: (options) => encryptedManager.startSession(options),
3591
- acceptEncryptedSession: (options) => encryptedManager.acceptSession(options)
3592
- };
3472
+ if (query?.persist !== void 0) {
3473
+ params.set("persist", String(query.persist));
3474
+ }
3475
+ const queryString = params.toString();
3476
+ const path = `/verification/dns/status/${encodeURIComponent(uaid)}${queryString ? `?${queryString}` : ""}`;
3477
+ const raw = await client.requestJson(path, {
3478
+ method: "GET"
3479
+ });
3480
+ return client.parseWithSchema(
3481
+ raw,
3482
+ verificationDnsStatusResponseSchema,
3483
+ "verification dns status response"
3484
+ );
3593
3485
  }
3594
- async function createSession(client, payload, allowHistoryAutoTopUp = true) {
3595
- const body = {};
3596
- if ("uaid" in payload && payload.uaid) {
3597
- body.uaid = payload.uaid;
3486
+ async function getRegisterStatus(client, uaid) {
3487
+ const raw = await client.requestJson(
3488
+ `/register/status/${encodeURIComponent(uaid)}`,
3489
+ { method: "GET" }
3490
+ );
3491
+ return client.parseWithSchema(
3492
+ raw,
3493
+ registerStatusResponseSchema,
3494
+ "register status response"
3495
+ );
3496
+ }
3497
+ async function registerOwnedMoltbookAgent(client, uaid, request) {
3498
+ const raw = await client.requestJson(
3499
+ `/register/${encodeURIComponent(uaid)}`,
3500
+ {
3501
+ method: "PUT",
3502
+ headers: { "content-type": "application/json" },
3503
+ body: {
3504
+ registered: request.registered ?? true,
3505
+ ...request.name ? { name: request.name } : {},
3506
+ ...request.description ? { description: request.description } : {},
3507
+ ...request.endpoint ? { endpoint: request.endpoint } : {},
3508
+ ...request.metadata ? { metadata: request.metadata } : {}
3509
+ }
3510
+ }
3511
+ );
3512
+ return client.parseWithSchema(
3513
+ raw,
3514
+ moltbookOwnerRegistrationUpdateResponseSchema,
3515
+ "moltbook owner registration update response"
3516
+ );
3517
+ }
3518
+
3519
+ // ../../src/services/registry-broker/client/ledger-auth.ts
3520
+ var import_buffer3 = require("buffer");
3521
+
3522
+ // ../../src/services/registry-broker/ledger-network.ts
3523
+ var normalise = (value) => value.trim().toLowerCase();
3524
+ var HEDERA_NETWORK_ALIASES = /* @__PURE__ */ new Map([
3525
+ ["hedera:mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
3526
+ ["mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
3527
+ ["hedera-mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
3528
+ ["hedera_mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
3529
+ ["hedera:testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
3530
+ ["testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
3531
+ ["hedera-testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
3532
+ ["hedera_testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }]
3533
+ ]);
3534
+ var EVM_NETWORK_CHAIN_IDS = {
3535
+ abstract: 2741,
3536
+ "abstract-testnet": 11124,
3537
+ base: 8453,
3538
+ "base-sepolia": 84532,
3539
+ avalanche: 43114,
3540
+ "avalanche-fuji": 43113,
3541
+ iotex: 4689,
3542
+ sei: 1329,
3543
+ "sei-testnet": 1328,
3544
+ polygon: 137,
3545
+ "polygon-amoy": 80002,
3546
+ peaq: 3338
3547
+ };
3548
+ var CHAIN_ID_TO_ALIAS = new Map(
3549
+ Object.entries(EVM_NETWORK_CHAIN_IDS).map(([alias, id]) => [id, alias])
3550
+ );
3551
+ var parseChainId = (value) => {
3552
+ if (/^eip155:\d+$/i.test(value)) {
3553
+ return Number.parseInt(value.split(":")[1], 10);
3598
3554
  }
3599
- if ("agentUrl" in payload && payload.agentUrl) {
3600
- body.agentUrl = payload.agentUrl;
3555
+ if (/^\d+$/.test(value)) {
3556
+ return Number.parseInt(value, 10);
3601
3557
  }
3602
- if (payload.auth) {
3603
- body.auth = serialiseAuthConfig(payload.auth);
3558
+ return void 0;
3559
+ };
3560
+ var normaliseEvmNetwork = (value) => {
3561
+ const trimmed = normalise(value);
3562
+ let chainId = parseChainId(trimmed);
3563
+ let alias;
3564
+ if (chainId === void 0) {
3565
+ const mapped = EVM_NETWORK_CHAIN_IDS[trimmed];
3566
+ if (mapped !== void 0) {
3567
+ chainId = mapped;
3568
+ alias = trimmed;
3569
+ }
3570
+ } else if (CHAIN_ID_TO_ALIAS.has(chainId)) {
3571
+ alias = CHAIN_ID_TO_ALIAS.get(chainId);
3604
3572
  }
3605
- if (payload.historyTtlSeconds !== void 0) {
3606
- body.historyTtlSeconds = payload.historyTtlSeconds;
3573
+ if (chainId === void 0) {
3574
+ throw new Error(
3575
+ 'Unsupported EVM ledger network. Provide an alias like "base-sepolia" or a canonical eip155:<chainId> string.'
3576
+ );
3607
3577
  }
3608
- if (payload.encryptionRequested !== void 0) {
3609
- body.encryptionRequested = payload.encryptionRequested;
3578
+ return {
3579
+ canonical: `eip155:${chainId}`,
3580
+ kind: "evm",
3581
+ chainId,
3582
+ legacyName: alias
3583
+ };
3584
+ };
3585
+ var normaliseHederaNetwork = (value) => {
3586
+ const trimmed = normalise(value);
3587
+ const mapping = HEDERA_NETWORK_ALIASES.get(trimmed);
3588
+ if (!mapping) {
3589
+ throw new Error(
3590
+ 'Unsupported Hedera network. Use hedera:mainnet or hedera:testnet (legacy "mainnet"/"testnet" also accepted).'
3591
+ );
3610
3592
  }
3611
- if (payload.senderUaid) {
3612
- body.senderUaid = payload.senderUaid;
3593
+ return {
3594
+ canonical: mapping.canonical,
3595
+ kind: "hedera",
3596
+ hederaNetwork: mapping.hederaNetwork
3597
+ };
3598
+ };
3599
+ var canonicalizeLedgerNetwork = (network) => {
3600
+ if (typeof network !== "string" || network.trim().length === 0) {
3601
+ throw new Error("Ledger network is required.");
3613
3602
  }
3614
- try {
3615
- const raw = await client.requestJson("/chat/session", {
3616
- method: "POST",
3617
- body,
3618
- headers: { "content-type": "application/json" }
3619
- });
3620
- return client.parseWithSchema(
3621
- raw,
3622
- createSessionResponseSchema,
3623
- "chat session response"
3624
- );
3625
- } catch (error) {
3626
- const maybeError = error instanceof Error ? error : null;
3627
- if (allowHistoryAutoTopUp && client.shouldAutoTopUpHistory(payload, maybeError)) {
3628
- await client.executeHistoryAutoTopUp("chat.session");
3629
- return createSession(client, payload, false);
3630
- }
3631
- throw error;
3603
+ const trimmed = normalise(network);
3604
+ if (trimmed.startsWith("hedera:") || trimmed.includes("hedera-") || trimmed.includes("hedera_") || trimmed === "mainnet" || trimmed === "testnet") {
3605
+ return normaliseHederaNetwork(trimmed);
3632
3606
  }
3633
- }
3634
- async function startChat(client, encryptedManager, options) {
3635
- if ("uaid" in options && options.uaid) {
3636
- return startConversation(client, encryptedManager, {
3637
- uaid: options.uaid,
3638
- senderUaid: options.senderUaid,
3639
- historyTtlSeconds: options.historyTtlSeconds,
3640
- auth: options.auth,
3641
- encryption: options.encryption,
3642
- onSessionCreated: options.onSessionCreated
3643
- });
3607
+ return normaliseEvmNetwork(trimmed);
3608
+ };
3609
+
3610
+ // ../../src/services/registry-broker/private-key-signer.ts
3611
+ var unsupported = (method) => new Error(`${method} is not supported by the in-memory signer`);
3612
+ var cachedSdk = null;
3613
+ var loadHashgraphSdk = () => {
3614
+ if (cachedSdk) {
3615
+ return cachedSdk;
3644
3616
  }
3645
- if ("agentUrl" in options && options.agentUrl) {
3646
- const session = await createSession(client, {
3647
- agentUrl: options.agentUrl,
3648
- auth: options.auth,
3649
- historyTtlSeconds: options.historyTtlSeconds,
3650
- senderUaid: options.senderUaid
3651
- });
3652
- options.onSessionCreated?.(session.sessionId);
3653
- return createPlaintextConversationHandle(
3654
- client,
3655
- session.sessionId,
3656
- session.encryption ?? null,
3657
- options.auth,
3658
- { agentUrl: options.agentUrl, uaid: options.uaid }
3659
- );
3617
+ const resolved = optionalImportSync("@hashgraph/sdk");
3618
+ if (resolved) {
3619
+ cachedSdk = resolved;
3620
+ return resolved;
3660
3621
  }
3661
- throw new Error("startChat requires either uaid or agentUrl");
3662
- }
3663
- async function startConversation(client, encryptedManager, options) {
3664
- const preference = options.encryption?.preference ?? "preferred";
3665
- const requestEncryption = preference !== "disabled";
3666
- if (!requestEncryption) {
3667
- const session = await createSession(client, {
3668
- uaid: options.uaid,
3669
- auth: options.auth,
3670
- historyTtlSeconds: options.historyTtlSeconds,
3671
- senderUaid: options.senderUaid,
3672
- encryptionRequested: false
3673
- });
3674
- options.onSessionCreated?.(session.sessionId);
3675
- return createPlaintextConversationHandle(
3676
- client,
3677
- session.sessionId,
3678
- session.encryption ?? null,
3679
- options.auth,
3680
- { uaid: options.uaid }
3681
- );
3622
+ const message = "@hashgraph/sdk is required for ledger signing. Install it as a dependency to enable createPrivateKeySigner.";
3623
+ throw new Error(message);
3624
+ };
3625
+ var loadHashgraphSdkAsync = async () => {
3626
+ if (cachedSdk) {
3627
+ return cachedSdk;
3682
3628
  }
3683
- try {
3684
- const handle = await encryptedManager.startSession({
3685
- uaid: options.uaid,
3686
- senderUaid: options.senderUaid,
3687
- historyTtlSeconds: options.historyTtlSeconds,
3688
- handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
3689
- pollIntervalMs: options.encryption?.pollIntervalMs,
3690
- onSessionCreated: (sessionId) => {
3691
- options.onSessionCreated?.(sessionId);
3692
- },
3693
- auth: options.auth
3694
- });
3695
- return handle;
3696
- } catch (error) {
3697
- if (error instanceof EncryptionUnavailableError) {
3698
- if (preference === "required") {
3699
- throw error;
3700
- }
3701
- return createPlaintextConversationHandle(
3702
- client,
3703
- error.sessionId,
3704
- error.summary ?? null,
3705
- options.auth,
3706
- { uaid: options.uaid }
3707
- );
3708
- }
3709
- throw error;
3629
+ const resolved = await optionalImport("@hashgraph/sdk");
3630
+ if (resolved) {
3631
+ cachedSdk = resolved;
3632
+ return resolved;
3710
3633
  }
3711
- }
3712
- async function acceptConversation(client, encryptedManager, options) {
3713
- const preference = options.encryption?.preference ?? "preferred";
3714
- if (preference === "disabled") {
3715
- return createPlaintextConversationHandle(client, options.sessionId, null);
3634
+ const message = "@hashgraph/sdk is required for ledger signing. Install it as a dependency to enable createPrivateKeySigner.";
3635
+ throw new Error(message);
3636
+ };
3637
+ var buildSigner = (sdk, options) => {
3638
+ const { AccountId, LedgerId, PrivateKey, SignerSignature } = sdk;
3639
+ if (!options.privateKey) {
3640
+ throw new Error("privateKey is required to create a ledger signer.");
3716
3641
  }
3717
- try {
3718
- const handle = await encryptedManager.acceptSession({
3719
- sessionId: options.sessionId,
3720
- responderUaid: options.responderUaid,
3721
- handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
3722
- pollIntervalMs: options.encryption?.pollIntervalMs
3723
- });
3724
- return handle;
3725
- } catch (error) {
3726
- if (error instanceof EncryptionUnavailableError && preference !== "required") {
3727
- return createPlaintextConversationHandle(
3728
- client,
3729
- options.sessionId,
3730
- null,
3731
- void 0,
3732
- { uaid: options.responderUaid }
3733
- );
3734
- }
3735
- throw error;
3642
+ if (!options.accountId) {
3643
+ throw new Error("accountId is required to create a ledger signer.");
3736
3644
  }
3737
- }
3738
- function createPlaintextConversationHandle(client, sessionId, summary, defaultAuth, context) {
3739
- const uaid = context?.uaid?.trim();
3740
- const agentUrl = context?.agentUrl?.trim();
3741
- const fetchHistory = async (options) => {
3742
- const snapshot = await client.fetchHistorySnapshot(sessionId, options);
3743
- if (snapshot.decryptedHistory) {
3744
- return snapshot.decryptedHistory;
3745
- }
3746
- return snapshot.history.map((entry) => ({
3747
- entry,
3748
- plaintext: entry.content
3749
- }));
3750
- };
3645
+ const accountId = AccountId.fromString(options.accountId);
3646
+ const privateKey = PrivateKey.fromString(options.privateKey);
3647
+ const ledgerId = LedgerId.fromString(options.network);
3751
3648
  return {
3752
- sessionId,
3753
- mode: "plaintext",
3754
- summary: summary ?? null,
3755
- send: async (options) => {
3756
- const plaintext = options.plaintext;
3757
- if (!plaintext || plaintext.trim().length === 0) {
3758
- throw new Error("plaintext is required for chat messages");
3759
- }
3760
- const message = options.message ?? plaintext;
3761
- return sendMessage(client, {
3762
- sessionId,
3763
- message,
3764
- streaming: options.streaming,
3765
- auth: options.auth ?? defaultAuth,
3766
- uaid,
3767
- agentUrl
3768
- });
3649
+ getLedgerId: () => ledgerId,
3650
+ getAccountId: () => accountId,
3651
+ getAccountKey: () => privateKey.publicKey,
3652
+ getNetwork: () => ({}),
3653
+ getMirrorNetwork: () => [],
3654
+ sign: async (messages) => Promise.all(
3655
+ messages.map(async (message) => {
3656
+ const signature = await privateKey.sign(message);
3657
+ return new SignerSignature({
3658
+ publicKey: privateKey.publicKey,
3659
+ signature,
3660
+ accountId
3661
+ });
3662
+ })
3663
+ ),
3664
+ getAccountBalance: async () => {
3665
+ throw unsupported("getAccountBalance");
3769
3666
  },
3770
- decryptHistoryEntry: (entry) => entry.content,
3771
- fetchHistory
3667
+ getAccountInfo: async () => {
3668
+ throw unsupported("getAccountInfo");
3669
+ },
3670
+ getAccountRecords: async () => {
3671
+ throw unsupported("getAccountRecords");
3672
+ },
3673
+ signTransaction: async (_) => {
3674
+ throw unsupported("signTransaction");
3675
+ },
3676
+ checkTransaction: async (_) => {
3677
+ throw unsupported("checkTransaction");
3678
+ },
3679
+ populateTransaction: async (_) => {
3680
+ throw unsupported("populateTransaction");
3681
+ },
3682
+ call: async (_request) => {
3683
+ throw unsupported("call");
3684
+ }
3772
3685
  };
3686
+ };
3687
+ var createPrivateKeySigner = (options) => buildSigner(loadHashgraphSdk(), options);
3688
+ var createPrivateKeySignerAsync = async (options) => buildSigner(await loadHashgraphSdkAsync(), options);
3689
+
3690
+ // ../../src/services/registry-broker/client/ledger-auth.ts
3691
+ async function loadViemAccount(privateKey) {
3692
+ try {
3693
+ const viem = await import("viem/accounts");
3694
+ return viem.privateKeyToAccount(privateKey);
3695
+ } catch (error) {
3696
+ const err = new Error(
3697
+ 'EVM ledger authentication requires the optional dependency "viem". Install it to use evmPrivateKey flows.'
3698
+ );
3699
+ err.cause = error;
3700
+ throw err;
3701
+ }
3773
3702
  }
3774
- async function compactHistory(client, payload) {
3775
- if (!payload.sessionId || payload.sessionId.trim().length === 0) {
3776
- throw new Error("sessionId is required to compact chat history");
3703
+ async function resolveLedgerAuthSignature(message, options) {
3704
+ if (typeof options.sign === "function") {
3705
+ const result = await options.sign(message);
3706
+ if (!result || typeof result.signature !== "string" || result.signature.length === 0) {
3707
+ throw new Error("Custom ledger signer failed to produce a signature.");
3708
+ }
3709
+ return result;
3777
3710
  }
3778
- const body = {};
3779
- if (typeof payload.preserveEntries === "number" && Number.isFinite(payload.preserveEntries) && payload.preserveEntries >= 0) {
3780
- body.preserveEntries = Math.floor(payload.preserveEntries);
3711
+ if (!options.signer || typeof options.signer.sign !== "function") {
3712
+ throw new Error(
3713
+ "Ledger authentication requires a Hedera Signer or custom sign function."
3714
+ );
3781
3715
  }
3782
- const raw = await client.requestJson(
3783
- `/chat/session/${encodeURIComponent(payload.sessionId)}/compact`,
3784
- {
3785
- method: "POST",
3786
- headers: { "content-type": "application/json" },
3787
- body
3788
- }
3789
- );
3790
- return client.parseWithSchema(
3791
- raw,
3792
- chatHistoryCompactionResponseSchema,
3793
- "chat history compaction response"
3794
- );
3795
- }
3796
- async function fetchEncryptionStatus(client, sessionId) {
3797
- if (!sessionId || sessionId.trim().length === 0) {
3798
- throw new Error("sessionId is required for encryption status");
3716
+ const payload = import_buffer3.Buffer.from(message, "utf8");
3717
+ const signatures = await options.signer.sign([payload]);
3718
+ const signatureEntry = signatures?.[0];
3719
+ if (!signatureEntry) {
3720
+ throw new Error("Signer did not return any signatures.");
3799
3721
  }
3800
- const raw = await client.requestJson(
3801
- `/chat/session/${encodeURIComponent(sessionId)}/encryption`,
3802
- {
3803
- method: "GET"
3722
+ let derivedPublicKey;
3723
+ if (signatureEntry.publicKey) {
3724
+ derivedPublicKey = signatureEntry.publicKey.toString();
3725
+ } else if (typeof options.signer.getAccountKey === "function") {
3726
+ const accountKey = await options.signer.getAccountKey();
3727
+ if (accountKey && typeof accountKey.toString === "function") {
3728
+ derivedPublicKey = accountKey.toString();
3804
3729
  }
3805
- );
3806
- return client.parseWithSchema(
3807
- raw,
3808
- sessionEncryptionStatusResponseSchema,
3809
- "session encryption status response"
3810
- );
3811
- }
3812
- async function postEncryptionHandshake(client, sessionId, payload) {
3813
- if (!sessionId || sessionId.trim().length === 0) {
3814
- throw new Error("sessionId is required for encryption handshake");
3815
3730
  }
3816
- const raw = await client.requestJson(
3817
- `/chat/session/${encodeURIComponent(sessionId)}/encryption-handshake`,
3818
- {
3819
- method: "POST",
3820
- headers: { "content-type": "application/json" },
3821
- body: {
3822
- role: payload.role,
3823
- keyType: payload.keyType,
3824
- ephemeralPublicKey: payload.ephemeralPublicKey,
3825
- longTermPublicKey: payload.longTermPublicKey,
3826
- signature: payload.signature,
3827
- uaid: payload.uaid,
3828
- userId: payload.userId,
3829
- ledgerAccountId: payload.ledgerAccountId,
3830
- metadata: payload.metadata
3831
- }
3731
+ return {
3732
+ signature: import_buffer3.Buffer.from(signatureEntry.signature).toString("base64"),
3733
+ signatureKind: "raw",
3734
+ publicKey: derivedPublicKey
3735
+ };
3736
+ }
3737
+ async function createLedgerChallenge(client, payload) {
3738
+ const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
3739
+ const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
3740
+ const raw = await client.requestJson("/auth/ledger/challenge", {
3741
+ method: "POST",
3742
+ headers: { "content-type": "application/json" },
3743
+ body: {
3744
+ accountId: payload.accountId,
3745
+ network
3832
3746
  }
3833
- );
3834
- const response = client.parseWithSchema(
3747
+ });
3748
+ return client.parseWithSchema(
3835
3749
  raw,
3836
- encryptionHandshakeResponseSchema,
3837
- "encryption handshake response"
3750
+ ledgerChallengeResponseSchema,
3751
+ "ledger challenge response"
3838
3752
  );
3839
- return response.handshake;
3840
3753
  }
3841
- async function sendMessage(client, payload) {
3754
+ async function verifyLedgerChallenge(client, payload) {
3755
+ const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
3756
+ const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
3842
3757
  const body = {
3843
- message: payload.message
3758
+ challengeId: payload.challengeId,
3759
+ accountId: payload.accountId,
3760
+ network,
3761
+ signature: payload.signature
3844
3762
  };
3845
- if (payload.streaming !== void 0) {
3846
- body.streaming = payload.streaming;
3847
- }
3848
- if (payload.auth) {
3849
- body.auth = serialiseAuthConfig(payload.auth);
3850
- }
3851
- if ("uaid" in payload) {
3852
- body.uaid = payload.uaid;
3763
+ if (payload.signatureKind) {
3764
+ body.signatureKind = payload.signatureKind;
3853
3765
  }
3854
- if ("sessionId" in payload && payload.sessionId) {
3855
- body.sessionId = payload.sessionId;
3766
+ if (payload.publicKey) {
3767
+ body.publicKey = payload.publicKey;
3856
3768
  }
3857
- if ("agentUrl" in payload && payload.agentUrl) {
3858
- body.agentUrl = payload.agentUrl;
3769
+ if (typeof payload.expiresInMinutes === "number") {
3770
+ body.expiresInMinutes = payload.expiresInMinutes;
3859
3771
  }
3860
- let cipherEnvelope = payload.cipherEnvelope ?? null;
3861
- if (payload.encryption) {
3862
- const sessionIdForEncryption = payload.encryption.sessionId ?? (typeof body.sessionId === "string" ? body.sessionId : void 0);
3863
- if (!sessionIdForEncryption) {
3772
+ const raw = await client.requestJson("/auth/ledger/verify", {
3773
+ method: "POST",
3774
+ headers: { "content-type": "application/json" },
3775
+ body
3776
+ });
3777
+ const result = client.parseWithSchema(
3778
+ raw,
3779
+ ledgerVerifyResponseSchema,
3780
+ "ledger verification response"
3781
+ );
3782
+ client.setLedgerApiKey(result.key);
3783
+ return result;
3784
+ }
3785
+ async function authenticateWithLedger(client, options) {
3786
+ const challenge = await client.createLedgerChallenge({
3787
+ accountId: options.accountId,
3788
+ network: options.network
3789
+ });
3790
+ const signed = await resolveLedgerAuthSignature(challenge.message, options);
3791
+ const verification = await client.verifyLedgerChallenge({
3792
+ challengeId: challenge.challengeId,
3793
+ accountId: options.accountId,
3794
+ network: options.network,
3795
+ signature: signed.signature,
3796
+ signatureKind: signed.signatureKind,
3797
+ publicKey: signed.publicKey,
3798
+ expiresInMinutes: options.expiresInMinutes
3799
+ });
3800
+ return verification;
3801
+ }
3802
+ async function authenticateWithLedgerCredentials(client, options) {
3803
+ const {
3804
+ accountId,
3805
+ network,
3806
+ signer,
3807
+ sign,
3808
+ hederaPrivateKey,
3809
+ evmPrivateKey,
3810
+ expiresInMinutes,
3811
+ setAccountHeader = true,
3812
+ label,
3813
+ logger
3814
+ } = options;
3815
+ const resolvedNetwork = canonicalizeLedgerNetwork(network);
3816
+ const labelSuffix = label ? ` for ${label}` : "";
3817
+ const networkPayload = resolvedNetwork.canonical;
3818
+ const authOptions = {
3819
+ accountId,
3820
+ network: networkPayload,
3821
+ expiresInMinutes
3822
+ };
3823
+ if (sign) {
3824
+ authOptions.sign = sign;
3825
+ } else if (signer) {
3826
+ authOptions.signer = signer;
3827
+ } else if (hederaPrivateKey) {
3828
+ if (resolvedNetwork.kind !== "hedera" || !resolvedNetwork.hederaNetwork) {
3864
3829
  throw new Error(
3865
- "sessionId is required when using encrypted chat payloads"
3830
+ "hederaPrivateKey can only be used with hedera:mainnet or hedera:testnet networks."
3866
3831
  );
3867
3832
  }
3868
- if (!payload.encryption.recipients?.length) {
3869
- throw new Error("recipients are required for encrypted chat payloads");
3833
+ authOptions.signer = await createPrivateKeySignerAsync({
3834
+ accountId,
3835
+ privateKey: hederaPrivateKey,
3836
+ network: resolvedNetwork.hederaNetwork
3837
+ });
3838
+ } else if (evmPrivateKey) {
3839
+ if (resolvedNetwork.kind !== "evm") {
3840
+ throw new Error(
3841
+ "evmPrivateKey can only be used with CAIP-2 EVM networks (eip155:<chainId>)."
3842
+ );
3870
3843
  }
3871
- cipherEnvelope = client.encryption.encryptCipherEnvelope({
3872
- ...payload.encryption,
3873
- sessionId: sessionIdForEncryption
3844
+ const formattedKey = evmPrivateKey.startsWith("0x") ? evmPrivateKey : `0x${evmPrivateKey}`;
3845
+ const account = await loadViemAccount(formattedKey);
3846
+ authOptions.sign = async (message) => ({
3847
+ signature: await account.signMessage({ message }),
3848
+ signatureKind: "evm",
3849
+ publicKey: account.publicKey
3874
3850
  });
3851
+ } else {
3852
+ throw new Error(
3853
+ "Provide a signer, sign function, hederaPrivateKey, or evmPrivateKey to authenticate with the ledger."
3854
+ );
3855
+ }
3856
+ logger?.info?.(
3857
+ `Authenticating ledger account ${accountId} (${resolvedNetwork.canonical})${labelSuffix}...`
3858
+ );
3859
+ const verification = await client.authenticateWithLedger(authOptions);
3860
+ if (setAccountHeader) {
3861
+ client.setDefaultHeader("x-account-id", verification.accountId);
3862
+ }
3863
+ logger?.info?.(
3864
+ `Ledger authentication complete${labelSuffix}. Issued key prefix: ${verification.apiKey.prefix}\u2026${verification.apiKey.lastFour}`
3865
+ );
3866
+ return verification;
3867
+ }
3868
+
3869
+ // ../../src/services/registry-broker/client/search.ts
3870
+ function buildVectorFallbackSearchParams(request) {
3871
+ const params = {
3872
+ q: request.query
3873
+ };
3874
+ let effectiveLimit;
3875
+ if (typeof request.limit === "number" && Number.isFinite(request.limit)) {
3876
+ effectiveLimit = request.limit;
3877
+ params.limit = request.limit;
3878
+ }
3879
+ if (typeof request.offset === "number" && Number.isFinite(request.offset) && request.offset > 0) {
3880
+ const limit = effectiveLimit && effectiveLimit > 0 ? effectiveLimit : 20;
3881
+ params.limit = limit;
3882
+ params.page = Math.floor(request.offset / limit) + 1;
3875
3883
  }
3876
- if (cipherEnvelope) {
3877
- body.cipherEnvelope = toJsonObject(cipherEnvelope);
3884
+ if (request.filter?.registry) {
3885
+ params.registry = request.filter.registry;
3878
3886
  }
3879
- const raw = await client.requestJson("/chat/message", {
3887
+ if (request.filter?.protocols?.length) {
3888
+ params.protocols = [...request.filter.protocols];
3889
+ }
3890
+ if (request.filter?.adapter?.length) {
3891
+ params.adapters = [...request.filter.adapter];
3892
+ }
3893
+ if (request.filter?.capabilities?.length) {
3894
+ params.capabilities = request.filter.capabilities.map(
3895
+ (value) => typeof value === "number" ? value.toString(10) : value
3896
+ );
3897
+ }
3898
+ if (request.filter?.type) {
3899
+ params.type = request.filter.type;
3900
+ }
3901
+ return params;
3902
+ }
3903
+ function convertSearchResultToVectorResponse(result) {
3904
+ const hits = result.hits.map((agent) => ({
3905
+ agent,
3906
+ score: 0,
3907
+ highlights: {}
3908
+ }));
3909
+ const total = result.total;
3910
+ const limit = result.limit;
3911
+ const page = result.page;
3912
+ const totalVisible = page * limit;
3913
+ const limited = total > totalVisible || page > 1;
3914
+ return {
3915
+ hits,
3916
+ total,
3917
+ took: 0,
3918
+ totalAvailable: total,
3919
+ visible: hits.length,
3920
+ limited,
3921
+ credits_used: 0
3922
+ };
3923
+ }
3924
+ async function search(client, params = {}) {
3925
+ const query = buildSearchQuery(params);
3926
+ const raw = await client.requestJson(`/search${query}`, {
3927
+ method: "GET"
3928
+ });
3929
+ return client.parseWithSchema(raw, searchResponseSchema, "search response");
3930
+ }
3931
+ async function delegate(client, request) {
3932
+ const raw = await client.requestJson("/delegate", {
3880
3933
  method: "POST",
3881
- body,
3934
+ body: request,
3882
3935
  headers: { "content-type": "application/json" }
3883
3936
  });
3884
3937
  return client.parseWithSchema(
3885
3938
  raw,
3886
- sendMessageResponseSchema,
3887
- "chat message response"
3939
+ delegationPlanResponseSchema,
3940
+ "delegate response"
3888
3941
  );
3889
3942
  }
3890
- async function endSession(client, sessionId) {
3891
- await client.request(`/chat/session/${encodeURIComponent(sessionId)}`, {
3892
- method: "DELETE"
3943
+ async function stats(client) {
3944
+ const raw = await client.requestJson("/stats", { method: "GET" });
3945
+ return client.parseWithSchema(raw, statsResponseSchema, "stats response");
3946
+ }
3947
+ async function registries(client) {
3948
+ const raw = await client.requestJson("/registries", {
3949
+ method: "GET"
3893
3950
  });
3951
+ return client.parseWithSchema(
3952
+ raw,
3953
+ registriesResponseSchema,
3954
+ "registries response"
3955
+ );
3894
3956
  }
3895
-
3896
- // ../../src/services/registry-broker/client/verification.ts
3897
- async function getVerificationStatus(client, uaid) {
3957
+ async function getAdditionalRegistries(client) {
3898
3958
  const raw = await client.requestJson(
3899
- `/verification/status/${encodeURIComponent(uaid)}`,
3900
- { method: "GET" }
3959
+ "/register/additional-registries",
3960
+ {
3961
+ method: "GET"
3962
+ }
3901
3963
  );
3902
3964
  return client.parseWithSchema(
3903
3965
  raw,
3904
- verificationStatusResponseSchema,
3905
- "verification status response"
3966
+ additionalRegistryCatalogResponseSchema,
3967
+ "additional registry catalog response"
3906
3968
  );
3907
3969
  }
3908
- async function createVerificationChallenge(client, uaid) {
3909
- const raw = await client.requestJson("/verification/challenge", {
3910
- method: "POST",
3911
- headers: { "content-type": "application/json" },
3912
- body: { uaid }
3970
+ async function popularSearches(client) {
3971
+ const raw = await client.requestJson("/popular", {
3972
+ method: "GET"
3913
3973
  });
3914
3974
  return client.parseWithSchema(
3915
3975
  raw,
3916
- verificationChallengeResponseSchema,
3917
- "verification challenge response"
3976
+ popularResponseSchema,
3977
+ "popular searches response"
3918
3978
  );
3919
3979
  }
3920
- async function getVerificationChallenge(client, challengeId) {
3921
- const raw = await client.requestJson(
3922
- `/verification/challenge/${encodeURIComponent(challengeId)}`,
3923
- { method: "GET" }
3924
- );
3980
+ async function listProtocols(client) {
3981
+ const raw = await client.requestJson("/protocols", {
3982
+ method: "GET"
3983
+ });
3925
3984
  return client.parseWithSchema(
3926
3985
  raw,
3927
- verificationChallengeDetailsResponseSchema,
3928
- "verification challenge details response"
3986
+ protocolsResponseSchema,
3987
+ "protocols response"
3929
3988
  );
3930
3989
  }
3931
- async function verifyVerificationChallenge(client, params) {
3932
- const raw = await client.requestJson("/verification/verify", {
3990
+ async function detectProtocol(client, message) {
3991
+ const raw = await client.requestJson("/detect-protocol", {
3933
3992
  method: "POST",
3934
- headers: { "content-type": "application/json" },
3935
- body: {
3936
- challengeId: params.challengeId,
3937
- method: params.method ?? "moltbook-post"
3938
- }
3993
+ body: { message },
3994
+ headers: { "content-type": "application/json" }
3939
3995
  });
3940
3996
  return client.parseWithSchema(
3941
3997
  raw,
3942
- verificationVerifyResponseSchema,
3943
- "verification verify response"
3944
- );
3945
- }
3946
- async function getVerificationOwnership(client, uaid) {
3947
- const raw = await client.requestJson(
3948
- `/verification/ownership/${encodeURIComponent(uaid)}`,
3949
- { method: "GET" }
3950
- );
3951
- return client.parseWithSchema(
3952
- raw,
3953
- verificationOwnershipResponseSchema,
3954
- "verification ownership response"
3998
+ detectProtocolResponseSchema,
3999
+ "detect protocol response"
3955
4000
  );
3956
4001
  }
3957
- async function verifySenderOwnership(client, uaid) {
4002
+ async function registrySearchByNamespace(client, registry, query) {
4003
+ const params = new URLSearchParams();
4004
+ if (query) {
4005
+ params.set("q", query);
4006
+ }
4007
+ const suffix = params.size > 0 ? `?${params.toString()}` : "";
3958
4008
  const raw = await client.requestJson(
3959
- "/verification/verify-sender",
4009
+ `/registries/${encodeURIComponent(registry)}/search${suffix}`,
3960
4010
  {
3961
- method: "POST",
3962
- headers: { "content-type": "application/json" },
3963
- body: { uaid }
4011
+ method: "GET"
3964
4012
  }
3965
4013
  );
3966
4014
  return client.parseWithSchema(
3967
4015
  raw,
3968
- verificationVerifySenderResponseSchema,
3969
- "verification sender response"
4016
+ registrySearchByNamespaceSchema,
4017
+ "registry search response"
3970
4018
  );
3971
4019
  }
3972
- async function verifyUaidDnsTxt(client, payload) {
3973
- const raw = await client.requestJson("/verification/dns/verify", {
3974
- method: "POST",
3975
- headers: { "content-type": "application/json" },
3976
- body: {
3977
- uaid: payload.uaid,
3978
- ...payload.persist !== void 0 ? { persist: payload.persist } : {}
4020
+ async function vectorSearch(client, request) {
4021
+ try {
4022
+ const raw = await client.requestJson("/search", {
4023
+ method: "POST",
4024
+ body: request,
4025
+ headers: { "content-type": "application/json" }
4026
+ });
4027
+ return client.parseWithSchema(
4028
+ raw,
4029
+ vectorSearchResponseSchema,
4030
+ "vector search response"
4031
+ );
4032
+ } catch (error) {
4033
+ if (error instanceof RegistryBrokerError && error.status === 501) {
4034
+ const fallback = await search(
4035
+ client,
4036
+ buildVectorFallbackSearchParams(request)
4037
+ );
4038
+ return convertSearchResultToVectorResponse(fallback);
3979
4039
  }
4040
+ throw error;
4041
+ }
4042
+ }
4043
+ async function searchStatus(client) {
4044
+ const raw = await client.requestJson("/search/status", {
4045
+ method: "GET"
3980
4046
  });
3981
4047
  return client.parseWithSchema(
3982
4048
  raw,
3983
- verificationDnsStatusResponseSchema,
3984
- "verification dns verify response"
4049
+ searchStatusResponseSchema,
4050
+ "search status response"
3985
4051
  );
3986
4052
  }
3987
- async function getVerificationDnsStatus(client, uaid, query) {
3988
- const params = new URLSearchParams();
3989
- if (query?.refresh !== void 0) {
3990
- params.set("refresh", String(query.refresh));
3991
- }
3992
- if (query?.persist !== void 0) {
3993
- params.set("persist", String(query.persist));
3994
- }
3995
- const queryString = params.toString();
3996
- const path2 = `/verification/dns/status/${encodeURIComponent(uaid)}${queryString ? `?${queryString}` : ""}`;
3997
- const raw = await client.requestJson(path2, {
4053
+ async function websocketStats(client) {
4054
+ const raw = await client.requestJson("/websocket/stats", {
3998
4055
  method: "GET"
3999
4056
  });
4000
4057
  return client.parseWithSchema(
4001
4058
  raw,
4002
- verificationDnsStatusResponseSchema,
4003
- "verification dns status response"
4059
+ websocketStatsResponseSchema,
4060
+ "websocket stats response"
4004
4061
  );
4005
4062
  }
4006
- async function getRegisterStatus(client, uaid) {
4007
- const raw = await client.requestJson(
4008
- `/register/status/${encodeURIComponent(uaid)}`,
4009
- { method: "GET" }
4010
- );
4063
+ async function metricsSummary(client) {
4064
+ const raw = await client.requestJson("/metrics", {
4065
+ method: "GET"
4066
+ });
4011
4067
  return client.parseWithSchema(
4012
4068
  raw,
4013
- registerStatusResponseSchema,
4014
- "register status response"
4069
+ metricsSummaryResponseSchema,
4070
+ "metrics summary response"
4015
4071
  );
4016
4072
  }
4017
- async function registerOwnedMoltbookAgent(client, uaid, request) {
4018
- const raw = await client.requestJson(
4019
- `/register/${encodeURIComponent(uaid)}`,
4020
- {
4021
- method: "PUT",
4022
- headers: { "content-type": "application/json" },
4023
- body: {
4024
- registered: request.registered ?? true,
4025
- ...request.name ? { name: request.name } : {},
4026
- ...request.description ? { description: request.description } : {},
4027
- ...request.endpoint ? { endpoint: request.endpoint } : {},
4028
- ...request.metadata ? { metadata: request.metadata } : {}
4029
- }
4030
- }
4031
- );
4073
+ async function facets(client, adapter) {
4074
+ const params = new URLSearchParams();
4075
+ if (adapter) {
4076
+ params.set("adapter", adapter);
4077
+ }
4078
+ const suffix = params.size > 0 ? `?${params.toString()}` : "";
4079
+ const raw = await client.requestJson(`/search/facets${suffix}`, {
4080
+ method: "GET"
4081
+ });
4032
4082
  return client.parseWithSchema(
4033
4083
  raw,
4034
- moltbookOwnerRegistrationUpdateResponseSchema,
4035
- "moltbook owner registration update response"
4084
+ searchFacetsResponseSchema,
4085
+ "search facets response"
4036
4086
  );
4037
4087
  }
4038
4088
 
@@ -4562,10 +4612,6 @@ async function verifySkillDomainProof(client, payload) {
4562
4612
  }
4563
4613
 
4564
4614
  // ../../src/services/registry-broker/client/base-client.ts
4565
- var import_buffer4 = require("buffer");
4566
- var import_crypto2 = require("crypto");
4567
- var import_secp256k12 = require("@noble/curves/secp256k1.js");
4568
- var import_zod3 = require("zod");
4569
4615
  var RegistryBrokerClient = class _RegistryBrokerClient {
4570
4616
  constructor(options = {}) {
4571
4617
  this.encryptionBootstrapPromise = null;
@@ -4682,11 +4728,11 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
4682
4728
  }
4683
4729
  await this.encryptionBootstrapPromise;
4684
4730
  }
4685
- buildUrl(path2) {
4686
- const normalisedPath = path2.startsWith("/") ? path2 : `/${path2}`;
4731
+ buildUrl(path) {
4732
+ const normalisedPath = path.startsWith("/") ? path : `/${path}`;
4687
4733
  return `${this.baseUrl}${normalisedPath}`;
4688
4734
  }
4689
- async request(path2, config) {
4735
+ async request(path, config) {
4690
4736
  const headers = new Headers();
4691
4737
  Object.entries(this.defaultHeaders).forEach(([key, value]) => {
4692
4738
  headers.set(key, value);
@@ -4712,7 +4758,7 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
4712
4758
  headers.set("content-type", "application/json");
4713
4759
  }
4714
4760
  }
4715
- const response = await this.fetchImpl(this.buildUrl(path2), init);
4761
+ const response = await this.fetchImpl(this.buildUrl(path), init);
4716
4762
  if (response.ok) {
4717
4763
  return response;
4718
4764
  }
@@ -4723,8 +4769,8 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
4723
4769
  body: errorBody
4724
4770
  });
4725
4771
  }
4726
- async requestJson(path2, config) {
4727
- const response = await this.request(path2, config);
4772
+ async requestJson(path, config) {
4773
+ const response = await this.request(path, config);
4728
4774
  const contentType = response.headers?.get("content-type") ?? "";
4729
4775
  if (!JSON_CONTENT_TYPE.test(contentType)) {
4730
4776
  const body = await response.text();
@@ -5294,12 +5340,12 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
5294
5340
  }
5295
5341
  return;
5296
5342
  }
5297
- await new Promise((resolve2, reject) => {
5343
+ await new Promise((resolve, reject) => {
5298
5344
  const timer = setTimeout(() => {
5299
5345
  if (signal) {
5300
5346
  signal.removeEventListener("abort", onAbort);
5301
5347
  }
5302
- resolve2();
5348
+ resolve();
5303
5349
  }, ms);
5304
5350
  const onAbort = () => {
5305
5351
  clearTimeout(timer);
@@ -5321,9 +5367,17 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
5321
5367
  throw new Error(`${feature} is only available in Node.js environments`);
5322
5368
  }
5323
5369
  }
5370
+ getNodeCrypto(feature) {
5371
+ this.assertNodeRuntime(feature);
5372
+ const nodeCrypto = optionalImportSync("node:crypto") ?? optionalImportSync("crypto");
5373
+ if (!nodeCrypto) {
5374
+ throw new Error(`${feature} requires the Node.js crypto module`);
5375
+ }
5376
+ return nodeCrypto;
5377
+ }
5324
5378
  createEphemeralKeyPair() {
5325
- this.assertNodeRuntime("generateEphemeralKeyPair");
5326
- const privateKeyBytes = (0, import_crypto2.randomBytes)(32);
5379
+ const { randomBytes } = this.getNodeCrypto("generateEphemeralKeyPair");
5380
+ const privateKeyBytes = randomBytes(32);
5327
5381
  const publicKey = import_secp256k12.secp256k1.getPublicKey(privateKeyBytes, true);
5328
5382
  return {
5329
5383
  privateKey: import_buffer4.Buffer.from(privateKeyBytes).toString("hex"),
@@ -5331,17 +5385,19 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
5331
5385
  };
5332
5386
  }
5333
5387
  deriveSharedSecret(options) {
5334
- this.assertNodeRuntime("deriveSharedSecret");
5388
+ const { createHash } = this.getNodeCrypto("deriveSharedSecret");
5335
5389
  const privateKey = this.hexToBuffer(options.privateKey);
5336
5390
  const peerPublicKey = this.hexToBuffer(options.peerPublicKey);
5337
5391
  const shared = import_secp256k12.secp256k1.getSharedSecret(privateKey, peerPublicKey, true);
5338
- return (0, import_crypto2.createHash)("sha256").update(import_buffer4.Buffer.from(shared)).digest();
5392
+ return createHash("sha256").update(import_buffer4.Buffer.from(shared)).digest();
5339
5393
  }
5340
5394
  buildCipherEnvelope(options) {
5341
- this.assertNodeRuntime("encryptCipherEnvelope");
5395
+ const { createCipheriv, randomBytes } = this.getNodeCrypto(
5396
+ "encryptCipherEnvelope"
5397
+ );
5342
5398
  const sharedSecret = this.normalizeSharedSecret(options.sharedSecret);
5343
- const iv = (0, import_crypto2.randomBytes)(12);
5344
- const cipher = (0, import_crypto2.createCipheriv)("aes-256-gcm", sharedSecret, iv);
5399
+ const iv = randomBytes(12);
5400
+ const cipher = createCipheriv("aes-256-gcm", sharedSecret, iv);
5345
5401
  const aadSource = options.associatedData ?? options.sessionId;
5346
5402
  const associatedDataEncoded = aadSource ? import_buffer4.Buffer.from(aadSource, "utf8").toString("base64") : void 0;
5347
5403
  if (aadSource) {
@@ -5369,13 +5425,13 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
5369
5425
  };
5370
5426
  }
5371
5427
  openCipherEnvelope(options) {
5372
- this.assertNodeRuntime("decryptCipherEnvelope");
5428
+ const { createDecipheriv } = this.getNodeCrypto("decryptCipherEnvelope");
5373
5429
  const sharedSecret = this.normalizeSharedSecret(options.sharedSecret);
5374
5430
  const payload = import_buffer4.Buffer.from(options.envelope.ciphertext, "base64");
5375
5431
  const nonce = import_buffer4.Buffer.from(options.envelope.nonce, "base64");
5376
5432
  const ciphertext = payload.slice(0, payload.length - 16);
5377
5433
  const tag = payload.slice(payload.length - 16);
5378
- const decipher = (0, import_crypto2.createDecipheriv)("aes-256-gcm", sharedSecret, nonce);
5434
+ const decipher = createDecipheriv("aes-256-gcm", sharedSecret, nonce);
5379
5435
  if (options.envelope.associatedData) {
5380
5436
  decipher.setAAD(import_buffer4.Buffer.from(options.envelope.associatedData, "base64"));
5381
5437
  }