@ecmaos/kernel 0.6.4 → 0.6.5

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.
@@ -25369,39 +25369,101 @@ const _Auth = class _Auth {
25369
25369
  // Create a new credential
25370
25370
  create: /* @__PURE__ */ __name(async (options) => {
25371
25371
  try {
25372
- return await navigator.credentials.create({ publicKey: options });
25372
+ if (!this.passkey.isSupported()) {
25373
+ throw new Error("WebAuthn is not supported in this browser");
25374
+ }
25375
+ if (!window.isSecureContext) {
25376
+ throw new Error("WebAuthn requires a secure context (HTTPS or localhost)");
25377
+ }
25378
+ const credential = await navigator.credentials.create({ publicKey: options });
25379
+ if (!credential || !(credential instanceof PublicKeyCredential)) {
25380
+ throw new Error("Failed to create credential");
25381
+ }
25382
+ return credential;
25373
25383
  } catch (error) {
25374
- console.error("Error creating credential:", error);
25375
- return null;
25384
+ if (error instanceof Error) {
25385
+ if (error.name === "NotAllowedError") {
25386
+ throw new Error("User cancelled or denied the operation");
25387
+ } else if (error.name === "InvalidStateError") {
25388
+ throw new Error("Credential already exists or operation is invalid");
25389
+ } else if (error.name === "NotSupportedError") {
25390
+ throw new Error("The operation is not supported");
25391
+ } else if (error.name === "SecurityError") {
25392
+ throw new Error("Security error: operation not allowed");
25393
+ }
25394
+ throw error;
25395
+ }
25396
+ throw new Error(`Error creating credential: ${String(error)}`);
25376
25397
  }
25377
25398
  }, "create"),
25378
25399
  // Get an existing credential
25379
25400
  get: /* @__PURE__ */ __name(async (options) => {
25380
25401
  try {
25381
- return await navigator.credentials.get({ publicKey: options });
25402
+ if (!this.passkey.isSupported()) {
25403
+ throw new Error("WebAuthn is not supported in this browser");
25404
+ }
25405
+ if (!window.isSecureContext) {
25406
+ throw new Error("WebAuthn requires a secure context (HTTPS or localhost)");
25407
+ }
25408
+ const credential = await navigator.credentials.get({ publicKey: options });
25409
+ if (!credential || !(credential instanceof PublicKeyCredential)) {
25410
+ return null;
25411
+ }
25412
+ return credential;
25382
25413
  } catch (error) {
25383
- console.error("Error getting credential:", error);
25384
- return null;
25414
+ if (error instanceof Error) {
25415
+ if (error.name === "NotAllowedError") {
25416
+ throw new Error("User cancelled or denied the operation");
25417
+ } else if (error.name === "InvalidStateError") {
25418
+ throw new Error("No matching credential found");
25419
+ } else if (error.name === "NotSupportedError") {
25420
+ throw new Error("The operation is not supported");
25421
+ } else if (error.name === "SecurityError") {
25422
+ throw new Error("Security error: operation not allowed");
25423
+ }
25424
+ throw error;
25425
+ }
25426
+ throw new Error(`Error getting credential: ${String(error)}`);
25385
25427
  }
25386
25428
  }, "get"),
25387
25429
  // Check if WebAuthn is supported in the current browser
25388
25430
  isSupported: /* @__PURE__ */ __name(() => {
25389
- return !!window.PublicKeyCredential;
25431
+ return !!window.PublicKeyCredential && !!navigator.credentials;
25390
25432
  }, "isSupported"),
25391
- // Register a new credential
25392
- register: /* @__PURE__ */ __name(async (credential) => {
25393
- await navigator.credentials.store(credential);
25394
- }, "register"),
25395
- // Full test of passkey functionality
25396
- fullTest: /* @__PURE__ */ __name(async () => {
25397
- const credential = await this.passkey.create({
25398
- challenge: new Uint8Array(32),
25399
- rp: { name: "Example RP" },
25400
- user: { id: new Uint8Array(16), name: "example@example.com", displayName: "Example User" },
25401
- pubKeyCredParams: [{ type: "public-key", alg: -7 }]
25402
- });
25403
- console.log(credential);
25404
- }, "fullTest")
25433
+ // Verify a passkey signature
25434
+ verify: /* @__PURE__ */ __name(async (credential, challenge, publicKey) => {
25435
+ try {
25436
+ const response = credential.response;
25437
+ const signature = response.signature;
25438
+ const clientDataJSON = response.clientDataJSON;
25439
+ const authenticatorData = response.authenticatorData;
25440
+ const clientData = JSON.parse(new TextDecoder().decode(clientDataJSON));
25441
+ const receivedChallenge = Uint8Array.from(atob(clientData.challenge), (c) => c.charCodeAt(0));
25442
+ const expectedChallenge = challenge;
25443
+ if (receivedChallenge.length !== expectedChallenge.length) {
25444
+ return false;
25445
+ }
25446
+ for (let i = 0; i < expectedChallenge.length; i++) {
25447
+ if (receivedChallenge[i] !== expectedChallenge[i]) {
25448
+ return false;
25449
+ }
25450
+ }
25451
+ const clientDataHash = await crypto.subtle.digest("SHA-256", clientDataJSON);
25452
+ const signedData = new Uint8Array(authenticatorData.byteLength + clientDataHash.byteLength);
25453
+ signedData.set(new Uint8Array(authenticatorData), 0);
25454
+ signedData.set(new Uint8Array(clientDataHash), authenticatorData.byteLength);
25455
+ const isValid2 = await crypto.subtle.verify(
25456
+ { name: "ECDSA", hash: "SHA-256" },
25457
+ publicKey,
25458
+ signature,
25459
+ signedData
25460
+ );
25461
+ return isValid2;
25462
+ } catch (error) {
25463
+ console.error("Error verifying passkey:", error);
25464
+ return false;
25465
+ }
25466
+ }, "verify")
25405
25467
  });
