@onklave/agent-cli 0.1.25 → 0.1.26

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.
Files changed (2) hide show
  1. package/main.js +116 -37
  2. package/package.json +2 -1
package/main.js CHANGED
@@ -6,24 +6,131 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
6
  throw Error('Dynamic require of "' + x + '" is not supported');
7
7
  });
8
8
 
9
- // _apps/@onklave/agent-cli/src/services/auth.service.ts
9
+ // _apps/@onklave/agent-cli/src/services/credential-store.ts
10
10
  import * as fs from "fs";
11
11
  import * as path from "path";
12
12
  import * as os from "os";
13
- var DEFAULT_PLATFORM_URL = "https://api.onklave.app";
14
- var AuthService = class {
13
+ import { createRequire } from "module";
14
+ var nodeRequire = createRequire(import.meta.url);
15
+ var KEYTAR_SERVICE = "onklave-agent-cli";
16
+ var KEYTAR_ACCOUNT = "default";
17
+ var keytarModule;
18
+ var warnedFallback = false;
19
+ function loadKeytar() {
20
+ if (keytarModule !== void 0) {
21
+ return keytarModule;
22
+ }
23
+ try {
24
+ keytarModule = nodeRequire("keytar");
25
+ } catch {
26
+ keytarModule = null;
27
+ }
28
+ return keytarModule;
29
+ }
30
+ function warnFallback(reason) {
31
+ if (warnedFallback) {
32
+ return;
33
+ }
34
+ warnedFallback = true;
35
+ console.warn(
36
+ `[onklave] OS keychain unavailable (${reason}); falling back to file store at ~/.config/onklave/credentials.json`
37
+ );
38
+ }
39
+ var CredentialStore = class {
15
40
  constructor() {
16
41
  this.configDir = path.join(os.homedir(), ".config", "onklave");
17
42
  this.credentialsPath = path.join(this.configDir, "credentials.json");
18
43
  }
19
44
  /*
20
- * Ensure the config directory exists with restricted permissions.
45
+ * Read the full credentials object, keychain-first.
21
46
  */
47
+ async read() {
48
+ const keytar = loadKeytar();
49
+ if (keytar) {
50
+ try {
51
+ const raw = await keytar.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
52
+ if (raw == null) {
53
+ return null;
54
+ }
55
+ return JSON.parse(raw);
56
+ } catch (err) {
57
+ warnFallback(err instanceof Error ? err.message : "read failed");
58
+ }
59
+ }
60
+ return this.readFile();
61
+ }
62
+ /*
63
+ * Persist the full credentials object, keychain-first.
64
+ */
65
+ async write(credentials) {
66
+ const keytar = loadKeytar();
67
+ if (keytar) {
68
+ try {
69
+ await keytar.setPassword(
70
+ KEYTAR_SERVICE,
71
+ KEYTAR_ACCOUNT,
72
+ JSON.stringify(credentials)
73
+ );
74
+ return;
75
+ } catch (err) {
76
+ warnFallback(err instanceof Error ? err.message : "write failed");
77
+ }
78
+ }
79
+ this.writeFile(credentials);
80
+ }
81
+ /*
82
+ * Remove stored credentials from both the keychain and the file fallback.
83
+ */
84
+ async clear() {
85
+ const keytar = loadKeytar();
86
+ if (keytar) {
87
+ try {
88
+ await keytar.deletePassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
89
+ } catch (err) {
90
+ warnFallback(err instanceof Error ? err.message : "delete failed");
91
+ }
92
+ }
93
+ if (fs.existsSync(this.credentialsPath)) {
94
+ fs.unlinkSync(this.credentialsPath);
95
+ }
96
+ }
97
+ /* ----- legacy mode-0600 file fallback ----- */
22
98
  ensureConfigDir() {
23
99
  if (!fs.existsSync(this.configDir)) {
24
100
  fs.mkdirSync(this.configDir, { recursive: true, mode: 448 });
25
101
  }
26
102
  }
103
+ readFile() {
104
+ if (!fs.existsSync(this.credentialsPath)) {
105
+ return null;
106
+ }
107
+ try {
108
+ const raw = fs.readFileSync(this.credentialsPath, "utf-8");
109
+ return JSON.parse(raw);
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+ writeFile(credentials) {
115
+ this.ensureConfigDir();
116
+ fs.writeFileSync(
117
+ this.credentialsPath,
118
+ JSON.stringify(credentials, null, 2),
119
+ {
120
+ encoding: "utf-8",
121
+ mode: 384
122
+ }
123
+ );
124
+ fs.chmodSync(this.credentialsPath, 384);
125
+ }
126
+ };
127
+
128
+ // _apps/@onklave/agent-cli/src/services/auth.service.ts
129
+ var DEFAULT_PLATFORM_URL = "https://api.onklave.app";
130
+ var AuthService = class {
131
+ constructor() {
132
+ this.store = new CredentialStore();
133
+ }
27
134
  /*
28
135
  * Read the stored auth token.
29
136
  */
@@ -35,7 +142,6 @@ var AuthService = class {
35
142
  * Save an auth token with optional metadata.
36
143
  */
37
144
  async saveToken(token, metadata) {
38
- this.ensureConfigDir();
39
145
  const existing = await this.getCredentials();
40
146
  const credentials = {
41
147
  ...existing,
@@ -45,23 +151,13 @@ var AuthService = class {
45
151
  orgId: metadata?.orgId ?? existing?.orgId,
46
152
  expiresAt: metadata?.expiresAt ?? existing?.expiresAt
47
153
  };
48
- fs.writeFileSync(
49
- this.credentialsPath,
50
- JSON.stringify(credentials, null, 2),
51
- {
52
- encoding: "utf-8",
53
- mode: 384
54
- }
55
- );
56
- fs.chmodSync(this.credentialsPath, 384);
154
+ await this.store.write(credentials);
57
155
  }
58
156
  /*
59
- * Remove the stored credentials file.
157
+ * Remove the stored credentials.
60
158
  */
61
159
  async clearToken() {
62
- if (fs.existsSync(this.credentialsPath)) {
63
- fs.unlinkSync(this.credentialsPath);
64
- }
160
+ await this.store.clear();
65
161
  }
66
162
  /*
67
163
  * Check if a valid (non-expired) token exists.
@@ -83,21 +179,12 @@ var AuthService = class {
83
179
  * Read the full credentials object from disk.
84
180
  */
85
181
  async getCredentials() {
86
- if (!fs.existsSync(this.credentialsPath)) {
87
- return null;
88
- }
89
- try {
90
- const raw = fs.readFileSync(this.credentialsPath, "utf-8");
91
- return JSON.parse(raw);
92
- } catch {
93
- return null;
94
- }
182
+ return this.store.read();
95
183
  }
96
184
  /*
97
185
  * Save the device token received during machine registration.
98
186
  */
99
187
  async saveDeviceToken(deviceToken, machineId, deviceTokenExpiresAt) {
100
- this.ensureConfigDir();
101
188
  const existing = await this.getCredentials();
102
189
  if (!existing) {
103
190
  throw new Error(
@@ -110,15 +197,7 @@ var AuthService = class {
110
197
  machineId,
111
198
  ...deviceTokenExpiresAt ? { deviceTokenExpiresAt } : {}
112
199
  };
113
- fs.writeFileSync(
114
- this.credentialsPath,
115
- JSON.stringify(credentials, null, 2),
116
- {
117
- encoding: "utf-8",
118
- mode: 384
119
- }
120
- );
121
- fs.chmodSync(this.credentialsPath, 384);
200
+ await this.store.write(credentials);
122
201
  }
123
202
  /*
124
203
  * Get the platform URL from credentials or fallback to default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onklave/agent-cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "Onklave Agent CLI — local agent runner with cloud orchestration",
5
5
  "bin": {
6
6
  "onklave": "./main.js"
@@ -24,6 +24,7 @@
24
24
  "dependencies": {
25
25
  "ink": "^5.2.1",
26
26
  "ink-text-input": "^6.0.0",
27
+ "keytar": "^7.9.0",
27
28
  "react": "^18.3.1",
28
29
  "socket.io-client": "4.8.3"
29
30
  },