@camstack/addon-training 0.1.53 → 0.1.56

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.
Files changed (21) hide show
  1. package/dist/{MotionZonesSettings-2L6ZZUzt.mjs → MotionZonesSettings-W5TJMIhz.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-z2Lm90YH.mjs → PrivacyMaskSettings-8bCieYP4.mjs} +2 -2
  3. package/dist/{SceneMonitorEditor-NTZadJI1.mjs → SceneMonitorEditor-hfbQKb07.mjs} +1 -1
  4. package/dist/_stub.js +2222 -2222
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-BNV-3iai.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-DtB9ff7l.mjs} +4 -4
  6. package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CdZst5Eh.mjs +26 -0
  7. package/dist/addon-training.css +1 -1
  8. package/dist/{dist-Dw2AZ607.js → dist-DYEQn1Ss.mjs} +1006 -202
  9. package/dist/{dist-DFfQ_Mth.mjs → dist-DnFIVL4Y.js} +1218 -20
  10. package/dist/{hostInit-CCumz-Qi.mjs → hostInit-Duj8IUS7.mjs} +3 -3
  11. package/dist/index.js +1 -1
  12. package/dist/orchestrator/training.addon.js +64 -104
  13. package/dist/orchestrator/training.addon.mjs +64 -104
  14. package/dist/{player-overlays-C3wXNwRM.mjs → player-overlays-DBfpI8h8.mjs} +1 -1
  15. package/dist/providers/modal/training-modal.addon.js +22 -1
  16. package/dist/providers/modal/training-modal.addon.mjs +19 -1
  17. package/dist/remoteEntry.js +1 -1
  18. package/dist/{responsive-9dr-MOnd.mjs → responsive-CVlns2k2.mjs} +1 -1
  19. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-BCUryvJe.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-GR9ZahAF.mjs} +1 -1
  20. package/package.json +1 -1
  21. package/dist/_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-QkGe-Wgc.mjs +0 -26
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.379",
39
+ version: "1.2.381",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -45,7 +45,7 @@ async function r() {
45
45
  }
46
46
  },
