@dominusnode/openai-functions 1.0.1 → 1.2.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/dist/handler.d.ts +5 -0
- package/dist/handler.js +523 -7
- package/functions.json +46 -0
- package/package.json +1 -1
package/dist/handler.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dominus Node OpenAI-compatible function calling handler (TypeScript).
|
|
3
3
|
*
|
|
4
|
+
* 53 tools covering proxy, wallet, usage, account lifecycle, API keys,
|
|
5
|
+
* plans, and teams.
|
|
6
|
+
*
|
|
4
7
|
* Provides a factory function that creates a handler for dispatching
|
|
5
8
|
* OpenAI function calls to the Dominus Node REST API. Works with any
|
|
6
9
|
* function-calling LLM system: OpenAI GPT, Anthropic Claude tool_use,
|
|
@@ -46,6 +49,8 @@ export interface DominusNodeFunctionConfig {
|
|
|
46
49
|
baseUrl?: string;
|
|
47
50
|
/** Request timeout in milliseconds. Defaults to 30000. */
|
|
48
51
|
timeoutMs?: number;
|
|
52
|
+
/** Agent secret for MCP agent identification. Bypasses reCAPTCHA and auto-verifies email. */
|
|
53
|
+
agentSecret?: string;
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
51
56
|
* Handler function type returned by createDominusNodeFunctionHandler.
|
package/dist/handler.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dominus Node OpenAI-compatible function calling handler (TypeScript).
|
|
3
3
|
*
|
|
4
|
+
* 53 tools covering proxy, wallet, usage, account lifecycle, API keys,
|
|
5
|
+
* plans, and teams.
|
|
6
|
+
*
|
|
4
7
|
* Provides a factory function that creates a handler for dispatching
|
|
5
8
|
* OpenAI function calls to the Dominus Node REST API. Works with any
|
|
6
9
|
* function-calling LLM system: OpenAI GPT, Anthropic Claude tool_use,
|
|
@@ -312,6 +315,10 @@ async function apiRequest(config, method, path, body) {
|
|
|
312
315
|
"Content-Type": "application/json",
|
|
313
316
|
Authorization: `Bearer ${config.token}`,
|
|
314
317
|
};
|
|
318
|
+
if (config.agentSecret) {
|
|
319
|
+
headers["X-DominusNode-Agent"] = "mcp";
|
|
320
|
+
headers["X-DominusNode-Agent-Secret"] = config.agentSecret;
|
|
321
|
+
}
|
|
315
322
|
const response = await fetch(url, {
|
|
316
323
|
method,
|
|
317
324
|
headers,
|
|
@@ -392,6 +399,7 @@ export { isPrivateIp, validateUrl, normalizeIpv4, sanitizeError, stripDangerousK
|
|
|
392
399
|
export function createDominusNodeFunctionHandler(config) {
|
|
393
400
|
const baseUrl = config.baseUrl ?? "https://api.dominusnode.com";
|
|
394
401
|
const timeoutMs = config.timeoutMs ?? 30_000;
|
|
402
|
+
const agentSecret = config.agentSecret || process.env.DOMINUSNODE_AGENT_SECRET;
|
|
395
403
|
if (!config.apiKey || typeof config.apiKey !== "string") {
|
|
396
404
|
throw new Error("apiKey is required and must be a non-empty string");
|
|
397
405
|
}
|
|
@@ -399,12 +407,17 @@ export function createDominusNodeFunctionHandler(config) {
|
|
|
399
407
|
let authToken = null;
|
|
400
408
|
let authPromise = null;
|
|
401
409
|
async function authenticate() {
|
|
410
|
+
const authHeaders = {
|
|
411
|
+
"User-Agent": "dominusnode-openai-functions/1.0.0",
|
|
412
|
+
"Content-Type": "application/json",
|
|
413
|
+
};
|
|
414
|
+
if (agentSecret) {
|
|
415
|
+
authHeaders["X-DominusNode-Agent"] = "mcp";
|
|
416
|
+
authHeaders["X-DominusNode-Agent-Secret"] = agentSecret;
|
|
417
|
+
}
|
|
402
418
|
const response = await fetch(`${baseUrl}/api/auth/verify-key`, {
|
|
403
419
|
method: "POST",
|
|
404
|
-
headers:
|
|
405
|
-
"User-Agent": "dominusnode-openai-functions/1.0.0",
|
|
406
|
-
"Content-Type": "application/json",
|
|
407
|
-
},
|
|
420
|
+
headers: authHeaders,
|
|
408
421
|
body: JSON.stringify({ apiKey: config.apiKey }),
|
|
409
422
|
signal: AbortSignal.timeout(timeoutMs),
|
|
410
423
|
redirect: "error",
|
|
@@ -432,7 +445,7 @@ export function createDominusNodeFunctionHandler(config) {
|
|
|
432
445
|
function api(method, path, body) {
|
|
433
446
|
if (!authToken)
|
|
434
447
|
throw new Error("Not authenticated");
|
|
435
|
-
return apiRequest({ baseUrl, timeoutMs, token: authToken }, method, path, body);
|
|
448
|
+
return apiRequest({ baseUrl, timeoutMs, token: authToken, agentSecret }, method, path, body);
|
|
436
449
|
}
|
|
437
450
|
// -----------------------------------------------------------------------
|
|
438
451
|
// Function handlers
|
|
@@ -923,6 +936,40 @@ export function createDominusNodeFunctionHandler(config) {
|
|
|
923
936
|
const result = await api("POST", "/api/wallet/topup/paypal", { amountCents });
|
|
924
937
|
return JSON.stringify(result);
|
|
925
938
|
}
|
|
939
|
+
async function handleTopupStripe(args) {
|
|
940
|
+
const amountCents = args.amount_cents;
|
|
941
|
+
if (!Number.isInteger(amountCents) ||
|
|
942
|
+
amountCents < 500 ||
|
|
943
|
+
amountCents > 100_000) {
|
|
944
|
+
return JSON.stringify({
|
|
945
|
+
error: "amount_cents must be an integer between 500 ($5) and 100,000 ($1,000)",
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
const result = await api("POST", "/api/wallet/topup/stripe", { amountCents });
|
|
949
|
+
return JSON.stringify(result);
|
|
950
|
+
}
|
|
951
|
+
async function handleTopupCrypto(args) {
|
|
952
|
+
const amountUsd = args.amount_usd;
|
|
953
|
+
const currency = args.currency;
|
|
954
|
+
if (typeof amountUsd !== "number" || !Number.isFinite(amountUsd) || amountUsd < 5 || amountUsd > 1000) {
|
|
955
|
+
return JSON.stringify({
|
|
956
|
+
error: "amount_usd must be a number between 5 and 1,000",
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
const validCurrencies = new Set([
|
|
960
|
+
"BTC", "ETH", "LTC", "XMR", "ZEC", "USDC", "SOL", "USDT", "DAI", "BNB", "LINK",
|
|
961
|
+
]);
|
|
962
|
+
if (!currency || typeof currency !== "string" || !validCurrencies.has(currency.toUpperCase())) {
|
|
963
|
+
return JSON.stringify({
|
|
964
|
+
error: "currency must be one of: BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, LINK",
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
const result = await api("POST", "/api/wallet/topup/crypto", {
|
|
968
|
+
amountUsd,
|
|
969
|
+
currency: currency.toLowerCase(),
|
|
970
|
+
});
|
|
971
|
+
return JSON.stringify(result);
|
|
972
|
+
}
|
|
926
973
|
async function handleUpdateWalletPolicy(args) {
|
|
927
974
|
const walletId = args.wallet_id;
|
|
928
975
|
if (!walletId || typeof walletId !== "string") {
|
|
@@ -1007,14 +1054,473 @@ export function createDominusNodeFunctionHandler(config) {
|
|
|
1007
1054
|
return JSON.stringify(result);
|
|
1008
1055
|
}
|
|
1009
1056
|
// -----------------------------------------------------------------------
|
|
1057
|
+
// Proxy extended
|
|
1058
|
+
// -----------------------------------------------------------------------
|
|
1059
|
+
async function handleGetProxyStatus() {
|
|
1060
|
+
const result = await api("GET", "/api/proxy/status");
|
|
1061
|
+
return JSON.stringify(result);
|
|
1062
|
+
}
|
|
1063
|
+
// -----------------------------------------------------------------------
|
|
1064
|
+
// Wallet extended
|
|
1065
|
+
// -----------------------------------------------------------------------
|
|
1066
|
+
async function handleGetTransactions(args) {
|
|
1067
|
+
const params = new URLSearchParams();
|
|
1068
|
+
if (args.limit !== undefined) {
|
|
1069
|
+
const limit = args.limit;
|
|
1070
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
|
|
1071
|
+
return JSON.stringify({ error: "limit must be an integer between 1 and 100" });
|
|
1072
|
+
}
|
|
1073
|
+
params.set("limit", String(limit));
|
|
1074
|
+
}
|
|
1075
|
+
const qs = params.toString();
|
|
1076
|
+
const result = await api("GET", `/api/wallet/transactions${qs ? `?${qs}` : ""}`);
|
|
1077
|
+
return JSON.stringify(result);
|
|
1078
|
+
}
|
|
1079
|
+
async function handleGetForecast() {
|
|
1080
|
+
const result = await api("GET", "/api/wallet/forecast");
|
|
1081
|
+
return JSON.stringify(result);
|
|
1082
|
+
}
|
|
1083
|
+
async function handleCheckPayment(args) {
|
|
1084
|
+
const invoiceId = args.invoice_id;
|
|
1085
|
+
if (!invoiceId || typeof invoiceId !== "string") {
|
|
1086
|
+
return JSON.stringify({ error: "invoice_id is required and must be a string" });
|
|
1087
|
+
}
|
|
1088
|
+
const result = await api("GET", `/api/wallet/topup/crypto/${encodeURIComponent(invoiceId)}/status`);
|
|
1089
|
+
return JSON.stringify(result);
|
|
1090
|
+
}
|
|
1091
|
+
// -----------------------------------------------------------------------
|
|
1092
|
+
// Usage extended
|
|
1093
|
+
// -----------------------------------------------------------------------
|
|
1094
|
+
async function handleGetDailyUsage(args) {
|
|
1095
|
+
const days = args.days ?? 30;
|
|
1096
|
+
if (!Number.isInteger(days) || days < 1 || days > 90) {
|
|
1097
|
+
return JSON.stringify({ error: "days must be an integer between 1 and 90" });
|
|
1098
|
+
}
|
|
1099
|
+
const params = new URLSearchParams({ days: String(days) });
|
|
1100
|
+
const result = await api("GET", `/api/usage/daily?${params.toString()}`);
|
|
1101
|
+
return JSON.stringify(result);
|
|
1102
|
+
}
|
|
1103
|
+
async function handleGetTopHosts(args) {
|
|
1104
|
+
const params = new URLSearchParams();
|
|
1105
|
+
if (args.limit !== undefined) {
|
|
1106
|
+
const limit = args.limit;
|
|
1107
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 50) {
|
|
1108
|
+
return JSON.stringify({ error: "limit must be an integer between 1 and 50" });
|
|
1109
|
+
}
|
|
1110
|
+
params.set("limit", String(limit));
|
|
1111
|
+
}
|
|
1112
|
+
const qs = params.toString();
|
|
1113
|
+
const result = await api("GET", `/api/usage/top-hosts${qs ? `?${qs}` : ""}`);
|
|
1114
|
+
return JSON.stringify(result);
|
|
1115
|
+
}
|
|
1116
|
+
// -----------------------------------------------------------------------
|
|
1117
|
+
// Account lifecycle
|
|
1118
|
+
// -----------------------------------------------------------------------
|
|
1119
|
+
async function handleRegister(args) {
|
|
1120
|
+
const email = args.email;
|
|
1121
|
+
const password = args.password;
|
|
1122
|
+
if (!email || typeof email !== "string") {
|
|
1123
|
+
return JSON.stringify({ error: "email is required and must be a string" });
|
|
1124
|
+
}
|
|
1125
|
+
if (!/^[^@]+@[^@]+\.[^@]+$/.test(email)) {
|
|
1126
|
+
return JSON.stringify({ error: "email must be a valid email address" });
|
|
1127
|
+
}
|
|
1128
|
+
if (!password || typeof password !== "string") {
|
|
1129
|
+
return JSON.stringify({ error: "password is required and must be a string" });
|
|
1130
|
+
}
|
|
1131
|
+
if (password.length < 8 || password.length > 128) {
|
|
1132
|
+
return JSON.stringify({ error: "password must be between 8 and 128 characters" });
|
|
1133
|
+
}
|
|
1134
|
+
const headers = {
|
|
1135
|
+
"User-Agent": "dominusnode-openai-functions/1.0.0",
|
|
1136
|
+
"Content-Type": "application/json",
|
|
1137
|
+
};
|
|
1138
|
+
if (agentSecret) {
|
|
1139
|
+
headers["X-DominusNode-Agent"] = "mcp";
|
|
1140
|
+
headers["X-DominusNode-Agent-Secret"] = agentSecret;
|
|
1141
|
+
}
|
|
1142
|
+
const response = await fetch(`${baseUrl}/api/auth/register`, {
|
|
1143
|
+
method: "POST",
|
|
1144
|
+
headers,
|
|
1145
|
+
body: JSON.stringify({ email, password }),
|
|
1146
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
1147
|
+
redirect: "error",
|
|
1148
|
+
});
|
|
1149
|
+
const text = await response.text();
|
|
1150
|
+
if (text.length > MAX_RESPONSE_BYTES) {
|
|
1151
|
+
return JSON.stringify({ error: "Response body exceeds size limit" });
|
|
1152
|
+
}
|
|
1153
|
+
if (!response.ok) {
|
|
1154
|
+
let message;
|
|
1155
|
+
try {
|
|
1156
|
+
const parsed = JSON.parse(text);
|
|
1157
|
+
message = parsed.error ?? parsed.message ?? text;
|
|
1158
|
+
}
|
|
1159
|
+
catch {
|
|
1160
|
+
message = text;
|
|
1161
|
+
}
|
|
1162
|
+
if (message.length > 500)
|
|
1163
|
+
message = message.slice(0, 500) + "... [truncated]";
|
|
1164
|
+
return JSON.stringify({ error: `Registration failed: ${sanitizeError(message)}` });
|
|
1165
|
+
}
|
|
1166
|
+
const data = safeJsonParse(text);
|
|
1167
|
+
stripDangerousKeys(data);
|
|
1168
|
+
return JSON.stringify({ userId: data.userId, email: data.email, message: data.message });
|
|
1169
|
+
}
|
|
1170
|
+
async function handleLogin(args) {
|
|
1171
|
+
const email = args.email;
|
|
1172
|
+
const password = args.password;
|
|
1173
|
+
if (!email || typeof email !== "string") {
|
|
1174
|
+
return JSON.stringify({ error: "email is required and must be a string" });
|
|
1175
|
+
}
|
|
1176
|
+
if (!/^[^@]+@[^@]+\.[^@]+$/.test(email)) {
|
|
1177
|
+
return JSON.stringify({ error: "email must be a valid email address" });
|
|
1178
|
+
}
|
|
1179
|
+
if (!password || typeof password !== "string") {
|
|
1180
|
+
return JSON.stringify({ error: "password is required and must be a string" });
|
|
1181
|
+
}
|
|
1182
|
+
if (password.length < 8 || password.length > 128) {
|
|
1183
|
+
return JSON.stringify({ error: "password must be between 8 and 128 characters" });
|
|
1184
|
+
}
|
|
1185
|
+
const headers = {
|
|
1186
|
+
"User-Agent": "dominusnode-openai-functions/1.0.0",
|
|
1187
|
+
"Content-Type": "application/json",
|
|
1188
|
+
};
|
|
1189
|
+
if (agentSecret) {
|
|
1190
|
+
headers["X-DominusNode-Agent"] = "mcp";
|
|
1191
|
+
headers["X-DominusNode-Agent-Secret"] = agentSecret;
|
|
1192
|
+
}
|
|
1193
|
+
const response = await fetch(`${baseUrl}/api/auth/login`, {
|
|
1194
|
+
method: "POST",
|
|
1195
|
+
headers,
|
|
1196
|
+
body: JSON.stringify({ email, password }),
|
|
1197
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
1198
|
+
redirect: "error",
|
|
1199
|
+
});
|
|
1200
|
+
const text = await response.text();
|
|
1201
|
+
if (text.length > MAX_RESPONSE_BYTES) {
|
|
1202
|
+
return JSON.stringify({ error: "Response body exceeds size limit" });
|
|
1203
|
+
}
|
|
1204
|
+
if (!response.ok) {
|
|
1205
|
+
let message;
|
|
1206
|
+
try {
|
|
1207
|
+
const parsed = JSON.parse(text);
|
|
1208
|
+
message = parsed.error ?? parsed.message ?? text;
|
|
1209
|
+
}
|
|
1210
|
+
catch {
|
|
1211
|
+
message = text;
|
|
1212
|
+
}
|
|
1213
|
+
if (message.length > 500)
|
|
1214
|
+
message = message.slice(0, 500) + "... [truncated]";
|
|
1215
|
+
return JSON.stringify({ error: `Login failed: ${sanitizeError(message)}` });
|
|
1216
|
+
}
|
|
1217
|
+
const data = safeJsonParse(text);
|
|
1218
|
+
stripDangerousKeys(data);
|
|
1219
|
+
return JSON.stringify({ token: data.token, message: data.message });
|
|
1220
|
+
}
|
|
1221
|
+
async function handleGetAccountInfo() {
|
|
1222
|
+
const result = await api("GET", "/api/auth/me");
|
|
1223
|
+
return JSON.stringify(result);
|
|
1224
|
+
}
|
|
1225
|
+
async function handleVerifyEmail(args) {
|
|
1226
|
+
const token = args.token;
|
|
1227
|
+
if (!token || typeof token !== "string") {
|
|
1228
|
+
return JSON.stringify({ error: "token is required and must be a string" });
|
|
1229
|
+
}
|
|
1230
|
+
const headers = {
|
|
1231
|
+
"User-Agent": "dominusnode-openai-functions/1.0.0",
|
|
1232
|
+
"Content-Type": "application/json",
|
|
1233
|
+
};
|
|
1234
|
+
if (agentSecret) {
|
|
1235
|
+
headers["X-DominusNode-Agent"] = "mcp";
|
|
1236
|
+
headers["X-DominusNode-Agent-Secret"] = agentSecret;
|
|
1237
|
+
}
|
|
1238
|
+
const response = await fetch(`${baseUrl}/api/auth/verify-email`, {
|
|
1239
|
+
method: "POST",
|
|
1240
|
+
headers,
|
|
1241
|
+
body: JSON.stringify({ token }),
|
|
1242
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
1243
|
+
redirect: "error",
|
|
1244
|
+
});
|
|
1245
|
+
const text = await response.text();
|
|
1246
|
+
if (text.length > MAX_RESPONSE_BYTES) {
|
|
1247
|
+
return JSON.stringify({ error: "Response body exceeds size limit" });
|
|
1248
|
+
}
|
|
1249
|
+
if (!response.ok) {
|
|
1250
|
+
let message;
|
|
1251
|
+
try {
|
|
1252
|
+
const parsed = JSON.parse(text);
|
|
1253
|
+
message = parsed.error ?? parsed.message ?? text;
|
|
1254
|
+
}
|
|
1255
|
+
catch {
|
|
1256
|
+
message = text;
|
|
1257
|
+
}
|
|
1258
|
+
if (message.length > 500)
|
|
1259
|
+
message = message.slice(0, 500) + "... [truncated]";
|
|
1260
|
+
return JSON.stringify({ error: `Email verification failed: ${sanitizeError(message)}` });
|
|
1261
|
+
}
|
|
1262
|
+
const data = safeJsonParse(text);
|
|
1263
|
+
stripDangerousKeys(data);
|
|
1264
|
+
return JSON.stringify(data);
|
|
1265
|
+
}
|
|
1266
|
+
async function handleResendVerification() {
|
|
1267
|
+
const result = await api("POST", "/api/auth/resend-verification");
|
|
1268
|
+
return JSON.stringify(result);
|
|
1269
|
+
}
|
|
1270
|
+
async function handleUpdatePassword(args) {
|
|
1271
|
+
const currentPassword = args.current_password;
|
|
1272
|
+
const newPassword = args.new_password;
|
|
1273
|
+
if (!currentPassword || typeof currentPassword !== "string") {
|
|
1274
|
+
return JSON.stringify({ error: "current_password is required and must be a string" });
|
|
1275
|
+
}
|
|
1276
|
+
if (!newPassword || typeof newPassword !== "string") {
|
|
1277
|
+
return JSON.stringify({ error: "new_password is required and must be a string" });
|
|
1278
|
+
}
|
|
1279
|
+
if (newPassword.length < 8 || newPassword.length > 128) {
|
|
1280
|
+
return JSON.stringify({ error: "new_password must be between 8 and 128 characters" });
|
|
1281
|
+
}
|
|
1282
|
+
const result = await api("POST", "/api/auth/change-password", {
|
|
1283
|
+
currentPassword,
|
|
1284
|
+
newPassword,
|
|
1285
|
+
});
|
|
1286
|
+
return JSON.stringify(result);
|
|
1287
|
+
}
|
|
1288
|
+
// -----------------------------------------------------------------------
|
|
1289
|
+
// API Keys
|
|
1290
|
+
// -----------------------------------------------------------------------
|
|
1291
|
+
async function handleListKeys() {
|
|
1292
|
+
const result = await api("GET", "/api/keys");
|
|
1293
|
+
return JSON.stringify(result);
|
|
1294
|
+
}
|
|
1295
|
+
async function handleCreateKey(args) {
|
|
1296
|
+
const label = args.label;
|
|
1297
|
+
if (!label || typeof label !== "string") {
|
|
1298
|
+
return JSON.stringify({ error: "label is required and must be a string" });
|
|
1299
|
+
}
|
|
1300
|
+
if (label.length > 100) {
|
|
1301
|
+
return JSON.stringify({ error: "label must be 100 characters or fewer" });
|
|
1302
|
+
}
|
|
1303
|
+
if (/[\x00-\x1f\x7f]/.test(label)) {
|
|
1304
|
+
return JSON.stringify({ error: "label contains invalid control characters" });
|
|
1305
|
+
}
|
|
1306
|
+
const result = await api("POST", "/api/keys", { label });
|
|
1307
|
+
return JSON.stringify(result);
|
|
1308
|
+
}
|
|
1309
|
+
async function handleRevokeKey(args) {
|
|
1310
|
+
const keyId = args.key_id;
|
|
1311
|
+
if (!keyId || typeof keyId !== "string") {
|
|
1312
|
+
return JSON.stringify({ error: "key_id is required and must be a string" });
|
|
1313
|
+
}
|
|
1314
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(keyId)) {
|
|
1315
|
+
return JSON.stringify({ error: "key_id must be a valid UUID" });
|
|
1316
|
+
}
|
|
1317
|
+
const result = await api("DELETE", `/api/keys/${encodeURIComponent(keyId)}`);
|
|
1318
|
+
return JSON.stringify(result);
|
|
1319
|
+
}
|
|
1320
|
+
// -----------------------------------------------------------------------
|
|
1321
|
+
// Plans
|
|
1322
|
+
// -----------------------------------------------------------------------
|
|
1323
|
+
async function handleGetPlan() {
|
|
1324
|
+
const result = await api("GET", "/api/plans/user/plan");
|
|
1325
|
+
return JSON.stringify(result);
|
|
1326
|
+
}
|
|
1327
|
+
async function handleListPlans() {
|
|
1328
|
+
const result = await api("GET", "/api/plans");
|
|
1329
|
+
return JSON.stringify(result);
|
|
1330
|
+
}
|
|
1331
|
+
async function handleChangePlan(args) {
|
|
1332
|
+
const planId = args.plan_id;
|
|
1333
|
+
if (!planId || typeof planId !== "string") {
|
|
1334
|
+
return JSON.stringify({ error: "plan_id is required and must be a string" });
|
|
1335
|
+
}
|
|
1336
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(planId)) {
|
|
1337
|
+
return JSON.stringify({ error: "plan_id must be a valid UUID" });
|
|
1338
|
+
}
|
|
1339
|
+
const result = await api("PUT", "/api/plans/user/plan", { planId });
|
|
1340
|
+
return JSON.stringify(result);
|
|
1341
|
+
}
|
|
1342
|
+
// -----------------------------------------------------------------------
|
|
1343
|
+
// Teams extended
|
|
1344
|
+
// -----------------------------------------------------------------------
|
|
1345
|
+
async function handleTeamDelete(args) {
|
|
1346
|
+
const teamId = args.team_id;
|
|
1347
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1348
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1349
|
+
}
|
|
1350
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1351
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1352
|
+
}
|
|
1353
|
+
const result = await api("DELETE", `/api/teams/${encodeURIComponent(teamId)}`);
|
|
1354
|
+
return JSON.stringify(result);
|
|
1355
|
+
}
|
|
1356
|
+
async function handleTeamRevokeKey(args) {
|
|
1357
|
+
const teamId = args.team_id;
|
|
1358
|
+
const keyId = args.key_id;
|
|
1359
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1360
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1361
|
+
}
|
|
1362
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1363
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1364
|
+
}
|
|
1365
|
+
if (!keyId || typeof keyId !== "string") {
|
|
1366
|
+
return JSON.stringify({ error: "key_id is required and must be a string" });
|
|
1367
|
+
}
|
|
1368
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(keyId)) {
|
|
1369
|
+
return JSON.stringify({ error: "key_id must be a valid UUID" });
|
|
1370
|
+
}
|
|
1371
|
+
const result = await api("DELETE", `/api/teams/${encodeURIComponent(teamId)}/keys/${encodeURIComponent(keyId)}`);
|
|
1372
|
+
return JSON.stringify(result);
|
|
1373
|
+
}
|
|
1374
|
+
async function handleTeamListKeys(args) {
|
|
1375
|
+
const teamId = args.team_id;
|
|
1376
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1377
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1378
|
+
}
|
|
1379
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1380
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1381
|
+
}
|
|
1382
|
+
const result = await api("GET", `/api/teams/${encodeURIComponent(teamId)}/keys`);
|
|
1383
|
+
return JSON.stringify(result);
|
|
1384
|
+
}
|
|
1385
|
+
async function handleTeamListMembers(args) {
|
|
1386
|
+
const teamId = args.team_id;
|
|
1387
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1388
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1389
|
+
}
|
|
1390
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1391
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1392
|
+
}
|
|
1393
|
+
const result = await api("GET", `/api/teams/${encodeURIComponent(teamId)}/members`);
|
|
1394
|
+
return JSON.stringify(result);
|
|
1395
|
+
}
|
|
1396
|
+
async function handleTeamAddMember(args) {
|
|
1397
|
+
const teamId = args.team_id;
|
|
1398
|
+
const userId = args.user_id;
|
|
1399
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1400
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1401
|
+
}
|
|
1402
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1403
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1404
|
+
}
|
|
1405
|
+
if (!userId || typeof userId !== "string") {
|
|
1406
|
+
return JSON.stringify({ error: "user_id is required and must be a string" });
|
|
1407
|
+
}
|
|
1408
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(userId)) {
|
|
1409
|
+
return JSON.stringify({ error: "user_id must be a valid UUID" });
|
|
1410
|
+
}
|
|
1411
|
+
const result = await api("POST", `/api/teams/${encodeURIComponent(teamId)}/members`, { userId });
|
|
1412
|
+
return JSON.stringify(result);
|
|
1413
|
+
}
|
|
1414
|
+
async function handleTeamRemoveMember(args) {
|
|
1415
|
+
const teamId = args.team_id;
|
|
1416
|
+
const userId = args.user_id;
|
|
1417
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1418
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1419
|
+
}
|
|
1420
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1421
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1422
|
+
}
|
|
1423
|
+
if (!userId || typeof userId !== "string") {
|
|
1424
|
+
return JSON.stringify({ error: "user_id is required and must be a string" });
|
|
1425
|
+
}
|
|
1426
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(userId)) {
|
|
1427
|
+
return JSON.stringify({ error: "user_id must be a valid UUID" });
|
|
1428
|
+
}
|
|
1429
|
+
const result = await api("DELETE", `/api/teams/${encodeURIComponent(teamId)}/members/${encodeURIComponent(userId)}`);
|
|
1430
|
+
return JSON.stringify(result);
|
|
1431
|
+
}
|
|
1432
|
+
async function handleTeamInviteMember(args) {
|
|
1433
|
+
const teamId = args.team_id;
|
|
1434
|
+
const email = args.email;
|
|
1435
|
+
const role = args.role;
|
|
1436
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1437
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1438
|
+
}
|
|
1439
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1440
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1441
|
+
}
|
|
1442
|
+
if (!email || typeof email !== "string") {
|
|
1443
|
+
return JSON.stringify({ error: "email is required and must be a string" });
|
|
1444
|
+
}
|
|
1445
|
+
if (!/^[^@]+@[^@]+\.[^@]+$/.test(email)) {
|
|
1446
|
+
return JSON.stringify({ error: "email must be a valid email address" });
|
|
1447
|
+
}
|
|
1448
|
+
if (!role || typeof role !== "string") {
|
|
1449
|
+
return JSON.stringify({ error: "role is required and must be a string" });
|
|
1450
|
+
}
|
|
1451
|
+
if (role !== "member" && role !== "admin") {
|
|
1452
|
+
return JSON.stringify({ error: "role must be 'member' or 'admin'" });
|
|
1453
|
+
}
|
|
1454
|
+
const result = await api("POST", `/api/teams/${encodeURIComponent(teamId)}/invites`, { email, role });
|
|
1455
|
+
return JSON.stringify(result);
|
|
1456
|
+
}
|
|
1457
|
+
async function handleTeamListInvites(args) {
|
|
1458
|
+
const teamId = args.team_id;
|
|
1459
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1460
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1461
|
+
}
|
|
1462
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1463
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1464
|
+
}
|
|
1465
|
+
const result = await api("GET", `/api/teams/${encodeURIComponent(teamId)}/invites`);
|
|
1466
|
+
return JSON.stringify(result);
|
|
1467
|
+
}
|
|
1468
|
+
async function handleTeamCancelInvite(args) {
|
|
1469
|
+
const teamId = args.team_id;
|
|
1470
|
+
const inviteId = args.invite_id;
|
|
1471
|
+
if (!teamId || typeof teamId !== "string") {
|
|
1472
|
+
return JSON.stringify({ error: "team_id is required and must be a string" });
|
|
1473
|
+
}
|
|
1474
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(teamId)) {
|
|
1475
|
+
return JSON.stringify({ error: "team_id must be a valid UUID" });
|
|
1476
|
+
}
|
|
1477
|
+
if (!inviteId || typeof inviteId !== "string") {
|
|
1478
|
+
return JSON.stringify({ error: "invite_id is required and must be a string" });
|
|
1479
|
+
}
|
|
1480
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(inviteId)) {
|
|
1481
|
+
return JSON.stringify({ error: "invite_id must be a valid UUID" });
|
|
1482
|
+
}
|
|
1483
|
+
const result = await api("DELETE", `/api/teams/${encodeURIComponent(teamId)}/invites/${encodeURIComponent(inviteId)}`);
|
|
1484
|
+
return JSON.stringify(result);
|
|
1485
|
+
}
|
|
1486
|
+
// -----------------------------------------------------------------------
|
|
1010
1487
|
// Dispatch table
|
|
1011
1488
|
// -----------------------------------------------------------------------
|
|
1012
1489
|
const handlers = {
|
|
1490
|
+
// Proxy (3)
|
|
1013
1491
|
dominusnode_proxied_fetch: handleProxiedFetch,
|
|
1492
|
+
dominusnode_get_proxy_config: handleGetProxyConfig,
|
|
1493
|
+
dominusnode_get_proxy_status: handleGetProxyStatus,
|
|
1494
|
+
// Wallet (7)
|
|
1014
1495
|
dominusnode_check_balance: handleCheckBalance,
|
|
1496
|
+
dominusnode_get_transactions: handleGetTransactions,
|
|
1497
|
+
dominusnode_get_forecast: handleGetForecast,
|
|
1498
|
+
dominusnode_check_payment: handleCheckPayment,
|
|
1499
|
+
dominusnode_topup_paypal: handleTopupPaypal,
|
|
1500
|
+
dominusnode_topup_stripe: handleTopupStripe,
|
|
1501
|
+
dominusnode_topup_crypto: handleTopupCrypto,
|
|
1502
|
+
// Usage (3)
|
|
1015
1503
|
dominusnode_check_usage: handleCheckUsage,
|
|
1016
|
-
|
|
1504
|
+
dominusnode_get_daily_usage: handleGetDailyUsage,
|
|
1505
|
+
dominusnode_get_top_hosts: handleGetTopHosts,
|
|
1506
|
+
// Sessions (1)
|
|
1017
1507
|
dominusnode_list_sessions: handleListSessions,
|
|
1508
|
+
// Account lifecycle (6)
|
|
1509
|
+
dominusnode_register: handleRegister,
|
|
1510
|
+
dominusnode_login: handleLogin,
|
|
1511
|
+
dominusnode_get_account_info: handleGetAccountInfo,
|
|
1512
|
+
dominusnode_verify_email: handleVerifyEmail,
|
|
1513
|
+
dominusnode_resend_verification: handleResendVerification,
|
|
1514
|
+
dominusnode_update_password: handleUpdatePassword,
|
|
1515
|
+
// API Keys (3)
|
|
1516
|
+
dominusnode_list_keys: handleListKeys,
|
|
1517
|
+
dominusnode_create_key: handleCreateKey,
|
|
1518
|
+
dominusnode_revoke_key: handleRevokeKey,
|
|
1519
|
+
// Plans (3)
|
|
1520
|
+
dominusnode_get_plan: handleGetPlan,
|
|
1521
|
+
dominusnode_list_plans: handleListPlans,
|
|
1522
|
+
dominusnode_change_plan: handleChangePlan,
|
|
1523
|
+
// Agentic wallets (7)
|
|
1018
1524
|
dominusnode_create_agentic_wallet: handleCreateAgenticWallet,
|
|
1019
1525
|
dominusnode_fund_agentic_wallet: handleFundAgenticWallet,
|
|
1020
1526
|
dominusnode_agentic_wallet_balance: handleAgenticWalletBalance,
|
|
@@ -1024,6 +1530,7 @@ export function createDominusNodeFunctionHandler(config) {
|
|
|
1024
1530
|
dominusnode_unfreeze_agentic_wallet: handleUnfreezeAgenticWallet,
|
|
1025
1531
|
dominusnode_delete_agentic_wallet: handleDeleteAgenticWallet,
|
|
1026
1532
|
dominusnode_update_wallet_policy: handleUpdateWalletPolicy,
|
|
1533
|
+
// Teams (17)
|
|
1027
1534
|
dominusnode_create_team: handleCreateTeam,
|
|
1028
1535
|
dominusnode_list_teams: handleListTeams,
|
|
1029
1536
|
dominusnode_team_details: handleTeamDetails,
|
|
@@ -1032,7 +1539,16 @@ export function createDominusNodeFunctionHandler(config) {
|
|
|
1032
1539
|
dominusnode_team_usage: handleTeamUsage,
|
|
1033
1540
|
dominusnode_update_team: handleUpdateTeam,
|
|
1034
1541
|
dominusnode_update_team_member_role: handleUpdateTeamMemberRole,
|
|
1035
|
-
|
|
1542
|
+
dominusnode_team_delete: handleTeamDelete,
|
|
1543
|
+
dominusnode_team_revoke_key: handleTeamRevokeKey,
|
|
1544
|
+
dominusnode_team_list_keys: handleTeamListKeys,
|
|
1545
|
+
dominusnode_team_list_members: handleTeamListMembers,
|
|
1546
|
+
dominusnode_team_add_member: handleTeamAddMember,
|
|
1547
|
+
dominusnode_team_remove_member: handleTeamRemoveMember,
|
|
1548
|
+
dominusnode_team_invite_member: handleTeamInviteMember,
|
|
1549
|
+
dominusnode_team_list_invites: handleTeamListInvites,
|
|
1550
|
+
dominusnode_team_cancel_invite: handleTeamCancelInvite,
|
|
1551
|
+
// x402 (1)
|
|
1036
1552
|
dominusnode_x402_info: handleX402Info,
|
|
1037
1553
|
};
|
|
1038
1554
|
async function handleX402Info() {
|
package/functions.json
CHANGED
|
@@ -415,5 +415,51 @@
|
|
|
415
415
|
},
|
|
416
416
|
"required": ["amount_cents"]
|
|
417
417
|
}
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"name": "dominusnode_topup_stripe",
|
|
421
|
+
"description": "Create a Stripe checkout session to top up your Dominus Node wallet with credit/debit card, Apple Pay, Google Pay, or Link. Returns a checkout URL. After payment, wallet is credited automatically. Minimum $5 (500 cents), maximum $1,000 (100,000 cents).",
|
|
422
|
+
"parameters": {
|
|
423
|
+
"type": "object",
|
|
424
|
+
"properties": {
|
|
425
|
+
"amount_cents": {
|
|
426
|
+
"type": "integer",
|
|
427
|
+
"description": "Amount in cents to add to wallet. Minimum 500 ($5.00), maximum 100000 ($1,000.00).",
|
|
428
|
+
"minimum": 500,
|
|
429
|
+
"maximum": 100000
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
"required": ["amount_cents"]
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"name": "dominusnode_topup_crypto",
|
|
437
|
+
"description": "Create a cryptocurrency payment invoice to top up your Dominus Node wallet. Supports BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, and LINK. Returns a payment URL with address and amount. Privacy coins (XMR, ZEC) provide anonymous billing. Minimum $5, maximum $1,000.",
|
|
438
|
+
"parameters": {
|
|
439
|
+
"type": "object",
|
|
440
|
+
"properties": {
|
|
441
|
+
"amount_usd": {
|
|
442
|
+
"type": "number",
|
|
443
|
+
"description": "Amount in USD to add to wallet. Minimum 5, maximum 1000.",
|
|
444
|
+
"minimum": 5,
|
|
445
|
+
"maximum": 1000
|
|
446
|
+
},
|
|
447
|
+
"currency": {
|
|
448
|
+
"type": "string",
|
|
449
|
+
"description": "Cryptocurrency to pay with: BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, or LINK.",
|
|
450
|
+
"enum": ["BTC", "ETH", "LTC", "XMR", "ZEC", "USDC", "SOL", "USDT", "DAI", "BNB", "LINK"]
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
"required": ["amount_usd", "currency"]
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
"name": "dominusnode_x402_info",
|
|
458
|
+
"description": "Get x402 micropayment protocol information for pay-per-request proxy access. Returns the accepted payment networks (Coinbase Base USDC, PayAI Solana USDC, Polygon, Avalanche, Sei, and more), per-request pricing, and how to use the X-PAYMENT header for zero-signup proxy access. Use this when you want to pay per-request without a wallet top-up.",
|
|
459
|
+
"parameters": {
|
|
460
|
+
"type": "object",
|
|
461
|
+
"properties": {},
|
|
462
|
+
"required": []
|
|
463
|
+
}
|
|
418
464
|
}
|
|
419
465
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dominusnode/openai-functions",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Dominus Node OpenAI-compatible function calling handler — dispatches LLM function calls to the Dominus Node REST API",
|
|
5
5
|
"main": "dist/handler.js",
|
|
6
6
|
"types": "dist/handler.d.ts",
|