@camstack/addon-model-studio 1.1.205 → 1.1.206
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/{MotionZonesSettings-DbxM42-u.mjs → MotionZonesSettings-C5YcAYX9.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-B6QbcEYx.mjs → PrivacyMaskSettings-B1M6BI5F.mjs} +4 -4
- package/dist/{SceneMonitorEditor-C_sWam-G.mjs → SceneMonitorEditor-8Nn6yjHl.mjs} +3 -3
- package/dist/_stub.js +5099 -4906
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-CNTVW6pB.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-B4UQ5mJi.mjs} +3 -3
- package/dist/{_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cl1eNNmq.mjs → _virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-2O40KrYq.mjs} +1 -1
- package/dist/{hostInit-Cz9X-HIo.mjs → hostInit-95eIoNUt.mjs} +2 -2
- package/dist/model-studio.addon.js +192 -35
- package/dist/model-studio.addon.mjs +192 -35
- package/dist/{player-overlays-p1wcAk-U.mjs → player-overlays-lpfo2ab8.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-a5o_RHI6.mjs → responsive-CO_rI6GL.mjs} +1 -1
- package/dist/{scene-monitor-copy-DRLPt6W9.mjs → scene-monitor-copy-Dx3Cq-sD.mjs} +1 -1
- package/dist/{square-Bfh8RaUF.mjs → square-DQHBxjsn.mjs} +1 -1
- package/dist/{trash-2-D-9uzmfU.mjs → trash-2-C6kfv9xl.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CrDmlyYW.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CXb44kDc.mjs} +1 -1
- package/package.json +1 -1
|
@@ -11124,6 +11124,19 @@ var ModelProviderIdSchema = _enum([
|
|
|
11124
11124
|
"custom"
|
|
11125
11125
|
]);
|
|
11126
11126
|
/**
|
|
11127
|
+
* Resolve a catalog entry's picker provider. An explicit stamp always wins;
|
|
11128
|
+
* otherwise Frigate/Scrypted are recognised from id prefix or description.
|
|
11129
|
+
* Unstamped BYO registry rows fall through to `custom`. Family `yolov9` is
|
|
11130
|
+
* NOT a Scrypted signal — CamStack ships that family too.
|
|
11131
|
+
*/
|
|
11132
|
+
function inferModelProvider(entry) {
|
|
11133
|
+
if (entry.provider !== void 0) return entry.provider;
|
|
11134
|
+
const haystack = `${entry.id} ${entry.description ?? ""}`;
|
|
11135
|
+
if (/scrypted/i.test(haystack)) return "scrypted";
|
|
11136
|
+
if (/frigate/i.test(haystack)) return "frigate";
|
|
11137
|
+
return "custom";
|
|
11138
|
+
}
|
|
11139
|
+
/**
|
|
11127
11140
|
* The licence of a model, as a record rather than a bare SPDX string: a
|
|
11128
11141
|
* permissive CODE licence routinely sits on top of restrictive WEIGHTS or
|
|
11129
11142
|
* DATA, and the obligations (attribution, modification notices, source offers)
|
|
@@ -16523,6 +16536,12 @@ method(_void(), array(string()).readonly(), { auth: "admin" }), method(object({
|
|
|
16523
16536
|
kind: "mutation",
|
|
16524
16537
|
auth: "admin"
|
|
16525
16538
|
});
|
|
16539
|
+
var HUB_ADDRESS_ROLES = [
|
|
16540
|
+
"appConnections",
|
|
16541
|
+
"notificationTaps",
|
|
16542
|
+
"internal",
|
|
16543
|
+
"publicEndpoint"
|
|
16544
|
+
];
|
|
16526
16545
|
/**
|
|
16527
16546
|
* Transport bounds for AI capability methods.
|
|
16528
16547
|
*
|
|
@@ -20700,7 +20719,13 @@ var NcAlarmModeDelaysListSchema = array(object({
|
|
|
20700
20719
|
* Absent = false (logged, not sent). Even when true it is not sent when that same sensor
|
|
20701
20720
|
* is the one that starts the entry delay — the entry-delay notification already names it.
|
|
20702
20721
|
*/
|
|
20703
|
-
notifySensorRewatched: boolean().optional()
|
|
20722
|
+
notifySensorRewatched: boolean().optional(),
|
|
20723
|
+
/**
|
|
20724
|
+
* D735: notify "ignored" when a sensor this arm bypassed really MOVED while armed (its own
|
|
20725
|
+
* change time is after the arm) and set nothing off. Absent = false (logged, not sent). A
|
|
20726
|
+
* re-sync, a recovery from `unavailable` or a duplicate is never announced, switch or not.
|
|
20727
|
+
*/
|
|
20728
|
+
notifySensorIgnored: boolean().optional()
|
|
20704
20729
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
|
|
20705
20730
|
var NcAlarmModeDelaysEditListSchema = array(object({
|
|
20706
20731
|
mode: AlarmArmModeSchema,
|
|
@@ -20713,7 +20738,9 @@ var NcAlarmModeDelaysEditListSchema = array(object({
|
|
|
20713
20738
|
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
20714
20739
|
notifyDuringEntryDelay: boolean().nullable().optional(),
|
|
20715
20740
|
/** D706: set the switch, or `null` to clear it (back to the default, false). */
|
|
20716
|
-
notifySensorRewatched: boolean().nullable().optional()
|
|
20741
|
+
notifySensorRewatched: boolean().nullable().optional(),
|
|
20742
|
+
/** D735: set the switch, or `null` to clear it (back to the default, false). */
|
|
20743
|
+
notifySensorIgnored: boolean().nullable().optional()
|
|
20717
20744
|
})).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
|
|
20718
20745
|
/** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
|
|
20719
20746
|
var NcAlarmNonBlockingEditSchema = object({
|
|
@@ -31218,7 +31245,7 @@ var GetConnectionEndpointsResultSchema = object({
|
|
|
31218
31245
|
localPort: AdvertisedLocalPortSchema
|
|
31219
31246
|
});
|
|
31220
31247
|
/**
|
|
31221
|
-
* The address flagged for notification
|
|
31248
|
+
* The address flagged for notification taps (`notificationTaps`). `baseUrl: null` = AUTO, which
|
|
31222
31249
|
* since D709 is the CamStack app link; `resolved` reports the effective value,
|
|
31223
31250
|
* so the UI can show it either way.
|
|
31224
31251
|
*/
|
|
@@ -31253,8 +31280,8 @@ var ViewerEndpointsSchema = object({
|
|
|
31253
31280
|
});
|
|
31254
31281
|
/**
|
|
31255
31282
|
* DEPRECATED compatibility shape of `getHubAddresses` (D729 amendment, kept
|
|
31256
|
-
*
|
|
31257
|
-
*
|
|
31283
|
+
* for addons built against it): `cluster` is the `internal` role, `browser`
|
|
31284
|
+
* the `publicEndpoint` role; `override` is the flagged address.
|
|
31258
31285
|
*/
|
|
31259
31286
|
var HubAddressSnapshotSchema = object({
|
|
31260
31287
|
override: string().nullable(),
|
|
@@ -31270,15 +31297,11 @@ var HubAddressesSchema = object({
|
|
|
31270
31297
|
browser: HubAddressSnapshotSchema
|
|
31271
31298
|
});
|
|
31272
31299
|
/**
|
|
31273
|
-
* What an address is used for (`hub-address.ts
|
|
31274
|
-
* `
|
|
31300
|
+
* What an address is used for (`hub-address.ts`, D734). `appConnections` is
|
|
31301
|
+
* many-valued; `notificationTaps`, `publicEndpoint` and `internal` are carried
|
|
31302
|
+
* by at most one address.
|
|
31275
31303
|
*/
|
|
31276
|
-
var HubAddressRoleSchema = _enum(
|
|
31277
|
-
"viewer",
|
|
31278
|
-
"notifications",
|
|
31279
|
-
"agents",
|
|
31280
|
-
"signIn"
|
|
31281
|
-
]);
|
|
31304
|
+
var HubAddressRoleSchema = _enum(HUB_ADDRESS_ROLES);
|
|
31282
31305
|
var RoleSourceSchema = _enum([
|
|
31283
31306
|
"flagged",
|
|
31284
31307
|
"auto",
|
|
@@ -31292,8 +31315,8 @@ var HubAddressRoleResolutionSchema = object({
|
|
|
31292
31315
|
resolved: string().nullable(),
|
|
31293
31316
|
source: RoleSourceSchema
|
|
31294
31317
|
});
|
|
31295
|
-
var
|
|
31296
|
-
/** The addresses flagged `
|
|
31318
|
+
var HubAppConnectionsResolutionSchema = object({
|
|
31319
|
+
/** The addresses flagged `appConnections`, or empty = automatic. */
|
|
31297
31320
|
flagged: array(string()).readonly(),
|
|
31298
31321
|
/** What the apps race right now. */
|
|
31299
31322
|
resolved: array(string()).readonly(),
|
|
@@ -31313,10 +31336,10 @@ var HubAddressBookSchema = object({
|
|
|
31313
31336
|
eligible: array(HubAddressRoleSchema).readonly()
|
|
31314
31337
|
})).readonly(),
|
|
31315
31338
|
roles: object({
|
|
31316
|
-
|
|
31317
|
-
|
|
31318
|
-
|
|
31319
|
-
|
|
31339
|
+
appConnections: HubAppConnectionsResolutionSchema,
|
|
31340
|
+
notificationTaps: HubAddressRoleResolutionSchema,
|
|
31341
|
+
internal: HubAddressRoleResolutionSchema,
|
|
31342
|
+
publicEndpoint: HubAddressRoleResolutionSchema
|
|
31320
31343
|
}),
|
|
31321
31344
|
/** The `hub=` an app link carries (D709), or null. */
|
|
31322
31345
|
appLinkHub: string().nullable()
|
|
@@ -31364,7 +31387,7 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
31364
31387
|
* tunnel always emits `https://` regardless. */
|
|
31365
31388
|
scheme: _enum(["http", "https"]).optional(),
|
|
31366
31389
|
/** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
|
|
31367
|
-
* an address notification
|
|
31390
|
+
* an address notification taps can be flagged with, not a hub
|
|
31368
31391
|
* route. Default `false`: racers and rankers never see it. */
|
|
31369
31392
|
includeAppLink: boolean().optional()
|
|
31370
31393
|
}), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(object({ scheme: _enum(["http", "https"]).optional() }).optional(), HubAddressBookSchema), method(object({
|
|
@@ -49462,6 +49485,35 @@ function buildModelConvertProvider(deps) {
|
|
|
49462
49485
|
};
|
|
49463
49486
|
} };
|
|
49464
49487
|
}
|
|
49488
|
+
var CONTROL_CHARS = /[\u0000-\u001f\u007f]/;
|
|
49489
|
+
/** Whitespace runs collapse to one space; leading/trailing whitespace goes. */
|
|
49490
|
+
function parseDisplayName(raw) {
|
|
49491
|
+
const name = raw.replace(/\s+/g, " ").trim();
|
|
49492
|
+
if (name.length === 0) return { kind: "reset" };
|
|
49493
|
+
if (CONTROL_CHARS.test(name)) return {
|
|
49494
|
+
kind: "invalid",
|
|
49495
|
+
reason: "The name contains control characters."
|
|
49496
|
+
};
|
|
49497
|
+
if (name.length > 80) return {
|
|
49498
|
+
kind: "invalid",
|
|
49499
|
+
reason: `The name is ${name.length} characters long; the limit is 80.`
|
|
49500
|
+
};
|
|
49501
|
+
return {
|
|
49502
|
+
kind: "set",
|
|
49503
|
+
name
|
|
49504
|
+
};
|
|
49505
|
+
}
|
|
49506
|
+
/**
|
|
49507
|
+
* The optional display name typed on an import card: `undefined` when left
|
|
49508
|
+
* empty (the source's own default applies), the cleaned name otherwise.
|
|
49509
|
+
* Throws with the reason when the input is not acceptable.
|
|
49510
|
+
*/
|
|
49511
|
+
function optionalImportName(raw) {
|
|
49512
|
+
if (raw === void 0) return void 0;
|
|
49513
|
+
const parsed = parseDisplayName(raw);
|
|
49514
|
+
if (parsed.kind === "invalid") throw new Error(`Display name rejected: ${parsed.reason}`);
|
|
49515
|
+
return parsed.kind === "set" ? parsed.name : void 0;
|
|
49516
|
+
}
|
|
49465
49517
|
//#endregion
|
|
49466
49518
|
//#region src/model-registry.ts
|
|
49467
49519
|
/**
|
|
@@ -49493,22 +49545,18 @@ function upsertAvailability(map, modelId, nodeId, entry) {
|
|
|
49493
49545
|
});
|
|
49494
49546
|
}
|
|
49495
49547
|
/**
|
|
49496
|
-
* Pure registry operations over the custom-model list. Kept side-effect-free
|
|
49497
|
-
* so they unit-test without a live `BaseAddon` context — the addon class is a
|
|
49498
|
-
* thin durable-state wrapper around these.
|
|
49499
|
-
*/
|
|
49500
|
-
/**
|
|
49501
49548
|
* Insert or replace a descriptor keyed by `entry.id`. When the id already
|
|
49502
49549
|
* exists, **formats are merged** (Scrypted multi-format accumulate) — sibling
|
|
49503
49550
|
* formats on the prior entry are never dropped. Returns a new array.
|
|
49504
49551
|
*/
|
|
49505
|
-
function upsertCustomModel(list, descriptor) {
|
|
49552
|
+
function upsertCustomModel(list, descriptor, nameOrigin = "source") {
|
|
49506
49553
|
const prev = list.find((m) => m.entry.id === descriptor.entry.id);
|
|
49507
49554
|
const merged = prev === void 0 ? descriptor : {
|
|
49508
49555
|
stepId: descriptor.stepId,
|
|
49509
49556
|
entry: {
|
|
49510
49557
|
...prev.entry,
|
|
49511
49558
|
...descriptor.entry,
|
|
49559
|
+
name: nameOrigin === "operator" ? descriptor.entry.name : prev.entry.name,
|
|
49512
49560
|
formats: {
|
|
49513
49561
|
...prev.entry.formats,
|
|
49514
49562
|
...descriptor.entry.formats
|
|
@@ -49517,6 +49565,43 @@ function upsertCustomModel(list, descriptor) {
|
|
|
49517
49565
|
};
|
|
49518
49566
|
return [...list.filter((m) => m.entry.id !== descriptor.entry.id), merged];
|
|
49519
49567
|
}
|
|
49568
|
+
/**
|
|
49569
|
+
* Rename one IMPORTED registry row in place. Only `entry.name` changes — the
|
|
49570
|
+
* id, step, formats and every pin keyed by the id stay exactly as they were.
|
|
49571
|
+
* An empty name resets the row to the name it was imported with. Throws on an
|
|
49572
|
+
* unknown id, a CamStack catalog row, or a name `parseDisplayName` rejects.
|
|
49573
|
+
*/
|
|
49574
|
+
function renameCustomModel(list, importedNames, modelId, rawName) {
|
|
49575
|
+
const row = list.find((m) => m.entry.id === modelId);
|
|
49576
|
+
if (row === void 0) throw new Error(`renameCustomModel: model "${modelId}" is not registered`);
|
|
49577
|
+
if (!isRenameableEntry(row.entry)) throw new Error(`renameCustomModel: "${modelId}" is a CamStack catalog model and keeps its name`);
|
|
49578
|
+
const parsed = parseDisplayName(rawName);
|
|
49579
|
+
if (parsed.kind === "invalid") throw new Error(`renameCustomModel: ${parsed.reason}`);
|
|
49580
|
+
const original = importedNames[modelId] ?? row.entry.name;
|
|
49581
|
+
const name = parsed.kind === "set" ? parsed.name : original;
|
|
49582
|
+
const nextNames = { ...importedNames };
|
|
49583
|
+
if (parsed.kind === "set" && name !== original) nextNames[modelId] = original;
|
|
49584
|
+
else delete nextNames[modelId];
|
|
49585
|
+
return {
|
|
49586
|
+
list: list.map((m) => m.entry.id === modelId ? {
|
|
49587
|
+
stepId: m.stepId,
|
|
49588
|
+
entry: {
|
|
49589
|
+
...m.entry,
|
|
49590
|
+
name
|
|
49591
|
+
}
|
|
49592
|
+
} : m),
|
|
49593
|
+
importedNames: nextNames,
|
|
49594
|
+
name
|
|
49595
|
+
};
|
|
49596
|
+
}
|
|
49597
|
+
/** An imported row can be renamed; a CamStack catalog model cannot. */
|
|
49598
|
+
function isRenameableEntry(entry) {
|
|
49599
|
+
return inferModelProvider({
|
|
49600
|
+
id: entry.id,
|
|
49601
|
+
description: entry.description,
|
|
49602
|
+
provider: entry.provider
|
|
49603
|
+
}) !== "camstack";
|
|
49604
|
+
}
|
|
49520
49605
|
/** Drop the descriptor with the given `entry.id`. Reports whether anything changed. */
|
|
49521
49606
|
function removeCustomModel(list, modelId) {
|
|
49522
49607
|
const next = list.filter((m) => m.entry.id !== modelId);
|
|
@@ -50364,6 +50449,19 @@ var modelStudioActions = defineCustomActions({
|
|
|
50364
50449
|
clearedPins: number().int().nonnegative()
|
|
50365
50450
|
}), { kind: "mutation" }),
|
|
50366
50451
|
/**
|
|
50452
|
+
* Rename an IMPORTED registry row (Frigate, Frigate+, Scrypted, uploads,
|
|
50453
|
+
* conversions) in place. Only `entry.name` changes — never the id, so pins
|
|
50454
|
+
* and availability are untouched. An empty name restores the name the model
|
|
50455
|
+
* was imported with. CamStack catalog models are refused.
|
|
50456
|
+
*/
|
|
50457
|
+
renameCustomModel: customAction(object({
|
|
50458
|
+
modelId: string().min(1),
|
|
50459
|
+
name: string()
|
|
50460
|
+
}), object({
|
|
50461
|
+
modelId: string(),
|
|
50462
|
+
name: string()
|
|
50463
|
+
}), { kind: "mutation" }),
|
|
50464
|
+
/**
|
|
50367
50465
|
* Delete one format of a Library model from one node. Keeps the registry row
|
|
50368
50466
|
* and sibling formats/nodes; clears only that availability chip.
|
|
50369
50467
|
*/
|
|
@@ -50452,6 +50550,8 @@ var modelStudioActions = defineCustomActions({
|
|
|
50452
50550
|
})),
|
|
50453
50551
|
importScryptedCatalogModel: customAction(object({
|
|
50454
50552
|
manifestId: string(),
|
|
50553
|
+
/** Optional display name typed on the import card. */
|
|
50554
|
+
name: string().optional(),
|
|
50455
50555
|
targetNodeId: string().optional()
|
|
50456
50556
|
}), CustomModelDescriptorSchema, { kind: "mutation" }),
|
|
50457
50557
|
/**
|
|
@@ -50481,7 +50581,8 @@ var modelStudioActions = defineCustomActions({
|
|
|
50481
50581
|
modelId: string().optional(),
|
|
50482
50582
|
name: string().optional(),
|
|
50483
50583
|
/**
|
|
50484
|
-
* Native artifact class
|
|
50584
|
+
* Native artifact class of the chosen build (`plusImportLane`: neural →
|
|
50585
|
+
* onnx, coral → tflite). The
|
|
50485
50586
|
* model-detail API does not always carry `supportedDetectors`, so the
|
|
50486
50587
|
* browser passes what the catalog already knew (fixes ssd/yolo-generic
|
|
50487
50588
|
* EdgeTPU rows that `plusTypeTraits` alone would call onnx).
|
|
@@ -50533,6 +50634,8 @@ var modelStudioActions = defineCustomActions({
|
|
|
50533
50634
|
//#region src/model-studio.addon.ts
|
|
50534
50635
|
var KEY_CUSTOM_MODELS = "customModels";
|
|
50535
50636
|
var KEY_AVAILABILITY = "availability";
|
|
50637
|
+
var KEY_IMPORTED_NAMES = "importedNames";
|
|
50638
|
+
var ImportedNamesSchema = record(string(), string());
|
|
50536
50639
|
var CustomModelsSchema = array(CustomModelDescriptorSchema);
|
|
50537
50640
|
var pythonDirCache;
|
|
50538
50641
|
function resolveAddonPythonDir() {
|
|
@@ -50595,12 +50698,18 @@ function spawnRunConvert(jobPath, pythonPath, onProgress, _sessionId) {
|
|
|
50595
50698
|
});
|
|
50596
50699
|
});
|
|
50597
50700
|
}
|
|
50701
|
+
/** A name the operator typed replaces an existing row's name; a derived one never does. */
|
|
50702
|
+
function nameOriginOf(operatorName) {
|
|
50703
|
+
return operatorName !== void 0 ? { nameOrigin: "operator" } : {};
|
|
50704
|
+
}
|
|
50598
50705
|
/** Global-fetch adapter for the injected Frigate+ client seam. */
|
|
50599
50706
|
var plusFetch = async (url, init) => fetch(url, init);
|
|
50600
50707
|
var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
50601
50708
|
id = "model-studio";
|
|
50602
50709
|
modelsState = null;
|
|
50603
50710
|
availabilityState = null;
|
|
50711
|
+
/** modelId → the name a renamed registry row had before its first rename. */
|
|
50712
|
+
importedNamesState = null;
|
|
50604
50713
|
/** Lazily-built chunked-upload store (hub only) — see `upload/model-upload-store.ts`. */
|
|
50605
50714
|
uploadStore = null;
|
|
50606
50715
|
/**
|
|
@@ -50683,6 +50792,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
50683
50792
|
const state = this.state(KEY_CUSTOM_MODELS, CustomModelsSchema, []);
|
|
50684
50793
|
this.modelsState = state;
|
|
50685
50794
|
this.availabilityState = this.state(KEY_AVAILABILITY, ModelAvailabilityMapSchema, {});
|
|
50795
|
+
this.importedNamesState = this.state(KEY_IMPORTED_NAMES, ImportedNamesSchema, {});
|
|
50686
50796
|
const rawNode = this.ctx.kernel?.localNodeId ?? "hub";
|
|
50687
50797
|
const isHub = (rawNode.includes("/") ? rawNode.split("/")[0] : rawNode) === "hub";
|
|
50688
50798
|
const pagesProvider = {
|
|
@@ -50716,7 +50826,11 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
50716
50826
|
return result;
|
|
50717
50827
|
},
|
|
50718
50828
|
abortModelUpload: async (input) => (await this.getUploadStore()).abort(input),
|
|
50719
|
-
registerCustomModel: async (input) => this.registerCustomModel(input, {
|
|
50829
|
+
registerCustomModel: async (input) => this.registerCustomModel(input, {
|
|
50830
|
+
ensureEngines: true,
|
|
50831
|
+
nameOrigin: "operator"
|
|
50832
|
+
}),
|
|
50833
|
+
renameCustomModel: async (input) => this.renameCustomModel_(input),
|
|
50720
50834
|
ensureFormatsThenDistribute: async (input) => this.ensureFormatsThenDistribute_(input.modelId),
|
|
50721
50835
|
ensureModelFormats: async (input) => this.ensureModelFormats_(input.modelId, input.formats),
|
|
50722
50836
|
removeCustomModel: async (input) => this.removeCustomModel(input),
|
|
@@ -50868,6 +50982,35 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
50868
50982
|
if (!this.modelsState) throw new Error("ModelStudioAddon: durable state not initialized");
|
|
50869
50983
|
return this.modelsState;
|
|
50870
50984
|
}
|
|
50985
|
+
get importedNames_() {
|
|
50986
|
+
if (!this.importedNamesState) throw new Error("ModelStudioAddon: imported-names state not initialized");
|
|
50987
|
+
return this.importedNamesState;
|
|
50988
|
+
}
|
|
50989
|
+
/**
|
|
50990
|
+
* Rename an imported registry row in place (`renameCustomModel` decides).
|
|
50991
|
+
* The id is untouched, so pins, availability and files are unaffected; the
|
|
50992
|
+
* pipeline's catalog view picks the new name up on its next registry read.
|
|
50993
|
+
*/
|
|
50994
|
+
async renameCustomModel_(input) {
|
|
50995
|
+
const names = await this.importedNames_.get();
|
|
50996
|
+
const outcome = {};
|
|
50997
|
+
await this.state_.update((prev) => {
|
|
50998
|
+
const renamed = renameCustomModel(prev, names, input.modelId, input.name);
|
|
50999
|
+
outcome.result = renamed;
|
|
51000
|
+
return renamed.list;
|
|
51001
|
+
});
|
|
51002
|
+
const result = outcome.result;
|
|
51003
|
+
if (result === void 0) throw new Error("renameCustomModel: registry update did not run");
|
|
51004
|
+
await this.importedNames_.set(result.importedNames);
|
|
51005
|
+
this.ctx.logger.info("Renamed custom model", { meta: {
|
|
51006
|
+
modelId: input.modelId,
|
|
51007
|
+
name: result.name
|
|
51008
|
+
} });
|
|
51009
|
+
return {
|
|
51010
|
+
modelId: input.modelId,
|
|
51011
|
+
name: result.name
|
|
51012
|
+
};
|
|
51013
|
+
}
|
|
50871
51014
|
get availability_() {
|
|
50872
51015
|
if (!this.availabilityState) throw new Error("ModelStudioAddon: availability state not initialized");
|
|
50873
51016
|
return this.availabilityState;
|
|
@@ -50989,6 +51132,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
50989
51132
|
* `targetNodeId` lands the HF URL on that node via download-on-target.
|
|
50990
51133
|
*/
|
|
50991
51134
|
async importScryptedCatalogFromManifest(input) {
|
|
51135
|
+
const name = optionalImportName(input.name);
|
|
50992
51136
|
const entry = getScryptedManifestEntry(input.manifestId);
|
|
50993
51137
|
if (!entry) throw new Error(`importScryptedCatalogModel: unknown manifest id "${input.manifestId}"`);
|
|
50994
51138
|
let drift;
|
|
@@ -51008,8 +51152,15 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
51008
51152
|
};
|
|
51009
51153
|
}
|
|
51010
51154
|
if (drift.status !== "ok") throw new Error(`importScryptedCatalogModel: entry "${entry.id}" is blocked by drift (${drift.status}${drift.details ? `: ${drift.details}` : ""})`);
|
|
51011
|
-
const
|
|
51012
|
-
|
|
51155
|
+
const built = buildScryptedRegistryDescriptor(entry);
|
|
51156
|
+
const descriptor = name !== void 0 ? {
|
|
51157
|
+
stepId: built.stepId,
|
|
51158
|
+
entry: {
|
|
51159
|
+
...built.entry,
|
|
51160
|
+
name
|
|
51161
|
+
}
|
|
51162
|
+
} : built;
|
|
51163
|
+
await this.registerCustomModel(descriptor, nameOriginOf(name));
|
|
51013
51164
|
if (input.targetNodeId !== void 0 && input.targetNodeId.length > 0) await this.distributeModel({
|
|
51014
51165
|
modelId: descriptor.entry.id,
|
|
51015
51166
|
nodeId: input.targetNodeId,
|
|
@@ -51031,11 +51182,12 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
51031
51182
|
async importFrigateCatalogModel(input) {
|
|
51032
51183
|
const cat = FRIGATE_PUBLIC_CATALOG.find((c) => c.id === input.catalogId);
|
|
51033
51184
|
if (!cat) throw new Error(`importFrigateCatalogModel: unknown catalog id "${input.catalogId}"`);
|
|
51185
|
+
const name = optionalImportName(input.name);
|
|
51034
51186
|
const descriptor = buildFrigateCatalogDescriptor(input.catalogId, {
|
|
51035
51187
|
...input.modelId !== void 0 ? { modelId: input.modelId } : {},
|
|
51036
|
-
...
|
|
51188
|
+
...name !== void 0 ? { name } : {}
|
|
51037
51189
|
});
|
|
51038
|
-
await this.registerCustomModel(descriptor);
|
|
51190
|
+
await this.registerCustomModel(descriptor, nameOriginOf(name));
|
|
51039
51191
|
let bytes = Math.round(cat.sizeMB * 1e6);
|
|
51040
51192
|
if (input.targetNodeId !== void 0 && input.targetNodeId.length > 0) {
|
|
51041
51193
|
const landed = await this.distributeModel({
|
|
@@ -51066,6 +51218,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
51066
51218
|
*/
|
|
51067
51219
|
async importFrigatePlusModel(input) {
|
|
51068
51220
|
const modelId = frigatePlusRegistryId(input.plusModelId);
|
|
51221
|
+
const operatorName = optionalImportName(input.name);
|
|
51069
51222
|
const key = this.config.frigatePlusApiKey ?? "";
|
|
51070
51223
|
const { info, downloadUrl } = await requestPlusModelDownload(plusFetch, key, input.plusModelId);
|
|
51071
51224
|
const typeTraits = plusTypeTraits(info.type);
|
|
@@ -51090,12 +51243,15 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
51090
51243
|
const sha256 = await ModelStudioAddon.fileSha256(destPath);
|
|
51091
51244
|
const descriptor = plusInfoToDescriptor(info, {
|
|
51092
51245
|
modelId,
|
|
51093
|
-
name:
|
|
51246
|
+
name: operatorName ?? `Frigate+ ${info.type} (${input.plusModelId.slice(0, 8)})`,
|
|
51094
51247
|
filename,
|
|
51095
51248
|
sizeMB: Number((bytes / 1e6).toFixed(1)),
|
|
51096
51249
|
...input.format !== void 0 ? { format: input.format } : {}
|
|
51097
51250
|
});
|
|
51098
|
-
await this.registerCustomModel(descriptor, {
|
|
51251
|
+
await this.registerCustomModel(descriptor, {
|
|
51252
|
+
ensureEngines: false,
|
|
51253
|
+
...nameOriginOf(operatorName)
|
|
51254
|
+
});
|
|
51099
51255
|
await this.availability_.update((prev) => upsertAvailability(prev, modelId, "hub", {
|
|
51100
51256
|
format: traits.format,
|
|
51101
51257
|
sha256,
|
|
@@ -51128,7 +51284,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
51128
51284
|
async registerCustomModel(input, opts = {}) {
|
|
51129
51285
|
if (!input.stepId.trim()) throw new Error("registerCustomModel: stepId is required");
|
|
51130
51286
|
if (!input.entry.id.trim()) throw new Error("registerCustomModel: entry.id is required");
|
|
51131
|
-
await this.state_.update((prev) => upsertCustomModel(prev, input));
|
|
51287
|
+
await this.state_.update((prev) => upsertCustomModel(prev, input, opts.nameOrigin));
|
|
51132
51288
|
this.ctx.logger.info("Registered custom model", { meta: {
|
|
51133
51289
|
modelId: input.entry.id,
|
|
51134
51290
|
stepId: input.stepId
|
|
@@ -51385,6 +51541,7 @@ var ModelStudioAddon = class ModelStudioAddon extends BaseAddon {
|
|
|
51385
51541
|
removed = result.removed;
|
|
51386
51542
|
return result.next;
|
|
51387
51543
|
});
|
|
51544
|
+
await this.importedNames_.update((prev) => Object.fromEntries(Object.entries(prev).filter(([id]) => id !== input.modelId)));
|
|
51388
51545
|
this.ctx.logger.info("Removed custom model", { meta: {
|
|
51389
51546
|
modelId: input.modelId,
|
|
51390
51547
|
removed,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h as e, l as t, u as n, y as r } from "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare__react__loadShare__.js-DJDHChgO.mjs";
|
|
2
|
-
import { o as i, s as a } from "./responsive-
|
|
2
|
+
import { o as i, s as a } from "./responsive-CO_rI6GL.mjs";
|
|
3
3
|
import { n as o, r as s, t as c } from "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-ds_Ehzaa.mjs";
|
|
4
4
|
var l = a("chevron-down", [["path", {
|
|
5
5
|
d: "m6 9 6 6 6-6",
|
package/dist/remoteEntry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-
|
|
1
|
+
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CXb44kDc.mjs";
|
|
2
2
|
export { t as get, e as init };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as e, g as t, h as n, l as r, n as i, p as a, r as o, t as s, u as c, y as l } from "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare__react__loadShare__.js-DJDHChgO.mjs";
|
|
2
2
|
import "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-ds_Ehzaa.mjs";
|
|
3
|
-
import { c as u } from "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
3
|
+
import { c as u } from "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-2O40KrYq.mjs";
|
|
4
4
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
|
|
5
5
|
l();
|
|
6
6
|
var d = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), f = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), p = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), m = (e) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as e, h as t, p as n, y as r } from "./_virtual_mf___mfe_internal__addon_model_studio_page__loadShare__react__loadShare__.js-DJDHChgO.mjs";
|
|
2
|
-
import { s as i } from "./responsive-
|
|
2
|
+
import { s as i } from "./responsive-CO_rI6GL.mjs";
|
|
3
3
|
var a = i("camera", [["path", {
|
|
4
4
|
d: "M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",
|
|
5
5
|
key: "18u6gg"
|
|
@@ -2753,7 +2753,7 @@ async function rr(e) {
|
|
|
2753
2753
|
}
|
|
2754
2754
|
}
|
|
2755
2755
|
async function ir() {
|
|
2756
|
-
return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-
|
|
2756
|
+
return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-B4UQ5mJi.mjs")).catch((e) => {
|
|
2757
2757
|
throw tr = void 0, e;
|
|
2758
2758
|
}), tr;
|
|
2759
2759
|
}
|