@eyepop.ai/eyepop 3.25.4 → 3.25.6
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/eyepop.index.d.mts +41 -2
- package/dist/eyepop.index.d.ts +41 -2
- package/dist/eyepop.index.js +112 -52
- package/dist/eyepop.index.js.map +1 -1
- package/dist/eyepop.index.mjs +112 -52
- package/dist/eyepop.index.mjs.map +1 -1
- package/dist/eyepop.min.js +1 -1
- package/package.json +1 -1
package/dist/eyepop.index.mjs
CHANGED
|
@@ -8928,14 +8928,25 @@ if ("document" in globalThis && "implementation" in globalThis.document) {
|
|
|
8928
8928
|
}
|
|
8929
8929
|
|
|
8930
8930
|
// endpoint.ts
|
|
8931
|
+
var ACCOUNT_CLAIM = "https://ident.eyepop.ai/account-uuid";
|
|
8932
|
+
var M2M_REFUSAL = "API key or user login required";
|
|
8933
|
+
function carriesAccount(token) {
|
|
8934
|
+
try {
|
|
8935
|
+
const payload = (token.split(".")[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
8936
|
+
return Boolean(JSON.parse(atob(payload))?.[ACCOUNT_CLAIM]);
|
|
8937
|
+
} catch {
|
|
8938
|
+
return false;
|
|
8939
|
+
}
|
|
8940
|
+
}
|
|
8931
8941
|
var Endpoint = class {
|
|
8932
8942
|
constructor(options) {
|
|
8943
|
+
this._exchanging = null;
|
|
8933
8944
|
this._options = options;
|
|
8934
8945
|
this._token = null;
|
|
8935
8946
|
this._expire_token_time = null;
|
|
8936
8947
|
this._client = null;
|
|
8937
8948
|
this._statusRetryHandlers = /* @__PURE__ */ new Map();
|
|
8938
|
-
this._statusRetryHandlers.set(401, (statusCode) => this.statusHandler401(statusCode));
|
|
8949
|
+
this._statusRetryHandlers.set(401, (statusCode, failedToken) => this.statusHandler401(statusCode, failedToken));
|
|
8939
8950
|
this._limit = new Semaphore(this._options.jobQueueLength ?? 1024);
|
|
8940
8951
|
this._state = "Idle" /* Idle */;
|
|
8941
8952
|
this._message = null;
|
|
@@ -8951,7 +8962,7 @@ var Endpoint = class {
|
|
|
8951
8962
|
}
|
|
8952
8963
|
setStatusRetryHandlers(statusRetryHandlers = void 0) {
|
|
8953
8964
|
this._statusRetryHandlers = new Map(statusRetryHandlers);
|
|
8954
|
-
this._statusRetryHandlers.set(401, (statusCode) => this.statusHandler401(statusCode));
|
|
8965
|
+
this._statusRetryHandlers.set(401, (statusCode, failedToken) => this.statusHandler401(statusCode, failedToken));
|
|
8955
8966
|
}
|
|
8956
8967
|
eyepopUrl() {
|
|
8957
8968
|
if (this._options.eyepopUrl) {
|
|
@@ -9048,12 +9059,15 @@ var Endpoint = class {
|
|
|
9048
9059
|
validUntil: this._expire_token_time * 1e3
|
|
9049
9060
|
};
|
|
9050
9061
|
}
|
|
9051
|
-
statusHandler401(_statusCode) {
|
|
9052
|
-
this._token
|
|
9053
|
-
|
|
9062
|
+
statusHandler401(_statusCode, failedToken = this._token) {
|
|
9063
|
+
if (this._token === failedToken) {
|
|
9064
|
+
this._token = null;
|
|
9065
|
+
this._expire_token_time = null;
|
|
9066
|
+
}
|
|
9054
9067
|
}
|
|
9055
9068
|
async fetchWithRetry(fetcher, retries = 1) {
|
|
9056
9069
|
while (true) {
|
|
9070
|
+
const sentToken = this._token ?? void 0;
|
|
9057
9071
|
try {
|
|
9058
9072
|
const response = await fetcher();
|
|
9059
9073
|
if (response.ok) {
|
|
@@ -9061,7 +9075,7 @@ var Endpoint = class {
|
|
|
9061
9075
|
} else {
|
|
9062
9076
|
const handler = this._statusRetryHandlers.get(response.status);
|
|
9063
9077
|
if (handler != null) {
|
|
9064
|
-
handler(response.status);
|
|
9078
|
+
handler(response.status, sentToken);
|
|
9065
9079
|
if (retries--) {
|
|
9066
9080
|
this._requestLogger.info("received %d response, retry", response.status);
|
|
9067
9081
|
} else {
|
|
@@ -9095,54 +9109,74 @@ var Endpoint = class {
|
|
|
9095
9109
|
}
|
|
9096
9110
|
return `Bearer ${await this.currentAccessToken()}`;
|
|
9097
9111
|
}
|
|
9112
|
+
async exchange(client, credential, accountUuid) {
|
|
9113
|
+
const query = accountUuid ? `?account_uuid=${encodeURIComponent(accountUuid)}` : "";
|
|
9114
|
+
return await client.fetch(`${this.eyepopUrl()}/v1/auth/authenticate${query}`, {
|
|
9115
|
+
method: "POST",
|
|
9116
|
+
headers: { Authorization: `Bearer ${credential}` }
|
|
9117
|
+
});
|
|
9118
|
+
}
|
|
9119
|
+
async storeExchangedToken(response, now) {
|
|
9120
|
+
if (response.status != 200) {
|
|
9121
|
+
const message = await response.text();
|
|
9122
|
+
return Promise.reject(`Unexpected status ${response.status}: ${message}`);
|
|
9123
|
+
}
|
|
9124
|
+
const token = await response.json();
|
|
9125
|
+
this._token = token.access_token;
|
|
9126
|
+
this._expire_token_time = now + token.expires_in - 60;
|
|
9127
|
+
}
|
|
9128
|
+
/**
|
|
9129
|
+
* A token that already carries an account, or that the compute API refuses as an exchanged
|
|
9130
|
+
* token ("API key or user login required"), is used as is. Any other refusal is raised.
|
|
9131
|
+
*/
|
|
9132
|
+
async exchangeLoginToken(client, loginToken, validUntil, now) {
|
|
9133
|
+
if (!carriesAccount(loginToken)) {
|
|
9134
|
+
const response = await this.exchange(client, loginToken, this._options.accountId);
|
|
9135
|
+
if (response.status != 401 || !(await response.clone().text()).includes(M2M_REFUSAL)) {
|
|
9136
|
+
await this.storeExchangedToken(response, now);
|
|
9137
|
+
return;
|
|
9138
|
+
}
|
|
9139
|
+
}
|
|
9140
|
+
this._token = loginToken;
|
|
9141
|
+
this._expire_token_time = validUntil;
|
|
9142
|
+
}
|
|
9098
9143
|
async currentAccessToken() {
|
|
9144
|
+
if (!this._token || this._expire_token_time < Date.now() / 1e3) {
|
|
9145
|
+
this._exchanging ?? (this._exchanging = this.authenticate().finally(() => this._exchanging = null));
|
|
9146
|
+
await this._exchanging;
|
|
9147
|
+
}
|
|
9148
|
+
this._logger.debug("using access token, valid for at least %d seconds", this._expire_token_time - Date.now() / 1e3);
|
|
9149
|
+
return this._token;
|
|
9150
|
+
}
|
|
9151
|
+
async authenticate() {
|
|
9099
9152
|
const now = Date.now() / 1e3;
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
} else if (this._options.eyepopUrl) {
|
|
9119
|
-
const credential = apiKeyCredential(auth);
|
|
9120
|
-
if (credential === void 0) {
|
|
9121
|
-
return Promise.reject("no valid auth option");
|
|
9122
|
-
}
|
|
9123
|
-
const headers = { Authorization: `Bearer ${credential}` };
|
|
9124
|
-
const post_url = `${this.eyepopUrl()}/v1/auth/authenticate`;
|
|
9125
|
-
const response = await this._client.fetch(post_url, {
|
|
9126
|
-
method: "POST",
|
|
9127
|
-
headers
|
|
9128
|
-
});
|
|
9129
|
-
if (response.status != 200) {
|
|
9130
|
-
const message = await response.text();
|
|
9131
|
-
return Promise.reject(`Unexpected status ${response.status}: ${message}`);
|
|
9132
|
-
}
|
|
9133
|
-
const data = await response.json();
|
|
9134
|
-
const token = data;
|
|
9135
|
-
this._token = token.access_token;
|
|
9136
|
-
this._expire_token_time = now + token.expires_in - 60;
|
|
9137
|
-
} else {
|
|
9153
|
+
this.updateState("Authenticating" /* Authenticating */);
|
|
9154
|
+
try {
|
|
9155
|
+
const auth = resolveAuth(this._options);
|
|
9156
|
+
if (!this._client) {
|
|
9157
|
+
return Promise.reject("endpoint not connected");
|
|
9158
|
+
} else if (auth?.isLocal !== void 0) {
|
|
9159
|
+
this._token = "implicit";
|
|
9160
|
+
this._expire_token_time = Number.MAX_VALUE;
|
|
9161
|
+
} else if (auth?.session !== void 0) {
|
|
9162
|
+
return Promise.reject("temporary access token expired");
|
|
9163
|
+
} else if (auth?.oAuth2 !== void 0 && this._options.eyepopUrl) {
|
|
9164
|
+
const login = await authenticateBrowserSession(auth.oAuth2, this._options);
|
|
9165
|
+
await this.exchangeLoginToken(this._client, login.accessToken, login.validUntil / 1e3, now);
|
|
9166
|
+
} else if (accessTokenCredential(auth) !== void 0) {
|
|
9167
|
+
await this.exchangeLoginToken(this._client, accessTokenCredential(auth), Number.MAX_VALUE, now);
|
|
9168
|
+
} else if (this._options.eyepopUrl) {
|
|
9169
|
+
const credential = apiKeyCredential(auth);
|
|
9170
|
+
if (credential === void 0) {
|
|
9138
9171
|
return Promise.reject("no valid auth option");
|
|
9139
9172
|
}
|
|
9140
|
-
|
|
9141
|
-
|
|
9173
|
+
await this.storeExchangedToken(await this.exchange(this._client, credential), now);
|
|
9174
|
+
} else {
|
|
9175
|
+
return Promise.reject("no valid auth option");
|
|
9142
9176
|
}
|
|
9177
|
+
} finally {
|
|
9178
|
+
this.updateState();
|
|
9143
9179
|
}
|
|
9144
|
-
this._logger.debug("using access token, valid for at least %d seconds", this._expire_token_time - now);
|
|
9145
|
-
return this._token;
|
|
9146
9180
|
}
|
|
9147
9181
|
};
|
|
9148
9182
|
|
|
@@ -11692,10 +11726,22 @@ var PipelineJob = class {
|
|
|
11692
11726
|
this.openSource = null;
|
|
11693
11727
|
// Stops the job's source on the pipeline, once it was sent.
|
|
11694
11728
|
this.stopOnPipeline = null;
|
|
11729
|
+
this._milliComputeUnits = void 0;
|
|
11695
11730
|
}
|
|
11696
11731
|
get cancelled() {
|
|
11697
11732
|
return this._cancelled;
|
|
11698
11733
|
}
|
|
11734
|
+
/** The source's milli compute units: the latest total of its `usage` messages and its `end`. */
|
|
11735
|
+
get milliComputeUnits() {
|
|
11736
|
+
return this._milliComputeUnits;
|
|
11737
|
+
}
|
|
11738
|
+
/** Keep a usage's or an end's milliComputeUnits: each carries the source's total so far. */
|
|
11739
|
+
noteMilliComputeUnits(message) {
|
|
11740
|
+
const value = message["milliComputeUnits"];
|
|
11741
|
+
if (Number.isInteger(value) && value >= 0) {
|
|
11742
|
+
this._milliComputeUnits = value;
|
|
11743
|
+
}
|
|
11744
|
+
}
|
|
11699
11745
|
command(id) {
|
|
11700
11746
|
const command = { type: "setSource", id, ...this.source };
|
|
11701
11747
|
if (this.params.componentParams !== void 0) {
|
|
@@ -12273,7 +12319,11 @@ var PipelineBackend = class {
|
|
|
12273
12319
|
case "prediction":
|
|
12274
12320
|
job.predicted(message["prediction"]);
|
|
12275
12321
|
break;
|
|
12322
|
+
case "usage":
|
|
12323
|
+
job.noteMilliComputeUnits(message);
|
|
12324
|
+
break;
|
|
12276
12325
|
case "end":
|
|
12326
|
+
job.noteMilliComputeUnits(message);
|
|
12277
12327
|
if (message["reason"] === "eos") {
|
|
12278
12328
|
return null;
|
|
12279
12329
|
}
|
|
@@ -12837,6 +12887,7 @@ var InferAssetJob = class {
|
|
|
12837
12887
|
constructor(assetUrl, inferRequest, vlmFetch, requestLogger) {
|
|
12838
12888
|
this._response = null;
|
|
12839
12889
|
this._runInfo = null;
|
|
12890
|
+
this._milliComputeUnits = void 0;
|
|
12840
12891
|
this._controller = new AbortController();
|
|
12841
12892
|
this._vlmFetch = vlmFetch;
|
|
12842
12893
|
this._assetUrl = assetUrl;
|
|
@@ -12873,6 +12924,13 @@ var InferAssetJob = class {
|
|
|
12873
12924
|
}
|
|
12874
12925
|
return iterator();
|
|
12875
12926
|
}
|
|
12927
|
+
/**
|
|
12928
|
+
* The milli compute units vlm-server billed for the inference, 0 on a cache hit; undefined before it answered
|
|
12929
|
+
* or when it reported none.
|
|
12930
|
+
*/
|
|
12931
|
+
get milliComputeUnits() {
|
|
12932
|
+
return this._milliComputeUnits;
|
|
12933
|
+
}
|
|
12876
12934
|
start(done) {
|
|
12877
12935
|
this._response = new Promise(async (resolve, reject) => {
|
|
12878
12936
|
try {
|
|
@@ -12897,6 +12955,8 @@ var InferAssetJob = class {
|
|
|
12897
12955
|
const runInfo = response["run_info"];
|
|
12898
12956
|
if (predictions) {
|
|
12899
12957
|
this._runInfo = runInfo;
|
|
12958
|
+
const used = response["milli_compute_units"] ?? response["compute_units"];
|
|
12959
|
+
this._milliComputeUnits = typeof used === "number" ? used : void 0;
|
|
12900
12960
|
resolve(predictions);
|
|
12901
12961
|
break;
|
|
12902
12962
|
} else {
|
|
@@ -14420,17 +14480,17 @@ var EyePop;
|
|
|
14420
14480
|
if (typeof auth.oAuth2 === "boolean") {
|
|
14421
14481
|
const oAuth2 = opts.eyepopUrl && opts.eyepopUrl.match(/https:(.*).staging.eyepop.xyz/i) ? {
|
|
14422
14482
|
oAuth2: {
|
|
14423
|
-
domain: "
|
|
14483
|
+
domain: "auth0.eyepop.xyz",
|
|
14424
14484
|
clientId: "jktx3YO2UnbkNPvr05PQWf26t1kNTJyg",
|
|
14425
14485
|
audience: "https://dev-app.eyepop.ai",
|
|
14426
|
-
scope: "
|
|
14486
|
+
scope: "access:inference-api access:datasets"
|
|
14427
14487
|
}
|
|
14428
14488
|
} : {
|
|
14429
14489
|
oAuth2: {
|
|
14430
|
-
domain: "eyepop.
|
|
14490
|
+
domain: "auth0.eyepop.ai",
|
|
14431
14491
|
clientId: "Lb9ubA9Hf3jlaqWLUx8XgA0zvotgViCl",
|
|
14432
14492
|
audience: "https://api.eyepop.ai",
|
|
14433
|
-
scope: "
|
|
14493
|
+
scope: "access:inference-api access:datasets"
|
|
14434
14494
|
}
|
|
14435
14495
|
};
|
|
14436
14496
|
if (opts.oAuth2 !== void 0) {
|