@camstack/addon-post-analysis 1.2.350 → 1.2.352
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/{clip-model-registry-DI12tTgY.js → clip-model-registry-CPNsQNt5.js} +302 -158
- package/dist/{clip-model-registry-CC-BJYiK.mjs → clip-model-registry-VI28etdt.mjs} +302 -158
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -2
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-yG9S0rx2.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DPlNaYLS.mjs} +3 -3
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-N64PaPIw.mjs +26 -0
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Clwp5JZq.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-C20VEWyk.mjs → hostInit-DFfu0TT0.mjs} +3 -3
- package/dist/pipeline-analytics/index.js +677 -941
- package/dist/pipeline-analytics/index.mjs +677 -941
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Du_tzgi2.mjs +0 -26
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQOJKiwa.mjs +0 -26
|
@@ -5480,7 +5480,7 @@ var ZodIssueCode = {
|
|
|
5480
5480
|
var ZodFirstPartyTypeKind;
|
|
5481
5481
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5482
5482
|
//#endregion
|
|
5483
|
-
//#region ../types/dist/sleep-
|
|
5483
|
+
//#region ../types/dist/sleep-CI0n5D44.mjs
|
|
5484
5484
|
/**
|
|
5485
5485
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5486
5486
|
* window to float samples (D455).
|
|
@@ -9970,6 +9970,16 @@ var CompositionSchema = object({
|
|
|
9970
9970
|
seen.add(feature.cap);
|
|
9971
9971
|
});
|
|
9972
9972
|
});
|
|
9973
|
+
var NodeColorIdSchema = _enum([
|
|
9974
|
+
"node-a",
|
|
9975
|
+
"node-b",
|
|
9976
|
+
"node-c",
|
|
9977
|
+
"node-d",
|
|
9978
|
+
"node-e",
|
|
9979
|
+
"node-f",
|
|
9980
|
+
"node-g",
|
|
9981
|
+
"node-h"
|
|
9982
|
+
]);
|
|
9973
9983
|
var OWNER_TYPES = new Set([
|
|
9974
9984
|
"track",
|
|
9975
9985
|
"face",
|
|
@@ -28981,24 +28991,69 @@ var RetrainFrameListSchema = object({
|
|
|
28981
28991
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
28982
28992
|
autoPickMediaId: number().int().optional()
|
|
28983
28993
|
});
|
|
28994
|
+
/** Exclusive partition of a corpus copy's annotation progress (design §4.2). */
|
|
28995
|
+
var RetrainFrameWorkStateSchema = _enum([
|
|
28996
|
+
"unannotated",
|
|
28997
|
+
"annotated",
|
|
28998
|
+
"complete"
|
|
28999
|
+
]);
|
|
29000
|
+
/**
|
|
29001
|
+
* Filters for paginated corpus list, KPI, and matching export (design §4.4).
|
|
29002
|
+
* Every narrowing field is ANDed; omitted fields impose no constraint.
|
|
29003
|
+
*/
|
|
29004
|
+
var RetrainCorpusFilterSchema = object({
|
|
29005
|
+
workState: RetrainFrameWorkStateSchema.optional(),
|
|
29006
|
+
deviceIds: array(number()).max(500).optional(),
|
|
29007
|
+
/** When set, only frames in this named collection. */
|
|
29008
|
+
collectionId: string().optional(),
|
|
29009
|
+
/** Frames that carry at least one saved annotation in one of these classes. */
|
|
29010
|
+
classes: array(RetrainMacroClassSchema).optional(),
|
|
29011
|
+
page: number().int().positive().default(1),
|
|
29012
|
+
pageSize: number().int().positive().max(100).default(50)
|
|
29013
|
+
});
|
|
29014
|
+
var RetrainCorpusPageSchema = object({
|
|
29015
|
+
frames: array(RetrainFrameSchema.extend({ workState: RetrainFrameWorkStateSchema })).readonly(),
|
|
29016
|
+
total: number().int().nonnegative(),
|
|
29017
|
+
page: number().int().positive(),
|
|
29018
|
+
pageSize: number().int().positive()
|
|
29019
|
+
});
|
|
29020
|
+
var RetrainCorpusKpiCameraRowSchema = object({
|
|
29021
|
+
deviceId: number(),
|
|
29022
|
+
unannotated: number().int().nonnegative(),
|
|
29023
|
+
annotated: number().int().nonnegative(),
|
|
29024
|
+
complete: number().int().nonnegative(),
|
|
29025
|
+
/** This camera's `complete` count divided by corpus `total`, in `[0,1]`.
|
|
29026
|
+
* `null` when the corpus is empty (no ratio). */
|
|
29027
|
+
pctOfCorpus: number().min(0).max(1).nullable()
|
|
29028
|
+
});
|
|
29029
|
+
var RetrainCorpusKpiSchema = object({
|
|
29030
|
+
total: number().int().nonnegative(),
|
|
29031
|
+
unannotated: number().int().nonnegative(),
|
|
29032
|
+
annotated: number().int().nonnegative(),
|
|
29033
|
+
complete: number().int().nonnegative(),
|
|
29034
|
+
cameras: array(RetrainCorpusKpiCameraRowSchema).readonly()
|
|
29035
|
+
});
|
|
28984
29036
|
/**
|
|
28985
29037
|
* Which frames an annotated export carries. Every field narrows; an empty
|
|
28986
|
-
* filter is every annotated copy.
|
|
28987
|
-
*
|
|
28988
|
-
*
|
|
28989
|
-
*
|
|
29038
|
+
* filter is every annotated copy. `frameIds` is the primitive a job or
|
|
29039
|
+
* download uses; `batchId` re-selects what an earlier export carried
|
|
29040
|
+
* (`exportedInBatch`). Frozen dataset versions were removed — live selection
|
|
29041
|
+
* resolves to `frameIds` at plan/start.
|
|
28990
29042
|
*/
|
|
28991
29043
|
var RetrainExportFilterSchema = object({
|
|
28992
29044
|
deviceIds: array(number()).optional(),
|
|
28993
29045
|
frameIds: array(string()).max(2e4).optional(),
|
|
28994
29046
|
/** Only frames in at least one of these named collections. */
|
|
28995
29047
|
collectionIds: array(string()).max(200).optional(),
|
|
28996
|
-
/**
|
|
28997
|
-
|
|
28998
|
-
datasetVersionId: string().optional(),
|
|
29048
|
+
/** Single collection (Frames filter bar). ANDed with `collectionIds` when both set. */
|
|
29049
|
+
collectionId: string().optional(),
|
|
28999
29050
|
batchId: string().optional(),
|
|
29000
29051
|
/** Only frames the operator marked complete (all subjects boxed). */
|
|
29001
|
-
completeOnly: boolean().optional()
|
|
29052
|
+
completeOnly: boolean().optional(),
|
|
29053
|
+
/** Exclusive work-state partition (`workStateOf`); same as the corpus list. */
|
|
29054
|
+
workState: RetrainFrameWorkStateSchema.optional(),
|
|
29055
|
+
/** Frames with at least one saved annotation in one of these classes. */
|
|
29056
|
+
classes: array(RetrainMacroClassSchema).optional()
|
|
29002
29057
|
});
|
|
29003
29058
|
/**
|
|
29004
29059
|
* `frames`: the full frame copies, boxes in `annotations.json`.
|
|
@@ -29198,8 +29253,7 @@ var RetrainDatasetStatsSchema = object({
|
|
|
29198
29253
|
completeFrames: number().int()
|
|
29199
29254
|
})).readonly()
|
|
29200
29255
|
});
|
|
29201
|
-
|
|
29202
|
-
var RetrainDatasetVersionSchema = object({
|
|
29256
|
+
object({
|
|
29203
29257
|
id: string(),
|
|
29204
29258
|
name: string(),
|
|
29205
29259
|
createdAt: number(),
|
|
@@ -29207,22 +29261,33 @@ var RetrainDatasetVersionSchema = object({
|
|
|
29207
29261
|
layout: RetrainExportLayoutSchema,
|
|
29208
29262
|
completeOnly: boolean(),
|
|
29209
29263
|
frameCount: number().int(),
|
|
29210
|
-
/** sha256 of what the frames taught when the version was frozen. */
|
|
29211
29264
|
annotationHash: string(),
|
|
29212
|
-
/** The export manifest schema the version was cut under. */
|
|
29213
29265
|
manifestSchema: string(),
|
|
29214
29266
|
stats: RetrainDatasetStatsSchema
|
|
29215
29267
|
});
|
|
29216
|
-
|
|
29217
|
-
|
|
29218
|
-
|
|
29268
|
+
/**
|
|
29269
|
+
* Live training corpus criteria — same shape as `TrainingCorpusSelection` on
|
|
29270
|
+
* the training cap. Resolved here so plan/start and the annotated export share
|
|
29271
|
+
* one definition of "the frames" (`buildRetrainExportPlan`).
|
|
29272
|
+
*/
|
|
29273
|
+
var RetrainTrainingCorpusSelectionSchema = object({
|
|
29274
|
+
collectionIds: array(string()).min(1),
|
|
29275
|
+
workState: _enum([
|
|
29276
|
+
"complete",
|
|
29277
|
+
"annotated_or_complete",
|
|
29278
|
+
"any_annotated"
|
|
29279
|
+
]).default("complete")
|
|
29280
|
+
});
|
|
29281
|
+
var RetrainTrainingCorpusResolveResultSchema = discriminatedUnion("kind", [object({
|
|
29282
|
+
kind: literal("resolved"),
|
|
29283
|
+
frameIds: array(string()).max(2e4).readonly(),
|
|
29284
|
+
stats: RetrainDatasetStatsSchema,
|
|
29285
|
+
annotationHash: string(),
|
|
29286
|
+
layout: RetrainExportLayoutSchema
|
|
29219
29287
|
}), object({
|
|
29220
29288
|
kind: literal("refused"),
|
|
29221
|
-
reason: _enum([
|
|
29222
|
-
|
|
29223
|
-
"duplicate-name",
|
|
29224
|
-
"no-frames"
|
|
29225
|
-
])
|
|
29289
|
+
reason: _enum(["unknown-collection", "no-frames"]),
|
|
29290
|
+
detail: string()
|
|
29226
29291
|
})]);
|
|
29227
29292
|
/** The outcome of a lifecycle move owned by the retrain page. */
|
|
29228
29293
|
var RetrainTransitionResultSchema = object({
|
|
@@ -30398,6 +30463,26 @@ var pipelineAnalyticsCapability = {
|
|
|
30398
30463
|
auth: "admin"
|
|
30399
30464
|
}),
|
|
30400
30465
|
/**
|
|
30466
|
+
* Paginated corpus copies for the Frames grid — index reads only.
|
|
30467
|
+
*
|
|
30468
|
+
* Filters AND (`workState`, cameras, one collection, annotated classes).
|
|
30469
|
+
* An answered empty match is `{ frames: [], total: 0, … }` (D315), never a
|
|
30470
|
+
* pending masquerade. Classification uses `workStateOf` (annotation count
|
|
30471
|
+
* wins over a stray `complete` flag).
|
|
30472
|
+
*/
|
|
30473
|
+
listRetrainCorpusPage: method(RetrainCorpusFilterSchema, RetrainCorpusPageSchema, {
|
|
30474
|
+
kind: "query",
|
|
30475
|
+
auth: "admin"
|
|
30476
|
+
}),
|
|
30477
|
+
/**
|
|
30478
|
+
* Global + per-camera corpus KPI. Unfiltered totals; `%` on a camera row is
|
|
30479
|
+
* `complete(camera) / corpus total`, or `null` when the corpus is empty.
|
|
30480
|
+
*/
|
|
30481
|
+
getRetrainCorpusKpi: method(object({}), RetrainCorpusKpiSchema, {
|
|
30482
|
+
kind: "query",
|
|
30483
|
+
auth: "admin"
|
|
30484
|
+
}),
|
|
30485
|
+
/**
|
|
30401
30486
|
* What a track can contribute, and what it already has.
|
|
30402
30487
|
*
|
|
30403
30488
|
* `candidates` are the track's whole, unannotated frames — index rows only,
|
|
@@ -30624,53 +30709,6 @@ var pipelineAnalyticsCapability = {
|
|
|
30624
30709
|
auth: "admin",
|
|
30625
30710
|
timeoutMs: 12e4
|
|
30626
30711
|
}),
|
|
30627
|
-
/** The counts a selection would freeze — class × camera × day/night,
|
|
30628
|
-
* completeness — without freezing anything. Index reads only. */
|
|
30629
|
-
previewRetrainDataset: method(object({
|
|
30630
|
-
selection: RetrainDatasetSelectionSchema,
|
|
30631
|
-
completeOnly: boolean().optional()
|
|
30632
|
-
}), RetrainDatasetStatsSchema, {
|
|
30633
|
-
kind: "query",
|
|
30634
|
-
auth: "admin"
|
|
30635
|
-
}),
|
|
30636
|
-
/**
|
|
30637
|
-
* Freeze a dataset version: the frames the selection yields (the same plan
|
|
30638
|
-
* the annotated export builds), the hash of what they teach, the export
|
|
30639
|
-
* parameters and the counts. Immutable — a different selection is a new
|
|
30640
|
-
* version. Export it with `getRetrainExportUrl({ datasetVersionId })`.
|
|
30641
|
-
*/
|
|
30642
|
-
createRetrainDatasetVersion: method(object({
|
|
30643
|
-
name: string().max(120),
|
|
30644
|
-
selection: RetrainDatasetSelectionSchema,
|
|
30645
|
-
layout: RetrainExportLayoutSchema,
|
|
30646
|
-
completeOnly: boolean()
|
|
30647
|
-
}), CreateRetrainDatasetVersionResultSchema, {
|
|
30648
|
-
kind: "mutation",
|
|
30649
|
-
auth: "admin",
|
|
30650
|
-
timeoutMs: 12e4
|
|
30651
|
-
}),
|
|
30652
|
-
/** Every dataset version, newest first. */
|
|
30653
|
-
listRetrainDatasetVersions: method(object({}), array(RetrainDatasetVersionSchema).readonly(), {
|
|
30654
|
-
kind: "query",
|
|
30655
|
-
auth: "admin"
|
|
30656
|
-
}),
|
|
30657
|
-
/** Delete a version. Its frames stay in the dataset. */
|
|
30658
|
-
deleteRetrainDatasetVersion: method(object({ id: string() }), object({ deleted: boolean() }), {
|
|
30659
|
-
kind: "mutation",
|
|
30660
|
-
auth: "admin"
|
|
30661
|
-
}),
|
|
30662
|
-
/** Does the corpus still teach what the version froze? `missingFrames`
|
|
30663
|
-
* counts frames that left the dataset (or lost every box and tick). */
|
|
30664
|
-
verifyRetrainDatasetVersion: method(object({ id: string() }), object({
|
|
30665
|
-
found: boolean(),
|
|
30666
|
-
annotationHash: string(),
|
|
30667
|
-
matches: boolean(),
|
|
30668
|
-
missingFrames: number().int()
|
|
30669
|
-
}), {
|
|
30670
|
-
kind: "query",
|
|
30671
|
-
auth: "admin",
|
|
30672
|
-
timeoutMs: 12e4
|
|
30673
|
-
}),
|
|
30674
30712
|
/** The enabled, vision-capable LLM profiles, each saying whether a frame
|
|
30675
30713
|
* sent to it leaves the house. */
|
|
30676
30714
|
listRetrainAssistProfiles: method(object({}), array(RetrainAssistProfileSchema).readonly(), {
|
|
@@ -30717,6 +30755,16 @@ var pipelineAnalyticsCapability = {
|
|
|
30717
30755
|
kind: "query",
|
|
30718
30756
|
auth: "admin"
|
|
30719
30757
|
}),
|
|
30758
|
+
/**
|
|
30759
|
+
* Resolve a live training corpus selection to frame ids + stats (index
|
|
30760
|
+
* reads only). Same plan the annotated export builds — training plan/start
|
|
30761
|
+
* calls this instead of a frozen dataset version.
|
|
30762
|
+
*/
|
|
30763
|
+
resolveRetrainTrainingCorpus: method(RetrainTrainingCorpusSelectionSchema, RetrainTrainingCorpusResolveResultSchema, {
|
|
30764
|
+
kind: "query",
|
|
30765
|
+
auth: "admin",
|
|
30766
|
+
timeoutMs: 6e4
|
|
30767
|
+
}),
|
|
30720
30768
|
renameRetrainCollection: method(object({
|
|
30721
30769
|
id: string(),
|
|
30722
30770
|
name: string().max(120)
|
|
@@ -31670,11 +31718,14 @@ var HardwareClassIdSchema = _enum([
|
|
|
31670
31718
|
"intel-n-series",
|
|
31671
31719
|
"apple-m-base",
|
|
31672
31720
|
"apple-m-pro",
|
|
31721
|
+
"amd-phoenix",
|
|
31673
31722
|
"unknown"
|
|
31674
31723
|
]);
|
|
31675
31724
|
var AcceleratorKindSchema = _enum([
|
|
31676
31725
|
"intel-npu",
|
|
31677
31726
|
"intel-igpu",
|
|
31727
|
+
"amd-igpu",
|
|
31728
|
+
"amd-npu",
|
|
31678
31729
|
"x86-cpu",
|
|
31679
31730
|
"arm-cpu",
|
|
31680
31731
|
"apple-ane",
|
|
@@ -33810,6 +33861,8 @@ var AgentPipelineSettingsSchema = object({
|
|
|
33810
33861
|
* address is wrong (multi-homed host, NAT, custom interface).
|
|
33811
33862
|
*/
|
|
33812
33863
|
reachableHost: string().optional(),
|
|
33864
|
+
/** Hub-persisted UI colour (`--color-node-*` theme tokens). */
|
|
33865
|
+
color: NodeColorIdSchema.optional(),
|
|
33813
33866
|
/**
|
|
33814
33867
|
* Multi-device inference opt-in (Phase 4). Per-node map deviceKey → {enabled,
|
|
33815
33868
|
* weight, steps}. Absent / all-disabled ⇒ the node's single default
|
|
@@ -34536,8 +34589,9 @@ var pipelineOrchestratorCapability = {
|
|
|
34536
34589
|
*/
|
|
34537
34590
|
setAgentReachableHost: method(object({
|
|
34538
34591
|
agentNodeId: string(),
|
|
34539
|
-
reachableHost: string().nullable()
|
|
34540
|
-
|
|
34592
|
+
reachableHost: string().nullable().optional(),
|
|
34593
|
+
color: NodeColorIdSchema.nullable().optional()
|
|
34594
|
+
}).refine((v) => v.reachableHost !== void 0 || v.color !== void 0, { message: "reachableHost or color required" }), object({ success: literal(true) }), {
|
|
34541
34595
|
kind: "mutation",
|
|
34542
34596
|
auth: "admin"
|
|
34543
34597
|
}),
|
|
@@ -45641,7 +45695,15 @@ var GpuInfoSchema = object({
|
|
|
45641
45695
|
name: string(),
|
|
45642
45696
|
memoryMB: number().optional()
|
|
45643
45697
|
});
|
|
45644
|
-
var NpuInfoSchema = object({
|
|
45698
|
+
var NpuInfoSchema = object({
|
|
45699
|
+
type: _enum([
|
|
45700
|
+
"apple-ane",
|
|
45701
|
+
"intel-npu",
|
|
45702
|
+
"amd-xdna"
|
|
45703
|
+
]),
|
|
45704
|
+
name: string().optional(),
|
|
45705
|
+
generation: _enum(["xdna1", "xdna2"]).optional()
|
|
45706
|
+
});
|
|
45645
45707
|
var CoralInfoSchema = object({
|
|
45646
45708
|
type: literal("coral-edgetpu"),
|
|
45647
45709
|
bus: string().optional()
|
|
@@ -51018,9 +51080,11 @@ var zoneRulesCapability = {
|
|
|
51018
51080
|
* once is what makes a second provider (RunPod, a local NVIDIA node) a new
|
|
51019
51081
|
* manifest entry and nothing else.
|
|
51020
51082
|
*
|
|
51021
|
-
* Collection
|
|
51022
|
-
*
|
|
51023
|
-
*
|
|
51083
|
+
* Collection of provider **types** (addons). Each addon owns zero or more
|
|
51084
|
+
* **entries** (credentials + defaults). Concat-fans: `describe`,
|
|
51085
|
+
* `describeTypes`, `listEntries`, `listJobs`. Single-row work is keyed by
|
|
51086
|
+
* `entryId`; callers also pass the owning `addonId` as the collection
|
|
51087
|
+
* selector (broker posture). Every method is `admin`: these spend money.
|
|
51024
51088
|
*
|
|
51025
51089
|
* Every cloud object a provider creates is tagged with the orchestrator's
|
|
51026
51090
|
* `jobKey`, so a retried submit finds the job it already started instead of
|
|
@@ -51044,8 +51108,8 @@ var TrainingRegionOptionSchema = object({
|
|
|
51044
51108
|
priceMultiplier: number().positive()
|
|
51045
51109
|
});
|
|
51046
51110
|
/**
|
|
51047
|
-
* The provider's per-
|
|
51048
|
-
* live
|
|
51111
|
+
* The provider's per-entry settings, as the orchestrator reads them. They
|
|
51112
|
+
* live on the PROVIDER addon's entry (operator decision 2026-10-08: they
|
|
51049
51113
|
* depend on the user's account), never hard-coded in the orchestrator.
|
|
51050
51114
|
*/
|
|
51051
51115
|
var TrainingProviderDefaultsSchema = object({
|
|
@@ -51056,9 +51120,32 @@ var TrainingProviderDefaultsSchema = object({
|
|
|
51056
51120
|
/** Hours a FAILED job's cloud dataset is kept for debugging; 0 = delete at once. */
|
|
51057
51121
|
failedDatasetGraceHours: number().nonnegative()
|
|
51058
51122
|
});
|
|
51123
|
+
/** One creatable provider type, for the Add-entry dialog. */
|
|
51124
|
+
var TrainingProviderTypeSchema = object({
|
|
51125
|
+
typeId: string(),
|
|
51126
|
+
label: string(),
|
|
51127
|
+
/** Path under the addon package (e.g. `assets/training-modal/icon.svg`). */
|
|
51128
|
+
iconAsset: string(),
|
|
51129
|
+
/** Owning `training-provider` addon — collection selector for createEntry. */
|
|
51130
|
+
addonId: string()
|
|
51131
|
+
});
|
|
51132
|
+
/** One configured account / workspace under a provider type. */
|
|
51133
|
+
var TrainingProviderEntrySchema = object({
|
|
51134
|
+
entryId: string(),
|
|
51135
|
+
typeId: string(),
|
|
51136
|
+
name: string(),
|
|
51137
|
+
addonId: string(),
|
|
51138
|
+
/** Credentials are present — never the values. */
|
|
51139
|
+
configured: boolean()
|
|
51140
|
+
});
|
|
51059
51141
|
var TrainingProviderDescriptorSchema = object({
|
|
51060
51142
|
addonId: string(),
|
|
51061
|
-
|
|
51143
|
+
entryId: string(),
|
|
51144
|
+
typeId: string(),
|
|
51145
|
+
/** Operator-chosen entry name. */
|
|
51146
|
+
name: string(),
|
|
51147
|
+
iconAsset: string(),
|
|
51148
|
+
/** `modal`, `runpod`, `fake`, … — same as typeId for current providers. */
|
|
51062
51149
|
kind: string(),
|
|
51063
51150
|
label: string(),
|
|
51064
51151
|
gpuTypes: array(TrainingGpuOptionSchema).readonly(),
|
|
@@ -51122,8 +51209,9 @@ var TrainerSourceRefSchema = object({
|
|
|
51122
51209
|
/** A commit sha (never a branch) — the job must be reproducible. */
|
|
51123
51210
|
revision: string().regex(/^[0-9a-f]{7,64}$/)
|
|
51124
51211
|
});
|
|
51212
|
+
/** Cloud job identity — route with the owning addon's `addonId` selector. */
|
|
51125
51213
|
var JobRef = {
|
|
51126
|
-
|
|
51214
|
+
entryId: string().min(1),
|
|
51127
51215
|
jobKey: string().uuid()
|
|
51128
51216
|
};
|
|
51129
51217
|
var TrainingLogLineSchema = object({
|
|
@@ -51136,17 +51224,37 @@ var trainingProviderCapability = {
|
|
|
51136
51224
|
mode: "collection",
|
|
51137
51225
|
internal: true,
|
|
51138
51226
|
methods: {
|
|
51139
|
-
/** Every
|
|
51227
|
+
/** Every entry's offer and settings. Concat-fans across providers. */
|
|
51140
51228
|
describe: method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "admin" }),
|
|
51141
|
-
/**
|
|
51142
|
-
|
|
51229
|
+
/** Creatable types for the Add-entry dialog. Concat-fans. */
|
|
51230
|
+
describeTypes: method(object({}), array(TrainingProviderTypeSchema).readonly(), { auth: "admin" }),
|
|
51231
|
+
/** Configured entries (pills). Concat-fans. */
|
|
51232
|
+
listEntries: method(object({}), array(TrainingProviderEntrySchema).readonly(), { auth: "admin" }),
|
|
51233
|
+
/**
|
|
51234
|
+
* Create an entry under this provider type. Pin with `{ addonId }` of the
|
|
51235
|
+
* type's owning addon (from describeTypes).
|
|
51236
|
+
*/
|
|
51237
|
+
createEntry: method(object({
|
|
51238
|
+
typeId: string().min(1),
|
|
51239
|
+
name: string().min(1)
|
|
51240
|
+
}), object({ entryId: string() }), {
|
|
51241
|
+
kind: "mutation",
|
|
51242
|
+
auth: "admin"
|
|
51243
|
+
}),
|
|
51244
|
+
/** Delete an entry. Pin with the owning `{ addonId }`. */
|
|
51245
|
+
deleteEntry: method(object({ entryId: string().min(1) }), object({ ok: literal(true) }), {
|
|
51246
|
+
kind: "mutation",
|
|
51247
|
+
auth: "admin"
|
|
51248
|
+
}),
|
|
51249
|
+
/** Call the provider with the entry's stored credentials. Never returns them. */
|
|
51250
|
+
validateCredentials: method(object({ entryId: string().min(1) }), TrainingCredentialCheckSchema, {
|
|
51143
51251
|
kind: "mutation",
|
|
51144
51252
|
auth: "admin",
|
|
51145
51253
|
timeoutMs: 3e4
|
|
51146
51254
|
}),
|
|
51147
51255
|
/** USD range for a run of `gpuSeconds` on `gpuType` in `region`. */
|
|
51148
51256
|
estimateJob: method(object({
|
|
51149
|
-
|
|
51257
|
+
entryId: string().min(1),
|
|
51150
51258
|
gpuType: string(),
|
|
51151
51259
|
region: string(),
|
|
51152
51260
|
datasetBytes: number().int().nonnegative(),
|
|
@@ -51242,8 +51350,11 @@ var trainingProviderCapability = {
|
|
|
51242
51350
|
auth: "admin",
|
|
51243
51351
|
timeoutMs: 5 * 6e4
|
|
51244
51352
|
}),
|
|
51245
|
-
/**
|
|
51246
|
-
|
|
51353
|
+
/**
|
|
51354
|
+
* Jobs this provider can still see. Optional `entryId` filters; omit to
|
|
51355
|
+
* list every entry (orphan sweep). Pin with `{ addonId }`.
|
|
51356
|
+
*/
|
|
51357
|
+
listJobs: method(object({ entryId: string().min(1).optional() }), array(ProviderJobStatusSchema).readonly(), {
|
|
51247
51358
|
auth: "admin",
|
|
51248
51359
|
timeoutMs: 2 * 6e4
|
|
51249
51360
|
})
|
|
@@ -51255,20 +51366,31 @@ var trainingProviderCapability = {
|
|
|
51255
51366
|
*
|
|
51256
51367
|
* It owns what every provider must agree on, written once:
|
|
51257
51368
|
*
|
|
51258
|
-
* - **Dataset versions.** Taken over from pipeline-analytics (D796): the rows
|
|
51259
|
-
* live here (D808); pipeline-analytics still CUTS a version (it owns the corpus and
|
|
51260
|
-
* the export plan) and reaches this store through the five row methods
|
|
51261
|
-
* below, so the Retrain page and the export did not change.
|
|
51262
51369
|
* - **Jobs.** A persisted state machine, a reconcile loop against the
|
|
51263
51370
|
* provider, a cost guard, a daily orphan sweep and the retention rules.
|
|
51264
51371
|
* - **The return flow.** Verified artefacts → Model Studio
|
|
51265
51372
|
* (`custom-model-registry.importModelBundle`) → canary on cameras →
|
|
51266
51373
|
* rollback. Nothing is ever registered automatically.
|
|
51267
51374
|
*
|
|
51375
|
+
* Plan/start takes a live {@link TrainingCorpusSelection} (collections +
|
|
51376
|
+
* work-state rule); frame ids are resolved via pipeline-analytics at that
|
|
51377
|
+
* moment and snapshotted on the job. No frozen dataset version.
|
|
51378
|
+
*
|
|
51268
51379
|
* Every method is `admin`.
|
|
51269
51380
|
*/
|
|
51270
|
-
/**
|
|
51271
|
-
|
|
51381
|
+
/**
|
|
51382
|
+
* Live corpus criteria for plan/start (design §5.2). Default is complete-only.
|
|
51383
|
+
* Frame ids are resolved at plan/start — never a frozen version id.
|
|
51384
|
+
*/
|
|
51385
|
+
var TrainingCorpusSelectionSchema = object({
|
|
51386
|
+
collectionIds: array(string()).min(1),
|
|
51387
|
+
/** Default complete-only for v1 */
|
|
51388
|
+
workState: _enum([
|
|
51389
|
+
"complete",
|
|
51390
|
+
"annotated_or_complete",
|
|
51391
|
+
"any_annotated"
|
|
51392
|
+
]).default("complete")
|
|
51393
|
+
});
|
|
51272
51394
|
/** A base model a detector job can fine-tune, and the baseline it is judged against. */
|
|
51273
51395
|
var TrainingBaseModelSchema = object({
|
|
51274
51396
|
modelId: string(),
|
|
@@ -51286,9 +51408,13 @@ var TrainingPresetSchema = _enum([
|
|
|
51286
51408
|
"thorough"
|
|
51287
51409
|
]);
|
|
51288
51410
|
var TrainingJobRequestSchema = object({
|
|
51289
|
-
|
|
51290
|
-
|
|
51291
|
-
|
|
51411
|
+
/** Live collection + work-state criteria; resolved at plan/start. */
|
|
51412
|
+
selection: TrainingCorpusSelectionSchema,
|
|
51413
|
+
/**
|
|
51414
|
+
* The provider **entry** that runs it (credentials + defaults).
|
|
51415
|
+
* Resolve to an owning addon via `training-provider.describe` / `listEntries`.
|
|
51416
|
+
*/
|
|
51417
|
+
entryId: string().min(1),
|
|
51292
51418
|
gpuType: string().min(1),
|
|
51293
51419
|
region: string(),
|
|
51294
51420
|
baseModelId: string().min(1),
|
|
@@ -51347,6 +51473,7 @@ var TrainingJobPlanSchema = object({
|
|
|
51347
51473
|
* result lives after the operator acted on it.
|
|
51348
51474
|
*/
|
|
51349
51475
|
var TrainingJobStateSchema = _enum([
|
|
51476
|
+
"queued",
|
|
51350
51477
|
"uploading",
|
|
51351
51478
|
"submitted",
|
|
51352
51479
|
"starting",
|
|
@@ -51400,6 +51527,11 @@ var TrainingJobSchema = object({
|
|
|
51400
51527
|
createdAt: number(),
|
|
51401
51528
|
updatedAt: number(),
|
|
51402
51529
|
state: TrainingJobStateSchema,
|
|
51530
|
+
/**
|
|
51531
|
+
* Shared by every job enqueued together via `startJobBatch`.
|
|
51532
|
+
* `null` for a lone `startJob`. The engine advances queued siblings by this id.
|
|
51533
|
+
*/
|
|
51534
|
+
batchId: string().nullable().default(null),
|
|
51403
51535
|
stage: TrainingStageSchema.nullable(),
|
|
51404
51536
|
failure: object({
|
|
51405
51537
|
reason: TrainingFailureReasonSchema,
|
|
@@ -51411,6 +51543,12 @@ var TrainingJobSchema = object({
|
|
|
51411
51543
|
maxRuntimeSec: number().int().positive(),
|
|
51412
51544
|
trainer: TrainerSourceRefSchema,
|
|
51413
51545
|
datasetLayout: RetrainExportLayoutSchema,
|
|
51546
|
+
/** Frame count snapshotted when the job started (audit; equals `frameIds.length`). */
|
|
51547
|
+
frameCount: number().int().nonnegative(),
|
|
51548
|
+
/** Resolved frame ids at start — the archive ships exactly these. */
|
|
51549
|
+
frameIds: array(string()).max(2e4).readonly(),
|
|
51550
|
+
/** Hash of what those frames taught at start (trainer `dataset.annotationHash`). */
|
|
51551
|
+
annotationHash: string(),
|
|
51414
51552
|
dataset: object({
|
|
51415
51553
|
bytes: number().int(),
|
|
51416
51554
|
sha256: string(),
|
|
@@ -51458,19 +51596,6 @@ var trainingCapability = {
|
|
|
51458
51596
|
mode: "singleton",
|
|
51459
51597
|
mount: { kind: "hub-only" },
|
|
51460
51598
|
methods: {
|
|
51461
|
-
/** Store a version once. `stored: false` = that id already exists (immutable). */
|
|
51462
|
-
putDatasetVersion: method(TrainingDatasetVersionRowSchema, object({ stored: boolean() }), {
|
|
51463
|
-
kind: "mutation",
|
|
51464
|
-
auth: "admin"
|
|
51465
|
-
}),
|
|
51466
|
-
getDatasetVersion: method(IdInput, TrainingDatasetVersionRowSchema.nullable(), { auth: "admin" }),
|
|
51467
|
-
/** Every version without its frame list, newest first. */
|
|
51468
|
-
listDatasetVersions: method(object({}), array(RetrainDatasetVersionSchema).readonly(), { auth: "admin" }),
|
|
51469
|
-
findDatasetVersionIdByName: method(object({ name: string() }), object({ id: string().nullable() }), { auth: "admin" }),
|
|
51470
|
-
removeDatasetVersion: method(IdInput, object({ removed: boolean() }), {
|
|
51471
|
-
kind: "mutation",
|
|
51472
|
-
auth: "admin"
|
|
51473
|
-
}),
|
|
51474
51599
|
listBaseModels: method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" }),
|
|
51475
51600
|
/** Split, estimate, defaults and any named refusal — nothing is started. */
|
|
51476
51601
|
planJob: method(TrainingJobRequestSchema, TrainingJobPlanSchema, {
|
|
@@ -51499,6 +51624,32 @@ var trainingCapability = {
|
|
|
51499
51624
|
auth: "admin",
|
|
51500
51625
|
timeoutMs: 12e4
|
|
51501
51626
|
}),
|
|
51627
|
+
/**
|
|
51628
|
+
* Enqueue one job per base model (same selection, entry, caps). The first
|
|
51629
|
+
* becomes `uploading`; the rest stay `queued` until the prior job settles.
|
|
51630
|
+
* One ACTIVE job at a time — a parallel `startJob` still gets
|
|
51631
|
+
* `job-already-running`. The same `idempotencyKey` returns the batch it
|
|
51632
|
+
* already started.
|
|
51633
|
+
*/
|
|
51634
|
+
startJobBatch: method(TrainingJobRequestSchema.omit({ baseModelId: true }).extend({
|
|
51635
|
+
baseModelIds: array(string().min(1)).min(1),
|
|
51636
|
+
name: string().min(1).max(120),
|
|
51637
|
+
maxCostUsd: number().positive(),
|
|
51638
|
+
maxRuntimeSec: number().int().positive(),
|
|
51639
|
+
idempotencyKey: string().min(8).max(80)
|
|
51640
|
+
}), discriminatedUnion("kind", [object({
|
|
51641
|
+
kind: literal("started"),
|
|
51642
|
+
batchId: string(),
|
|
51643
|
+
jobs: array(TrainingJobSchema).min(1).readonly()
|
|
51644
|
+
}), object({
|
|
51645
|
+
kind: literal("refused"),
|
|
51646
|
+
reason: TrainingRefusalReasonSchema,
|
|
51647
|
+
detail: string()
|
|
51648
|
+
})]), {
|
|
51649
|
+
kind: "mutation",
|
|
51650
|
+
auth: "admin",
|
|
51651
|
+
timeoutMs: 12e4
|
|
51652
|
+
}),
|
|
51502
51653
|
listJobs: method(object({}), array(TrainingJobSchema).readonly(), { auth: "admin" }),
|
|
51503
51654
|
getJob: method(IdInput, TrainingJobSchema.nullable(), { auth: "admin" }),
|
|
51504
51655
|
cancelJob: method(IdInput, TrainingJobSchema, {
|
|
@@ -56857,12 +57008,6 @@ Object.freeze({
|
|
|
56857
57008
|
addonId: null,
|
|
56858
57009
|
access: "create"
|
|
56859
57010
|
},
|
|
56860
|
-
"pipelineAnalytics.createRetrainDatasetVersion": {
|
|
56861
|
-
capName: "pipeline-analytics",
|
|
56862
|
-
capScope: "device",
|
|
56863
|
-
addonId: null,
|
|
56864
|
-
access: "create"
|
|
56865
|
-
},
|
|
56866
57011
|
"pipelineAnalytics.deleteDeviceEvents": {
|
|
56867
57012
|
capName: "pipeline-analytics",
|
|
56868
57013
|
capScope: "device",
|
|
@@ -56875,12 +57020,6 @@ Object.freeze({
|
|
|
56875
57020
|
addonId: null,
|
|
56876
57021
|
access: "delete"
|
|
56877
57022
|
},
|
|
56878
|
-
"pipelineAnalytics.deleteRetrainDatasetVersion": {
|
|
56879
|
-
capName: "pipeline-analytics",
|
|
56880
|
-
capScope: "device",
|
|
56881
|
-
addonId: null,
|
|
56882
|
-
access: "delete"
|
|
56883
|
-
},
|
|
56884
57023
|
"pipelineAnalytics.deleteTracks": {
|
|
56885
57024
|
capName: "pipeline-analytics",
|
|
56886
57025
|
capScope: "device",
|
|
@@ -56983,6 +57122,12 @@ Object.freeze({
|
|
|
56983
57122
|
addonId: null,
|
|
56984
57123
|
access: "view"
|
|
56985
57124
|
},
|
|
57125
|
+
"pipelineAnalytics.getRetrainCorpusKpi": {
|
|
57126
|
+
capName: "pipeline-analytics",
|
|
57127
|
+
capScope: "device",
|
|
57128
|
+
addonId: null,
|
|
57129
|
+
access: "view"
|
|
57130
|
+
},
|
|
56986
57131
|
"pipelineAnalytics.getRetrainExportUrl": {
|
|
56987
57132
|
capName: "pipeline-analytics",
|
|
56988
57133
|
capScope: "device",
|
|
@@ -57103,7 +57248,7 @@ Object.freeze({
|
|
|
57103
57248
|
addonId: null,
|
|
57104
57249
|
access: "view"
|
|
57105
57250
|
},
|
|
57106
|
-
"pipelineAnalytics.
|
|
57251
|
+
"pipelineAnalytics.listRetrainCorpusPage": {
|
|
57107
57252
|
capName: "pipeline-analytics",
|
|
57108
57253
|
capScope: "device",
|
|
57109
57254
|
addonId: null,
|
|
@@ -57157,12 +57302,6 @@ Object.freeze({
|
|
|
57157
57302
|
addonId: null,
|
|
57158
57303
|
access: "create"
|
|
57159
57304
|
},
|
|
57160
|
-
"pipelineAnalytics.previewRetrainDataset": {
|
|
57161
|
-
capName: "pipeline-analytics",
|
|
57162
|
-
capScope: "device",
|
|
57163
|
-
addonId: null,
|
|
57164
|
-
access: "view"
|
|
57165
|
-
},
|
|
57166
57305
|
"pipelineAnalytics.proposeRetrainAnnotations": {
|
|
57167
57306
|
capName: "pipeline-analytics",
|
|
57168
57307
|
capScope: "device",
|
|
@@ -57241,6 +57380,12 @@ Object.freeze({
|
|
|
57241
57380
|
addonId: null,
|
|
57242
57381
|
access: "create"
|
|
57243
57382
|
},
|
|
57383
|
+
"pipelineAnalytics.resolveRetrainTrainingCorpus": {
|
|
57384
|
+
capName: "pipeline-analytics",
|
|
57385
|
+
capScope: "device",
|
|
57386
|
+
addonId: null,
|
|
57387
|
+
access: "view"
|
|
57388
|
+
},
|
|
57244
57389
|
"pipelineAnalytics.restageRetrainTrack": {
|
|
57245
57390
|
capName: "pipeline-analytics",
|
|
57246
57391
|
capScope: "device",
|
|
@@ -57301,12 +57446,6 @@ Object.freeze({
|
|
|
57301
57446
|
addonId: null,
|
|
57302
57447
|
access: "create"
|
|
57303
57448
|
},
|
|
57304
|
-
"pipelineAnalytics.verifyRetrainDatasetVersion": {
|
|
57305
|
-
capName: "pipeline-analytics",
|
|
57306
|
-
capScope: "device",
|
|
57307
|
-
addonId: null,
|
|
57308
|
-
access: "view"
|
|
57309
|
-
},
|
|
57310
57449
|
"pipelineAnalytics.wipeAllAnalytics": {
|
|
57311
57450
|
capName: "pipeline-analytics",
|
|
57312
57451
|
capScope: "device",
|
|
@@ -59701,18 +59840,6 @@ Object.freeze({
|
|
|
59701
59840
|
addonId: null,
|
|
59702
59841
|
access: "create"
|
|
59703
59842
|
},
|
|
59704
|
-
"training.findDatasetVersionIdByName": {
|
|
59705
|
-
capName: "training",
|
|
59706
|
-
capScope: "system",
|
|
59707
|
-
addonId: null,
|
|
59708
|
-
access: "view"
|
|
59709
|
-
},
|
|
59710
|
-
"training.getDatasetVersion": {
|
|
59711
|
-
capName: "training",
|
|
59712
|
-
capScope: "system",
|
|
59713
|
-
addonId: null,
|
|
59714
|
-
access: "view"
|
|
59715
|
-
},
|
|
59716
59843
|
"training.getJob": {
|
|
59717
59844
|
capName: "training",
|
|
59718
59845
|
capScope: "system",
|
|
@@ -59731,12 +59858,6 @@ Object.freeze({
|
|
|
59731
59858
|
addonId: null,
|
|
59732
59859
|
access: "view"
|
|
59733
59860
|
},
|
|
59734
|
-
"training.listDatasetVersions": {
|
|
59735
|
-
capName: "training",
|
|
59736
|
-
capScope: "system",
|
|
59737
|
-
addonId: null,
|
|
59738
|
-
access: "view"
|
|
59739
|
-
},
|
|
59740
59861
|
"training.listJobs": {
|
|
59741
59862
|
capName: "training",
|
|
59742
59863
|
capScope: "system",
|
|
@@ -59749,54 +59870,66 @@ Object.freeze({
|
|
|
59749
59870
|
addonId: null,
|
|
59750
59871
|
access: "view"
|
|
59751
59872
|
},
|
|
59752
|
-
"training.
|
|
59873
|
+
"training.registerResult": {
|
|
59753
59874
|
capName: "training",
|
|
59754
59875
|
capScope: "system",
|
|
59755
59876
|
addonId: null,
|
|
59756
59877
|
access: "create"
|
|
59757
59878
|
},
|
|
59758
|
-
"training.
|
|
59879
|
+
"training.rollbackCanary": {
|
|
59759
59880
|
capName: "training",
|
|
59760
59881
|
capScope: "system",
|
|
59761
59882
|
addonId: null,
|
|
59762
59883
|
access: "create"
|
|
59763
59884
|
},
|
|
59764
|
-
"training.
|
|
59885
|
+
"training.startJob": {
|
|
59765
59886
|
capName: "training",
|
|
59766
59887
|
capScope: "system",
|
|
59767
59888
|
addonId: null,
|
|
59768
|
-
access: "
|
|
59889
|
+
access: "create"
|
|
59769
59890
|
},
|
|
59770
|
-
"training.
|
|
59891
|
+
"training.startJobBatch": {
|
|
59771
59892
|
capName: "training",
|
|
59772
59893
|
capScope: "system",
|
|
59773
59894
|
addonId: null,
|
|
59774
59895
|
access: "create"
|
|
59775
59896
|
},
|
|
59776
|
-
"
|
|
59777
|
-
capName: "training",
|
|
59897
|
+
"trainingProvider.cancelJob": {
|
|
59898
|
+
capName: "training-provider",
|
|
59778
59899
|
capScope: "system",
|
|
59779
59900
|
addonId: null,
|
|
59780
59901
|
access: "create"
|
|
59781
59902
|
},
|
|
59782
|
-
"trainingProvider.
|
|
59903
|
+
"trainingProvider.cleanupJob": {
|
|
59783
59904
|
capName: "training-provider",
|
|
59784
59905
|
capScope: "system",
|
|
59785
59906
|
addonId: null,
|
|
59786
59907
|
access: "create"
|
|
59787
59908
|
},
|
|
59788
|
-
"trainingProvider.
|
|
59909
|
+
"trainingProvider.createEntry": {
|
|
59789
59910
|
capName: "training-provider",
|
|
59790
59911
|
capScope: "system",
|
|
59791
59912
|
addonId: null,
|
|
59792
59913
|
access: "create"
|
|
59793
59914
|
},
|
|
59915
|
+
"trainingProvider.deleteEntry": {
|
|
59916
|
+
capName: "training-provider",
|
|
59917
|
+
capScope: "system",
|
|
59918
|
+
addonId: null,
|
|
59919
|
+
access: "delete"
|
|
59920
|
+
},
|
|
59794
59921
|
"trainingProvider.describe": {
|
|
59795
59922
|
capName: "training-provider",
|
|
59796
59923
|
capScope: "system",
|
|
59797
59924
|
addonId: null,
|
|
59798
59925
|
access: "view"
|
|
59799
59926
|
},
|
|
59927
|
+
"trainingProvider.describeTypes": {
|
|
59928
|
+
capName: "training-provider",
|
|
59929
|
+
capScope: "system",
|
|
59930
|
+
addonId: null,
|
|
59931
|
+
access: "view"
|
|
59932
|
+
},
|
|
59800
59933
|
"trainingProvider.estimateJob": {
|
|
59801
59934
|
capName: "training-provider",
|
|
59802
59935
|
capScope: "system",
|
|
@@ -59809,6 +59942,12 @@ Object.freeze({
|
|
|
59809
59942
|
addonId: null,
|
|
59810
59943
|
access: "view"
|
|
59811
59944
|
},
|
|
59945
|
+
"trainingProvider.listEntries": {
|
|
59946
|
+
capName: "training-provider",
|
|
59947
|
+
capScope: "system",
|
|
59948
|
+
addonId: null,
|
|
59949
|
+
access: "view"
|
|
59950
|
+
},
|
|
59812
59951
|
"trainingProvider.listJobEvents": {
|
|
59813
59952
|
capName: "training-provider",
|
|
59814
59953
|
capScope: "system",
|
|
@@ -63445,6 +63584,11 @@ Object.freeze({
|
|
|
63445
63584
|
form: "array",
|
|
63446
63585
|
optional: false
|
|
63447
63586
|
}],
|
|
63587
|
+
"pipelineAnalytics.listRetrainCorpusPage": [{
|
|
63588
|
+
name: "deviceIds",
|
|
63589
|
+
form: "array",
|
|
63590
|
+
optional: true
|
|
63591
|
+
}],
|
|
63448
63592
|
"pipelineAnalytics.listRetrainStaging": [{
|
|
63449
63593
|
name: "deviceIds",
|
|
63450
63594
|
form: "array",
|