apteva 0.3.6 → 0.3.8

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/package.json +6 -6
  2. package/src/crypto.ts +48 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apteva",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Run AI agents locally. Multi-provider support for Claude, GPT, Gemini, Llama, and more.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -65,10 +65,10 @@
65
65
  "react-dom": "^18.2.0"
66
66
  },
67
67
  "optionalDependencies": {
68
- "@apteva/agent-darwin-arm64": "*",
69
- "@apteva/agent-darwin-x64": "*",
70
- "@apteva/agent-linux-arm64": "*",
71
- "@apteva/agent-linux-x64": "*",
72
- "@apteva/agent-win32-x64": "*"
68
+ "@apteva/agent-darwin-arm64": "^1.33.73",
69
+ "@apteva/agent-darwin-x64": "^1.33.73",
70
+ "@apteva/agent-linux-arm64": "^1.33.73",
71
+ "@apteva/agent-linux-x64": "^1.33.73",
72
+ "@apteva/agent-win32-x64": "^1.33.73"
73
73
  }
74
74
  }
package/src/crypto.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { createCipheriv, createDecipheriv, randomBytes, scryptSync, createHash } from "crypto";
2
2
  import { hostname, userInfo } from "os";
3
3
  import { join } from "path";
4
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
5
+ import { homedir } from "os";
4
6
 
5
7
  const ALGORITHM = "aes-256-gcm";
6
8
  const IV_LENGTH = 16;
@@ -8,15 +10,54 @@ const SALT_LENGTH = 32;
8
10
  const TAG_LENGTH = 16;
9
11
  const KEY_LENGTH = 32;
10
12
 
13
+ // Cache the encryption secret to avoid repeated file reads
14
+ let cachedSecret: string | null = null;
15
+
16
+ // Get the path for storing the encryption secret
17
+ function getSecretPath(): string {
18
+ const dataDir = process.env.DATA_DIR || join(homedir(), ".apteva");
19
+ return join(dataDir, ".encryption-key");
20
+ }
21
+
22
+ // Get or create a persistent encryption secret
23
+ // This ensures keys can be decrypted after container/app restarts
24
+ function getOrCreateSecret(): string {
25
+ if (cachedSecret) return cachedSecret;
26
+
27
+ const secretPath = getSecretPath();
28
+
29
+ // Try to read existing secret
30
+ if (existsSync(secretPath)) {
31
+ try {
32
+ cachedSecret = readFileSync(secretPath, "utf8").trim();
33
+ if (cachedSecret && cachedSecret.length >= 32) {
34
+ return cachedSecret;
35
+ }
36
+ } catch {
37
+ // Fall through to create new
38
+ }
39
+ }
40
+
41
+ // Create new secret and persist it
42
+ cachedSecret = randomBytes(32).toString("hex");
43
+ try {
44
+ const dir = process.env.DATA_DIR || join(homedir(), ".apteva");
45
+ if (!existsSync(dir)) {
46
+ mkdirSync(dir, { recursive: true });
47
+ }
48
+ writeFileSync(secretPath, cachedSecret, { mode: 0o600 });
49
+ } catch (err) {
50
+ console.error("[crypto] Warning: Could not persist encryption key:", err);
51
+ // Continue with in-memory key - will work for this session but not across restarts
52
+ }
53
+
54
+ return cachedSecret;
55
+ }
56
+
11
57
  // Get a machine-specific identifier for key derivation
58
+ // Now uses a persistent secret instead of volatile machine factors
12
59
  function getMachineId(): string {
13
- const factors = [
14
- hostname(),
15
- userInfo().username,
16
- process.env.HOME || process.env.USERPROFILE || "",
17
- __dirname, // Installation path adds uniqueness
18
- ];
19
- return factors.join("|");
60
+ return getOrCreateSecret();
20
61
  }
21
62
 
22
63
  // Derive encryption key from machine ID and salt