@datagrout/conduit 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -2
- package/dist/{chunk-RED5DKGI.mjs → chunk-26DYCD4G.mjs} +4 -30
- package/dist/chunk-CIESM3BP.mjs +33 -0
- package/dist/chunk-SWH5Y2U7.mjs +69 -0
- package/dist/index.d.mts +294 -10
- package/dist/index.d.ts +294 -10
- package/dist/index.js +478 -5
- package/dist/index.mjs +410 -11
- package/dist/{oauth-OMPWCI2X.mjs → oauth-NSDC2G7W.mjs} +2 -1
- package/dist/onramp-743RJTNI.mjs +13 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -343,6 +343,81 @@ var init_identity = __esm({
|
|
|
343
343
|
}
|
|
344
344
|
});
|
|
345
345
|
|
|
346
|
+
// src/onramp.ts
|
|
347
|
+
var onramp_exports = {};
|
|
348
|
+
__export(onramp_exports, {
|
|
349
|
+
_doRegister: () => _doRegister,
|
|
350
|
+
_exchangeToken: () => _exchangeToken,
|
|
351
|
+
registerAndExchange: () => registerAndExchange,
|
|
352
|
+
registerOnly: () => registerOnly
|
|
353
|
+
});
|
|
354
|
+
async function _doRegister(opts) {
|
|
355
|
+
const base = opts.gateway.replace(/\/$/, "");
|
|
356
|
+
const body = { agent_name: opts.agentName };
|
|
357
|
+
if (opts.agentType) body["agent_type"] = opts.agentType;
|
|
358
|
+
if (opts.intendedUse) body["intended_use"] = opts.intendedUse;
|
|
359
|
+
if (opts.accessCode) body["access_code"] = opts.accessCode;
|
|
360
|
+
const initResp = await fetch(`${base}/onramp`, {
|
|
361
|
+
method: "POST",
|
|
362
|
+
headers: { "Content-Type": "application/json" },
|
|
363
|
+
body: JSON.stringify(body)
|
|
364
|
+
});
|
|
365
|
+
if (!initResp.ok) {
|
|
366
|
+
const text = await initResp.text();
|
|
367
|
+
throw new Error(`onramp init rejected (HTTP ${initResp.status}): ${text}`);
|
|
368
|
+
}
|
|
369
|
+
const initData = await initResp.json();
|
|
370
|
+
const sessionToken = initData.session_token;
|
|
371
|
+
const completeResp = await fetch(`${base}/onramp/complete`, {
|
|
372
|
+
method: "POST",
|
|
373
|
+
headers: { Authorization: `Bearer ${sessionToken}` }
|
|
374
|
+
});
|
|
375
|
+
if (!completeResp.ok) {
|
|
376
|
+
const text = await completeResp.text();
|
|
377
|
+
throw new Error(`onramp complete rejected (HTTP ${completeResp.status}): ${text}`);
|
|
378
|
+
}
|
|
379
|
+
const data = await completeResp.json();
|
|
380
|
+
return {
|
|
381
|
+
clientId: data["client_id"],
|
|
382
|
+
clientSecret: data["client_secret"],
|
|
383
|
+
tokenUrl: data["token_url"],
|
|
384
|
+
scopes: data["scopes"] ?? [],
|
|
385
|
+
expiresIn: data["expires_in"] ?? 0,
|
|
386
|
+
rpcUrl: data["rpc_url"],
|
|
387
|
+
mcpUrl: data["mcp_url"]
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
async function _exchangeToken(creds) {
|
|
391
|
+
const body = new URLSearchParams({
|
|
392
|
+
grant_type: "client_credentials",
|
|
393
|
+
client_id: creds.clientId,
|
|
394
|
+
client_secret: creds.clientSecret
|
|
395
|
+
});
|
|
396
|
+
const resp = await fetch(creds.tokenUrl, {
|
|
397
|
+
method: "POST",
|
|
398
|
+
body
|
|
399
|
+
});
|
|
400
|
+
if (!resp.ok) {
|
|
401
|
+
const text = await resp.text();
|
|
402
|
+
throw new Error(`token exchange failed (HTTP ${resp.status}): ${text}`);
|
|
403
|
+
}
|
|
404
|
+
const data = await resp.json();
|
|
405
|
+
return data.access_token;
|
|
406
|
+
}
|
|
407
|
+
async function registerOnly(opts) {
|
|
408
|
+
return _doRegister(opts);
|
|
409
|
+
}
|
|
410
|
+
async function registerAndExchange(opts) {
|
|
411
|
+
const creds = await _doRegister(opts);
|
|
412
|
+
const token = await _exchangeToken(creds);
|
|
413
|
+
return [creds, token];
|
|
414
|
+
}
|
|
415
|
+
var init_onramp = __esm({
|
|
416
|
+
"src/onramp.ts"() {
|
|
417
|
+
"use strict";
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
|
|
346
421
|
// src/index.ts
|
|
347
422
|
var index_exports = {};
|
|
348
423
|
__export(index_exports, {
|
|
@@ -360,6 +435,8 @@ __export(index_exports, {
|
|
|
360
435
|
OAuthTokenProvider: () => OAuthTokenProvider,
|
|
361
436
|
RateLimitError: () => RateLimitError,
|
|
362
437
|
ServerError: () => ServerError,
|
|
438
|
+
WS_SUBPROTOCOL: () => SUBPROTOCOL,
|
|
439
|
+
WsTransport: () => WsTransport,
|
|
363
440
|
deriveTokenEndpoint: () => deriveTokenEndpoint,
|
|
364
441
|
extractMeta: () => extractMeta,
|
|
365
442
|
fetchDgCaCert: () => fetchDgCaCert,
|
|
@@ -367,7 +444,9 @@ __export(index_exports, {
|
|
|
367
444
|
generateKeypair: () => generateKeypair,
|
|
368
445
|
isDgUrl: () => isDgUrl,
|
|
369
446
|
refreshCaCert: () => refreshCaCert,
|
|
447
|
+
registerAndExchange: () => registerAndExchange,
|
|
370
448
|
registerIdentity: () => registerIdentity,
|
|
449
|
+
registerOnly: () => registerOnly,
|
|
371
450
|
rotateIdentity: () => rotateIdentity,
|
|
372
451
|
saveIdentity: () => saveIdentity,
|
|
373
452
|
version: () => version
|
|
@@ -727,6 +806,295 @@ var JSONRPCTransport = class extends Transport {
|
|
|
727
806
|
}
|
|
728
807
|
};
|
|
729
808
|
|
|
809
|
+
// src/transports/ws.ts
|
|
810
|
+
var SUBPROTOCOL = "datagrout-jsonrpc.v1";
|
|
811
|
+
var SUBSCRIPTION_BUFFER = 256;
|
|
812
|
+
var Subscription = class {
|
|
813
|
+
id;
|
|
814
|
+
topic;
|
|
815
|
+
_queue = [];
|
|
816
|
+
_waiters = [];
|
|
817
|
+
_rejecters = [];
|
|
818
|
+
_closed = false;
|
|
819
|
+
constructor(id, topic) {
|
|
820
|
+
this.id = id;
|
|
821
|
+
this.topic = topic;
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Wait for the next event from this subscription.
|
|
825
|
+
*
|
|
826
|
+
* @throws When the subscription has been closed.
|
|
827
|
+
*/
|
|
828
|
+
recv() {
|
|
829
|
+
if (this._queue.length > 0) {
|
|
830
|
+
return Promise.resolve(this._queue.shift());
|
|
831
|
+
}
|
|
832
|
+
if (this._closed) {
|
|
833
|
+
return Promise.reject(new Error("Subscription closed"));
|
|
834
|
+
}
|
|
835
|
+
return new Promise((resolve, reject) => {
|
|
836
|
+
this._waiters.push(resolve);
|
|
837
|
+
this._rejecters.push(reject);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
async *[Symbol.asyncIterator]() {
|
|
841
|
+
while (this._queue.length > 0 || !this._closed) {
|
|
842
|
+
try {
|
|
843
|
+
yield await this.recv();
|
|
844
|
+
} catch {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
// ── Internal ───────────────────────────────────────────────────────────────
|
|
850
|
+
_enqueue(event) {
|
|
851
|
+
if (this._waiters.length > 0) {
|
|
852
|
+
const resolve = this._waiters.shift();
|
|
853
|
+
this._rejecters.shift();
|
|
854
|
+
resolve(event);
|
|
855
|
+
} else if (this._queue.length < SUBSCRIPTION_BUFFER) {
|
|
856
|
+
this._queue.push(event);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
_close() {
|
|
860
|
+
this._closed = true;
|
|
861
|
+
const err = new Error("Subscription closed");
|
|
862
|
+
for (const reject of this._rejecters) {
|
|
863
|
+
reject(err);
|
|
864
|
+
}
|
|
865
|
+
this._waiters.length = 0;
|
|
866
|
+
this._rejecters.length = 0;
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
var WsTransport = class extends Transport {
|
|
870
|
+
_url;
|
|
871
|
+
_auth;
|
|
872
|
+
_ws = null;
|
|
873
|
+
_nextId = 0;
|
|
874
|
+
_pending = /* @__PURE__ */ new Map();
|
|
875
|
+
_pendingSubscribe = /* @__PURE__ */ new Map();
|
|
876
|
+
_subscriptions = /* @__PURE__ */ new Map();
|
|
877
|
+
constructor(url, auth, _timeout, _identity) {
|
|
878
|
+
super();
|
|
879
|
+
const scheme = new URL(url).protocol.replace(":", "");
|
|
880
|
+
if (scheme !== "ws" && scheme !== "wss") {
|
|
881
|
+
throw new Error(`WS transport requires a ws:// or wss:// URL, got ${scheme}://`);
|
|
882
|
+
}
|
|
883
|
+
this._url = url;
|
|
884
|
+
this._auth = auth;
|
|
885
|
+
}
|
|
886
|
+
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
|
887
|
+
async connect() {
|
|
888
|
+
if (this._ws !== null) return;
|
|
889
|
+
const WsImpl = await resolveWebSocketImpl();
|
|
890
|
+
const headers = buildUpgradeHeaders(this._auth);
|
|
891
|
+
const ws = new WsImpl(this._url, [SUBPROTOCOL], {
|
|
892
|
+
headers
|
|
893
|
+
});
|
|
894
|
+
await new Promise((resolve, reject) => {
|
|
895
|
+
ws.onopen = () => resolve();
|
|
896
|
+
ws.onerror = (ev) => reject(new Error(`WS connect failed: ${ev.message ?? "unknown"}`));
|
|
897
|
+
});
|
|
898
|
+
ws.onmessage = (ev) => this._handleMessage(ev.data);
|
|
899
|
+
ws.onerror = (_ev) => this._failAll("WS connection error");
|
|
900
|
+
ws.onclose = () => {
|
|
901
|
+
this._failAll("WS connection closed");
|
|
902
|
+
this._ws = null;
|
|
903
|
+
};
|
|
904
|
+
this._ws = ws;
|
|
905
|
+
}
|
|
906
|
+
async disconnect() {
|
|
907
|
+
const ws = this._ws;
|
|
908
|
+
this._ws = null;
|
|
909
|
+
this._failAll("WS connection closed");
|
|
910
|
+
if (ws !== null) {
|
|
911
|
+
try {
|
|
912
|
+
ws.close();
|
|
913
|
+
} catch {
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
// ── Subscriptions ─────────────────────────────────────────────────────────
|
|
918
|
+
/**
|
|
919
|
+
* Open a server-side push subscription for `topic`.
|
|
920
|
+
*
|
|
921
|
+
* @param topic - Dotted namespace topic, e.g.
|
|
922
|
+
* `"agents.my-agent-id.events"` or `"tasks.task-123.*"`.
|
|
923
|
+
* @returns A {@link Subscription} handle whose async-for loop delivers events.
|
|
924
|
+
*/
|
|
925
|
+
async subscribe(topic) {
|
|
926
|
+
this._requireConnected();
|
|
927
|
+
const id = this._mintId();
|
|
928
|
+
return new Promise((resolve, reject) => {
|
|
929
|
+
this._pendingSubscribe.set(id, { topic, resolve, reject });
|
|
930
|
+
this._send({ jsonrpc: "2.0", id, method: "subscribe", params: { topic } });
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Cancel a server-side subscription.
|
|
935
|
+
*
|
|
936
|
+
* The local {@link Subscription} queue is closed immediately.
|
|
937
|
+
*
|
|
938
|
+
* @param subscriptionId - The `id` field from the {@link Subscription}
|
|
939
|
+
* returned by {@link subscribe}.
|
|
940
|
+
*/
|
|
941
|
+
async unsubscribe(subscriptionId) {
|
|
942
|
+
this._requireConnected();
|
|
943
|
+
const sub = this._subscriptions.get(subscriptionId);
|
|
944
|
+
if (sub !== void 0) {
|
|
945
|
+
this._subscriptions.delete(subscriptionId);
|
|
946
|
+
sub._close();
|
|
947
|
+
}
|
|
948
|
+
const id = this._mintId();
|
|
949
|
+
const ackPromise = new Promise((resolve, reject) => {
|
|
950
|
+
this._pending.set(id, { resolve, reject });
|
|
951
|
+
});
|
|
952
|
+
this._send({
|
|
953
|
+
jsonrpc: "2.0",
|
|
954
|
+
id,
|
|
955
|
+
method: "unsubscribe",
|
|
956
|
+
params: { subscription: subscriptionId }
|
|
957
|
+
});
|
|
958
|
+
await Promise.race([
|
|
959
|
+
ackPromise,
|
|
960
|
+
new Promise((resolve) => setTimeout(resolve, 5e3))
|
|
961
|
+
]);
|
|
962
|
+
this._pending.delete(id);
|
|
963
|
+
}
|
|
964
|
+
// ── Transport base implementation ─────────────────────────────────────────
|
|
965
|
+
async listTools(options) {
|
|
966
|
+
return await this._request("tools/list", options);
|
|
967
|
+
}
|
|
968
|
+
async callTool(name, args, _options) {
|
|
969
|
+
return this._request("tools/call", { name, arguments: args });
|
|
970
|
+
}
|
|
971
|
+
async listResources(_options) {
|
|
972
|
+
return await this._request("resources/list");
|
|
973
|
+
}
|
|
974
|
+
async readResource(uri, _options) {
|
|
975
|
+
return this._request("resources/read", { uri });
|
|
976
|
+
}
|
|
977
|
+
async listPrompts(_options) {
|
|
978
|
+
return await this._request("prompts/list");
|
|
979
|
+
}
|
|
980
|
+
async getPrompt(name, args, _options) {
|
|
981
|
+
return this._request("prompts/get", { name, arguments: args });
|
|
982
|
+
}
|
|
983
|
+
// ── Internal ──────────────────────────────────────────────────────────────
|
|
984
|
+
_mintId() {
|
|
985
|
+
return `ws-${++this._nextId}`;
|
|
986
|
+
}
|
|
987
|
+
_requireConnected() {
|
|
988
|
+
if (this._ws === null) {
|
|
989
|
+
throw new Error("WS transport not connected. Call connect() first.");
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
_send(payload) {
|
|
993
|
+
this._ws.send(JSON.stringify(payload));
|
|
994
|
+
}
|
|
995
|
+
async _request(method, params) {
|
|
996
|
+
this._requireConnected();
|
|
997
|
+
const id = this._mintId();
|
|
998
|
+
return new Promise((resolve, reject) => {
|
|
999
|
+
this._pending.set(id, { resolve, reject });
|
|
1000
|
+
this._send({ jsonrpc: "2.0", id, method, ...params !== void 0 ? { params } : {} });
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
_handleMessage(data) {
|
|
1004
|
+
let msg;
|
|
1005
|
+
try {
|
|
1006
|
+
msg = JSON.parse(data);
|
|
1007
|
+
} catch {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
if (!("id" in msg)) {
|
|
1011
|
+
if (msg["method"] === "notification") {
|
|
1012
|
+
this._routeNotification(msg["params"]);
|
|
1013
|
+
}
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
const msgId = String(msg["id"]);
|
|
1017
|
+
const pendingSub = this._pendingSubscribe.get(msgId);
|
|
1018
|
+
if (pendingSub !== void 0) {
|
|
1019
|
+
this._pendingSubscribe.delete(msgId);
|
|
1020
|
+
const err = msg["error"];
|
|
1021
|
+
if (err !== void 0) {
|
|
1022
|
+
pendingSub.reject(new Error(String(err["message"] ?? "Subscribe failed")));
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
const result = msg["result"] ?? {};
|
|
1026
|
+
const subId = String(result["subscription"] ?? msgId);
|
|
1027
|
+
const sub = new Subscription(subId, pendingSub.topic);
|
|
1028
|
+
this._subscriptions.set(subId, sub);
|
|
1029
|
+
pendingSub.resolve(sub);
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
const pending = this._pending.get(msgId);
|
|
1033
|
+
if (pending !== void 0) {
|
|
1034
|
+
this._pending.delete(msgId);
|
|
1035
|
+
const err = msg["error"];
|
|
1036
|
+
if (err !== void 0) {
|
|
1037
|
+
pending.reject(new Error(String(err["message"] ?? "RPC error")));
|
|
1038
|
+
} else {
|
|
1039
|
+
pending.resolve(msg["result"]);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
_routeNotification(params) {
|
|
1044
|
+
if (params === void 0) return;
|
|
1045
|
+
const subId = params["subscription"];
|
|
1046
|
+
if (typeof subId !== "string") return;
|
|
1047
|
+
const sub = this._subscriptions.get(subId);
|
|
1048
|
+
if (sub === void 0) return;
|
|
1049
|
+
sub._enqueue({
|
|
1050
|
+
subscription: subId,
|
|
1051
|
+
event: String(params["event"] ?? ""),
|
|
1052
|
+
data: params["data"]
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
_failAll(reason) {
|
|
1056
|
+
const err = new Error(reason);
|
|
1057
|
+
for (const { reject } of this._pending.values()) {
|
|
1058
|
+
reject(err);
|
|
1059
|
+
}
|
|
1060
|
+
this._pending.clear();
|
|
1061
|
+
for (const { reject } of this._pendingSubscribe.values()) {
|
|
1062
|
+
reject(err);
|
|
1063
|
+
}
|
|
1064
|
+
this._pendingSubscribe.clear();
|
|
1065
|
+
for (const sub of this._subscriptions.values()) {
|
|
1066
|
+
sub._close();
|
|
1067
|
+
}
|
|
1068
|
+
this._subscriptions.clear();
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
function buildUpgradeHeaders(auth) {
|
|
1072
|
+
const headers = {};
|
|
1073
|
+
if (auth === void 0) return headers;
|
|
1074
|
+
if ("bearer" in auth && auth.bearer !== void 0) {
|
|
1075
|
+
headers["Authorization"] = `Bearer ${auth.bearer}`;
|
|
1076
|
+
} else if ("apiKey" in auth && auth.apiKey !== void 0) {
|
|
1077
|
+
headers["X-API-Key"] = auth.apiKey;
|
|
1078
|
+
} else if ("basic" in auth && auth.basic !== void 0) {
|
|
1079
|
+
const encoded = Buffer.from(`${auth.basic.username}:${auth.basic.password}`).toString("base64");
|
|
1080
|
+
headers["Authorization"] = `Basic ${encoded}`;
|
|
1081
|
+
}
|
|
1082
|
+
return headers;
|
|
1083
|
+
}
|
|
1084
|
+
async function resolveWebSocketImpl() {
|
|
1085
|
+
if (typeof globalThis.WebSocket !== "undefined") {
|
|
1086
|
+
return globalThis.WebSocket;
|
|
1087
|
+
}
|
|
1088
|
+
try {
|
|
1089
|
+
const { default: WS } = await import("ws");
|
|
1090
|
+
return WS;
|
|
1091
|
+
} catch {
|
|
1092
|
+
throw new Error(
|
|
1093
|
+
"No WebSocket implementation found. Install the 'ws' package: npm install ws"
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
|
|
730
1098
|
// src/client.ts
|
|
731
1099
|
init_identity();
|
|
732
1100
|
|
|
@@ -1247,13 +1615,15 @@ var Client2 = class _Client {
|
|
|
1247
1615
|
this.isDg = isDgUrl(this.url);
|
|
1248
1616
|
this.useIntelligentInterface = options.useIntelligentInterface ?? this.isDg;
|
|
1249
1617
|
this.maxRetries = options.maxRetries ?? 3;
|
|
1250
|
-
|
|
1251
|
-
if (identity === void 0 && this.isDg && !options.disableMtls) {
|
|
1252
|
-
identity = ConduitIdentity.tryDiscover(options.identityDir) ?? void 0;
|
|
1253
|
-
}
|
|
1618
|
+
const identity = options.identity ?? (options.identityAuto ? ConduitIdentity.tryDiscover(options.identityDir) ?? void 0 : void 0);
|
|
1254
1619
|
const transportType = options.transport || "mcp";
|
|
1255
1620
|
if (transportType === "mcp") {
|
|
1256
1621
|
this.transport = new MCPTransport(this.url, this.auth, identity);
|
|
1622
|
+
} else if (transportType === "websocket") {
|
|
1623
|
+
let wsUrl = this.url;
|
|
1624
|
+
if (wsUrl.startsWith("https://")) wsUrl = "wss://" + wsUrl.slice(8);
|
|
1625
|
+
else if (wsUrl.startsWith("http://")) wsUrl = "ws://" + wsUrl.slice(7);
|
|
1626
|
+
this.transport = new WsTransport(wsUrl, this.auth, options.timeout, identity);
|
|
1257
1627
|
} else {
|
|
1258
1628
|
const rpcUrl = this.url.endsWith("/mcp") ? this.url.slice(0, -4) + "/rpc" : this.url;
|
|
1259
1629
|
this.transport = new JSONRPCTransport(rpcUrl, this.auth, options.timeout, identity);
|
|
@@ -1330,6 +1700,60 @@ var Client2 = class _Client {
|
|
|
1330
1700
|
substrateEndpoint: options.substrateEndpoint
|
|
1331
1701
|
});
|
|
1332
1702
|
}
|
|
1703
|
+
/**
|
|
1704
|
+
* Register autonomously with DG and bootstrap an mTLS identity.
|
|
1705
|
+
*
|
|
1706
|
+
* The all-in-one flow: onramp (no prior credentials required) →
|
|
1707
|
+
* OAuth token exchange → mTLS identity registration and persistence.
|
|
1708
|
+
*
|
|
1709
|
+
* On subsequent runs the saved mTLS identity is auto-discovered and
|
|
1710
|
+
* no credentials are needed.
|
|
1711
|
+
*
|
|
1712
|
+
* @param options.opts - Onramp registration options.
|
|
1713
|
+
* @param options.url - MCP server URL. Required if the onramp
|
|
1714
|
+
* response does not include `mcpUrl`.
|
|
1715
|
+
* @param options.identityDir - Custom identity storage directory.
|
|
1716
|
+
*
|
|
1717
|
+
* @example
|
|
1718
|
+
* ```ts
|
|
1719
|
+
* import { Client } from './client';
|
|
1720
|
+
* import type { OnrampOptions } from './onramp';
|
|
1721
|
+
*
|
|
1722
|
+
* const client = await Client.bootstrapOnramp({
|
|
1723
|
+
* opts: {
|
|
1724
|
+
* gateway: 'https://app.datagrout.ai',
|
|
1725
|
+
* agentName: 'my-research-agent',
|
|
1726
|
+
* agentType: 'claude-sonnet-4-6',
|
|
1727
|
+
* },
|
|
1728
|
+
* });
|
|
1729
|
+
* await client.connect();
|
|
1730
|
+
* ```
|
|
1731
|
+
*/
|
|
1732
|
+
static async bootstrapOnramp(options) {
|
|
1733
|
+
const { _doRegister: _doRegister2, _exchangeToken: _exchangeToken2 } = await Promise.resolve().then(() => (init_onramp(), onramp_exports));
|
|
1734
|
+
const dir = options.identityDir || DEFAULT_IDENTITY_DIR;
|
|
1735
|
+
const existing = ConduitIdentity.tryDiscover(dir);
|
|
1736
|
+
if (existing && !existing.needsRotation(7)) {
|
|
1737
|
+
if (!options.url) {
|
|
1738
|
+
throw new Error("'url' must be provided when an existing identity is reused");
|
|
1739
|
+
}
|
|
1740
|
+
return new _Client({ url: options.url, identity: existing, identityDir: dir });
|
|
1741
|
+
}
|
|
1742
|
+
const creds = await _doRegister2(options.opts);
|
|
1743
|
+
const token = await _exchangeToken2(creds);
|
|
1744
|
+
const url = creds.mcpUrl ?? options.url;
|
|
1745
|
+
if (!url) {
|
|
1746
|
+
throw new Error(
|
|
1747
|
+
"'url' must be provided when mcpUrl is absent from the onramp response"
|
|
1748
|
+
);
|
|
1749
|
+
}
|
|
1750
|
+
return _Client.bootstrapIdentity({
|
|
1751
|
+
url,
|
|
1752
|
+
authToken: token,
|
|
1753
|
+
name: options.opts.agentName,
|
|
1754
|
+
identityDir: options.identityDir
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1333
1757
|
// ===== Lifecycle =====
|
|
1334
1758
|
/**
|
|
1335
1759
|
* Establish the underlying transport connection.
|
|
@@ -1488,6 +1912,50 @@ var Client2 = class _Client {
|
|
|
1488
1912
|
this.ensureInitialized();
|
|
1489
1913
|
return this.sendWithRetry(() => this.transport.getPrompt(name, args, options));
|
|
1490
1914
|
}
|
|
1915
|
+
// ===== WebSocket push subscriptions =====
|
|
1916
|
+
/**
|
|
1917
|
+
* Subscribe to a server-push topic (WebSocket transport only).
|
|
1918
|
+
*
|
|
1919
|
+
* Requires `transport: 'websocket'` when constructing the client.
|
|
1920
|
+
*
|
|
1921
|
+
* @param topic - Dotted namespace topic, e.g.
|
|
1922
|
+
* `"agents.my-agent-id.events"` or `"tasks.task-123.*"`.
|
|
1923
|
+
* @returns A {@link Subscription} handle. Consume events with
|
|
1924
|
+
* {@link Subscription.recv} or an `for await` loop.
|
|
1925
|
+
*
|
|
1926
|
+
* @example
|
|
1927
|
+
* ```ts
|
|
1928
|
+
* const sub = await client.subscribe('agents.my-agent-id.events');
|
|
1929
|
+
* for await (const event of sub) {
|
|
1930
|
+
* console.log(event.event, event.data);
|
|
1931
|
+
* }
|
|
1932
|
+
* await client.unsubscribe(sub.id);
|
|
1933
|
+
* ```
|
|
1934
|
+
*/
|
|
1935
|
+
async subscribe(topic) {
|
|
1936
|
+
this.ensureInitialized();
|
|
1937
|
+
if (!(this.transport instanceof WsTransport)) {
|
|
1938
|
+
throw new Error(
|
|
1939
|
+
"subscribe() requires transport: 'websocket'. Reinitialise the client with transport: 'websocket'."
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
return this.transport.subscribe(topic);
|
|
1943
|
+
}
|
|
1944
|
+
/**
|
|
1945
|
+
* Cancel a server-side push subscription.
|
|
1946
|
+
*
|
|
1947
|
+
* @param subscriptionId - The `id` from the {@link Subscription} returned
|
|
1948
|
+
* by {@link subscribe}.
|
|
1949
|
+
*/
|
|
1950
|
+
async unsubscribe(subscriptionId) {
|
|
1951
|
+
this.ensureInitialized();
|
|
1952
|
+
if (!(this.transport instanceof WsTransport)) {
|
|
1953
|
+
throw new Error(
|
|
1954
|
+
"unsubscribe() requires transport: 'websocket'. Reinitialise the client with transport: 'websocket'."
|
|
1955
|
+
);
|
|
1956
|
+
}
|
|
1957
|
+
return this.transport.unsubscribe(subscriptionId);
|
|
1958
|
+
}
|
|
1491
1959
|
// ===== DG-awareness helpers =====
|
|
1492
1960
|
warnIfNotDg(method) {
|
|
1493
1961
|
if (!this.isDg && !this.dgWarned) {
|
|
@@ -1778,7 +2246,8 @@ function buildToolMeta(raw) {
|
|
|
1778
2246
|
}
|
|
1779
2247
|
|
|
1780
2248
|
// src/index.ts
|
|
1781
|
-
|
|
2249
|
+
init_onramp();
|
|
2250
|
+
var version = "0.5.0";
|
|
1782
2251
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1783
2252
|
0 && (module.exports = {
|
|
1784
2253
|
AuthError,
|
|
@@ -1795,6 +2264,8 @@ var version = "0.1.0";
|
|
|
1795
2264
|
OAuthTokenProvider,
|
|
1796
2265
|
RateLimitError,
|
|
1797
2266
|
ServerError,
|
|
2267
|
+
WS_SUBPROTOCOL,
|
|
2268
|
+
WsTransport,
|
|
1798
2269
|
deriveTokenEndpoint,
|
|
1799
2270
|
extractMeta,
|
|
1800
2271
|
fetchDgCaCert,
|
|
@@ -1802,7 +2273,9 @@ var version = "0.1.0";
|
|
|
1802
2273
|
generateKeypair,
|
|
1803
2274
|
isDgUrl,
|
|
1804
2275
|
refreshCaCert,
|
|
2276
|
+
registerAndExchange,
|
|
1805
2277
|
registerIdentity,
|
|
2278
|
+
registerOnly,
|
|
1806
2279
|
rotateIdentity,
|
|
1807
2280
|
saveIdentity,
|
|
1808
2281
|
version
|