@camstack/addon-training 0.1.21 → 0.1.23
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/MaskShapeCanvas-BokARvOj.mjs +13806 -0
- package/dist/MotionZonesSettings-CwGjtvsX.mjs +310 -0
- package/dist/{PrivacyMaskSettings-Bo1S23wt.mjs → PrivacyMaskSettings-CM_WsrKB.mjs} +70 -45
- package/dist/{SceneMonitorEditor-DnQJ7Hx3.mjs → SceneMonitorEditor-B-sAJ--C.mjs} +311 -311
- package/dist/_stub.js +7372 -16803
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-DQi_LrZZ.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-DKblQaAP.mjs} +2 -2
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-ff7X-Xlf.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BSOdwqcC.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-B3rryujf.mjs +25 -0
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-nL4MGFRP.mjs +26 -0
- package/dist/{_virtual_mf___mfe_internal__addon_training_page__loadShare__react__loadShare__.js-DeDbF7NI.mjs → _virtual_mf___mfe_internal__addon_training_page__loadShare__react__loadShare__.js-BT_wL8s3.mjs} +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DDBEvLdo.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_2_dom__loadShare__.js-CK-LlgOt.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-gTIQrhKs.mjs +25 -0
- package/dist/{dist-BSYBh1ZO.mjs → dist-CVDWIKl7.mjs} +52 -2
- package/dist/{dist-BCLkrWJc.js → dist-DwF1P1v7.js} +87 -1
- package/dist/{hostInit-Bx2a8M7w.mjs → hostInit-Di0tDODX.mjs} +1 -1
- package/dist/index.js +8 -1
- package/dist/index.mjs +7 -0
- package/dist/orchestrator/training.addon.js +8 -1
- package/dist/orchestrator/training.addon.mjs +8 -1
- package/dist/{player-overlays-BR2_H0wZ.mjs → player-overlays-BFAqW2L1.mjs} +10 -32
- package/dist/providers/modal/training-modal.addon.js +196 -123
- package/dist/providers/modal/training-modal.addon.mjs +196 -123
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-emJo3EdF.mjs → responsive-BBlQWFFi.mjs} +38 -42
- package/dist/{scene-monitor-copy-CcQxbRXa.mjs → scene-monitor-copy-D5mKGqt0.mjs} +4 -4
- package/dist/{square-CErp1WgN.mjs → square-D0FYSm8b.mjs} +4 -29
- package/dist/{trash-2-Drz0fMgI.mjs → trash-2-DdjGvgDw.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-C-uqIKLg.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-Dw400Y0a.mjs} +390 -399
- package/package.json +1 -1
- package/dist/MaskShapeCanvas-Kfg9dl6B.mjs +0 -686
- package/dist/MotionZonesSettings-DflIL9ss.mjs +0 -292
- package/dist/ReactKonva-DGuYUN0L.mjs +0 -5416
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C7dks3FG.mjs +0 -26
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DpjirGmB.mjs +0 -89
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-CFCVuRAs.mjs +0 -58
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-BkvDudqY.mjs +0 -62
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DnrbBvrw.mjs +0 -34
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_2_dom__loadShare__.js-DAZkHxxU.mjs +0 -45
- package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-CHqN9NLt.mjs +0 -34
- package/dist/grid-2x2-D9syAI6z.mjs +0 -21
- package/dist/lib-CVGFTwe0.mjs +0 -7770
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as addonPagesSourceCapability, i as TrainingResultSchema, l as BaseAddon, n as TrainingJobSchema, o as parseTrainingEventLine, r as TrainingJobSpecSchema, s as trainingCapability, t as TRAINING_JOB_SCHEMA } from "../dist-
|
|
1
|
+
import { a as addonPagesSourceCapability, i as TrainingResultSchema, l as BaseAddon, n as TrainingJobSchema, o as parseTrainingEventLine, r as TrainingJobSpecSchema, s as trainingCapability, t as TRAINING_JOB_SCHEMA } from "../dist-CVDWIKl7.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { createReadStream } from "node:fs";
|
|
@@ -30,6 +30,13 @@ function providerPort(api) {
|
|
|
30
30
|
addonId
|
|
31
31
|
});
|
|
32
32
|
},
|
|
33
|
+
updateEntry: async (i) => {
|
|
34
|
+
const addonId = await addonForEntry(i.entryId);
|
|
35
|
+
return p.updateEntry.mutate({
|
|
36
|
+
...i,
|
|
37
|
+
addonId
|
|
38
|
+
});
|
|
39
|
+
},
|
|
33
40
|
deleteEntry: async (i) => {
|
|
34
41
|
const addonId = await addonForEntry(i.entryId);
|
|
35
42
|
return p.deleteEntry.mutate({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { n as o, r as s, t as c } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-
|
|
4
|
-
var l =
|
|
1
|
+
import { b as e, g as t, l as n, u as r } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react__loadShare__.js-BT_wL8s3.mjs";
|
|
2
|
+
import { v as i, y as a } from "./responsive-BBlQWFFi.mjs";
|
|
3
|
+
import { n as o, r as s, t as c } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DDBEvLdo.mjs";
|
|
4
|
+
var l = a("chevron-down", [["path", {
|
|
5
5
|
d: "m6 9 6 6 6-6",
|
|
6
6
|
key: "qrunsl"
|
|
7
|
-
}]]), u =
|
|
7
|
+
}]]), u = a("chevron-right", [["path", {
|
|
8
8
|
d: "m9 18 6-6-6-6",
|
|
9
9
|
key: "mthhwq"
|
|
10
10
|
}]]);
|
|
@@ -32,35 +32,13 @@ function d({ title: e, icon: n, headerRight: r, collapsible: i = !1, defaultOpen
|
|
|
32
32
|
}) : null]
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/* @__PURE__ */ s("div", {
|
|
40
|
-
className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-[10px] uppercase tracking-wider text-foreground-subtle",
|
|
41
|
-
children: [t, /* @__PURE__ */ o("span", {
|
|
42
|
-
className: "min-w-0 truncate",
|
|
43
|
-
children: e
|
|
44
|
-
})]
|
|
45
|
-
}),
|
|
46
|
-
/* @__PURE__ */ o("div", {
|
|
47
|
-
className: "truncate text-lg font-semibold leading-tight text-foreground",
|
|
48
|
-
children: n
|
|
49
|
-
}),
|
|
50
|
-
r == null ? null : /* @__PURE__ */ o("div", {
|
|
51
|
-
className: "mt-0.5 truncate text-[10px] text-foreground-subtle",
|
|
52
|
-
children: r
|
|
53
|
-
})
|
|
54
|
-
]
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
e(), a("camstack:player-overlays-state", null);
|
|
58
|
-
var p = a("camstack:player-overlays-actions", null);
|
|
59
|
-
function m(e) {
|
|
60
|
-
let t = n(p);
|
|
35
|
+
e(), i("camstack:player-overlays-state", null);
|
|
36
|
+
var f = i("camstack:player-overlays-actions", null);
|
|
37
|
+
function p(e) {
|
|
38
|
+
let t = n(f);
|
|
61
39
|
r(() => {
|
|
62
40
|
if (!(!t || !e)) return t.setLayer(e), () => t.removeLayer(e.id);
|
|
63
41
|
}, [t, e]);
|
|
64
42
|
}
|
|
65
43
|
//#endregion
|
|
66
|
-
export { l as
|
|
44
|
+
export { l as i, d as n, u as r, p as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("../../dist-
|
|
2
|
+
const require_dist = require("../../dist-DwF1P1v7.js");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_dist.__toESM(node_path, 1);
|
|
5
5
|
let node_crypto = require("node:crypto");
|
|
@@ -11,14 +11,43 @@ let timers_promises = require("timers/promises");
|
|
|
11
11
|
let node_console = require("node:console");
|
|
12
12
|
let node_os = require("node:os");
|
|
13
13
|
let node_stream = require("node:stream");
|
|
14
|
-
//#region src/providers/modal/
|
|
14
|
+
//#region src/providers/modal/entry-secret-view.ts
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Build the {@link SecretFieldView} the Providers edit form needs for an
|
|
17
|
+
* entry's token secret.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* `readStoredGlobalKey` / `this.config` answer VALUES (D798), never markers —
|
|
20
|
+
* so `toSecretFieldView(plaintext)` alone yields an inline view (`$secret:
|
|
21
|
+
* null`) and `SecretFieldControl` cannot reveal. When the secret is set we
|
|
22
|
+
* prefer the deterministic keychain ref (`ctx.secrets.ref`) so the eye can
|
|
23
|
+
* call `keychain-admin.reveal` (D789).
|
|
21
24
|
*/
|
|
25
|
+
/** View for one entry row, or `null` when nothing is stored. */
|
|
26
|
+
function entryTokenSecretView(tokenSecret, secrets, entryId) {
|
|
27
|
+
if (require_dist.isSecretMarker(tokenSecret)) return require_dist.toSecretFieldView(tokenSecret);
|
|
28
|
+
const plain = typeof tokenSecret === "string" ? tokenSecret.trim() : "";
|
|
29
|
+
if (plain === "") return null;
|
|
30
|
+
if (secrets === void 0) return require_dist.toSecretFieldView(plain);
|
|
31
|
+
return {
|
|
32
|
+
$secret: secrets.ref(require_dist.globalSecretScope(), require_dist.arrayItemFieldPath("entries", entryId, "tokenSecret")),
|
|
33
|
+
v: 1,
|
|
34
|
+
set: true
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** View for the legacy flat `tokenSecret` (pre-multi-entry Default). */
|
|
38
|
+
function flatTokenSecretView(tokenSecret, secrets) {
|
|
39
|
+
if (require_dist.isSecretMarker(tokenSecret)) return require_dist.toSecretFieldView(tokenSecret);
|
|
40
|
+
const plain = typeof tokenSecret === "string" ? tokenSecret.trim() : "";
|
|
41
|
+
if (plain === "") return null;
|
|
42
|
+
if (secrets === void 0) return require_dist.toSecretFieldView(plain);
|
|
43
|
+
return {
|
|
44
|
+
$secret: secrets.ref(require_dist.globalSecretScope(), "tokenSecret"),
|
|
45
|
+
v: 1,
|
|
46
|
+
set: true
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/providers/modal/modal-entries.ts
|
|
22
51
|
var MODAL_TYPE_ID = "modal";
|
|
23
52
|
var DEFAULT_MODAL_ENTRY_NAME = "Default";
|
|
24
53
|
var MODAL_ICON_ASSET = "assets/training-modal/icon.svg";
|
|
@@ -29,22 +58,44 @@ var DEFAULT_GRACE = 24;
|
|
|
29
58
|
function legacyConfigured(config) {
|
|
30
59
|
return (config.tokenId ?? "").trim() !== "" || (config.tokenSecret ?? "").trim() !== "";
|
|
31
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Keychain / secretStatePaths may omit an empty `tokenSecret` from a stored
|
|
63
|
+
* row (writing `''` is KEEP, not "store empty"). Readers must never see
|
|
64
|
+
* `undefined` and then call `.trim()`.
|
|
65
|
+
*/
|
|
66
|
+
function secretAsString(value) {
|
|
67
|
+
return typeof value === "string" ? value : "";
|
|
68
|
+
}
|
|
69
|
+
function normalizeModalEntry(entry) {
|
|
70
|
+
return {
|
|
71
|
+
id: entry.id,
|
|
72
|
+
name: entry.name ?? "Default",
|
|
73
|
+
tokenId: entry.tokenId ?? "",
|
|
74
|
+
tokenSecret: secretAsString(entry.tokenSecret),
|
|
75
|
+
environment: entry.environment ?? "",
|
|
76
|
+
gpuType: entry.gpuType ?? DEFAULT_GPU,
|
|
77
|
+
region: entry.region ?? "",
|
|
78
|
+
costCapUsd: entry.costCapUsd ?? DEFAULT_COST,
|
|
79
|
+
maxRuntimeHours: entry.maxRuntimeHours ?? DEFAULT_HOURS,
|
|
80
|
+
failedDatasetGraceHours: entry.failedDatasetGraceHours ?? DEFAULT_GRACE
|
|
81
|
+
};
|
|
82
|
+
}
|
|
32
83
|
/** Entries the operator sees — synthesises Default from legacy flat fields. */
|
|
33
84
|
function effectiveModalEntries(config) {
|
|
34
|
-
if (config.entries.length > 0) return config.entries;
|
|
85
|
+
if (config.entries.length > 0) return config.entries.map((e) => normalizeModalEntry(e));
|
|
35
86
|
if (!legacyConfigured(config)) return [];
|
|
36
|
-
return [{
|
|
87
|
+
return [normalizeModalEntry({
|
|
37
88
|
id: "legacy-default",
|
|
38
89
|
name: DEFAULT_MODAL_ENTRY_NAME,
|
|
39
|
-
tokenId: config.tokenId
|
|
40
|
-
tokenSecret: config.tokenSecret
|
|
41
|
-
environment: config.environment
|
|
42
|
-
gpuType: config.gpuType
|
|
43
|
-
region: config.region
|
|
44
|
-
costCapUsd: config.costCapUsd
|
|
45
|
-
maxRuntimeHours: config.maxRuntimeHours
|
|
46
|
-
failedDatasetGraceHours: config.failedDatasetGraceHours
|
|
47
|
-
}];
|
|
90
|
+
tokenId: config.tokenId,
|
|
91
|
+
tokenSecret: config.tokenSecret,
|
|
92
|
+
environment: config.environment,
|
|
93
|
+
gpuType: config.gpuType,
|
|
94
|
+
region: config.region,
|
|
95
|
+
costCapUsd: config.costCapUsd,
|
|
96
|
+
maxRuntimeHours: config.maxRuntimeHours,
|
|
97
|
+
failedDatasetGraceHours: config.failedDatasetGraceHours
|
|
98
|
+
})];
|
|
48
99
|
}
|
|
49
100
|
function findModalEntry(config, entryId) {
|
|
50
101
|
return effectiveModalEntries(config).find((e) => e.id === entryId) ?? null;
|
|
@@ -128,6 +179,43 @@ function deleteModalEntry(config, entryId) {
|
|
|
128
179
|
}
|
|
129
180
|
};
|
|
130
181
|
}
|
|
182
|
+
function updateModalEntry(config, entryId, patch) {
|
|
183
|
+
const current = [...effectiveModalEntries(config)];
|
|
184
|
+
const index = current.findIndex((e) => e.id === entryId);
|
|
185
|
+
if (index < 0) return {
|
|
186
|
+
ok: false,
|
|
187
|
+
reason: "unknown-entry"
|
|
188
|
+
};
|
|
189
|
+
const prev = current[index];
|
|
190
|
+
const secret = patch.tokenSecret !== void 0 && patch.tokenSecret !== "" ? patch.tokenSecret : prev.tokenSecret;
|
|
191
|
+
current[index] = {
|
|
192
|
+
id: prev.id,
|
|
193
|
+
name: patch.name !== void 0 ? patch.name : prev.name,
|
|
194
|
+
tokenId: patch.tokenId !== void 0 ? patch.tokenId : prev.tokenId,
|
|
195
|
+
tokenSecret: secret,
|
|
196
|
+
environment: patch.environment !== void 0 ? patch.environment : prev.environment,
|
|
197
|
+
gpuType: patch.gpuType !== void 0 ? patch.gpuType : prev.gpuType,
|
|
198
|
+
region: patch.region !== void 0 ? patch.region : prev.region,
|
|
199
|
+
costCapUsd: patch.costCapUsd !== void 0 ? patch.costCapUsd : prev.costCapUsd,
|
|
200
|
+
maxRuntimeHours: patch.maxRuntimeHours !== void 0 ? patch.maxRuntimeHours : prev.maxRuntimeHours,
|
|
201
|
+
failedDatasetGraceHours: patch.failedDatasetGraceHours !== void 0 ? patch.failedDatasetGraceHours : prev.failedDatasetGraceHours
|
|
202
|
+
};
|
|
203
|
+
return {
|
|
204
|
+
ok: true,
|
|
205
|
+
entryId,
|
|
206
|
+
config: {
|
|
207
|
+
entries: current,
|
|
208
|
+
tokenId: "",
|
|
209
|
+
tokenSecret: "",
|
|
210
|
+
environment: config.environment ?? "",
|
|
211
|
+
gpuType: config.gpuType ?? DEFAULT_GPU,
|
|
212
|
+
region: config.region ?? "",
|
|
213
|
+
costCapUsd: config.costCapUsd ?? DEFAULT_COST,
|
|
214
|
+
maxRuntimeHours: config.maxRuntimeHours ?? DEFAULT_HOURS,
|
|
215
|
+
failedDatasetGraceHours: config.failedDatasetGraceHours ?? DEFAULT_GRACE
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
131
219
|
/**
|
|
132
220
|
* Mint a stable id for every persisted entry that lacks one. Operator-typed
|
|
133
221
|
* empty ids (legacy settings UI) must never stay empty — createEntry always
|
|
@@ -344,7 +432,10 @@ var ModalTrainingProvider = class {
|
|
|
344
432
|
constructor(deps) {
|
|
345
433
|
this.deps = deps;
|
|
346
434
|
}
|
|
347
|
-
describe = async () =>
|
|
435
|
+
describe = async () => {
|
|
436
|
+
const views = await this.deps.secretViews();
|
|
437
|
+
return this.deps.listEntries().map((entry) => this.descriptorOf(entry, views.get(entry.id) ?? null));
|
|
438
|
+
};
|
|
348
439
|
describeTypes = async () => [{
|
|
349
440
|
typeId: MODAL_TYPE_ID,
|
|
350
441
|
label: "Modal",
|
|
@@ -359,6 +450,21 @@ var ModalTrainingProvider = class {
|
|
|
359
450
|
configured: this.entryConfigured(entry)
|
|
360
451
|
}));
|
|
361
452
|
createEntry = async (input) => this.deps.createEntry(input);
|
|
453
|
+
updateEntry = async (input) => {
|
|
454
|
+
const secret = input.tokenSecret === void 0 ? {} : require_dist.isSecretClear(input.tokenSecret) ? { clearTokenSecret: true } : input.tokenSecret === "" ? {} : { tokenSecret: input.tokenSecret };
|
|
455
|
+
await this.deps.updateEntry(input.entryId, {
|
|
456
|
+
name: input.name,
|
|
457
|
+
...input.tokenId !== void 0 ? { tokenId: input.tokenId } : {},
|
|
458
|
+
...secret,
|
|
459
|
+
...input.environment !== void 0 ? { environment: input.environment } : {},
|
|
460
|
+
...input.gpuType !== void 0 ? { gpuType: input.gpuType } : {},
|
|
461
|
+
...input.region !== void 0 ? { region: input.region } : {},
|
|
462
|
+
...input.costCapUsd !== void 0 ? { costCapUsd: input.costCapUsd } : {},
|
|
463
|
+
...input.maxRuntimeSec !== void 0 ? { maxRuntimeHours: input.maxRuntimeSec / 3600 } : {},
|
|
464
|
+
...input.failedDatasetGraceHours !== void 0 ? { failedDatasetGraceHours: input.failedDatasetGraceHours } : {}
|
|
465
|
+
});
|
|
466
|
+
return { ok: true };
|
|
467
|
+
};
|
|
362
468
|
deleteEntry = async (input) => {
|
|
363
469
|
await this.deps.deleteEntry(input.entryId);
|
|
364
470
|
return { ok: true };
|
|
@@ -636,9 +742,12 @@ var ModalTrainingProvider = class {
|
|
|
636
742
|
}))];
|
|
637
743
|
};
|
|
638
744
|
entryConfigured(entry) {
|
|
639
|
-
|
|
745
|
+
const secret = typeof entry.tokenSecret === "string" ? entry.tokenSecret : "";
|
|
746
|
+
return (entry.tokenId ?? "").trim() !== "" && secret.trim() !== "";
|
|
640
747
|
}
|
|
641
|
-
descriptorOf(entry) {
|
|
748
|
+
descriptorOf(entry, tokenSecretView) {
|
|
749
|
+
const tokenId = entry.tokenId ?? "";
|
|
750
|
+
const environment = entry.environment ?? "";
|
|
642
751
|
return {
|
|
643
752
|
addonId: this.deps.addonId,
|
|
644
753
|
entryId: entry.id,
|
|
@@ -655,12 +764,16 @@ var ModalTrainingProvider = class {
|
|
|
655
764
|
dataResidencyNote: "Modal keeps the frames on a Volume of your workspace for the length of the job; the training container sees them only while it runs.",
|
|
656
765
|
configured: this.entryConfigured(entry),
|
|
657
766
|
defaults: {
|
|
658
|
-
gpuType: entry.gpuType,
|
|
659
|
-
region: entry.region,
|
|
660
|
-
costCapUsd: entry.costCapUsd,
|
|
661
|
-
maxRuntimeSec: Math.round(entry.maxRuntimeHours * 3600),
|
|
662
|
-
failedDatasetGraceHours: entry.failedDatasetGraceHours
|
|
663
|
-
}
|
|
767
|
+
gpuType: entry.gpuType ?? "L4",
|
|
768
|
+
region: entry.region ?? "",
|
|
769
|
+
costCapUsd: entry.costCapUsd ?? 5,
|
|
770
|
+
maxRuntimeSec: Math.round((entry.maxRuntimeHours ?? 4) * 3600),
|
|
771
|
+
failedDatasetGraceHours: entry.failedDatasetGraceHours ?? 24
|
|
772
|
+
},
|
|
773
|
+
tokenId,
|
|
774
|
+
environment,
|
|
775
|
+
hasTokenSecret: tokenSecretView !== null,
|
|
776
|
+
tokenSecretView
|
|
664
777
|
};
|
|
665
778
|
}
|
|
666
779
|
requireGateway(entryId) {
|
|
@@ -88513,6 +88626,12 @@ async function fetchText(url) {
|
|
|
88513
88626
|
var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
88514
88627
|
ledgerState = null;
|
|
88515
88628
|
gateways = /* @__PURE__ */ new Map();
|
|
88629
|
+
/**
|
|
88630
|
+
* Entry secrets live on `entries[id].tokenSecret` (and legacy flat
|
|
88631
|
+
* `tokenSecret`). Declared here — not via an editable-array form — so the
|
|
88632
|
+
* Training → Providers page is the only UI that edits entries.
|
|
88633
|
+
*/
|
|
88634
|
+
secretStatePaths = ["entries[id].tokenSecret", "tokenSecret"];
|
|
88516
88635
|
constructor() {
|
|
88517
88636
|
super({
|
|
88518
88637
|
entries: [],
|
|
@@ -88528,9 +88647,15 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
|
88528
88647
|
}
|
|
88529
88648
|
async onInitialize() {
|
|
88530
88649
|
let next = this.config;
|
|
88531
|
-
|
|
88650
|
+
let migratedLegacy = false;
|
|
88651
|
+
if (next.entries.length === 0) {
|
|
88652
|
+
const migrated = migrateLegacyModalConfig(next, () => (0, node_crypto.randomUUID)());
|
|
88653
|
+
migratedLegacy = migrated !== next;
|
|
88654
|
+
next = migrated;
|
|
88655
|
+
}
|
|
88532
88656
|
next = ensureModalEntryIds(next, () => (0, node_crypto.randomUUID)());
|
|
88533
88657
|
if (next !== this.config) await this.updateGlobalSettings(next);
|
|
88658
|
+
if (migratedLegacy) await this.clearSecrets(["tokenSecret"]);
|
|
88534
88659
|
this.ledgerState = this.state(LEDGER_KEY, LedgerSchema, {});
|
|
88535
88660
|
const peer = this.ctx.peerBytes;
|
|
88536
88661
|
if (peer === void 0) throw new Error("training-modal needs the peer-bytes facility");
|
|
@@ -88545,12 +88670,28 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
|
88545
88670
|
await this.updateGlobalSettings(result.config);
|
|
88546
88671
|
return { entryId: result.entryId };
|
|
88547
88672
|
},
|
|
88673
|
+
updateEntry: async (entryId, patch) => {
|
|
88674
|
+
const { clearTokenSecret, ...rest } = patch;
|
|
88675
|
+
const result = updateModalEntry(this.config, entryId, rest);
|
|
88676
|
+
if (!result.ok) throw new Error(`cannot update entry: ${result.reason}`);
|
|
88677
|
+
if (clearTokenSecret === true) await this.updateGlobalSettings({
|
|
88678
|
+
...result.config,
|
|
88679
|
+
entries: result.config.entries.map((entry) => entry.id === entryId ? {
|
|
88680
|
+
...entry,
|
|
88681
|
+
tokenSecret: require_dist.SECRET_CLEAR
|
|
88682
|
+
} : entry)
|
|
88683
|
+
});
|
|
88684
|
+
else await this.updateGlobalSettings(result.config);
|
|
88685
|
+
this.closeGateway(entryId);
|
|
88686
|
+
},
|
|
88548
88687
|
deleteEntry: async (entryId) => {
|
|
88549
88688
|
const result = deleteModalEntry(this.config, entryId);
|
|
88550
88689
|
if (!result.ok) throw new Error(`cannot delete entry: ${result.reason}`);
|
|
88551
88690
|
await this.updateGlobalSettings(result.config);
|
|
88691
|
+
await this.clearSecrets(["tokenSecret"]);
|
|
88552
88692
|
this.closeGateway(entryId);
|
|
88553
88693
|
},
|
|
88694
|
+
secretViews: () => this.readEntrySecretViews(),
|
|
88554
88695
|
ledger: this.ledger(),
|
|
88555
88696
|
peer,
|
|
88556
88697
|
fetchText,
|
|
@@ -88559,7 +88700,10 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
|
88559
88700
|
});
|
|
88560
88701
|
this.ctx.logger.info("Modal training provider ready", { meta: {
|
|
88561
88702
|
entries: effectiveModalEntries(this.config).length,
|
|
88562
|
-
configured: effectiveModalEntries(this.config).some((e) =>
|
|
88703
|
+
configured: effectiveModalEntries(this.config).some((e) => {
|
|
88704
|
+
const secret = typeof e.tokenSecret === "string" ? e.tokenSecret : "";
|
|
88705
|
+
return (e.tokenId ?? "").trim() !== "" && secret.trim() !== "";
|
|
88706
|
+
})
|
|
88563
88707
|
} });
|
|
88564
88708
|
return { providers: [{
|
|
88565
88709
|
capability: require_dist.trainingProviderCapability,
|
|
@@ -88577,15 +88721,18 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
|
88577
88721
|
gatewayFor(entryId) {
|
|
88578
88722
|
const entry = findModalEntry(this.config, entryId);
|
|
88579
88723
|
if (entry === null) return null;
|
|
88580
|
-
|
|
88581
|
-
const
|
|
88724
|
+
const tokenId = (entry.tokenId ?? "").trim();
|
|
88725
|
+
const tokenSecret = (typeof entry.tokenSecret === "string" ? entry.tokenSecret : "").trim();
|
|
88726
|
+
if (tokenId === "" || tokenSecret === "") return null;
|
|
88727
|
+
const environment = (entry.environment ?? "").trim();
|
|
88728
|
+
const key = `${tokenId}\u0000${environment}`;
|
|
88582
88729
|
const cached = this.gateways.get(entryId);
|
|
88583
88730
|
if (cached !== void 0 && cached.key === key) return cached.gateway;
|
|
88584
88731
|
cached?.gateway.close();
|
|
88585
88732
|
const gateway = new ModalSdkGateway({
|
|
88586
|
-
tokenId
|
|
88587
|
-
tokenSecret
|
|
88588
|
-
environment
|
|
88733
|
+
tokenId,
|
|
88734
|
+
tokenSecret,
|
|
88735
|
+
environment
|
|
88589
88736
|
});
|
|
88590
88737
|
this.gateways.set(entryId, {
|
|
88591
88738
|
key,
|
|
@@ -88599,6 +88746,19 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
|
88599
88746
|
cached.gateway.close();
|
|
88600
88747
|
this.gateways.delete(entryId);
|
|
88601
88748
|
}
|
|
88749
|
+
/**
|
|
88750
|
+
* Keychain views for the Providers edit form. Addon-facing reads answer
|
|
88751
|
+
* VALUES (D798), so we cannot recover markers from `readStoredGlobalKey`.
|
|
88752
|
+
* When a secret is present on the resolved entry we emit the deterministic
|
|
88753
|
+
* keychain ref (`ctx.secrets.ref`) so `SecretFieldControl` can reveal.
|
|
88754
|
+
*/
|
|
88755
|
+
async readEntrySecretViews() {
|
|
88756
|
+
const map = /* @__PURE__ */ new Map();
|
|
88757
|
+
const secrets = this.ctx.secrets;
|
|
88758
|
+
for (const entry of effectiveModalEntries(this.config)) map.set(entry.id, entryTokenSecretView(entry.tokenSecret, secrets, entry.id));
|
|
88759
|
+
map.set("legacy-default", flatTokenSecretView(this.config.tokenSecret, secrets));
|
|
88760
|
+
return map;
|
|
88761
|
+
}
|
|
88602
88762
|
ledger() {
|
|
88603
88763
|
const state = () => {
|
|
88604
88764
|
if (this.ledgerState === null) throw new Error("training-modal ledger not initialised");
|
|
@@ -88623,97 +88783,10 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
|
|
|
88623
88783
|
}
|
|
88624
88784
|
globalSettingsSchema() {
|
|
88625
88785
|
return this.schema({ sections: [{
|
|
88626
|
-
id: "
|
|
88786
|
+
id: "providers",
|
|
88627
88787
|
title: "Modal accounts",
|
|
88628
|
-
description: "
|
|
88629
|
-
fields: [
|
|
88630
|
-
type: "editable-array",
|
|
88631
|
-
key: "entries",
|
|
88632
|
-
label: "Entries",
|
|
88633
|
-
itemIdKey: "id",
|
|
88634
|
-
/** Create only via trainingProvider.createEntry (auto id). */
|
|
88635
|
-
maxRows: 0,
|
|
88636
|
-
emptyMessage: "No Modal entries yet — add one from Training → Providers.",
|
|
88637
|
-
rowTitleTemplate: "{name}",
|
|
88638
|
-
defaultItem: {
|
|
88639
|
-
id: "",
|
|
88640
|
-
name: "Default",
|
|
88641
|
-
tokenId: "",
|
|
88642
|
-
tokenSecret: "",
|
|
88643
|
-
environment: "",
|
|
88644
|
-
gpuType: "L4",
|
|
88645
|
-
region: "",
|
|
88646
|
-
costCapUsd: 5,
|
|
88647
|
-
maxRuntimeHours: 4,
|
|
88648
|
-
failedDatasetGraceHours: 24
|
|
88649
|
-
},
|
|
88650
|
-
itemFields: [
|
|
88651
|
-
{
|
|
88652
|
-
type: "text",
|
|
88653
|
-
key: "name",
|
|
88654
|
-
label: "Name"
|
|
88655
|
-
},
|
|
88656
|
-
{
|
|
88657
|
-
type: "text",
|
|
88658
|
-
key: "tokenId",
|
|
88659
|
-
label: "Token id",
|
|
88660
|
-
placeholder: "ak-…"
|
|
88661
|
-
},
|
|
88662
|
-
{
|
|
88663
|
-
type: "password",
|
|
88664
|
-
key: "tokenSecret",
|
|
88665
|
-
label: "Token secret",
|
|
88666
|
-
showToggle: true
|
|
88667
|
-
},
|
|
88668
|
-
{
|
|
88669
|
-
type: "text",
|
|
88670
|
-
key: "environment",
|
|
88671
|
-
label: "Environment",
|
|
88672
|
-
description: "Leave empty for the workspace default."
|
|
88673
|
-
},
|
|
88674
|
-
{
|
|
88675
|
-
type: "select",
|
|
88676
|
-
key: "gpuType",
|
|
88677
|
-
label: "GPU",
|
|
88678
|
-
options: MODAL_GPUS.map((g) => ({
|
|
88679
|
-
value: g.id,
|
|
88680
|
-
label: `${g.label} — $${g.usdPerHour.toFixed(2)}/h`
|
|
88681
|
-
}))
|
|
88682
|
-
},
|
|
88683
|
-
{
|
|
88684
|
-
type: "select",
|
|
88685
|
-
key: "region",
|
|
88686
|
-
label: "Region",
|
|
88687
|
-
options: MODAL_REGIONS.map((r) => ({
|
|
88688
|
-
value: r.id,
|
|
88689
|
-
label: r.label
|
|
88690
|
-
}))
|
|
88691
|
-
},
|
|
88692
|
-
{
|
|
88693
|
-
type: "number",
|
|
88694
|
-
key: "costCapUsd",
|
|
88695
|
-
label: "Cost cap per job (USD)",
|
|
88696
|
-
min: .5,
|
|
88697
|
-
step: .5
|
|
88698
|
-
},
|
|
88699
|
-
{
|
|
88700
|
-
type: "number",
|
|
88701
|
-
key: "maxRuntimeHours",
|
|
88702
|
-
label: "Maximum runtime (hours)",
|
|
88703
|
-
min: .5,
|
|
88704
|
-
max: 24,
|
|
88705
|
-
step: .5
|
|
88706
|
-
},
|
|
88707
|
-
{
|
|
88708
|
-
type: "number",
|
|
88709
|
-
key: "failedDatasetGraceHours",
|
|
88710
|
-
label: "Keep a failed job’s dataset (hours)",
|
|
88711
|
-
min: 0,
|
|
88712
|
-
max: 168,
|
|
88713
|
-
step: 1
|
|
88714
|
-
}
|
|
88715
|
-
]
|
|
88716
|
-
}]
|
|
88788
|
+
description: "Create and edit Modal workspace entries under Training → Providers. Credentials stay in the CamStack keychain.",
|
|
88789
|
+
fields: []
|
|
88717
88790
|
}] });
|
|
88718
88791
|
}
|
|
88719
88792
|
};
|