@ecmaos/kernel 0.10.3 → 0.10.4

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.
Binary file
@@ -1,6 +1,6 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
- import { c as chalk, s as semver, p as path } from "./kernel-C3PA_-lt.js";
3
+ import { c as chalk, s as semver, p as path } from "./kernel-M80zlY8S.js";
4
4
  const install = /* @__PURE__ */ __name(async ({ kernel, shell, terminal, args }) => {
5
5
  const [packageArg, registryArg, reinstallArg] = args;
6
6
  if (!packageArg) {
@@ -118,4 +118,4 @@ const install = /* @__PURE__ */ __name(async ({ kernel, shell, terminal, args })
118
118
  export {
119
119
  install as default
120
120
  };
121
- //# sourceMappingURL=install-C78wAcrD.js.map
121
+ //# sourceMappingURL=install-Bs2UAdQv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install-C78wAcrD.js","sources":["../src/tree/lib/commands/install.ts"],"sourcesContent":["import chalk from 'chalk'\nimport path from 'path'\nimport semver from 'semver'\n\nimport { CommandArgs } from './'\n\nconst install = async ({ kernel, shell, terminal, args }: CommandArgs) => {\n const [packageArg, registryArg, reinstallArg] = args as [string, string, boolean]\n if (!packageArg) {\n terminal.writeln(chalk.red('Usage: install <package-name>[@version]'))\n return 1\n }\n\n const spec = packageArg.match(/(@[^/]+\\/[^@]+|[^@]+)(?:@([^/]+))?/)\n if (!spec) {\n terminal.writeln(chalk.red('Invalid package name format'))\n return 1\n }\n\n const registry = registryArg || shell.env.get('REGISTRY') || 'https://registry.npmjs.org'\n const packageName = spec[1]?.replace('vnpm:', '')\n let version = spec[2] || 'latest'\n\n if (!packageName) {\n terminal.writeln(chalk.red('Invalid package name format'))\n return 1\n }\n\n const url = `${registry}/${packageName}`\n const packageInfo = await globalThis.fetch(url)\n const data = await packageInfo.json()\n\n if (!data.versions || !data['dist-tags']) {\n terminal.writeln(chalk.red(`No versions found for ${packageName}`))\n return 1\n }\n\n if (version === 'latest') version = data['dist-tags'].latest\n else version = semver.maxSatisfying(Object.keys(data.versions), version) || version\n\n if (reinstallArg) {\n try {\n const pkgData = JSON.parse(await kernel.filesystem.fs.readFile(path.join('/usr/lib', packageName, version, 'package.json'), 'utf-8'))\n for (const bin in pkgData.bin) await kernel.filesystem.fs.unlink(path.join('/usr/bin', bin))\n await kernel.filesystem.fs.rm(path.join('/usr/lib', packageName, version), { recursive: true, force: true })\n } catch {}\n }\n\n const packagePath = path.join('/usr/lib', packageName, version, 'package.json')\n if (await kernel.filesystem.fs.exists(packagePath)) {\n terminal.writeln(chalk.green(`${packageName} v${version} is already installed`))\n return 0\n }\n\n terminal.writeln(`Installing ${data.name} v${version} from ${registry}...`)\n\n const tarballUrl = data.versions[version]?.dist?.tarball\n const tarballChecksum = data.versions[version]?.dist?.shasum?.toLowerCase()\n if (!tarballUrl || !tarballChecksum) {\n terminal.writeln(chalk.red(`No tarball URL or checksum found for ${packageName} v${version}`))\n return 1\n }\n\n const tarball = await globalThis.fetch(tarballUrl)\n const arrayBuffer = await tarball.arrayBuffer()\n const hashBuffer = await crypto.subtle.digest('SHA-1', arrayBuffer)\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n const downloadChecksum = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')\n\n if (downloadChecksum !== tarballChecksum) {\n terminal.writeln(chalk.red(`Checksum verification failed. Expected ${tarballChecksum} but got ${downloadChecksum}`))\n return 1\n }\n\n const tarballFilename = `${data.name.replace('@', '').replace('/', '-')}-${version}.tar.gz`\n await kernel.filesystem.fs.writeFile(`/tmp/${tarballFilename}`, new Uint8Array(arrayBuffer))\n\n // TODO: Support user packages installed to user's home?\n const extractPath = `/usr/lib/${data.name}/${version}`\n\n await kernel.filesystem.fs.mkdir(extractPath, { mode: 0o755, recursive: true })\n await kernel.filesystem.extractTarball(`/tmp/${tarballFilename}`, extractPath)\n await kernel.filesystem.fs.unlink(`/tmp/${tarballFilename}`)\n terminal.writeln(chalk.green(`Installed ${data.name} v${version} to ${extractPath}`))\n\n const packageData = await kernel.filesystem.fs.readFile(packagePath, 'utf-8')\n const packageJson = JSON.parse(packageData)\n\n try { // execute preinstall script\n if (packageJson.scripts?.['ecmaos:preinstall']) await shell.execute(packageJson.scripts['ecmaos:preinstall'])\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to execute preinstall script for ${packageName}@${version}: ${error}`))\n return 1\n }\n\n try { // link any bins\n if (packageJson.bin) {\n if (typeof packageJson.bin === 'string') {\n const binPath = path.join('/usr/lib', packageName, version, packageJson.bin)\n if (!await kernel.filesystem.fs.exists(binPath)) {\n terminal.writeln(chalk.red(`${binPath} does not exist`))\n return 1\n }\n\n await kernel.filesystem.fs.symlink(binPath, path.join('/usr/bin', packageJson.name))\n terminal.writeln(chalk.blue(`Linked ${packageJson.name} to ${path.join('/usr/bin', packageJson.name)}`))\n } else if (typeof packageJson.bin === 'object') {\n for (const bin in packageJson.bin) {\n const binPath = path.join('/usr/lib', packageName, version, packageJson.bin[bin])\n if (!await kernel.filesystem.fs.exists(binPath)) {\n terminal.writeln(chalk.red(`${binPath} does not exist`))\n return 1\n }\n\n await kernel.filesystem.fs.symlink(binPath, path.join('/usr/bin', bin))\n terminal.writeln(chalk.blue(`Linked ${bin} to ${path.join('/usr/bin', bin)}`))\n }\n }\n }\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to link bins for ${packageName}@${version}: ${error}`))\n }\n\n try { // install dependencies\n if (packageJson.dependencies) {\n for (const dependency in packageJson.dependencies) {\n const packageSpec = `${dependency}${packageJson.dependencies[dependency] ? `@${packageJson.dependencies[dependency]}` : ''}`\n await install({ kernel, shell, terminal, args: [packageSpec, registryArg] })\n }\n }\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to install dependencies for ${packageName}@${version}: ${error}`))\n return 1\n }\n\n try { // execute postinstall script\n if (packageJson.scripts?.['ecmaos:postinstall']) await shell.execute(packageJson.scripts['ecmaos:postinstall'])\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to execute postinstall script for ${packageName}@${version}: ${error}`))\n return 1\n }\n}\n\nexport default install\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install-Bs2UAdQv.js","sources":["../src/tree/lib/commands/install.ts"],"sourcesContent":["import chalk from 'chalk'\nimport path from 'path'\nimport semver from 'semver'\n\nimport { CommandArgs } from './'\n\nconst install = async ({ kernel, shell, terminal, args }: CommandArgs) => {\n const [packageArg, registryArg, reinstallArg] = args as [string, string, boolean]\n if (!packageArg) {\n terminal.writeln(chalk.red('Usage: install <package-name>[@version]'))\n return 1\n }\n\n const spec = packageArg.match(/(@[^/]+\\/[^@]+|[^@]+)(?:@([^/]+))?/)\n if (!spec) {\n terminal.writeln(chalk.red('Invalid package name format'))\n return 1\n }\n\n const registry = registryArg || shell.env.get('REGISTRY') || 'https://registry.npmjs.org'\n const packageName = spec[1]?.replace('vnpm:', '')\n let version = spec[2] || 'latest'\n\n if (!packageName) {\n terminal.writeln(chalk.red('Invalid package name format'))\n return 1\n }\n\n const url = `${registry}/${packageName}`\n const packageInfo = await globalThis.fetch(url)\n const data = await packageInfo.json()\n\n if (!data.versions || !data['dist-tags']) {\n terminal.writeln(chalk.red(`No versions found for ${packageName}`))\n return 1\n }\n\n if (version === 'latest') version = data['dist-tags'].latest\n else version = semver.maxSatisfying(Object.keys(data.versions), version) || version\n\n if (reinstallArg) {\n try {\n const pkgData = JSON.parse(await kernel.filesystem.fs.readFile(path.join('/usr/lib', packageName, version, 'package.json'), 'utf-8'))\n for (const bin in pkgData.bin) await kernel.filesystem.fs.unlink(path.join('/usr/bin', bin))\n await kernel.filesystem.fs.rm(path.join('/usr/lib', packageName, version), { recursive: true, force: true })\n } catch {}\n }\n\n const packagePath = path.join('/usr/lib', packageName, version, 'package.json')\n if (await kernel.filesystem.fs.exists(packagePath)) {\n terminal.writeln(chalk.green(`${packageName} v${version} is already installed`))\n return 0\n }\n\n terminal.writeln(`Installing ${data.name} v${version} from ${registry}...`)\n\n const tarballUrl = data.versions[version]?.dist?.tarball\n const tarballChecksum = data.versions[version]?.dist?.shasum?.toLowerCase()\n if (!tarballUrl || !tarballChecksum) {\n terminal.writeln(chalk.red(`No tarball URL or checksum found for ${packageName} v${version}`))\n return 1\n }\n\n const tarball = await globalThis.fetch(tarballUrl)\n const arrayBuffer = await tarball.arrayBuffer()\n const hashBuffer = await crypto.subtle.digest('SHA-1', arrayBuffer)\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n const downloadChecksum = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')\n\n if (downloadChecksum !== tarballChecksum) {\n terminal.writeln(chalk.red(`Checksum verification failed. Expected ${tarballChecksum} but got ${downloadChecksum}`))\n return 1\n }\n\n const tarballFilename = `${data.name.replace('@', '').replace('/', '-')}-${version}.tar.gz`\n await kernel.filesystem.fs.writeFile(`/tmp/${tarballFilename}`, new Uint8Array(arrayBuffer))\n\n // TODO: Support user packages installed to user's home?\n const extractPath = `/usr/lib/${data.name}/${version}`\n\n await kernel.filesystem.fs.mkdir(extractPath, { mode: 0o755, recursive: true })\n await kernel.filesystem.extractTarball(`/tmp/${tarballFilename}`, extractPath)\n await kernel.filesystem.fs.unlink(`/tmp/${tarballFilename}`)\n terminal.writeln(chalk.green(`Installed ${data.name} v${version} to ${extractPath}`))\n\n const packageData = await kernel.filesystem.fs.readFile(packagePath, 'utf-8')\n const packageJson = JSON.parse(packageData)\n\n try { // execute preinstall script\n if (packageJson.scripts?.['ecmaos:preinstall']) await shell.execute(packageJson.scripts['ecmaos:preinstall'])\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to execute preinstall script for ${packageName}@${version}: ${error}`))\n return 1\n }\n\n try { // link any bins\n if (packageJson.bin) {\n if (typeof packageJson.bin === 'string') {\n const binPath = path.join('/usr/lib', packageName, version, packageJson.bin)\n if (!await kernel.filesystem.fs.exists(binPath)) {\n terminal.writeln(chalk.red(`${binPath} does not exist`))\n return 1\n }\n\n await kernel.filesystem.fs.symlink(binPath, path.join('/usr/bin', packageJson.name))\n terminal.writeln(chalk.blue(`Linked ${packageJson.name} to ${path.join('/usr/bin', packageJson.name)}`))\n } else if (typeof packageJson.bin === 'object') {\n for (const bin in packageJson.bin) {\n const binPath = path.join('/usr/lib', packageName, version, packageJson.bin[bin])\n if (!await kernel.filesystem.fs.exists(binPath)) {\n terminal.writeln(chalk.red(`${binPath} does not exist`))\n return 1\n }\n\n await kernel.filesystem.fs.symlink(binPath, path.join('/usr/bin', bin))\n terminal.writeln(chalk.blue(`Linked ${bin} to ${path.join('/usr/bin', bin)}`))\n }\n }\n }\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to link bins for ${packageName}@${version}: ${error}`))\n }\n\n try { // install dependencies\n if (packageJson.dependencies) {\n for (const dependency in packageJson.dependencies) {\n const packageSpec = `${dependency}${packageJson.dependencies[dependency] ? `@${packageJson.dependencies[dependency]}` : ''}`\n await install({ kernel, shell, terminal, args: [packageSpec, registryArg] })\n }\n }\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to install dependencies for ${packageName}@${version}: ${error}`))\n return 1\n }\n\n try { // execute postinstall script\n if (packageJson.scripts?.['ecmaos:postinstall']) await shell.execute(packageJson.scripts['ecmaos:postinstall'])\n } catch (error) {\n terminal.writeln(chalk.red(`Failed to execute postinstall script for ${packageName}@${version}: ${error}`))\n return 1\n }\n}\n\nexport default install\n"],"names":[],"mappings":"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"}
@@ -59315,11 +59315,16 @@ function createCommand$1e(kernel, shell, terminal) {
59315
59315
  }, "getModeString");
59316
59316
  const getTimestampString = /* @__PURE__ */ __name((timestamp2) => {
59317
59317
  const diff = ((/* @__PURE__ */ new Date()).getTime() - timestamp2.getTime()) / 1e3;
59318
- if (diff < 24 * 60 * 60) return chalk$1.green(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59319
- else if (diff < 7 * 24 * 60 * 60) return chalk$1.yellow(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59320
- else if (diff < 30 * 24 * 60 * 60) return chalk$1.blue(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59321
- else if (diff < 365 * 24 * 60 * 60) return chalk$1.magenta(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59322
- else return chalk$1.gray(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59318
+ if (diff < 24 * 60 * 60)
59319
+ return chalk$1.red(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59320
+ else if (diff < 7 * 24 * 60 * 60)
59321
+ return chalk$1.yellow(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59322
+ else if (diff < 30 * 24 * 60 * 60)
59323
+ return chalk$1.green(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59324
+ else if (diff < 365 * 24 * 60 * 60)
59325
+ return chalk$1.cyan(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59326
+ else
59327
+ return chalk$1.blue(timestamp2.toISOString().slice(0, 19).replace("T", " "));
59323
59328
  }, "getTimestampString");
59324
59329
  const getOwnerString = /* @__PURE__ */ __name((stats) => {
59325
59330
  const owner = kernel.users.all.get(Number(stats.uid)) || kernel.users.all.get(0);
@@ -81872,7 +81877,7 @@ function createCommand$1b(kernel, shell, terminal) {
81872
81877
  if (!clientConfig.accessToken) {
81873
81878
  throw new Error("client configuration must include accessToken");
81874
81879
  }
81875
- const dropboxModule = await import("./index-9M8pZtzV.js");
81880
+ const dropboxModule = await import("./index-DXuNSaKe.js");
81876
81881
  const DropboxClient = dropboxModule.Dropbox;
81877
81882
  const client = new DropboxClient(clientConfig);
81878
81883
  const cacheTTL = mountOptions.cacheTTL ? parseInt(mountOptions.cacheTTL, 10) : void 0;
@@ -82212,7 +82217,7 @@ Mount summary: ${successCount} succeeded, ${failCount} failed`);
82212
82217
  await writelnStderr(process2, terminal, chalk$1.red("mount: client configuration must include accessToken"));
82213
82218
  return 1;
82214
82219
  }
82215
- const dropboxModule = await import("./index-9M8pZtzV.js");
82220
+ const dropboxModule = await import("./index-DXuNSaKe.js");
82216
82221
  const DropboxClient = dropboxModule.Dropbox;
82217
82222
  const client = new DropboxClient(clientConfig);
82218
82223
  const cacheTTL = mountOptions.cacheTTL ? parseInt(mountOptions.cacheTTL, 10) : void 0;
@@ -104664,7 +104669,7 @@ customElements.define("json-viewer", JsonViewer);
104664
104669
  function detectFileType(filePath) {
104665
104670
  const ext = path$2.extname(filePath).toLowerCase();
104666
104671
  if (ext === ".pdf") return "pdf";
104667
- const markdownExts = [".md", ".markdown", ".mdown", ".mkd", ".mkdn"];
104672
+ const markdownExts = [".md", ".markdown", ".mdown", ".mkd", ".mkdn", ".txt"];
104668
104673
  if (markdownExts.includes(ext)) return "markdown";
104669
104674
  const jsonExts = [".json", ".jsonl", ".jsonc", ".jsonld"];
104670
104675
  if (jsonExts.includes(ext)) return "json";
@@ -125306,7 +125311,7 @@ const TerminalCommands = /* @__PURE__ */ __name((kernel, shell, terminal) => {
125306
125311
  { name: "reinstall", type: Boolean, description: "Reinstall the package if it is already installed" }
125307
125312
  ],
125308
125313
  run: /* @__PURE__ */ __name(async (argv) => {
125309
- const { default: install } = await import("./install-C78wAcrD.js");
125314
+ const { default: install } = await import("./install-Bs2UAdQv.js");
125310
125315
  return await install({ kernel, shell, terminal, args: [argv.package, argv.registry, argv.reinstall] });
125311
125316
  }, "run")
125312
125317
  }),
@@ -125321,7 +125326,7 @@ const TerminalCommands = /* @__PURE__ */ __name((kernel, shell, terminal) => {
125321
125326
  { name: "package", type: String, typeLabel: "{underline package}", defaultOption: true, description: "The package name and optional version (e.g. package@1.0.0). If no version is specified, all versions will be uninstalled." }
125322
125327
  ],
125323
125328
  run: /* @__PURE__ */ __name(async (argv) => {
125324
- const { default: uninstall } = await import("./uninstall-qEkzPbxE.js");
125329
+ const { default: uninstall } = await import("./uninstall-_cO2Evrz.js");
125325
125330
  return await uninstall({ kernel, shell, terminal, args: [argv.package] });
125326
125331
  }, "run")
125327
125332
  }),
@@ -143103,7 +143108,7 @@ async function createWasiPreview2Bindings({
143103
143108
  const stdinReader = streams2.stdin.getReader();
143104
143109
  const stdoutWriter = streams2.stdout.getWriter();
143105
143110
  const stderrWriter = streams2.stderr.getWriter();
143106
- const jco = await import("./browser-BjnxDyrD.js");
143111
+ const jco = await import("./browser-CX2g4OIh.js");
143107
143112
  const { transpile: transpileComponent } = jco;
143108
143113
  const wasiCli = await Promise.resolve().then(() => cli);
143109
143114
  const wasiCliAny = wasiCli;
@@ -145292,7 +145297,7 @@ function parseFstabFile(content) {
145292
145297
  return entries2;
145293
145298
  }
145294
145299
  __name(parseFstabFile, "parseFstabFile");
145295
- const __vite_import_meta_env__ = { "AUTHOR": { "name": "Jay Mathis", "email": "code@mathis.network", "url": "https://github.com/mathiscode" }, "BASE_URL": "/", "DESCRIPTION": "ecmaOS: A web-native operating system and framework for web technologies", "DEV": false, "ECMAOS_APP_SHOW_DEFAULT_LOGIN": "true", "ECMAOS_AUTOLOGIN_PASSWORD": "root", "ECMAOS_AUTOLOGIN_USERNAME": "root", "ECMAOS_BOOT_DISABLE_ISSUES": "true", "ECMAOS_BOOT_DISABLE_LOGO_CONSOLE": "false", "ECMAOS_BOOT_DISABLE_LOGO_FIGLET": "false", "ECMAOS_BOOT_DISABLE_TIPS": "false", "ECMAOS_INITFS": "/initfs.tar.gz", "ECMAOS_KERNEL_INTERVALS_PROC": "1000", "ECMAOS_KERNEL_MODULES": "@ecmaos-modules/boilerplate@0.1.0", "ECMAOS_METAL_SOCKET": "ws://localhost:30445/socket", "ECMAOS_OPENTELEMETRY_ENDPOINT": "http://localhost:4318/v1/traces", "ECMAOS_PORT": "30443", "ECMAOS_RECOMMENDED_APPS": "@ecmaos-apps/code,@ecmaos-apps/edit,@ecmaos-apps/ai,@ecmaos-apps/webamp,@ecmaos-apps/news", "HOMEPAGE": "https://ecmaos.sh", "KNOWN_ISSUES": ["To disable known issues, type `touch /etc/noissues`", "It's best to stick to Chromium-based browsers for the most features", "Keyboard is broken on mobile; ecmaOS is not mobile-friendly at this time", "Don't expect any sort of POSIX compliance at this stage", "Most commands/devices are very basic implementations, not complete reproductions", "CTRL-C will return you to a prompt, but doesn't currently interrupt a process", "Lots of unfinished work; watch your step"], "MODE": "production", "NAME": "@ecmaos/kernel", "PROD": true, "REPOSITORY": "https://github.com/ecmaos/ecmaos", "SSR": false, "TIPS": ["To disable tips, type `touch /etc/notips`", "ecmaos.sh has no backend server; all data is stored and processed entirely in your browser", "If it ever fails to boot, check your logs, try clearing all data, try incognito mode, or try another browser", "You can switch between TTYs using CTRL+SHIFT+<0-9>", "You can run some devices that offer a CLI - e.g. '/dev/battery --help'", "Use the 'install' command to install packages - e.g. 'install @ecmaos-apps/news'", "You can install any NPM package - e.g. 'install jquery'", "You can use the 'mount' command to view and mount filesystems (/etc/fstab supported)", "Use the 'news' command to see the latest news about ecmaOS", "Type 'ls /bin' to see all built-in commands", "Type 'ls /usr/bin' to see all installed commands", "Type 'ls /dev' to see all available devices", "You can set your environment variables in ~/.env (try setting PROMPT to a PS1-like format)", "You can register and login with a passkey: 'passkey register' and 'passkey list'", "The 'man' command can be used to view the manual pages for packages: 'man @ecmaos/kernel'", "Try 'fetch /xkcd-os.sixel'"], "VERSION": "0.10.3", "XTERM_VERSION": "6.0.0", "ZENFS_VERSION": "2.4.4" };
145300
+ const __vite_import_meta_env__ = { "AUTHOR": { "name": "Jay Mathis", "email": "code@mathis.network", "url": "https://github.com/mathiscode" }, "BASE_URL": "/", "DESCRIPTION": "ecmaOS: A web-native operating system and framework for web technologies", "DEV": false, "ECMAOS_APP_SHOW_DEFAULT_LOGIN": "true", "ECMAOS_AUTOLOGIN_PASSWORD": "root", "ECMAOS_AUTOLOGIN_USERNAME": "root", "ECMAOS_BOOT_DISABLE_ISSUES": "true", "ECMAOS_BOOT_DISABLE_LOGO_CONSOLE": "false", "ECMAOS_BOOT_DISABLE_LOGO_FIGLET": "false", "ECMAOS_BOOT_DISABLE_TIPS": "false", "ECMAOS_INITFS": "/initfs.tar.gz", "ECMAOS_KERNEL_INTERVALS_PROC": "1000", "ECMAOS_KERNEL_MODULES": "@ecmaos-modules/boilerplate@0.1.0", "ECMAOS_METAL_SOCKET": "ws://localhost:30445/socket", "ECMAOS_OPENTELEMETRY_ENDPOINT": "http://localhost:4318/v1/traces", "ECMAOS_PORT": "30443", "ECMAOS_RECOMMENDED_APPS": "@ecmaos-apps/code,@ecmaos-apps/edit,@ecmaos-apps/ai,@ecmaos-apps/webamp,@ecmaos-apps/news", "HOMEPAGE": "https://ecmaos.sh", "KNOWN_ISSUES": ["To disable known issues, type `touch /etc/noissues`", "It's best to stick to Chromium-based browsers for the most features", "Keyboard is broken on mobile; ecmaOS is not mobile-friendly at this time", "Don't expect any sort of POSIX compliance at this stage", "Most commands/devices are very basic implementations, not complete reproductions", "CTRL-C will return you to a prompt, but doesn't currently interrupt a process", "Lots of unfinished work; watch your step"], "MODE": "production", "NAME": "@ecmaos/kernel", "PROD": true, "REPOSITORY": "https://github.com/ecmaos/ecmaos", "SSR": false, "TIPS": ["To disable tips, type `touch /etc/notips`", "ecmaos.sh has no backend server; all data is stored and processed entirely in your browser", "If it ever fails to boot, check your logs, try clearing all data, try incognito mode, or try another browser", "You can switch between TTYs using CTRL+SHIFT+<0-9>", "You can run some devices that offer a CLI - e.g. '/dev/battery --help'", "Use the 'install' command to install packages - e.g. 'install @ecmaos-apps/news'", "You can install any NPM package - e.g. 'install jquery'", "You can use the 'mount' command to view and mount filesystems (/etc/fstab supported)", "Use the 'news' command to see the latest news about ecmaOS", "Type 'ls /bin' to see all built-in commands", "Type 'ls /usr/bin' to see all installed commands", "Type 'ls /dev' to see all available devices", "You can set your environment variables in ~/.env (try setting PROMPT to a PS1-like format)", "You can register and login with a passkey: 'passkey register' and 'passkey list'", "The 'man' command can be used to view the manual pages for packages: 'man @ecmaos/kernel'", "Try 'fetch /xkcd-os.sixel'"], "VERSION": "0.10.4", "XTERM_VERSION": "6.0.0", "ZENFS_VERSION": "2.4.4" };
145296
145301
  var define_import_meta_env_AUTHOR_default = { name: "Jay Mathis", email: "code@mathis.network", url: "https://github.com/mathiscode" };
145297
145302
  var define_import_meta_env_KNOWN_ISSUES_default = ["To disable known issues, type `touch /etc/noissues`", "It's best to stick to Chromium-based browsers for the most features", "Keyboard is broken on mobile; ecmaOS is not mobile-friendly at this time", "Don't expect any sort of POSIX compliance at this stage", "Most commands/devices are very basic implementations, not complete reproductions", "CTRL-C will return you to a prompt, but doesn't currently interrupt a process", "Lots of unfinished work; watch your step"];
145298
145303
  var define_import_meta_env_TIPS_default = ["To disable tips, type `touch /etc/notips`", "ecmaos.sh has no backend server; all data is stored and processed entirely in your browser", "If it ever fails to boot, check your logs, try clearing all data, try incognito mode, or try another browser", "You can switch between TTYs using CTRL+SHIFT+<0-9>", "You can run some devices that offer a CLI - e.g. '/dev/battery --help'", "Use the 'install' command to install packages - e.g. 'install @ecmaos-apps/news'", "You can install any NPM package - e.g. 'install jquery'", "You can use the 'mount' command to view and mount filesystems (/etc/fstab supported)", "Use the 'news' command to see the latest news about ecmaOS", "Type 'ls /bin' to see all built-in commands", "Type 'ls /usr/bin' to see all installed commands", "Type 'ls /dev' to see all available devices", "You can set your environment variables in ~/.env (try setting PROMPT to a PS1-like format)", "You can register and login with a passkey: 'passkey register' and 'passkey list'", "The 'man' command can be used to view the manual pages for packages: 'man @ecmaos/kernel'", "Try 'fetch /xkcd-os.sixel'"];
@@ -145337,7 +145342,7 @@ const _Kernel = class _Kernel {
145337
145342
  /** Name of the kernel */
145338
145343
  __publicField(this, "name", "@ecmaos/kernel");
145339
145344
  /** Version string of the kernel */
145340
- __publicField(this, "version", "0.10.3");
145345
+ __publicField(this, "version", "0.10.4");
145341
145346
  /** Authentication and authorization service */
145342
145347
  __publicField(this, "auth");
145343
145348
  /** BIOS module providing low-level functionality */
@@ -145632,7 +145637,7 @@ const _Kernel = class _Kernel {
145632
145637
  ];
145633
145638
  this.terminal.writeln(chalk$2.red.bold(`🐉 ${this.i18n.ns.kernel("experimental")} 🐉`));
145634
145639
  this.terminal.writeln(
145635
- `${this.terminal.createSpecialLink("https://ecmaos.sh", "@ecmaos/kernel")}@${"0.10.3"}` + chalk$2.cyan(` [${dependencyLinks.map((link2) => link2.link).join(", ")}]`)
145640
+ `${this.terminal.createSpecialLink("https://ecmaos.sh", "@ecmaos/kernel")}@${"0.10.4"}` + chalk$2.cyan(` [${dependencyLinks.map((link2) => link2.link).join(", ")}]`)
145636
145641
  );
145637
145642
  this.terminal.writeln(`${this.i18n.ns.kernel("madeBy")} ${this.terminal.createSpecialLink(
145638
145643
  define_import_meta_env_AUTHOR_default?.url || "https://github.com/mathiscode",
@@ -145655,14 +145660,14 @@ const _Kernel = class _Kernel {
145655
145660
  if (logoFiglet && true) {
145656
145661
  console.log(`%c${logoFiglet}`, "color: green");
145657
145662
  console.log(`%c${"https://github.com/ecmaos/ecmaos"}`, "color: blue; text-decoration: underline; font-size: 16px");
145658
- this.log.info(`${"@ecmaos/kernel"} v${"0.10.3"}`);
145663
+ this.log.info(`${"@ecmaos/kernel"} v${"0.10.4"}`);
145659
145664
  }
145660
145665
  if (Notification?.permission === "default") Notification.requestPermission();
145661
145666
  if (Notification?.permission === "denied") this.log.warn(t2("kernel.permissionNotificationDenied", "Notification permission denied"));
145662
145667
  this.intervals.set("title-blink", () => {
145663
145668
  globalThis.document.title = globalThis.document.title.includes("_") ? "ecmaos# " : "ecmaos# _";
145664
145669
  }, 600);
145665
- this.dom.toast.success(`${"@ecmaos/kernel"} v${"0.10.3"}`);
145670
+ this.dom.toast.success(`${"@ecmaos/kernel"} v${"0.10.4"}`);
145666
145671
  this.dom.showTtyIndicator(this._activeTty);
145667
145672
  }
145668
145673
  if (await this.filesystem.fs.exists("/run")) {
@@ -145949,17 +145954,25 @@ const _Kernel = class _Kernel {
145949
145954
  const device = Array.from(this.devices.values()).find((d2) => d2.drivers?.some((driver) => driver.name === options.command.replace(/^\/dev\//, "")));
145950
145955
  if (device) return await this.executeDevice(device.device, options.args);
145951
145956
  }
145952
- const header = await this.readFileHeader(options.command);
145957
+ const header = await this.readFileHeader(options.command, options.shell);
145953
145958
  if (!header) return -1;
145954
145959
  let exitCode = -1;
145955
145960
  switch (header.type) {
145956
145961
  case "wasm":
145957
145962
  exitCode = await this.executeWasm(options);
145958
145963
  break;
145964
+ case "js":
145965
+ exitCode = await this.executeJavaScript(options);
145966
+ break;
145967
+ case "view":
145968
+ exitCode = await this.execute({
145969
+ ...options,
145970
+ command: "/bin/view",
145971
+ args: [options.command, ...options.args || []]
145972
+ });
145973
+ break;
145959
145974
  case "bin":
145960
145975
  switch (header.namespace) {
145961
- case "terminal":
145962
- // left for backward-compatibility
145963
145976
  case "command":
145964
145977
  if (!header.name) return -1;
145965
145978
  exitCode = await this.executeCommand({ ...options, command: header.name });
@@ -146164,7 +146177,7 @@ const _Kernel = class _Kernel {
146164
146177
  const shouldUnlisten = terminal && stdinIsTTY;
146165
146178
  let keyListener = null;
146166
146179
  try {
146167
- const wasmBytes = await this.shell.context.fs.promises.readFile(options.command);
146180
+ const wasmBytes = await options.shell.context.fs.promises.readFile(options.command);
146168
146181
  const needsWasi = await this.wasm.detectWasiRequirements(wasmBytes);
146169
146182
  let stdin2;
146170
146183
  let closeStdin = null;
@@ -146276,13 +146289,13 @@ const _Kernel = class _Kernel {
146276
146289
  * @returns Exit code of the script
146277
146290
  */
146278
146291
  async executeScript(options) {
146279
- const header = await this.readFileHeader(options.command);
146292
+ const header = await this.readFileHeader(options.command, options.shell);
146280
146293
  if (!header) return -1;
146281
146294
  if (header.type !== "bin" || header.namespace !== "script") {
146282
146295
  this.log.error(`File is not a script: ${options.command}`);
146283
146296
  return -1;
146284
146297
  }
146285
- const script = await this.shell.context.fs.promises.readFile(options.command, "utf-8");
146298
+ const script = await options.shell.context.fs.promises.readFile(options.command, "utf-8");
146286
146299
  if (script) {
146287
146300
  const terminalCmdBefore = options.terminal?.cmd || "";
146288
146301
  for (const line3 of script.split("\n")) {
@@ -146297,6 +146310,27 @@ const _Kernel = class _Kernel {
146297
146310
  } else this.log.error(`Script ${options.command} not found`);
146298
146311
  return -1;
146299
146312
  }
146313
+ /**
146314
+ * Executes a JavaScript file
146315
+ * @param options - Execution options containing JavaScript file path and shell
146316
+ * @returns Exit code of the JavaScript execution
146317
+ */
146318
+ async executeJavaScript(options) {
146319
+ try {
146320
+ const code2 = await options.shell.context.fs.promises.readFile(options.command, "utf-8");
146321
+ if (!code2) {
146322
+ this.log.error(`JavaScript file not found or empty: ${options.command}`);
146323
+ return -1;
146324
+ }
146325
+ const script = new Function(code2);
146326
+ script();
146327
+ return 0;
146328
+ } catch (error2) {
146329
+ this.log.error(`Failed to execute JavaScript file: ${error2}`);
146330
+ options.terminal?.writeln(chalk$2.red(error2.message));
146331
+ return -1;
146332
+ }
146333
+ }
146300
146334
  /**
146301
146335
  * Shows a system notification if permissions are granted
146302
146336
  * @param {string} title - Notification title
@@ -146328,9 +146362,10 @@ const _Kernel = class _Kernel {
146328
146362
  /**
146329
146363
  * Reads and parses a file header to determine its type
146330
146364
  * @param {string} filePath - Path to the file
146365
+ * @param {IShell} shell - Optional shell instance to use for filesystem operations
146331
146366
  * @returns {Promise<FileHeader|null>} Parsed header information or null if invalid
146332
146367
  */
146333
- async readFileHeader(filePath) {
146368
+ async readFileHeader(filePath, shell) {
146334
146369
  const parseHeader = /* @__PURE__ */ __name((header) => {
146335
146370
  if (!header.startsWith("#!")) return null;
146336
146371
  if (header.startsWith("#!ecmaos:")) {
@@ -146341,50 +146376,145 @@ const _Kernel = class _Kernel {
146341
146376
  if (header.startsWith("#!/usr/bin/env node")) return { type: "bin", namespace: "node", name: "node" };
146342
146377
  return null;
146343
146378
  }, "parseHeader");
146344
- return new Promise((resolve2, reject) => {
146345
- (async () => {
146346
- try {
146347
- if (!await this.shell.context.fs.promises.exists(filePath)) return resolve2(null);
146348
- const wasmMagicBytes = new Uint8Array([0, 97, 115, 109]);
146349
- try {
146350
- const handle = await this.shell.context.fs.promises.open(filePath, "r");
146351
- const buffer2 = new Uint8Array(4);
146352
- const { bytesRead } = await handle.read(buffer2, 0, 4, 0);
146353
- await handle.close();
146354
- if (bytesRead >= 4) {
146355
- const isWasm = wasmMagicBytes.every((byte, index2) => byte === buffer2[index2]);
146356
- if (isWasm) {
146357
- return resolve2({ type: "wasm" });
146358
- }
146359
- }
146360
- } catch {
146361
- const readable22 = this.shell.context.fs.createReadStream(filePath);
146362
- readable22.on("data", (chunk) => {
146363
- if (chunk.length >= 4) {
146364
- const firstBytes = new Uint8Array(chunk.buffer, chunk.byteOffset, 4);
146365
- const isWasm = wasmMagicBytes.every((byte, index2) => byte === firstBytes[index2]);
146366
- if (isWasm) {
146367
- readable22.destroy();
146368
- return resolve2({ type: "wasm" });
146379
+ const checkMagicBytes = /* @__PURE__ */ __name((buffer2, magicBytes, offset = 0) => {
146380
+ if (buffer2.length < offset + magicBytes.length) return false;
146381
+ return magicBytes.every((byte, index2) => byte === buffer2[offset + index2]);
146382
+ }, "checkMagicBytes");
146383
+ const checkMagicBytesPattern = /* @__PURE__ */ __name((buffer2, pattern2) => {
146384
+ if (pattern2.checker) {
146385
+ return pattern2.checker(buffer2);
146386
+ }
146387
+ return checkMagicBytes(buffer2, pattern2.bytes, pattern2.offset || 0);
146388
+ }, "checkMagicBytesPattern");
146389
+ const shellContext = shell?.context || this.shell.context;
146390
+ try {
146391
+ if (!await shellContext.fs.promises.exists(filePath)) return null;
146392
+ const magicBytesPatterns = [
146393
+ { bytes: new Uint8Array([0, 97, 115, 109]), type: "wasm" },
146394
+ // WebAssembly Binary
146395
+ { bytes: new Uint8Array([255, 216, 255]), type: "view" },
146396
+ // JPEG Image (Start of Image / SOI)
146397
+ { bytes: new Uint8Array([137, 80, 78, 71]), type: "view" },
146398
+ // PNG Image (ASCII ".PNG")
146399
+ { bytes: new Uint8Array([71, 73, 70, 56]), type: "view" },
146400
+ // GIF Image (ASCII "GIF8" - matches GIF87a and GIF89a)
146401
+ { bytes: new Uint8Array([71, 73, 70, 57]), type: "view" },
146402
+ // GIF Image (ASCII "GIF9" - likely a typo intended for GIF89a)
146403
+ { bytes: new Uint8Array([66, 77]), type: "view" },
146404
+ // BMP Image (ASCII "BM" - Windows Bitmap)
146405
+ { bytes: new Uint8Array([37, 80, 68, 70]), type: "view" },
146406
+ // PDF Document (ASCII "%PDF")
146407
+ { bytes: new Uint8Array([102, 76, 97, 67]), type: "view" },
146408
+ // FLAC Audio (ASCII "fLaC")
146409
+ { bytes: new Uint8Array([79, 103, 103, 83]), type: "view" },
146410
+ // Ogg Container (ASCII "OggS" - Vorbis, Theora, etc.)
146411
+ { bytes: new Uint8Array([255, 251]), type: "view" },
146412
+ // MP3 Audio (MPEG-1 Layer 3, No CRC)
146413
+ { bytes: new Uint8Array([255, 243]), type: "view" },
146414
+ // MP3 Audio (MPEG-2 Layer 3, No CRC - Lower sampling rates)
146415
+ { bytes: new Uint8Array([255, 242]), type: "view" },
146416
+ // MP3 Audio (MPEG-2 Layer 3, CRC Protected)
146417
+ { bytes: new Uint8Array([73, 68, 51]), type: "view" },
146418
+ // MP3 Metadata (ID3v2 container - often at start of MP3)
146419
+ { bytes: new Uint8Array([26, 69, 223, 163]), type: "view" },
146420
+ // Matroska / WebM (EBML Header ID)
146421
+ {
146422
+ bytes: new Uint8Array([82, 73, 70, 70]),
146423
+ // RIFF (ASCII "RIFF")
146424
+ type: "view",
146425
+ checker: /* @__PURE__ */ __name((buf) => {
146426
+ if (buf.length < 12) return false;
146427
+ if (!checkMagicBytes(buf, new Uint8Array([82, 73, 70, 70]))) return false;
146428
+ const avi = new Uint8Array([65, 86, 73, 32]);
146429
+ const webp = new Uint8Array([87, 69, 66, 80]);
146430
+ const wave = new Uint8Array([87, 65, 86, 69]);
146431
+ return checkMagicBytes(buf, avi, 8) || checkMagicBytes(buf, webp, 8) || checkMagicBytes(buf, wave, 8);
146432
+ }, "checker")
146433
+ },
146434
+ {
146435
+ bytes: new Uint8Array([0]),
146436
+ // MP4 Video (ASCII "MP4V")
146437
+ type: "view",
146438
+ checker: /* @__PURE__ */ __name((buf) => {
146439
+ if (buf.length < 8) return false;
146440
+ const ftyp = new Uint8Array([102, 116, 121, 112]);
146441
+ return checkMagicBytes(buf, ftyp, 4);
146442
+ }, "checker")
146443
+ }
146444
+ ];
146445
+ const maxMagicBytesLength = Math.max(12, ...magicBytesPatterns.map((p2) => (p2.offset || 0) + p2.bytes.length));
146446
+ let handle;
146447
+ let firstBytes = null;
146448
+ const checkExtensionType = /* @__PURE__ */ __name((filePath2) => {
146449
+ if (filePath2.endsWith(".js")) return "js";
146450
+ else if (filePath2.endsWith(".md")) return "view";
146451
+ else if (filePath2.endsWith(".json")) return "view";
146452
+ else if (filePath2.endsWith(".txt")) return "view";
146453
+ else return "application/octet-stream";
146454
+ }, "checkExtensionType");
146455
+ try {
146456
+ handle = await shellContext.fs.promises.open(filePath, "r");
146457
+ const buffer2 = new Uint8Array(maxMagicBytesLength);
146458
+ const result = await handle.read(buffer2, 0, maxMagicBytesLength, 0);
146459
+ if (result.bytesRead >= maxMagicBytesLength) firstBytes = buffer2;
146460
+ } catch {
146461
+ const readable2 = shellContext.fs.createReadStream(filePath);
146462
+ return new Promise((resolve2, reject) => {
146463
+ let firstChunk = null;
146464
+ readable2.on("data", (chunk) => {
146465
+ if (firstChunk === null) {
146466
+ firstChunk = chunk;
146467
+ if (chunk.length >= maxMagicBytesLength) {
146468
+ const chunkBytes = new Uint8Array(chunk.buffer, chunk.byteOffset, maxMagicBytesLength);
146469
+ for (const pattern2 of magicBytesPatterns) {
146470
+ if (checkMagicBytesPattern(chunkBytes, pattern2)) {
146471
+ readable2.destroy();
146472
+ return resolve2({ type: pattern2.type });
146473
+ }
146369
146474
  }
146370
146475
  }
146371
- resolve2(parseHeader(chunk.toString().split("\n")[0] || ""));
146372
- readable22.destroy();
146373
- });
146374
- readable22.on("error", (error2) => reject(error2));
146375
- readable22.on("close", () => resolve2(null));
146376
- return;
146377
- }
146378
- const readable2 = this.shell.context.fs.createReadStream(filePath);
146379
- readable2.on("data", (chunk) => resolve2(parseHeader(chunk.toString().split("\n")[0] || "")));
146476
+ const firstLine = chunk.toString().split("\n")[0] || "";
146477
+ const header = parseHeader(firstLine);
146478
+ if (header) {
146479
+ readable2.destroy();
146480
+ return resolve2(header);
146481
+ }
146482
+ readable2.destroy();
146483
+ const extensionType2 = checkExtensionType(filePath);
146484
+ return extensionType2 ? resolve2({ type: extensionType2 }) : resolve2(null);
146485
+ }
146486
+ });
146380
146487
  readable2.on("error", (error2) => reject(error2));
146381
- readable2.on("close", () => resolve2(null));
146382
- } catch (error2) {
146383
- this.log.error(error2);
146384
- reject(error2);
146488
+ readable2.on("close", () => {
146489
+ readable2.destroy();
146490
+ const extensionType2 = checkExtensionType(filePath);
146491
+ return extensionType2 ? resolve2({ type: extensionType2 }) : resolve2(null);
146492
+ });
146493
+ });
146494
+ }
146495
+ if (!handle) return null;
146496
+ if (firstBytes) {
146497
+ for (const pattern2 of magicBytesPatterns) {
146498
+ if (checkMagicBytesPattern(firstBytes, pattern2)) {
146499
+ await handle.close();
146500
+ return { type: pattern2.type };
146501
+ }
146385
146502
  }
146386
- })();
146387
- });
146503
+ }
146504
+ const firstLineBuffer = new Uint8Array(512);
146505
+ const firstLineResult = await handle.read(firstLineBuffer, 0, 512, 0);
146506
+ await handle.close();
146507
+ if (firstLineResult.bytesRead > 0) {
146508
+ const firstLine = new TextDecoder().decode(firstLineBuffer.slice(0, firstLineResult.bytesRead)).split("\n")[0] || "";
146509
+ const header = parseHeader(firstLine);
146510
+ if (header) return header;
146511
+ }
146512
+ const extensionType = checkExtensionType(filePath);
146513
+ return extensionType ? { type: extensionType } : null;
146514
+ } catch (error2) {
146515
+ this.log.error(error2);
146516
+ throw error2;
146517
+ }
146388
146518
  }
146389
146519
  /**
146390
146520
  * Reboots the kernel by performing a shutdown and page reload
@@ -146430,6 +146560,27 @@ const _Kernel = class _Kernel {
146430
146560
  switch (event) {
146431
146561
  case KernelEvents.PANIC:
146432
146562
  this.log.fatal("KernelPanic:", detail);
146563
+ if (this.telemetry.active) {
146564
+ const tracer = this.telemetry.getTracer("ecmaos.kernel", this.version);
146565
+ const panicSpan = tracer.startSpan("kernel.panic", {
146566
+ attributes: {
146567
+ "kernel.id": this.id,
146568
+ "kernel.state": this._state,
146569
+ "kernel.version": this.version
146570
+ }
146571
+ });
146572
+ const panicDetail = detail;
146573
+ if (panicDetail?.error) {
146574
+ panicSpan.recordException(panicDetail.error);
146575
+ panicSpan.setStatus({ code: 2, message: panicDetail.error.message });
146576
+ panicSpan.setAttribute("error.name", panicDetail.error.name);
146577
+ panicSpan.setAttribute("error.message", panicDetail.error.message);
146578
+ if (panicDetail.error.stack) {
146579
+ panicSpan.setAttribute("error.stack", panicDetail.error.stack);
146580
+ }
146581
+ }
146582
+ panicSpan.end();
146583
+ }
146433
146584
  break;
146434
146585
  }
146435
146586
  });
@@ -146606,7 +146757,7 @@ const _Kernel = class _Kernel {
146606
146757
  memory: "?",
146607
146758
  platform: navigator.userAgentData?.platform || navigator?.platform || navigator.userAgent,
146608
146759
  querystring: location.search,
146609
- version: `${"@ecmaos/kernel"} ${"0.10.3"}`,
146760
+ version: `${"@ecmaos/kernel"} ${"0.10.4"}`,
146610
146761
  language: navigator.language,
146611
146762
  host: location.host,
146612
146763
  userAgent: navigator.userAgent,
@@ -147140,4 +147291,4 @@ export {
147140
147291
  semver as s,
147141
147292
  types$1 as t
147142
147293
  };
147143
- //# sourceMappingURL=kernel-C3PA_-lt.js.map
147294
+ //# sourceMappingURL=kernel-M80zlY8S.js.map