@forklaunch/core 3.2.1 → 3.4.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/bin/gateway-mock/routes/payments-context.mjs +260 -0
- package/bin/gateway-mock/routes/payments.mjs +94 -1
- package/lib/agent/agent.d.ts +26 -0
- package/lib/agent/agent.d.ts.map +1 -0
- package/lib/agent/continuation.d.ts +29 -0
- package/lib/agent/continuation.d.ts.map +1 -0
- package/lib/agent/index.d.ts +8 -0
- package/lib/agent/index.d.ts.map +1 -0
- package/lib/agent/index.js +1049 -0
- package/lib/agent/index.js.map +1 -0
- package/lib/agent/index.mjs +1005 -0
- package/lib/agent/index.mjs.map +1 -0
- package/lib/agent/sources.d.ts +27 -0
- package/lib/agent/sources.d.ts.map +1 -0
- package/lib/agent/tools.d.ts +39 -0
- package/lib/agent/tools.d.ts.map +1 -0
- package/lib/agent/types.d.ts +130 -0
- package/lib/agent/types.d.ts.map +1 -0
- package/lib/http/bindRuntimeAuth.d.ts +53 -0
- package/lib/http/bindRuntimeAuth.d.ts.map +1 -0
- package/lib/http/bindRuntimeAuth.test.d.ts +2 -0
- package/lib/http/bindRuntimeAuth.test.d.ts.map +1 -0
- package/lib/http/index.d.ts +3 -0
- package/lib/http/index.d.ts.map +1 -1
- package/lib/http/index.js +487 -114
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +484 -114
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/localModelGatewayClient.d.ts +27 -0
- package/lib/http/localModelGatewayClient.d.ts.map +1 -0
- package/lib/http/mcpGenerator/mcpGenerator.d.ts.map +1 -1
- package/lib/http/middleware/internal/validationDiagnostic.d.ts +3 -0
- package/lib/http/middleware/internal/validationDiagnostic.d.ts.map +1 -0
- package/lib/http/middleware/request/auth.middleware.d.ts +0 -11
- package/lib/http/middleware/request/auth.middleware.d.ts.map +1 -1
- package/lib/http/middleware/request/parse.middleware.d.ts.map +1 -1
- package/lib/http/middleware/response/enrichExpressLikeSend.middleware.d.ts.map +1 -1
- package/lib/http/middleware/response/parse.middleware.d.ts.map +1 -1
- package/lib/http/modelGatewayClient.d.ts.map +1 -1
- package/lib/http/modelStream.d.ts +4 -0
- package/lib/http/modelStream.d.ts.map +1 -0
- package/lib/http/openApiV3Generator/openApiV3Generator.d.ts.map +1 -1
- package/lib/http/paymentsClient.d.ts +55 -1
- package/lib/http/paymentsClient.d.ts.map +1 -1
- package/lib/http/previewModelGatewayClient.d.ts +5 -1
- package/lib/http/previewModelGatewayClient.d.ts.map +1 -1
- package/lib/http/registerDelegatedSurface.d.ts +28 -0
- package/lib/http/registerDelegatedSurface.d.ts.map +1 -0
- package/lib/http/registerDelegatedSurface.test.d.ts +2 -0
- package/lib/http/registerDelegatedSurface.test.d.ts.map +1 -0
- package/lib/http/router/discriminateBody.d.ts +2 -1
- package/lib/http/router/discriminateBody.d.ts.map +1 -1
- package/lib/http/router/expressLikeRouter.d.ts.map +1 -1
- package/lib/ws/asyncApiV3Generator/asyncApiV3Generator.d.ts.map +1 -1
- package/lib/ws/index.js +94 -8
- package/lib/ws/index.js.map +1 -1
- package/lib/ws/index.mjs +94 -8
- package/lib/ws/index.mjs.map +1 -1
- package/package.json +12 -5
package/lib/http/index.mjs
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
+
// src/http/bindRuntimeAuth.ts
|
|
2
|
+
function bindRuntimeAuth(details, binding) {
|
|
3
|
+
const policy = { ...details.auth };
|
|
4
|
+
const keys = Object.keys(binding);
|
|
5
|
+
const credentials = { ...binding };
|
|
6
|
+
const invalid = () => {
|
|
7
|
+
throw new Error("Invalid runtime authentication binding");
|
|
8
|
+
};
|
|
9
|
+
const allowedPolicy = policy.scheme === "jwt" ? [
|
|
10
|
+
"scheme",
|
|
11
|
+
"headerName",
|
|
12
|
+
"tokenPrefix",
|
|
13
|
+
"sessionSchema",
|
|
14
|
+
"allowedRoles",
|
|
15
|
+
"allowedPermissions"
|
|
16
|
+
] : ["scheme", "headerName", "tokenPrefix"];
|
|
17
|
+
if (Object.keys(policy).some((key) => !allowedPolicy.includes(key)))
|
|
18
|
+
invalid();
|
|
19
|
+
for (const key of ["headerName", "tokenPrefix"]) {
|
|
20
|
+
if (policy[key] !== void 0 && (typeof policy[key] !== "string" || !policy[key]))
|
|
21
|
+
invalid();
|
|
22
|
+
}
|
|
23
|
+
if (policy.scheme === "jwt" && policy.allowedRoles === void 0 && policy.allowedPermissions === void 0)
|
|
24
|
+
invalid();
|
|
25
|
+
let authentication;
|
|
26
|
+
if (policy.scheme === "jwt") {
|
|
27
|
+
if (keys.some(
|
|
28
|
+
(key) => !["jwksPublicKeyUrl", "signatureKey", "decodeResource"].includes(key)
|
|
29
|
+
))
|
|
30
|
+
invalid();
|
|
31
|
+
const keyFields = keys.filter((key) => key !== "decodeResource");
|
|
32
|
+
if (keyFields.length !== 1 || typeof credentials[keyFields[0]] !== "string" || !credentials[keyFields[0]])
|
|
33
|
+
invalid();
|
|
34
|
+
const decodeResource = credentials.decodeResource;
|
|
35
|
+
if (decodeResource !== void 0 && typeof decodeResource !== "function")
|
|
36
|
+
invalid();
|
|
37
|
+
delete credentials.decodeResource;
|
|
38
|
+
authentication = {
|
|
39
|
+
jwt: credentials,
|
|
40
|
+
...decodeResource === void 0 ? {} : { decodeResource }
|
|
41
|
+
};
|
|
42
|
+
} else if (policy.scheme === "hmac") {
|
|
43
|
+
if (keys.length !== 1 || keys[0] !== "secretKeys" || !credentials.secretKeys || typeof credentials.secretKeys !== "object" || Array.isArray(credentials.secretKeys) || Object.keys(credentials.secretKeys).length === 0 || Object.values(credentials.secretKeys).some(
|
|
44
|
+
(key) => typeof key !== "string" || !key
|
|
45
|
+
))
|
|
46
|
+
invalid();
|
|
47
|
+
authentication = { hmac: credentials };
|
|
48
|
+
} else {
|
|
49
|
+
return invalid();
|
|
50
|
+
}
|
|
51
|
+
delete policy.scheme;
|
|
52
|
+
for (const key of ["allowedRoles", "allowedPermissions"]) {
|
|
53
|
+
if (policy[key] !== void 0) {
|
|
54
|
+
const values = policy[key];
|
|
55
|
+
if (!Array.isArray(values) || values.some((value) => typeof value !== "string"))
|
|
56
|
+
invalid();
|
|
57
|
+
policy[key] = new Set(values);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { ...details, auth: { ...policy, ...authentication } };
|
|
61
|
+
}
|
|
62
|
+
|
|
1
63
|
// src/http/middleware/request/cors.middleware.ts
|
|
2
64
|
import corsMiddleware from "cors";
|
|
3
65
|
function cors(corsOptions) {
|
|
@@ -473,7 +535,7 @@ function createContext(schemaValidator) {
|
|
|
473
535
|
}
|
|
474
536
|
|
|
475
537
|
// src/http/router/discriminateBody.ts
|
|
476
|
-
function discriminateBody(schemaValidator, body) {
|
|
538
|
+
function discriminateBody(schemaValidator, body, inputProjection) {
|
|
477
539
|
if (body == null) {
|
|
478
540
|
return void 0;
|
|
479
541
|
}
|
|
@@ -523,7 +585,7 @@ function discriminateBody(schemaValidator, body) {
|
|
|
523
585
|
parserType: "text",
|
|
524
586
|
schema: maybeTypedBody
|
|
525
587
|
};
|
|
526
|
-
} else if (schemaValidator.openapi(maybeTypedBody).format === "binary") {
|
|
588
|
+
} else if ((inputProjection ?? schemaValidator.openapi(maybeTypedBody)).format === "binary") {
|
|
527
589
|
return {
|
|
528
590
|
contentType: "application/octet-stream",
|
|
529
591
|
parserType: "file",
|
|
@@ -955,15 +1017,23 @@ async function checkAuthorizationToken(req, authorizationMethod, authorizationTo
|
|
|
955
1017
|
if (!parsedKeyId || !parsedTimestamp || !parsedNonce || !parsedSignature) {
|
|
956
1018
|
return invalidAuthorizationTokenFormat;
|
|
957
1019
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1020
|
+
let verificationResult = false;
|
|
1021
|
+
const signedPaths = hmacSignedPaths(req);
|
|
1022
|
+
for (const path of signedPaths) {
|
|
1023
|
+
verificationResult = Boolean(await auth.verificationFunction({
|
|
1024
|
+
method: req?.method ?? "",
|
|
1025
|
+
path,
|
|
1026
|
+
body: req?._rawBody ?? req?.body,
|
|
1027
|
+
timestamp: new Date(parsedTimestamp),
|
|
1028
|
+
nonce: parsedNonce,
|
|
1029
|
+
signature: parsedSignature,
|
|
1030
|
+
secretKey: collapsedAuthorizationMethod.hmac.secretKeys[parsedKeyId]
|
|
1031
|
+
}));
|
|
1032
|
+
if (verificationResult) {
|
|
1033
|
+
if (path !== signedPaths[0]) warnMountRelativeHmacPath();
|
|
1034
|
+
break;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
967
1037
|
if (!verificationResult) {
|
|
968
1038
|
return invalidAuthorizationSignature;
|
|
969
1039
|
}
|
|
@@ -1130,6 +1200,25 @@ async function checkAuthorizationToken(req, authorizationMethod, authorizationTo
|
|
|
1130
1200
|
}
|
|
1131
1201
|
}
|
|
1132
1202
|
}
|
|
1203
|
+
function acceptMountRelativeHmacPaths() {
|
|
1204
|
+
const value = typeof process === "undefined" ? void 0 : process.env?.HMAC_ACCEPT_MOUNT_RELATIVE_PATHS;
|
|
1205
|
+
return value == null || !["false", "0"].includes(value.trim().toLowerCase());
|
|
1206
|
+
}
|
|
1207
|
+
var warnedMountRelativeHmacPath = false;
|
|
1208
|
+
function warnMountRelativeHmacPath() {
|
|
1209
|
+
if (warnedMountRelativeHmacPath) return;
|
|
1210
|
+
warnedMountRelativeHmacPath = true;
|
|
1211
|
+
console.warn(
|
|
1212
|
+
"Accepted an HMAC signature over the router-relative path. Sign the full request path instead; set HMAC_ACCEPT_MOUNT_RELATIVE_PATHS=false to reject the deprecated form."
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
function hmacSignedPaths(req) {
|
|
1216
|
+
const relative = req?.path ?? "";
|
|
1217
|
+
const wire = (req?.originalUrl ?? req?.url ?? relative).split("?")[0] || relative;
|
|
1218
|
+
const paths = [wire];
|
|
1219
|
+
if (relative !== wire && acceptMountRelativeHmacPaths()) paths.push(relative);
|
|
1220
|
+
return paths;
|
|
1221
|
+
}
|
|
1133
1222
|
async function parseRequestAuth(req, res, next) {
|
|
1134
1223
|
const access = req.contractDetails.access;
|
|
1135
1224
|
if (access === "public") {
|
|
@@ -1367,6 +1456,21 @@ function isRequestShape(maybeResponseShape) {
|
|
|
1367
1456
|
return maybeResponseShape != null && ("body" in maybeResponseShape || "query" in maybeResponseShape || "params" in maybeResponseShape || "headers" in maybeResponseShape);
|
|
1368
1457
|
}
|
|
1369
1458
|
|
|
1459
|
+
// src/http/middleware/internal/validationDiagnostic.ts
|
|
1460
|
+
var sendingDiagnostics = /* @__PURE__ */ new WeakSet();
|
|
1461
|
+
function isValidationDiagnostic(response) {
|
|
1462
|
+
return sendingDiagnostics.has(response);
|
|
1463
|
+
}
|
|
1464
|
+
function sendValidationDiagnostic(response, send) {
|
|
1465
|
+
const alreadySending = sendingDiagnostics.has(response);
|
|
1466
|
+
sendingDiagnostics.add(response);
|
|
1467
|
+
try {
|
|
1468
|
+
return send();
|
|
1469
|
+
} finally {
|
|
1470
|
+
if (!alreadySending) sendingDiagnostics.delete(response);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1370
1474
|
// src/http/middleware/request/parse.middleware.ts
|
|
1371
1475
|
function parse(req, res, next) {
|
|
1372
1476
|
const globalOptions = req._globalOptions?.();
|
|
@@ -1448,14 +1552,13 @@ function parse(req, res, next) {
|
|
|
1448
1552
|
default:
|
|
1449
1553
|
case void 0:
|
|
1450
1554
|
case "error":
|
|
1451
|
-
res.type("
|
|
1555
|
+
res.type("text/plain");
|
|
1452
1556
|
res.status(400);
|
|
1453
1557
|
if (hasSend(res)) {
|
|
1454
|
-
|
|
1455
|
-
`${collectedParseErrors ?? prettyPrintParseErrors2(parsedRequest.errors, "Request")}
|
|
1558
|
+
const diagnostic = `${collectedParseErrors ?? prettyPrintParseErrors2(parsedRequest.errors, "Request")}
|
|
1456
1559
|
|
|
1457
|
-
Correlation id: ${req.context.correlationId ?? "No correlation ID"}
|
|
1458
|
-
);
|
|
1560
|
+
Correlation id: ${req.context.correlationId ?? "No correlation ID"}`;
|
|
1561
|
+
sendValidationDiagnostic(res, () => res.send(diagnostic));
|
|
1459
1562
|
} else {
|
|
1460
1563
|
next?.(new Error("Request is not sendable."));
|
|
1461
1564
|
}
|
|
@@ -1864,13 +1967,25 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
1864
1967
|
span: void 0
|
|
1865
1968
|
},
|
|
1866
1969
|
_rawBody: void 0,
|
|
1867
|
-
_parsedVersions: void 0
|
|
1970
|
+
_parsedVersions: void 0,
|
|
1971
|
+
// hyper-express's content parser reads the body through its Request's
|
|
1972
|
+
// body readers; serve the body the call was given.
|
|
1973
|
+
buffer: async () => Buffer.from(
|
|
1974
|
+
typeof req.body === "string" ? req.body : JSON.stringify(req.body)
|
|
1975
|
+
),
|
|
1976
|
+
json: async () => req.body,
|
|
1977
|
+
text: async () => typeof req.body === "string" ? req.body : JSON.stringify(req.body)
|
|
1868
1978
|
};
|
|
1869
1979
|
const res = {
|
|
1870
1980
|
statusCode: 200,
|
|
1981
|
+
// hyper-express's response enrichment reads the status and headers
|
|
1982
|
+
// from these fields, which its own Response keeps.
|
|
1983
|
+
_status_code: 200,
|
|
1984
|
+
_headers: responseHeaders,
|
|
1871
1985
|
status: (code) => {
|
|
1872
1986
|
statusCode = code;
|
|
1873
1987
|
res.statusCode = code;
|
|
1988
|
+
res._status_code = code;
|
|
1874
1989
|
return res;
|
|
1875
1990
|
},
|
|
1876
1991
|
send: (message) => {
|
|
@@ -1890,6 +2005,8 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
1890
2005
|
return res;
|
|
1891
2006
|
},
|
|
1892
2007
|
getHeader: (key) => responseHeaders[key],
|
|
2008
|
+
getHeaders: () => ({ ...responseHeaders }),
|
|
2009
|
+
locals: {},
|
|
1893
2010
|
type: (contentType) => {
|
|
1894
2011
|
responseHeaders["content-type"] = contentType;
|
|
1895
2012
|
return res;
|
|
@@ -1908,31 +2025,59 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
|
1908
2025
|
version
|
|
1909
2026
|
};
|
|
1910
2027
|
const executeMiddlewares = request?.executeMiddlewares ?? false;
|
|
2028
|
+
const cHandler = controllerHandler;
|
|
1911
2029
|
if (executeMiddlewares && middlewares.length > 0) {
|
|
1912
|
-
const
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
2030
|
+
const chain = middlewares;
|
|
2031
|
+
await new Promise((resolve, reject) => {
|
|
2032
|
+
let settled = false;
|
|
2033
|
+
let responded = false;
|
|
2034
|
+
let controllerStarted = false;
|
|
2035
|
+
const finish = (error) => {
|
|
2036
|
+
if (settled) return;
|
|
2037
|
+
settled = true;
|
|
2038
|
+
if (error) reject(error);
|
|
2039
|
+
else resolve();
|
|
2040
|
+
};
|
|
2041
|
+
res.on("finish", () => {
|
|
2042
|
+
responded = true;
|
|
2043
|
+
if (!controllerStarted) finish();
|
|
2044
|
+
});
|
|
2045
|
+
const run = async (index) => {
|
|
2046
|
+
try {
|
|
2047
|
+
if (index === chain.length) {
|
|
2048
|
+
controllerStarted = true;
|
|
2049
|
+
await cHandler(req, res, (err) => {
|
|
2050
|
+
if (err) {
|
|
2051
|
+
throw err;
|
|
2052
|
+
}
|
|
2053
|
+
});
|
|
2054
|
+
finish();
|
|
2055
|
+
return;
|
|
1919
2056
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2057
|
+
let calledNext = false;
|
|
2058
|
+
await chain[index](req, res, (err) => {
|
|
2059
|
+
calledNext = true;
|
|
2060
|
+
if (err) {
|
|
2061
|
+
throw err;
|
|
2062
|
+
}
|
|
2063
|
+
return run(index + 1);
|
|
2064
|
+
});
|
|
2065
|
+
if (!calledNext && chain[index].length < 3 && !responded) {
|
|
2066
|
+
await run(index + 1);
|
|
2067
|
+
}
|
|
2068
|
+
} catch (error) {
|
|
2069
|
+
finish(error);
|
|
1926
2070
|
}
|
|
1927
|
-
}
|
|
1928
|
-
|
|
2071
|
+
};
|
|
2072
|
+
void run(0);
|
|
2073
|
+
});
|
|
2074
|
+
} else {
|
|
2075
|
+
await cHandler(req, res, (err) => {
|
|
2076
|
+
if (err) {
|
|
2077
|
+
throw err;
|
|
2078
|
+
}
|
|
2079
|
+
});
|
|
1929
2080
|
}
|
|
1930
|
-
const cHandler = controllerHandler;
|
|
1931
|
-
await cHandler(req, res, (err) => {
|
|
1932
|
-
if (err) {
|
|
1933
|
-
throw err;
|
|
1934
|
-
}
|
|
1935
|
-
});
|
|
1936
2081
|
return {
|
|
1937
2082
|
code: Number(statusCode),
|
|
1938
2083
|
response: responseMessage,
|
|
@@ -2716,12 +2861,55 @@ function signPlatformEvent(params) {
|
|
|
2716
2861
|
});
|
|
2717
2862
|
}
|
|
2718
2863
|
|
|
2864
|
+
// src/http/modelStream.ts
|
|
2865
|
+
async function* readModelStream(response) {
|
|
2866
|
+
const reader = response.body?.getReader();
|
|
2867
|
+
if (!reader)
|
|
2868
|
+
throw new ModelGatewayRequestError(502, "The model stream is empty.");
|
|
2869
|
+
const decoder = new TextDecoder();
|
|
2870
|
+
let buffer = "", bytes = 0;
|
|
2871
|
+
try {
|
|
2872
|
+
for (; ; ) {
|
|
2873
|
+
const part = await reader.read();
|
|
2874
|
+
if (part.done) break;
|
|
2875
|
+
bytes += part.value.byteLength;
|
|
2876
|
+
if (bytes > 512e3) throw new Error("oversized");
|
|
2877
|
+
buffer += decoder.decode(part.value, { stream: true });
|
|
2878
|
+
let match;
|
|
2879
|
+
while (match = buffer.match(/\r?\n\r?\n/)) {
|
|
2880
|
+
const event = buffer.slice(0, match.index);
|
|
2881
|
+
buffer = buffer.slice(match.index + match[0].length);
|
|
2882
|
+
const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n");
|
|
2883
|
+
if (!data) continue;
|
|
2884
|
+
if (data === "[DONE]") return;
|
|
2885
|
+
const value = JSON.parse(data);
|
|
2886
|
+
if (value.error || !Array.isArray(value.choices))
|
|
2887
|
+
throw new Error("invalid");
|
|
2888
|
+
yield value;
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
throw new Error("interrupted");
|
|
2892
|
+
} catch {
|
|
2893
|
+
throw new ModelGatewayRequestError(
|
|
2894
|
+
502,
|
|
2895
|
+
"The model stream was interrupted. No automatic retry was sent."
|
|
2896
|
+
);
|
|
2897
|
+
} finally {
|
|
2898
|
+
await reader.cancel().catch(() => {
|
|
2899
|
+
});
|
|
2900
|
+
reader.releaseLock();
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2719
2904
|
// src/http/modelGatewayClient.ts
|
|
2720
2905
|
var ModelGatewayRequestError = class extends InstanceGatewayRequestError {
|
|
2721
2906
|
name = "ModelGatewayRequestError";
|
|
2722
2907
|
};
|
|
2723
2908
|
function createModelGatewayClient(options2 = {}) {
|
|
2724
|
-
const transport = createInstanceGatewayTransport(
|
|
2909
|
+
const transport = createInstanceGatewayTransport(
|
|
2910
|
+
options2,
|
|
2911
|
+
"The model gateway"
|
|
2912
|
+
);
|
|
2725
2913
|
async function send(method, route, body, signal) {
|
|
2726
2914
|
try {
|
|
2727
2915
|
return await transport.request(method, route, body, { signal });
|
|
@@ -2757,42 +2945,12 @@ function createModelGatewayClient(options2 = {}) {
|
|
|
2757
2945
|
request,
|
|
2758
2946
|
streamOptions.signal
|
|
2759
2947
|
);
|
|
2760
|
-
|
|
2761
|
-
for await (const data of sseData(response.body)) {
|
|
2762
|
-
if (data === "[DONE]") return;
|
|
2763
|
-
try {
|
|
2764
|
-
yield JSON.parse(data);
|
|
2765
|
-
} catch {
|
|
2766
|
-
}
|
|
2767
|
-
}
|
|
2948
|
+
yield* readModelStream(response);
|
|
2768
2949
|
}
|
|
2769
2950
|
}
|
|
2770
2951
|
}
|
|
2771
2952
|
};
|
|
2772
2953
|
}
|
|
2773
|
-
async function* sseData(stream) {
|
|
2774
|
-
const decoder = new TextDecoder();
|
|
2775
|
-
let buffer = "";
|
|
2776
|
-
const reader = stream.getReader();
|
|
2777
|
-
try {
|
|
2778
|
-
for (; ; ) {
|
|
2779
|
-
const { value, done } = await reader.read();
|
|
2780
|
-
if (done) break;
|
|
2781
|
-
buffer += decoder.decode(value, { stream: true });
|
|
2782
|
-
let boundary;
|
|
2783
|
-
while ((boundary = buffer.search(/\r?\n\r?\n/)) !== -1) {
|
|
2784
|
-
const event = buffer.slice(0, boundary);
|
|
2785
|
-
buffer = buffer.slice(boundary).replace(/^\r?\n\r?\n/, "");
|
|
2786
|
-
const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n");
|
|
2787
|
-
if (data) yield data;
|
|
2788
|
-
}
|
|
2789
|
-
}
|
|
2790
|
-
const tail = buffer.trim();
|
|
2791
|
-
if (tail.startsWith("data:")) yield tail.slice(5).trimStart();
|
|
2792
|
-
} finally {
|
|
2793
|
-
reader.releaseLock();
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
2954
|
|
|
2797
2955
|
// src/http/previewModelGatewayClient.ts
|
|
2798
2956
|
function record(value) {
|
|
@@ -2848,9 +3006,9 @@ function createPreviewModelGatewayClient(options2 = {}) {
|
|
|
2848
3006
|
options2,
|
|
2849
3007
|
"The local preview model gateway"
|
|
2850
3008
|
);
|
|
2851
|
-
async function send(method, route, body) {
|
|
3009
|
+
async function send(method, route, body, signal) {
|
|
2852
3010
|
try {
|
|
2853
|
-
return await transport.request(method, route, body);
|
|
3011
|
+
return await transport.request(method, route, body, { signal });
|
|
2854
3012
|
} catch (error) {
|
|
2855
3013
|
if (error instanceof InstanceGatewayRequestError)
|
|
2856
3014
|
throw new ModelGatewayRequestError(
|
|
@@ -2868,6 +3026,15 @@ function createPreviewModelGatewayClient(options2 = {}) {
|
|
|
2868
3026
|
},
|
|
2869
3027
|
chat: {
|
|
2870
3028
|
completions: {
|
|
3029
|
+
async *stream(request, options3 = {}) {
|
|
3030
|
+
const response = await send(
|
|
3031
|
+
"POST",
|
|
3032
|
+
"/models/chat/completions",
|
|
3033
|
+
{ ...request, stream: true },
|
|
3034
|
+
options3.signal
|
|
3035
|
+
);
|
|
3036
|
+
yield* readModelStream(response);
|
|
3037
|
+
},
|
|
2871
3038
|
async create(request) {
|
|
2872
3039
|
return await (await send(
|
|
2873
3040
|
"POST",
|
|
@@ -3401,6 +3568,19 @@ function createPaymentsClient(options2 = {}) {
|
|
|
3401
3568
|
},
|
|
3402
3569
|
status() {
|
|
3403
3570
|
return call("GET", "/payments/status");
|
|
3571
|
+
},
|
|
3572
|
+
payouts(params = {}) {
|
|
3573
|
+
const { limit } = params;
|
|
3574
|
+
if (limit !== void 0 && (!Number.isInteger(limit) || limit < 1 || limit > 50)) {
|
|
3575
|
+
throw new TypeError("limit must be a whole number from 1 to 50");
|
|
3576
|
+
}
|
|
3577
|
+
return call(
|
|
3578
|
+
"GET",
|
|
3579
|
+
limit === void 0 ? "/payments/payouts" : `/payments/payouts?limit=${limit}`
|
|
3580
|
+
);
|
|
3581
|
+
},
|
|
3582
|
+
dashboardLink() {
|
|
3583
|
+
return call("POST", "/payments/dashboard-link", {});
|
|
3404
3584
|
}
|
|
3405
3585
|
};
|
|
3406
3586
|
}
|
|
@@ -3420,7 +3600,7 @@ function loadStripe() {
|
|
|
3420
3600
|
function stripeGatewayFetch(settings, fetchImpl = fetch) {
|
|
3421
3601
|
const base = new URL(settings.gatewayUrl);
|
|
3422
3602
|
const basePath = base.pathname.replace(/\/+$/, "");
|
|
3423
|
-
|
|
3603
|
+
const signedFetch = async (input, init = {}) => {
|
|
3424
3604
|
const original = new URL(
|
|
3425
3605
|
typeof input === "string" || input instanceof URL ? input : input.url
|
|
3426
3606
|
);
|
|
@@ -3460,6 +3640,13 @@ function stripeGatewayFetch(settings, fetchImpl = fetch) {
|
|
|
3460
3640
|
}
|
|
3461
3641
|
);
|
|
3462
3642
|
};
|
|
3643
|
+
const preconnect = Reflect.get(fetchImpl, "preconnect");
|
|
3644
|
+
if (typeof preconnect === "function") {
|
|
3645
|
+
Object.defineProperty(signedFetch, "preconnect", {
|
|
3646
|
+
value: (_input, options2) => Reflect.apply(preconnect, fetchImpl, [base.origin, options2])
|
|
3647
|
+
});
|
|
3648
|
+
}
|
|
3649
|
+
return signedFetch;
|
|
3463
3650
|
}
|
|
3464
3651
|
function createStripeClient(options2 = {}) {
|
|
3465
3652
|
const StripeClass = options2.Stripe ?? loadStripe();
|
|
@@ -3478,8 +3665,8 @@ function createStripeClient(options2 = {}) {
|
|
|
3478
3665
|
return new StripeClass(options2.apiKey, options2.config);
|
|
3479
3666
|
}
|
|
3480
3667
|
const settings = instanceGatewaySettings(options2, "Payments");
|
|
3481
|
-
const
|
|
3482
|
-
const protocol =
|
|
3668
|
+
const gateway2 = new URL(settings.gatewayUrl);
|
|
3669
|
+
const protocol = gateway2.protocol === "http:" ? "http" : "https";
|
|
3483
3670
|
return new StripeClass(
|
|
3484
3671
|
// No key: the authenticator below replaces it, and the gateway holds the
|
|
3485
3672
|
// real one. (stripe-node accepts an authenticator in place of a key.)
|
|
@@ -3487,8 +3674,8 @@ function createStripeClient(options2 = {}) {
|
|
|
3487
3674
|
{
|
|
3488
3675
|
maxNetworkRetries: 2,
|
|
3489
3676
|
...options2.config,
|
|
3490
|
-
host:
|
|
3491
|
-
port:
|
|
3677
|
+
host: gateway2.hostname,
|
|
3678
|
+
port: gateway2.port || (protocol === "http" ? 80 : 443),
|
|
3492
3679
|
protocol,
|
|
3493
3680
|
telemetry: false,
|
|
3494
3681
|
// The signed fetch sets `authorization`; nothing else may.
|
|
@@ -4692,10 +4879,10 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4692
4879
|
let bodySchema;
|
|
4693
4880
|
let responsesSchemas;
|
|
4694
4881
|
if (route.contractDetails.versions) {
|
|
4695
|
-
const version2 = route.contractDetails.versions[index];
|
|
4882
|
+
const version2 = Object.values(route.contractDetails.versions)[index];
|
|
4883
|
+
responsesSchemas = version2.responses;
|
|
4696
4884
|
if (version2.body && schemaValidator.parse(inputSchema, args).ok) {
|
|
4697
4885
|
bodySchema = version2.body;
|
|
4698
|
-
responsesSchemas = version2.responses;
|
|
4699
4886
|
}
|
|
4700
4887
|
} else {
|
|
4701
4888
|
bodySchema = route.contractDetails.body;
|
|
@@ -4706,7 +4893,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4706
4893
|
if (discriminatedBody) {
|
|
4707
4894
|
switch (discriminatedBody.parserType) {
|
|
4708
4895
|
case "json": {
|
|
4709
|
-
parsedBody =
|
|
4896
|
+
parsedBody = body === void 0 ? void 0 : JSON.stringify(body);
|
|
4710
4897
|
break;
|
|
4711
4898
|
}
|
|
4712
4899
|
case "text": {
|
|
@@ -4772,11 +4959,11 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
|
4772
4959
|
).toString();
|
|
4773
4960
|
url += queryString ? `?${queryString}` : "";
|
|
4774
4961
|
}
|
|
4775
|
-
const response = await fetch(
|
|
4962
|
+
const response = await fetch(url, {
|
|
4776
4963
|
method: route.method.toUpperCase(),
|
|
4777
4964
|
headers: {
|
|
4778
4965
|
...headers,
|
|
4779
|
-
...discriminatedBody?.contentType != "multipart/form-data" ? {
|
|
4966
|
+
...discriminatedBody?.contentType != "multipart/form-data" && (contentType ?? discriminatedBody?.contentType) !== void 0 ? {
|
|
4780
4967
|
"Content-Type": contentType ?? discriminatedBody?.contentType
|
|
4781
4968
|
} : {}
|
|
4782
4969
|
},
|
|
@@ -4856,7 +5043,12 @@ function isResponseCompiledSchema(schema) {
|
|
|
4856
5043
|
}
|
|
4857
5044
|
|
|
4858
5045
|
// src/http/middleware/response/parse.middleware.ts
|
|
5046
|
+
var sendingValidationError = /* @__PURE__ */ new WeakSet();
|
|
4859
5047
|
function parse2(req, res, next) {
|
|
5048
|
+
if (sendingValidationError.has(res)) {
|
|
5049
|
+
next?.();
|
|
5050
|
+
return;
|
|
5051
|
+
}
|
|
4860
5052
|
let headers;
|
|
4861
5053
|
let responses;
|
|
4862
5054
|
const globalOptions = req._globalOptions?.();
|
|
@@ -4899,15 +5091,35 @@ function parse2(req, res, next) {
|
|
|
4899
5091
|
responses = responseSchemas.responses;
|
|
4900
5092
|
}
|
|
4901
5093
|
const statusCode = Number(res.statusCode);
|
|
4902
|
-
const
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
5094
|
+
const defaultErrorStatus = [400, 401, 404, 403, 500].includes(statusCode);
|
|
5095
|
+
const missingResponseSchema = !defaultErrorStatus && !Object.prototype.hasOwnProperty.call(responses, statusCode);
|
|
5096
|
+
if (missingResponseSchema && collapsedOptions !== "warning") {
|
|
5097
|
+
throw new Error(`Undocumented response status ${statusCode}`);
|
|
5098
|
+
}
|
|
5099
|
+
const declaredResponse = responses?.[statusCode];
|
|
5100
|
+
const defaultErrorResponse = () => {
|
|
5101
|
+
try {
|
|
5102
|
+
return schemaValidator.parse(
|
|
5103
|
+
schemaValidator.union([schemaValidator.string, declaredResponse]),
|
|
5104
|
+
res.bodyData
|
|
5105
|
+
);
|
|
5106
|
+
} catch (error) {
|
|
5107
|
+
if (declaredResponse === void 0) throw error;
|
|
5108
|
+
const declared = schemaValidator.parse(declaredResponse, res.bodyData);
|
|
5109
|
+
if (declared.ok) return declared;
|
|
5110
|
+
const message = schemaValidator.parse(
|
|
5111
|
+
schemaValidator.string,
|
|
5112
|
+
res.bodyData
|
|
5113
|
+
);
|
|
5114
|
+
return message.ok ? message : declared;
|
|
5115
|
+
}
|
|
5116
|
+
};
|
|
5117
|
+
const parsedResponse = missingResponseSchema ? { ok: true } : defaultErrorStatus ? defaultErrorResponse() : schemaValidator.parse(declaredResponse, res.bodyData);
|
|
4906
5118
|
const parsedHeaders = schemaValidator.parse(
|
|
4907
5119
|
headers ?? schemaValidator.unknown,
|
|
4908
5120
|
res.getHeaders()
|
|
4909
5121
|
);
|
|
4910
|
-
const parseErrors = [];
|
|
5122
|
+
const parseErrors = missingResponseSchema ? [`Response: Undocumented response status ${statusCode}`] : [];
|
|
4911
5123
|
if (!parsedHeaders.ok) {
|
|
4912
5124
|
const headerErrors = prettyPrintParseErrors3(parsedHeaders.errors, "Header");
|
|
4913
5125
|
if (headerErrors) {
|
|
@@ -4924,21 +5136,26 @@ function parse2(req, res, next) {
|
|
|
4924
5136
|
}
|
|
4925
5137
|
}
|
|
4926
5138
|
if (parseErrors.length > 0) {
|
|
4927
|
-
switch (
|
|
5139
|
+
switch (collapsedOptions) {
|
|
4928
5140
|
default:
|
|
4929
5141
|
case void 0:
|
|
4930
5142
|
case "error":
|
|
4931
5143
|
res.type("text/plain");
|
|
4932
5144
|
res.status(500);
|
|
4933
5145
|
if (hasSend(res)) {
|
|
4934
|
-
|
|
4935
|
-
|
|
5146
|
+
sendingValidationError.add(res);
|
|
5147
|
+
try {
|
|
5148
|
+
res.send(
|
|
5149
|
+
`Invalid response:
|
|
4936
5150
|
${parseErrors.join(
|
|
4937
|
-
|
|
4938
|
-
|
|
5151
|
+
"\n\n"
|
|
5152
|
+
)}
|
|
4939
5153
|
|
|
4940
5154
|
Correlation id: ${req.context.correlationId ?? "No correlation ID"}`
|
|
4941
|
-
|
|
5155
|
+
);
|
|
5156
|
+
} finally {
|
|
5157
|
+
sendingValidationError.delete(res);
|
|
5158
|
+
}
|
|
4942
5159
|
} else {
|
|
4943
5160
|
next?.(new Error("Response is not sendable."));
|
|
4944
5161
|
}
|
|
@@ -4949,8 +5166,6 @@ Correlation id: ${req.context.correlationId ?? "No correlation ID"}`
|
|
|
4949
5166
|
${parseErrors.join("\n\n")}`
|
|
4950
5167
|
);
|
|
4951
5168
|
break;
|
|
4952
|
-
case "none":
|
|
4953
|
-
break;
|
|
4954
5169
|
}
|
|
4955
5170
|
}
|
|
4956
5171
|
next?.();
|
|
@@ -5004,6 +5219,10 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
|
5004
5219
|
originalSend.call(instance, data);
|
|
5005
5220
|
return;
|
|
5006
5221
|
}
|
|
5222
|
+
if (typeof data === "string" && isValidationDiagnostic(res)) {
|
|
5223
|
+
originalSend.call(instance, data);
|
|
5224
|
+
return;
|
|
5225
|
+
}
|
|
5007
5226
|
let responses;
|
|
5008
5227
|
if (req.contractDetails.responses == null && (req.contractDetails.versions == null || Object.values(req.contractDetails.versions).some(
|
|
5009
5228
|
(version) => version?.responses == null
|
|
@@ -5013,7 +5232,7 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
|
5013
5232
|
if (req.contractDetails.responses != null) {
|
|
5014
5233
|
responses = req.contractDetails.responses;
|
|
5015
5234
|
} else {
|
|
5016
|
-
responses = req.contractDetails.versions[req.version]
|
|
5235
|
+
responses = req.contractDetails.versions[req.version]?.responses ?? {};
|
|
5017
5236
|
}
|
|
5018
5237
|
}
|
|
5019
5238
|
const responseBodies = discriminateResponseBodies(
|
|
@@ -5235,7 +5454,16 @@ function generateOperationObject(schemaValidator, path, method, controllerName,
|
|
|
5235
5454
|
for (const key in discriminatedResponseBodiesResult) {
|
|
5236
5455
|
coercedResponses[key] = {
|
|
5237
5456
|
description: httpStatusCodes_default[key],
|
|
5238
|
-
|
|
5457
|
+
// Undefined/void represent no response body, not a JSON null payload.
|
|
5458
|
+
// Check the schema kind rather than its OpenAPI projection: null and
|
|
5459
|
+
// nullish also project to null but still admit an actual JSON body.
|
|
5460
|
+
content: schemaValidator.undefined !== void 0 && typedSchemaValidator.isInstanceOf(
|
|
5461
|
+
discriminatedResponseBodiesResult[key].schema,
|
|
5462
|
+
schemaValidator.undefined
|
|
5463
|
+
) || schemaValidator.void !== void 0 && typedSchemaValidator.isInstanceOf(
|
|
5464
|
+
discriminatedResponseBodiesResult[key].schema,
|
|
5465
|
+
schemaValidator.void
|
|
5466
|
+
) ? void 0 : contentResolver(
|
|
5239
5467
|
schemaValidator,
|
|
5240
5468
|
discriminatedResponseBodiesResult[key].schema,
|
|
5241
5469
|
discriminatedResponseBodiesResult[key].contentType
|
|
@@ -5271,15 +5499,21 @@ function generateOperationObject(schemaValidator, path, method, controllerName,
|
|
|
5271
5499
|
operationObject.parameters?.push({
|
|
5272
5500
|
name: key,
|
|
5273
5501
|
in: "path",
|
|
5502
|
+
required: true,
|
|
5274
5503
|
schema: typedSchemaValidator.openapi(params[key])
|
|
5275
5504
|
});
|
|
5276
5505
|
}
|
|
5277
5506
|
}
|
|
5278
|
-
const
|
|
5507
|
+
const adapter = schemaValidator;
|
|
5508
|
+
const bareProjection = body && adapter.isSchema(body) ? adapter.openapiRequestBody?.(body) : void 0;
|
|
5509
|
+
const discriminatedBodyResult = body ? discriminateBody(schemaValidator, body, bareProjection?.schema) : null;
|
|
5279
5510
|
if (discriminatedBodyResult) {
|
|
5511
|
+
const projection = bareProjection ?? adapter.openapiRequestBody?.(discriminatedBodyResult.schema);
|
|
5280
5512
|
operationObject.requestBody = {
|
|
5281
|
-
required: true,
|
|
5282
|
-
content:
|
|
5513
|
+
required: projection?.required ?? true,
|
|
5514
|
+
content: projection ? {
|
|
5515
|
+
[discriminatedBodyResult.contentType]: { schema: projection.schema }
|
|
5516
|
+
} : contentResolver(
|
|
5283
5517
|
schemaValidator,
|
|
5284
5518
|
discriminatedBodyResult.schema,
|
|
5285
5519
|
discriminatedBodyResult.contentType
|
|
@@ -5314,25 +5548,14 @@ function generateOperationObject(schemaValidator, path, method, controllerName,
|
|
|
5314
5548
|
content: contentResolver(schemaValidator, schemaValidator.string)
|
|
5315
5549
|
};
|
|
5316
5550
|
if ("basic" in auth) {
|
|
5317
|
-
operationObject.security = [
|
|
5318
|
-
{
|
|
5319
|
-
basic: Array.from(
|
|
5320
|
-
"allowedPermissions" in auth && auth.allowedPermissions instanceof Set ? auth.allowedPermissions.values() : []
|
|
5321
|
-
)
|
|
5322
|
-
}
|
|
5323
|
-
];
|
|
5551
|
+
operationObject.security = [{ basic: [] }];
|
|
5324
5552
|
securitySchemes["basic"] = {
|
|
5325
5553
|
type: "http",
|
|
5326
5554
|
scheme: "basic"
|
|
5327
5555
|
};
|
|
5328
5556
|
} else if (auth) {
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
[auth.headerName !== "Authorization" ? "bearer" : "apiKey"]: Array.from(
|
|
5332
|
-
"allowedPermissions" in auth && auth.allowedPermissions instanceof Set ? auth.allowedPermissions.values() : []
|
|
5333
|
-
)
|
|
5334
|
-
}
|
|
5335
|
-
];
|
|
5557
|
+
const schemeName = auth.headerName || "Authorization";
|
|
5558
|
+
operationObject.security = [{ [schemeName]: [] }];
|
|
5336
5559
|
if (auth.headerName && auth.headerName !== "Authorization") {
|
|
5337
5560
|
securitySchemes[auth.headerName] = {
|
|
5338
5561
|
type: "apiKey",
|
|
@@ -5563,6 +5786,150 @@ var RateLimiter = class {
|
|
|
5563
5786
|
return READ_METHODS.has(method.toUpperCase()) ? "read" : "write";
|
|
5564
5787
|
}
|
|
5565
5788
|
};
|
|
5789
|
+
|
|
5790
|
+
// src/http/registerDelegatedSurface.ts
|
|
5791
|
+
function registerDelegatedSurface(surface, mount, register) {
|
|
5792
|
+
if (!surface.id || !surface.provider || surface.coverage !== "provider-owned" || !surface.client.package || !surface.client.export || surface.runtime.basePath !== "runtime-resolved" || typeof surface.runtime.openApi !== "boolean" || !Array.isArray(surface.callbacks) || surface.callbacks.some(
|
|
5793
|
+
(callback) => typeof callback !== "string" || !callback.startsWith("/")
|
|
5794
|
+
)) {
|
|
5795
|
+
throw new Error("Invalid delegated HTTP surface descriptor");
|
|
5796
|
+
}
|
|
5797
|
+
const paths = Array.isArray(mount.paths) ? mount.paths : [mount.paths];
|
|
5798
|
+
if (mount.basePath !== "" && !mount.basePath.startsWith("/") || paths.length === 0 || paths.some(
|
|
5799
|
+
(path) => !path.startsWith("/") || mount.basePath !== "" && !path.startsWith(mount.basePath + "/")
|
|
5800
|
+
)) {
|
|
5801
|
+
throw new Error("Invalid delegated HTTP surface mount");
|
|
5802
|
+
}
|
|
5803
|
+
return register(mount);
|
|
5804
|
+
}
|
|
5805
|
+
|
|
5806
|
+
// src/http/localModelGatewayClient.ts
|
|
5807
|
+
import { execFile } from "child_process";
|
|
5808
|
+
import { promisify } from "util";
|
|
5809
|
+
var execute = promisify(execFile);
|
|
5810
|
+
var gateway = "https://studio-orchestrator.forklaunch.com/studio-orchestrator/desktop-runtime-model-gateway";
|
|
5811
|
+
function validate(value) {
|
|
5812
|
+
if (!value || !/^[a-f0-9]{64}$/.test(value.grantId) || !/^[a-f0-9]{64}$/.test(value.capability) || value.gatewayBaseUrl !== `${gateway}/${value.grantId}/v1` || value.scope !== "local-runtime" || !Number.isSafeInteger(value.expiresAt) || value.expiresAt <= Date.now() || value.expiresAt > Date.now() + 9e5 || !/^[A-Za-z0-9._-]{1,128}$/.test(value.model) || !Number.isInteger(value.maxCalls) || value.maxCalls < 1 || value.maxCalls > 20 || !Number.isInteger(value.maxUnits) || value.maxUnits < 1 || value.maxUnits > 1e5) {
|
|
5813
|
+
throw new Error(
|
|
5814
|
+
"Invalid local model connection. No model request was sent."
|
|
5815
|
+
);
|
|
5816
|
+
}
|
|
5817
|
+
return value;
|
|
5818
|
+
}
|
|
5819
|
+
function createLocalModelGatewayClient(options2 = {}) {
|
|
5820
|
+
if (process.env.FORKLAUNCH_API_KEY === void 0 && !options2.credentialProvider && process.env.FORKLAUNCH_LOCAL_MODEL_RELAY === "1") {
|
|
5821
|
+
return createPreviewModelGatewayClient({ fetch: options2.fetch });
|
|
5822
|
+
}
|
|
5823
|
+
const applicationId = options2.applicationId ?? process.env.FORKLAUNCH_APPLICATION_ID;
|
|
5824
|
+
const model = options2.model ?? process.env.AGENT_MODEL;
|
|
5825
|
+
if (applicationId && !/^[a-f0-9-]{36}$/i.test(applicationId)) {
|
|
5826
|
+
throw new Error(
|
|
5827
|
+
"FORKLAUNCH_APPLICATION_ID must be a saved application UUID."
|
|
5828
|
+
);
|
|
5829
|
+
}
|
|
5830
|
+
const provider = options2.credentialProvider ?? (async () => {
|
|
5831
|
+
const args = ["model", "credential", "--json"];
|
|
5832
|
+
if (applicationId) args.push("--application-id", applicationId);
|
|
5833
|
+
if (model) args.push("--model", model);
|
|
5834
|
+
try {
|
|
5835
|
+
const { stdout } = await execute("forklaunch", args, {
|
|
5836
|
+
timeout: 35e3,
|
|
5837
|
+
maxBuffer: 65536,
|
|
5838
|
+
windowsHide: true
|
|
5839
|
+
});
|
|
5840
|
+
return JSON.parse(stdout);
|
|
5841
|
+
} catch {
|
|
5842
|
+
throw new Error(
|
|
5843
|
+
"Could not connect the local agent. Run forklaunch login, check app access, and use a CLI that supports model credential."
|
|
5844
|
+
);
|
|
5845
|
+
}
|
|
5846
|
+
});
|
|
5847
|
+
const optionsFetch = options2.fetch ?? fetch;
|
|
5848
|
+
let pending;
|
|
5849
|
+
let credential;
|
|
5850
|
+
async function connection() {
|
|
5851
|
+
if (credential && credential.expiresAt > Date.now()) return credential;
|
|
5852
|
+
pending ??= provider().then(validate).then((value) => credential = value).finally(() => {
|
|
5853
|
+
pending = void 0;
|
|
5854
|
+
});
|
|
5855
|
+
return pending;
|
|
5856
|
+
}
|
|
5857
|
+
return {
|
|
5858
|
+
async models() {
|
|
5859
|
+
const c = await connection();
|
|
5860
|
+
return {
|
|
5861
|
+
models: [{ id: c.model }],
|
|
5862
|
+
preview: {
|
|
5863
|
+
expiresAt: c.expiresAt,
|
|
5864
|
+
maxCalls: c.maxCalls,
|
|
5865
|
+
maxUnits: c.maxUnits
|
|
5866
|
+
}
|
|
5867
|
+
};
|
|
5868
|
+
},
|
|
5869
|
+
chat: {
|
|
5870
|
+
completions: {
|
|
5871
|
+
async *stream(request, options3 = {}) {
|
|
5872
|
+
const c = await connection();
|
|
5873
|
+
if (request.model !== c.model)
|
|
5874
|
+
throw new ModelGatewayRequestError(
|
|
5875
|
+
400,
|
|
5876
|
+
"Choose the model authorized for this local session."
|
|
5877
|
+
);
|
|
5878
|
+
const response = await optionsFetch(
|
|
5879
|
+
`${c.gatewayBaseUrl}/chat/completions`,
|
|
5880
|
+
{
|
|
5881
|
+
method: "POST",
|
|
5882
|
+
redirect: "error",
|
|
5883
|
+
signal: options3.signal ? AbortSignal.any([options3.signal, AbortSignal.timeout(6e4)]) : AbortSignal.timeout(6e4),
|
|
5884
|
+
headers: {
|
|
5885
|
+
authorization: `Bearer ${c.capability}`,
|
|
5886
|
+
"content-type": "application/json"
|
|
5887
|
+
},
|
|
5888
|
+
body: JSON.stringify({ ...request, stream: true })
|
|
5889
|
+
}
|
|
5890
|
+
);
|
|
5891
|
+
if (!response.ok) {
|
|
5892
|
+
await response.body?.cancel();
|
|
5893
|
+
throw new ModelGatewayRequestError(
|
|
5894
|
+
response.status,
|
|
5895
|
+
"The local model stream was refused. No automatic retry was sent."
|
|
5896
|
+
);
|
|
5897
|
+
}
|
|
5898
|
+
yield* readModelStream(response);
|
|
5899
|
+
},
|
|
5900
|
+
async create(request) {
|
|
5901
|
+
const c = await connection();
|
|
5902
|
+
if (request.model !== c.model)
|
|
5903
|
+
throw new ModelGatewayRequestError(
|
|
5904
|
+
400,
|
|
5905
|
+
"Choose the model authorized for this local session."
|
|
5906
|
+
);
|
|
5907
|
+
const response = await (options2.fetch ?? fetch)(
|
|
5908
|
+
`${c.gatewayBaseUrl}/chat/completions`,
|
|
5909
|
+
{
|
|
5910
|
+
method: "POST",
|
|
5911
|
+
redirect: "error",
|
|
5912
|
+
signal: AbortSignal.timeout(6e4),
|
|
5913
|
+
headers: {
|
|
5914
|
+
authorization: `Bearer ${c.capability}`,
|
|
5915
|
+
"content-type": "application/json"
|
|
5916
|
+
},
|
|
5917
|
+
body: JSON.stringify({ ...request, stream: false })
|
|
5918
|
+
}
|
|
5919
|
+
);
|
|
5920
|
+
if (!response.ok) {
|
|
5921
|
+
await response.body?.cancel();
|
|
5922
|
+
throw new ModelGatewayRequestError(
|
|
5923
|
+
response.status,
|
|
5924
|
+
"The local model request was refused or failed. No automatic retry was sent."
|
|
5925
|
+
);
|
|
5926
|
+
}
|
|
5927
|
+
return response.json();
|
|
5928
|
+
}
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
};
|
|
5932
|
+
}
|
|
5566
5933
|
export {
|
|
5567
5934
|
ATTR_API_NAME,
|
|
5568
5935
|
ATTR_APPLICATION_ID,
|
|
@@ -5600,10 +5967,12 @@ export {
|
|
|
5600
5967
|
auditComplianceAccess,
|
|
5601
5968
|
auditEnabled,
|
|
5602
5969
|
auditEventType,
|
|
5970
|
+
bindRuntimeAuth,
|
|
5603
5971
|
createContext,
|
|
5604
5972
|
createEmailClient,
|
|
5605
5973
|
createHmacToken,
|
|
5606
5974
|
createInstanceGatewayTransport,
|
|
5975
|
+
createLocalModelGatewayClient,
|
|
5607
5976
|
createModelGatewayClient,
|
|
5608
5977
|
createPaymentsClient,
|
|
5609
5978
|
createPreviewModelGatewayClient,
|
|
@@ -5653,6 +6022,7 @@ export {
|
|
|
5653
6022
|
put,
|
|
5654
6023
|
recordMetric,
|
|
5655
6024
|
recordRequestAudit,
|
|
6025
|
+
registerDelegatedSurface,
|
|
5656
6026
|
resetProcessHandlersForTesting,
|
|
5657
6027
|
signPlatformEvent,
|
|
5658
6028
|
smsSegments,
|