@eyepop.ai/eyepop 3.17.0 → 3.17.2

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.
@@ -1338,6 +1338,7 @@ declare function randomMultipartBoundary(): string;
1338
1338
  */
1339
1339
  declare function encodeMultipartFormData(parts: MultipartPart[], boundary: string): ReadableStream<Uint8Array>;
1340
1340
 
1341
+ type UploadBody = ReadableStream<Uint8Array> | Blob | BufferSource;
1341
1342
  declare class AbstractJob implements ResultStream {
1342
1343
  protected _getSession: () => Promise<WorkerSession>;
1343
1344
  protected _params: ProcessParams;
@@ -1356,12 +1357,14 @@ declare class AbstractJob implements ResultStream {
1356
1357
  }
1357
1358
  declare class UploadJob extends AbstractJob {
1358
1359
  private readonly _uploadStream;
1360
+ private readonly _uploadBodyFactory;
1359
1361
  private readonly _mimeType;
1360
1362
  private readonly _size;
1361
1363
  private readonly _needsFullDuplex;
1362
1364
  private readonly _videoMode;
1363
1365
  get [Symbol.toStringTag](): string;
1364
- constructor(stream: ReadableStream<Uint8Array> | Blob | BufferSource, mimeType: string, size: number | undefined, videoMode: VideoMode | undefined, params: ProcessParams, getSession: () => Promise<WorkerSession>, client: HttpClient, requestLogger: Logger);
1366
+ constructor(stream: UploadBody, mimeType: string, size: number | undefined, videoMode: VideoMode | undefined, params: ProcessParams, getSession: () => Promise<WorkerSession>, client: HttpClient, requestLogger: Logger, uploadBodyFactory?: () => Promise<UploadBody>);
1367
+ private uploadBody;
1365
1368
  protected onEvent(event: StreamEvent): Promise<void>;
1366
1369
  protected startJob(): Promise<Response>;
1367
1370
  }
@@ -1338,6 +1338,7 @@ declare function randomMultipartBoundary(): string;
1338
1338
  */
1339
1339
  declare function encodeMultipartFormData(parts: MultipartPart[], boundary: string): ReadableStream<Uint8Array>;
1340
1340
 
1341
+ type UploadBody = ReadableStream<Uint8Array> | Blob | BufferSource;
1341
1342
  declare class AbstractJob implements ResultStream {
1342
1343
  protected _getSession: () => Promise<WorkerSession>;
1343
1344
  protected _params: ProcessParams;
@@ -1356,12 +1357,14 @@ declare class AbstractJob implements ResultStream {
1356
1357
  }
1357
1358
  declare class UploadJob extends AbstractJob {
1358
1359
  private readonly _uploadStream;
1360
+ private readonly _uploadBodyFactory;
1359
1361
  private readonly _mimeType;
1360
1362
  private readonly _size;
1361
1363
  private readonly _needsFullDuplex;
1362
1364
  private readonly _videoMode;
1363
1365
  get [Symbol.toStringTag](): string;
1364
- constructor(stream: ReadableStream<Uint8Array> | Blob | BufferSource, mimeType: string, size: number | undefined, videoMode: VideoMode | undefined, params: ProcessParams, getSession: () => Promise<WorkerSession>, client: HttpClient, requestLogger: Logger);
1366
+ constructor(stream: UploadBody, mimeType: string, size: number | undefined, videoMode: VideoMode | undefined, params: ProcessParams, getSession: () => Promise<WorkerSession>, client: HttpClient, requestLogger: Logger, uploadBodyFactory?: () => Promise<UploadBody>);
1367
+ private uploadBody;
1365
1368
  protected onEvent(event: StreamEvent): Promise<void>;
1366
1369
  protected startJob(): Promise<Response>;
1367
1370
  }
@@ -8766,14 +8766,96 @@ function accessTokenValidUntil(session) {
8766
8766
  }
8767
8767
  return null;
8768
8768
  }
8769
+ function errorInfoMessage(errorInfo) {
8770
+ return [errorInfo.code, errorInfo.message, errorInfo.details].filter((part) => typeof part == "string" && part.length > 0).join(": ");
8771
+ }
8772
+ function pipelineErrorMessage(session) {
8773
+ if (session.pipeline_error) {
8774
+ const message = errorInfoMessage(session.pipeline_error);
8775
+ return message ? `Pipeline failed for compute session ${session.session_uuid}: ${message}` : `Pipeline failed for compute session ${session.session_uuid}`;
8776
+ }
8777
+ if (session.session_status == "pipeline_error" /* PIPELINE_ERROR */) {
8778
+ return `Pipeline failed for compute session ${session.session_uuid}`;
8779
+ }
8780
+ return null;
8781
+ }
8782
+ async function responseErrorMessage(response) {
8783
+ const contentType = response.headers.get("content-type") || "";
8784
+ if (contentType.includes("application/json")) {
8785
+ try {
8786
+ const parsed = normalizedJsonValue(await response.clone().json());
8787
+ const message2 = normalizedErrorMessage(parsed);
8788
+ if (message2) {
8789
+ return message2;
8790
+ }
8791
+ } catch (_) {
8792
+ }
8793
+ }
8794
+ const body = await response.text();
8795
+ const message = normalizedErrorMessage(body);
8796
+ return message || body;
8797
+ }
8798
+ function normalizedJsonValue(value) {
8799
+ if (typeof value == "string") {
8800
+ try {
8801
+ const parsed = JSON.parse(value);
8802
+ return normalizedJsonValue(parsed);
8803
+ } catch (_) {
8804
+ const unescaped = value.replace(/\\"/g, '"');
8805
+ if (unescaped != value) {
8806
+ try {
8807
+ const parsed = JSON.parse(unescaped);
8808
+ return normalizedJsonValue(parsed);
8809
+ } catch (_2) {
8810
+ }
8811
+ }
8812
+ return value;
8813
+ }
8814
+ }
8815
+ return value;
8816
+ }
8817
+ async function responseJson(response) {
8818
+ return normalizedJsonValue(await response.json());
8819
+ }
8820
+ function normalizedErrorMessage(value) {
8821
+ value = normalizedJsonValue(value);
8822
+ if (typeof value == "string") {
8823
+ return value;
8824
+ }
8825
+ if (!value || typeof value != "object") {
8826
+ return null;
8827
+ }
8828
+ const record = value;
8829
+ const normalizedError = normalizedJsonValue(record["error"]);
8830
+ const errorMessage = normalizedErrorMessage(normalizedError) || (typeof normalizedError == "string" ? normalizedError : null);
8831
+ const message = [record["code"], errorMessage, record["message"], record["details"]].filter((part) => typeof part == "string" && part.length > 0).join(": ");
8832
+ if (message) {
8833
+ return message;
8834
+ }
8835
+ if (record["pipeline_error"]) {
8836
+ return normalizedErrorMessage(record["pipeline_error"]);
8837
+ }
8838
+ if (normalizedError && typeof normalizedError == "object") {
8839
+ return normalizedErrorMessage(normalizedError);
8840
+ }
8841
+ try {
8842
+ return JSON.stringify(value);
8843
+ } catch (_) {
8844
+ return null;
8845
+ }
8846
+ }
8769
8847
  var ComputeSessionClient = class {
8770
8848
  constructor(options) {
8771
8849
  this.options = options;
8772
8850
  }
8773
8851
  async resolve() {
8774
8852
  const session = this.options.sessionUuid ? await this.getPermanentComputeSession(this.options.sessionUuid) : await this.getOnDemandComputeSession();
8775
- const accessToken = this.sessionAccessToken(session);
8776
- await this.waitUntilReady(session, accessToken);
8853
+ const pipelineFailure = pipelineErrorMessage(session);
8854
+ if (pipelineFailure) {
8855
+ throw new Error(pipelineFailure);
8856
+ }
8857
+ const authorizationHeader = await this.sessionAuthorizationHeader(session);
8858
+ await this.waitUntilReady(session, authorizationHeader);
8777
8859
  const pipelineId = pipelineIdFromSession(session);
8778
8860
  if (this.options.pop && !pipelineId) {
8779
8861
  throw new Error("Compute session did not provide a pipeline for the requested pop");
@@ -8781,7 +8863,7 @@ var ComputeSessionClient = class {
8781
8863
  return {
8782
8864
  session,
8783
8865
  pipelineId,
8784
- accessToken,
8866
+ accessToken: session.access_token || null,
8785
8867
  accessTokenValidUntil: accessTokenValidUntil(session)
8786
8868
  };
8787
8869
  }
@@ -8800,10 +8882,10 @@ var ComputeSessionClient = class {
8800
8882
  if (response.status == 404) {
8801
8883
  sessions = [];
8802
8884
  } else if (response.status != 200) {
8803
- const message = await response.text();
8885
+ const message = await responseErrorMessage(response);
8804
8886
  throw new Error(`Unexpected status ${response.status} fetching compute sessions: ${message}`);
8805
8887
  } else {
8806
- const response_content = await response.json();
8888
+ const response_content = await responseJson(response);
8807
8889
  sessions = response_content;
8808
8890
  }
8809
8891
  if (sessions.length > 0) {
@@ -8834,10 +8916,10 @@ var ComputeSessionClient = class {
8834
8916
  const query = "wait=true";
8835
8917
  const response = await this.options.httpClient.fetch(`${sessionsUrl}?${query}`, request);
8836
8918
  if (response.status != 200) {
8837
- const message = await response.text();
8919
+ const message = await responseErrorMessage(response);
8838
8920
  throw new Error(`Unexpected status ${response.status} creating a compute session: ${message}`);
8839
8921
  } else {
8840
- sessions = await response.json();
8922
+ sessions = await responseJson(response);
8841
8923
  }
8842
8924
  if (sessions.length == 0) {
8843
8925
  throw new Error("Unexpected, no compute session after attempt to create one");
@@ -8847,9 +8929,6 @@ var ComputeSessionClient = class {
8847
8929
  if (!session) {
8848
8930
  throw new Error("unexpected undefined session");
8849
8931
  }
8850
- if (this.options.pop && !pipelineIdFromSession(session)) {
8851
- throw new Error("Compute session did not provide a pipeline for the requested pop");
8852
- }
8853
8932
  return session;
8854
8933
  }
8855
8934
  async getPermanentComputeSession(sessionUuid) {
@@ -8865,28 +8944,28 @@ var ComputeSessionClient = class {
8865
8944
  if (response.status == 404) {
8866
8945
  throw new Error(`Unexpected status ${response.status} compute sessions ${sessionUuid} not found`);
8867
8946
  } else if (response.status != 200) {
8868
- const message = await response.text();
8947
+ const message = await responseErrorMessage(response);
8869
8948
  throw new Error(`Unexpected status ${response.status} fetching compute sessions: ${message}`);
8870
8949
  } else {
8871
- const response_content = await response.json();
8950
+ const response_content = await responseJson(response);
8872
8951
  session = response_content;
8873
8952
  }
8874
8953
  return session;
8875
8954
  }
8876
- sessionAccessToken(session) {
8877
- if (!session.access_token) {
8878
- throw new Error(`Compute session ${session.session_uuid} did not provide an access token`);
8955
+ async sessionAuthorizationHeader(session) {
8956
+ if (session.access_token) {
8957
+ return `Bearer ${session.access_token}`;
8879
8958
  }
8880
- return session.access_token;
8959
+ return this.options.authorizationHeader();
8881
8960
  }
8882
- async waitUntilReady(session, accessToken) {
8961
+ async waitUntilReady(session, authorizationHeader) {
8883
8962
  let isReady = false;
8884
8963
  const deadline = Date.now() + this.options.readyTimeoutMs;
8885
8964
  while (!isReady) {
8886
8965
  const health_url = `${session.session_endpoint}/health`;
8887
8966
  const response = await this.options.httpClient.fetch(health_url, {
8888
8967
  headers: {
8889
- Authorization: `Bearer ${accessToken}`,
8968
+ Authorization: authorizationHeader,
8890
8969
  Accept: "application/json"
8891
8970
  }
8892
8971
  });
@@ -9684,14 +9763,18 @@ var UploadJob = class extends AbstractJob {
9684
9763
  get [Symbol.toStringTag]() {
9685
9764
  return "uploadJob";
9686
9765
  }
9687
- constructor(stream, mimeType, size, videoMode, params, getSession, client, requestLogger) {
9766
+ constructor(stream, mimeType, size, videoMode, params, getSession, client, requestLogger, uploadBodyFactory) {
9688
9767
  super(params, getSession, client, requestLogger);
9689
9768
  this._uploadStream = stream;
9769
+ this._uploadBodyFactory = uploadBodyFactory;
9690
9770
  this._mimeType = mimeType;
9691
9771
  this._size = size;
9692
9772
  this._videoMode = videoMode;
9693
9773
  this._needsFullDuplex = !client.isFullDuplex() && mimeType.startsWith("video/") && videoMode == "stream" /* STREAM */;
9694
9774
  }
9775
+ async uploadBody() {
9776
+ return this._uploadBodyFactory ? await this._uploadBodyFactory() : this._uploadStream;
9777
+ }
9695
9778
  async onEvent(event) {
9696
9779
  if (event.type == "prepared") {
9697
9780
  if (!event.source_id) {
@@ -9733,7 +9816,7 @@ var UploadJob = class extends AbstractJob {
9733
9816
  const blob = new Blob([JSON.stringify(this._params.fps)], { type: "application/json" });
9734
9817
  formData.append("fps", blob);
9735
9818
  }
9736
- const fileBlob = await new Response(this._uploadStream).blob();
9819
+ const fileBlob = await new Response(await this.uploadBody()).blob();
9737
9820
  formData.append("file", fileBlob);
9738
9821
  const headers = {
9739
9822
  ...session.authenticationHeaders(),
@@ -9760,7 +9843,7 @@ var UploadJob = class extends AbstractJob {
9760
9843
  request = this._client.fetch(postUrl, {
9761
9844
  headers,
9762
9845
  method: "POST",
9763
- body: this._uploadStream,
9846
+ body: await this.uploadBody(),
9764
9847
  signal: this._controller.signal,
9765
9848
  // @ts-ignore
9766
9849
  duplex: "half",
@@ -9828,7 +9911,7 @@ var UploadJob = class extends AbstractJob {
9828
9911
  const blob = new Blob([JSON.stringify(this._params.fps)], { type: "application/json" });
9829
9912
  formData.append("fps", blob);
9830
9913
  }
9831
- const fileBlob = await new Response(this._uploadStream).blob();
9914
+ const fileBlob = await new Response(await this.uploadBody()).blob();
9832
9915
  formData.append("file", fileBlob);
9833
9916
  const headers = {
9834
9917
  ...session.authenticationHeaders(),
@@ -9855,7 +9938,7 @@ var UploadJob = class extends AbstractJob {
9855
9938
  response = await this._client.fetch(postUrl, {
9856
9939
  headers,
9857
9940
  method: "POST",
9858
- body: this._uploadStream,
9941
+ body: await this.uploadBody(),
9859
9942
  signal: this._controller.signal,
9860
9943
  // @ts-ignore
9861
9944
  duplex: "half"
@@ -10955,12 +11038,21 @@ var _WorkerEndpoint = class _WorkerEndpoint extends Endpoint {
10955
11038
  await this._limit.acquire();
10956
11039
  try {
10957
11040
  this.updateState();
10958
- let streamSource;
10959
- if (this._options.platformSupport?.resolvePath) {
10960
- streamSource = await this._options.platformSupport.resolvePath(source, this._logger);
10961
- } else {
10962
- streamSource = await resolvePath(source, this._logger);
10963
- }
11041
+ const resolveStreamSource = async () => {
11042
+ if (this._options.platformSupport?.resolvePath) {
11043
+ return await this._options.platformSupport.resolvePath(source, this._logger);
11044
+ }
11045
+ return await resolvePath(source, this._logger);
11046
+ };
11047
+ const streamSource = await resolveStreamSource();
11048
+ let firstStreamPending = true;
11049
+ const uploadBodyFactory = async () => {
11050
+ if (firstStreamPending) {
11051
+ firstStreamPending = false;
11052
+ return streamSource.stream;
11053
+ }
11054
+ return (await resolveStreamSource()).stream;
11055
+ };
10964
11056
  const job = new UploadJob(
10965
11057
  streamSource.stream,
10966
11058
  streamSource.mimeType,
@@ -10971,7 +11063,8 @@ var _WorkerEndpoint = class _WorkerEndpoint extends Endpoint {
10971
11063
  return this.session();
10972
11064
  },
10973
11065
  this._client,
10974
- this._requestLogger
11066
+ this._requestLogger,
11067
+ uploadBodyFactory
10975
11068
  );
10976
11069
  return job.start(
10977
11070
  () => {