@hol-org/rb-client 0.1.171 → 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 +2065 -1815
- package/dist/index.d.cts +17827 -114
- package/dist/index.d.ts +17827 -114
- package/dist/index.js +2050 -1816
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// ../../src/services/registry-broker/client/
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
1
|
+
// ../../src/services/registry-broker/client/base-client.ts
|
|
2
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
3
|
+
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1.js";
|
|
4
|
+
import { ZodError } from "zod";
|
|
6
5
|
|
|
7
6
|
// ../../src/services/registry-broker/schemas.ts
|
|
8
7
|
import { z as z2 } from "zod";
|
|
@@ -239,6 +238,13 @@ var metadataFacetSchema = z2.record(
|
|
|
239
238
|
jsonValueSchema
|
|
240
239
|
])
|
|
241
240
|
).optional();
|
|
241
|
+
var searchHitMetadataSchema = z2.object({
|
|
242
|
+
delegationRoles: jsonValueSchema.optional(),
|
|
243
|
+
delegationTaskTags: jsonValueSchema.optional(),
|
|
244
|
+
delegationProtocols: jsonValueSchema.optional(),
|
|
245
|
+
delegationSummary: jsonValueSchema.optional(),
|
|
246
|
+
delegationSignals: jsonValueSchema.optional()
|
|
247
|
+
}).passthrough();
|
|
242
248
|
var searchHitSchema = z2.object({
|
|
243
249
|
id: z2.string(),
|
|
244
250
|
uaid: z2.string(),
|
|
@@ -247,7 +253,7 @@ var searchHitSchema = z2.object({
|
|
|
247
253
|
description: z2.string().optional(),
|
|
248
254
|
capabilities: z2.array(capabilityValueSchema),
|
|
249
255
|
endpoints: z2.union([z2.record(jsonValueSchema), z2.array(z2.string())]).optional(),
|
|
250
|
-
metadata:
|
|
256
|
+
metadata: searchHitMetadataSchema.optional(),
|
|
251
257
|
metadataFacet: metadataFacetSchema,
|
|
252
258
|
profile: agentProfileSchema.optional(),
|
|
253
259
|
protocols: z2.array(z2.string()).optional(),
|
|
@@ -291,6 +297,62 @@ var popularResponseSchema = z2.object({
|
|
|
291
297
|
var resolveResponseSchema = z2.object({
|
|
292
298
|
agent: searchHitSchema
|
|
293
299
|
});
|
|
300
|
+
var delegationPlanCandidateSchema = z2.object({
|
|
301
|
+
uaid: z2.string(),
|
|
302
|
+
label: z2.string(),
|
|
303
|
+
registry: z2.string().optional(),
|
|
304
|
+
agent: searchHitSchema,
|
|
305
|
+
score: z2.number(),
|
|
306
|
+
matchedQueries: z2.array(z2.string()).optional(),
|
|
307
|
+
matchedRoles: z2.array(z2.string()).optional(),
|
|
308
|
+
matchedProtocols: z2.array(z2.string()).optional(),
|
|
309
|
+
matchedSurfaces: z2.array(z2.string()).optional(),
|
|
310
|
+
matchedLanguages: z2.array(z2.string()).optional(),
|
|
311
|
+
matchedArtifacts: z2.array(z2.string()).optional(),
|
|
312
|
+
matchedTaskTags: z2.array(z2.string()).optional(),
|
|
313
|
+
reasons: z2.array(z2.string()).optional(),
|
|
314
|
+
suggestedMessage: z2.string().optional(),
|
|
315
|
+
trustScore: z2.number().optional(),
|
|
316
|
+
verified: z2.boolean().optional(),
|
|
317
|
+
communicationSupported: z2.boolean().optional(),
|
|
318
|
+
availability: z2.boolean().optional(),
|
|
319
|
+
explanation: z2.string().optional()
|
|
320
|
+
}).passthrough();
|
|
321
|
+
var delegationOpportunitySchema = z2.object({
|
|
322
|
+
id: z2.string(),
|
|
323
|
+
title: z2.string(),
|
|
324
|
+
reason: z2.string(),
|
|
325
|
+
role: z2.string(),
|
|
326
|
+
type: z2.enum(["ai-agents", "mcp-servers"]),
|
|
327
|
+
suggestedMode: z2.enum(["best-match", "fallback", "parallel"]),
|
|
328
|
+
searchQueries: z2.array(z2.string()),
|
|
329
|
+
protocols: z2.array(z2.string()).optional(),
|
|
330
|
+
surfaces: z2.array(z2.string()).optional(),
|
|
331
|
+
languages: z2.array(z2.string()).optional(),
|
|
332
|
+
artifacts: z2.array(z2.string()).optional(),
|
|
333
|
+
candidates: z2.array(delegationPlanCandidateSchema)
|
|
334
|
+
}).passthrough();
|
|
335
|
+
var delegationRecommendationSchema = z2.object({
|
|
336
|
+
action: z2.enum(["delegate-now", "review-shortlist", "handle-locally"]),
|
|
337
|
+
confidence: z2.number(),
|
|
338
|
+
reason: z2.string(),
|
|
339
|
+
opportunityId: z2.string().optional(),
|
|
340
|
+
candidate: delegationPlanCandidateSchema.optional()
|
|
341
|
+
}).passthrough();
|
|
342
|
+
var delegationPlanResponseSchema = z2.object({
|
|
343
|
+
task: z2.string(),
|
|
344
|
+
context: z2.string().optional(),
|
|
345
|
+
summary: z2.string().optional(),
|
|
346
|
+
intents: z2.array(z2.string()),
|
|
347
|
+
protocols: z2.array(z2.string()),
|
|
348
|
+
surfaces: z2.array(z2.string()),
|
|
349
|
+
languages: z2.array(z2.string()).optional(),
|
|
350
|
+
artifacts: z2.array(z2.string()).optional(),
|
|
351
|
+
shouldDelegate: z2.boolean(),
|
|
352
|
+
localFirstReason: z2.string().optional(),
|
|
353
|
+
recommendation: delegationRecommendationSchema.optional(),
|
|
354
|
+
opportunities: z2.array(delegationOpportunitySchema)
|
|
355
|
+
}).passthrough();
|
|
294
356
|
var agentFeedbackSummarySchema = z2.object({
|
|
295
357
|
averageScore: z2.number(),
|
|
296
358
|
totalFeedbacks: z2.number(),
|
|
@@ -1519,285 +1581,171 @@ var skillVerificationDomainProofVerifyResponseSchema = z2.object({
|
|
|
1519
1581
|
signal: skillVerificationDomainProofSignalSchema
|
|
1520
1582
|
}).passthrough();
|
|
1521
1583
|
|
|
1522
|
-
// ../../src/
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
if (!
|
|
1584
|
+
// ../../src/services/registry-broker/client/chat-history.ts
|
|
1585
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
1586
|
+
function identitiesMatch(a, b) {
|
|
1587
|
+
if (!a && !b) {
|
|
1588
|
+
return true;
|
|
1589
|
+
}
|
|
1590
|
+
if (!a || !b) {
|
|
1529
1591
|
return false;
|
|
1530
1592
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
const messageText = typeof message === "string" ? message : "";
|
|
1534
|
-
if (typeof code === "string" && code.includes("MODULE_NOT_FOUND")) {
|
|
1535
|
-
return messageText.includes(specifier);
|
|
1593
|
+
if (a.uaid && b.uaid && a.uaid.toLowerCase() === b.uaid.toLowerCase()) {
|
|
1594
|
+
return true;
|
|
1536
1595
|
}
|
|
1537
|
-
if (
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1596
|
+
if (a.ledgerAccountId && b.ledgerAccountId && a.ledgerAccountId.toLowerCase() === b.ledgerAccountId.toLowerCase()) {
|
|
1597
|
+
return true;
|
|
1598
|
+
}
|
|
1599
|
+
if (a.userId && b.userId && a.userId === b.userId) {
|
|
1600
|
+
return true;
|
|
1601
|
+
}
|
|
1602
|
+
if (a.email && b.email && a.email.toLowerCase() === b.email.toLowerCase()) {
|
|
1603
|
+
return true;
|
|
1542
1604
|
}
|
|
1543
1605
|
return false;
|
|
1544
1606
|
}
|
|
1545
|
-
async function
|
|
1546
|
-
if (
|
|
1547
|
-
|
|
1607
|
+
async function fetchHistorySnapshot(conversationContexts, client, sessionId, options) {
|
|
1608
|
+
if (!sessionId || sessionId.trim().length === 0) {
|
|
1609
|
+
throw new Error("sessionId is required to fetch chat history");
|
|
1548
1610
|
}
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1611
|
+
const raw = await client.requestJson(
|
|
1612
|
+
`/chat/session/${encodeURIComponent(sessionId)}/history`,
|
|
1613
|
+
{
|
|
1614
|
+
method: "GET"
|
|
1615
|
+
}
|
|
1616
|
+
);
|
|
1617
|
+
const snapshot = client.parseWithSchema(
|
|
1618
|
+
raw,
|
|
1619
|
+
chatHistorySnapshotResponseSchema,
|
|
1620
|
+
"chat history snapshot response"
|
|
1621
|
+
);
|
|
1622
|
+
return attachDecryptedHistory(
|
|
1623
|
+
conversationContexts,
|
|
1624
|
+
client,
|
|
1625
|
+
sessionId,
|
|
1626
|
+
snapshot,
|
|
1627
|
+
options
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
function attachDecryptedHistory(conversationContexts, client, sessionId, snapshot, options) {
|
|
1631
|
+
const shouldDecrypt = options?.decrypt !== void 0 ? options.decrypt : client.encryptionOptions?.autoDecryptHistory === true;
|
|
1632
|
+
if (!shouldDecrypt) {
|
|
1633
|
+
return snapshot;
|
|
1552
1634
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1635
|
+
const requiresContext = snapshot.history.some(
|
|
1636
|
+
(entry) => Boolean(entry.cipherEnvelope)
|
|
1637
|
+
);
|
|
1638
|
+
if (!requiresContext) {
|
|
1639
|
+
return {
|
|
1640
|
+
...snapshot,
|
|
1641
|
+
decryptedHistory: snapshot.history.map((entry) => ({
|
|
1642
|
+
entry,
|
|
1643
|
+
plaintext: entry.content
|
|
1644
|
+
}))
|
|
1645
|
+
};
|
|
1559
1646
|
}
|
|
1560
|
-
|
|
1647
|
+
const context = resolveDecryptionContext(
|
|
1648
|
+
conversationContexts,
|
|
1649
|
+
client,
|
|
1650
|
+
sessionId,
|
|
1651
|
+
options
|
|
1652
|
+
);
|
|
1653
|
+
if (!context) {
|
|
1654
|
+
throw new Error(
|
|
1655
|
+
"Unable to decrypt chat history: encryption context unavailable"
|
|
1656
|
+
);
|
|
1657
|
+
}
|
|
1658
|
+
const decryptedHistory = snapshot.history.map((entry) => ({
|
|
1659
|
+
entry,
|
|
1660
|
+
plaintext: decryptHistoryEntryFromContext(client, entry, context)
|
|
1661
|
+
}));
|
|
1662
|
+
return { ...snapshot, decryptedHistory };
|
|
1561
1663
|
}
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1664
|
+
function registerConversationContextForEncryption(conversationContexts, context) {
|
|
1665
|
+
const normalized = {
|
|
1666
|
+
sessionId: context.sessionId,
|
|
1667
|
+
sharedSecret: Buffer2.from(context.sharedSecret),
|
|
1668
|
+
identity: context.identity ? { ...context.identity } : void 0
|
|
1669
|
+
};
|
|
1670
|
+
const entries = conversationContexts.get(context.sessionId) ?? [];
|
|
1671
|
+
const existingIndex = entries.findIndex(
|
|
1672
|
+
(existing) => identitiesMatch(existing.identity, normalized.identity)
|
|
1673
|
+
);
|
|
1674
|
+
if (existingIndex >= 0) {
|
|
1675
|
+
entries[existingIndex] = normalized;
|
|
1676
|
+
} else {
|
|
1677
|
+
entries.push(normalized);
|
|
1570
1678
|
}
|
|
1679
|
+
conversationContexts.set(context.sessionId, entries);
|
|
1571
1680
|
}
|
|
1572
|
-
|
|
1573
|
-
if (
|
|
1574
|
-
return
|
|
1681
|
+
function resolveDecryptionContext(conversationContexts, client, sessionId, options) {
|
|
1682
|
+
if (options?.sharedSecret) {
|
|
1683
|
+
return {
|
|
1684
|
+
sessionId,
|
|
1685
|
+
sharedSecret: client.normalizeSharedSecret(options.sharedSecret),
|
|
1686
|
+
identity: options.identity
|
|
1687
|
+
};
|
|
1575
1688
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1689
|
+
const contexts = conversationContexts.get(sessionId);
|
|
1690
|
+
if (!contexts || contexts.length === 0) {
|
|
1691
|
+
return null;
|
|
1692
|
+
}
|
|
1693
|
+
if (options?.identity) {
|
|
1694
|
+
const match = contexts.find(
|
|
1695
|
+
(context) => identitiesMatch(context.identity, options.identity)
|
|
1696
|
+
);
|
|
1697
|
+
if (match) {
|
|
1698
|
+
return match;
|
|
1586
1699
|
}
|
|
1587
1700
|
}
|
|
1588
|
-
return
|
|
1701
|
+
return contexts[0];
|
|
1589
1702
|
}
|
|
1590
|
-
function
|
|
1591
|
-
|
|
1592
|
-
|
|
1703
|
+
function decryptHistoryEntryFromContext(client, entry, context) {
|
|
1704
|
+
const envelope = entry.cipherEnvelope;
|
|
1705
|
+
if (!envelope) {
|
|
1706
|
+
return entry.content;
|
|
1593
1707
|
}
|
|
1708
|
+
const secret = Buffer2.from(context.sharedSecret);
|
|
1594
1709
|
try {
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
if (!isModuleNotFound(specifier, error)) {
|
|
1602
|
-
throw error;
|
|
1603
|
-
}
|
|
1710
|
+
return client.encryption.decryptCipherEnvelope({
|
|
1711
|
+
envelope,
|
|
1712
|
+
sharedSecret: secret
|
|
1713
|
+
});
|
|
1714
|
+
} catch (_error) {
|
|
1715
|
+
return null;
|
|
1604
1716
|
}
|
|
1605
|
-
return null;
|
|
1606
1717
|
}
|
|
1607
1718
|
|
|
1608
|
-
// ../../src/services/registry-broker/client/
|
|
1609
|
-
var
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1719
|
+
// ../../src/services/registry-broker/client/utils.ts
|
|
1720
|
+
var DEFAULT_USER_AGENT = "@hol-org/rb-client";
|
|
1721
|
+
var DEFAULT_PROGRESS_INTERVAL_MS = 1500;
|
|
1722
|
+
var DEFAULT_PROGRESS_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1723
|
+
var DEFAULT_BASE_URL = "https://hol.org/registry/api/v1";
|
|
1724
|
+
var JSON_CONTENT_TYPE = /application\/json/i;
|
|
1725
|
+
var DEFAULT_HISTORY_TOP_UP_HBAR = 0.25;
|
|
1726
|
+
var MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS = 1;
|
|
1727
|
+
var stripTrailingSlashes = (value) => {
|
|
1728
|
+
let end = value.length;
|
|
1729
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) {
|
|
1730
|
+
end -= 1;
|
|
1613
1731
|
}
|
|
1614
|
-
return
|
|
1732
|
+
return end === value.length ? value : value.slice(0, end);
|
|
1615
1733
|
};
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
return client.parseWithSchema(
|
|
1623
|
-
raw,
|
|
1624
|
-
registerEncryptionKeyResponseSchema,
|
|
1625
|
-
"register encryption key response"
|
|
1626
|
-
);
|
|
1627
|
-
}
|
|
1628
|
-
function normalizeAutoRegisterIdentity(config) {
|
|
1629
|
-
const identity = {};
|
|
1630
|
-
if (config.uaid) {
|
|
1631
|
-
identity.uaid = config.uaid;
|
|
1734
|
+
var createAbortError = () => typeof DOMException === "function" ? new DOMException("Aborted", "AbortError") : new Error("The operation was aborted");
|
|
1735
|
+
var normaliseHeaderName = (name) => name.trim().toLowerCase();
|
|
1736
|
+
var isBrowserRuntime = () => typeof window !== "undefined" && typeof window.fetch === "function";
|
|
1737
|
+
var toJsonValue = (value) => {
|
|
1738
|
+
if (value === null) {
|
|
1739
|
+
return null;
|
|
1632
1740
|
}
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1635
|
-
if (config.ledgerNetwork) {
|
|
1636
|
-
identity.ledgerNetwork = config.ledgerNetwork;
|
|
1637
|
-
}
|
|
1741
|
+
if (value instanceof Date) {
|
|
1742
|
+
return value.toISOString();
|
|
1638
1743
|
}
|
|
1639
|
-
if (
|
|
1640
|
-
|
|
1744
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1745
|
+
return value;
|
|
1641
1746
|
}
|
|
1642
|
-
if (
|
|
1643
|
-
return
|
|
1644
|
-
}
|
|
1645
|
-
return null;
|
|
1646
|
-
}
|
|
1647
|
-
function derivePublicKeyFromPrivateKey(client, privateKey) {
|
|
1648
|
-
const normalized = client.hexToBuffer(privateKey);
|
|
1649
|
-
const publicKey = secp256k1.getPublicKey(normalized, true);
|
|
1650
|
-
return Buffer2.from(publicKey).toString("hex");
|
|
1651
|
-
}
|
|
1652
|
-
async function resolveAutoRegisterKeyMaterial(client, config) {
|
|
1653
|
-
if (config.publicKey?.trim()) {
|
|
1654
|
-
return { publicKey: config.publicKey.trim() };
|
|
1655
|
-
}
|
|
1656
|
-
let privateKey = config.privateKey?.trim();
|
|
1657
|
-
const envVar = config.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
|
|
1658
|
-
if (!privateKey && envVar && process?.env?.[envVar]?.trim()) {
|
|
1659
|
-
privateKey = process.env[envVar]?.trim();
|
|
1660
|
-
}
|
|
1661
|
-
if (!privateKey && config.generateIfMissing) {
|
|
1662
|
-
const pair = await client.generateEncryptionKeyPair({
|
|
1663
|
-
keyType: config.keyType ?? "secp256k1",
|
|
1664
|
-
envVar,
|
|
1665
|
-
envPath: config.envPath,
|
|
1666
|
-
overwrite: config.overwriteEnv
|
|
1667
|
-
});
|
|
1668
|
-
return { publicKey: pair.publicKey, privateKey: pair.privateKey };
|
|
1669
|
-
}
|
|
1670
|
-
if (privateKey) {
|
|
1671
|
-
const publicKey = derivePublicKeyFromPrivateKey(client, privateKey);
|
|
1672
|
-
return { publicKey, privateKey };
|
|
1673
|
-
}
|
|
1674
|
-
return null;
|
|
1675
|
-
}
|
|
1676
|
-
async function autoRegisterEncryptionKey(client, config) {
|
|
1677
|
-
const identity = normalizeAutoRegisterIdentity(config);
|
|
1678
|
-
if (!identity) {
|
|
1679
|
-
throw new Error(
|
|
1680
|
-
"Auto-registration requires uaid, ledgerAccountId, or email"
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1683
|
-
const material = await resolveAutoRegisterKeyMaterial(client, config);
|
|
1684
|
-
if (!material) {
|
|
1685
|
-
throw new Error(
|
|
1686
|
-
"Unable to resolve encryption public key for auto-registration"
|
|
1687
|
-
);
|
|
1688
|
-
}
|
|
1689
|
-
await registerEncryptionKey(client, {
|
|
1690
|
-
keyType: config.keyType ?? "secp256k1",
|
|
1691
|
-
publicKey: material.publicKey,
|
|
1692
|
-
...identity
|
|
1693
|
-
});
|
|
1694
|
-
return material;
|
|
1695
|
-
}
|
|
1696
|
-
async function ensureAgentEncryptionKey(client, options) {
|
|
1697
|
-
return autoRegisterEncryptionKey(client, {
|
|
1698
|
-
...options,
|
|
1699
|
-
uaid: options.uaid,
|
|
1700
|
-
enabled: true
|
|
1701
|
-
});
|
|
1702
|
-
}
|
|
1703
|
-
function createEncryptionApi(client) {
|
|
1704
|
-
return {
|
|
1705
|
-
registerKey: (payload) => registerEncryptionKey(client, payload),
|
|
1706
|
-
generateEphemeralKeyPair: () => client.createEphemeralKeyPair(),
|
|
1707
|
-
deriveSharedSecret: (options) => client.deriveSharedSecret(options),
|
|
1708
|
-
encryptCipherEnvelope: (options) => client.buildCipherEnvelope(options),
|
|
1709
|
-
decryptCipherEnvelope: (options) => client.openCipherEnvelope(options),
|
|
1710
|
-
ensureAgentKey: (options) => ensureAgentEncryptionKey(client, options)
|
|
1711
|
-
};
|
|
1712
|
-
}
|
|
1713
|
-
async function bootstrapEncryptionOptions(client, options) {
|
|
1714
|
-
if (!options?.autoRegister || options.autoRegister.enabled === false) {
|
|
1715
|
-
return null;
|
|
1716
|
-
}
|
|
1717
|
-
return autoRegisterEncryptionKey(client, options.autoRegister);
|
|
1718
|
-
}
|
|
1719
|
-
async function generateEncryptionKeyPair(client, options = {}) {
|
|
1720
|
-
client.assertNodeRuntime("generateEncryptionKeyPair");
|
|
1721
|
-
const keyType = options.keyType ?? "secp256k1";
|
|
1722
|
-
if (keyType !== "secp256k1") {
|
|
1723
|
-
throw new Error("Only secp256k1 key generation is supported currently");
|
|
1724
|
-
}
|
|
1725
|
-
const privateKeyBytes = randomBytes(32);
|
|
1726
|
-
const privateKey = Buffer2.from(privateKeyBytes).toString("hex");
|
|
1727
|
-
const publicKeyBytes = secp256k1.getPublicKey(privateKeyBytes, true);
|
|
1728
|
-
const publicKey = Buffer2.from(publicKeyBytes).toString("hex");
|
|
1729
|
-
const envVar = options.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
|
|
1730
|
-
const resolvedPath = options.envPath ? path.resolve(options.envPath) : void 0;
|
|
1731
|
-
if (resolvedPath) {
|
|
1732
|
-
const fsModule = await getFs();
|
|
1733
|
-
if (!fsModule) {
|
|
1734
|
-
throw new Error(
|
|
1735
|
-
"File system module is not available; cannot write encryption key env file"
|
|
1736
|
-
);
|
|
1737
|
-
}
|
|
1738
|
-
const envLine = `${envVar}=${privateKey}`;
|
|
1739
|
-
if (fsModule.existsSync(resolvedPath)) {
|
|
1740
|
-
const content = fsModule.readFileSync(resolvedPath, "utf-8");
|
|
1741
|
-
const lineRegex = new RegExp(`^${envVar}=.*$`, "m");
|
|
1742
|
-
if (lineRegex.test(content)) {
|
|
1743
|
-
if (!options.overwrite) {
|
|
1744
|
-
throw new Error(
|
|
1745
|
-
`${envVar} already exists in ${resolvedPath}; set overwrite=true to replace it`
|
|
1746
|
-
);
|
|
1747
|
-
}
|
|
1748
|
-
const updated = content.replace(lineRegex, envLine);
|
|
1749
|
-
fsModule.writeFileSync(resolvedPath, updated);
|
|
1750
|
-
} else {
|
|
1751
|
-
const needsNewline = !content.endsWith("\n");
|
|
1752
|
-
fsModule.appendFileSync(
|
|
1753
|
-
resolvedPath,
|
|
1754
|
-
`${needsNewline ? "\n" : ""}${envLine}
|
|
1755
|
-
`
|
|
1756
|
-
);
|
|
1757
|
-
}
|
|
1758
|
-
} else {
|
|
1759
|
-
fsModule.writeFileSync(resolvedPath, `${envLine}
|
|
1760
|
-
`);
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
return {
|
|
1764
|
-
privateKey,
|
|
1765
|
-
publicKey,
|
|
1766
|
-
envPath: resolvedPath,
|
|
1767
|
-
envVar
|
|
1768
|
-
};
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
// ../../src/services/registry-broker/client/utils.ts
|
|
1772
|
-
var DEFAULT_USER_AGENT = "@hol-org/rb-client";
|
|
1773
|
-
var DEFAULT_PROGRESS_INTERVAL_MS = 1500;
|
|
1774
|
-
var DEFAULT_PROGRESS_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1775
|
-
var DEFAULT_BASE_URL = "https://hol.org/registry/api/v1";
|
|
1776
|
-
var JSON_CONTENT_TYPE = /application\/json/i;
|
|
1777
|
-
var DEFAULT_HISTORY_TOP_UP_HBAR = 0.25;
|
|
1778
|
-
var MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS = 1;
|
|
1779
|
-
var stripTrailingSlashes = (value) => {
|
|
1780
|
-
let end = value.length;
|
|
1781
|
-
while (end > 0 && value.charCodeAt(end - 1) === 47) {
|
|
1782
|
-
end -= 1;
|
|
1783
|
-
}
|
|
1784
|
-
return end === value.length ? value : value.slice(0, end);
|
|
1785
|
-
};
|
|
1786
|
-
var createAbortError = () => typeof DOMException === "function" ? new DOMException("Aborted", "AbortError") : new Error("The operation was aborted");
|
|
1787
|
-
var normaliseHeaderName = (name) => name.trim().toLowerCase();
|
|
1788
|
-
var isBrowserRuntime = () => typeof window !== "undefined" && typeof window.fetch === "function";
|
|
1789
|
-
var toJsonValue = (value) => {
|
|
1790
|
-
if (value === null) {
|
|
1791
|
-
return null;
|
|
1792
|
-
}
|
|
1793
|
-
if (value instanceof Date) {
|
|
1794
|
-
return value.toISOString();
|
|
1795
|
-
}
|
|
1796
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1797
|
-
return value;
|
|
1798
|
-
}
|
|
1799
|
-
if (Array.isArray(value)) {
|
|
1800
|
-
return value.map((item) => item === void 0 ? null : toJsonValue(item));
|
|
1747
|
+
if (Array.isArray(value)) {
|
|
1748
|
+
return value.map((item) => item === void 0 ? null : toJsonValue(item));
|
|
1801
1749
|
}
|
|
1802
1750
|
if (typeof value === "object") {
|
|
1803
1751
|
const result = {};
|
|
@@ -1991,1818 +1939,2090 @@ function buildSearchQuery(params) {
|
|
|
1991
1939
|
return queryString.length > 0 ? `?${queryString}` : "";
|
|
1992
1940
|
}
|
|
1993
1941
|
|
|
1994
|
-
// ../../src/services/registry-broker/client/
|
|
1995
|
-
var
|
|
1996
|
-
constructor(
|
|
1997
|
-
super(
|
|
1998
|
-
this.
|
|
1999
|
-
this.
|
|
2000
|
-
this.body = details.body;
|
|
2001
|
-
}
|
|
2002
|
-
};
|
|
2003
|
-
var RegistryBrokerParseError = class extends Error {
|
|
2004
|
-
constructor(message, cause, rawValue) {
|
|
2005
|
-
super(message);
|
|
2006
|
-
this.cause = cause;
|
|
2007
|
-
this.rawValue = rawValue;
|
|
1942
|
+
// ../../src/services/registry-broker/client/encrypted-chat-manager.ts
|
|
1943
|
+
var EncryptionUnavailableError = class extends Error {
|
|
1944
|
+
constructor(sessionId, summary) {
|
|
1945
|
+
super("Encryption is not enabled for this session");
|
|
1946
|
+
this.sessionId = sessionId;
|
|
1947
|
+
this.summary = summary;
|
|
2008
1948
|
}
|
|
2009
1949
|
};
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
const params = {
|
|
2014
|
-
q: request.query
|
|
2015
|
-
};
|
|
2016
|
-
let effectiveLimit;
|
|
2017
|
-
if (typeof request.limit === "number" && Number.isFinite(request.limit)) {
|
|
2018
|
-
effectiveLimit = request.limit;
|
|
2019
|
-
params.limit = request.limit;
|
|
2020
|
-
}
|
|
2021
|
-
if (typeof request.offset === "number" && Number.isFinite(request.offset) && request.offset > 0) {
|
|
2022
|
-
const limit = effectiveLimit && effectiveLimit > 0 ? effectiveLimit : 20;
|
|
2023
|
-
params.limit = limit;
|
|
2024
|
-
params.page = Math.floor(request.offset / limit) + 1;
|
|
2025
|
-
}
|
|
2026
|
-
if (request.filter?.registry) {
|
|
2027
|
-
params.registry = request.filter.registry;
|
|
1950
|
+
var EncryptedChatManager = class {
|
|
1951
|
+
constructor(client) {
|
|
1952
|
+
this.client = client;
|
|
2028
1953
|
}
|
|
2029
|
-
|
|
2030
|
-
|
|
1954
|
+
registerConversationContext(context) {
|
|
1955
|
+
this.client.registerConversationContextForEncryption(context);
|
|
2031
1956
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
1957
|
+
async startSession(options) {
|
|
1958
|
+
await this.client.encryptionReady();
|
|
1959
|
+
const session = await this.client.chat.createSession({
|
|
1960
|
+
uaid: options.uaid,
|
|
1961
|
+
senderUaid: options.senderUaid,
|
|
1962
|
+
encryptionRequested: true,
|
|
1963
|
+
historyTtlSeconds: options.historyTtlSeconds,
|
|
1964
|
+
auth: options.auth
|
|
1965
|
+
});
|
|
1966
|
+
options.onSessionCreated?.(session.sessionId);
|
|
1967
|
+
const summary = session.encryption;
|
|
1968
|
+
if (!summary?.enabled) {
|
|
1969
|
+
throw new EncryptionUnavailableError(
|
|
1970
|
+
session.sessionId,
|
|
1971
|
+
session.encryption ?? null
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1974
|
+
const handle = await this.establishRequesterContext({
|
|
1975
|
+
sessionId: session.sessionId,
|
|
1976
|
+
summary,
|
|
1977
|
+
senderUaid: options.senderUaid,
|
|
1978
|
+
handshakeTimeoutMs: options.handshakeTimeoutMs,
|
|
1979
|
+
pollIntervalMs: options.pollIntervalMs
|
|
1980
|
+
});
|
|
1981
|
+
return handle;
|
|
2034
1982
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
1983
|
+
async acceptSession(options) {
|
|
1984
|
+
await this.client.encryptionReady();
|
|
1985
|
+
const summary = await this.waitForEncryptionSummary(
|
|
1986
|
+
options.sessionId,
|
|
1987
|
+
options.handshakeTimeoutMs,
|
|
1988
|
+
options.pollIntervalMs
|
|
2038
1989
|
);
|
|
1990
|
+
const handle = await this.establishResponderContext({
|
|
1991
|
+
sessionId: options.sessionId,
|
|
1992
|
+
summary,
|
|
1993
|
+
responderUaid: options.responderUaid,
|
|
1994
|
+
handshakeTimeoutMs: options.handshakeTimeoutMs,
|
|
1995
|
+
pollIntervalMs: options.pollIntervalMs
|
|
1996
|
+
});
|
|
1997
|
+
return handle;
|
|
2039
1998
|
}
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
return {
|
|
2057
|
-
hits,
|
|
2058
|
-
total,
|
|
2059
|
-
took: 0,
|
|
2060
|
-
totalAvailable: total,
|
|
2061
|
-
visible: hits.length,
|
|
2062
|
-
limited,
|
|
2063
|
-
credits_used: 0
|
|
2064
|
-
};
|
|
2065
|
-
}
|
|
2066
|
-
async function search(client, params = {}) {
|
|
2067
|
-
const query = buildSearchQuery(params);
|
|
2068
|
-
const raw = await client.requestJson(`/search${query}`, {
|
|
2069
|
-
method: "GET"
|
|
2070
|
-
});
|
|
2071
|
-
return client.parseWithSchema(raw, searchResponseSchema, "search response");
|
|
2072
|
-
}
|
|
2073
|
-
async function stats(client) {
|
|
2074
|
-
const raw = await client.requestJson("/stats", { method: "GET" });
|
|
2075
|
-
return client.parseWithSchema(raw, statsResponseSchema, "stats response");
|
|
2076
|
-
}
|
|
2077
|
-
async function registries(client) {
|
|
2078
|
-
const raw = await client.requestJson("/registries", {
|
|
2079
|
-
method: "GET"
|
|
2080
|
-
});
|
|
2081
|
-
return client.parseWithSchema(
|
|
2082
|
-
raw,
|
|
2083
|
-
registriesResponseSchema,
|
|
2084
|
-
"registries response"
|
|
2085
|
-
);
|
|
2086
|
-
}
|
|
2087
|
-
async function getAdditionalRegistries(client) {
|
|
2088
|
-
const raw = await client.requestJson(
|
|
2089
|
-
"/register/additional-registries",
|
|
2090
|
-
{
|
|
2091
|
-
method: "GET"
|
|
1999
|
+
async establishRequesterContext(params) {
|
|
2000
|
+
const keyPair = this.client.encryption.generateEphemeralKeyPair();
|
|
2001
|
+
await this.client.chat.submitEncryptionHandshake(params.sessionId, {
|
|
2002
|
+
role: "requester",
|
|
2003
|
+
keyType: "secp256k1",
|
|
2004
|
+
ephemeralPublicKey: keyPair.publicKey,
|
|
2005
|
+
uaid: params.senderUaid ?? params.summary.requester?.uaid ?? void 0
|
|
2006
|
+
});
|
|
2007
|
+
const { summary, record } = await this.waitForHandshakeCompletion(
|
|
2008
|
+
params.sessionId,
|
|
2009
|
+
params.handshakeTimeoutMs,
|
|
2010
|
+
params.pollIntervalMs
|
|
2011
|
+
);
|
|
2012
|
+
const responderKey = record.responder?.ephemeralPublicKey;
|
|
2013
|
+
if (!responderKey) {
|
|
2014
|
+
throw new Error("Responder handshake was not completed in time");
|
|
2092
2015
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2016
|
+
const sharedSecret = this.client.encryption.deriveSharedSecret({
|
|
2017
|
+
privateKey: keyPair.privateKey,
|
|
2018
|
+
peerPublicKey: responderKey
|
|
2019
|
+
}).subarray();
|
|
2020
|
+
const recipients = this.buildRecipients(summary);
|
|
2021
|
+
return this.createHandle({
|
|
2022
|
+
sessionId: params.sessionId,
|
|
2023
|
+
sharedSecret,
|
|
2024
|
+
summary,
|
|
2025
|
+
recipients,
|
|
2026
|
+
identity: summary.requester ?? void 0
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
async establishResponderContext(params) {
|
|
2030
|
+
const keyPair = this.client.encryption.generateEphemeralKeyPair();
|
|
2031
|
+
await this.client.chat.submitEncryptionHandshake(params.sessionId, {
|
|
2032
|
+
role: "responder",
|
|
2033
|
+
keyType: "secp256k1",
|
|
2034
|
+
ephemeralPublicKey: keyPair.publicKey,
|
|
2035
|
+
uaid: params.responderUaid ?? params.summary.responder?.uaid ?? void 0
|
|
2036
|
+
});
|
|
2037
|
+
const { summary, record } = await this.waitForHandshakeCompletion(
|
|
2038
|
+
params.sessionId,
|
|
2039
|
+
params.handshakeTimeoutMs,
|
|
2040
|
+
params.pollIntervalMs
|
|
2041
|
+
);
|
|
2042
|
+
const requesterKey = record.requester?.ephemeralPublicKey;
|
|
2043
|
+
if (!requesterKey) {
|
|
2044
|
+
throw new Error("Requester handshake was not detected in time");
|
|
2045
|
+
}
|
|
2046
|
+
const sharedSecret = this.client.encryption.deriveSharedSecret({
|
|
2047
|
+
privateKey: keyPair.privateKey,
|
|
2048
|
+
peerPublicKey: requesterKey
|
|
2049
|
+
}).subarray();
|
|
2050
|
+
const recipients = this.buildRecipients(summary);
|
|
2051
|
+
return this.createHandle({
|
|
2052
|
+
sessionId: params.sessionId,
|
|
2053
|
+
sharedSecret,
|
|
2054
|
+
summary,
|
|
2055
|
+
recipients,
|
|
2056
|
+
identity: summary.responder ?? void 0
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
async waitForHandshakeCompletion(sessionId, timeoutMs = 3e4, pollIntervalMs = 1e3) {
|
|
2060
|
+
const deadline = Date.now() + timeoutMs;
|
|
2061
|
+
while (true) {
|
|
2062
|
+
const status = await this.client.chat.getEncryptionStatus(sessionId);
|
|
2063
|
+
const summary = status.encryption;
|
|
2064
|
+
const record = summary?.handshake;
|
|
2065
|
+
if (summary && record && record.status === "complete") {
|
|
2066
|
+
return { summary, record };
|
|
2067
|
+
}
|
|
2068
|
+
if (Date.now() >= deadline) {
|
|
2069
|
+
throw new Error("Timed out waiting for encrypted handshake completion");
|
|
2070
|
+
}
|
|
2071
|
+
await this.delay(pollIntervalMs);
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
async waitForEncryptionSummary(sessionId, _timeoutMs = 3e4, _pollIntervalMs = 1e3) {
|
|
2075
|
+
const status = await this.client.chat.getEncryptionStatus(sessionId);
|
|
2076
|
+
if (!status.encryption?.enabled) {
|
|
2077
|
+
throw new EncryptionUnavailableError(
|
|
2078
|
+
sessionId,
|
|
2079
|
+
status.encryption ?? null
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
return status.encryption;
|
|
2083
|
+
}
|
|
2084
|
+
buildRecipients(summary) {
|
|
2085
|
+
const candidates = [summary.requester, summary.responder].filter(Boolean);
|
|
2086
|
+
const normalized = candidates.map((candidate) => {
|
|
2087
|
+
if (!candidate) {
|
|
2088
|
+
return null;
|
|
2089
|
+
}
|
|
2090
|
+
const recipient = {};
|
|
2091
|
+
if (candidate.uaid) {
|
|
2092
|
+
recipient.uaid = candidate.uaid;
|
|
2093
|
+
}
|
|
2094
|
+
if (candidate.ledgerAccountId) {
|
|
2095
|
+
recipient.ledgerAccountId = candidate.ledgerAccountId;
|
|
2096
|
+
}
|
|
2097
|
+
if (candidate.userId) {
|
|
2098
|
+
recipient.userId = candidate.userId;
|
|
2099
|
+
}
|
|
2100
|
+
if (candidate.email) {
|
|
2101
|
+
recipient.email = candidate.email;
|
|
2102
|
+
}
|
|
2103
|
+
return recipient;
|
|
2104
|
+
}).filter(
|
|
2105
|
+
(entry) => Boolean(
|
|
2106
|
+
entry?.uaid || entry?.ledgerAccountId || entry?.userId || entry?.email
|
|
2107
|
+
)
|
|
2108
|
+
);
|
|
2109
|
+
if (normalized.length > 0) {
|
|
2110
|
+
return normalized;
|
|
2111
|
+
}
|
|
2112
|
+
if (summary.responder?.uaid) {
|
|
2113
|
+
return [{ uaid: summary.responder.uaid }];
|
|
2114
|
+
}
|
|
2115
|
+
return [];
|
|
2116
|
+
}
|
|
2117
|
+
createHandle(context) {
|
|
2118
|
+
const sharedSecret = context.sharedSecret;
|
|
2119
|
+
const uaid = context.summary.requester?.uaid ?? context.summary.responder?.uaid ?? context.identity?.uaid;
|
|
2120
|
+
const decryptHistoryEntry = (entry) => this.decryptEntry(entry, context.identity, sharedSecret);
|
|
2121
|
+
const fetchHistory = async (options) => {
|
|
2122
|
+
const snapshot = await this.client.fetchHistorySnapshot(
|
|
2123
|
+
context.sessionId,
|
|
2124
|
+
options
|
|
2125
|
+
);
|
|
2126
|
+
if (snapshot.decryptedHistory) {
|
|
2127
|
+
return snapshot.decryptedHistory;
|
|
2128
|
+
}
|
|
2129
|
+
return snapshot.history.map((entry) => ({
|
|
2130
|
+
entry,
|
|
2131
|
+
plaintext: decryptHistoryEntry(entry)
|
|
2132
|
+
}));
|
|
2133
|
+
};
|
|
2134
|
+
const handle = {
|
|
2135
|
+
sessionId: context.sessionId,
|
|
2136
|
+
mode: "encrypted",
|
|
2137
|
+
summary: context.summary,
|
|
2138
|
+
send: async (options) => {
|
|
2139
|
+
const recipients = options.recipients ?? context.recipients;
|
|
2140
|
+
return this.client.chat.sendMessage({
|
|
2141
|
+
sessionId: context.sessionId,
|
|
2142
|
+
message: options.message ?? "[ciphertext omitted]",
|
|
2143
|
+
streaming: options.streaming,
|
|
2144
|
+
auth: options.auth,
|
|
2145
|
+
uaid,
|
|
2146
|
+
encryption: {
|
|
2147
|
+
plaintext: options.plaintext,
|
|
2148
|
+
sharedSecret: Buffer.from(sharedSecret),
|
|
2149
|
+
recipients
|
|
2150
|
+
}
|
|
2151
|
+
});
|
|
2152
|
+
},
|
|
2153
|
+
decryptHistoryEntry,
|
|
2154
|
+
fetchHistory
|
|
2155
|
+
};
|
|
2156
|
+
this.registerConversationContext({
|
|
2157
|
+
sessionId: context.sessionId,
|
|
2158
|
+
sharedSecret,
|
|
2159
|
+
identity: context.identity
|
|
2160
|
+
});
|
|
2161
|
+
return handle;
|
|
2162
|
+
}
|
|
2163
|
+
decryptEntry(entry, identity, fallbackSecret) {
|
|
2164
|
+
const envelope = entry.cipherEnvelope;
|
|
2165
|
+
if (!envelope) {
|
|
2166
|
+
return null;
|
|
2167
|
+
}
|
|
2168
|
+
const secret = Buffer.from(fallbackSecret);
|
|
2169
|
+
try {
|
|
2170
|
+
return this.client.encryption.decryptCipherEnvelope({
|
|
2171
|
+
envelope,
|
|
2172
|
+
sharedSecret: secret
|
|
2173
|
+
});
|
|
2174
|
+
} catch (_error) {
|
|
2175
|
+
return null;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
recipientMatches(candidate, target) {
|
|
2179
|
+
if (target.uaid && candidate.uaid?.toLowerCase() === target.uaid.toLowerCase()) {
|
|
2180
|
+
return true;
|
|
2181
|
+
}
|
|
2182
|
+
if (target.ledgerAccountId && candidate.ledgerAccountId?.toLowerCase() === target.ledgerAccountId.toLowerCase()) {
|
|
2183
|
+
return true;
|
|
2184
|
+
}
|
|
2185
|
+
if (target.userId && candidate.userId === target.userId) {
|
|
2186
|
+
return true;
|
|
2187
|
+
}
|
|
2188
|
+
if (target.email && candidate.email?.toLowerCase() === target.email.toLowerCase()) {
|
|
2189
|
+
return true;
|
|
2190
|
+
}
|
|
2191
|
+
return false;
|
|
2192
|
+
}
|
|
2193
|
+
async delay(ms) {
|
|
2194
|
+
if (ms <= 0) {
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
2198
|
+
}
|
|
2199
|
+
};
|
|
2200
|
+
|
|
2201
|
+
// ../../src/services/registry-broker/client/chat.ts
|
|
2202
|
+
function createChatApi(client, encryptedManager) {
|
|
2203
|
+
return {
|
|
2204
|
+
start: (options) => client.startChat(options),
|
|
2205
|
+
createSession: (payload) => client.createSession(payload),
|
|
2206
|
+
sendMessage: (payload) => client.sendMessage(payload),
|
|
2207
|
+
endSession: (sessionId) => client.endSession(sessionId),
|
|
2208
|
+
getHistory: (sessionId, options) => client.fetchHistorySnapshot(sessionId, options),
|
|
2209
|
+
compactHistory: (payload) => client.compactHistory(payload),
|
|
2210
|
+
getEncryptionStatus: (sessionId) => client.fetchEncryptionStatus(sessionId),
|
|
2211
|
+
submitEncryptionHandshake: (sessionId, payload) => client.postEncryptionHandshake(sessionId, payload),
|
|
2212
|
+
startConversation: (options) => client.startConversation(options),
|
|
2213
|
+
acceptConversation: (options) => client.acceptConversation(options),
|
|
2214
|
+
createEncryptedSession: (options) => encryptedManager.startSession(options),
|
|
2215
|
+
acceptEncryptedSession: (options) => encryptedManager.acceptSession(options)
|
|
2216
|
+
};
|
|
2131
2217
|
}
|
|
2132
|
-
async function
|
|
2133
|
-
const
|
|
2134
|
-
if (
|
|
2135
|
-
|
|
2218
|
+
async function createSession(client, payload, allowHistoryAutoTopUp = true) {
|
|
2219
|
+
const body = {};
|
|
2220
|
+
if ("uaid" in payload && payload.uaid) {
|
|
2221
|
+
body.uaid = payload.uaid;
|
|
2222
|
+
}
|
|
2223
|
+
if ("agentUrl" in payload && payload.agentUrl) {
|
|
2224
|
+
body.agentUrl = payload.agentUrl;
|
|
2225
|
+
}
|
|
2226
|
+
if (payload.auth) {
|
|
2227
|
+
body.auth = serialiseAuthConfig(payload.auth);
|
|
2228
|
+
}
|
|
2229
|
+
if (payload.historyTtlSeconds !== void 0) {
|
|
2230
|
+
body.historyTtlSeconds = payload.historyTtlSeconds;
|
|
2231
|
+
}
|
|
2232
|
+
if (payload.encryptionRequested !== void 0) {
|
|
2233
|
+
body.encryptionRequested = payload.encryptionRequested;
|
|
2234
|
+
}
|
|
2235
|
+
if (payload.senderUaid) {
|
|
2236
|
+
body.senderUaid = payload.senderUaid;
|
|
2136
2237
|
}
|
|
2137
|
-
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
2138
|
-
const raw = await client.requestJson(
|
|
2139
|
-
`/registries/${encodeURIComponent(registry)}/search${suffix}`,
|
|
2140
|
-
{
|
|
2141
|
-
method: "GET"
|
|
2142
|
-
}
|
|
2143
|
-
);
|
|
2144
|
-
return client.parseWithSchema(
|
|
2145
|
-
raw,
|
|
2146
|
-
registrySearchByNamespaceSchema,
|
|
2147
|
-
"registry search response"
|
|
2148
|
-
);
|
|
2149
|
-
}
|
|
2150
|
-
async function vectorSearch(client, request) {
|
|
2151
2238
|
try {
|
|
2152
|
-
const raw = await client.requestJson("/
|
|
2239
|
+
const raw = await client.requestJson("/chat/session", {
|
|
2153
2240
|
method: "POST",
|
|
2154
|
-
body
|
|
2241
|
+
body,
|
|
2155
2242
|
headers: { "content-type": "application/json" }
|
|
2156
2243
|
});
|
|
2157
2244
|
return client.parseWithSchema(
|
|
2158
2245
|
raw,
|
|
2159
|
-
|
|
2160
|
-
"
|
|
2246
|
+
createSessionResponseSchema,
|
|
2247
|
+
"chat session response"
|
|
2161
2248
|
);
|
|
2162
2249
|
} catch (error) {
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
);
|
|
2168
|
-
return convertSearchResultToVectorResponse(fallback);
|
|
2250
|
+
const maybeError = error instanceof Error ? error : null;
|
|
2251
|
+
if (allowHistoryAutoTopUp && client.shouldAutoTopUpHistory(payload, maybeError)) {
|
|
2252
|
+
await client.executeHistoryAutoTopUp("chat.session");
|
|
2253
|
+
return createSession(client, payload, false);
|
|
2169
2254
|
}
|
|
2170
2255
|
throw error;
|
|
2171
2256
|
}
|
|
2172
2257
|
}
|
|
2173
|
-
async function
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
}
|
|
2183
|
-
async function websocketStats(client) {
|
|
2184
|
-
const raw = await client.requestJson("/websocket/stats", {
|
|
2185
|
-
method: "GET"
|
|
2186
|
-
});
|
|
2187
|
-
return client.parseWithSchema(
|
|
2188
|
-
raw,
|
|
2189
|
-
websocketStatsResponseSchema,
|
|
2190
|
-
"websocket stats response"
|
|
2191
|
-
);
|
|
2192
|
-
}
|
|
2193
|
-
async function metricsSummary(client) {
|
|
2194
|
-
const raw = await client.requestJson("/metrics", {
|
|
2195
|
-
method: "GET"
|
|
2196
|
-
});
|
|
2197
|
-
return client.parseWithSchema(
|
|
2198
|
-
raw,
|
|
2199
|
-
metricsSummaryResponseSchema,
|
|
2200
|
-
"metrics summary response"
|
|
2201
|
-
);
|
|
2202
|
-
}
|
|
2203
|
-
async function facets(client, adapter) {
|
|
2204
|
-
const params = new URLSearchParams();
|
|
2205
|
-
if (adapter) {
|
|
2206
|
-
params.set("adapter", adapter);
|
|
2258
|
+
async function startChat(client, encryptedManager, options) {
|
|
2259
|
+
if ("uaid" in options && options.uaid) {
|
|
2260
|
+
return startConversation(client, encryptedManager, {
|
|
2261
|
+
uaid: options.uaid,
|
|
2262
|
+
senderUaid: options.senderUaid,
|
|
2263
|
+
historyTtlSeconds: options.historyTtlSeconds,
|
|
2264
|
+
auth: options.auth,
|
|
2265
|
+
encryption: options.encryption,
|
|
2266
|
+
onSessionCreated: options.onSessionCreated
|
|
2267
|
+
});
|
|
2207
2268
|
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
}
|
|
2224
|
-
|
|
2225
|
-
raw,
|
|
2226
|
-
adaptersResponseSchema,
|
|
2227
|
-
"adapters response"
|
|
2228
|
-
);
|
|
2229
|
-
}
|
|
2230
|
-
async function adaptersDetailed(client) {
|
|
2231
|
-
const raw = await client.requestJson("/adapters/details", {
|
|
2232
|
-
method: "GET"
|
|
2233
|
-
});
|
|
2234
|
-
return client.parseWithSchema(
|
|
2235
|
-
raw,
|
|
2236
|
-
adapterDetailsResponseSchema,
|
|
2237
|
-
"adapter details response"
|
|
2238
|
-
);
|
|
2239
|
-
}
|
|
2240
|
-
async function adapterRegistryCategories(client) {
|
|
2241
|
-
const raw = await client.requestJson(
|
|
2242
|
-
"/adapters/registry/categories",
|
|
2243
|
-
{
|
|
2244
|
-
method: "GET"
|
|
2245
|
-
}
|
|
2246
|
-
);
|
|
2247
|
-
return client.parseWithSchema(
|
|
2248
|
-
raw,
|
|
2249
|
-
adapterRegistryCategoriesResponseSchema,
|
|
2250
|
-
"adapter registry categories response"
|
|
2251
|
-
);
|
|
2269
|
+
if ("agentUrl" in options && options.agentUrl) {
|
|
2270
|
+
const session = await createSession(client, {
|
|
2271
|
+
agentUrl: options.agentUrl,
|
|
2272
|
+
auth: options.auth,
|
|
2273
|
+
historyTtlSeconds: options.historyTtlSeconds,
|
|
2274
|
+
senderUaid: options.senderUaid
|
|
2275
|
+
});
|
|
2276
|
+
options.onSessionCreated?.(session.sessionId);
|
|
2277
|
+
return createPlaintextConversationHandle(
|
|
2278
|
+
client,
|
|
2279
|
+
session.sessionId,
|
|
2280
|
+
session.encryption ?? null,
|
|
2281
|
+
options.auth,
|
|
2282
|
+
{ agentUrl: options.agentUrl, uaid: options.uaid }
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
throw new Error("startChat requires either uaid or agentUrl");
|
|
2252
2286
|
}
|
|
2253
|
-
async function
|
|
2254
|
-
const
|
|
2255
|
-
|
|
2256
|
-
|
|
2287
|
+
async function startConversation(client, encryptedManager, options) {
|
|
2288
|
+
const preference = options.encryption?.preference ?? "preferred";
|
|
2289
|
+
const requestEncryption = preference !== "disabled";
|
|
2290
|
+
if (!requestEncryption) {
|
|
2291
|
+
const session = await createSession(client, {
|
|
2292
|
+
uaid: options.uaid,
|
|
2293
|
+
auth: options.auth,
|
|
2294
|
+
historyTtlSeconds: options.historyTtlSeconds,
|
|
2295
|
+
senderUaid: options.senderUaid,
|
|
2296
|
+
encryptionRequested: false
|
|
2297
|
+
});
|
|
2298
|
+
options.onSessionCreated?.(session.sessionId);
|
|
2299
|
+
return createPlaintextConversationHandle(
|
|
2300
|
+
client,
|
|
2301
|
+
session.sessionId,
|
|
2302
|
+
session.encryption ?? null,
|
|
2303
|
+
options.auth,
|
|
2304
|
+
{ uaid: options.uaid }
|
|
2305
|
+
);
|
|
2257
2306
|
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2307
|
+
try {
|
|
2308
|
+
const handle = await encryptedManager.startSession({
|
|
2309
|
+
uaid: options.uaid,
|
|
2310
|
+
senderUaid: options.senderUaid,
|
|
2311
|
+
historyTtlSeconds: options.historyTtlSeconds,
|
|
2312
|
+
handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
|
|
2313
|
+
pollIntervalMs: options.encryption?.pollIntervalMs,
|
|
2314
|
+
onSessionCreated: (sessionId) => {
|
|
2315
|
+
options.onSessionCreated?.(sessionId);
|
|
2316
|
+
},
|
|
2317
|
+
auth: options.auth
|
|
2318
|
+
});
|
|
2319
|
+
return handle;
|
|
2320
|
+
} catch (error) {
|
|
2321
|
+
if (error instanceof EncryptionUnavailableError) {
|
|
2322
|
+
if (preference === "required") {
|
|
2323
|
+
throw error;
|
|
2324
|
+
}
|
|
2325
|
+
return createPlaintextConversationHandle(
|
|
2326
|
+
client,
|
|
2327
|
+
error.sessionId,
|
|
2328
|
+
error.summary ?? null,
|
|
2329
|
+
options.auth,
|
|
2330
|
+
{ uaid: options.uaid }
|
|
2331
|
+
);
|
|
2332
|
+
}
|
|
2333
|
+
throw error;
|
|
2260
2334
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2335
|
+
}
|
|
2336
|
+
async function acceptConversation(client, encryptedManager, options) {
|
|
2337
|
+
const preference = options.encryption?.preference ?? "preferred";
|
|
2338
|
+
if (preference === "disabled") {
|
|
2339
|
+
return createPlaintextConversationHandle(client, options.sessionId, null);
|
|
2263
2340
|
}
|
|
2264
|
-
|
|
2265
|
-
|
|
2341
|
+
try {
|
|
2342
|
+
const handle = await encryptedManager.acceptSession({
|
|
2343
|
+
sessionId: options.sessionId,
|
|
2344
|
+
responderUaid: options.responderUaid,
|
|
2345
|
+
handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
|
|
2346
|
+
pollIntervalMs: options.encryption?.pollIntervalMs
|
|
2347
|
+
});
|
|
2348
|
+
return handle;
|
|
2349
|
+
} catch (error) {
|
|
2350
|
+
if (error instanceof EncryptionUnavailableError && preference !== "required") {
|
|
2351
|
+
return createPlaintextConversationHandle(
|
|
2352
|
+
client,
|
|
2353
|
+
options.sessionId,
|
|
2354
|
+
null,
|
|
2355
|
+
void 0,
|
|
2356
|
+
{ uaid: options.responderUaid }
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
throw error;
|
|
2266
2360
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2361
|
+
}
|
|
2362
|
+
function createPlaintextConversationHandle(client, sessionId, summary, defaultAuth, context) {
|
|
2363
|
+
const uaid = context?.uaid?.trim();
|
|
2364
|
+
const agentUrl = context?.agentUrl?.trim();
|
|
2365
|
+
const fetchHistory = async (options) => {
|
|
2366
|
+
const snapshot = await client.fetchHistorySnapshot(sessionId, options);
|
|
2367
|
+
if (snapshot.decryptedHistory) {
|
|
2368
|
+
return snapshot.decryptedHistory;
|
|
2369
|
+
}
|
|
2370
|
+
return snapshot.history.map((entry) => ({
|
|
2371
|
+
entry,
|
|
2372
|
+
plaintext: entry.content
|
|
2373
|
+
}));
|
|
2374
|
+
};
|
|
2375
|
+
return {
|
|
2376
|
+
sessionId,
|
|
2377
|
+
mode: "plaintext",
|
|
2378
|
+
summary: summary ?? null,
|
|
2379
|
+
send: async (options) => {
|
|
2380
|
+
const plaintext = options.plaintext;
|
|
2381
|
+
if (!plaintext || plaintext.trim().length === 0) {
|
|
2382
|
+
throw new Error("plaintext is required for chat messages");
|
|
2383
|
+
}
|
|
2384
|
+
const message = options.message ?? plaintext;
|
|
2385
|
+
return sendMessage(client, {
|
|
2386
|
+
sessionId,
|
|
2387
|
+
message,
|
|
2388
|
+
streaming: options.streaming,
|
|
2389
|
+
auth: options.auth ?? defaultAuth,
|
|
2390
|
+
uaid,
|
|
2391
|
+
agentUrl
|
|
2392
|
+
});
|
|
2393
|
+
},
|
|
2394
|
+
decryptHistoryEntry: (entry) => entry.content,
|
|
2395
|
+
fetchHistory
|
|
2396
|
+
};
|
|
2397
|
+
}
|
|
2398
|
+
async function compactHistory(client, payload) {
|
|
2399
|
+
if (!payload.sessionId || payload.sessionId.trim().length === 0) {
|
|
2400
|
+
throw new Error("sessionId is required to compact chat history");
|
|
2269
2401
|
}
|
|
2270
|
-
|
|
2271
|
-
|
|
2402
|
+
const body = {};
|
|
2403
|
+
if (typeof payload.preserveEntries === "number" && Number.isFinite(payload.preserveEntries) && payload.preserveEntries >= 0) {
|
|
2404
|
+
body.preserveEntries = Math.floor(payload.preserveEntries);
|
|
2272
2405
|
}
|
|
2273
|
-
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
2274
|
-
const raw = await client.requestJson(
|
|
2275
|
-
`/adapters/registry/adapters${suffix}`,
|
|
2276
|
-
{
|
|
2277
|
-
method: "GET"
|
|
2278
|
-
}
|
|
2279
|
-
);
|
|
2280
|
-
return client.parseWithSchema(
|
|
2281
|
-
raw,
|
|
2282
|
-
adapterRegistryAdaptersResponseSchema,
|
|
2283
|
-
"adapter registry adapters response"
|
|
2284
|
-
);
|
|
2285
|
-
}
|
|
2286
|
-
async function createAdapterRegistryCategory(client, payload) {
|
|
2287
2406
|
const raw = await client.requestJson(
|
|
2288
|
-
|
|
2407
|
+
`/chat/session/${encodeURIComponent(payload.sessionId)}/compact`,
|
|
2289
2408
|
{
|
|
2290
2409
|
method: "POST",
|
|
2291
2410
|
headers: { "content-type": "application/json" },
|
|
2292
|
-
body
|
|
2411
|
+
body
|
|
2293
2412
|
}
|
|
2294
2413
|
);
|
|
2295
|
-
|
|
2414
|
+
return client.parseWithSchema(
|
|
2296
2415
|
raw,
|
|
2297
|
-
|
|
2298
|
-
"
|
|
2416
|
+
chatHistoryCompactionResponseSchema,
|
|
2417
|
+
"chat history compaction response"
|
|
2299
2418
|
);
|
|
2300
|
-
return parsed.category;
|
|
2301
2419
|
}
|
|
2302
|
-
async function
|
|
2420
|
+
async function fetchEncryptionStatus(client, sessionId) {
|
|
2421
|
+
if (!sessionId || sessionId.trim().length === 0) {
|
|
2422
|
+
throw new Error("sessionId is required for encryption status");
|
|
2423
|
+
}
|
|
2303
2424
|
const raw = await client.requestJson(
|
|
2304
|
-
|
|
2425
|
+
`/chat/session/${encodeURIComponent(sessionId)}/encryption`,
|
|
2305
2426
|
{
|
|
2306
|
-
method: "
|
|
2307
|
-
headers: { "content-type": "application/json" },
|
|
2308
|
-
body: toJsonObject(payload)
|
|
2427
|
+
method: "GET"
|
|
2309
2428
|
}
|
|
2310
2429
|
);
|
|
2311
2430
|
return client.parseWithSchema(
|
|
2312
2431
|
raw,
|
|
2313
|
-
|
|
2314
|
-
"
|
|
2432
|
+
sessionEncryptionStatusResponseSchema,
|
|
2433
|
+
"session encryption status response"
|
|
2315
2434
|
);
|
|
2316
2435
|
}
|
|
2317
|
-
async function
|
|
2436
|
+
async function postEncryptionHandshake(client, sessionId, payload) {
|
|
2437
|
+
if (!sessionId || sessionId.trim().length === 0) {
|
|
2438
|
+
throw new Error("sessionId is required for encryption handshake");
|
|
2439
|
+
}
|
|
2318
2440
|
const raw = await client.requestJson(
|
|
2319
|
-
`/
|
|
2441
|
+
`/chat/session/${encodeURIComponent(sessionId)}/encryption-handshake`,
|
|
2320
2442
|
{
|
|
2321
|
-
method: "
|
|
2443
|
+
method: "POST",
|
|
2444
|
+
headers: { "content-type": "application/json" },
|
|
2445
|
+
body: {
|
|
2446
|
+
role: payload.role,
|
|
2447
|
+
keyType: payload.keyType,
|
|
2448
|
+
ephemeralPublicKey: payload.ephemeralPublicKey,
|
|
2449
|
+
longTermPublicKey: payload.longTermPublicKey,
|
|
2450
|
+
signature: payload.signature,
|
|
2451
|
+
uaid: payload.uaid,
|
|
2452
|
+
userId: payload.userId,
|
|
2453
|
+
ledgerAccountId: payload.ledgerAccountId,
|
|
2454
|
+
metadata: payload.metadata
|
|
2455
|
+
}
|
|
2322
2456
|
}
|
|
2323
2457
|
);
|
|
2324
|
-
|
|
2458
|
+
const response = client.parseWithSchema(
|
|
2325
2459
|
raw,
|
|
2326
|
-
|
|
2327
|
-
"
|
|
2460
|
+
encryptionHandshakeResponseSchema,
|
|
2461
|
+
"encryption handshake response"
|
|
2328
2462
|
);
|
|
2463
|
+
return response.handshake;
|
|
2329
2464
|
}
|
|
2330
|
-
|
|
2331
|
-
// ../../src/services/registry-broker/client/credits.ts
|
|
2332
|
-
async function loadX402Dependencies(client) {
|
|
2333
|
-
const [{ default: axios }, x402Axios, x402Types] = await Promise.all([
|
|
2334
|
-
import("axios"),
|
|
2335
|
-
optionalImport("x402-axios"),
|
|
2336
|
-
optionalImport("x402/types")
|
|
2337
|
-
]);
|
|
2338
|
-
if (!x402Axios || !x402Types) {
|
|
2339
|
-
throw new Error(
|
|
2340
|
-
"x402-axios and x402/types are required for X402 flows. Install them to enable ledger payments."
|
|
2341
|
-
);
|
|
2342
|
-
}
|
|
2343
|
-
const withPaymentInterceptor = x402Axios.withPaymentInterceptor;
|
|
2344
|
-
const decodePaymentResponse = x402Axios.decodeXPaymentResponse;
|
|
2345
|
-
const createX402Signer = x402Types.createSigner;
|
|
2346
|
-
const createPaymentClient = (walletClient) => {
|
|
2347
|
-
const axiosClient = axios.create({
|
|
2348
|
-
baseURL: client.baseUrl,
|
|
2349
|
-
headers: {
|
|
2350
|
-
...client.getDefaultHeaders(),
|
|
2351
|
-
"content-type": "application/json"
|
|
2352
|
-
}
|
|
2353
|
-
});
|
|
2354
|
-
const paymentClient = withPaymentInterceptor(axiosClient, walletClient);
|
|
2355
|
-
return paymentClient;
|
|
2356
|
-
};
|
|
2357
|
-
return { createPaymentClient, decodePaymentResponse, createX402Signer };
|
|
2358
|
-
}
|
|
2359
|
-
function calculateHbarAmountParam(hbarAmount) {
|
|
2360
|
-
const tinybars = Math.ceil(hbarAmount * 1e8);
|
|
2361
|
-
if (tinybars <= 0) {
|
|
2362
|
-
throw new Error("Calculated purchase amount must be positive");
|
|
2363
|
-
}
|
|
2364
|
-
return tinybars / 1e8;
|
|
2365
|
-
}
|
|
2366
|
-
async function purchaseCreditsWithHbar(client, params) {
|
|
2465
|
+
async function sendMessage(client, payload) {
|
|
2367
2466
|
const body = {
|
|
2368
|
-
|
|
2369
|
-
payerKey: params.privateKey,
|
|
2370
|
-
hbarAmount: calculateHbarAmountParam(params.hbarAmount)
|
|
2467
|
+
message: payload.message
|
|
2371
2468
|
};
|
|
2372
|
-
if (
|
|
2373
|
-
body.
|
|
2469
|
+
if (payload.streaming !== void 0) {
|
|
2470
|
+
body.streaming = payload.streaming;
|
|
2374
2471
|
}
|
|
2375
|
-
if (
|
|
2376
|
-
body.
|
|
2472
|
+
if (payload.auth) {
|
|
2473
|
+
body.auth = serialiseAuthConfig(payload.auth);
|
|
2377
2474
|
}
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
headers: { "content-type": "application/json" },
|
|
2381
|
-
body
|
|
2382
|
-
});
|
|
2383
|
-
return client.parseWithSchema(
|
|
2384
|
-
raw,
|
|
2385
|
-
creditPurchaseResponseSchema,
|
|
2386
|
-
"credit purchase response"
|
|
2387
|
-
);
|
|
2388
|
-
}
|
|
2389
|
-
async function getX402Minimums(client) {
|
|
2390
|
-
const raw = await client.requestJson(
|
|
2391
|
-
"/credits/purchase/x402/minimums",
|
|
2392
|
-
{ method: "GET" }
|
|
2393
|
-
);
|
|
2394
|
-
return client.parseWithSchema(
|
|
2395
|
-
raw,
|
|
2396
|
-
x402MinimumsResponseSchema,
|
|
2397
|
-
"x402 minimums response"
|
|
2398
|
-
);
|
|
2399
|
-
}
|
|
2400
|
-
async function purchaseCreditsWithX402(client, params) {
|
|
2401
|
-
const { createPaymentClient, decodePaymentResponse } = await loadX402Dependencies(client);
|
|
2402
|
-
if (!Number.isFinite(params.credits) || params.credits <= 0) {
|
|
2403
|
-
throw new Error("credits must be a positive number");
|
|
2475
|
+
if ("uaid" in payload) {
|
|
2476
|
+
body.uaid = payload.uaid;
|
|
2404
2477
|
}
|
|
2405
|
-
if (
|
|
2406
|
-
|
|
2478
|
+
if ("sessionId" in payload && payload.sessionId) {
|
|
2479
|
+
body.sessionId = payload.sessionId;
|
|
2407
2480
|
}
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
credits: params.credits
|
|
2411
|
-
};
|
|
2412
|
-
if (params.usdAmount !== void 0) {
|
|
2413
|
-
body.usdAmount = params.usdAmount;
|
|
2481
|
+
if ("agentUrl" in payload && payload.agentUrl) {
|
|
2482
|
+
body.agentUrl = payload.agentUrl;
|
|
2414
2483
|
}
|
|
2415
|
-
|
|
2416
|
-
|
|
2484
|
+
let cipherEnvelope = payload.cipherEnvelope ?? null;
|
|
2485
|
+
if (payload.encryption) {
|
|
2486
|
+
const sessionIdForEncryption = payload.encryption.sessionId ?? (typeof body.sessionId === "string" ? body.sessionId : void 0);
|
|
2487
|
+
if (!sessionIdForEncryption) {
|
|
2488
|
+
throw new Error(
|
|
2489
|
+
"sessionId is required when using encrypted chat payloads"
|
|
2490
|
+
);
|
|
2491
|
+
}
|
|
2492
|
+
if (!payload.encryption.recipients?.length) {
|
|
2493
|
+
throw new Error("recipients are required for encrypted chat payloads");
|
|
2494
|
+
}
|
|
2495
|
+
cipherEnvelope = client.encryption.encryptCipherEnvelope({
|
|
2496
|
+
...payload.encryption,
|
|
2497
|
+
sessionId: sessionIdForEncryption
|
|
2498
|
+
});
|
|
2417
2499
|
}
|
|
2418
|
-
if (
|
|
2419
|
-
body.
|
|
2500
|
+
if (cipherEnvelope) {
|
|
2501
|
+
body.cipherEnvelope = toJsonObject(cipherEnvelope);
|
|
2420
2502
|
}
|
|
2421
|
-
const
|
|
2422
|
-
const response = await paymentClient.post("/credits/purchase/x402", body);
|
|
2423
|
-
const parsed = client.parseWithSchema(
|
|
2424
|
-
response.data,
|
|
2425
|
-
x402CreditPurchaseResponseSchema,
|
|
2426
|
-
"x402 credit purchase response"
|
|
2427
|
-
);
|
|
2428
|
-
const responseHeaders = response.headers ?? {};
|
|
2429
|
-
const paymentHeader = typeof responseHeaders["x-payment-response"] === "string" ? responseHeaders["x-payment-response"] : void 0;
|
|
2430
|
-
const decodedPayment = paymentHeader !== void 0 ? decodePaymentResponse(paymentHeader) : void 0;
|
|
2431
|
-
return {
|
|
2432
|
-
...parsed,
|
|
2433
|
-
paymentResponseHeader: paymentHeader,
|
|
2434
|
-
paymentResponse: decodedPayment
|
|
2435
|
-
};
|
|
2436
|
-
}
|
|
2437
|
-
async function buyCreditsWithX402(client, params) {
|
|
2438
|
-
const network = params.network ?? "base";
|
|
2439
|
-
const { createX402Signer } = await loadX402Dependencies(client);
|
|
2440
|
-
const normalizedKey = normalizeHexPrivateKey(params.evmPrivateKey);
|
|
2441
|
-
const walletClient = await createX402Signer(network, normalizedKey);
|
|
2442
|
-
return purchaseCreditsWithX402(client, {
|
|
2443
|
-
accountId: params.accountId,
|
|
2444
|
-
credits: params.credits,
|
|
2445
|
-
usdAmount: params.usdAmount,
|
|
2446
|
-
description: params.description,
|
|
2447
|
-
metadata: params.metadata,
|
|
2448
|
-
walletClient
|
|
2449
|
-
});
|
|
2450
|
-
}
|
|
2451
|
-
|
|
2452
|
-
// ../../src/services/registry-broker/client/agents.ts
|
|
2453
|
-
async function resolveUaid(client, uaid) {
|
|
2454
|
-
const raw = await client.requestJson(
|
|
2455
|
-
`/resolve/${encodeURIComponent(uaid)}`,
|
|
2456
|
-
{
|
|
2457
|
-
method: "GET"
|
|
2458
|
-
}
|
|
2459
|
-
);
|
|
2460
|
-
return client.parseWithSchema(
|
|
2461
|
-
raw,
|
|
2462
|
-
resolveResponseSchema,
|
|
2463
|
-
"resolve UAID response"
|
|
2464
|
-
);
|
|
2465
|
-
}
|
|
2466
|
-
async function getRegistrationQuote(client, payload) {
|
|
2467
|
-
const raw = await client.requestJson("/register/quote", {
|
|
2503
|
+
const raw = await client.requestJson("/chat/message", {
|
|
2468
2504
|
method: "POST",
|
|
2469
|
-
body
|
|
2505
|
+
body,
|
|
2470
2506
|
headers: { "content-type": "application/json" }
|
|
2471
2507
|
});
|
|
2472
2508
|
return client.parseWithSchema(
|
|
2473
2509
|
raw,
|
|
2474
|
-
|
|
2475
|
-
"
|
|
2510
|
+
sendMessageResponseSchema,
|
|
2511
|
+
"chat message response"
|
|
2476
2512
|
);
|
|
2477
2513
|
}
|
|
2478
|
-
async function
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2514
|
+
async function endSession(client, sessionId) {
|
|
2515
|
+
await client.request(`/chat/session/${encodeURIComponent(sessionId)}`, {
|
|
2516
|
+
method: "DELETE"
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
// ../../src/services/registry-broker/client/encryption.ts
|
|
2521
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
2522
|
+
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
2523
|
+
|
|
2524
|
+
// ../../src/utils/is-browser.ts
|
|
2525
|
+
var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
2526
|
+
|
|
2527
|
+
// ../../src/utils/dynamic-import.ts
|
|
2528
|
+
var nodeRequire;
|
|
2529
|
+
var isNodeRuntime = () => typeof process !== "undefined" && Boolean(process.versions?.node);
|
|
2530
|
+
function getNodeRequireSync() {
|
|
2531
|
+
try {
|
|
2532
|
+
const moduleNamespace = process.getBuiltinModule?.("module");
|
|
2533
|
+
if (typeof moduleNamespace?.createRequire === "function") {
|
|
2534
|
+
const requireFromModule = moduleNamespace.createRequire(import.meta.url);
|
|
2535
|
+
if (typeof requireFromModule.resolve === "function") {
|
|
2536
|
+
return requireFromModule;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
const globalObject = typeof global !== "undefined" ? global : globalThis;
|
|
2540
|
+
const runtimeRequire = globalObject.process?.mainModule?.require ?? globalObject.require ?? Function('return typeof require === "function" ? require : undefined;')();
|
|
2541
|
+
if (typeof runtimeRequire === "function" && typeof runtimeRequire.resolve === "function") {
|
|
2542
|
+
return runtimeRequire;
|
|
2543
|
+
}
|
|
2544
|
+
} catch {
|
|
2545
|
+
return null;
|
|
2546
|
+
}
|
|
2547
|
+
return null;
|
|
2548
|
+
}
|
|
2549
|
+
function isModuleNotFound(specifier, error) {
|
|
2550
|
+
if (!error || typeof error !== "object") {
|
|
2551
|
+
return false;
|
|
2552
|
+
}
|
|
2553
|
+
const code = Reflect.get(error, "code");
|
|
2554
|
+
const message = Reflect.get(error, "message");
|
|
2555
|
+
const messageText = typeof message === "string" ? message : "";
|
|
2556
|
+
if (typeof code === "string" && code.includes("MODULE_NOT_FOUND")) {
|
|
2557
|
+
return messageText.includes(specifier);
|
|
2558
|
+
}
|
|
2559
|
+
if (messageText) {
|
|
2560
|
+
const lowered = messageText.toLowerCase();
|
|
2561
|
+
if (lowered.includes("cannot find module") || lowered.includes("module not found") || lowered.includes("cannot find package")) {
|
|
2562
|
+
return lowered.includes(specifier.toLowerCase());
|
|
2485
2563
|
}
|
|
2486
|
-
|
|
2487
|
-
return
|
|
2488
|
-
raw,
|
|
2489
|
-
registerAgentResponseSchema,
|
|
2490
|
-
"update agent response"
|
|
2491
|
-
);
|
|
2564
|
+
}
|
|
2565
|
+
return false;
|
|
2492
2566
|
}
|
|
2493
|
-
async function
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2567
|
+
async function resolveNodeRequire() {
|
|
2568
|
+
if (nodeRequire !== void 0) {
|
|
2569
|
+
return nodeRequire;
|
|
2570
|
+
}
|
|
2571
|
+
if (isBrowser && !isNodeRuntime()) {
|
|
2572
|
+
nodeRequire = null;
|
|
2573
|
+
return nodeRequire;
|
|
2497
2574
|
}
|
|
2498
2575
|
try {
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2576
|
+
nodeRequire = getNodeRequireSync();
|
|
2577
|
+
} catch {
|
|
2578
|
+
nodeRequire = null;
|
|
2579
|
+
}
|
|
2580
|
+
return nodeRequire;
|
|
2581
|
+
}
|
|
2582
|
+
async function dynamicImport(specifier) {
|
|
2583
|
+
try {
|
|
2584
|
+
return await import(
|
|
2585
|
+
/* webpackIgnore: true */
|
|
2586
|
+
specifier
|
|
2507
2587
|
);
|
|
2508
|
-
return parsed.progress;
|
|
2509
2588
|
} catch (error) {
|
|
2510
|
-
if (
|
|
2589
|
+
if (isModuleNotFound(specifier, error)) {
|
|
2511
2590
|
return null;
|
|
2512
2591
|
}
|
|
2513
2592
|
throw error;
|
|
2514
2593
|
}
|
|
2515
2594
|
}
|
|
2516
|
-
async function
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
throw new Error("attemptId is required");
|
|
2595
|
+
async function optionalImport(specifier, options = {}) {
|
|
2596
|
+
if (isBrowser && !isNodeRuntime()) {
|
|
2597
|
+
return dynamicImport(specifier);
|
|
2520
2598
|
}
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
while (true) {
|
|
2530
|
-
if (signal?.aborted) {
|
|
2531
|
-
throw createAbortError();
|
|
2532
|
-
}
|
|
2533
|
-
const progress = await client.getRegistrationProgress(normalisedAttemptId);
|
|
2534
|
-
if (progress) {
|
|
2535
|
-
options.onProgress?.(progress);
|
|
2536
|
-
if (progress.status === "completed") {
|
|
2537
|
-
return progress;
|
|
2538
|
-
}
|
|
2539
|
-
if (progress.status === "partial" || progress.status === "failed") {
|
|
2540
|
-
if (throwOnFailure) {
|
|
2541
|
-
throw new RegistryBrokerError(
|
|
2542
|
-
"Registration did not complete successfully",
|
|
2543
|
-
{
|
|
2544
|
-
status: 409,
|
|
2545
|
-
statusText: progress.status,
|
|
2546
|
-
body: progress
|
|
2547
|
-
}
|
|
2548
|
-
);
|
|
2599
|
+
if (!options.preferImport) {
|
|
2600
|
+
const requireFn = await resolveNodeRequire();
|
|
2601
|
+
if (requireFn) {
|
|
2602
|
+
try {
|
|
2603
|
+
return requireFn(specifier);
|
|
2604
|
+
} catch (error) {
|
|
2605
|
+
if (!isModuleNotFound(specifier, error)) {
|
|
2606
|
+
throw error;
|
|
2549
2607
|
}
|
|
2550
|
-
return progress;
|
|
2551
2608
|
}
|
|
2552
2609
|
}
|
|
2553
|
-
if (Date.now() - startedAt >= timeoutMs) {
|
|
2554
|
-
throw new Error(
|
|
2555
|
-
`Registration progress polling timed out after ${timeoutMs}ms`
|
|
2556
|
-
);
|
|
2557
|
-
}
|
|
2558
|
-
await client.delay(interval, signal);
|
|
2559
2610
|
}
|
|
2611
|
+
return dynamicImport(specifier);
|
|
2560
2612
|
}
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2613
|
+
function optionalImportSync(specifier) {
|
|
2614
|
+
if (isBrowser && !isNodeRuntime()) {
|
|
2615
|
+
return null;
|
|
2616
|
+
}
|
|
2617
|
+
try {
|
|
2618
|
+
const requireFn = getNodeRequireSync();
|
|
2619
|
+
if (requireFn) {
|
|
2620
|
+
return requireFn(specifier);
|
|
2566
2621
|
}
|
|
2567
|
-
)
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
uaidValidationResponseSchema,
|
|
2571
|
-
"UAID validation response"
|
|
2572
|
-
);
|
|
2573
|
-
}
|
|
2574
|
-
async function getUaidConnectionStatus(client, uaid) {
|
|
2575
|
-
const raw = await client.requestJson(
|
|
2576
|
-
`/uaids/connections/${encodeURIComponent(uaid)}/status`,
|
|
2577
|
-
{
|
|
2578
|
-
method: "GET"
|
|
2622
|
+
} catch (error) {
|
|
2623
|
+
if (!isModuleNotFound(specifier, error)) {
|
|
2624
|
+
throw error;
|
|
2579
2625
|
}
|
|
2580
|
-
|
|
2581
|
-
return
|
|
2582
|
-
raw,
|
|
2583
|
-
uaidConnectionStatusSchema,
|
|
2584
|
-
"UAID connection status"
|
|
2585
|
-
);
|
|
2586
|
-
}
|
|
2587
|
-
async function closeUaidConnection(client, uaid) {
|
|
2588
|
-
await client.request(`/uaids/connections/${encodeURIComponent(uaid)}`, {
|
|
2589
|
-
method: "DELETE"
|
|
2590
|
-
});
|
|
2591
|
-
}
|
|
2592
|
-
async function dashboardStats(client) {
|
|
2593
|
-
const raw = await client.requestJson("/dashboard/stats", {
|
|
2594
|
-
method: "GET"
|
|
2595
|
-
});
|
|
2596
|
-
return client.parseWithSchema(
|
|
2597
|
-
raw,
|
|
2598
|
-
dashboardStatsResponseSchema,
|
|
2599
|
-
"dashboard stats response"
|
|
2600
|
-
);
|
|
2626
|
+
}
|
|
2627
|
+
return null;
|
|
2601
2628
|
}
|
|
2602
2629
|
|
|
2603
|
-
// ../../src/services/registry-broker/client/
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
var HEDERA_NETWORK_ALIASES = /* @__PURE__ */ new Map([
|
|
2609
|
-
["hedera:mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
2610
|
-
["mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
2611
|
-
["hedera-mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
2612
|
-
["hedera_mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
2613
|
-
["hedera:testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
|
|
2614
|
-
["testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
|
|
2615
|
-
["hedera-testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
|
|
2616
|
-
["hedera_testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }]
|
|
2617
|
-
]);
|
|
2618
|
-
var EVM_NETWORK_CHAIN_IDS = {
|
|
2619
|
-
abstract: 2741,
|
|
2620
|
-
"abstract-testnet": 11124,
|
|
2621
|
-
base: 8453,
|
|
2622
|
-
"base-sepolia": 84532,
|
|
2623
|
-
avalanche: 43114,
|
|
2624
|
-
"avalanche-fuji": 43113,
|
|
2625
|
-
iotex: 4689,
|
|
2626
|
-
sei: 1329,
|
|
2627
|
-
"sei-testnet": 1328,
|
|
2628
|
-
polygon: 137,
|
|
2629
|
-
"polygon-amoy": 80002,
|
|
2630
|
-
peaq: 3338
|
|
2631
|
-
};
|
|
2632
|
-
var CHAIN_ID_TO_ALIAS = new Map(
|
|
2633
|
-
Object.entries(EVM_NETWORK_CHAIN_IDS).map(([alias, id]) => [id, alias])
|
|
2634
|
-
);
|
|
2635
|
-
var parseChainId = (value) => {
|
|
2636
|
-
if (/^eip155:\d+$/i.test(value)) {
|
|
2637
|
-
return Number.parseInt(value.split(":")[1], 10);
|
|
2638
|
-
}
|
|
2639
|
-
if (/^\d+$/.test(value)) {
|
|
2640
|
-
return Number.parseInt(value, 10);
|
|
2630
|
+
// ../../src/services/registry-broker/client/encryption.ts
|
|
2631
|
+
var getFs = async () => {
|
|
2632
|
+
const fsModule = await optionalImport("node:fs") ?? await optionalImport("fs");
|
|
2633
|
+
if (fsModule && typeof fsModule.existsSync === "function" && typeof fsModule.readFileSync === "function" && typeof fsModule.writeFileSync === "function" && typeof fsModule.appendFileSync === "function") {
|
|
2634
|
+
return fsModule;
|
|
2641
2635
|
}
|
|
2642
|
-
return
|
|
2636
|
+
return null;
|
|
2643
2637
|
};
|
|
2644
|
-
var
|
|
2645
|
-
const
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
if (chainId === void 0) {
|
|
2649
|
-
const mapped = EVM_NETWORK_CHAIN_IDS[trimmed];
|
|
2650
|
-
if (mapped !== void 0) {
|
|
2651
|
-
chainId = mapped;
|
|
2652
|
-
alias = trimmed;
|
|
2653
|
-
}
|
|
2654
|
-
} else if (CHAIN_ID_TO_ALIAS.has(chainId)) {
|
|
2655
|
-
alias = CHAIN_ID_TO_ALIAS.get(chainId);
|
|
2638
|
+
var getNodePath = async () => {
|
|
2639
|
+
const pathModule = await optionalImport("node:path") ?? await optionalImport("path");
|
|
2640
|
+
if (pathModule && typeof pathModule.resolve === "function") {
|
|
2641
|
+
return pathModule;
|
|
2656
2642
|
}
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2643
|
+
return null;
|
|
2644
|
+
};
|
|
2645
|
+
var getNodeCrypto = async () => {
|
|
2646
|
+
const cryptoModule = await optionalImport("node:crypto") ?? await optionalImport("crypto");
|
|
2647
|
+
if (cryptoModule && typeof cryptoModule.randomBytes === "function") {
|
|
2648
|
+
return cryptoModule;
|
|
2661
2649
|
}
|
|
2662
|
-
return
|
|
2663
|
-
canonical: `eip155:${chainId}`,
|
|
2664
|
-
kind: "evm",
|
|
2665
|
-
chainId,
|
|
2666
|
-
legacyName: alias
|
|
2667
|
-
};
|
|
2650
|
+
return null;
|
|
2668
2651
|
};
|
|
2669
|
-
|
|
2670
|
-
const
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2652
|
+
async function registerEncryptionKey(client, payload) {
|
|
2653
|
+
const raw = await client.requestJson("/encryption/keys", {
|
|
2654
|
+
method: "POST",
|
|
2655
|
+
headers: { "content-type": "application/json" },
|
|
2656
|
+
body: payload
|
|
2657
|
+
});
|
|
2658
|
+
return client.parseWithSchema(
|
|
2659
|
+
raw,
|
|
2660
|
+
registerEncryptionKeyResponseSchema,
|
|
2661
|
+
"register encryption key response"
|
|
2662
|
+
);
|
|
2663
|
+
}
|
|
2664
|
+
function normalizeAutoRegisterIdentity(config) {
|
|
2665
|
+
const identity = {};
|
|
2666
|
+
if (config.uaid) {
|
|
2667
|
+
identity.uaid = config.uaid;
|
|
2676
2668
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
};
|
|
2683
|
-
var canonicalizeLedgerNetwork = (network) => {
|
|
2684
|
-
if (typeof network !== "string" || network.trim().length === 0) {
|
|
2685
|
-
throw new Error("Ledger network is required.");
|
|
2669
|
+
if (config.ledgerAccountId) {
|
|
2670
|
+
identity.ledgerAccountId = config.ledgerAccountId;
|
|
2671
|
+
if (config.ledgerNetwork) {
|
|
2672
|
+
identity.ledgerNetwork = config.ledgerNetwork;
|
|
2673
|
+
}
|
|
2686
2674
|
}
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
return normaliseHederaNetwork(trimmed);
|
|
2675
|
+
if (config.email) {
|
|
2676
|
+
identity.email = config.email;
|
|
2690
2677
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
// ../../src/services/registry-broker/private-key-signer.ts
|
|
2695
|
-
var unsupported = (method) => new Error(`${method} is not supported by the in-memory signer`);
|
|
2696
|
-
var cachedSdk = null;
|
|
2697
|
-
var loadHashgraphSdk = () => {
|
|
2698
|
-
if (cachedSdk) {
|
|
2699
|
-
return cachedSdk;
|
|
2678
|
+
if (identity.uaid || identity.ledgerAccountId || identity.email) {
|
|
2679
|
+
return identity;
|
|
2700
2680
|
}
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2681
|
+
return null;
|
|
2682
|
+
}
|
|
2683
|
+
function derivePublicKeyFromPrivateKey(client, privateKey) {
|
|
2684
|
+
const normalized = client.hexToBuffer(privateKey);
|
|
2685
|
+
const publicKey = secp256k1.getPublicKey(normalized, true);
|
|
2686
|
+
return Buffer3.from(publicKey).toString("hex");
|
|
2687
|
+
}
|
|
2688
|
+
async function resolveAutoRegisterKeyMaterial(client, config) {
|
|
2689
|
+
if (config.publicKey?.trim()) {
|
|
2690
|
+
return { publicKey: config.publicKey.trim() };
|
|
2705
2691
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
if (cachedSdk) {
|
|
2711
|
-
return cachedSdk;
|
|
2692
|
+
let privateKey = config.privateKey?.trim();
|
|
2693
|
+
const envVar = config.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
|
|
2694
|
+
if (!privateKey && envVar && process?.env?.[envVar]?.trim()) {
|
|
2695
|
+
privateKey = process.env[envVar]?.trim();
|
|
2712
2696
|
}
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2697
|
+
if (!privateKey && config.generateIfMissing) {
|
|
2698
|
+
const pair = await client.generateEncryptionKeyPair({
|
|
2699
|
+
keyType: config.keyType ?? "secp256k1",
|
|
2700
|
+
envVar,
|
|
2701
|
+
envPath: config.envPath,
|
|
2702
|
+
overwrite: config.overwriteEnv
|
|
2703
|
+
});
|
|
2704
|
+
return { publicKey: pair.publicKey, privateKey: pair.privateKey };
|
|
2717
2705
|
}
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
};
|
|
2721
|
-
var buildSigner = (sdk, options) => {
|
|
2722
|
-
const { AccountId, LedgerId, PrivateKey, SignerSignature } = sdk;
|
|
2723
|
-
if (!options.privateKey) {
|
|
2724
|
-
throw new Error("privateKey is required to create a ledger signer.");
|
|
2706
|
+
if (privateKey) {
|
|
2707
|
+
const publicKey = derivePublicKeyFromPrivateKey(client, privateKey);
|
|
2708
|
+
return { publicKey, privateKey };
|
|
2725
2709
|
}
|
|
2726
|
-
|
|
2727
|
-
|
|
2710
|
+
return null;
|
|
2711
|
+
}
|
|
2712
|
+
async function autoRegisterEncryptionKey(client, config) {
|
|
2713
|
+
const identity = normalizeAutoRegisterIdentity(config);
|
|
2714
|
+
if (!identity) {
|
|
2715
|
+
throw new Error(
|
|
2716
|
+
"Auto-registration requires uaid, ledgerAccountId, or email"
|
|
2717
|
+
);
|
|
2728
2718
|
}
|
|
2729
|
-
const
|
|
2730
|
-
|
|
2731
|
-
|
|
2719
|
+
const material = await resolveAutoRegisterKeyMaterial(client, config);
|
|
2720
|
+
if (!material) {
|
|
2721
|
+
throw new Error(
|
|
2722
|
+
"Unable to resolve encryption public key for auto-registration"
|
|
2723
|
+
);
|
|
2724
|
+
}
|
|
2725
|
+
await registerEncryptionKey(client, {
|
|
2726
|
+
keyType: config.keyType ?? "secp256k1",
|
|
2727
|
+
publicKey: material.publicKey,
|
|
2728
|
+
...identity
|
|
2729
|
+
});
|
|
2730
|
+
return material;
|
|
2731
|
+
}
|
|
2732
|
+
async function ensureAgentEncryptionKey(client, options) {
|
|
2733
|
+
return autoRegisterEncryptionKey(client, {
|
|
2734
|
+
...options,
|
|
2735
|
+
uaid: options.uaid,
|
|
2736
|
+
enabled: true
|
|
2737
|
+
});
|
|
2738
|
+
}
|
|
2739
|
+
function createEncryptionApi(client) {
|
|
2732
2740
|
return {
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
messages.map(async (message) => {
|
|
2740
|
-
const signature = await privateKey.sign(message);
|
|
2741
|
-
return new SignerSignature({
|
|
2742
|
-
publicKey: privateKey.publicKey,
|
|
2743
|
-
signature,
|
|
2744
|
-
accountId
|
|
2745
|
-
});
|
|
2746
|
-
})
|
|
2747
|
-
),
|
|
2748
|
-
getAccountBalance: async () => {
|
|
2749
|
-
throw unsupported("getAccountBalance");
|
|
2750
|
-
},
|
|
2751
|
-
getAccountInfo: async () => {
|
|
2752
|
-
throw unsupported("getAccountInfo");
|
|
2753
|
-
},
|
|
2754
|
-
getAccountRecords: async () => {
|
|
2755
|
-
throw unsupported("getAccountRecords");
|
|
2756
|
-
},
|
|
2757
|
-
signTransaction: async (_) => {
|
|
2758
|
-
throw unsupported("signTransaction");
|
|
2759
|
-
},
|
|
2760
|
-
checkTransaction: async (_) => {
|
|
2761
|
-
throw unsupported("checkTransaction");
|
|
2762
|
-
},
|
|
2763
|
-
populateTransaction: async (_) => {
|
|
2764
|
-
throw unsupported("populateTransaction");
|
|
2765
|
-
},
|
|
2766
|
-
call: async (_request) => {
|
|
2767
|
-
throw unsupported("call");
|
|
2768
|
-
}
|
|
2741
|
+
registerKey: (payload) => registerEncryptionKey(client, payload),
|
|
2742
|
+
generateEphemeralKeyPair: () => client.createEphemeralKeyPair(),
|
|
2743
|
+
deriveSharedSecret: (options) => client.deriveSharedSecret(options),
|
|
2744
|
+
encryptCipherEnvelope: (options) => client.buildCipherEnvelope(options),
|
|
2745
|
+
decryptCipherEnvelope: (options) => client.openCipherEnvelope(options),
|
|
2746
|
+
ensureAgentKey: (options) => ensureAgentEncryptionKey(client, options)
|
|
2769
2747
|
};
|
|
2770
|
-
}
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
// ../../src/services/registry-broker/client/ledger-auth.ts
|
|
2775
|
-
async function loadViemAccount(privateKey) {
|
|
2776
|
-
try {
|
|
2777
|
-
const viem = await import("viem/accounts");
|
|
2778
|
-
return viem.privateKeyToAccount(privateKey);
|
|
2779
|
-
} catch (error) {
|
|
2780
|
-
const err = new Error(
|
|
2781
|
-
'EVM ledger authentication requires the optional dependency "viem". Install it to use evmPrivateKey flows.'
|
|
2782
|
-
);
|
|
2783
|
-
err.cause = error;
|
|
2784
|
-
throw err;
|
|
2748
|
+
}
|
|
2749
|
+
async function bootstrapEncryptionOptions(client, options) {
|
|
2750
|
+
if (!options?.autoRegister || options.autoRegister.enabled === false) {
|
|
2751
|
+
return null;
|
|
2785
2752
|
}
|
|
2753
|
+
return autoRegisterEncryptionKey(client, options.autoRegister);
|
|
2786
2754
|
}
|
|
2787
|
-
async function
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
}
|
|
2793
|
-
return result;
|
|
2755
|
+
async function generateEncryptionKeyPair(client, options = {}) {
|
|
2756
|
+
client.assertNodeRuntime("generateEncryptionKeyPair");
|
|
2757
|
+
const keyType = options.keyType ?? "secp256k1";
|
|
2758
|
+
if (keyType !== "secp256k1") {
|
|
2759
|
+
throw new Error("Only secp256k1 key generation is supported currently");
|
|
2794
2760
|
}
|
|
2795
|
-
|
|
2761
|
+
const cryptoModule = await getNodeCrypto();
|
|
2762
|
+
if (!cryptoModule) {
|
|
2796
2763
|
throw new Error(
|
|
2797
|
-
"
|
|
2764
|
+
"Node.js crypto module is not available; cannot generate encryption key pair"
|
|
2798
2765
|
);
|
|
2799
2766
|
}
|
|
2800
|
-
const
|
|
2801
|
-
const
|
|
2802
|
-
const
|
|
2803
|
-
|
|
2804
|
-
|
|
2767
|
+
const privateKeyBytes = cryptoModule.randomBytes(32);
|
|
2768
|
+
const privateKey = Buffer3.from(privateKeyBytes).toString("hex");
|
|
2769
|
+
const publicKeyBytes = secp256k1.getPublicKey(privateKeyBytes, true);
|
|
2770
|
+
const publicKey = Buffer3.from(publicKeyBytes).toString("hex");
|
|
2771
|
+
const envVar = options.envVar ?? "RB_ENCRYPTION_PRIVATE_KEY";
|
|
2772
|
+
const pathModule = options.envPath ? await getNodePath() : null;
|
|
2773
|
+
const resolvedPath = options.envPath && pathModule ? pathModule.resolve(options.envPath) : void 0;
|
|
2774
|
+
if (options.envPath && !resolvedPath) {
|
|
2775
|
+
throw new Error(
|
|
2776
|
+
"Node.js path module is not available; cannot resolve encryption key env path"
|
|
2777
|
+
);
|
|
2805
2778
|
}
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2779
|
+
if (resolvedPath) {
|
|
2780
|
+
const fsModule = await getFs();
|
|
2781
|
+
if (!fsModule) {
|
|
2782
|
+
throw new Error(
|
|
2783
|
+
"File system module is not available; cannot write encryption key env file"
|
|
2784
|
+
);
|
|
2785
|
+
}
|
|
2786
|
+
const envLine = `${envVar}=${privateKey}`;
|
|
2787
|
+
if (fsModule.existsSync(resolvedPath)) {
|
|
2788
|
+
const content = fsModule.readFileSync(resolvedPath, "utf-8");
|
|
2789
|
+
const lineRegex = new RegExp(`^${envVar}=.*$`, "m");
|
|
2790
|
+
if (lineRegex.test(content)) {
|
|
2791
|
+
if (!options.overwrite) {
|
|
2792
|
+
throw new Error(
|
|
2793
|
+
`${envVar} already exists in ${resolvedPath}; set overwrite=true to replace it`
|
|
2794
|
+
);
|
|
2795
|
+
}
|
|
2796
|
+
const updated = content.replace(lineRegex, envLine);
|
|
2797
|
+
fsModule.writeFileSync(resolvedPath, updated);
|
|
2798
|
+
} else {
|
|
2799
|
+
const needsNewline = !content.endsWith("\n");
|
|
2800
|
+
fsModule.appendFileSync(
|
|
2801
|
+
resolvedPath,
|
|
2802
|
+
`${needsNewline ? "\n" : ""}${envLine}
|
|
2803
|
+
`
|
|
2804
|
+
);
|
|
2805
|
+
}
|
|
2806
|
+
} else {
|
|
2807
|
+
fsModule.writeFileSync(resolvedPath, `${envLine}
|
|
2808
|
+
`);
|
|
2813
2809
|
}
|
|
2814
2810
|
}
|
|
2815
2811
|
return {
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2812
|
+
privateKey,
|
|
2813
|
+
publicKey,
|
|
2814
|
+
envPath: resolvedPath,
|
|
2815
|
+
envVar
|
|
2819
2816
|
};
|
|
2820
2817
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
const raw = await client.requestJson("/
|
|
2825
|
-
method: "
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2818
|
+
|
|
2819
|
+
// ../../src/services/registry-broker/client/adapters.ts
|
|
2820
|
+
async function adapters(client) {
|
|
2821
|
+
const raw = await client.requestJson("/adapters", {
|
|
2822
|
+
method: "GET"
|
|
2823
|
+
});
|
|
2824
|
+
return client.parseWithSchema(
|
|
2825
|
+
raw,
|
|
2826
|
+
adaptersResponseSchema,
|
|
2827
|
+
"adapters response"
|
|
2828
|
+
);
|
|
2829
|
+
}
|
|
2830
|
+
async function adaptersDetailed(client) {
|
|
2831
|
+
const raw = await client.requestJson("/adapters/details", {
|
|
2832
|
+
method: "GET"
|
|
2833
|
+
});
|
|
2834
|
+
return client.parseWithSchema(
|
|
2835
|
+
raw,
|
|
2836
|
+
adapterDetailsResponseSchema,
|
|
2837
|
+
"adapter details response"
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2840
|
+
async function adapterRegistryCategories(client) {
|
|
2841
|
+
const raw = await client.requestJson(
|
|
2842
|
+
"/adapters/registry/categories",
|
|
2843
|
+
{
|
|
2844
|
+
method: "GET"
|
|
2830
2845
|
}
|
|
2831
|
-
|
|
2846
|
+
);
|
|
2832
2847
|
return client.parseWithSchema(
|
|
2833
2848
|
raw,
|
|
2834
|
-
|
|
2835
|
-
"
|
|
2849
|
+
adapterRegistryCategoriesResponseSchema,
|
|
2850
|
+
"adapter registry categories response"
|
|
2836
2851
|
);
|
|
2837
2852
|
}
|
|
2838
|
-
async function
|
|
2839
|
-
const
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
challengeId: payload.challengeId,
|
|
2843
|
-
accountId: payload.accountId,
|
|
2844
|
-
network,
|
|
2845
|
-
signature: payload.signature
|
|
2846
|
-
};
|
|
2847
|
-
if (payload.signatureKind) {
|
|
2848
|
-
body.signatureKind = payload.signatureKind;
|
|
2853
|
+
async function adapterRegistryAdapters(client, filters = {}) {
|
|
2854
|
+
const params = new URLSearchParams();
|
|
2855
|
+
if (filters.category) {
|
|
2856
|
+
params.set("category", filters.category);
|
|
2849
2857
|
}
|
|
2850
|
-
if (
|
|
2851
|
-
|
|
2858
|
+
if (filters.entity) {
|
|
2859
|
+
params.set("entity", filters.entity);
|
|
2852
2860
|
}
|
|
2853
|
-
if (
|
|
2854
|
-
|
|
2861
|
+
if (filters.keywords?.length) {
|
|
2862
|
+
params.set("keywords", filters.keywords.join(","));
|
|
2855
2863
|
}
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2864
|
+
if (filters.query) {
|
|
2865
|
+
params.set("query", filters.query);
|
|
2866
|
+
}
|
|
2867
|
+
if (typeof filters.limit === "number") {
|
|
2868
|
+
params.set("limit", String(filters.limit));
|
|
2869
|
+
}
|
|
2870
|
+
if (typeof filters.offset === "number") {
|
|
2871
|
+
params.set("offset", String(filters.offset));
|
|
2872
|
+
}
|
|
2873
|
+
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
2874
|
+
const raw = await client.requestJson(
|
|
2875
|
+
`/adapters/registry/adapters${suffix}`,
|
|
2876
|
+
{
|
|
2877
|
+
method: "GET"
|
|
2878
|
+
}
|
|
2879
|
+
);
|
|
2880
|
+
return client.parseWithSchema(
|
|
2862
2881
|
raw,
|
|
2863
|
-
|
|
2864
|
-
"
|
|
2882
|
+
adapterRegistryAdaptersResponseSchema,
|
|
2883
|
+
"adapter registry adapters response"
|
|
2865
2884
|
);
|
|
2866
|
-
client.setLedgerApiKey(result.key);
|
|
2867
|
-
return result;
|
|
2868
2885
|
}
|
|
2869
|
-
async function
|
|
2870
|
-
const
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
return verification;
|
|
2886
|
+
async function createAdapterRegistryCategory(client, payload) {
|
|
2887
|
+
const raw = await client.requestJson(
|
|
2888
|
+
"/adapters/registry/categories",
|
|
2889
|
+
{
|
|
2890
|
+
method: "POST",
|
|
2891
|
+
headers: { "content-type": "application/json" },
|
|
2892
|
+
body: toJsonObject(payload)
|
|
2893
|
+
}
|
|
2894
|
+
);
|
|
2895
|
+
const parsed = client.parseWithSchema(
|
|
2896
|
+
raw,
|
|
2897
|
+
adapterRegistryCreateCategoryResponseSchema,
|
|
2898
|
+
"adapter registry create category response"
|
|
2899
|
+
);
|
|
2900
|
+
return parsed.category;
|
|
2885
2901
|
}
|
|
2886
|
-
async function
|
|
2887
|
-
const
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
evmPrivateKey,
|
|
2894
|
-
expiresInMinutes,
|
|
2895
|
-
setAccountHeader = true,
|
|
2896
|
-
label,
|
|
2897
|
-
logger
|
|
2898
|
-
} = options;
|
|
2899
|
-
const resolvedNetwork = canonicalizeLedgerNetwork(network);
|
|
2900
|
-
const labelSuffix = label ? ` for ${label}` : "";
|
|
2901
|
-
const networkPayload = resolvedNetwork.canonical;
|
|
2902
|
-
const authOptions = {
|
|
2903
|
-
accountId,
|
|
2904
|
-
network: networkPayload,
|
|
2905
|
-
expiresInMinutes
|
|
2906
|
-
};
|
|
2907
|
-
if (sign) {
|
|
2908
|
-
authOptions.sign = sign;
|
|
2909
|
-
} else if (signer) {
|
|
2910
|
-
authOptions.signer = signer;
|
|
2911
|
-
} else if (hederaPrivateKey) {
|
|
2912
|
-
if (resolvedNetwork.kind !== "hedera" || !resolvedNetwork.hederaNetwork) {
|
|
2913
|
-
throw new Error(
|
|
2914
|
-
"hederaPrivateKey can only be used with hedera:mainnet or hedera:testnet networks."
|
|
2915
|
-
);
|
|
2902
|
+
async function submitAdapterRegistryAdapter(client, payload) {
|
|
2903
|
+
const raw = await client.requestJson(
|
|
2904
|
+
"/adapters/registry/adapters",
|
|
2905
|
+
{
|
|
2906
|
+
method: "POST",
|
|
2907
|
+
headers: { "content-type": "application/json" },
|
|
2908
|
+
body: toJsonObject(payload)
|
|
2916
2909
|
}
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2910
|
+
);
|
|
2911
|
+
return client.parseWithSchema(
|
|
2912
|
+
raw,
|
|
2913
|
+
adapterRegistrySubmitAdapterAcceptedResponseSchema,
|
|
2914
|
+
"adapter registry submit adapter response"
|
|
2915
|
+
);
|
|
2916
|
+
}
|
|
2917
|
+
async function adapterRegistrySubmissionStatus(client, submissionId) {
|
|
2918
|
+
const raw = await client.requestJson(
|
|
2919
|
+
`/adapters/registry/submissions/${encodeURIComponent(submissionId)}`,
|
|
2920
|
+
{
|
|
2921
|
+
method: "GET"
|
|
2927
2922
|
}
|
|
2928
|
-
const formattedKey = evmPrivateKey.startsWith("0x") ? evmPrivateKey : `0x${evmPrivateKey}`;
|
|
2929
|
-
const account = await loadViemAccount(formattedKey);
|
|
2930
|
-
authOptions.sign = async (message) => ({
|
|
2931
|
-
signature: await account.signMessage({ message }),
|
|
2932
|
-
signatureKind: "evm",
|
|
2933
|
-
publicKey: account.publicKey
|
|
2934
|
-
});
|
|
2935
|
-
} else {
|
|
2936
|
-
throw new Error(
|
|
2937
|
-
"Provide a signer, sign function, hederaPrivateKey, or evmPrivateKey to authenticate with the ledger."
|
|
2938
|
-
);
|
|
2939
|
-
}
|
|
2940
|
-
logger?.info?.(
|
|
2941
|
-
`Authenticating ledger account ${accountId} (${resolvedNetwork.canonical})${labelSuffix}...`
|
|
2942
2923
|
);
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
logger?.info?.(
|
|
2948
|
-
`Ledger authentication complete${labelSuffix}. Issued key prefix: ${verification.apiKey.prefix}\u2026${verification.apiKey.lastFour}`
|
|
2924
|
+
return client.parseWithSchema(
|
|
2925
|
+
raw,
|
|
2926
|
+
adapterRegistrySubmissionStatusResponseSchema,
|
|
2927
|
+
"adapter registry submission status response"
|
|
2949
2928
|
);
|
|
2950
|
-
return verification;
|
|
2951
2929
|
}
|
|
2952
2930
|
|
|
2953
|
-
// ../../src/services/registry-broker/client/
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2931
|
+
// ../../src/services/registry-broker/client/credits.ts
|
|
2932
|
+
async function loadX402Dependencies(client) {
|
|
2933
|
+
const [{ default: axios }, x402Axios, x402Types] = await Promise.all([
|
|
2934
|
+
import("axios"),
|
|
2935
|
+
optionalImport("x402-axios"),
|
|
2936
|
+
optionalImport("x402/types")
|
|
2937
|
+
]);
|
|
2938
|
+
if (!x402Axios || !x402Types) {
|
|
2939
|
+
throw new Error(
|
|
2940
|
+
"x402-axios and x402/types are required for X402 flows. Install them to enable ledger payments."
|
|
2941
|
+
);
|
|
2964
2942
|
}
|
|
2965
|
-
|
|
2966
|
-
|
|
2943
|
+
const withPaymentInterceptor = x402Axios.withPaymentInterceptor;
|
|
2944
|
+
const decodePaymentResponse = x402Axios.decodeXPaymentResponse;
|
|
2945
|
+
const createX402Signer = x402Types.createSigner;
|
|
2946
|
+
const createPaymentClient = (walletClient) => {
|
|
2947
|
+
const axiosClient = axios.create({
|
|
2948
|
+
baseURL: client.baseUrl,
|
|
2949
|
+
headers: {
|
|
2950
|
+
...client.getDefaultHeaders(),
|
|
2951
|
+
"content-type": "application/json"
|
|
2952
|
+
}
|
|
2953
|
+
});
|
|
2954
|
+
const paymentClient = withPaymentInterceptor(axiosClient, walletClient);
|
|
2955
|
+
return paymentClient;
|
|
2956
|
+
};
|
|
2957
|
+
return { createPaymentClient, decodePaymentResponse, createX402Signer };
|
|
2958
|
+
}
|
|
2959
|
+
function calculateHbarAmountParam(hbarAmount) {
|
|
2960
|
+
const tinybars = Math.ceil(hbarAmount * 1e8);
|
|
2961
|
+
if (tinybars <= 0) {
|
|
2962
|
+
throw new Error("Calculated purchase amount must be positive");
|
|
2967
2963
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
2964
|
+
return tinybars / 1e8;
|
|
2965
|
+
}
|
|
2966
|
+
async function purchaseCreditsWithHbar(client, params) {
|
|
2967
|
+
const body = {
|
|
2968
|
+
accountId: params.accountId,
|
|
2969
|
+
payerKey: params.privateKey,
|
|
2970
|
+
hbarAmount: calculateHbarAmountParam(params.hbarAmount)
|
|
2971
|
+
};
|
|
2972
|
+
if (params.memo) {
|
|
2973
|
+
body.memo = params.memo;
|
|
2970
2974
|
}
|
|
2971
|
-
if (
|
|
2972
|
-
|
|
2975
|
+
if (params.metadata) {
|
|
2976
|
+
body.metadata = params.metadata;
|
|
2973
2977
|
}
|
|
2974
|
-
|
|
2978
|
+
const raw = await client.requestJson("/credits/purchase", {
|
|
2979
|
+
method: "POST",
|
|
2980
|
+
headers: { "content-type": "application/json" },
|
|
2981
|
+
body
|
|
2982
|
+
});
|
|
2983
|
+
return client.parseWithSchema(
|
|
2984
|
+
raw,
|
|
2985
|
+
creditPurchaseResponseSchema,
|
|
2986
|
+
"credit purchase response"
|
|
2987
|
+
);
|
|
2975
2988
|
}
|
|
2976
|
-
async function
|
|
2977
|
-
if (!sessionId || sessionId.trim().length === 0) {
|
|
2978
|
-
throw new Error("sessionId is required to fetch chat history");
|
|
2979
|
-
}
|
|
2989
|
+
async function getX402Minimums(client) {
|
|
2980
2990
|
const raw = await client.requestJson(
|
|
2981
|
-
|
|
2982
|
-
{
|
|
2983
|
-
method: "GET"
|
|
2984
|
-
}
|
|
2991
|
+
"/credits/purchase/x402/minimums",
|
|
2992
|
+
{ method: "GET" }
|
|
2985
2993
|
);
|
|
2986
|
-
|
|
2994
|
+
return client.parseWithSchema(
|
|
2987
2995
|
raw,
|
|
2988
|
-
|
|
2989
|
-
"
|
|
2990
|
-
);
|
|
2991
|
-
return attachDecryptedHistory(
|
|
2992
|
-
conversationContexts,
|
|
2993
|
-
client,
|
|
2994
|
-
sessionId,
|
|
2995
|
-
snapshot,
|
|
2996
|
-
options
|
|
2996
|
+
x402MinimumsResponseSchema,
|
|
2997
|
+
"x402 minimums response"
|
|
2997
2998
|
);
|
|
2998
2999
|
}
|
|
2999
|
-
function
|
|
3000
|
-
const
|
|
3001
|
-
if (!
|
|
3002
|
-
|
|
3003
|
-
}
|
|
3004
|
-
const requiresContext = snapshot.history.some(
|
|
3005
|
-
(entry) => Boolean(entry.cipherEnvelope)
|
|
3006
|
-
);
|
|
3007
|
-
if (!requiresContext) {
|
|
3008
|
-
return {
|
|
3009
|
-
...snapshot,
|
|
3010
|
-
decryptedHistory: snapshot.history.map((entry) => ({
|
|
3011
|
-
entry,
|
|
3012
|
-
plaintext: entry.content
|
|
3013
|
-
}))
|
|
3014
|
-
};
|
|
3000
|
+
async function purchaseCreditsWithX402(client, params) {
|
|
3001
|
+
const { createPaymentClient, decodePaymentResponse } = await loadX402Dependencies(client);
|
|
3002
|
+
if (!Number.isFinite(params.credits) || params.credits <= 0) {
|
|
3003
|
+
throw new Error("credits must be a positive number");
|
|
3015
3004
|
}
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
client,
|
|
3019
|
-
sessionId,
|
|
3020
|
-
options
|
|
3021
|
-
);
|
|
3022
|
-
if (!context) {
|
|
3023
|
-
throw new Error(
|
|
3024
|
-
"Unable to decrypt chat history: encryption context unavailable"
|
|
3025
|
-
);
|
|
3005
|
+
if (params.usdAmount !== void 0 && (!Number.isFinite(params.usdAmount) || params.usdAmount <= 0)) {
|
|
3006
|
+
throw new Error("usdAmount must be a positive number when provided");
|
|
3026
3007
|
}
|
|
3027
|
-
const
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
}));
|
|
3031
|
-
return { ...snapshot, decryptedHistory };
|
|
3032
|
-
}
|
|
3033
|
-
function registerConversationContextForEncryption(conversationContexts, context) {
|
|
3034
|
-
const normalized = {
|
|
3035
|
-
sessionId: context.sessionId,
|
|
3036
|
-
sharedSecret: Buffer4.from(context.sharedSecret),
|
|
3037
|
-
identity: context.identity ? { ...context.identity } : void 0
|
|
3008
|
+
const body = {
|
|
3009
|
+
accountId: params.accountId,
|
|
3010
|
+
credits: params.credits
|
|
3038
3011
|
};
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
(existing) => identitiesMatch(existing.identity, normalized.identity)
|
|
3042
|
-
);
|
|
3043
|
-
if (existingIndex >= 0) {
|
|
3044
|
-
entries[existingIndex] = normalized;
|
|
3045
|
-
} else {
|
|
3046
|
-
entries.push(normalized);
|
|
3047
|
-
}
|
|
3048
|
-
conversationContexts.set(context.sessionId, entries);
|
|
3049
|
-
}
|
|
3050
|
-
function resolveDecryptionContext(conversationContexts, client, sessionId, options) {
|
|
3051
|
-
if (options?.sharedSecret) {
|
|
3052
|
-
return {
|
|
3053
|
-
sessionId,
|
|
3054
|
-
sharedSecret: client.normalizeSharedSecret(options.sharedSecret),
|
|
3055
|
-
identity: options.identity
|
|
3056
|
-
};
|
|
3012
|
+
if (params.usdAmount !== void 0) {
|
|
3013
|
+
body.usdAmount = params.usdAmount;
|
|
3057
3014
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
return null;
|
|
3015
|
+
if (params.description) {
|
|
3016
|
+
body.description = params.description;
|
|
3061
3017
|
}
|
|
3062
|
-
if (
|
|
3063
|
-
|
|
3064
|
-
(context) => identitiesMatch(context.identity, options.identity)
|
|
3065
|
-
);
|
|
3066
|
-
if (match) {
|
|
3067
|
-
return match;
|
|
3068
|
-
}
|
|
3018
|
+
if (params.metadata) {
|
|
3019
|
+
body.metadata = params.metadata;
|
|
3069
3020
|
}
|
|
3070
|
-
|
|
3021
|
+
const paymentClient = createPaymentClient(params.walletClient);
|
|
3022
|
+
const response = await paymentClient.post("/credits/purchase/x402", body);
|
|
3023
|
+
const parsed = client.parseWithSchema(
|
|
3024
|
+
response.data,
|
|
3025
|
+
x402CreditPurchaseResponseSchema,
|
|
3026
|
+
"x402 credit purchase response"
|
|
3027
|
+
);
|
|
3028
|
+
const responseHeaders = response.headers ?? {};
|
|
3029
|
+
const paymentHeader = typeof responseHeaders["x-payment-response"] === "string" ? responseHeaders["x-payment-response"] : void 0;
|
|
3030
|
+
const decodedPayment = paymentHeader !== void 0 ? decodePaymentResponse(paymentHeader) : void 0;
|
|
3031
|
+
return {
|
|
3032
|
+
...parsed,
|
|
3033
|
+
paymentResponseHeader: paymentHeader,
|
|
3034
|
+
paymentResponse: decodedPayment
|
|
3035
|
+
};
|
|
3071
3036
|
}
|
|
3072
|
-
function
|
|
3073
|
-
const
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
}
|
|
3037
|
+
async function buyCreditsWithX402(client, params) {
|
|
3038
|
+
const network = params.network ?? "base";
|
|
3039
|
+
const { createX402Signer } = await loadX402Dependencies(client);
|
|
3040
|
+
const normalizedKey = normalizeHexPrivateKey(params.evmPrivateKey);
|
|
3041
|
+
const walletClient = await createX402Signer(network, normalizedKey);
|
|
3042
|
+
return purchaseCreditsWithX402(client, {
|
|
3043
|
+
accountId: params.accountId,
|
|
3044
|
+
credits: params.credits,
|
|
3045
|
+
usdAmount: params.usdAmount,
|
|
3046
|
+
description: params.description,
|
|
3047
|
+
metadata: params.metadata,
|
|
3048
|
+
walletClient
|
|
3049
|
+
});
|
|
3086
3050
|
}
|
|
3087
3051
|
|
|
3088
|
-
// ../../src/services/registry-broker/client/
|
|
3089
|
-
var
|
|
3090
|
-
constructor(
|
|
3091
|
-
super(
|
|
3092
|
-
this.
|
|
3093
|
-
this.
|
|
3052
|
+
// ../../src/services/registry-broker/client/errors.ts
|
|
3053
|
+
var RegistryBrokerError = class extends Error {
|
|
3054
|
+
constructor(message, details) {
|
|
3055
|
+
super(message);
|
|
3056
|
+
this.status = details.status;
|
|
3057
|
+
this.statusText = details.statusText;
|
|
3058
|
+
this.body = details.body;
|
|
3094
3059
|
}
|
|
3095
3060
|
};
|
|
3096
|
-
var
|
|
3097
|
-
constructor(
|
|
3098
|
-
|
|
3061
|
+
var RegistryBrokerParseError = class extends Error {
|
|
3062
|
+
constructor(message, cause, rawValue) {
|
|
3063
|
+
super(message);
|
|
3064
|
+
this.cause = cause;
|
|
3065
|
+
this.rawValue = rawValue;
|
|
3099
3066
|
}
|
|
3100
|
-
|
|
3101
|
-
|
|
3067
|
+
};
|
|
3068
|
+
|
|
3069
|
+
// ../../src/services/registry-broker/client/agents.ts
|
|
3070
|
+
async function performRegisterAgent(client, payload) {
|
|
3071
|
+
const raw = await client.requestJson("/register", {
|
|
3072
|
+
method: "POST",
|
|
3073
|
+
body: serialiseAgentRegistrationRequest(payload),
|
|
3074
|
+
headers: { "content-type": "application/json" }
|
|
3075
|
+
});
|
|
3076
|
+
return client.parseWithSchema(
|
|
3077
|
+
raw,
|
|
3078
|
+
registerAgentResponseSchema,
|
|
3079
|
+
"register agent response"
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
function calculateHbarAmount(creditsToPurchase, creditsPerHbar) {
|
|
3083
|
+
if (creditsPerHbar <= 0) {
|
|
3084
|
+
throw new Error("creditsPerHbar must be positive");
|
|
3102
3085
|
}
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
const session = await this.client.chat.createSession({
|
|
3106
|
-
uaid: options.uaid,
|
|
3107
|
-
senderUaid: options.senderUaid,
|
|
3108
|
-
encryptionRequested: true,
|
|
3109
|
-
historyTtlSeconds: options.historyTtlSeconds,
|
|
3110
|
-
auth: options.auth
|
|
3111
|
-
});
|
|
3112
|
-
options.onSessionCreated?.(session.sessionId);
|
|
3113
|
-
const summary = session.encryption;
|
|
3114
|
-
if (!summary?.enabled) {
|
|
3115
|
-
throw new EncryptionUnavailableError(
|
|
3116
|
-
session.sessionId,
|
|
3117
|
-
session.encryption ?? null
|
|
3118
|
-
);
|
|
3119
|
-
}
|
|
3120
|
-
const handle = await this.establishRequesterContext({
|
|
3121
|
-
sessionId: session.sessionId,
|
|
3122
|
-
summary,
|
|
3123
|
-
senderUaid: options.senderUaid,
|
|
3124
|
-
handshakeTimeoutMs: options.handshakeTimeoutMs,
|
|
3125
|
-
pollIntervalMs: options.pollIntervalMs
|
|
3126
|
-
});
|
|
3127
|
-
return handle;
|
|
3086
|
+
if (creditsToPurchase <= 0) {
|
|
3087
|
+
throw new Error("creditsToPurchase must be positive");
|
|
3128
3088
|
}
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
const handle = await this.establishResponderContext({
|
|
3137
|
-
sessionId: options.sessionId,
|
|
3138
|
-
summary,
|
|
3139
|
-
responderUaid: options.responderUaid,
|
|
3140
|
-
handshakeTimeoutMs: options.handshakeTimeoutMs,
|
|
3141
|
-
pollIntervalMs: options.pollIntervalMs
|
|
3142
|
-
});
|
|
3143
|
-
return handle;
|
|
3089
|
+
const rawHbar = creditsToPurchase / creditsPerHbar;
|
|
3090
|
+
const tinybars = Math.ceil(rawHbar * 1e8);
|
|
3091
|
+
return tinybars / 1e8;
|
|
3092
|
+
}
|
|
3093
|
+
function resolveCreditsToPurchase(shortfallCredits) {
|
|
3094
|
+
if (!Number.isFinite(shortfallCredits) || shortfallCredits <= 0) {
|
|
3095
|
+
return 0;
|
|
3144
3096
|
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
params.sessionId,
|
|
3155
|
-
params.handshakeTimeoutMs,
|
|
3156
|
-
params.pollIntervalMs
|
|
3157
|
-
);
|
|
3158
|
-
const responderKey = record.responder?.ephemeralPublicKey;
|
|
3159
|
-
if (!responderKey) {
|
|
3160
|
-
throw new Error("Responder handshake was not completed in time");
|
|
3161
|
-
}
|
|
3162
|
-
const sharedSecret = this.client.encryption.deriveSharedSecret({
|
|
3163
|
-
privateKey: keyPair.privateKey,
|
|
3164
|
-
peerPublicKey: responderKey
|
|
3165
|
-
}).subarray();
|
|
3166
|
-
const recipients = this.buildRecipients(summary);
|
|
3167
|
-
return this.createHandle({
|
|
3168
|
-
sessionId: params.sessionId,
|
|
3169
|
-
sharedSecret,
|
|
3170
|
-
summary,
|
|
3171
|
-
recipients,
|
|
3172
|
-
identity: summary.requester ?? void 0
|
|
3173
|
-
});
|
|
3097
|
+
return Math.max(
|
|
3098
|
+
Math.ceil(shortfallCredits),
|
|
3099
|
+
MINIMUM_REGISTRATION_AUTO_TOP_UP_CREDITS
|
|
3100
|
+
);
|
|
3101
|
+
}
|
|
3102
|
+
async function ensureCreditsForRegistration(client, payload, autoTopUp) {
|
|
3103
|
+
const details = autoTopUp ?? null;
|
|
3104
|
+
if (!details) {
|
|
3105
|
+
return;
|
|
3174
3106
|
}
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
const
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
params.pollIntervalMs
|
|
3187
|
-
);
|
|
3188
|
-
const requesterKey = record.requester?.ephemeralPublicKey;
|
|
3189
|
-
if (!requesterKey) {
|
|
3190
|
-
throw new Error("Requester handshake was not detected in time");
|
|
3107
|
+
if (!details.accountId || !details.accountId.trim()) {
|
|
3108
|
+
throw new Error("autoTopUp.accountId is required");
|
|
3109
|
+
}
|
|
3110
|
+
if (!details.privateKey || !details.privateKey.trim()) {
|
|
3111
|
+
throw new Error("autoTopUp.privateKey is required");
|
|
3112
|
+
}
|
|
3113
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
3114
|
+
const quote = await getRegistrationQuote(client, payload);
|
|
3115
|
+
const shortfall = quote.shortfallCredits ?? 0;
|
|
3116
|
+
if (shortfall <= 0) {
|
|
3117
|
+
return;
|
|
3191
3118
|
}
|
|
3192
|
-
const
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
}
|
|
3196
|
-
const
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3119
|
+
const creditsToPurchase = resolveCreditsToPurchase(shortfall);
|
|
3120
|
+
if (creditsToPurchase <= 0) {
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
const creditsPerHbar = quote.creditsPerHbar ?? null;
|
|
3124
|
+
if (!creditsPerHbar || creditsPerHbar <= 0) {
|
|
3125
|
+
throw new Error("Unable to determine credits per HBAR for auto top-up");
|
|
3126
|
+
}
|
|
3127
|
+
const hbarAmount = calculateHbarAmount(creditsToPurchase, creditsPerHbar);
|
|
3128
|
+
await purchaseCreditsWithHbar(client, {
|
|
3129
|
+
accountId: details.accountId.trim(),
|
|
3130
|
+
privateKey: details.privateKey.trim(),
|
|
3131
|
+
hbarAmount,
|
|
3132
|
+
memo: details.memo ?? "Registry Broker auto top-up",
|
|
3133
|
+
metadata: {
|
|
3134
|
+
shortfallCredits: shortfall,
|
|
3135
|
+
requiredCredits: quote.requiredCredits,
|
|
3136
|
+
purchasedCredits: creditsToPurchase
|
|
3137
|
+
}
|
|
3203
3138
|
});
|
|
3204
3139
|
}
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3140
|
+
const finalQuote = await getRegistrationQuote(client, payload);
|
|
3141
|
+
if ((finalQuote.shortfallCredits ?? 0) > 0) {
|
|
3142
|
+
throw new Error("Unable to purchase sufficient credits for registration");
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
async function resolveUaid(client, uaid) {
|
|
3146
|
+
const raw = await client.requestJson(
|
|
3147
|
+
`/resolve/${encodeURIComponent(uaid)}`,
|
|
3148
|
+
{
|
|
3149
|
+
method: "GET"
|
|
3150
|
+
}
|
|
3151
|
+
);
|
|
3152
|
+
return client.parseWithSchema(
|
|
3153
|
+
raw,
|
|
3154
|
+
resolveResponseSchema,
|
|
3155
|
+
"resolve UAID response"
|
|
3156
|
+
);
|
|
3157
|
+
}
|
|
3158
|
+
async function registerAgent(client, payload, options) {
|
|
3159
|
+
const autoTopUp = options?.autoTopUp ?? client.registrationAutoTopUp;
|
|
3160
|
+
if (!autoTopUp) {
|
|
3161
|
+
return performRegisterAgent(client, payload);
|
|
3162
|
+
}
|
|
3163
|
+
await ensureCreditsForRegistration(client, payload, autoTopUp);
|
|
3164
|
+
let retried = false;
|
|
3165
|
+
while (true) {
|
|
3166
|
+
try {
|
|
3167
|
+
return await performRegisterAgent(client, payload);
|
|
3168
|
+
} catch (error) {
|
|
3169
|
+
const shortfall = client.extractInsufficientCreditsDetails(error);
|
|
3170
|
+
if (shortfall && !retried) {
|
|
3171
|
+
await ensureCreditsForRegistration(client, payload, autoTopUp);
|
|
3172
|
+
retried = true;
|
|
3173
|
+
continue;
|
|
3216
3174
|
}
|
|
3217
|
-
|
|
3175
|
+
throw error;
|
|
3218
3176
|
}
|
|
3219
3177
|
}
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3178
|
+
}
|
|
3179
|
+
async function getRegistrationQuote(client, payload) {
|
|
3180
|
+
const raw = await client.requestJson("/register/quote", {
|
|
3181
|
+
method: "POST",
|
|
3182
|
+
body: serialiseAgentRegistrationRequest(payload),
|
|
3183
|
+
headers: { "content-type": "application/json" }
|
|
3184
|
+
});
|
|
3185
|
+
return client.parseWithSchema(
|
|
3186
|
+
raw,
|
|
3187
|
+
registrationQuoteResponseSchema,
|
|
3188
|
+
"registration quote response"
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
async function updateAgent(client, uaid, payload) {
|
|
3192
|
+
const raw = await client.requestJson(
|
|
3193
|
+
`/register/${encodeURIComponent(uaid)}`,
|
|
3194
|
+
{
|
|
3195
|
+
method: "PUT",
|
|
3196
|
+
body: serialiseAgentRegistrationRequest(payload),
|
|
3197
|
+
headers: { "content-type": "application/json" }
|
|
3227
3198
|
}
|
|
3228
|
-
|
|
3199
|
+
);
|
|
3200
|
+
return client.parseWithSchema(
|
|
3201
|
+
raw,
|
|
3202
|
+
registerAgentResponseSchema,
|
|
3203
|
+
"update agent response"
|
|
3204
|
+
);
|
|
3205
|
+
}
|
|
3206
|
+
async function getRegistrationProgress(client, attemptId) {
|
|
3207
|
+
const normalisedAttemptId = attemptId.trim();
|
|
3208
|
+
if (!normalisedAttemptId) {
|
|
3209
|
+
throw new Error("attemptId is required");
|
|
3229
3210
|
}
|
|
3230
|
-
|
|
3231
|
-
const
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
return null;
|
|
3235
|
-
}
|
|
3236
|
-
const recipient = {};
|
|
3237
|
-
if (candidate.uaid) {
|
|
3238
|
-
recipient.uaid = candidate.uaid;
|
|
3239
|
-
}
|
|
3240
|
-
if (candidate.ledgerAccountId) {
|
|
3241
|
-
recipient.ledgerAccountId = candidate.ledgerAccountId;
|
|
3242
|
-
}
|
|
3243
|
-
if (candidate.userId) {
|
|
3244
|
-
recipient.userId = candidate.userId;
|
|
3245
|
-
}
|
|
3246
|
-
if (candidate.email) {
|
|
3247
|
-
recipient.email = candidate.email;
|
|
3248
|
-
}
|
|
3249
|
-
return recipient;
|
|
3250
|
-
}).filter(
|
|
3251
|
-
(entry) => Boolean(
|
|
3252
|
-
entry?.uaid || entry?.ledgerAccountId || entry?.userId || entry?.email
|
|
3253
|
-
)
|
|
3211
|
+
try {
|
|
3212
|
+
const raw = await client.requestJson(
|
|
3213
|
+
`/register/progress/${encodeURIComponent(normalisedAttemptId)}`,
|
|
3214
|
+
{ method: "GET" }
|
|
3254
3215
|
);
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3216
|
+
const parsed = client.parseWithSchema(
|
|
3217
|
+
raw,
|
|
3218
|
+
registrationProgressResponseSchema,
|
|
3219
|
+
"registration progress response"
|
|
3220
|
+
);
|
|
3221
|
+
return parsed.progress;
|
|
3222
|
+
} catch (error) {
|
|
3223
|
+
if (error instanceof RegistryBrokerError && error.status === 404) {
|
|
3224
|
+
return null;
|
|
3260
3225
|
}
|
|
3261
|
-
|
|
3226
|
+
throw error;
|
|
3262
3227
|
}
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
const snapshot = await this.client.fetchHistorySnapshot(
|
|
3269
|
-
context.sessionId,
|
|
3270
|
-
options
|
|
3271
|
-
);
|
|
3272
|
-
if (snapshot.decryptedHistory) {
|
|
3273
|
-
return snapshot.decryptedHistory;
|
|
3274
|
-
}
|
|
3275
|
-
return snapshot.history.map((entry) => ({
|
|
3276
|
-
entry,
|
|
3277
|
-
plaintext: decryptHistoryEntry(entry)
|
|
3278
|
-
}));
|
|
3279
|
-
};
|
|
3280
|
-
const handle = {
|
|
3281
|
-
sessionId: context.sessionId,
|
|
3282
|
-
mode: "encrypted",
|
|
3283
|
-
summary: context.summary,
|
|
3284
|
-
send: async (options) => {
|
|
3285
|
-
const recipients = options.recipients ?? context.recipients;
|
|
3286
|
-
return this.client.chat.sendMessage({
|
|
3287
|
-
sessionId: context.sessionId,
|
|
3288
|
-
message: options.message ?? "[ciphertext omitted]",
|
|
3289
|
-
streaming: options.streaming,
|
|
3290
|
-
auth: options.auth,
|
|
3291
|
-
uaid,
|
|
3292
|
-
encryption: {
|
|
3293
|
-
plaintext: options.plaintext,
|
|
3294
|
-
sharedSecret: Buffer.from(sharedSecret),
|
|
3295
|
-
recipients
|
|
3296
|
-
}
|
|
3297
|
-
});
|
|
3298
|
-
},
|
|
3299
|
-
decryptHistoryEntry,
|
|
3300
|
-
fetchHistory
|
|
3301
|
-
};
|
|
3302
|
-
this.registerConversationContext({
|
|
3303
|
-
sessionId: context.sessionId,
|
|
3304
|
-
sharedSecret,
|
|
3305
|
-
identity: context.identity
|
|
3306
|
-
});
|
|
3307
|
-
return handle;
|
|
3228
|
+
}
|
|
3229
|
+
async function waitForRegistrationCompletion(client, attemptId, options = {}) {
|
|
3230
|
+
const normalisedAttemptId = attemptId.trim();
|
|
3231
|
+
if (!normalisedAttemptId) {
|
|
3232
|
+
throw new Error("attemptId is required");
|
|
3308
3233
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3234
|
+
const interval = Math.max(
|
|
3235
|
+
250,
|
|
3236
|
+
options.intervalMs ?? DEFAULT_PROGRESS_INTERVAL_MS
|
|
3237
|
+
);
|
|
3238
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_PROGRESS_TIMEOUT_MS;
|
|
3239
|
+
const throwOnFailure = options.throwOnFailure ?? true;
|
|
3240
|
+
const signal = options.signal;
|
|
3241
|
+
const startedAt = Date.now();
|
|
3242
|
+
while (true) {
|
|
3243
|
+
if (signal?.aborted) {
|
|
3244
|
+
throw createAbortError();
|
|
3313
3245
|
}
|
|
3314
|
-
const
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
}
|
|
3320
|
-
|
|
3321
|
-
|
|
3246
|
+
const progress = await client.getRegistrationProgress(normalisedAttemptId);
|
|
3247
|
+
if (progress) {
|
|
3248
|
+
options.onProgress?.(progress);
|
|
3249
|
+
if (progress.status === "completed") {
|
|
3250
|
+
return progress;
|
|
3251
|
+
}
|
|
3252
|
+
if (progress.status === "partial" || progress.status === "failed") {
|
|
3253
|
+
if (throwOnFailure) {
|
|
3254
|
+
throw new RegistryBrokerError(
|
|
3255
|
+
"Registration did not complete successfully",
|
|
3256
|
+
{
|
|
3257
|
+
status: 409,
|
|
3258
|
+
statusText: progress.status,
|
|
3259
|
+
body: progress
|
|
3260
|
+
}
|
|
3261
|
+
);
|
|
3262
|
+
}
|
|
3263
|
+
return progress;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
3267
|
+
throw new Error(
|
|
3268
|
+
`Registration progress polling timed out after ${timeoutMs}ms`
|
|
3269
|
+
);
|
|
3270
|
+
}
|
|
3271
|
+
await client.delay(interval, signal);
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
async function validateUaid(client, uaid) {
|
|
3275
|
+
const raw = await client.requestJson(
|
|
3276
|
+
`/uaids/validate/${encodeURIComponent(uaid)}`,
|
|
3277
|
+
{
|
|
3278
|
+
method: "GET"
|
|
3322
3279
|
}
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3280
|
+
);
|
|
3281
|
+
return client.parseWithSchema(
|
|
3282
|
+
raw,
|
|
3283
|
+
uaidValidationResponseSchema,
|
|
3284
|
+
"UAID validation response"
|
|
3285
|
+
);
|
|
3286
|
+
}
|
|
3287
|
+
async function getUaidConnectionStatus(client, uaid) {
|
|
3288
|
+
const raw = await client.requestJson(
|
|
3289
|
+
`/uaids/connections/${encodeURIComponent(uaid)}/status`,
|
|
3290
|
+
{
|
|
3291
|
+
method: "GET"
|
|
3327
3292
|
}
|
|
3328
|
-
|
|
3329
|
-
|
|
3293
|
+
);
|
|
3294
|
+
return client.parseWithSchema(
|
|
3295
|
+
raw,
|
|
3296
|
+
uaidConnectionStatusSchema,
|
|
3297
|
+
"UAID connection status"
|
|
3298
|
+
);
|
|
3299
|
+
}
|
|
3300
|
+
async function closeUaidConnection(client, uaid) {
|
|
3301
|
+
await client.request(`/uaids/connections/${encodeURIComponent(uaid)}`, {
|
|
3302
|
+
method: "DELETE"
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
3305
|
+
async function dashboardStats(client) {
|
|
3306
|
+
const raw = await client.requestJson("/dashboard/stats", {
|
|
3307
|
+
method: "GET"
|
|
3308
|
+
});
|
|
3309
|
+
return client.parseWithSchema(
|
|
3310
|
+
raw,
|
|
3311
|
+
dashboardStatsResponseSchema,
|
|
3312
|
+
"dashboard stats response"
|
|
3313
|
+
);
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
// ../../src/services/registry-broker/client/verification.ts
|
|
3317
|
+
async function getVerificationStatus(client, uaid) {
|
|
3318
|
+
const raw = await client.requestJson(
|
|
3319
|
+
`/verification/status/${encodeURIComponent(uaid)}`,
|
|
3320
|
+
{ method: "GET" }
|
|
3321
|
+
);
|
|
3322
|
+
return client.parseWithSchema(
|
|
3323
|
+
raw,
|
|
3324
|
+
verificationStatusResponseSchema,
|
|
3325
|
+
"verification status response"
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
async function createVerificationChallenge(client, uaid) {
|
|
3329
|
+
const raw = await client.requestJson("/verification/challenge", {
|
|
3330
|
+
method: "POST",
|
|
3331
|
+
headers: { "content-type": "application/json" },
|
|
3332
|
+
body: { uaid }
|
|
3333
|
+
});
|
|
3334
|
+
return client.parseWithSchema(
|
|
3335
|
+
raw,
|
|
3336
|
+
verificationChallengeResponseSchema,
|
|
3337
|
+
"verification challenge response"
|
|
3338
|
+
);
|
|
3339
|
+
}
|
|
3340
|
+
async function getVerificationChallenge(client, challengeId) {
|
|
3341
|
+
const raw = await client.requestJson(
|
|
3342
|
+
`/verification/challenge/${encodeURIComponent(challengeId)}`,
|
|
3343
|
+
{ method: "GET" }
|
|
3344
|
+
);
|
|
3345
|
+
return client.parseWithSchema(
|
|
3346
|
+
raw,
|
|
3347
|
+
verificationChallengeDetailsResponseSchema,
|
|
3348
|
+
"verification challenge details response"
|
|
3349
|
+
);
|
|
3350
|
+
}
|
|
3351
|
+
async function verifyVerificationChallenge(client, params) {
|
|
3352
|
+
const raw = await client.requestJson("/verification/verify", {
|
|
3353
|
+
method: "POST",
|
|
3354
|
+
headers: { "content-type": "application/json" },
|
|
3355
|
+
body: {
|
|
3356
|
+
challengeId: params.challengeId,
|
|
3357
|
+
method: params.method ?? "moltbook-post"
|
|
3330
3358
|
}
|
|
3331
|
-
|
|
3332
|
-
|
|
3359
|
+
});
|
|
3360
|
+
return client.parseWithSchema(
|
|
3361
|
+
raw,
|
|
3362
|
+
verificationVerifyResponseSchema,
|
|
3363
|
+
"verification verify response"
|
|
3364
|
+
);
|
|
3365
|
+
}
|
|
3366
|
+
async function getVerificationOwnership(client, uaid) {
|
|
3367
|
+
const raw = await client.requestJson(
|
|
3368
|
+
`/verification/ownership/${encodeURIComponent(uaid)}`,
|
|
3369
|
+
{ method: "GET" }
|
|
3370
|
+
);
|
|
3371
|
+
return client.parseWithSchema(
|
|
3372
|
+
raw,
|
|
3373
|
+
verificationOwnershipResponseSchema,
|
|
3374
|
+
"verification ownership response"
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3377
|
+
async function verifySenderOwnership(client, uaid) {
|
|
3378
|
+
const raw = await client.requestJson(
|
|
3379
|
+
"/verification/verify-sender",
|
|
3380
|
+
{
|
|
3381
|
+
method: "POST",
|
|
3382
|
+
headers: { "content-type": "application/json" },
|
|
3383
|
+
body: { uaid }
|
|
3333
3384
|
}
|
|
3334
|
-
|
|
3335
|
-
|
|
3385
|
+
);
|
|
3386
|
+
return client.parseWithSchema(
|
|
3387
|
+
raw,
|
|
3388
|
+
verificationVerifySenderResponseSchema,
|
|
3389
|
+
"verification sender response"
|
|
3390
|
+
);
|
|
3391
|
+
}
|
|
3392
|
+
async function verifyUaidDnsTxt(client, payload) {
|
|
3393
|
+
const raw = await client.requestJson("/verification/dns/verify", {
|
|
3394
|
+
method: "POST",
|
|
3395
|
+
headers: { "content-type": "application/json" },
|
|
3396
|
+
body: {
|
|
3397
|
+
uaid: payload.uaid,
|
|
3398
|
+
...payload.persist !== void 0 ? { persist: payload.persist } : {}
|
|
3336
3399
|
}
|
|
3337
|
-
|
|
3400
|
+
});
|
|
3401
|
+
return client.parseWithSchema(
|
|
3402
|
+
raw,
|
|
3403
|
+
verificationDnsStatusResponseSchema,
|
|
3404
|
+
"verification dns verify response"
|
|
3405
|
+
);
|
|
3406
|
+
}
|
|
3407
|
+
async function getVerificationDnsStatus(client, uaid, query) {
|
|
3408
|
+
const params = new URLSearchParams();
|
|
3409
|
+
if (query?.refresh !== void 0) {
|
|
3410
|
+
params.set("refresh", String(query.refresh));
|
|
3338
3411
|
}
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
return;
|
|
3342
|
-
}
|
|
3343
|
-
await new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3412
|
+
if (query?.persist !== void 0) {
|
|
3413
|
+
params.set("persist", String(query.persist));
|
|
3344
3414
|
}
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
compactHistory: (payload) => client.compactHistory(payload),
|
|
3356
|
-
getEncryptionStatus: (sessionId) => client.fetchEncryptionStatus(sessionId),
|
|
3357
|
-
submitEncryptionHandshake: (sessionId, payload) => client.postEncryptionHandshake(sessionId, payload),
|
|
3358
|
-
startConversation: (options) => client.startConversation(options),
|
|
3359
|
-
acceptConversation: (options) => client.acceptConversation(options),
|
|
3360
|
-
createEncryptedSession: (options) => encryptedManager.startSession(options),
|
|
3361
|
-
acceptEncryptedSession: (options) => encryptedManager.acceptSession(options)
|
|
3362
|
-
};
|
|
3415
|
+
const queryString = params.toString();
|
|
3416
|
+
const path = `/verification/dns/status/${encodeURIComponent(uaid)}${queryString ? `?${queryString}` : ""}`;
|
|
3417
|
+
const raw = await client.requestJson(path, {
|
|
3418
|
+
method: "GET"
|
|
3419
|
+
});
|
|
3420
|
+
return client.parseWithSchema(
|
|
3421
|
+
raw,
|
|
3422
|
+
verificationDnsStatusResponseSchema,
|
|
3423
|
+
"verification dns status response"
|
|
3424
|
+
);
|
|
3363
3425
|
}
|
|
3364
|
-
async function
|
|
3365
|
-
const
|
|
3366
|
-
|
|
3367
|
-
|
|
3426
|
+
async function getRegisterStatus(client, uaid) {
|
|
3427
|
+
const raw = await client.requestJson(
|
|
3428
|
+
`/register/status/${encodeURIComponent(uaid)}`,
|
|
3429
|
+
{ method: "GET" }
|
|
3430
|
+
);
|
|
3431
|
+
return client.parseWithSchema(
|
|
3432
|
+
raw,
|
|
3433
|
+
registerStatusResponseSchema,
|
|
3434
|
+
"register status response"
|
|
3435
|
+
);
|
|
3436
|
+
}
|
|
3437
|
+
async function registerOwnedMoltbookAgent(client, uaid, request) {
|
|
3438
|
+
const raw = await client.requestJson(
|
|
3439
|
+
`/register/${encodeURIComponent(uaid)}`,
|
|
3440
|
+
{
|
|
3441
|
+
method: "PUT",
|
|
3442
|
+
headers: { "content-type": "application/json" },
|
|
3443
|
+
body: {
|
|
3444
|
+
registered: request.registered ?? true,
|
|
3445
|
+
...request.name ? { name: request.name } : {},
|
|
3446
|
+
...request.description ? { description: request.description } : {},
|
|
3447
|
+
...request.endpoint ? { endpoint: request.endpoint } : {},
|
|
3448
|
+
...request.metadata ? { metadata: request.metadata } : {}
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3451
|
+
);
|
|
3452
|
+
return client.parseWithSchema(
|
|
3453
|
+
raw,
|
|
3454
|
+
moltbookOwnerRegistrationUpdateResponseSchema,
|
|
3455
|
+
"moltbook owner registration update response"
|
|
3456
|
+
);
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
// ../../src/services/registry-broker/client/ledger-auth.ts
|
|
3460
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
3461
|
+
|
|
3462
|
+
// ../../src/services/registry-broker/ledger-network.ts
|
|
3463
|
+
var normalise = (value) => value.trim().toLowerCase();
|
|
3464
|
+
var HEDERA_NETWORK_ALIASES = /* @__PURE__ */ new Map([
|
|
3465
|
+
["hedera:mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
3466
|
+
["mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
3467
|
+
["hedera-mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
3468
|
+
["hedera_mainnet", { canonical: "hedera:mainnet", hederaNetwork: "mainnet" }],
|
|
3469
|
+
["hedera:testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
|
|
3470
|
+
["testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
|
|
3471
|
+
["hedera-testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }],
|
|
3472
|
+
["hedera_testnet", { canonical: "hedera:testnet", hederaNetwork: "testnet" }]
|
|
3473
|
+
]);
|
|
3474
|
+
var EVM_NETWORK_CHAIN_IDS = {
|
|
3475
|
+
abstract: 2741,
|
|
3476
|
+
"abstract-testnet": 11124,
|
|
3477
|
+
base: 8453,
|
|
3478
|
+
"base-sepolia": 84532,
|
|
3479
|
+
avalanche: 43114,
|
|
3480
|
+
"avalanche-fuji": 43113,
|
|
3481
|
+
iotex: 4689,
|
|
3482
|
+
sei: 1329,
|
|
3483
|
+
"sei-testnet": 1328,
|
|
3484
|
+
polygon: 137,
|
|
3485
|
+
"polygon-amoy": 80002,
|
|
3486
|
+
peaq: 3338
|
|
3487
|
+
};
|
|
3488
|
+
var CHAIN_ID_TO_ALIAS = new Map(
|
|
3489
|
+
Object.entries(EVM_NETWORK_CHAIN_IDS).map(([alias, id]) => [id, alias])
|
|
3490
|
+
);
|
|
3491
|
+
var parseChainId = (value) => {
|
|
3492
|
+
if (/^eip155:\d+$/i.test(value)) {
|
|
3493
|
+
return Number.parseInt(value.split(":")[1], 10);
|
|
3368
3494
|
}
|
|
3369
|
-
if (
|
|
3370
|
-
|
|
3495
|
+
if (/^\d+$/.test(value)) {
|
|
3496
|
+
return Number.parseInt(value, 10);
|
|
3371
3497
|
}
|
|
3372
|
-
|
|
3373
|
-
|
|
3498
|
+
return void 0;
|
|
3499
|
+
};
|
|
3500
|
+
var normaliseEvmNetwork = (value) => {
|
|
3501
|
+
const trimmed = normalise(value);
|
|
3502
|
+
let chainId = parseChainId(trimmed);
|
|
3503
|
+
let alias;
|
|
3504
|
+
if (chainId === void 0) {
|
|
3505
|
+
const mapped = EVM_NETWORK_CHAIN_IDS[trimmed];
|
|
3506
|
+
if (mapped !== void 0) {
|
|
3507
|
+
chainId = mapped;
|
|
3508
|
+
alias = trimmed;
|
|
3509
|
+
}
|
|
3510
|
+
} else if (CHAIN_ID_TO_ALIAS.has(chainId)) {
|
|
3511
|
+
alias = CHAIN_ID_TO_ALIAS.get(chainId);
|
|
3374
3512
|
}
|
|
3375
|
-
if (
|
|
3376
|
-
|
|
3513
|
+
if (chainId === void 0) {
|
|
3514
|
+
throw new Error(
|
|
3515
|
+
'Unsupported EVM ledger network. Provide an alias like "base-sepolia" or a canonical eip155:<chainId> string.'
|
|
3516
|
+
);
|
|
3377
3517
|
}
|
|
3378
|
-
|
|
3379
|
-
|
|
3518
|
+
return {
|
|
3519
|
+
canonical: `eip155:${chainId}`,
|
|
3520
|
+
kind: "evm",
|
|
3521
|
+
chainId,
|
|
3522
|
+
legacyName: alias
|
|
3523
|
+
};
|
|
3524
|
+
};
|
|
3525
|
+
var normaliseHederaNetwork = (value) => {
|
|
3526
|
+
const trimmed = normalise(value);
|
|
3527
|
+
const mapping = HEDERA_NETWORK_ALIASES.get(trimmed);
|
|
3528
|
+
if (!mapping) {
|
|
3529
|
+
throw new Error(
|
|
3530
|
+
'Unsupported Hedera network. Use hedera:mainnet or hedera:testnet (legacy "mainnet"/"testnet" also accepted).'
|
|
3531
|
+
);
|
|
3380
3532
|
}
|
|
3381
|
-
|
|
3382
|
-
|
|
3533
|
+
return {
|
|
3534
|
+
canonical: mapping.canonical,
|
|
3535
|
+
kind: "hedera",
|
|
3536
|
+
hederaNetwork: mapping.hederaNetwork
|
|
3537
|
+
};
|
|
3538
|
+
};
|
|
3539
|
+
var canonicalizeLedgerNetwork = (network) => {
|
|
3540
|
+
if (typeof network !== "string" || network.trim().length === 0) {
|
|
3541
|
+
throw new Error("Ledger network is required.");
|
|
3383
3542
|
}
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
body,
|
|
3388
|
-
headers: { "content-type": "application/json" }
|
|
3389
|
-
});
|
|
3390
|
-
return client.parseWithSchema(
|
|
3391
|
-
raw,
|
|
3392
|
-
createSessionResponseSchema,
|
|
3393
|
-
"chat session response"
|
|
3394
|
-
);
|
|
3395
|
-
} catch (error) {
|
|
3396
|
-
const maybeError = error instanceof Error ? error : null;
|
|
3397
|
-
if (allowHistoryAutoTopUp && client.shouldAutoTopUpHistory(payload, maybeError)) {
|
|
3398
|
-
await client.executeHistoryAutoTopUp("chat.session");
|
|
3399
|
-
return createSession(client, payload, false);
|
|
3400
|
-
}
|
|
3401
|
-
throw error;
|
|
3543
|
+
const trimmed = normalise(network);
|
|
3544
|
+
if (trimmed.startsWith("hedera:") || trimmed.includes("hedera-") || trimmed.includes("hedera_") || trimmed === "mainnet" || trimmed === "testnet") {
|
|
3545
|
+
return normaliseHederaNetwork(trimmed);
|
|
3402
3546
|
}
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
onSessionCreated: options.onSessionCreated
|
|
3413
|
-
});
|
|
3547
|
+
return normaliseEvmNetwork(trimmed);
|
|
3548
|
+
};
|
|
3549
|
+
|
|
3550
|
+
// ../../src/services/registry-broker/private-key-signer.ts
|
|
3551
|
+
var unsupported = (method) => new Error(`${method} is not supported by the in-memory signer`);
|
|
3552
|
+
var cachedSdk = null;
|
|
3553
|
+
var loadHashgraphSdk = () => {
|
|
3554
|
+
if (cachedSdk) {
|
|
3555
|
+
return cachedSdk;
|
|
3414
3556
|
}
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
historyTtlSeconds: options.historyTtlSeconds,
|
|
3420
|
-
senderUaid: options.senderUaid
|
|
3421
|
-
});
|
|
3422
|
-
options.onSessionCreated?.(session.sessionId);
|
|
3423
|
-
return createPlaintextConversationHandle(
|
|
3424
|
-
client,
|
|
3425
|
-
session.sessionId,
|
|
3426
|
-
session.encryption ?? null,
|
|
3427
|
-
options.auth,
|
|
3428
|
-
{ agentUrl: options.agentUrl, uaid: options.uaid }
|
|
3429
|
-
);
|
|
3557
|
+
const resolved = optionalImportSync("@hashgraph/sdk");
|
|
3558
|
+
if (resolved) {
|
|
3559
|
+
cachedSdk = resolved;
|
|
3560
|
+
return resolved;
|
|
3430
3561
|
}
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
const session = await createSession(client, {
|
|
3438
|
-
uaid: options.uaid,
|
|
3439
|
-
auth: options.auth,
|
|
3440
|
-
historyTtlSeconds: options.historyTtlSeconds,
|
|
3441
|
-
senderUaid: options.senderUaid,
|
|
3442
|
-
encryptionRequested: false
|
|
3443
|
-
});
|
|
3444
|
-
options.onSessionCreated?.(session.sessionId);
|
|
3445
|
-
return createPlaintextConversationHandle(
|
|
3446
|
-
client,
|
|
3447
|
-
session.sessionId,
|
|
3448
|
-
session.encryption ?? null,
|
|
3449
|
-
options.auth,
|
|
3450
|
-
{ uaid: options.uaid }
|
|
3451
|
-
);
|
|
3562
|
+
const message = "@hashgraph/sdk is required for ledger signing. Install it as a dependency to enable createPrivateKeySigner.";
|
|
3563
|
+
throw new Error(message);
|
|
3564
|
+
};
|
|
3565
|
+
var loadHashgraphSdkAsync = async () => {
|
|
3566
|
+
if (cachedSdk) {
|
|
3567
|
+
return cachedSdk;
|
|
3452
3568
|
}
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
historyTtlSeconds: options.historyTtlSeconds,
|
|
3458
|
-
handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
|
|
3459
|
-
pollIntervalMs: options.encryption?.pollIntervalMs,
|
|
3460
|
-
onSessionCreated: (sessionId) => {
|
|
3461
|
-
options.onSessionCreated?.(sessionId);
|
|
3462
|
-
},
|
|
3463
|
-
auth: options.auth
|
|
3464
|
-
});
|
|
3465
|
-
return handle;
|
|
3466
|
-
} catch (error) {
|
|
3467
|
-
if (error instanceof EncryptionUnavailableError) {
|
|
3468
|
-
if (preference === "required") {
|
|
3469
|
-
throw error;
|
|
3470
|
-
}
|
|
3471
|
-
return createPlaintextConversationHandle(
|
|
3472
|
-
client,
|
|
3473
|
-
error.sessionId,
|
|
3474
|
-
error.summary ?? null,
|
|
3475
|
-
options.auth,
|
|
3476
|
-
{ uaid: options.uaid }
|
|
3477
|
-
);
|
|
3478
|
-
}
|
|
3479
|
-
throw error;
|
|
3569
|
+
const resolved = await optionalImport("@hashgraph/sdk");
|
|
3570
|
+
if (resolved) {
|
|
3571
|
+
cachedSdk = resolved;
|
|
3572
|
+
return resolved;
|
|
3480
3573
|
}
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3574
|
+
const message = "@hashgraph/sdk is required for ledger signing. Install it as a dependency to enable createPrivateKeySigner.";
|
|
3575
|
+
throw new Error(message);
|
|
3576
|
+
};
|
|
3577
|
+
var buildSigner = (sdk, options) => {
|
|
3578
|
+
const { AccountId, LedgerId, PrivateKey, SignerSignature } = sdk;
|
|
3579
|
+
if (!options.privateKey) {
|
|
3580
|
+
throw new Error("privateKey is required to create a ledger signer.");
|
|
3486
3581
|
}
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
sessionId: options.sessionId,
|
|
3490
|
-
responderUaid: options.responderUaid,
|
|
3491
|
-
handshakeTimeoutMs: options.encryption?.handshakeTimeoutMs,
|
|
3492
|
-
pollIntervalMs: options.encryption?.pollIntervalMs
|
|
3493
|
-
});
|
|
3494
|
-
return handle;
|
|
3495
|
-
} catch (error) {
|
|
3496
|
-
if (error instanceof EncryptionUnavailableError && preference !== "required") {
|
|
3497
|
-
return createPlaintextConversationHandle(
|
|
3498
|
-
client,
|
|
3499
|
-
options.sessionId,
|
|
3500
|
-
null,
|
|
3501
|
-
void 0,
|
|
3502
|
-
{ uaid: options.responderUaid }
|
|
3503
|
-
);
|
|
3504
|
-
}
|
|
3505
|
-
throw error;
|
|
3582
|
+
if (!options.accountId) {
|
|
3583
|
+
throw new Error("accountId is required to create a ledger signer.");
|
|
3506
3584
|
}
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
const
|
|
3510
|
-
const agentUrl = context?.agentUrl?.trim();
|
|
3511
|
-
const fetchHistory = async (options) => {
|
|
3512
|
-
const snapshot = await client.fetchHistorySnapshot(sessionId, options);
|
|
3513
|
-
if (snapshot.decryptedHistory) {
|
|
3514
|
-
return snapshot.decryptedHistory;
|
|
3515
|
-
}
|
|
3516
|
-
return snapshot.history.map((entry) => ({
|
|
3517
|
-
entry,
|
|
3518
|
-
plaintext: entry.content
|
|
3519
|
-
}));
|
|
3520
|
-
};
|
|
3585
|
+
const accountId = AccountId.fromString(options.accountId);
|
|
3586
|
+
const privateKey = PrivateKey.fromString(options.privateKey);
|
|
3587
|
+
const ledgerId = LedgerId.fromString(options.network);
|
|
3521
3588
|
return {
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3589
|
+
getLedgerId: () => ledgerId,
|
|
3590
|
+
getAccountId: () => accountId,
|
|
3591
|
+
getAccountKey: () => privateKey.publicKey,
|
|
3592
|
+
getNetwork: () => ({}),
|
|
3593
|
+
getMirrorNetwork: () => [],
|
|
3594
|
+
sign: async (messages) => Promise.all(
|
|
3595
|
+
messages.map(async (message) => {
|
|
3596
|
+
const signature = await privateKey.sign(message);
|
|
3597
|
+
return new SignerSignature({
|
|
3598
|
+
publicKey: privateKey.publicKey,
|
|
3599
|
+
signature,
|
|
3600
|
+
accountId
|
|
3601
|
+
});
|
|
3602
|
+
})
|
|
3603
|
+
),
|
|
3604
|
+
getAccountBalance: async () => {
|
|
3605
|
+
throw unsupported("getAccountBalance");
|
|
3606
|
+
},
|
|
3607
|
+
getAccountInfo: async () => {
|
|
3608
|
+
throw unsupported("getAccountInfo");
|
|
3609
|
+
},
|
|
3610
|
+
getAccountRecords: async () => {
|
|
3611
|
+
throw unsupported("getAccountRecords");
|
|
3612
|
+
},
|
|
3613
|
+
signTransaction: async (_) => {
|
|
3614
|
+
throw unsupported("signTransaction");
|
|
3615
|
+
},
|
|
3616
|
+
checkTransaction: async (_) => {
|
|
3617
|
+
throw unsupported("checkTransaction");
|
|
3539
3618
|
},
|
|
3540
|
-
|
|
3541
|
-
|
|
3619
|
+
populateTransaction: async (_) => {
|
|
3620
|
+
throw unsupported("populateTransaction");
|
|
3621
|
+
},
|
|
3622
|
+
call: async (_request) => {
|
|
3623
|
+
throw unsupported("call");
|
|
3624
|
+
}
|
|
3542
3625
|
};
|
|
3626
|
+
};
|
|
3627
|
+
var createPrivateKeySigner = (options) => buildSigner(loadHashgraphSdk(), options);
|
|
3628
|
+
var createPrivateKeySignerAsync = async (options) => buildSigner(await loadHashgraphSdkAsync(), options);
|
|
3629
|
+
|
|
3630
|
+
// ../../src/services/registry-broker/client/ledger-auth.ts
|
|
3631
|
+
async function loadViemAccount(privateKey) {
|
|
3632
|
+
try {
|
|
3633
|
+
const viem = await import("viem/accounts");
|
|
3634
|
+
return viem.privateKeyToAccount(privateKey);
|
|
3635
|
+
} catch (error) {
|
|
3636
|
+
const err = new Error(
|
|
3637
|
+
'EVM ledger authentication requires the optional dependency "viem". Install it to use evmPrivateKey flows.'
|
|
3638
|
+
);
|
|
3639
|
+
err.cause = error;
|
|
3640
|
+
throw err;
|
|
3641
|
+
}
|
|
3543
3642
|
}
|
|
3544
|
-
async function
|
|
3545
|
-
if (
|
|
3546
|
-
|
|
3643
|
+
async function resolveLedgerAuthSignature(message, options) {
|
|
3644
|
+
if (typeof options.sign === "function") {
|
|
3645
|
+
const result = await options.sign(message);
|
|
3646
|
+
if (!result || typeof result.signature !== "string" || result.signature.length === 0) {
|
|
3647
|
+
throw new Error("Custom ledger signer failed to produce a signature.");
|
|
3648
|
+
}
|
|
3649
|
+
return result;
|
|
3547
3650
|
}
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3651
|
+
if (!options.signer || typeof options.signer.sign !== "function") {
|
|
3652
|
+
throw new Error(
|
|
3653
|
+
"Ledger authentication requires a Hedera Signer or custom sign function."
|
|
3654
|
+
);
|
|
3551
3655
|
}
|
|
3552
|
-
const
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3656
|
+
const payload = Buffer4.from(message, "utf8");
|
|
3657
|
+
const signatures = await options.signer.sign([payload]);
|
|
3658
|
+
const signatureEntry = signatures?.[0];
|
|
3659
|
+
if (!signatureEntry) {
|
|
3660
|
+
throw new Error("Signer did not return any signatures.");
|
|
3661
|
+
}
|
|
3662
|
+
let derivedPublicKey;
|
|
3663
|
+
if (signatureEntry.publicKey) {
|
|
3664
|
+
derivedPublicKey = signatureEntry.publicKey.toString();
|
|
3665
|
+
} else if (typeof options.signer.getAccountKey === "function") {
|
|
3666
|
+
const accountKey = await options.signer.getAccountKey();
|
|
3667
|
+
if (accountKey && typeof accountKey.toString === "function") {
|
|
3668
|
+
derivedPublicKey = accountKey.toString();
|
|
3558
3669
|
}
|
|
3559
|
-
|
|
3670
|
+
}
|
|
3671
|
+
return {
|
|
3672
|
+
signature: Buffer4.from(signatureEntry.signature).toString("base64"),
|
|
3673
|
+
signatureKind: "raw",
|
|
3674
|
+
publicKey: derivedPublicKey
|
|
3675
|
+
};
|
|
3676
|
+
}
|
|
3677
|
+
async function createLedgerChallenge(client, payload) {
|
|
3678
|
+
const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
|
|
3679
|
+
const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
|
|
3680
|
+
const raw = await client.requestJson("/auth/ledger/challenge", {
|
|
3681
|
+
method: "POST",
|
|
3682
|
+
headers: { "content-type": "application/json" },
|
|
3683
|
+
body: {
|
|
3684
|
+
accountId: payload.accountId,
|
|
3685
|
+
network
|
|
3686
|
+
}
|
|
3687
|
+
});
|
|
3560
3688
|
return client.parseWithSchema(
|
|
3561
3689
|
raw,
|
|
3562
|
-
|
|
3563
|
-
"
|
|
3690
|
+
ledgerChallengeResponseSchema,
|
|
3691
|
+
"ledger challenge response"
|
|
3564
3692
|
);
|
|
3565
3693
|
}
|
|
3566
|
-
async function
|
|
3567
|
-
|
|
3568
|
-
|
|
3694
|
+
async function verifyLedgerChallenge(client, payload) {
|
|
3695
|
+
const resolvedNetwork = canonicalizeLedgerNetwork(payload.network);
|
|
3696
|
+
const network = resolvedNetwork.kind === "hedera" ? resolvedNetwork.hederaNetwork ?? resolvedNetwork.canonical : resolvedNetwork.canonical;
|
|
3697
|
+
const body = {
|
|
3698
|
+
challengeId: payload.challengeId,
|
|
3699
|
+
accountId: payload.accountId,
|
|
3700
|
+
network,
|
|
3701
|
+
signature: payload.signature
|
|
3702
|
+
};
|
|
3703
|
+
if (payload.signatureKind) {
|
|
3704
|
+
body.signatureKind = payload.signatureKind;
|
|
3569
3705
|
}
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3706
|
+
if (payload.publicKey) {
|
|
3707
|
+
body.publicKey = payload.publicKey;
|
|
3708
|
+
}
|
|
3709
|
+
if (typeof payload.expiresInMinutes === "number") {
|
|
3710
|
+
body.expiresInMinutes = payload.expiresInMinutes;
|
|
3711
|
+
}
|
|
3712
|
+
const raw = await client.requestJson("/auth/ledger/verify", {
|
|
3713
|
+
method: "POST",
|
|
3714
|
+
headers: { "content-type": "application/json" },
|
|
3715
|
+
body
|
|
3716
|
+
});
|
|
3717
|
+
const result = client.parseWithSchema(
|
|
3577
3718
|
raw,
|
|
3578
|
-
|
|
3579
|
-
"
|
|
3719
|
+
ledgerVerifyResponseSchema,
|
|
3720
|
+
"ledger verification response"
|
|
3580
3721
|
);
|
|
3722
|
+
client.setLedgerApiKey(result.key);
|
|
3723
|
+
return result;
|
|
3581
3724
|
}
|
|
3582
|
-
async function
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3725
|
+
async function authenticateWithLedger(client, options) {
|
|
3726
|
+
const challenge = await client.createLedgerChallenge({
|
|
3727
|
+
accountId: options.accountId,
|
|
3728
|
+
network: options.network
|
|
3729
|
+
});
|
|
3730
|
+
const signed = await resolveLedgerAuthSignature(challenge.message, options);
|
|
3731
|
+
const verification = await client.verifyLedgerChallenge({
|
|
3732
|
+
challengeId: challenge.challengeId,
|
|
3733
|
+
accountId: options.accountId,
|
|
3734
|
+
network: options.network,
|
|
3735
|
+
signature: signed.signature,
|
|
3736
|
+
signatureKind: signed.signatureKind,
|
|
3737
|
+
publicKey: signed.publicKey,
|
|
3738
|
+
expiresInMinutes: options.expiresInMinutes
|
|
3739
|
+
});
|
|
3740
|
+
return verification;
|
|
3741
|
+
}
|
|
3742
|
+
async function authenticateWithLedgerCredentials(client, options) {
|
|
3743
|
+
const {
|
|
3744
|
+
accountId,
|
|
3745
|
+
network,
|
|
3746
|
+
signer,
|
|
3747
|
+
sign,
|
|
3748
|
+
hederaPrivateKey,
|
|
3749
|
+
evmPrivateKey,
|
|
3750
|
+
expiresInMinutes,
|
|
3751
|
+
setAccountHeader = true,
|
|
3752
|
+
label,
|
|
3753
|
+
logger
|
|
3754
|
+
} = options;
|
|
3755
|
+
const resolvedNetwork = canonicalizeLedgerNetwork(network);
|
|
3756
|
+
const labelSuffix = label ? ` for ${label}` : "";
|
|
3757
|
+
const networkPayload = resolvedNetwork.canonical;
|
|
3758
|
+
const authOptions = {
|
|
3759
|
+
accountId,
|
|
3760
|
+
network: networkPayload,
|
|
3761
|
+
expiresInMinutes
|
|
3762
|
+
};
|
|
3763
|
+
if (sign) {
|
|
3764
|
+
authOptions.sign = sign;
|
|
3765
|
+
} else if (signer) {
|
|
3766
|
+
authOptions.signer = signer;
|
|
3767
|
+
} else if (hederaPrivateKey) {
|
|
3768
|
+
if (resolvedNetwork.kind !== "hedera" || !resolvedNetwork.hederaNetwork) {
|
|
3769
|
+
throw new Error(
|
|
3770
|
+
"hederaPrivateKey can only be used with hedera:mainnet or hedera:testnet networks."
|
|
3771
|
+
);
|
|
3772
|
+
}
|
|
3773
|
+
authOptions.signer = await createPrivateKeySignerAsync({
|
|
3774
|
+
accountId,
|
|
3775
|
+
privateKey: hederaPrivateKey,
|
|
3776
|
+
network: resolvedNetwork.hederaNetwork
|
|
3777
|
+
});
|
|
3778
|
+
} else if (evmPrivateKey) {
|
|
3779
|
+
if (resolvedNetwork.kind !== "evm") {
|
|
3780
|
+
throw new Error(
|
|
3781
|
+
"evmPrivateKey can only be used with CAIP-2 EVM networks (eip155:<chainId>)."
|
|
3782
|
+
);
|
|
3602
3783
|
}
|
|
3784
|
+
const formattedKey = evmPrivateKey.startsWith("0x") ? evmPrivateKey : `0x${evmPrivateKey}`;
|
|
3785
|
+
const account = await loadViemAccount(formattedKey);
|
|
3786
|
+
authOptions.sign = async (message) => ({
|
|
3787
|
+
signature: await account.signMessage({ message }),
|
|
3788
|
+
signatureKind: "evm",
|
|
3789
|
+
publicKey: account.publicKey
|
|
3790
|
+
});
|
|
3791
|
+
} else {
|
|
3792
|
+
throw new Error(
|
|
3793
|
+
"Provide a signer, sign function, hederaPrivateKey, or evmPrivateKey to authenticate with the ledger."
|
|
3794
|
+
);
|
|
3795
|
+
}
|
|
3796
|
+
logger?.info?.(
|
|
3797
|
+
`Authenticating ledger account ${accountId} (${resolvedNetwork.canonical})${labelSuffix}...`
|
|
3603
3798
|
);
|
|
3604
|
-
const
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3799
|
+
const verification = await client.authenticateWithLedger(authOptions);
|
|
3800
|
+
if (setAccountHeader) {
|
|
3801
|
+
client.setDefaultHeader("x-account-id", verification.accountId);
|
|
3802
|
+
}
|
|
3803
|
+
logger?.info?.(
|
|
3804
|
+
`Ledger authentication complete${labelSuffix}. Issued key prefix: ${verification.apiKey.prefix}\u2026${verification.apiKey.lastFour}`
|
|
3608
3805
|
);
|
|
3609
|
-
return
|
|
3806
|
+
return verification;
|
|
3610
3807
|
}
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3808
|
+
|
|
3809
|
+
// ../../src/services/registry-broker/client/search.ts
|
|
3810
|
+
function buildVectorFallbackSearchParams(request) {
|
|
3811
|
+
const params = {
|
|
3812
|
+
q: request.query
|
|
3614
3813
|
};
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
body.auth = serialiseAuthConfig(payload.auth);
|
|
3814
|
+
let effectiveLimit;
|
|
3815
|
+
if (typeof request.limit === "number" && Number.isFinite(request.limit)) {
|
|
3816
|
+
effectiveLimit = request.limit;
|
|
3817
|
+
params.limit = request.limit;
|
|
3620
3818
|
}
|
|
3621
|
-
if ("
|
|
3622
|
-
|
|
3819
|
+
if (typeof request.offset === "number" && Number.isFinite(request.offset) && request.offset > 0) {
|
|
3820
|
+
const limit = effectiveLimit && effectiveLimit > 0 ? effectiveLimit : 20;
|
|
3821
|
+
params.limit = limit;
|
|
3822
|
+
params.page = Math.floor(request.offset / limit) + 1;
|
|
3623
3823
|
}
|
|
3624
|
-
if (
|
|
3625
|
-
|
|
3824
|
+
if (request.filter?.registry) {
|
|
3825
|
+
params.registry = request.filter.registry;
|
|
3626
3826
|
}
|
|
3627
|
-
if (
|
|
3628
|
-
|
|
3827
|
+
if (request.filter?.protocols?.length) {
|
|
3828
|
+
params.protocols = [...request.filter.protocols];
|
|
3629
3829
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
const sessionIdForEncryption = payload.encryption.sessionId ?? (typeof body.sessionId === "string" ? body.sessionId : void 0);
|
|
3633
|
-
if (!sessionIdForEncryption) {
|
|
3634
|
-
throw new Error(
|
|
3635
|
-
"sessionId is required when using encrypted chat payloads"
|
|
3636
|
-
);
|
|
3637
|
-
}
|
|
3638
|
-
if (!payload.encryption.recipients?.length) {
|
|
3639
|
-
throw new Error("recipients are required for encrypted chat payloads");
|
|
3640
|
-
}
|
|
3641
|
-
cipherEnvelope = client.encryption.encryptCipherEnvelope({
|
|
3642
|
-
...payload.encryption,
|
|
3643
|
-
sessionId: sessionIdForEncryption
|
|
3644
|
-
});
|
|
3830
|
+
if (request.filter?.adapter?.length) {
|
|
3831
|
+
params.adapters = [...request.filter.adapter];
|
|
3645
3832
|
}
|
|
3646
|
-
if (
|
|
3647
|
-
|
|
3833
|
+
if (request.filter?.capabilities?.length) {
|
|
3834
|
+
params.capabilities = request.filter.capabilities.map(
|
|
3835
|
+
(value) => typeof value === "number" ? value.toString(10) : value
|
|
3836
|
+
);
|
|
3648
3837
|
}
|
|
3649
|
-
|
|
3838
|
+
if (request.filter?.type) {
|
|
3839
|
+
params.type = request.filter.type;
|
|
3840
|
+
}
|
|
3841
|
+
return params;
|
|
3842
|
+
}
|
|
3843
|
+
function convertSearchResultToVectorResponse(result) {
|
|
3844
|
+
const hits = result.hits.map((agent) => ({
|
|
3845
|
+
agent,
|
|
3846
|
+
score: 0,
|
|
3847
|
+
highlights: {}
|
|
3848
|
+
}));
|
|
3849
|
+
const total = result.total;
|
|
3850
|
+
const limit = result.limit;
|
|
3851
|
+
const page = result.page;
|
|
3852
|
+
const totalVisible = page * limit;
|
|
3853
|
+
const limited = total > totalVisible || page > 1;
|
|
3854
|
+
return {
|
|
3855
|
+
hits,
|
|
3856
|
+
total,
|
|
3857
|
+
took: 0,
|
|
3858
|
+
totalAvailable: total,
|
|
3859
|
+
visible: hits.length,
|
|
3860
|
+
limited,
|
|
3861
|
+
credits_used: 0
|
|
3862
|
+
};
|
|
3863
|
+
}
|
|
3864
|
+
async function search(client, params = {}) {
|
|
3865
|
+
const query = buildSearchQuery(params);
|
|
3866
|
+
const raw = await client.requestJson(`/search${query}`, {
|
|
3867
|
+
method: "GET"
|
|
3868
|
+
});
|
|
3869
|
+
return client.parseWithSchema(raw, searchResponseSchema, "search response");
|
|
3870
|
+
}
|
|
3871
|
+
async function delegate(client, request) {
|
|
3872
|
+
const raw = await client.requestJson("/delegate", {
|
|
3650
3873
|
method: "POST",
|
|
3651
|
-
body,
|
|
3874
|
+
body: request,
|
|
3652
3875
|
headers: { "content-type": "application/json" }
|
|
3653
3876
|
});
|
|
3654
3877
|
return client.parseWithSchema(
|
|
3655
3878
|
raw,
|
|
3656
|
-
|
|
3657
|
-
"
|
|
3879
|
+
delegationPlanResponseSchema,
|
|
3880
|
+
"delegate response"
|
|
3658
3881
|
);
|
|
3659
3882
|
}
|
|
3660
|
-
async function
|
|
3661
|
-
await client.
|
|
3662
|
-
|
|
3883
|
+
async function stats(client) {
|
|
3884
|
+
const raw = await client.requestJson("/stats", { method: "GET" });
|
|
3885
|
+
return client.parseWithSchema(raw, statsResponseSchema, "stats response");
|
|
3886
|
+
}
|
|
3887
|
+
async function registries(client) {
|
|
3888
|
+
const raw = await client.requestJson("/registries", {
|
|
3889
|
+
method: "GET"
|
|
3663
3890
|
});
|
|
3891
|
+
return client.parseWithSchema(
|
|
3892
|
+
raw,
|
|
3893
|
+
registriesResponseSchema,
|
|
3894
|
+
"registries response"
|
|
3895
|
+
);
|
|
3664
3896
|
}
|
|
3665
|
-
|
|
3666
|
-
// ../../src/services/registry-broker/client/verification.ts
|
|
3667
|
-
async function getVerificationStatus(client, uaid) {
|
|
3897
|
+
async function getAdditionalRegistries(client) {
|
|
3668
3898
|
const raw = await client.requestJson(
|
|
3669
|
-
|
|
3670
|
-
{
|
|
3899
|
+
"/register/additional-registries",
|
|
3900
|
+
{
|
|
3901
|
+
method: "GET"
|
|
3902
|
+
}
|
|
3671
3903
|
);
|
|
3672
3904
|
return client.parseWithSchema(
|
|
3673
3905
|
raw,
|
|
3674
|
-
|
|
3675
|
-
"
|
|
3906
|
+
additionalRegistryCatalogResponseSchema,
|
|
3907
|
+
"additional registry catalog response"
|
|
3676
3908
|
);
|
|
3677
3909
|
}
|
|
3678
|
-
async function
|
|
3679
|
-
const raw = await client.requestJson("/
|
|
3680
|
-
method: "
|
|
3681
|
-
headers: { "content-type": "application/json" },
|
|
3682
|
-
body: { uaid }
|
|
3910
|
+
async function popularSearches(client) {
|
|
3911
|
+
const raw = await client.requestJson("/popular", {
|
|
3912
|
+
method: "GET"
|
|
3683
3913
|
});
|
|
3684
3914
|
return client.parseWithSchema(
|
|
3685
3915
|
raw,
|
|
3686
|
-
|
|
3687
|
-
"
|
|
3916
|
+
popularResponseSchema,
|
|
3917
|
+
"popular searches response"
|
|
3688
3918
|
);
|
|
3689
3919
|
}
|
|
3690
|
-
async function
|
|
3691
|
-
const raw = await client.requestJson(
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
);
|
|
3920
|
+
async function listProtocols(client) {
|
|
3921
|
+
const raw = await client.requestJson("/protocols", {
|
|
3922
|
+
method: "GET"
|
|
3923
|
+
});
|
|
3695
3924
|
return client.parseWithSchema(
|
|
3696
3925
|
raw,
|
|
3697
|
-
|
|
3698
|
-
"
|
|
3926
|
+
protocolsResponseSchema,
|
|
3927
|
+
"protocols response"
|
|
3699
3928
|
);
|
|
3700
3929
|
}
|
|
3701
|
-
async function
|
|
3702
|
-
const raw = await client.requestJson("/
|
|
3930
|
+
async function detectProtocol(client, message) {
|
|
3931
|
+
const raw = await client.requestJson("/detect-protocol", {
|
|
3703
3932
|
method: "POST",
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
challengeId: params.challengeId,
|
|
3707
|
-
method: params.method ?? "moltbook-post"
|
|
3708
|
-
}
|
|
3933
|
+
body: { message },
|
|
3934
|
+
headers: { "content-type": "application/json" }
|
|
3709
3935
|
});
|
|
3710
3936
|
return client.parseWithSchema(
|
|
3711
3937
|
raw,
|
|
3712
|
-
|
|
3713
|
-
"
|
|
3714
|
-
);
|
|
3715
|
-
}
|
|
3716
|
-
async function getVerificationOwnership(client, uaid) {
|
|
3717
|
-
const raw = await client.requestJson(
|
|
3718
|
-
`/verification/ownership/${encodeURIComponent(uaid)}`,
|
|
3719
|
-
{ method: "GET" }
|
|
3720
|
-
);
|
|
3721
|
-
return client.parseWithSchema(
|
|
3722
|
-
raw,
|
|
3723
|
-
verificationOwnershipResponseSchema,
|
|
3724
|
-
"verification ownership response"
|
|
3938
|
+
detectProtocolResponseSchema,
|
|
3939
|
+
"detect protocol response"
|
|
3725
3940
|
);
|
|
3726
3941
|
}
|
|
3727
|
-
async function
|
|
3942
|
+
async function registrySearchByNamespace(client, registry, query) {
|
|
3943
|
+
const params = new URLSearchParams();
|
|
3944
|
+
if (query) {
|
|
3945
|
+
params.set("q", query);
|
|
3946
|
+
}
|
|
3947
|
+
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
3728
3948
|
const raw = await client.requestJson(
|
|
3729
|
-
|
|
3949
|
+
`/registries/${encodeURIComponent(registry)}/search${suffix}`,
|
|
3730
3950
|
{
|
|
3731
|
-
method: "
|
|
3732
|
-
headers: { "content-type": "application/json" },
|
|
3733
|
-
body: { uaid }
|
|
3951
|
+
method: "GET"
|
|
3734
3952
|
}
|
|
3735
3953
|
);
|
|
3736
3954
|
return client.parseWithSchema(
|
|
3737
3955
|
raw,
|
|
3738
|
-
|
|
3739
|
-
"
|
|
3956
|
+
registrySearchByNamespaceSchema,
|
|
3957
|
+
"registry search response"
|
|
3740
3958
|
);
|
|
3741
3959
|
}
|
|
3742
|
-
async function
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3960
|
+
async function vectorSearch(client, request) {
|
|
3961
|
+
try {
|
|
3962
|
+
const raw = await client.requestJson("/search", {
|
|
3963
|
+
method: "POST",
|
|
3964
|
+
body: request,
|
|
3965
|
+
headers: { "content-type": "application/json" }
|
|
3966
|
+
});
|
|
3967
|
+
return client.parseWithSchema(
|
|
3968
|
+
raw,
|
|
3969
|
+
vectorSearchResponseSchema,
|
|
3970
|
+
"vector search response"
|
|
3971
|
+
);
|
|
3972
|
+
} catch (error) {
|
|
3973
|
+
if (error instanceof RegistryBrokerError && error.status === 501) {
|
|
3974
|
+
const fallback = await search(
|
|
3975
|
+
client,
|
|
3976
|
+
buildVectorFallbackSearchParams(request)
|
|
3977
|
+
);
|
|
3978
|
+
return convertSearchResultToVectorResponse(fallback);
|
|
3749
3979
|
}
|
|
3980
|
+
throw error;
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
async function searchStatus(client) {
|
|
3984
|
+
const raw = await client.requestJson("/search/status", {
|
|
3985
|
+
method: "GET"
|
|
3750
3986
|
});
|
|
3751
3987
|
return client.parseWithSchema(
|
|
3752
3988
|
raw,
|
|
3753
|
-
|
|
3754
|
-
"
|
|
3989
|
+
searchStatusResponseSchema,
|
|
3990
|
+
"search status response"
|
|
3755
3991
|
);
|
|
3756
3992
|
}
|
|
3757
|
-
async function
|
|
3758
|
-
const
|
|
3759
|
-
if (query?.refresh !== void 0) {
|
|
3760
|
-
params.set("refresh", String(query.refresh));
|
|
3761
|
-
}
|
|
3762
|
-
if (query?.persist !== void 0) {
|
|
3763
|
-
params.set("persist", String(query.persist));
|
|
3764
|
-
}
|
|
3765
|
-
const queryString = params.toString();
|
|
3766
|
-
const path2 = `/verification/dns/status/${encodeURIComponent(uaid)}${queryString ? `?${queryString}` : ""}`;
|
|
3767
|
-
const raw = await client.requestJson(path2, {
|
|
3993
|
+
async function websocketStats(client) {
|
|
3994
|
+
const raw = await client.requestJson("/websocket/stats", {
|
|
3768
3995
|
method: "GET"
|
|
3769
3996
|
});
|
|
3770
3997
|
return client.parseWithSchema(
|
|
3771
3998
|
raw,
|
|
3772
|
-
|
|
3773
|
-
"
|
|
3999
|
+
websocketStatsResponseSchema,
|
|
4000
|
+
"websocket stats response"
|
|
3774
4001
|
);
|
|
3775
4002
|
}
|
|
3776
|
-
async function
|
|
3777
|
-
const raw = await client.requestJson(
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
);
|
|
4003
|
+
async function metricsSummary(client) {
|
|
4004
|
+
const raw = await client.requestJson("/metrics", {
|
|
4005
|
+
method: "GET"
|
|
4006
|
+
});
|
|
3781
4007
|
return client.parseWithSchema(
|
|
3782
4008
|
raw,
|
|
3783
|
-
|
|
3784
|
-
"
|
|
4009
|
+
metricsSummaryResponseSchema,
|
|
4010
|
+
"metrics summary response"
|
|
3785
4011
|
);
|
|
3786
4012
|
}
|
|
3787
|
-
async function
|
|
3788
|
-
const
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
...request.description ? { description: request.description } : {},
|
|
3797
|
-
...request.endpoint ? { endpoint: request.endpoint } : {},
|
|
3798
|
-
...request.metadata ? { metadata: request.metadata } : {}
|
|
3799
|
-
}
|
|
3800
|
-
}
|
|
3801
|
-
);
|
|
4013
|
+
async function facets(client, adapter) {
|
|
4014
|
+
const params = new URLSearchParams();
|
|
4015
|
+
if (adapter) {
|
|
4016
|
+
params.set("adapter", adapter);
|
|
4017
|
+
}
|
|
4018
|
+
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
4019
|
+
const raw = await client.requestJson(`/search/facets${suffix}`, {
|
|
4020
|
+
method: "GET"
|
|
4021
|
+
});
|
|
3802
4022
|
return client.parseWithSchema(
|
|
3803
4023
|
raw,
|
|
3804
|
-
|
|
3805
|
-
"
|
|
4024
|
+
searchFacetsResponseSchema,
|
|
4025
|
+
"search facets response"
|
|
3806
4026
|
);
|
|
3807
4027
|
}
|
|
3808
4028
|
|
|
@@ -4332,15 +4552,6 @@ async function verifySkillDomainProof(client, payload) {
|
|
|
4332
4552
|
}
|
|
4333
4553
|
|
|
4334
4554
|
// ../../src/services/registry-broker/client/base-client.ts
|
|
4335
|
-
import { Buffer as Buffer5 } from "buffer";
|
|
4336
|
-
import {
|
|
4337
|
-
createCipheriv,
|
|
4338
|
-
createDecipheriv,
|
|
4339
|
-
createHash,
|
|
4340
|
-
randomBytes as randomBytes2
|
|
4341
|
-
} from "crypto";
|
|
4342
|
-
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1.js";
|
|
4343
|
-
import { ZodError } from "zod";
|
|
4344
4555
|
var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
4345
4556
|
constructor(options = {}) {
|
|
4346
4557
|
this.encryptionBootstrapPromise = null;
|
|
@@ -4457,11 +4668,11 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
4457
4668
|
}
|
|
4458
4669
|
await this.encryptionBootstrapPromise;
|
|
4459
4670
|
}
|
|
4460
|
-
buildUrl(
|
|
4461
|
-
const normalisedPath =
|
|
4671
|
+
buildUrl(path) {
|
|
4672
|
+
const normalisedPath = path.startsWith("/") ? path : `/${path}`;
|
|
4462
4673
|
return `${this.baseUrl}${normalisedPath}`;
|
|
4463
4674
|
}
|
|
4464
|
-
async request(
|
|
4675
|
+
async request(path, config) {
|
|
4465
4676
|
const headers = new Headers();
|
|
4466
4677
|
Object.entries(this.defaultHeaders).forEach(([key, value]) => {
|
|
4467
4678
|
headers.set(key, value);
|
|
@@ -4487,7 +4698,7 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
4487
4698
|
headers.set("content-type", "application/json");
|
|
4488
4699
|
}
|
|
4489
4700
|
}
|
|
4490
|
-
const response = await this.fetchImpl(this.buildUrl(
|
|
4701
|
+
const response = await this.fetchImpl(this.buildUrl(path), init);
|
|
4491
4702
|
if (response.ok) {
|
|
4492
4703
|
return response;
|
|
4493
4704
|
}
|
|
@@ -4498,8 +4709,8 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
4498
4709
|
body: errorBody
|
|
4499
4710
|
});
|
|
4500
4711
|
}
|
|
4501
|
-
async requestJson(
|
|
4502
|
-
const response = await this.request(
|
|
4712
|
+
async requestJson(path, config) {
|
|
4713
|
+
const response = await this.request(path, config);
|
|
4503
4714
|
const contentType = response.headers?.get("content-type") ?? "";
|
|
4504
4715
|
if (!JSON_CONTENT_TYPE.test(contentType)) {
|
|
4505
4716
|
const body = await response.text();
|
|
@@ -4610,6 +4821,9 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
4610
4821
|
async search(params = {}) {
|
|
4611
4822
|
return search(this, params);
|
|
4612
4823
|
}
|
|
4824
|
+
async delegate(request) {
|
|
4825
|
+
return delegate(this, request);
|
|
4826
|
+
}
|
|
4613
4827
|
async searchErc8004ByAgentId(params) {
|
|
4614
4828
|
const chainId = Math.floor(params.chainId);
|
|
4615
4829
|
if (!Number.isFinite(chainId) || chainId <= 0) {
|
|
@@ -5066,12 +5280,12 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
5066
5280
|
}
|
|
5067
5281
|
return;
|
|
5068
5282
|
}
|
|
5069
|
-
await new Promise((
|
|
5283
|
+
await new Promise((resolve, reject) => {
|
|
5070
5284
|
const timer = setTimeout(() => {
|
|
5071
5285
|
if (signal) {
|
|
5072
5286
|
signal.removeEventListener("abort", onAbort);
|
|
5073
5287
|
}
|
|
5074
|
-
|
|
5288
|
+
resolve();
|
|
5075
5289
|
}, ms);
|
|
5076
5290
|
const onAbort = () => {
|
|
5077
5291
|
clearTimeout(timer);
|
|
@@ -5093,9 +5307,17 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
5093
5307
|
throw new Error(`${feature} is only available in Node.js environments`);
|
|
5094
5308
|
}
|
|
5095
5309
|
}
|
|
5310
|
+
getNodeCrypto(feature) {
|
|
5311
|
+
this.assertNodeRuntime(feature);
|
|
5312
|
+
const nodeCrypto = optionalImportSync("node:crypto") ?? optionalImportSync("crypto");
|
|
5313
|
+
if (!nodeCrypto) {
|
|
5314
|
+
throw new Error(`${feature} requires the Node.js crypto module`);
|
|
5315
|
+
}
|
|
5316
|
+
return nodeCrypto;
|
|
5317
|
+
}
|
|
5096
5318
|
createEphemeralKeyPair() {
|
|
5097
|
-
this.
|
|
5098
|
-
const privateKeyBytes =
|
|
5319
|
+
const { randomBytes } = this.getNodeCrypto("generateEphemeralKeyPair");
|
|
5320
|
+
const privateKeyBytes = randomBytes(32);
|
|
5099
5321
|
const publicKey = secp256k12.getPublicKey(privateKeyBytes, true);
|
|
5100
5322
|
return {
|
|
5101
5323
|
privateKey: Buffer5.from(privateKeyBytes).toString("hex"),
|
|
@@ -5103,16 +5325,18 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
5103
5325
|
};
|
|
5104
5326
|
}
|
|
5105
5327
|
deriveSharedSecret(options) {
|
|
5106
|
-
this.
|
|
5328
|
+
const { createHash } = this.getNodeCrypto("deriveSharedSecret");
|
|
5107
5329
|
const privateKey = this.hexToBuffer(options.privateKey);
|
|
5108
5330
|
const peerPublicKey = this.hexToBuffer(options.peerPublicKey);
|
|
5109
5331
|
const shared = secp256k12.getSharedSecret(privateKey, peerPublicKey, true);
|
|
5110
5332
|
return createHash("sha256").update(Buffer5.from(shared)).digest();
|
|
5111
5333
|
}
|
|
5112
5334
|
buildCipherEnvelope(options) {
|
|
5113
|
-
this.
|
|
5335
|
+
const { createCipheriv, randomBytes } = this.getNodeCrypto(
|
|
5336
|
+
"encryptCipherEnvelope"
|
|
5337
|
+
);
|
|
5114
5338
|
const sharedSecret = this.normalizeSharedSecret(options.sharedSecret);
|
|
5115
|
-
const iv =
|
|
5339
|
+
const iv = randomBytes(12);
|
|
5116
5340
|
const cipher = createCipheriv("aes-256-gcm", sharedSecret, iv);
|
|
5117
5341
|
const aadSource = options.associatedData ?? options.sessionId;
|
|
5118
5342
|
const associatedDataEncoded = aadSource ? Buffer5.from(aadSource, "utf8").toString("base64") : void 0;
|
|
@@ -5141,7 +5365,7 @@ var RegistryBrokerClient = class _RegistryBrokerClient {
|
|
|
5141
5365
|
};
|
|
5142
5366
|
}
|
|
5143
5367
|
openCipherEnvelope(options) {
|
|
5144
|
-
this.
|
|
5368
|
+
const { createDecipheriv } = this.getNodeCrypto("decryptCipherEnvelope");
|
|
5145
5369
|
const sharedSecret = this.normalizeSharedSecret(options.sharedSecret);
|
|
5146
5370
|
const payload = Buffer5.from(options.envelope.ciphertext, "base64");
|
|
5147
5371
|
const nonce = Buffer5.from(options.envelope.nonce, "base64");
|
|
@@ -5322,11 +5546,21 @@ export {
|
|
|
5322
5546
|
buildPaymentApproveMessage,
|
|
5323
5547
|
buildPaymentDeclineMessage,
|
|
5324
5548
|
canonicalizeLedgerNetwork,
|
|
5549
|
+
closeUaidConnection,
|
|
5325
5550
|
createPrivateKeySigner,
|
|
5326
5551
|
createPrivateKeySignerAsync,
|
|
5552
|
+
dashboardStats,
|
|
5553
|
+
getRegistrationProgress,
|
|
5554
|
+
getRegistrationQuote,
|
|
5555
|
+
getUaidConnectionStatus,
|
|
5327
5556
|
isHolChatOp,
|
|
5328
5557
|
isPartialRegisterAgentResponse,
|
|
5329
5558
|
isPendingRegisterAgentResponse,
|
|
5330
5559
|
isSuccessRegisterAgentResponse,
|
|
5331
|
-
parseHolChatOps
|
|
5560
|
+
parseHolChatOps,
|
|
5561
|
+
registerAgent,
|
|
5562
|
+
resolveUaid,
|
|
5563
|
+
updateAgent,
|
|
5564
|
+
validateUaid,
|
|
5565
|
+
waitForRegistrationCompletion
|
|
5332
5566
|
};
|