import { validateConfig as l } from "./models/config.js";
import { saveModel as p } from "./loader/save.js";
import { loadModel as u } from "./loader/load.js";
import f from "./Generator.js";
import h from "./Trainer.js";
import { E as c } from "./index-DvYrXKkX.js";
import { dummyPassTrainAsync as d } from "./utilities/dummy.js";
import "./index-DSGwv2Yx.js";
import "./random_width-B_fVXhGx.js";
import "./zeros_like-rOHr54NY.js";
import "./index-Cp39cXWe.js";
import "./dataset-DlqAN81i.js";
import "./ops/cpu/attentionMask.js";
import "./ops/webgl/attentionMask.js";
import "./ops/grads/attentionMask.js";
import "./ops/cpu/rope.js";
import "./ops/webgl/rope.js";
import "./rope-CC5RjmKU.js";
import "./ops/cpu/appendCache.js";
import "./ops/webgl/appendCache.js";
import "./ops/grads/softmax16.js";
import "./matMul16-BIT70Vya.js";
import "./ops/webgl/matMul16.js";
import "./ops/cpu/matMul16.js";
import "./pack16-WlOSOuZA.js";
import "./ops/transpose16.js";
import "./ops/reshape16.js";
import "./ops/cpu/qkv.js";
import "./ops/webgl/qkv.js";
import "./ops/grads/qkv.js";
import "./ops/cpu/normRMS.js";
import "./ops/webgl/normRMS.js";
import "./ops/grads/normRMS.js";
import "./ops/dropout16.js";
import "./ops/webgl/dropout16.js";
import "./ops/grads/add16.js";
import g from "./tokeniser/CharTokeniser.js";
import w from "./tokeniser/bpe.js";
import "./papaparse.min-C0cScC2i.js";
import "./jszip.min-BZhlzntC.js";
import "./ops/cpu/gatherSub.js";
import "./ops/webgl/gatherSub.js";
import "./ops/cpu/scatterSub.js";
import "./ops/webgl/scatterSub.js";
import "./ops/cpu/matMulGelu.js";
import "./matMulGelu-CsZnh18H.js";
import "./ops/grads/matMulGelu.js";
import "./ops/cpu/gelu.js";
import "./ops/webgl/gelu.js";
import "./gelu-DpTCC3eB.js";
import "./ops/webgl/log.js";
import "./ops/cpu/adamMoments.js";
import "./ops/webgl/adamMoments.js";
import "./ops/cpu/adamAdjust.js";
import "./ops/webgl/adamAdjust.js";
import "./checks/normRMS.js";
import "./checks/normRMSGrad.js";
import k from "./utilities/profile.js";
import y from "./models/factory.js";
class _ {
  ee = new c();
  _config;
  _model;
  _tokeniser;
  _status = "loading";
  _memoryRequirements;
  meta = {
    version: 2,
    application: "@genai-fi/nanogpt"
  };
  _trainer = null;
  constructor(t, i) {
    this._config = i?.config, this._tokeniser = t, this._model = i, i?.metaData && (this.meta = i.metaData);
  }
  get currentTrainer() {
    return this._trainer;
  }
  get vocab() {
    return this._tokeniser?.getVocab() || [];
  }
  get phase() {
    return this._model?.metaData?.phase ?? "untrained";
  }
  set phase(t) {
    if (!this._model)
      throw new Error("model_not_initialized.");
    this._model.metaData.phase = t, this.ee.emit("phase", t);
  }
  /** Model is fully loaded */
  get loaded() {
    return !!this._model && !!this._tokeniser && !!this._config;
  }
  get config() {
    if (!this._config)
      throw new Error("configuration_not_initialized.");
    return this._config;
  }
  get model() {
    if (!this._model)
      throw new Error("model_not_initialized.");
    return this._model;
  }
  get tokeniser() {
    if (!this._tokeniser)
      throw new Error("tokeniser_not_initialized.");
    return this._tokeniser;
  }
  get status() {
    return this._status;
  }
  /** Model is both ready and not busy */
  get ready() {
    return this._status === "ready" && !!this._model && !!this._tokeniser;
  }
  get busy() {
    return this._status === "busy" || this._status === "training";
  }
  createLoRA(t, i) {
    if (!this._model)
      throw new Error("model_not_initialized.");
    this._model.createLoRA(t, i), this.ee.emit("changeLoRA");
  }
  deleteLoRA(t) {
    if (!this._model)
      throw new Error("model_not_initialized.");
    this._model.deleteLoRA(t), this.ee.emit("changeLoRA");
  }
  renameLoRA(t, i) {
    if (!this._model)
      throw new Error("model_not_initialized.");
    this._model.renameLoRA(t, i), this.ee.emit("changeLoRA");
  }
  attachLoRA(t) {
    if (!this._model)
      throw new Error("model_not_initialized.");
    this._model.attachLoRA(t), this.ee.emit("changeLoRA");
  }
  detachLoRA() {
    if (!this._model)
      throw new Error("model_not_initialized.");
    this._model.detachLoRA(), this.ee.emit("changeLoRA");
  }
  hasLoRA(t) {
    if (!this._model)
      throw new Error("model_not_initialized.");
    return this._model.hasLoRA(t);
  }
  listLoRAs() {
    if (!this._model)
      throw new Error("model_not_initialized.");
    return this._model.listLoRAs();
  }
  estimateTrainingMemoryUsage(t) {
    const i = this._memoryRequirements ?? { perBatch: 0, gradients: 0 }, e = i.perBatch * t, o = i.gradients;
    return e * 0.66 + o * 4;
  }
  setStatus(t) {
    this._status !== t && (this._status = t, this.ee.emit("status", t));
  }
  saveModel(t) {
    if (!this._model || !this._tokeniser)
      throw new Error("model_or_tokeniser_not_initialized.");
    return p(
      this._model,
      this._tokeniser,
      {
        ...t,
        name: t?.name || this.meta.name
      },
      t?.includeOptimizer && this._trainer?.trainingType === "pretraining" ? { optimizer: this._trainer.optimizer, trainingLog: this._trainer.log } : void 0
    );
  }
  static loadModel(t, i) {
    const e = new _();
    return u(t, i).then(({ model: o, tokeniser: s, metaData: r, optimizer: n, log: a }) => {
      l(o.config), e._model = o, e._tokeniser = s, e._config = o.config, r && (e.meta = r), e.setStatus("warmup"), d(o).then((m) => {
        e._memoryRequirements = m, n && (e._trainer = new h(
          o,
          s,
          "pretraining",
          o.metaData.pretrainingSettings,
          n
        ), a && (e._trainer.log = a)), e.setStatus("ready"), e.ee.emit("loaded"), e.ee.emit("phase", e.phase);
      }).catch((m) => {
        e.setStatus("error"), e.ee.emit("error", m), console.error("Error during warmup:", m);
      });
    }).catch((o) => {
      e.setStatus("error"), e.ee.emit("error", o), console.error("Error loading model:", o);
    }), e;
  }
  static create(t, i) {
    l(i);
    const e = i, o = t === "char" ? new g(e.vocabSize) : new w(e.vocabSize), s = y(e), r = new _(o, s);
    return r.setStatus("warmup"), d(s).then((n) => {
      r._memoryRequirements = n, r.tokeniser.trained ? (r.setStatus("ready"), r.ee.emit("loaded"), r.ee.emit("phase", r.phase)) : (r.setStatus("awaitingTokens"), r.ee.emit("loaded"), r.ee.emit("phase", r.phase), r.tokeniser.once("trainStatus", (a) => {
        a === "trained" && r.setStatus("ready");
      }));
    }).catch((n) => {
      r.setStatus("error"), r.ee.emit("error", n), console.error("Error during warmup:", n);
    }), r;
  }
  getProfiler() {
    return this._model?.getProfiler();
  }
  get enableProfiler() {
    return !!this._model?.getProfiler();
  }
  set enableProfiler(t) {
    if (t) {
      if (!this._config)
        return;
      this.model.getProfiler() || this.model.setProfiler(new k());
    } else
      this.model.getProfiler() && this.model.setProfiler(null);
  }
  getNumParams() {
    return this._model ? this._model.getNumParams() : 0;
  }
  trainer(t, i) {
    if (!this._model || !this._tokeniser)
      throw new Error("model_or_tokeniser_not_initialized.");
    this._trainer && t && this._trainer.trainingType !== t && (this._trainer.dispose(), this._trainer = null);
    const e = this._trainer === null ? new h(this._model, this._tokeniser, t, i) : new h(this._trainer, i);
    return e.on("start", () => {
      this.setStatus("training"), this.phase = t === "sft" ? "finetuned" : "pretrained";
    }), e.on("stop", () => this.setStatus("ready")), e.on("log", async (o) => {
      const s = this.ee.listeners("trainStep");
      for (const r of s)
        await r(o);
    }), this._trainer && this._trainer !== e && this._trainer.removeAllListeners(), this._trainer = e, e;
  }
  async train(t, i, e) {
    const o = this.trainer(e, i);
    await o.prepare(t), await o.train();
  }
  async trainTokeniser(t) {
    if (!this._tokeniser)
      throw new Error("tokeniser_not_initialized.");
    const i = await this._tokeniser.train(t);
    return this._status === "awaitingTokens" && this.setStatus("ready"), i;
  }
  generator() {
    if (!this._model || !this._tokeniser)
      throw new Error("model_or_tokeniser_not_initialized.");
    const t = new f(this._model, this._tokeniser);
    return t.on("start", () => {
      this.status === "ready" && this.setStatus("busy");
    }), t.on("stop", () => {
      this.status === "busy" && this.setStatus("ready");
    }), t;
  }
  generateText(t, i) {
    return Array.isArray(t) ? this.generator().generate(t, i) : this.generator().generate([], i);
  }
  dispose() {
    this._trainer && (this._trainer.dispose(), this._trainer = null), this._model?.dispose(), this.ee.removeAllListeners();
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  on(t, i) {
    if (t === "loaded" && this.loaded) {
      setTimeout(() => i(), 0);
      return;
    }
    this.ee.on(t, i);
  }
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  off(t, i) {
    this.ee.off(t, i);
  }
}
export {
  _ as default
};