25406
25468
  __publicField(this, "password", {
25407
25469
  create: /* @__PURE__ */ __name(async (options) => {
@@ -28559,7 +28621,7 @@ const _Dom = class _Dom {
28559
28621
  }
28560
28622
  async topbar(show) {
28561
28623
  if (!this._topbar) return;
28562
- const { default: topbar } = await import("./topbar.min-BK1fdCNA.js").then((n) => n.t);
28624
+ const { default: topbar } = await import("./topbar.min-D7kPyIYf.js").then((n) => n.t);
28563
28625
  this._topbarShow = show ?? !this._topbarShow;
28564
28626
  if (this._topbarShow) topbar.show();
28565
28627
  else topbar.hide();
@@ -59629,7 +59691,7 @@ const _TerminalCommand = class _TerminalCommand {
59629
59691
  };
59630
59692
  __name(_TerminalCommand, "TerminalCommand");
59631
59693
  let TerminalCommand = _TerminalCommand;
59632
- function createCommand$h(kernel, shell, terminal) {
59694
+ function createCommand$i(kernel, shell, terminal) {
59633
59695
  return new TerminalCommand({
59634
59696
  command: "cat",
59635
59697
  description: "Concatenate files and print on the standard output",
@@ -59713,8 +59775,8 @@ function createCommand$h(kernel, shell, terminal) {
59713
59775
  }, "run")
59714
59776
  });
59715
59777
  }
59716
- __name(createCommand$h, "createCommand$h");
59717
- function createCommand$g(kernel, shell, terminal) {
59778
+ __name(createCommand$i, "createCommand$i");
59779
+ function createCommand$h(kernel, shell, terminal) {
59718
59780
  return new TerminalCommand({
59719
59781
  command: "cd",
59720
59782
  description: "Change the shell working directory",
@@ -59735,8 +59797,8 @@ function createCommand$g(kernel, shell, terminal) {
59735
59797
  }, "run")
59736
59798
  });
59737
59799
  }
59738
- __name(createCommand$g, "createCommand$g");
59739
- function createCommand$f(kernel, shell, terminal) {
59800
+ __name(createCommand$h, "createCommand$h");
59801
+ function createCommand$g(kernel, shell, terminal) {
59740
59802
  return new TerminalCommand({
59741
59803
  command: "chmod",
59742
59804
  description: "Change file mode bits",
@@ -59762,8 +59824,8 @@ function createCommand$f(kernel, shell, terminal) {
59762
59824
  }, "run")
59763
59825
  });
59764
59826
  }
59765
- __name(createCommand$f, "createCommand$f");
59766
- function createCommand$e(kernel, shell, terminal) {
59827
+ __name(createCommand$g, "createCommand$g");
59828
+ function createCommand$f(kernel, shell, terminal) {
59767
59829
  return new TerminalCommand({
59768
59830
  command: "cp",
59769
59831
  description: "Copy files",
@@ -59785,8 +59847,8 @@ function createCommand$e(kernel, shell, terminal) {
59785
59847
  }, "run")
59786
59848
  });
59787
59849
  }
59788
- __name(createCommand$e, "createCommand$e");
59789
- function createCommand$d(kernel, shell, terminal) {
59850
+ __name(createCommand$f, "createCommand$f");
59851
+ function createCommand$e(kernel, shell, terminal) {
59790
59852
  return new TerminalCommand({
59791
59853
  command: "echo",
59792
59854
  description: "Print arguments to the standard output",
@@ -59814,8 +59876,8 @@ function createCommand$d(kernel, shell, terminal) {
59814
59876
  }, "run")
59815
59877
  });
59816
59878
  }
59817
- __name(createCommand$d, "createCommand$d");
59818
- function createCommand$c(kernel, shell, terminal) {
59879
+ __name(createCommand$e, "createCommand$e");
59880
+ function createCommand$d(kernel, shell, terminal) {
59819
59881
  return new TerminalCommand({
59820
59882
  command: "ln",
59821
59883
  description: "Create links between files",
@@ -59907,7 +59969,7 @@ function createCommand$c(kernel, shell, terminal) {
59907
59969
  }, "run")
59908
59970
  });
59909
59971
  }
59910
- __name(createCommand$c, "createCommand$c");
59972
+ __name(createCommand$d, "createCommand$d");
59911
59973
  var humanFormat$2 = { exports: {} };
59912
59974
  var humanFormat$1 = humanFormat$2.exports;
59913
59975
  var hasRequiredHumanFormat;
@@ -60188,7 +60250,7 @@ function requireHumanFormat() {
60188
60250
  __name(requireHumanFormat, "requireHumanFormat");
60189
60251
  var humanFormatExports = requireHumanFormat();
60190
60252
  const humanFormat = /* @__PURE__ */ getDefaultExportFromCjs(humanFormatExports);
60191
- function createCommand$b(kernel, shell, terminal) {
60253
+ function createCommand$c(kernel, shell, terminal) {
60192
60254
  return new TerminalCommand({
60193
60255
  command: "ls",
60194
60256
  description: "List directory contents",
@@ -60353,8 +60415,8 @@ function createCommand$b(kernel, shell, terminal) {
60353
60415
  }, "run")
60354
60416
  });
60355
60417
  }
60356
- __name(createCommand$b, "createCommand$b");
60357
- function createCommand$a(kernel, shell, terminal) {
60418
+ __name(createCommand$c, "createCommand$c");
60419
+ function createCommand$b(kernel, shell, terminal) {
60358
60420
  return new TerminalCommand({
60359
60421
  command: "mkdir",
60360
60422
  description: "Create a directory",
@@ -60373,8 +60435,8 @@ function createCommand$a(kernel, shell, terminal) {
60373
60435
  }, "run")
60374
60436
  });
60375
60437
  }
60376
- __name(createCommand$a, "createCommand$a");
60377
- function createCommand$9(kernel, shell, terminal) {
60438
+ __name(createCommand$b, "createCommand$b");
60439
+ function createCommand$a(kernel, shell, terminal) {
60378
60440
  return new TerminalCommand({
60379
60441
  command: "mv",
60380
60442
  description: "Move or rename files",
@@ -60413,8 +60475,8 @@ function createCommand$9(kernel, shell, terminal) {
60413
60475
  }, "run")
60414
60476
  });
60415
60477
  }
60416
- __name(createCommand$9, "createCommand$9");
60417
- function createCommand$8(kernel, shell, terminal) {
60478
+ __name(createCommand$a, "createCommand$a");
60479
+ function createCommand$9(kernel, shell, terminal) {
60418
60480
  return new TerminalCommand({
60419
60481
  command: "pwd",
60420
60482
  description: "Print the shell working directory",
@@ -60430,8 +60492,8 @@ function createCommand$8(kernel, shell, terminal) {
60430
60492
  }, "run")
60431
60493
  });
60432
60494
  }
60433
- __name(createCommand$8, "createCommand$8");
60434
- function createCommand$7(kernel, shell, terminal) {
60495
+ __name(createCommand$9, "createCommand$9");
60496
+ function createCommand$8(kernel, shell, terminal) {
60435
60497
  return new TerminalCommand({
60436
60498
  command: "rm",
60437
60499
  description: "Remove files or directories",
@@ -60451,8 +60513,8 @@ function createCommand$7(kernel, shell, terminal) {
60451
60513
  }, "run")
60452
60514
  });
60453
60515
  }
60454
- __name(createCommand$7, "createCommand$7");
60455
- function createCommand$6(kernel, shell, terminal) {
60516
+ __name(createCommand$8, "createCommand$8");
60517
+ function createCommand$7(kernel, shell, terminal) {
60456
60518
  return new TerminalCommand({
60457
60519
  command: "rmdir",
60458
60520
  description: "Remove a directory",
@@ -60471,7 +60533,7 @@ function createCommand$6(kernel, shell, terminal) {
60471
60533
  }, "run")
60472
60534
  });
60473
60535
  }
60474
- __name(createCommand$6, "createCommand$6");
60536
+ __name(createCommand$7, "createCommand$7");
60475
60537
  const MAX_32_BITS = 4294967295;
60476
60538
  const MAX_16_BITS = 65535;
60477
60539
  const MAX_8_BITS = 255;
@@ -65266,7 +65328,7 @@ const table = {
65266
65328
  return mimeTypes;
65267
65329
  })();
65268
65330
  t(configure);
65269
- function createCommand$5(kernel, shell, terminal) {
65331
+ function createCommand$6(kernel, shell, terminal) {
65270
65332
  return new TerminalCommand({
65271
65333
  command: "stat",
65272
65334
  description: "Display information about a file or directory",
@@ -65296,8 +65358,8 @@ function createCommand$5(kernel, shell, terminal) {
65296
65358
  }, "run")
65297
65359
  });
65298
65360
  }
65299
- __name(createCommand$5, "createCommand$5");
65300
- function createCommand$4(kernel, shell, terminal) {
65361
+ __name(createCommand$6, "createCommand$6");
65362
+ function createCommand$5(kernel, shell, terminal) {
65301
65363
  return new TerminalCommand({
65302
65364
  command: "touch",
65303
65365
  description: "Create an empty file",
@@ -65316,8 +65378,8 @@ function createCommand$4(kernel, shell, terminal) {
65316
65378
  }, "run")
65317
65379
  });
65318
65380
  }
65319
- __name(createCommand$4, "createCommand$4");
65320
- function createCommand$3(kernel, shell, terminal) {
65381
+ __name(createCommand$5, "createCommand$5");
65382
+ function createCommand$4(kernel, shell, terminal) {
65321
65383
  return new TerminalCommand({
65322
65384
  command: "hex",
65323
65385
  description: "Display file contents in hexadecimal format",
@@ -65389,7 +65451,7 @@ function createCommand$3(kernel, shell, terminal) {
65389
65451
  }, "run")
65390
65452
  });
65391
65453
  }
65392
- __name(createCommand$3, "createCommand$3");
65454
+ __name(createCommand$4, "createCommand$4");
65393
65455
  const csi = "\x1B[";
65394
65456
  const ansi = {};
65395
65457
  ansi.style = {
@@ -65567,7 +65629,7 @@ ansi.erase = {
65567
65629
  return csi + (n || 0) + "K";
65568
65630
  }, "inLine")
65569
65631
  };
65570
- function createCommand$2(kernel, shell, terminal) {
65632
+ function createCommand$3(kernel, shell, terminal) {
65571
65633
  return new TerminalCommand({
65572
65634
  command: "less",
65573
65635
  description: "View file contents interactively",
@@ -65730,6 +65792,181 @@ function createCommand$2(kernel, shell, terminal) {
65730
65792
  }, "run")
65731
65793
  });
65732
65794
  }
65795
+ __name(createCommand$3, "createCommand$3");
65796
+ function createCommand$2(kernel, shell, terminal) {
65797
+ return new TerminalCommand({
65798
+ command: "passkey",
65799
+ description: "Manage passkey credentials for WebAuthn authentication",
65800
+ kernel,
65801
+ shell,
65802
+ terminal,
65803
+ options: [
65804
+ { name: "help", type: Boolean, description: kernel.i18n.t("Display help") },
65805
+ { name: "subcommand", type: String, defaultOption: true, description: "Subcommand: register, list, remove, remove-all" },
65806
+ { name: "name", type: String, description: "Name/description for the passkey (used with register)" },
65807
+ { name: "id", type: String, description: "Passkey ID to remove (used with remove)" }
65808
+ ],
65809
+ run: /* @__PURE__ */ __name(async (argv, process2) => {
65810
+ if (!process2) return 1;
65811
+ const currentUid = shell.credentials.uid;
65812
+ const user2 = kernel.users.get(currentUid);
65813
+ if (!user2) {
65814
+ await writelnStderr(process2, terminal, chalk$1.red("Error: Current user not found"));
65815
+ return 1;
65816
+ }
65817
+ const subcommand = argv.subcommand?.toLowerCase();
65818
+ if (!subcommand || subcommand === "help" || argv.help) {
65819
+ await writelnStdout(process2, terminal, "Usage: passkey <subcommand> [options]");
65820
+ await writelnStdout(process2, terminal, "");
65821
+ await writelnStdout(process2, terminal, "Subcommands:");
65822
+ await writelnStdout(process2, terminal, " register [--name <name>] Register a new passkey");
65823
+ await writelnStdout(process2, terminal, " list List all registered passkeys");
65824
+ await writelnStdout(process2, terminal, " remove --id <id> Remove a specific passkey");
65825
+ await writelnStdout(process2, terminal, " remove-all Remove all passkeys");
65826
+ return 0;
65827
+ }
65828
+ try {
65829
+ switch (subcommand) {
65830
+ case "register": {
65831
+ if (!kernel.auth.passkey.isSupported()) {
65832
+ await writelnStderr(process2, terminal, chalk$1.red("Error: WebAuthn is not supported in this browser"));
65833
+ return 1;
65834
+ }
65835
+ const name = argv.name || void 0;
65836
+ const username = user2.username;
65837
+ const userId = new TextEncoder().encode(username);
65838
+ const challenge = crypto.getRandomValues(new Uint8Array(32));
65839
+ const rpId = globalThis.location.hostname || "localhost";
65840
+ const createOptions = {
65841
+ challenge,
65842
+ rp: {
65843
+ name: kernel.name || "ecmaOS",
65844
+ id: rpId
65845
+ },
65846
+ user: {
65847
+ id: userId,
65848
+ name: username,
65849
+ displayName: username
65850
+ },
65851
+ pubKeyCredParams: [
65852
+ { type: "public-key", alg: -7 },
65853
+ { type: "public-key", alg: -257 }
65854
+ ],
65855
+ authenticatorSelection: {
65856
+ userVerification: "preferred"
65857
+ },
65858
+ timeout: 6e4
65859
+ };
65860
+ await writelnStdout(process2, terminal, chalk$1.yellow("Please interact with your authenticator to register a passkey..."));
65861
+ const credential = await kernel.auth.passkey.create(createOptions);
65862
+ if (!credential || !(credential instanceof PublicKeyCredential)) {
65863
+ await writelnStderr(process2, terminal, chalk$1.red("Error: Failed to create passkey. Registration cancelled or failed."));
65864
+ return 1;
65865
+ }
65866
+ const publicKeyCredential = credential;
65867
+ const response = publicKeyCredential.response;
65868
+ const credentialId = btoa(String.fromCharCode(...new Uint8Array(publicKeyCredential.rawId)));
65869
+ let publicKeyArray;
65870
+ try {
65871
+ if (typeof response.getPublicKey === "function") {
65872
+ try {
65873
+ const publicKeyCrypto = response.getPublicKey();
65874
+ if (publicKeyCrypto && publicKeyCrypto instanceof CryptoKey) {
65875
+ const publicKeyJwk = await crypto.subtle.exportKey("jwk", publicKeyCrypto);
65876
+ publicKeyArray = new TextEncoder().encode(JSON.stringify(publicKeyJwk));
65877
+ } else {
65878
+ throw new Error("getPublicKey() did not return a valid CryptoKey");
65879
+ }
65880
+ } catch (exportError) {
65881
+ await writelnStderr(process2, terminal, chalk$1.yellow(`Warning: Could not extract public key via getPublicKey(): ${exportError instanceof Error ? exportError.message : String(exportError)}. Using attestationObject instead.`));
65882
+ const attestationObject = response.attestationObject;
65883
+ publicKeyArray = new Uint8Array(attestationObject);
65884
+ }
65885
+ } else {
65886
+ const attestationObject = response.attestationObject;
65887
+ publicKeyArray = new Uint8Array(attestationObject);
65888
+ }
65889
+ } catch (error) {
65890
+ await writelnStderr(process2, terminal, chalk$1.red(`Error processing credential data: ${error instanceof Error ? error.message : String(error)}`));
65891
+ return 1;
65892
+ }
65893
+ const passkey = {
65894
+ id: crypto.randomUUID(),
65895
+ credentialId,
65896
+ publicKey: publicKeyArray,
65897
+ createdAt: Date.now(),
65898
+ name
65899
+ };
65900
+ await kernel.users.addPasskey(currentUid, passkey);
65901
+ await writelnStdout(process2, terminal, chalk$1.green(`Passkey registered successfully${name ? `: ${name}` : ""}`));
65902
+ await writelnStdout(process2, terminal, `Passkey ID: ${passkey.id}`);
65903
+ return 0;
65904
+ }
65905
+ case "list": {
65906
+ const passkeys = await kernel.users.getPasskeys(currentUid);
65907
+ if (passkeys.length === 0) {
65908
+ await writelnStdout(process2, terminal, "No passkeys registered for this user.");
65909
+ return 0;
65910
+ }
65911
+ await writelnStdout(process2, terminal, `Registered passkeys (${passkeys.length}):`);
65912
+ await writelnStdout(process2, terminal, "");
65913
+ for (const pk of passkeys) {
65914
+ const createdDate = new Date(pk.createdAt).toLocaleString();
65915
+ const lastUsedDate = pk.lastUsed ? new Date(pk.lastUsed).toLocaleString() : "Never";
65916
+ await writelnStdout(process2, terminal, ` ID: ${pk.id}`);
65917
+ if (pk.name) {
65918
+ await writelnStdout(process2, terminal, ` Name: ${pk.name}`);
65919
+ }
65920
+ await writelnStdout(process2, terminal, ` Created: ${createdDate}`);
65921
+ await writelnStdout(process2, terminal, ` Last used: ${lastUsedDate}`);
65922
+ await writelnStdout(process2, terminal, "");
65923
+ }
65924
+ return 0;
65925
+ }
65926
+ case "remove": {
65927
+ const id = argv.id;
65928
+ if (!id) {
65929
+ await writelnStderr(process2, terminal, chalk$1.red("Error: --id is required for remove command"));
65930
+ await writelnStdout(process2, terminal, "Usage: passkey remove --id <id>");
65931
+ return 1;
65932
+ }
65933
+ const passkeys = await kernel.users.getPasskeys(currentUid);
65934
+ const passkey = passkeys.find((pk) => pk.id === id);
65935
+ if (!passkey) {
65936
+ await writelnStderr(process2, terminal, chalk$1.red(`Error: Passkey with ID ${id} not found`));
65937
+ return 1;
65938
+ }
65939
+ await kernel.users.removePasskey(currentUid, id);
65940
+ await writelnStdout(process2, terminal, chalk$1.green(`Passkey removed successfully${passkey.name ? `: ${passkey.name}` : ""}`));
65941
+ return 0;
65942
+ }
65943
+ case "remove-all": {
65944
+ const passkeys = await kernel.users.getPasskeys(currentUid);
65945
+ if (passkeys.length === 0) {
65946
+ await writelnStdout(process2, terminal, "No passkeys to remove.");
65947
+ return 0;
65948
+ }
65949
+ await kernel.users.savePasskeys(currentUid, []);
65950
+ const passkeysPath = `${user2.home}/.passkeys`;
65951
+ try {
65952
+ await kernel.filesystem.fs.unlink(passkeysPath);
65953
+ } catch {
65954
+ }
65955
+ await writelnStdout(process2, terminal, chalk$1.green(`Removed ${passkeys.length} passkey(s)`));
65956
+ return 0;
65957
+ }
65958
+ default:
65959
+ await writelnStderr(process2, terminal, chalk$1.red(`Error: Unknown subcommand: ${subcommand}`));
65960
+ await writelnStdout(process2, terminal, 'Run "passkey help" for usage information');
65961
+ return 1;
65962
+ }
65963
+ } catch (error) {
65964
+ await writelnStderr(process2, terminal, chalk$1.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
65965
+ return 1;
65966
+ }
65967
+ }, "run")
65968
+ });
65969
+ }
65733
65970
  __name(createCommand$2, "createCommand$2");
65734
65971
  function parseSedExpression(expr) {
65735
65972
  expr = expr.trim();
@@ -66168,22 +66405,23 @@ function createCommand(kernel, shell, terminal) {
66168
66405
  __name(createCommand, "createCommand");
66169
66406
  function createAllCommands(kernel, shell, terminal) {
66170
66407
  return {
66171
- cat: createCommand$h(kernel, shell, terminal),
66172
- cd: createCommand$g(kernel, shell, terminal),
66173
- chmod: createCommand$f(kernel, shell, terminal),
66174
- cp: createCommand$e(kernel, shell, terminal),
66175
- echo: createCommand$d(kernel, shell, terminal),
66176
- ln: createCommand$c(kernel, shell, terminal),
66177
- ls: createCommand$b(kernel, shell, terminal),
66178
- mkdir: createCommand$a(kernel, shell, terminal),
66179
- mv: createCommand$9(kernel, shell, terminal),
66180
- pwd: createCommand$8(kernel, shell, terminal),
66181
- rm: createCommand$7(kernel, shell, terminal),
66182
- rmdir: createCommand$6(kernel, shell, terminal),
66183
- stat: createCommand$5(kernel, shell, terminal),
66184
- touch: createCommand$4(kernel, shell, terminal),
66185
- hex: createCommand$3(kernel, shell, terminal),
66186
- less: createCommand$2(kernel, shell, terminal),
66408
+ cat: createCommand$i(kernel, shell, terminal),
66409
+ cd: createCommand$h(kernel, shell, terminal),
66410
+ chmod: createCommand$g(kernel, shell, terminal),
66411
+ cp: createCommand$f(kernel, shell, terminal),
66412
+ echo: createCommand$e(kernel, shell, terminal),
66413
+ ln: createCommand$d(kernel, shell, terminal),
66414
+ ls: createCommand$c(kernel, shell, terminal),
66415
+ mkdir: createCommand$b(kernel, shell, terminal),
66416
+ mv: createCommand$a(kernel, shell, terminal),
66417
+ pwd: createCommand$9(kernel, shell, terminal),
66418
+ rm: createCommand$8(kernel, shell, terminal),
66419
+ rmdir: createCommand$7(kernel, shell, terminal),
66420
+ stat: createCommand$6(kernel, shell, terminal),
66421
+ touch: createCommand$5(kernel, shell, terminal),
66422
+ hex: createCommand$4(kernel, shell, terminal),
66423
+ less: createCommand$3(kernel, shell, terminal),
66424
+ passkey: createCommand$2(kernel, shell, terminal),
66187
66425
  sed: createCommand$1(kernel, shell, terminal),
66188
66426
  tee: createCommand(kernel, shell, terminal)
66189
66427
  };
@@ -66289,7 +66527,7 @@ const TerminalCommands = /* @__PURE__ */ __name((kernel, shell, terminal) => {
66289
66527
  { name: "reinstall", type: Boolean, description: "Reinstall the package if it is already installed" }
66290
66528
  ],
66291
66529
  run: /* @__PURE__ */ __name(async (argv) => {
66292
- const { default: install } = await import("./install-DIY-HQ9n.js");
66530
+ const { default: install } = await import("./install-CNseKaMB.js");
66293
66531
  return await install({ kernel, shell, terminal, args: [argv.package, argv.registry, argv.reinstall] });
66294
66532
  }, "run")
66295
66533
  }),
@@ -66304,7 +66542,7 @@ const TerminalCommands = /* @__PURE__ */ __name((kernel, shell, terminal) => {
66304
66542
  { 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." }
66305
66543
  ],
66306
66544
  run: /* @__PURE__ */ __name(async (argv) => {
66307
- const { default: uninstall } = await import("./uninstall-BOyXf2bF.js");
66545
+ const { default: uninstall } = await import("./uninstall-CamF7_kP.js");
66308
66546
  return await uninstall({ kernel, shell, terminal, args: [argv.package] });
66309
66547
  }, "run")
66310
66548
  }),
@@ -72157,10 +72395,27 @@ const _Users = class _Users {
72157
72395
  /**
72158
72396
  * Login a user
72159
72397
  */
72160
- async login(username, password) {
72398
+ async login(username, password, passkeyCredential) {
72161
72399
  const user2 = Array.from(this._users.values()).find((u) => u.username === username);
72162
- const hashedPassword = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(password.trim()));
72163
- if (!user2 || user2.password !== Array.from(new Uint8Array(hashedPassword)).map((b) => b.toString(16).padStart(2, "0")).join("")) throw new Error("Invalid username or password");
72400
+ if (!user2) throw new Error("Invalid username or password");
72401
+ if (passkeyCredential) {
72402
+ const passkeys = await this.getPasskeys(user2.uid);
72403
+ const credential = passkeyCredential;
72404
+ const credentialId = btoa(String.fromCharCode(...new Uint8Array(credential.rawId)));
72405
+ const matchingPasskey = passkeys.find((pk) => pk.credentialId === credentialId);
72406
+ if (!matchingPasskey) {
72407
+ throw new Error("Passkey not found for this user");
72408
+ }
72409
+ matchingPasskey.lastUsed = Date.now();
72410
+ await this.savePasskeys(user2.uid, passkeys);
72411
+ } else if (password) {
72412
+ const hashedPassword = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(password.trim()));
72413
+ if (user2.password !== Array.from(new Uint8Array(hashedPassword)).map((b) => b.toString(16).padStart(2, "0")).join("")) {
72414
+ throw new Error("Invalid username or password");
72415
+ }
72416
+ } else {
72417
+ throw new Error("Password or passkey required");
72418
+ }
72164
72419
  const cred = createCredentials({
72165
72420
  uid: user2.uid,
72166
72421
  gid: user2.gid,
@@ -72204,6 +72459,77 @@ const _Users = class _Users {
72204
72459
  throw new Error(`User with UID ${uid} not found`);
72205
72460
  }
72206
72461
  }
72462
+ /**
72463
+ * Get all passkeys for a user
72464
+ */
72465
+ async getPasskeys(uid) {
72466
+ const user2 = this._users.get(uid);
72467
+ if (!user2) return [];
72468
+ const passkeysPath = `${user2.home}/.passkeys`;
72469
+ try {
72470
+ const exists2 = await this._options.kernel.filesystem.fs.exists(passkeysPath);
72471
+ if (!exists2) return [];
72472
+ const content = await this._options.kernel.filesystem.fs.readFile(passkeysPath, "utf-8");
72473
+ const parsed = JSON.parse(content);
72474
+ return parsed.map((pk) => {
72475
+ const publicKeyArray = JSON.parse(pk.publicKey);
72476
+ return {
72477
+ ...pk,
72478
+ publicKey: new Uint8Array(publicKeyArray)
72479
+ };
72480
+ });
72481
+ } catch (error) {
72482
+ this._options.kernel.log.warn(`Failed to read passkeys for user ${uid}: ${error}`);
72483
+ return [];
72484
+ }
72485
+ }
72486
+ /**
72487
+ * Save passkeys for a user
72488
+ */
72489
+ async savePasskeys(uid, passkeys) {
72490
+ const user2 = this._users.get(uid);
72491
+ if (!user2) throw new Error(`User with UID ${uid} not found`);
72492
+ const passkeysPath = `${user2.home}/.passkeys`;
72493
+ const serialized = passkeys.map((pk) => {
72494
+ const publicKeyArray = pk.publicKey instanceof ArrayBuffer ? Array.from(new Uint8Array(pk.publicKey)) : Array.from(pk.publicKey);
72495
+ return {
72496
+ ...pk,
72497
+ publicKey: JSON.stringify(publicKeyArray)
72498
+ };
72499
+ });
72500
+ await this._options.kernel.filesystem.fs.writeFile(
72501
+ passkeysPath,
72502
+ JSON.stringify(serialized, null, 2),
72503
+ { encoding: "utf-8", mode: 384 }
72504
+ );
72505
+ try {
72506
+ await this._options.kernel.filesystem.fs.chown(passkeysPath, uid, user2.gid);
72507
+ } catch {
72508
+ }
72509
+ }
72510
+ /**
72511
+ * Add a passkey to a user's collection
72512
+ */
72513
+ async addPasskey(uid, passkey) {
72514
+ const existing = await this.getPasskeys(uid);
72515
+ existing.push(passkey);
72516
+ await this.savePasskeys(uid, existing);
72517
+ }
72518
+ /**
72519
+ * Remove a passkey by ID
72520
+ */
72521
+ async removePasskey(uid, passkeyId) {
72522
+ const existing = await this.getPasskeys(uid);
72523
+ const filtered = existing.filter((pk) => pk.id !== passkeyId);
72524
+ await this.savePasskeys(uid, filtered);
72525
+ }
72526
+ /**
72527
+ * Check if a user has any registered passkeys
72528
+ */
72529
+ async hasPasskeys(uid) {
72530
+ const passkeys = await this.getPasskeys(uid);
72531
+ return passkeys.length > 0;
72532
+ }
72207
72533
  };
72208
72534
  __name(_Users, "Users");
72209
72535
  let Users = _Users;
@@ -73568,10 +73894,10 @@ const _Workers = class _Workers {
73568
73894
  };
73569
73895
  __name(_Workers, "Workers");
73570
73896
  let Workers = _Workers;
73571
- const __vite_import_meta_env__ = { "AUTHOR": { "name": "Jay Mathis", "email": "code@mathis.network", "url": "https://github.com/mathiscode" }, "BASE_URL": "/", "DESCRIPTION": "ecmaOS: Micro-kernel and framework for web technologies", "DEV": false, "HOMEPAGE": "https://ecmaos.sh", "KNOWN_ISSUES": ["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", "stdin/stdout/stderr streams and redirection can be wonky and don't work everywhere, but are coming along", "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": ["If it ever fails to boot, check your logs or try clearing all data", "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'", "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", "You can set your environment variables in ~/.env (try setting PROMPT to a PS1-like format)", "Try 'fetch /xkcd-os.sixel'"], "VERSION": "0.6.4", "VITE_APP_SHOW_DEFAULT_LOGIN": "true", "VITE_AUTOLOGIN_PASSWORD": "root", "VITE_AUTOLOGIN_USERNAME": "root", "VITE_BOOT_DISABLE_ISSUES": "true", "VITE_BOOT_DISABLE_LOGO_CONSOLE": "false", "VITE_BOOT_DISABLE_LOGO_FIGLET": "false", "VITE_BOOT_DISABLE_TIPS": "false", "VITE_INITFS": "/initfs.tar.gz", "VITE_KERNEL_INTERVALS_PROC": "1000", "VITE_KERNEL_MODULES": "@ecmaos-modules/boilerplate@0.1.0", "VITE_METAL_SOCKET": "ws://localhost:30445/socket", "VITE_PORT": "30443", "VITE_RECOMMENDED_APPS": "@ecmaos-apps/code,@ecmaos-apps/edit,@ecmaos-apps/ai,@ecmaos-apps/webamp,@ecmaos-apps/news", "XTERM_VERSION": "5.5.0", "ZENFS_VERSION": "2.4.2" };
73897
+ const __vite_import_meta_env__ = { "AUTHOR": { "name": "Jay Mathis", "email": "code@mathis.network", "url": "https://github.com/mathiscode" }, "BASE_URL": "/", "DESCRIPTION": "ecmaOS: Micro-kernel and framework for web technologies", "DEV": false, "HOMEPAGE": "https://ecmaos.sh", "KNOWN_ISSUES": ["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", "stdin/stdout/stderr streams and redirection can be wonky and don't work everywhere, but are coming along", "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": ["If it ever fails to boot, check your logs, try clearing all data, try incognito mode, or try another browser", "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'", "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", "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'", "Try 'fetch /xkcd-os.sixel'"], "VERSION": "0.6.5", "VITE_APP_SHOW_DEFAULT_LOGIN": "true", "VITE_BOOT_DISABLE_ISSUES": "true", "VITE_BOOT_DISABLE_LOGO_CONSOLE": "false", "VITE_BOOT_DISABLE_LOGO_FIGLET": "false", "VITE_BOOT_DISABLE_TIPS": "false", "VITE_INITFS": "/initfs.tar.gz", "VITE_KERNEL_INTERVALS_PROC": "1000", "VITE_KERNEL_MODULES": "@ecmaos-modules/boilerplate@0.1.0", "VITE_METAL_SOCKET": "ws://localhost:30445/socket", "VITE_PORT": "30443", "VITE_RECOMMENDED_APPS": "@ecmaos-apps/code,@ecmaos-apps/edit,@ecmaos-apps/ai,@ecmaos-apps/webamp,@ecmaos-apps/news", "XTERM_VERSION": "5.5.0", "ZENFS_VERSION": "2.4.2" };
73572
73898
  var define_import_meta_env_AUTHOR_default = { name: "Jay Mathis", email: "code@mathis.network", url: "https://github.com/mathiscode" };
73573
73899
  var define_import_meta_env_KNOWN_ISSUES_default = ["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", "stdin/stdout/stderr streams and redirection can be wonky and don't work everywhere, but are coming along", "CTRL-C will return you to a prompt, but doesn't currently interrupt a process", "Lots of unfinished work; watch your step"];
73574
- var define_import_meta_env_TIPS_default = ["If it ever fails to boot, check your logs or try clearing all data", "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'", "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", "You can set your environment variables in ~/.env (try setting PROMPT to a PS1-like format)", "Try 'fetch /xkcd-os.sixel'"];
73900
+ var define_import_meta_env_TIPS_default = ["If it ever fails to boot, check your logs, try clearing all data, try incognito mode, or try another browser", "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'", "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", "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'", "Try 'fetch /xkcd-os.sixel'"];
73575
73901
  const DefaultKernelOptions = {
73576
73902
  devices: DefaultDevices,
73577
73903
  dom: DefaultDomOptions,
@@ -73613,7 +73939,7 @@ const _Kernel = class _Kernel {
73613
73939
  /** Name of the kernel */
73614
73940
  __publicField(this, "name", "@ecmaos/kernel");
73615
73941
  /** Version string of the kernel */
73616
- __publicField(this, "version", "0.6.4");
73942
+ __publicField(this, "version", "0.6.5");
73617
73943
  /** Authentication and authorization service */
73618
73944
  __publicField(this, "auth");
73619
73945
  /** BIOS module providing low-level functionality */
@@ -73771,7 +74097,7 @@ const _Kernel = class _Kernel {
73771
74097
  ];
73772
74098
  this.terminal.writeln(chalk$2.red.bold(`🐉 ${t2("kernel.experimental", "EXPERIMENTAL")} 🐉`));
73773
74099
  this.terminal.writeln(
73774
- `${this.terminal.createSpecialLink("https://ecmaos.sh", "@ecmaos/kernel")}@${"0.6.4"}` + chalk$2.cyan(` [${dependencyLinks.map((link2) => link2.link).join(", ")}]`)
74100
+ `${this.terminal.createSpecialLink("https://ecmaos.sh", "@ecmaos/kernel")}@${"0.6.5"}` + chalk$2.cyan(` [${dependencyLinks.map((link2) => link2.link).join(", ")}]`)
73775
74101
  );
73776
74102
  this.terminal.writeln(`${t2("kernel.madeBy", "Made with ❤️ by Jay Mathis")} ${this.terminal.createSpecialLink(
73777
74103
  define_import_meta_env_AUTHOR_default?.url || "https://github.com/mathiscode",
@@ -73788,14 +74114,14 @@ const _Kernel = class _Kernel {
73788
74114
  if (logoFiglet && true) {
73789
74115
  console.log(`%c${logoFiglet}`, "color: green");
73790
74116
  console.log(`%c${"https://github.com/ecmaos/ecmaos"}`, "color: blue; text-decoration: underline; font-size: 16px");
73791
- this.log.info(`${"@ecmaos/kernel"} v${"0.6.4"}`);
74117
+ this.log.info(`${"@ecmaos/kernel"} v${"0.6.5"}`);
73792
74118
  }
73793
74119
  if (Notification?.permission === "default") Notification.requestPermission();
73794
74120
  if (Notification?.permission === "denied") this.log.warn(t2("kernel.permissionNotificationDenied", "Notification permission denied"));
73795
74121
  this.intervals.set("title-blink", () => {
73796
74122
  globalThis.document.title = globalThis.document.title.includes("_") ? "ecmaos# " : "ecmaos# _";
73797
74123
  }, 600);
73798
- this.toast.success(`${"@ecmaos/kernel"} v${"0.6.4"}`);
74124
+ this.toast.success(`${"@ecmaos/kernel"} v${"0.6.5"}`);
73799
74125
  }
73800
74126
  await this.configure({ devices: this.options.devices || DefaultDevices, filesystem: Filesystem.options() });
73801
74127
  const requiredPaths = [
@@ -73956,20 +74282,62 @@ const _Kernel = class _Kernel {
73956
74282
  const icon = isSecure ? "🔒" : "🔓";
73957
74283
  this.terminal.writeln(`${icon} ${protocolStr}//${hostname}${port}`);
73958
74284
  const username = await this.terminal.readline(`👤 ${this.i18n.t("Username")}: `);
73959
- const password = await this.terminal.readline(`🔑 ${this.i18n.t("Password")}: `, true);
73960
- const { user: user22, cred } = await this.users.login(username, password);
73961
- this.shell.credentials = cred;
73962
- this.shell.context = bindContext({ root: "/", pwd: "/", credentials: cred });
74285
+ const user22 = Array.from(this.users.all.values()).find((u) => u.username === username);
74286
+ let loginSuccess = false;
74287
+ let userCred = null;
74288
+ if (user22) {
74289
+ const passkeys = await this.users.getPasskeys(user22.uid);
74290
+ if (passkeys.length > 0 && this.auth.passkey.isSupported()) {
74291
+ try {
74292
+ const challenge = crypto.getRandomValues(new Uint8Array(32));
74293
+ const rpId = globalThis.location.hostname || "localhost";
74294
+ const allowCredentials = passkeys.map((pk) => {
74295
+ const credentialIdBytes = Uint8Array.from(atob(pk.credentialId), (c) => c.charCodeAt(0));
74296
+ return {
74297
+ id: credentialIdBytes.buffer,
74298
+ type: "public-key",
74299
+ transports: ["usb", "nfc", "ble", "internal"]
74300
+ };
74301
+ });
74302
+ const requestOptions = {
74303
+ challenge,
74304
+ allowCredentials,
74305
+ rpId,
74306
+ userVerification: "preferred",
74307
+ timeout: 6e4
74308
+ };
74309
+ this.terminal.writeln(chalk$2.yellow("🔐 Please use your passkey to authenticate..."));
74310
+ const credential = await this.auth.passkey.get(requestOptions);
74311
+ if (credential && credential instanceof PublicKeyCredential) {
74312
+ userCred = await this.users.login(username, void 0, credential);
74313
+ loginSuccess = true;
74314
+ } else {
74315
+ this.terminal.writeln(chalk$2.yellow("Passkey authentication cancelled or failed. Falling back to password..."));
74316
+ }
74317
+ } catch (err2) {
74318
+ this.terminal.writeln(chalk$2.yellow(`Passkey authentication error: ${err2.message}. Falling back to password...`));
74319
+ }
74320
+ }
74321
+ }
74322
+ if (!loginSuccess) {
74323
+ const password = await this.terminal.readline(`🔑 ${this.i18n.t("Password")}: `, true);
74324
+ userCred = await this.users.login(username, password);
74325
+ }
74326
+ if (!userCred) {
74327
+ throw new Error("Login failed");
74328
+ }
74329
+ this.shell.credentials = userCred.cred;
74330
+ this.shell.context = bindContext({ root: "/", pwd: "/", credentials: userCred.cred });
73963
74331
  await this.shell.loadEnvFile();
73964
- this.shell.env.set("UID", user22.uid.toString());
73965
- this.shell.env.set("GID", user22.gid.toString());
73966
- this.shell.env.set("SUID", cred.suid.toString());
73967
- this.shell.env.set("SGID", cred.sgid.toString());
73968
- this.shell.env.set("EUID", cred.euid.toString());
73969
- this.shell.env.set("EGID", cred.egid.toString());
73970
- this.shell.env.set("SHELL", user22.shell || "ecmaos");
73971
- this.shell.env.set("HOME", user22.home || "/root");
73972
- this.shell.env.set("USER", user22.username);
74332
+ this.shell.env.set("UID", userCred.user.uid.toString());
74333
+ this.shell.env.set("GID", userCred.user.gid.toString());
74334
+ this.shell.env.set("SUID", userCred.cred.suid.toString());
74335
+ this.shell.env.set("SGID", userCred.cred.sgid.toString());
74336
+ this.shell.env.set("EUID", userCred.cred.euid.toString());
74337
+ this.shell.env.set("EGID", userCred.cred.egid.toString());
74338
+ this.shell.env.set("SHELL", userCred.user.shell || "ecmaos");
74339
+ this.shell.env.set("HOME", userCred.user.home || "/root");
74340
+ this.shell.env.set("USER", userCred.user.username);
73973
74341
  process$1.env = Object.fromEntries(this.shell.env);
73974
74342
  break;
73975
74343
  } catch (err2) {
@@ -74499,7 +74867,7 @@ const _Kernel = class _Kernel {
74499
74867
  memory: "?",
74500
74868
  platform: navigator.userAgentData?.platform || navigator?.platform || navigator.userAgent,
74501
74869
  querystring: location.search,
74502
- version: `${"@ecmaos/kernel"} ${"0.6.4"}`,
74870
+ version: `${"@ecmaos/kernel"} ${"0.6.5"}`,
74503
74871
  language: navigator.language,
74504
74872
  host: location.host,
74505
74873
  userAgent: navigator.userAgent,
@@ -74676,4 +75044,4 @@ export {
74676
75044
  path$1 as p,
74677
75045
  semver as s
74678
75046
  };
74679
- //# sourceMappingURL=kernel-DtEbpoeV.js.map
75047
+ //# sourceMappingURL=kernel-C_Xvcpox.js.map