@aigne/secrets 0.1.1-beta → 0.1.1-beta.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.1-beta.2](https://github.com/AIGNE-io/aigne-framework/compare/secrets-v0.1.1-beta.1...secrets-v0.1.1-beta.2) (2025-11-27)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **secrets:** improve keyring availability detection with environment checks ([#778](https://github.com/AIGNE-io/aigne-framework/issues/778)) ([75dceab](https://github.com/AIGNE-io/aigne-framework/commit/75dceabeb7d6fd8c057759f003e703a2ebb41afd))
9
+
10
+ ## [0.1.1-beta.1](https://github.com/AIGNE-io/aigne-framework/compare/secrets-v0.1.1-beta...secrets-v0.1.1-beta.1) (2025-11-26)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **cli:** use sequential migration to handle keyring and callback file save ([#776](https://github.com/AIGNE-io/aigne-framework/issues/776)) ([da0db46](https://github.com/AIGNE-io/aigne-framework/commit/da0db46597b76cc0f41d604fd51bcd64931f0315))
16
+
3
17
  ## [0.1.1-beta](https://github.com/AIGNE-io/aigne-framework/compare/secrets-v0.1.0...secrets-v0.1.1-beta) (2025-11-26)
4
18
 
5
19
 
@@ -5,6 +5,8 @@ export declare class KeyringStore extends BaseSecretStore {
5
5
  private serviceName;
6
6
  private defaultAccount;
7
7
  private _forceUnavailable;
8
+ private _environmentChecked;
9
+ private _environmentReady;
8
10
  constructor(options: StoreOptions);
9
11
  available(): Promise<boolean>;
10
12
  setItem(key: string, value: ItemInfo): Promise<any>;
package/lib/cjs/keytar.js CHANGED
@@ -34,24 +34,40 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.KeyringStore = void 0;
37
+ const logger_js_1 = require("@aigne/core/utils/logger.js");
37
38
  const base_js_1 = require("./base.js");
38
- const DEFAULT_SERVICE_NAME = "-secrets";
39
+ const util_js_1 = require("./util.js");
40
+ const DEFAULT_SERVICE_NAME = "-api-key";
39
41
  const DEFAULT_ACCOUNT_NAME_FOR_DEFAULT = "-default";
40
42
  class KeyringStore extends base_js_1.BaseSecretStore {
41
43
  _impl = null;
42
44
  serviceName;
43
45
  defaultAccount;
44
46
  _forceUnavailable;
47
+ _environmentChecked = false;
48
+ _environmentReady = false;
45
49
  constructor(options) {
46
50
  super();
47
- const { serviceName, forceUnavailable = false } = options;
51
+ const { serviceName, forceKeytarUnavailable = false } = options;
48
52
  this.serviceName = `${serviceName}${DEFAULT_SERVICE_NAME}`;
49
53
  this.defaultAccount = `${serviceName}${DEFAULT_ACCOUNT_NAME_FOR_DEFAULT}`;
50
- this._forceUnavailable = !!forceUnavailable;
54
+ this._forceUnavailable = !!forceKeytarUnavailable;
51
55
  }
52
56
  async available() {
53
57
  if (this._forceUnavailable)
54
58
  return false;
59
+ // Check environment prerequisites before attempting to load the module
60
+ if (!this._environmentChecked) {
61
+ const { ready, reason } = (0, util_js_1.isKeyringEnvironmentReady)();
62
+ this._environmentReady = ready;
63
+ if (!ready) {
64
+ logger_js_1.logger.warn(`Keyring environment not ready: ${reason}`);
65
+ }
66
+ this._environmentChecked = true;
67
+ }
68
+ if (!this._environmentReady) {
69
+ return false;
70
+ }
55
71
  try {
56
72
  if (!this._impl) {
57
73
  const module = await Promise.resolve().then(() => __importStar(require("@zowe/secrets-for-zowe-sdk")));
@@ -62,7 +78,8 @@ class KeyringStore extends base_js_1.BaseSecretStore {
62
78
  typeof this._impl.setPassword === "function" &&
63
79
  typeof this._impl.deletePassword === "function");
64
80
  }
65
- catch {
81
+ catch (error) {
82
+ logger_js_1.logger.error(`Failed to load keyring: ${error.message}`);
66
83
  return false;
67
84
  }
68
85
  }
@@ -9,7 +9,7 @@ export interface GetDefaultOptions {
9
9
  export interface StoreOptions {
10
10
  filepath?: string;
11
11
  serviceName: string;
12
- forceUnavailable?: boolean;
12
+ forceKeytarUnavailable?: boolean;
13
13
  }
14
14
  export type ItemInfo = {
15
15
  [key: string]: any;
@@ -0,0 +1,4 @@
1
+ export declare function isKeyringEnvironmentReady(): {
2
+ ready: boolean;
3
+ reason?: string;
4
+ };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isKeyringEnvironmentReady = isKeyringEnvironmentReady;
4
+ const node_fs_1 = require("node:fs");
5
+ function isWSL() {
6
+ if (process.platform !== "linux")
7
+ return false;
8
+ // env checks
9
+ if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP)
10
+ return true;
11
+ try {
12
+ const v = (0, node_fs_1.readFileSync)("/proc/version", "utf8").toLowerCase();
13
+ if (v.includes("microsoft") || v.includes("wsl"))
14
+ return true;
15
+ }
16
+ catch { }
17
+ try {
18
+ const r = (0, node_fs_1.readFileSync)("/proc/sys/kernel/osrelease", "utf8").toLowerCase();
19
+ if (r.includes("microsoft") || r.includes("wsl"))
20
+ return true;
21
+ }
22
+ catch { }
23
+ // some WSL setups have /run/WSL or other hints
24
+ if ((0, node_fs_1.existsSync)("/run/WSL") || (0, node_fs_1.existsSync)("/run/WSL/"))
25
+ return true;
26
+ return false;
27
+ }
28
+ function isDBusAvailable() {
29
+ return !!process.env.DBUS_SESSION_BUS_ADDRESS;
30
+ }
31
+ function isDisplayAvailable() {
32
+ return !!(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
33
+ }
34
+ function isKeyringEnvironmentReady() {
35
+ if (process.platform === "win32")
36
+ return { ready: true };
37
+ if (process.platform === "darwin")
38
+ return { ready: true };
39
+ if (process.platform === "linux") {
40
+ if (!process.env.CI) {
41
+ if (isWSL()) {
42
+ return { ready: false, reason: "Detected WSL (no GNOME keyring by default)" };
43
+ }
44
+ // Check for D-Bus (required for libsecret)
45
+ if (!isDBusAvailable()) {
46
+ return { ready: false, reason: "D-Bus not available" };
47
+ }
48
+ // Check for display server (most keyring services need it)
49
+ if (!isDisplayAvailable()) {
50
+ return { ready: false, reason: "Display not available" };
51
+ }
52
+ }
53
+ return { ready: true };
54
+ }
55
+ // Unknown platform
56
+ return { ready: false, reason: `Unsupported platform: ${process.platform}` };
57
+ }
@@ -5,6 +5,8 @@ export declare class KeyringStore extends BaseSecretStore {
5
5
  private serviceName;
6
6
  private defaultAccount;
7
7
  private _forceUnavailable;
8
+ private _environmentChecked;
9
+ private _environmentReady;
8
10
  constructor(options: StoreOptions);
9
11
  available(): Promise<boolean>;
10
12
  setItem(key: string, value: ItemInfo): Promise<any>;
package/lib/esm/keytar.js CHANGED
@@ -1,21 +1,37 @@
1
+ import { logger } from "@aigne/core/utils/logger.js";
1
2
  import { BaseSecretStore } from "./base.js";
2
- const DEFAULT_SERVICE_NAME = "-secrets";
3
+ import { isKeyringEnvironmentReady } from "./util.js";
4
+ const DEFAULT_SERVICE_NAME = "-api-key";
3
5
  const DEFAULT_ACCOUNT_NAME_FOR_DEFAULT = "-default";
4
6
  export class KeyringStore extends BaseSecretStore {
5
7
  _impl = null;
6
8
  serviceName;
7
9
  defaultAccount;
8
10
  _forceUnavailable;
11
+ _environmentChecked = false;
12
+ _environmentReady = false;
9
13
  constructor(options) {
10
14
  super();
11
- const { serviceName, forceUnavailable = false } = options;
15
+ const { serviceName, forceKeytarUnavailable = false } = options;
12
16
  this.serviceName = `${serviceName}${DEFAULT_SERVICE_NAME}`;
13
17
  this.defaultAccount = `${serviceName}${DEFAULT_ACCOUNT_NAME_FOR_DEFAULT}`;
14
- this._forceUnavailable = !!forceUnavailable;
18
+ this._forceUnavailable = !!forceKeytarUnavailable;
15
19
  }
16
20
  async available() {
17
21
  if (this._forceUnavailable)
18
22
  return false;
23
+ // Check environment prerequisites before attempting to load the module
24
+ if (!this._environmentChecked) {
25
+ const { ready, reason } = isKeyringEnvironmentReady();
26
+ this._environmentReady = ready;
27
+ if (!ready) {
28
+ logger.warn(`Keyring environment not ready: ${reason}`);
29
+ }
30
+ this._environmentChecked = true;
31
+ }
32
+ if (!this._environmentReady) {
33
+ return false;
34
+ }
19
35
  try {
20
36
  if (!this._impl) {
21
37
  const module = await import("@zowe/secrets-for-zowe-sdk");
@@ -26,7 +42,8 @@ export class KeyringStore extends BaseSecretStore {
26
42
  typeof this._impl.setPassword === "function" &&
27
43
  typeof this._impl.deletePassword === "function");
28
44
  }
29
- catch {
45
+ catch (error) {
46
+ logger.error(`Failed to load keyring: ${error.message}`);
30
47
  return false;
31
48
  }
32
49
  }
@@ -9,7 +9,7 @@ export interface GetDefaultOptions {
9
9
  export interface StoreOptions {
10
10
  filepath?: string;
11
11
  serviceName: string;
12
- forceUnavailable?: boolean;
12
+ forceKeytarUnavailable?: boolean;
13
13
  }
14
14
  export type ItemInfo = {
15
15
  [key: string]: any;
@@ -0,0 +1,4 @@
1
+ export declare function isKeyringEnvironmentReady(): {
2
+ ready: boolean;
3
+ reason?: string;
4
+ };
@@ -0,0 +1,54 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ function isWSL() {
3
+ if (process.platform !== "linux")
4
+ return false;
5
+ // env checks
6
+ if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP)
7
+ return true;
8
+ try {
9
+ const v = readFileSync("/proc/version", "utf8").toLowerCase();
10
+ if (v.includes("microsoft") || v.includes("wsl"))
11
+ return true;
12
+ }
13
+ catch { }
14
+ try {
15
+ const r = readFileSync("/proc/sys/kernel/osrelease", "utf8").toLowerCase();
16
+ if (r.includes("microsoft") || r.includes("wsl"))
17
+ return true;
18
+ }
19
+ catch { }
20
+ // some WSL setups have /run/WSL or other hints
21
+ if (existsSync("/run/WSL") || existsSync("/run/WSL/"))
22
+ return true;
23
+ return false;
24
+ }
25
+ function isDBusAvailable() {
26
+ return !!process.env.DBUS_SESSION_BUS_ADDRESS;
27
+ }
28
+ function isDisplayAvailable() {
29
+ return !!(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
30
+ }
31
+ export function isKeyringEnvironmentReady() {
32
+ if (process.platform === "win32")
33
+ return { ready: true };
34
+ if (process.platform === "darwin")
35
+ return { ready: true };
36
+ if (process.platform === "linux") {
37
+ if (!process.env.CI) {
38
+ if (isWSL()) {
39
+ return { ready: false, reason: "Detected WSL (no GNOME keyring by default)" };
40
+ }
41
+ // Check for D-Bus (required for libsecret)
42
+ if (!isDBusAvailable()) {
43
+ return { ready: false, reason: "D-Bus not available" };
44
+ }
45
+ // Check for display server (most keyring services need it)
46
+ if (!isDisplayAvailable()) {
47
+ return { ready: false, reason: "Display not available" };
48
+ }
49
+ }
50
+ return { ready: true };
51
+ }
52
+ // Unknown platform
53
+ return { ready: false, reason: `Unsupported platform: ${process.platform}` };
54
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/secrets",
3
- "version": "0.1.1-beta",
3
+ "version": "0.1.1-beta.2",
4
4
  "description": "Secure credential storage for AIGNE Hub API keys with system keyring and file-based fallback",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -44,6 +44,7 @@
44
44
  }
45
45
  },
46
46
  "dependencies": {
47
+ "@aigne/core": "^1.69.0",
47
48
  "@zowe/secrets-for-zowe-sdk": "^8.29.4",
48
49
  "yaml": "^2.8.1"
49
50
  },