{"version":3,"sources":["../../../src/tools/python/storage.ts"],"names":["PythonStorage","Serializable","TemporaryStorage","files","list","slice","upload","map","file","id","pythonId","filename","download","filter","every","f","createSnapshot","loadSnapshot","snapshot","Object","assign","LocalPythonStorage","input","ignoredFiles","Set","init","fs","promises","mkdir","localWorkingDir","recursive","interpreterWorkingDir","readdir","withFileTypes","Promise","all","isFile","has","name","computeHash","path","join","toString","fileList","filesystemFile","find","copyFile","hash","crypto","createHash","pipeline","createReadStream","digest","shallowCopy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCO,MAAeA,sBAAsBC,6BAAAA,CAAAA;AAAAA,EAAAA;;;AAe5C;AAEO,MAAMC,yBAAyBF,aAAAA,CAAAA;AAAAA,EAAAA;;;AAC1BG,EAAAA,KAAAA,GAAsB,EAAA;AAEhC,EAAA,MAAMC,IAAAA,GAAO;AACX,IAAA,OAAO,IAAA,CAAKD,MAAME,KAAAA,EAAK;AACzB,EAAA;AAEA,EAAA,MAAMC,OAAOH,KAAAA,EAAkD;AAC7D,IAAA,OAAOA,KAAAA,CAAMI,GAAAA,CAAI,CAACC,IAAAA,MAAU;AAC1BC,MAAAA,EAAAA,EAAID,IAAAA,CAAKC,EAAAA;AACTC,MAAAA,QAAAA,EAAUF,IAAAA,CAAKC,EAAAA;AACfE,MAAAA,QAAAA,EAAUH,IAAAA,CAAKG;KACjB,CAAA,CAAA;AACF,EAAA;AAEA,EAAA,MAAMC,SAAST,KAAAA,EAA6B;AAC1C,IAAA,IAAA,CAAKA,KAAAA,GAAQ;AACR,MAAA,GAAA,IAAA,CAAKA,KAAAA,CAAMU,MAAAA,CAAO,CAACL,IAAAA,KAASL,KAAAA,CAAMW,KAAAA,CAAM,CAACC,CAAAA,KAAMA,CAAAA,CAAEJ,QAAAA,KAAaH,IAAAA,CAAKG,QAAQ,CAAA,CAAA;SAC3ER,KAAAA,CAAMI,GAAAA,CAAI,CAACC,IAAAA,MAAU;AAAEC,QAAAA,EAAAA,EAAID,IAAAA,CAAKE,QAAAA;QAAU,GAAGF;OAAK,CAAA;;AAEvD,IAAA,OAAO,IAAA,CAAKL,MAAME,KAAAA,EAAK;AACzB,EAAA;EAEAW,cAAAA,GAAiB;AACf,IAAA,OAAO;MAAEb,KAAAA,EAAO,IAAA,CAAKA,MAAME,KAAAA;AAAQ,KAAA;AACrC,EAAA;AAEAY,EAAAA,YAAAA,CAAaC,QAAAA,EAAkD;AAC7DC,IAAAA,MAAAA,CAAOC,MAAAA,CAAO,MAAMF,QAAAA,CAAAA;AACtB,EAAA;AACF;AAQO,MAAMG,2BAA2BrB,aAAAA,CAAAA;AAAAA,EAAAA;;;AACnBsB,EAAAA,KAAAA;AAEnB,EAAA,WAAA,CAAYA,KAAAA,EAAc;AACxB,IAAA,KAAA,EAAK;AACL,IAAA,IAAA,CAAKA,KAAAA,GAAQ;MACX,GAAGA,KAAAA;MACHC,YAAAA,EAAcD,KAAAA,EAAOC,YAAAA,oBAAgB,IAAIC,GAAAA,CAAI;AAAC,QAAA;AAAW,OAAA;AAC3D,KAAA;AACF,EAAA;AAEA,EAAA,MACgBC,IAAAA,GAAO;AACrB,IAAA,MAAMC,mBAAAA,CAAGC,QAAAA,CAASC,KAAAA,CAAM,IAAA,CAAKN,MAAMO,eAAAA,EAAiB;MAAEC,SAAAA,EAAW;KAAK,CAAA;AACtE,IAAA,MAAMJ,mBAAAA,CAAGC,QAAAA,CAASC,KAAAA,CAAM,IAAA,CAAKN,MAAMS,qBAAAA,EAAuB;MAAED,SAAAA,EAAW;KAAK,CAAA;AAC9E,EAAA;AAEA,EAAA,MAAM1B,IAAAA,GAA8B;AAClC,IAAA,MAAM,KAAKqB,IAAAA,EAAI;AAEf,IAAA,MAAMtB,QAAQ,MAAMuB,mBAAAA,CAAGC,SAASK,OAAAA,CAAQ,IAAA,CAAKV,MAAMO,eAAAA,EAAiB;MAClEI,aAAAA,EAAe,IAAA;MACfH,SAAAA,EAAW;KACb,CAAA;AACA,IAAA,OAAOI,OAAAA,CAAQC,IACbhC,KAAAA,CACGU,MAAAA,CAAO,CAACL,IAAAA,KAASA,IAAAA,CAAK4B,QAAM,IAAM,CAAC,KAAKd,KAAAA,CAAMC,YAAAA,CAAac,IAAI7B,IAAAA,CAAK8B,IAAI,CAAA,CAAA,CACxE/B,GAAAA,CAAI,OAAOC,IAAAA,KAAAA;AACV,MAAA,MAAME,QAAAA,GAAW,MAAM,IAAA,CAAK6B,WAAAA,CAC1BC,qBAAAA,CAAKC,IAAAA,CAAK,IAAA,CAAKnB,KAAAA,CAAMO,eAAAA,CAAgBa,QAAAA,EAAQ,EAAIlC,IAAAA,CAAK8B,IAAI,CAAA,CAAA;AAG5D,MAAA,OAAO;QACL7B,EAAAA,EAAIC,QAAAA;AACJC,QAAAA,QAAAA,EAAUH,IAAAA,CAAK8B,IAAAA;AACf5B,QAAAA;AACF,OAAA;AACF,IAAA,CAAA,CAAA,CAAA;AAEN,EAAA;AAEA,EAAA,MAAMJ,OAAOH,KAAAA,EAAkD;AAC7D,IAAA,MAAM,KAAKsB,IAAAA,EAAI;AAEf,IAAA,MAAMkB,QAAAA,GAAW,MAAM,IAAA,CAAKvC,IAAAA,EAAI;AAEhC,IAAA,MAAM8B,OAAAA,CAAQC,GAAAA,CACZhC,KAAAA,CAAMI,GAAAA,CAAI,CAACC,IAAAA,KAAAA;AACT,MAAA,MAAMoC,cAAAA,GAAiBD,SAASE,IAAAA,CAAK,CAACD,oBAAmBA,eAAAA,CAAenC,EAAAA,KAAOD,KAAKC,EAAE,CAAA;AACtF,MAAA,OAAOqC,iBAAAA,CACLN,sBAAKC,IAAAA,CAAK,IAAA,CAAKnB,MAAMO,eAAAA,CAAgBa,QAAAA,IAAYE,cAAAA,CAAejC,QAAQ,GACxE6B,qBAAAA,CAAKC,IAAAA,CAAK,KAAKnB,KAAAA,CAAMS,qBAAAA,CAAsBW,UAAQ,EAAIE,cAAAA,CAAenC,EAAE,CAAA,CAAA;AAE5E,IAAA,CAAA,CAAA,CAAA;AAEF,IAAA,OAAON,KAAAA,CAAMI,GAAAA,CAAI,CAACC,IAAAA,MAAU;MAAE,GAAGA,IAAAA;AAAME,MAAAA,QAAAA,EAAUF,IAAAA,CAAKC;KAAG,CAAA,CAAA;AAC3D,EAAA;AAEA,EAAA,MAAMG,SAAST,KAAAA,EAA6B;AAC1C,IAAA,MAAM,KAAKsB,IAAAA,EAAI;AAEf,IAAA,MAAMS,OAAAA,CAAQC,GAAAA,CACZhC,KAAAA,CAAMI,GAAAA,CAAI,CAACC,IAAAA,KACTsC,iBAAAA,CACEN,qBAAAA,CAAKC,IAAAA,CAAK,IAAA,CAAKnB,KAAAA,CAAMS,qBAAAA,CAAsBW,QAAAA,EAAQ,EAAIlC,IAAAA,CAAKE,QAAQ,CAAA,EACpE8B,qBAAAA,CAAKC,IAAAA,CAAK,IAAA,CAAKnB,KAAAA,CAAMO,eAAAA,CAAgBa,QAAAA,EAAQ,EAAIlC,IAAAA,CAAKG,QAAQ,CAAA,CAAA,CAAA,CAAA;AAIpE,IAAA,OAAOR,KAAAA,CAAMI,GAAAA,CAAI,CAACC,IAAAA,MAAU;MAAE,GAAGA,IAAAA;AAAMC,MAAAA,EAAAA,EAAID,IAAAA,CAAKE;KAAS,CAAA,CAAA;AAC3D,EAAA;AAEA,EAAA,MAAgB6B,YAAY/B,IAAAA,EAAgB;AAC1C,IAAA,MAAMuC,IAAAA,GAAOC,iBAAAA,CAAOC,UAAAA,CAAW,QAAA,CAAA;AAC/B,IAAA,MAAMC,mBAAAA,CAASC,mBAAAA,CAAiB3C,IAAAA,CAAAA,EAAOuC,IAAAA,CAAAA;AACvC,IAAA,OAAOA,IAAAA,CAAKK,OAAO,KAAA,CAAA;AACrB,EAAA;EAEApC,cAAAA,GAAiB;AACf,IAAA,OAAO;MAAEM,KAAAA,EAAO+B,qBAAAA,CAAY,KAAK/B,KAAK;AAAE,KAAA;AAC1C,EAAA;AAEAL,EAAAA,YAAAA,CAAaC,QAAAA,EAAkD;AAC7DC,IAAAA,MAAAA,CAAOC,MAAAA,CAAO,MAAMF,QAAAA,CAAAA;AACtB,EAAA;AACF","file":"storage.cjs","sourcesContent":["/**\n * Copyright 2025 © BeeAI a Series of LF Projects, LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { PathLike } from \"fs\";\nimport * as crypto from \"node:crypto\";\nimport { pipeline } from \"node:stream/promises\";\nimport fs, { createReadStream } from \"node:fs\";\nimport { copyFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Cache } from \"@/cache/decoratorCache.js\";\nimport { Serializable } from \"@/internals/serializable.js\";\nimport { shallowCopy } from \"@/serializer/utils.js\";\n\nexport interface PythonFile {\n  id: string;\n  pythonId: string;\n  filename: string;\n}\n\nexport interface PythonUploadFile {\n  id: string;\n  filename: string;\n}\n\nexport interface PythonDownloadFile {\n  id?: string;\n  filename: string;\n  pythonId: string;\n}\n\nexport abstract class PythonStorage extends Serializable {\n  /**\n   * List all files that code interpreter can use.\n   */\n  abstract list(): Promise<PythonFile[]>;\n\n  /**\n   * Prepare subset of available files to code interpreter.\n   */\n  abstract upload(files: PythonUploadFile[]): Promise<PythonFile[]>;\n\n  /**\n   * Process updated/modified/deleted files from code interpreter response.\n   */\n  abstract download(files: PythonDownloadFile[]): Promise<PythonFile[]>;\n}\n\nexport class TemporaryStorage extends PythonStorage {\n  protected files: PythonFile[] = [];\n\n  async list() {\n    return this.files.slice();\n  }\n\n  async upload(files: PythonUploadFile[]): Promise<PythonFile[]> {\n    return files.map((file) => ({\n      id: file.id,\n      pythonId: file.id,\n      filename: file.filename,\n    }));\n  }\n\n  async download(files: PythonDownloadFile[]) {\n    this.files = [\n      ...this.files.filter((file) => files.every((f) => f.filename !== file.filename)),\n      ...files.map((file) => ({ id: file.pythonId, ...file })),\n    ];\n    return this.files.slice();\n  }\n\n  createSnapshot() {\n    return { files: this.files.slice() };\n  }\n\n  loadSnapshot(snapshot: ReturnType<typeof this.createSnapshot>) {\n    Object.assign(this, snapshot);\n  }\n}\n\ninterface Input {\n  localWorkingDir: PathLike;\n  interpreterWorkingDir: PathLike;\n  ignoredFiles?: Set<string>;\n}\n\nexport class LocalPythonStorage extends PythonStorage {\n  protected readonly input: Required<Input>;\n\n  constructor(input: Input) {\n    super();\n    this.input = {\n      ...input,\n      ignoredFiles: input?.ignoredFiles ?? new Set([\".gitkeep\"]),\n    };\n  }\n\n  @Cache()\n  protected async init() {\n    await fs.promises.mkdir(this.input.localWorkingDir, { recursive: true });\n    await fs.promises.mkdir(this.input.interpreterWorkingDir, { recursive: true });\n  }\n\n  async list(): Promise<PythonFile[]> {\n    await this.init();\n\n    const files = await fs.promises.readdir(this.input.localWorkingDir, {\n      withFileTypes: true,\n      recursive: false,\n    });\n    return Promise.all(\n      files\n        .filter((file) => file.isFile() && !this.input.ignoredFiles.has(file.name))\n        .map(async (file) => {\n          const pythonId = await this.computeHash(\n            path.join(this.input.localWorkingDir.toString(), file.name),\n          );\n\n          return {\n            id: pythonId,\n            filename: file.name,\n            pythonId,\n          };\n        }),\n    );\n  }\n\n  async upload(files: PythonUploadFile[]): Promise<PythonFile[]> {\n    await this.init();\n\n    const fileList = await this.list();\n\n    await Promise.all(\n      files.map((file) => {\n        const filesystemFile = fileList.find((filesystemFile) => filesystemFile.id === file.id)!;\n        return copyFile(\n          path.join(this.input.localWorkingDir.toString(), filesystemFile.filename),\n          path.join(this.input.interpreterWorkingDir.toString(), filesystemFile.id),\n        );\n      }),\n    );\n    return files.map((file) => ({ ...file, pythonId: file.id }));\n  }\n\n  async download(files: PythonDownloadFile[]) {\n    await this.init();\n\n    await Promise.all(\n      files.map((file) =>\n        copyFile(\n          path.join(this.input.interpreterWorkingDir.toString(), file.pythonId),\n          path.join(this.input.localWorkingDir.toString(), file.filename),\n        ),\n      ),\n    );\n    return files.map((file) => ({ ...file, id: file.pythonId }));\n  }\n\n  protected async computeHash(file: PathLike) {\n    const hash = crypto.createHash(\"sha256\");\n    await pipeline(createReadStream(file), hash);\n    return hash.digest(\"hex\");\n  }\n\n  createSnapshot() {\n    return { input: shallowCopy(this.input) };\n  }\n\n  loadSnapshot(snapshot: ReturnType<typeof this.createSnapshot>) {\n    Object.assign(this, snapshot);\n  }\n}\n"]}