@eyepop.ai/eyepop 3.25.3 → 3.25.4

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.
@@ -665,6 +665,16 @@ interface InferRequest {
665
665
  refresh?: boolean;
666
666
  transform_into?: TransformInto;
667
667
  response_schema?: ResponseSchema;
668
+ /**
669
+ * Auto-label task. The worker derives the prompt and output schema from the task and
670
+ * `prompts`, so `text_prompt`, `transform_into` and `response_schema` must be unset.
671
+ * Object detection returns `objects`, image classification `classes`, each labeled with a
672
+ * prompt's label. A task takes one image. Leave `config.max_new_tokens` unset to use the
673
+ * worker's default, which leaves room for a detection answer.
674
+ */
675
+ task?: AutoAnnotateTask;
676
+ /** Labels and what each one means, for `task`; required with a task. */
677
+ prompts?: AutoAnnotatePrompt[];
668
678
  }
669
679
  interface EvaluateFilter {
670
680
  partitions?: string[];
@@ -1477,6 +1487,11 @@ interface WorkerOptions extends Options {
1477
1487
  * Defaults to process.env['EYEPOP_PIPELINE_MODE'].
1478
1488
  */
1479
1489
  isPipelineMode?: boolean;
1490
+ /**
1491
+ * In pipeline mode, the most sockets the endpoint opens. Each runs its own pipeline, which plays its
1492
+ * sources one after another; a new one opens only while every open one has a source. Defaults to 4.
1493
+ */
1494
+ pipelineSockets?: number;
1480
1495
  }
1481
1496
 
1482
1497
  /**
@@ -2014,10 +2029,12 @@ declare const PIPELINE_PATH = "/api/v1/pipeline";
2014
2029
  declare const SUBPROTOCOL = "eyepop.v1";
2015
2030
  /** A socket may have this many open sources; one more is answered `queue_full`. */
2016
2031
  declare const MAX_OPEN_SOURCES = 256;
2032
+ /** The most sockets an endpoint opens unless `pipelineSockets` says otherwise. */
2033
+ declare const PIPELINE_SOCKETS = 4;
2017
2034
  /** Uploads up to this size go as one combined message, larger ones in chunks. */
2018
2035
  declare const COMBINED_UPLOAD_MAX_BYTES: number;
2019
2036
  /** Why pipeline mode refused its configuration. */
2020
- type PipelineConfigurationProblem = 'session_options' | 'job_queue_length' | 'no_pipeline_api_url' | 'insecure_url';
2037
+ type PipelineConfigurationProblem = 'session_options' | 'job_queue_length' | 'pipeline_sockets' | 'no_pipeline_api_url' | 'insecure_url';
2021
2038
  /** Pipeline mode cannot run as configured; `options` names the refused options for `session_options`. */
2022
2039
  declare class PipelineConfigurationError extends Error {
2023
2040
  readonly problem: PipelineConfigurationProblem;
@@ -2102,18 +2119,23 @@ declare class PipelineJob implements ResultStream {
2102
2119
  cancel(): void;
2103
2120
  [Symbol.asyncIterator](): AsyncIterator<Prediction>;
2104
2121
  }
2105
- /** Runs jobs on one socket to the pipeline API, opened when the endpoint connects. */
2122
+ /**
2123
+ * Runs jobs on up to `pipelineSockets` sockets to the pipeline API; connecting opens the first. A
2124
+ * socket's pipeline plays its sources one after another, so a batch on one socket leaves the GPU
2125
+ * mostly idle. While every open socket has a source and fewer than `pipelineSockets` are open, the next
2126
+ * job opens another; each job goes on the socket that has room and the fewest open sources.
2127
+ */
2106
2128
  declare class PipelineBackend implements WorkerBackend {
2107
2129
  private readonly ctx;
2108
2130
  private _pipelineApiUrl;
2109
- private _socket;
2131
+ private _sockets;
2110
2132
  private _connecting;
2111
2133
  private _sendChain;
2112
2134
  private _disconnecting;
2113
2135
  private _nextId;
2114
2136
  private _currentPop;
2115
2137
  private readonly _warned;
2116
- private _heartbeat;
2138
+ private _noExtraSocketUntil;
2117
2139
  private _reconnects;
2118
2140
  constructor(ctx: WorkerContext);
2119
2141
  reconnect(): Promise<void>;
@@ -2122,8 +2144,17 @@ declare class PipelineBackend implements WorkerBackend {
2122
2144
  popName(): string | null;
2123
2145
  authorizationHeader(): Promise<string>;
2124
2146
  private inOrder;
2125
- /** The open socket, or a new one with the last pop set on it. */
2147
+ private openSockets;
2148
+ /** An open socket, or a new one with the last pop set on it. */
2126
2149
  private ensureSocket;
2150
+ /**
2151
+ * The socket for the next job; the caller runs it in submission order. A live job goes on a socket
2152
+ * of its own, an idle one or a new one, which `pipelineSockets` does not count. Any other job skips
2153
+ * the sockets with a live source: a new one while every other socket has a source and fewer than
2154
+ * `pipelineSockets` are open, else the one with room and the fewest sources.
2155
+ */
2156
+ private socketForJob;
2157
+ /** A new socket with the last pop set on it; `patient` waits through 503 with Retry-After. */
2127
2158
  private openSocket;
2128
2159
  private startHeartbeat;
2129
2160
  private socketUrl;
@@ -2137,7 +2168,11 @@ declare class PipelineBackend implements WorkerBackend {
2137
2168
  /** Send a command that is answered by `result` or `error` under its id. */
2138
2169
  private command;
2139
2170
  pop(): Pop | null;
2140
- /** Set the pop on the socket's pipeline; a pop it refuses rejects, and the last pop it took stays. */
2171
+ /**
2172
+ * Set the pop on every open socket's pipeline; a pop the first refuses rejects, and the last pop it
2173
+ * took stays. shortcut: a refusal from a later socket, which the first took, leaves the earlier ones
2174
+ * on the new pop; a refusal is the pop's own fault, so every socket answers it alike.
2175
+ */
2141
2176
  changePop(pop: Pop): Promise<void>;
2142
2177
  private setPopOn;
2143
2178
  submit(work: WorkerWork): Promise<ResultStream>;
@@ -2290,4 +2325,4 @@ declare namespace EyePop {
2290
2325
  function dataEndpoint(opts?: DataOptions): DataEndpoint;
2291
2326
  }
2292
2327
 
2293
- export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, COMBINED_UPLOAD_MAX_BYTES, type Camera, type CameraDistortion, type CameraExtrinsics, type CameraIntrinsics, type ChangeEvent, ChangeType, type ClassificationTask, type CloudBounds, type CloudBox, type ComponentFinderComponent, type ComponentParams, ComputeAccountMismatchError, ComputeApiError, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DepthSemantic, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyePopDataWebSocketError, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, MAX_OPEN_SOURCES, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, PIPELINE_PATH, type PathSource, PipelineBackend, PipelineCommandError, PipelineConfigurationError, type PipelineConfigurationProblem, PipelineJob, PipelineSocketClosedError, PipelineSourceError, type PlatformSupport, type Point2d, type Point3d, PointCloud, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopDepthMap, type PopForward, type PopForwardOperator, type PopSelect, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, QUATERNION_TOLERANCE, type QcAiHubExportParams, type Quaternion, type RectangleArea, type ResponseSchema, type ResultStream, type Roi, SUBPROTOCOL, SelectMode, Semaphore, type Session, type SessionAuth, SessionBackend, type Source, type SourceDefaults, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, type Vector3, type Vector3d, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, type WorkerBackend, type WorkerContext, WorkerEndpoint, type WorkerOptions, type WorkerSession, type WorkerWork, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, cloudOfDepth, cloudOfObject, cloudsOfPrediction, decodeDepthMap, decodePointCloud, EyePop as default, encodeMultipartFormData, getBaseUrl, isSelectOperator, popSelects, randomMultipartBoundary, readableStreamFromString, resolveAuth, validateCamera, validatePop };
2328
+ export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, COMBINED_UPLOAD_MAX_BYTES, type Camera, type CameraDistortion, type CameraExtrinsics, type CameraIntrinsics, type ChangeEvent, ChangeType, type ClassificationTask, type CloudBounds, type CloudBox, type ComponentFinderComponent, type ComponentParams, ComputeAccountMismatchError, ComputeApiError, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DepthSemantic, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyePopDataWebSocketError, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, MAX_OPEN_SOURCES, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, PIPELINE_PATH, PIPELINE_SOCKETS, type PathSource, PipelineBackend, PipelineCommandError, PipelineConfigurationError, type PipelineConfigurationProblem, PipelineJob, PipelineSocketClosedError, PipelineSourceError, type PlatformSupport, type Point2d, type Point3d, PointCloud, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopDepthMap, type PopForward, type PopForwardOperator, type PopSelect, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, QUATERNION_TOLERANCE, type QcAiHubExportParams, type Quaternion, type RectangleArea, type ResponseSchema, type ResultStream, type Roi, SUBPROTOCOL, SelectMode, Semaphore, type Session, type SessionAuth, SessionBackend, type Source, type SourceDefaults, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, type Vector3, type Vector3d, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, type WorkerBackend, type WorkerContext, WorkerEndpoint, type WorkerOptions, type WorkerSession, type WorkerWork, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, cloudOfDepth, cloudOfObject, cloudsOfPrediction, decodeDepthMap, decodePointCloud, EyePop as default, encodeMultipartFormData, getBaseUrl, isSelectOperator, popSelects, randomMultipartBoundary, readableStreamFromString, resolveAuth, validateCamera, validatePop };
@@ -665,6 +665,16 @@ interface InferRequest {
665
665
  refresh?: boolean;
666
666
  transform_into?: TransformInto;
667
667
  response_schema?: ResponseSchema;
668
+ /**
669
+ * Auto-label task. The worker derives the prompt and output schema from the task and
670
+ * `prompts`, so `text_prompt`, `transform_into` and `response_schema` must be unset.
671
+ * Object detection returns `objects`, image classification `classes`, each labeled with a
672
+ * prompt's label. A task takes one image. Leave `config.max_new_tokens` unset to use the
673
+ * worker's default, which leaves room for a detection answer.
674
+ */
675
+ task?: AutoAnnotateTask;
676
+ /** Labels and what each one means, for `task`; required with a task. */
677
+ prompts?: AutoAnnotatePrompt[];
668
678
  }
669
679
  interface EvaluateFilter {
670
680
  partitions?: string[];
@@ -1477,6 +1487,11 @@ interface WorkerOptions extends Options {
1477
1487
  * Defaults to process.env['EYEPOP_PIPELINE_MODE'].
1478
1488
  */
1479
1489
  isPipelineMode?: boolean;
1490
+ /**
1491
+ * In pipeline mode, the most sockets the endpoint opens. Each runs its own pipeline, which plays its
1492
+ * sources one after another; a new one opens only while every open one has a source. Defaults to 4.
1493
+ */
1494
+ pipelineSockets?: number;
1480
1495
  }
1481
1496
 
1482
1497
  /**
@@ -2014,10 +2029,12 @@ declare const PIPELINE_PATH = "/api/v1/pipeline";
2014
2029
  declare const SUBPROTOCOL = "eyepop.v1";
2015
2030
  /** A socket may have this many open sources; one more is answered `queue_full`. */
2016
2031
  declare const MAX_OPEN_SOURCES = 256;
2032
+ /** The most sockets an endpoint opens unless `pipelineSockets` says otherwise. */
2033
+ declare const PIPELINE_SOCKETS = 4;
2017
2034
  /** Uploads up to this size go as one combined message, larger ones in chunks. */
2018
2035
  declare const COMBINED_UPLOAD_MAX_BYTES: number;
2019
2036
  /** Why pipeline mode refused its configuration. */
2020
- type PipelineConfigurationProblem = 'session_options' | 'job_queue_length' | 'no_pipeline_api_url' | 'insecure_url';
2037
+ type PipelineConfigurationProblem = 'session_options' | 'job_queue_length' | 'pipeline_sockets' | 'no_pipeline_api_url' | 'insecure_url';
2021
2038
  /** Pipeline mode cannot run as configured; `options` names the refused options for `session_options`. */
2022
2039
  declare class PipelineConfigurationError extends Error {
2023
2040
  readonly problem: PipelineConfigurationProblem;
@@ -2102,18 +2119,23 @@ declare class PipelineJob implements ResultStream {
2102
2119
  cancel(): void;
2103
2120
  [Symbol.asyncIterator](): AsyncIterator<Prediction>;
2104
2121
  }
2105
- /** Runs jobs on one socket to the pipeline API, opened when the endpoint connects. */
2122
+ /**
2123
+ * Runs jobs on up to `pipelineSockets` sockets to the pipeline API; connecting opens the first. A
2124
+ * socket's pipeline plays its sources one after another, so a batch on one socket leaves the GPU
2125
+ * mostly idle. While every open socket has a source and fewer than `pipelineSockets` are open, the next
2126
+ * job opens another; each job goes on the socket that has room and the fewest open sources.
2127
+ */
2106
2128
  declare class PipelineBackend implements WorkerBackend {
2107
2129
  private readonly ctx;
2108
2130
  private _pipelineApiUrl;
2109
- private _socket;
2131
+ private _sockets;
2110
2132
  private _connecting;
2111
2133
  private _sendChain;
2112
2134
  private _disconnecting;
2113
2135
  private _nextId;
2114
2136
  private _currentPop;
2115
2137
  private readonly _warned;
2116
- private _heartbeat;
2138
+ private _noExtraSocketUntil;
2117
2139
  private _reconnects;
2118
2140
  constructor(ctx: WorkerContext);
2119
2141
  reconnect(): Promise<void>;
@@ -2122,8 +2144,17 @@ declare class PipelineBackend implements WorkerBackend {
2122
2144
  popName(): string | null;
2123
2145
  authorizationHeader(): Promise<string>;
2124
2146
  private inOrder;
2125
- /** The open socket, or a new one with the last pop set on it. */
2147
+ private openSockets;
2148
+ /** An open socket, or a new one with the last pop set on it. */
2126
2149
  private ensureSocket;
2150
+ /**
2151
+ * The socket for the next job; the caller runs it in submission order. A live job goes on a socket
2152
+ * of its own, an idle one or a new one, which `pipelineSockets` does not count. Any other job skips
2153
+ * the sockets with a live source: a new one while every other socket has a source and fewer than
2154
+ * `pipelineSockets` are open, else the one with room and the fewest sources.
2155
+ */
2156
+ private socketForJob;
2157
+ /** A new socket with the last pop set on it; `patient` waits through 503 with Retry-After. */
2127
2158
  private openSocket;
2128
2159
  private startHeartbeat;
2129
2160
  private socketUrl;
@@ -2137,7 +2168,11 @@ declare class PipelineBackend implements WorkerBackend {
2137
2168
  /** Send a command that is answered by `result` or `error` under its id. */
2138
2169
  private command;
2139
2170
  pop(): Pop | null;
2140
- /** Set the pop on the socket's pipeline; a pop it refuses rejects, and the last pop it took stays. */
2171
+ /**
2172
+ * Set the pop on every open socket's pipeline; a pop the first refuses rejects, and the last pop it
2173
+ * took stays. shortcut: a refusal from a later socket, which the first took, leaves the earlier ones
2174
+ * on the new pop; a refusal is the pop's own fault, so every socket answers it alike.
2175
+ */
2141
2176
  changePop(pop: Pop): Promise<void>;
2142
2177
  private setPopOn;
2143
2178
  submit(work: WorkerWork): Promise<ResultStream>;
@@ -2290,4 +2325,4 @@ declare namespace EyePop {
2290
2325
  function dataEndpoint(opts?: DataOptions): DataEndpoint;
2291
2326
  }
2292
2327
 
2293
- export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, COMBINED_UPLOAD_MAX_BYTES, type Camera, type CameraDistortion, type CameraExtrinsics, type CameraIntrinsics, type ChangeEvent, ChangeType, type ClassificationTask, type CloudBounds, type CloudBox, type ComponentFinderComponent, type ComponentParams, ComputeAccountMismatchError, ComputeApiError, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DepthSemantic, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyePopDataWebSocketError, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, MAX_OPEN_SOURCES, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, PIPELINE_PATH, type PathSource, PipelineBackend, PipelineCommandError, PipelineConfigurationError, type PipelineConfigurationProblem, PipelineJob, PipelineSocketClosedError, PipelineSourceError, type PlatformSupport, type Point2d, type Point3d, PointCloud, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopDepthMap, type PopForward, type PopForwardOperator, type PopSelect, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, QUATERNION_TOLERANCE, type QcAiHubExportParams, type Quaternion, type RectangleArea, type ResponseSchema, type ResultStream, type Roi, SUBPROTOCOL, SelectMode, Semaphore, type Session, type SessionAuth, SessionBackend, type Source, type SourceDefaults, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, type Vector3, type Vector3d, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, type WorkerBackend, type WorkerContext, WorkerEndpoint, type WorkerOptions, type WorkerSession, type WorkerWork, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, cloudOfDepth, cloudOfObject, cloudsOfPrediction, decodeDepthMap, decodePointCloud, EyePop as default, encodeMultipartFormData, getBaseUrl, isSelectOperator, popSelects, randomMultipartBoundary, readableStreamFromString, resolveAuth, validateCamera, validatePop };
2328
+ export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, COMBINED_UPLOAD_MAX_BYTES, type Camera, type CameraDistortion, type CameraExtrinsics, type CameraIntrinsics, type ChangeEvent, ChangeType, type ClassificationTask, type CloudBounds, type CloudBox, type ComponentFinderComponent, type ComponentParams, ComputeAccountMismatchError, ComputeApiError, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DepthSemantic, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyePopDataWebSocketError, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, MAX_OPEN_SOURCES, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, PIPELINE_PATH, PIPELINE_SOCKETS, type PathSource, PipelineBackend, PipelineCommandError, PipelineConfigurationError, type PipelineConfigurationProblem, PipelineJob, PipelineSocketClosedError, PipelineSourceError, type PlatformSupport, type Point2d, type Point3d, PointCloud, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopDepthMap, type PopForward, type PopForwardOperator, type PopSelect, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, QUATERNION_TOLERANCE, type QcAiHubExportParams, type Quaternion, type RectangleArea, type ResponseSchema, type ResultStream, type Roi, SUBPROTOCOL, SelectMode, Semaphore, type Session, type SessionAuth, SessionBackend, type Source, type SourceDefaults, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, type Vector3, type Vector3d, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, type WorkerBackend, type WorkerContext, WorkerEndpoint, type WorkerOptions, type WorkerSession, type WorkerWork, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, cloudOfDepth, cloudOfObject, cloudsOfPrediction, decodeDepthMap, decodePointCloud, EyePop as default, encodeMultipartFormData, getBaseUrl, isSelectOperator, popSelects, randomMultipartBoundary, readableStreamFromString, resolveAuth, validateCamera, validatePop };
@@ -8698,6 +8698,7 @@ __export(index_exports, {
8698
8698
  ModelType: () => ModelType,
8699
8699
  MotionModel: () => MotionModel,
8700
8700
  PIPELINE_PATH: () => PIPELINE_PATH,
8701
+ PIPELINE_SOCKETS: () => PIPELINE_SOCKETS,
8701
8702
  PipelineBackend: () => PipelineBackend,
8702
8703
  PipelineCommandError: () => PipelineCommandError,
8703
8704
  PipelineConfigurationError: () => PipelineConfigurationError,
@@ -9050,7 +9051,7 @@ var Endpoint = class {
9050
9051
  this._expire_token_time = null;
9051
9052
  this._client = null;
9052
9053
  this._statusRetryHandlers = /* @__PURE__ */ new Map();
9053
- this._statusRetryHandlers.set(401, this.statusHandler401);
9054
+ this._statusRetryHandlers.set(401, (statusCode) => this.statusHandler401(statusCode));
9054
9055
  this._limit = new Semaphore(this._options.jobQueueLength ?? 1024);
9055
9056
  this._state = "Idle" /* Idle */;
9056
9057
  this._message = null;
@@ -9066,7 +9067,7 @@ var Endpoint = class {
9066
9067
  }
9067
9068
  setStatusRetryHandlers(statusRetryHandlers = void 0) {
9068
9069
  this._statusRetryHandlers = new Map(statusRetryHandlers);
9069
- this._statusRetryHandlers.set(401, this.statusHandler401);
9070
+ this._statusRetryHandlers.set(401, (statusCode) => this.statusHandler401(statusCode));
9070
9071
  }
9071
9072
  eyepopUrl() {
9072
9073
  if (this._options.eyepopUrl) {
@@ -11612,6 +11613,8 @@ if (isBrowser) {
11612
11613
  var PIPELINE_PATH = "/api/v1/pipeline";
11613
11614
  var SUBPROTOCOL = "eyepop.v1";
11614
11615
  var MAX_OPEN_SOURCES = 256;
11616
+ var PIPELINE_SOCKETS = 4;
11617
+ var EXTRA_SOCKET_RETRY_MS = 10 * 1e3;
11615
11618
  var COMBINED_UPLOAD_MAX_BYTES = 8 * 1024 * 1024;
11616
11619
  var CHUNK = 1;
11617
11620
  var COMBINED = 2;
@@ -11731,6 +11734,8 @@ var PipelineSocket = class {
11731
11734
  // The ids of sources sent on this socket that have neither ended nor been refused, as the
11732
11735
  // pipeline API counts them, cancelled ones included.
11733
11736
  this.held = /* @__PURE__ */ new Set();
11737
+ // The held sources that are live. A live source never ends, so nothing queued behind it plays.
11738
+ this.lives = /* @__PURE__ */ new Set();
11734
11739
  // The held sources the pipeline API took: only these end, so only these make room.
11735
11740
  this.accepted = /* @__PURE__ */ new Set();
11736
11741
  // The ends on this socket so far.
@@ -11739,6 +11744,7 @@ var PipelineSocket = class {
11739
11744
  // the next send waits. Null once none is held.
11740
11745
  this.cap = null;
11741
11746
  this._roomWaiters = [];
11747
+ this.heartbeat = null;
11742
11748
  this.closed = new Promise((resolve) => this._markClosed = resolve);
11743
11749
  }
11744
11750
  /** A source ended or the socket closed: wake the send waiting for room. */
@@ -11772,6 +11778,10 @@ var PipelineSocket = class {
11772
11778
  return !this._closed && this.ws.readyState === 1;
11773
11779
  }
11774
11780
  markClosed() {
11781
+ if (this.heartbeat !== null) {
11782
+ clearInterval(this.heartbeat);
11783
+ this.heartbeat = null;
11784
+ }
11775
11785
  this._closed = true;
11776
11786
  this._markClosed();
11777
11787
  this.freed();
@@ -11860,14 +11870,14 @@ var PipelineBackend = class {
11860
11870
  constructor(ctx) {
11861
11871
  this.ctx = ctx;
11862
11872
  this._pipelineApiUrl = null;
11863
- this._socket = null;
11873
+ this._sockets = [];
11864
11874
  this._connecting = null;
11865
11875
  // Every job's setSource and every changePop goes out through this chain, in the order submitted.
11866
11876
  this._sendChain = Promise.resolve();
11867
11877
  this._disconnecting = false;
11868
11878
  this._nextId = 0;
11869
11879
  this._warned = /* @__PURE__ */ new Set();
11870
- this._heartbeat = null;
11880
+ this._noExtraSocketUntil = 0;
11871
11881
  // Reconnects at once since a source last played.
11872
11882
  this._reconnects = 0;
11873
11883
  this._currentPop = ctx.options.pop ?? null;
@@ -11881,13 +11891,9 @@ var PipelineBackend = class {
11881
11891
  async disconnect(closeEndpoint) {
11882
11892
  await closeEndpoint();
11883
11893
  this._disconnecting = true;
11884
- if (this._heartbeat !== null) {
11885
- clearInterval(this._heartbeat);
11886
- this._heartbeat = null;
11887
- }
11888
- const socket = this._socket;
11889
- this._socket = null;
11890
- if (socket !== null) {
11894
+ const sockets = this._sockets;
11895
+ this._sockets = [];
11896
+ for (const socket of sockets) {
11891
11897
  socket.ws.close(1e3);
11892
11898
  await socket.closed;
11893
11899
  }
@@ -11905,21 +11911,55 @@ var PipelineBackend = class {
11905
11911
  this._sendChain = result.catch(() => void 0);
11906
11912
  return result;
11907
11913
  }
11908
- /** The open socket, or a new one with the last pop set on it. */
11914
+ openSockets() {
11915
+ return this._sockets.filter((socket) => socket.open);
11916
+ }
11917
+ /** An open socket, or a new one with the last pop set on it. */
11909
11918
  async ensureSocket() {
11910
- if (this._socket !== null && this._socket.open) {
11911
- return this._socket;
11919
+ const open = this.openSockets()[0];
11920
+ if (open !== void 0) {
11921
+ return open;
11912
11922
  }
11913
11923
  if (this._connecting === null) {
11914
- this._connecting = this.openSocket().finally(() => this._connecting = null);
11924
+ this._connecting = this.openSocket(true).finally(() => this._connecting = null);
11915
11925
  }
11916
11926
  return await this._connecting;
11917
11927
  }
11918
- async openSocket() {
11928
+ /**
11929
+ * The socket for the next job; the caller runs it in submission order. A live job goes on a socket
11930
+ * of its own, an idle one or a new one, which `pipelineSockets` does not count. Any other job skips
11931
+ * the sockets with a live source: a new one while every other socket has a source and fewer than
11932
+ * `pipelineSockets` are open, else the one with room and the fewest sources.
11933
+ */
11934
+ async socketForJob(job) {
11935
+ if (job.live) {
11936
+ return this.openSockets().find((socket) => socket.held.size === 0) ?? await this.openSocket(true);
11937
+ }
11938
+ const sockets = this.openSockets().filter((socket) => socket.lives.size === 0);
11939
+ if (sockets.length === 0) {
11940
+ return await this.openSocket(true);
11941
+ }
11942
+ if (sockets.length < (this.ctx.options.pipelineSockets ?? PIPELINE_SOCKETS) && sockets.every((socket) => socket.held.size > 0) && Date.now() >= this._noExtraSocketUntil) {
11943
+ try {
11944
+ return await this.openSocket(false);
11945
+ } catch (error) {
11946
+ this._noExtraSocketUntil = Date.now() + EXTRA_SOCKET_RETRY_MS;
11947
+ this.ctx.requestLogger.info("could not open another pipeline API socket: %s", error);
11948
+ }
11949
+ }
11950
+ const rank = (socket) => (socket.hasRoom ? 0 : MAX_OPEN_SOURCES + 1) + socket.held.size;
11951
+ return sockets.reduce((best, socket) => rank(socket) < rank(best) ? socket : best);
11952
+ }
11953
+ /** A new socket with the last pop set on it; `patient` waits through 503 with Retry-After. */
11954
+ async openSocket(patient) {
11919
11955
  if (this.ctx.client() === null) {
11920
11956
  throw new PipelineSocketClosedError(void 0, "the endpoint is not connected");
11921
11957
  }
11922
- const ws = await this.upgrade(await this.socketUrl());
11958
+ const ws = await this.upgrade(await this.socketUrl(), patient);
11959
+ if (this._disconnecting) {
11960
+ ws.close(1e3);
11961
+ throw new PipelineSocketClosedError(void 0, "the endpoint disconnected");
11962
+ }
11923
11963
  const socket = new PipelineSocket(ws);
11924
11964
  ws.onmessage = (event) => {
11925
11965
  if (typeof event.data === "string") {
@@ -11933,31 +11973,29 @@ var PipelineBackend = class {
11933
11973
  ws.onerror = () => {
11934
11974
  };
11935
11975
  ws.onclose = (event) => this.closed(socket, event.code, event.reason);
11936
- this._socket = socket;
11937
- this.startHeartbeat(ws);
11976
+ this._sockets.push(socket);
11977
+ this.startHeartbeat(socket);
11938
11978
  if (this._currentPop !== null) {
11939
11979
  try {
11940
11980
  await this.setPopOn(socket, this._currentPop);
11941
11981
  } catch (error) {
11942
- this._socket = null;
11982
+ this._sockets = this._sockets.filter((other) => other !== socket);
11943
11983
  ws.close(1e3);
11944
11984
  throw error;
11945
11985
  }
11946
11986
  }
11947
11987
  return socket;
11948
11988
  }
11949
- startHeartbeat(ws) {
11950
- if (this._heartbeat !== null) {
11951
- clearInterval(this._heartbeat);
11952
- }
11989
+ startHeartbeat(socket) {
11990
+ const ws = socket.ws;
11953
11991
  const ping = ws.ping;
11954
11992
  if (typeof ping === "function") {
11955
- this._heartbeat = setInterval(() => {
11993
+ socket.heartbeat = setInterval(() => {
11956
11994
  if (ws.readyState === 1) {
11957
11995
  ping.call(ws);
11958
11996
  }
11959
11997
  }, HEARTBEAT_MS);
11960
- this._heartbeat.unref?.();
11998
+ socket.heartbeat.unref?.();
11961
11999
  }
11962
12000
  }
11963
12001
  async socketUrl() {
@@ -11995,7 +12033,7 @@ var PipelineBackend = class {
11995
12033
  return (await this.ctx.credentialHeader()).replace(/^Bearer /, "");
11996
12034
  }
11997
12035
  /** Open the socket, waiting through 503 with Retry-After and exchanging the API key again after a 401. */
11998
- async upgrade(url) {
12036
+ async upgrade(url, patient) {
11999
12037
  const deadline = Date.now() + MAX_RETRY_MS;
12000
12038
  let rejected = false;
12001
12039
  while (true) {
@@ -12013,7 +12051,7 @@ var PipelineBackend = class {
12013
12051
  continue;
12014
12052
  }
12015
12053
  const wait = error.status === 503 && error.retryAfter !== void 0 ? Math.max(error.retryAfter, 1) * 1e3 : void 0;
12016
- if (wait === void 0 || Date.now() + wait > deadline) {
12054
+ if (!patient || wait === void 0 || Date.now() + wait > deadline) {
12017
12055
  throw error;
12018
12056
  }
12019
12057
  this.ctx.requestLogger.info("the pipeline API answered 503, retrying in %d ms", wait);
@@ -12023,9 +12061,7 @@ var PipelineBackend = class {
12023
12061
  }
12024
12062
  closed(socket, code, reason) {
12025
12063
  socket.markClosed();
12026
- if (this._socket === socket) {
12027
- this._socket = null;
12028
- }
12064
+ this._sockets = this._sockets.filter((other) => other !== socket);
12029
12065
  const error = new PipelineSocketClosedError(code, reason);
12030
12066
  socket.sources.forEach((source) => source.close(error));
12031
12067
  socket.commands.forEach((command) => command.reject(error));
@@ -12051,12 +12087,14 @@ var PipelineBackend = class {
12051
12087
  const source = typeof id === "string" ? socket.sources.get(id) : void 0;
12052
12088
  if (type === "end") {
12053
12089
  socket.held.delete(id);
12090
+ socket.lives.delete(id);
12054
12091
  socket.accepted.delete(id);
12055
12092
  socket.freed();
12056
12093
  } else if (type === "result" && socket.held.has(id)) {
12057
12094
  socket.accepted.add(id);
12058
12095
  } else if (type === "error" && message["error"] !== "unknown_command") {
12059
12096
  socket.held.delete(id);
12097
+ socket.lives.delete(id);
12060
12098
  socket.wake();
12061
12099
  }
12062
12100
  if (type === "send" || type === "credit") {
@@ -12098,6 +12136,10 @@ var PipelineBackend = class {
12098
12136
  command(socket, message) {
12099
12137
  const id = this.newId(message["type"]);
12100
12138
  return new Promise((resolve, reject) => {
12139
+ if (!socket.open) {
12140
+ reject(new PipelineSocketClosedError(void 0, "the socket closed"));
12141
+ return;
12142
+ }
12101
12143
  socket.commands.set(id, { resolve, reject });
12102
12144
  socket.sendJson({ ...message, id });
12103
12145
  });
@@ -12106,15 +12148,28 @@ var PipelineBackend = class {
12106
12148
  pop() {
12107
12149
  return this._currentPop;
12108
12150
  }
12109
- /** Set the pop on the socket's pipeline; a pop it refuses rejects, and the last pop it took stays. */
12151
+ /**
12152
+ * Set the pop on every open socket's pipeline; a pop the first refuses rejects, and the last pop it
12153
+ * took stays. shortcut: a refusal from a later socket, which the first took, leaves the earlier ones
12154
+ * on the new pop; a refusal is the pop's own fault, so every socket answers it alike.
12155
+ */
12110
12156
  async changePop(pop) {
12111
12157
  if (this.ctx.client() === null) {
12112
12158
  this._currentPop = pop;
12113
12159
  return;
12114
12160
  }
12115
12161
  await this.inOrder(async () => {
12116
- if (this._socket !== null && this._socket.open) {
12117
- await this.setPopOn(this._socket, pop);
12162
+ const sockets = this.openSockets();
12163
+ if (sockets.length > 0) {
12164
+ for (const socket of sockets) {
12165
+ try {
12166
+ await this.setPopOn(socket, pop);
12167
+ } catch (error) {
12168
+ if (!(error instanceof PipelineSocketClosedError)) {
12169
+ throw error;
12170
+ }
12171
+ }
12172
+ }
12118
12173
  this._currentPop = pop;
12119
12174
  return;
12120
12175
  }
@@ -12275,22 +12330,30 @@ var PipelineBackend = class {
12275
12330
  }
12276
12331
  /** Send the job's setSource; the caller runs it in submission order. */
12277
12332
  async setSource(job) {
12278
- if (job.cancelled) {
12279
- return null;
12280
- }
12281
- let socket = await this.ensureSocket();
12282
- await socket.room(job);
12283
12333
  if (job.cancelled) {
12284
12334
  return null;
12285
12335
  }
12286
12336
  const combined = await combinedMedia(job);
12287
- socket = await this.ensureSocket();
12337
+ let socket;
12338
+ while (true) {
12339
+ socket = await this.socketForJob(job);
12340
+ await socket.room(job);
12341
+ if (job.cancelled) {
12342
+ return null;
12343
+ }
12344
+ if (socket.open) {
12345
+ break;
12346
+ }
12347
+ }
12288
12348
  const source = new OpenSource(this.newId("source"));
12289
12349
  if (combined === null) {
12290
12350
  uploadKeys(job).forEach((key) => source.uploads.set(key, new Credit()));
12291
12351
  }
12292
12352
  socket.sources.set(source.id, source);
12293
12353
  socket.held.add(source.id);
12354
+ if (job.live) {
12355
+ socket.lives.add(source.id);
12356
+ }
12294
12357
  source.endedBefore = socket.ended;
12295
12358
  job.openSource = source;
12296
12359
  job.stopOnPipeline = () => {
@@ -12566,6 +12629,9 @@ var WorkerEndpoint = class extends Endpoint {
12566
12629
  if (options.jobQueueLength > MAX_OPEN_SOURCES) {
12567
12630
  throw new PipelineConfigurationError("job_queue_length", `jobQueueLength ${options.jobQueueLength} exceeds ${MAX_OPEN_SOURCES}, the open sources a pipeline API socket takes`);
12568
12631
  }
12632
+ if (options.pipelineSockets !== void 0 && !(Number.isInteger(options.pipelineSockets) && options.pipelineSockets > 0)) {
12633
+ throw new PipelineConfigurationError("pipeline_sockets", `pipelineSockets ${options.pipelineSockets} is not a positive whole number`);
12634
+ }
12569
12635
  }
12570
12636
  super(options);
12571
12637
  const context = {
@@ -14541,6 +14607,7 @@ var index_default = EyePop;
14541
14607
  ModelType,
14542
14608
  MotionModel,
14543
14609
  PIPELINE_PATH,
14610
+ PIPELINE_SOCKETS,
14544
14611
  PipelineBackend,
14545
14612
  PipelineCommandError,
14546
14613
  PipelineConfigurationError,