@forklaunch/core 3.3.0 → 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.mjs +47 -0
- 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/index.d.ts +1 -0
- package/lib/http/index.d.ts.map +1 -1
- package/lib/http/index.js +203 -38
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +202 -38
- 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/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/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/persistence/compliantField.d.ts.map +1 -1
- package/lib/persistence/index.js +6 -1
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +6 -1
- package/lib/persistence/index.mjs.map +1 -1
- package/package.json +9 -2
package/lib/http/index.mjs
CHANGED
|
@@ -2861,12 +2861,55 @@ function signPlatformEvent(params) {
|
|
|
2861
2861
|
});
|
|
2862
2862
|
}
|
|
2863
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
|
+
|
|
2864
2904
|
// src/http/modelGatewayClient.ts
|
|
2865
2905
|
var ModelGatewayRequestError = class extends InstanceGatewayRequestError {
|
|
2866
2906
|
name = "ModelGatewayRequestError";
|
|
2867
2907
|
};
|
|
2868
2908
|
function createModelGatewayClient(options2 = {}) {
|
|
2869
|
-
const transport = createInstanceGatewayTransport(
|
|
2909
|
+
const transport = createInstanceGatewayTransport(
|
|
2910
|
+
options2,
|
|
2911
|
+
"The model gateway"
|
|
2912
|
+
);
|
|
2870
2913
|
async function send(method, route, body, signal) {
|
|
2871
2914
|
try {
|
|
2872
2915
|
return await transport.request(method, route, body, { signal });
|
|
@@ -2902,42 +2945,12 @@ function createModelGatewayClient(options2 = {}) {
|
|
|
2902
2945
|
request,
|
|
2903
2946
|
streamOptions.signal
|
|
2904
2947
|
);
|
|
2905
|
-
|
|
2906
|
-
for await (const data of sseData(response.body)) {
|
|
2907
|
-
if (data === "[DONE]") return;
|
|
2908
|
-
try {
|
|
2909
|
-
yield JSON.parse(data);
|
|
2910
|
-
} catch {
|
|
2911
|
-
}
|
|
2912
|
-
}
|
|
2948
|
+
yield* readModelStream(response);
|
|
2913
2949
|
}
|
|
2914
2950
|
}
|
|
2915
2951
|
}
|
|
2916
2952
|
};
|
|
2917
2953
|
}
|
|
2918
|
-
async function* sseData(stream) {
|
|
2919
|
-
const decoder = new TextDecoder();
|
|
2920
|
-
let buffer = "";
|
|
2921
|
-
const reader = stream.getReader();
|
|
2922
|
-
try {
|
|
2923
|
-
for (; ; ) {
|
|
2924
|
-
const { value, done } = await reader.read();
|
|
2925
|
-
if (done) break;
|
|
2926
|
-
buffer += decoder.decode(value, { stream: true });
|
|
2927
|
-
let boundary;
|
|
2928
|
-
while ((boundary = buffer.search(/\r?\n\r?\n/)) !== -1) {
|
|
2929
|
-
const event = buffer.slice(0, boundary);
|
|
2930
|
-
buffer = buffer.slice(boundary).replace(/^\r?\n\r?\n/, "");
|
|
2931
|
-
const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n");
|
|
2932
|
-
if (data) yield data;
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
const tail = buffer.trim();
|
|
2936
|
-
if (tail.startsWith("data:")) yield tail.slice(5).trimStart();
|
|
2937
|
-
} finally {
|
|
2938
|
-
reader.releaseLock();
|
|
2939
|
-
}
|
|
2940
|
-
}
|
|
2941
2954
|
|
|
2942
2955
|
// src/http/previewModelGatewayClient.ts
|
|
2943
2956
|
function record(value) {
|
|
@@ -2993,9 +3006,9 @@ function createPreviewModelGatewayClient(options2 = {}) {
|
|
|
2993
3006
|
options2,
|
|
2994
3007
|
"The local preview model gateway"
|
|
2995
3008
|
);
|
|
2996
|
-
async function send(method, route, body) {
|
|
3009
|
+
async function send(method, route, body, signal) {
|
|
2997
3010
|
try {
|
|
2998
|
-
return await transport.request(method, route, body);
|
|
3011
|
+
return await transport.request(method, route, body, { signal });
|
|
2999
3012
|
} catch (error) {
|
|
3000
3013
|
if (error instanceof InstanceGatewayRequestError)
|
|
3001
3014
|
throw new ModelGatewayRequestError(
|
|
@@ -3013,6 +3026,15 @@ function createPreviewModelGatewayClient(options2 = {}) {
|
|
|
3013
3026
|
},
|
|
3014
3027
|
chat: {
|
|
3015
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
|
+
},
|
|
3016
3038
|
async create(request) {
|
|
3017
3039
|
return await (await send(
|
|
3018
3040
|
"POST",
|
|
@@ -3546,6 +3568,19 @@ function createPaymentsClient(options2 = {}) {
|
|
|
3546
3568
|
},
|
|
3547
3569
|
status() {
|
|
3548
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", {});
|
|
3549
3584
|
}
|
|
3550
3585
|
};
|
|
3551
3586
|
}
|
|
@@ -3630,8 +3665,8 @@ function createStripeClient(options2 = {}) {
|
|
|
3630
3665
|
return new StripeClass(options2.apiKey, options2.config);
|
|
3631
3666
|
}
|
|
3632
3667
|
const settings = instanceGatewaySettings(options2, "Payments");
|
|
3633
|
-
const
|
|
3634
|
-
const protocol =
|
|
3668
|
+
const gateway2 = new URL(settings.gatewayUrl);
|
|
3669
|
+
const protocol = gateway2.protocol === "http:" ? "http" : "https";
|
|
3635
3670
|
return new StripeClass(
|
|
3636
3671
|
// No key: the authenticator below replaces it, and the gateway holds the
|
|
3637
3672
|
// real one. (stripe-node accepts an authenticator in place of a key.)
|
|
@@ -3639,8 +3674,8 @@ function createStripeClient(options2 = {}) {
|
|
|
3639
3674
|
{
|
|
3640
3675
|
maxNetworkRetries: 2,
|
|
3641
3676
|
...options2.config,
|
|
3642
|
-
host:
|
|
3643
|
-
port:
|
|
3677
|
+
host: gateway2.hostname,
|
|
3678
|
+
port: gateway2.port || (protocol === "http" ? 80 : 443),
|
|
3644
3679
|
protocol,
|
|
3645
3680
|
telemetry: false,
|
|
3646
3681
|
// The signed fetch sets `authorization`; nothing else may.
|
|
@@ -5767,6 +5802,134 @@ function registerDelegatedSurface(surface, mount, register) {
|
|
|
5767
5802
|
}
|
|
5768
5803
|
return register(mount);
|
|
5769
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
|
+
}
|
|
5770
5933
|
export {
|
|
5771
5934
|
ATTR_API_NAME,
|
|
5772
5935
|
ATTR_APPLICATION_ID,
|
|
@@ -5809,6 +5972,7 @@ export {
|
|
|
5809
5972
|
createEmailClient,
|
|
5810
5973
|
createHmacToken,
|
|
5811
5974
|
createInstanceGatewayTransport,
|
|
5975
|
+
createLocalModelGatewayClient,
|
|
5812
5976
|
createModelGatewayClient,
|
|
5813
5977
|
createPaymentsClient,
|
|
5814
5978
|
createPreviewModelGatewayClient,
|