47
47
  "@camstack/sdk": {
48
- version: "1.2.132",
48
+ version: "1.2.133",
49
49
  scope: "default",
50
50
  shareConfig: {
51
51
  singleton: !0,
@@ -81,7 +81,7 @@ async function r() {
81
81
  }
82
82
  },
83
83
  "@camstack/ui-library": {
84
- version: "1.2.297",
84
+ version: "1.2.299",
85
85
  scope: "default",
86
86
  shareConfig: {
87
87
  singleton: !0,
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./dist-Dw2AZ607.js");
2
+ require("./dist-DnFIVL4Y.js");
3
3
  const require_orchestrator_training_addon = require("./orchestrator/training.addon.js");
4
4
  const require_providers_modal_training_modal_addon = require("./providers/modal/training-modal.addon.js");
5
5
  //#region src/providers/fake/fake-provider.ts
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("../dist-Dw2AZ607.js");
2
+ const require_dist = require("../dist-DnFIVL4Y.js");
3
3
  let node_path = require("node:path");
4
4
  node_path = require_dist.__toESM(node_path);
5
5
  let node_crypto = require("node:crypto");
@@ -1630,128 +1630,86 @@ var ReturnFlow = class {
1630
1630
  }
1631
1631
  };
1632
1632
  //#endregion
1633
+ //#region src/orchestrator/record-kinds.ts
1634
+ /**
1635
+ * Record kinds owned by the training orchestrator (records plan phase 2).
1636
+ */
1637
+ var trainingRecordKinds = require_dist.defineRecordKinds({ jobs: {
1638
+ schema: require_dist.TrainingJobSchema,
1639
+ class: "ledger",
1640
+ writeTrigger: "one row per training job, rewritten on every state change by the job engine (upload, submit, reconcile, collect, register, canary, rollback)",
1641
+ device: "none",
1642
+ at: "required",
1643
+ indexes: [{
1644
+ name: "idem",
1645
+ fields: ["idempotencyKey"],
1646
+ unique: true
1647
+ }],
1648
+ retention: { none: "a job row is the record of what ran; it leaves only when the operator deletes it" },
1649
+ maxDataBytes: require_dist.RECORD_MAX_DATA_BYTES,
1650
+ adoptsFrom: "training:jobs"
1651
+ } });
1652
+ //#endregion
1633
1653
  //#region src/orchestrator/stores.ts
1634
1654
  /**
1635
- * The orchestrator's durable job table in the settings store.
1655
+ * The orchestrator's durable job ledger over `ctx.records` (records plan phase 2).
1636
1656
  *
1637
1657
  * Rows are validated on the way OUT (a row a newer build wrote, or a hand
1638
1658
  * edit, never reaches the state machine as a half-shaped job) and dropped
1639
1659
  * with a log line when they do not parse — a job that cannot be read cannot
1640
1660
  * be reconciled, and saying so beats acting on a guess.
1641
1661
  */
1642
- /**
1643
- * @durable class=ledger owner=training
1644
- * write="one row per training job, rewritten on every state change by the job engine
1645
- * (upload, submit, each reconcile poll, collect, register, canary, rollback)."
1646
- * retention="none — a job row is the record of what ran, what it cost and what was
1647
- * registered; it leaves only when the operator deletes it. Its staged artefacts expire
1648
- * separately (14 days after ready/registration) and the row says so."
1649
- */
1650
- var TRAINING_JOBS_COLLECTION = "training:jobs";
1651
- var JOB_COLUMNS = [
1652
- {
1653
- name: "id",
1654
- type: "TEXT",
1655
- primaryKey: true,
1656
- notNull: true
1657
- },
1658
- {
1659
- name: "state",
1660
- type: "TEXT",
1661
- notNull: true
1662
- },
1663
- {
1664
- name: "createdAt",
1665
- type: "INTEGER",
1666
- notNull: true
1667
- },
1668
- {
1669
- name: "idempotencyKey",
1670
- type: "TEXT",
1671
- notNull: true
1672
- },
1673
- {
1674
- name: "job",
1675
- type: "JSON",
1676
- notNull: true
1677
- }
1678
- ];
1679
- var JOB_INDEXES = [{
1680
- name: "idx_training_jobs_idem",
1681
- columns: ["idempotencyKey"],
1682
- unique: true
1683
- }, {
1684
- name: "idx_training_jobs_created",
1685
- columns: ["createdAt"]
1686
- }];
1687
- function parseJson(value) {
1688
- if (typeof value !== "string") return value;
1689
- try {
1690
- return JSON.parse(value);
1691
- } catch {
1692
- return;
1693
- }
1694
- }
1695
- function recordOf(value) {
1696
- return value !== null && typeof value === "object" && !Array.isArray(value) ? { ...value } : {};
1697
- }
1698
- async function declareTrainingCollections(store) {
1699
- await store.declareCollection.mutate({
1700
- collection: TRAINING_JOBS_COLLECTION,
1701
- columns: [...JOB_COLUMNS],
1702
- indexes: [...JOB_INDEXES]
1703
- });
1704
- }
1705
- var SettingsJobStore = class {
1706
- store;
1662
+ var RecordsJobStore = class RecordsJobStore {
1663
+ kind;
1707
1664
  logger;
1708
- constructor(store, logger) {
1709
- this.store = store;
1665
+ constructor(kind, logger) {
1666
+ this.kind = kind;
1710
1667
  this.logger = logger;
1711
1668
  }
1669
+ static of(records, logger) {
1670
+ return new RecordsJobStore(records.kind(trainingRecordKinds.jobs), logger);
1671
+ }
1712
1672
  put = async (job) => {
1713
- await this.store.set.mutate({
1714
- collection: TRAINING_JOBS_COLLECTION,
1715
- key: job.id,
1716
- value: {
1717
- state: job.state,
1718
- createdAt: job.createdAt,
1719
- idempotencyKey: job.idempotencyKey,
1720
- job
1721
- }
1673
+ await this.kind.put({
1674
+ id: job.id,
1675
+ at: job.createdAt,
1676
+ data: job
1722
1677
  });
1723
1678
  };
1724
1679
  get = async (id) => {
1725
- const row = await this.store.get.query({
1726
- collection: TRAINING_JOBS_COLLECTION,
1727
- key: id
1728
- });
1729
- return row === null || row === void 0 ? null : this.parse(id, recordOf(row));
1680
+ const row = await this.kind.get(id);
1681
+ return row === null ? null : this.parse(id, row.data);
1730
1682
  };
1731
1683
  list = async () => {
1732
- return (await this.store.query.query({
1733
- collection: TRAINING_JOBS_COLLECTION,
1734
- filter: { orderBy: {
1735
- field: "createdAt",
1736
- direction: "desc"
1737
- } }
1738
- })).flatMap((r) => {
1739
- const job = this.parse(r.id, recordOf(r.data));
1740
- return job === null ? [] : [job];
1741
- });
1684
+ const out = [];
1685
+ let cursor;
1686
+ for (let page = 0; page < 100; page += 1) {
1687
+ const { records, nextCursor } = await this.kind.query({
1688
+ order: "at",
1689
+ desc: true,
1690
+ limit: 1e3,
1691
+ ...cursor === void 0 ? {} : { cursor }
1692
+ });
1693
+ for (const row of records) {
1694
+ const job = this.parse(row.id, row.data);
1695
+ if (job !== null) out.push(job);
1696
+ }
1697
+ if (nextCursor === null) return out;
1698
+ cursor = nextCursor;
1699
+ }
1700
+ this.logger.warn("training job list hit the page bound — truncated", { meta: { kept: out.length } });
1701
+ return out;
1742
1702
  };
1743
1703
  findByIdempotencyKey = async (key) => {
1744
- const row = (await this.store.query.query({
1745
- collection: TRAINING_JOBS_COLLECTION,
1746
- filter: {
1747
- where: { idempotencyKey: key },
1748
- limit: 1
1749
- }
1750
- }))[0];
1751
- return row === void 0 ? null : this.parse(row.id, recordOf(row.data));
1704
+ const { records } = await this.kind.query({
1705
+ where: { idempotencyKey: key },
1706
+ limit: 1
1707
+ });
1708
+ const row = records[0];
1709
+ return row === void 0 ? null : this.parse(row.id, row.data);
1752
1710
  };
1753
1711
  parse(id, data) {
1754
- const parsed = require_dist.TrainingJobSchema.safeParse(parseJson(data["job"]));
1712
+ const parsed = require_dist.TrainingJobSchema.safeParse(data);
1755
1713
  if (parsed.success) return parsed.data;
1756
1714
  this.logger.warn("training job row does not parse — skipped", { meta: {
1757
1715
  jobId: id,
@@ -1797,14 +1755,16 @@ var TrainingAddon = class extends require_dist.BaseAddon {
1797
1755
  async onInitialize() {
1798
1756
  const api = this.ctx.api;
1799
1757
  const peer = this.ctx.peerBytes;
1758
+ const records = this.ctx.records;
1800
1759
  if (peer === void 0) throw new Error("training needs the peer-bytes facility");
1801
- await declareTrainingCollections(api.settingsStore);
1760
+ if (records === void 0) throw new Error("training needs ctx.records");
1761
+ await records.declare(trainingRecordKinds);
1802
1762
  const logger = this.ctx.logger;
1803
1763
  const ports = {
1804
1764
  provider: providerPort(api),
1805
1765
  datasets: datasetPort(api),
1806
1766
  corpus: corpusPort(api),
1807
- jobs: new SettingsJobStore(api.settingsStore, logger),
1767
+ jobs: RecordsJobStore.of(records, logger),
1808
1768
  artifacts: createDiskArtifacts(node_path.default.join(this.ctx.dataDir, "training", "jobs"), peer),
1809
1769
  registry: registryPort(api),
1810
1770
  pins: pinPort(api),
@@ -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-DFfQ_Mth.mjs";
1
+ import { a as addonPagesSourceCapability, i as TrainingResultSchema, l as BaseAddon, m as defineRecordKinds, n as TrainingJobSchema, o as parseTrainingEventLine, r as TrainingJobSpecSchema, s as trainingCapability, t as TRAINING_JOB_SCHEMA, u as RECORD_MAX_DATA_BYTES } from "../dist-DYEQn1Ss.mjs";
2
2
  import path from "node:path";
3
3
  import { createHash } from "node:crypto";
4
4
  import { createReadStream } from "node:fs";
@@ -1628,128 +1628,86 @@ var ReturnFlow = class {
1628
1628
  }
1629
1629
  };
1630
1630
  //#endregion
1631
+ //#region src/orchestrator/record-kinds.ts
1632
+ /**
1633
+ * Record kinds owned by the training orchestrator (records plan phase 2).
1634
+ */
1635
+ var trainingRecordKinds = defineRecordKinds({ jobs: {
1636
+ schema: TrainingJobSchema,
1637
+ class: "ledger",
1638
+ writeTrigger: "one row per training job, rewritten on every state change by the job engine (upload, submit, reconcile, collect, register, canary, rollback)",
1639
+ device: "none",
1640
+ at: "required",
1641
+ indexes: [{
1642
+ name: "idem",
1643
+ fields: ["idempotencyKey"],
1644
+ unique: true
1645
+ }],
1646
+ retention: { none: "a job row is the record of what ran; it leaves only when the operator deletes it" },
1647
+ maxDataBytes: RECORD_MAX_DATA_BYTES,
1648
+ adoptsFrom: "training:jobs"
1649
+ } });
1650
+ //#endregion
1631
1651
  //#region src/orchestrator/stores.ts
1632
1652
  /**
1633
- * The orchestrator's durable job table in the settings store.
1653
+ * The orchestrator's durable job ledger over `ctx.records` (records plan phase 2).
1634
1654
  *
1635
1655
  * Rows are validated on the way OUT (a row a newer build wrote, or a hand
1636
1656
  * edit, never reaches the state machine as a half-shaped job) and dropped
1637
1657
  * with a log line when they do not parse — a job that cannot be read cannot
1638
1658
  * be reconciled, and saying so beats acting on a guess.
1639
1659
  */
1640
- /**
1641
- * @durable class=ledger owner=training
1642
- * write="one row per training job, rewritten on every state change by the job engine
1643
- * (upload, submit, each reconcile poll, collect, register, canary, rollback)."
1644
- * retention="none — a job row is the record of what ran, what it cost and what was
1645
- * registered; it leaves only when the operator deletes it. Its staged artefacts expire
1646
- * separately (14 days after ready/registration) and the row says so."
1647
- */
1648
- var TRAINING_JOBS_COLLECTION = "training:jobs";
1649
- var JOB_COLUMNS = [
1650
- {
1651
- name: "id",
1652
- type: "TEXT",
1653
- primaryKey: true,
1654
- notNull: true
1655
- },
1656
- {
1657
- name: "state",
1658
- type: "TEXT",
1659
- notNull: true
1660
- },
1661
- {
1662
- name: "createdAt",
1663
- type: "INTEGER",
1664
- notNull: true
1665
- },
1666
- {
1667
- name: "idempotencyKey",
1668
- type: "TEXT",
1669
- notNull: true
1670
- },
1671
- {
1672
- name: "job",
1673
- type: "JSON",
1674
- notNull: true
1675
- }
1676
- ];
1677
- var JOB_INDEXES = [{
1678
- name: "idx_training_jobs_idem",
1679
- columns: ["idempotencyKey"],
1680
- unique: true
1681
- }, {
1682
- name: "idx_training_jobs_created",
1683
- columns: ["createdAt"]
1684
- }];
1685
- function parseJson(value) {
1686
- if (typeof value !== "string") return value;
1687
- try {
1688
- return JSON.parse(value);
1689
- } catch {
1690
- return;
1691
- }
1692
- }
1693
- function recordOf(value) {
1694
- return value !== null && typeof value === "object" && !Array.isArray(value) ? { ...value } : {};
1695
- }
1696
- async function declareTrainingCollections(store) {
1697
- await store.declareCollection.mutate({
1698
- collection: TRAINING_JOBS_COLLECTION,
1699
- columns: [...JOB_COLUMNS],
1700
- indexes: [...JOB_INDEXES]
1701
- });
1702
- }
1703
- var SettingsJobStore = class {
1704
- store;
1660
+ var RecordsJobStore = class RecordsJobStore {
1661
+ kind;
1705
1662
  logger;
1706
- constructor(store, logger) {
1707
- this.store = store;
1663
+ constructor(kind, logger) {
1664
+ this.kind = kind;
1708
1665
  this.logger = logger;
1709
1666
  }
1667
+ static of(records, logger) {
1668
+ return new RecordsJobStore(records.kind(trainingRecordKinds.jobs), logger);
1669
+ }
1710
1670
  put = async (job) => {
1711
- await this.store.set.mutate({
1712
- collection: TRAINING_JOBS_COLLECTION,
1713
- key: job.id,
1714
- value: {
1715
- state: job.state,
1716
- createdAt: job.createdAt,
1717
- idempotencyKey: job.idempotencyKey,
1718
- job
1719
- }
1671
+ await this.kind.put({
1672
+ id: job.id,
1673
+ at: job.createdAt,
1674
+ data: job
1720
1675
  });
1721
1676
  };
1722
1677
  get = async (id) => {
1723
- const row = await this.store.get.query({
1724
- collection: TRAINING_JOBS_COLLECTION,
1725
- key: id
1726
- });
1727
- return row === null || row === void 0 ? null : this.parse(id, recordOf(row));
1678
+ const row = await this.kind.get(id);
1679
+ return row === null ? null : this.parse(id, row.data);
1728
1680
  };
1729
1681
  list = async () => {
1730
- return (await this.store.query.query({
1731
- collection: TRAINING_JOBS_COLLECTION,
1732
- filter: { orderBy: {
1733
- field: "createdAt",
1734
- direction: "desc"
1735
- } }
1736
- })).flatMap((r) => {
1737
- const job = this.parse(r.id, recordOf(r.data));
1738
- return job === null ? [] : [job];
1739
- });
1682
+ const out = [];
1683
+ let cursor;
1684
+ for (let page = 0; page < 100; page += 1) {
1685
+ const { records, nextCursor } = await this.kind.query({
1686
+ order: "at",
1687
+ desc: true,
1688
+ limit: 1e3,
1689
+ ...cursor === void 0 ? {} : { cursor }
1690
+ });
1691
+ for (const row of records) {
1692
+ const job = this.parse(row.id, row.data);
1693
+ if (job !== null) out.push(job);
1694
+ }
1695
+ if (nextCursor === null) return out;
1696
+ cursor = nextCursor;
1697
+ }
1698
+ this.logger.warn("training job list hit the page bound — truncated", { meta: { kept: out.length } });
1699
+ return out;
1740
1700
  };
1741
1701
  findByIdempotencyKey = async (key) => {
1742
- const row = (await this.store.query.query({
1743
- collection: TRAINING_JOBS_COLLECTION,
1744
- filter: {
1745
- where: { idempotencyKey: key },
1746
- limit: 1
1747
- }
1748
- }))[0];
1749
- return row === void 0 ? null : this.parse(row.id, recordOf(row.data));
1702
+ const { records } = await this.kind.query({
1703
+ where: { idempotencyKey: key },
1704
+ limit: 1
1705
+ });
1706
+ const row = records[0];
1707
+ return row === void 0 ? null : this.parse(row.id, row.data);
1750
1708
  };
1751
1709
  parse(id, data) {
1752
- const parsed = TrainingJobSchema.safeParse(parseJson(data["job"]));
1710
+ const parsed = TrainingJobSchema.safeParse(data);
1753
1711
  if (parsed.success) return parsed.data;
1754
1712
  this.logger.warn("training job row does not parse — skipped", { meta: {
1755
1713
  jobId: id,
@@ -1795,14 +1753,16 @@ var TrainingAddon = class extends BaseAddon {
1795
1753
  async onInitialize() {
1796
1754
  const api = this.ctx.api;
1797
1755
  const peer = this.ctx.peerBytes;
1756
+ const records = this.ctx.records;
1798
1757
  if (peer === void 0) throw new Error("training needs the peer-bytes facility");
1799
- await declareTrainingCollections(api.settingsStore);
1758
+ if (records === void 0) throw new Error("training needs ctx.records");
1759
+ await records.declare(trainingRecordKinds);
1800
1760
  const logger = this.ctx.logger;
1801
1761
  const ports = {
1802
1762
  provider: providerPort(api),
1803
1763
  datasets: datasetPort(api),
1804
1764
  corpus: corpusPort(api),
1805
- jobs: new SettingsJobStore(api.settingsStore, logger),
1765
+ jobs: RecordsJobStore.of(records, logger),
1806
1766
  artifacts: createDiskArtifacts(path.join(this.ctx.dataDir, "training", "jobs"), peer),
1807
1767
  registry: registryPort(api),
1808
1768
  pins: pinPort(api),
@@ -1,7 +1,7 @@
1
1
  import { d as e, u as t, w as n, y as r } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react__loadShare__.js-CEvdvp1T.mjs";
2
2
  import { n as i, r as a, t as o } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DnrbBvrw.mjs";
3
3
  import { n as s, t as c } from "./chevron-right-cA8Hucbi.mjs";
4
- import { h as l } from "./responsive-9dr-MOnd.mjs";
4
+ import { h as l } from "./responsive-CVlns2k2.mjs";
5
5
  //#region ../ui-library/src/composites/widget-panel.tsx
6
6
  n();
7
7
  function u({ title: e, icon: t, headerRight: n, collapsible: l = !1, defaultOpen: u = !0, bodyClassName: d = "p-3", children: f }) {
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("../../dist-Dw2AZ607.js");
2
+ const require_dist = require("../../dist-DnFIVL4Y.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");
@@ -88677,6 +88677,24 @@ var ModalSdkGateway = class {
88677
88677
  }
88678
88678
  };
88679
88679
  //#endregion
88680
+ //#region src/providers/modal/training-account-record-kinds.ts
88681
+ var TrainingAccountBodySchema = require_dist.entryBody({
88682
+ tokenId: require_dist.string(),
88683
+ tokenSecret: require_dist.string().meta({ secret: true }),
88684
+ environment: require_dist.string(),
88685
+ gpuType: require_dist.string(),
88686
+ region: require_dist.string(),
88687
+ costCapUsd: require_dist.number(),
88688
+ maxRuntimeHours: require_dist.number(),
88689
+ failedDatasetGraceHours: require_dist.number()
88690
+ });
88691
+ var trainingAccountEntryKind = require_dist.defineEntryKind("training-account", {
88692
+ title: "Modal training accounts",
88693
+ schema: TrainingAccountBodySchema,
88694
+ writeTrigger: "an operator adds or edits a cloud training provider account",
88695
+ adoptsFrom: require_dist.settingsArrayAdoptsFrom("training-modal", "entries")
88696
+ });
88697
+ //#endregion
88680
88698
  //#region src/providers/modal/training-modal.addon.ts
88681
88699
  /**
88682
88700
  * `training-modal` — the Modal `training-provider` (D807).
@@ -88734,6 +88752,9 @@ var TrainingModalAddon = class extends require_dist.BaseAddon {
88734
88752
  });
88735
88753
  }
88736
88754
  async onInitialize() {
88755
+ const records = this.ctx.records;
88756
+ if (records === void 0) throw new Error("training-modal: ctx.records is required (hub-only addon)");
88757
+ await records.declare({ "training-account": trainingAccountEntryKind });
88737
88758
  let next = this.config;
88738
88759
  let migratedLegacy = false;
88739
88760
  if (next.entries.length === 0) {
@@ -1,4 +1,4 @@
1
- import { _ as number, b as string, c as trainingProviderCapability, d as arrayItemFieldPath, f as globalSecretScope, g as boolean, h as toSecretFieldView, l as BaseAddon, m as isSecretMarker, p as isSecretClear, u as SECRET_CLEAR, v as object, y as record } from "../../dist-DFfQ_Mth.mjs";
1
+ import { C as object, S as number, T as string, _ as isSecretClear, b as toSecretFieldView, c as trainingProviderCapability, d as SECRET_CLEAR, f as arrayItemFieldPath, g as globalSecretScope, h as entryBody, l as BaseAddon, p as defineEntryKind, v as isSecretMarker, w as record, x as boolean, y as settingsArrayAdoptsFrom } from "../../dist-DYEQn1Ss.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import path, { dirname, posix } from "node:path";
4
4
  import { createHash, createPrivateKey, createPublicKey, createSign, randomBytes, randomUUID } from "node:crypto";
@@ -88704,6 +88704,21 @@ var ModalSdkGateway = class {
88704
88704
  return this.client.images.fromRegistry(spec.recipe.from).dockerfileCommands([...spec.recipe.commands]);
88705
88705
  }
88706
88706
  };
88707
+ var trainingAccountEntryKind = defineEntryKind("training-account", {
88708
+ title: "Modal training accounts",
88709
+ schema: entryBody({
88710
+ tokenId: string(),
88711
+ tokenSecret: string().meta({ secret: true }),
88712
+ environment: string(),
88713
+ gpuType: string(),
88714
+ region: string(),
88715
+ costCapUsd: number(),
88716
+ maxRuntimeHours: number(),
88717
+ failedDatasetGraceHours: number()
88718
+ }),
88719
+ writeTrigger: "an operator adds or edits a cloud training provider account",
88720
+ adoptsFrom: settingsArrayAdoptsFrom("training-modal", "entries")
88721
+ });
88707
88722
  //#endregion
88708
88723
  //#region src/providers/modal/training-modal.addon.ts
88709
88724
  /**
@@ -88762,6 +88777,9 @@ var TrainingModalAddon = class extends BaseAddon {
88762
88777
  });
88763
88778
  }
88764
88779
  async onInitialize() {
88780
+ const records = this.ctx.records;
88781
+ if (records === void 0) throw new Error("training-modal: ctx.records is required (hub-only addon)");
88782
+ await records.declare({ "training-account": trainingAccountEntryKind });
88765
88783
  let next = this.config;
88766
88784
  let migratedLegacy = false;
88767
88785
  if (next.entries.length === 0) {
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-BCUryvJe.mjs";
1
+ import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_training_page__remoteEntry_js-GR9ZahAF.mjs";
2
2
  export { t as get, e as init };
@@ -1,6 +1,6 @@
1
1
  import { b as e, d as t, g as n, l as r, n as i, u as a, w as o, y as s } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react__loadShare__.js-CEvdvp1T.mjs";
2
2
  import "./_virtual_mf___mfe_internal__addon_training_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DnrbBvrw.mjs";
3
- import { y as c } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-QkGe-Wgc.mjs";
3
+ import { y as c } from "./_virtual_mf___mfe_internal__addon_training_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CdZst5Eh.mjs";
4
4
  //#region ../ui-library/src/lib/shared-context.ts
5
5
  o();
6
6
  function l(e, t) {
@@ -2762,7 +2762,7 @@ async function or(e) {
2762
2762
  }
2763
2763
  }
2764
2764
  async function sr() {
2765
- return ir ||= or(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-BNV-3iai.mjs")).catch((e) => {
2765
+ return ir ||= or(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_training_page-DtB9ff7l.mjs")).catch((e) => {
2766
2766
  throw ir = void 0, e;
2767
2767
  }), ir;
2768
2768
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-training",
3
- "version": "0.1.53",
3
+ "version": "0.1.56",
4
4
  "description": "Cloud training for CamStack: fine-tune the root detector on your own frames, on your own GPU-cloud account",
5
5
  "keywords": [
6
6
  "camstack",