@kanadego/dsh-heartbeat 1.9.1 → 1.9.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/README.md +27 -5
- package/cordis.patch.yml +18 -39
- package/dist/{chunk-BQCXYE7N.js → chunk-3MDBU6WY.js} +2 -2
- package/dist/{chunk-HT57FOEF.js → chunk-AJ5HLAL7.js} +34 -11
- package/dist/chunk-AJ5HLAL7.js.map +1 -0
- package/dist/{chunk-OYVNWB5G.js → chunk-CUOSICYJ.js} +2 -2
- package/dist/{chunk-WRJCINZ7.js → chunk-IG6YMUHW.js} +4 -4
- package/dist/{chunk-KOOQOMQY.js → chunk-JDH2LDFS.js} +2 -2
- package/dist/chunk-K5Y6JP2B.js +399 -0
- package/dist/chunk-K5Y6JP2B.js.map +1 -0
- package/dist/{chunk-QOQ7EPZZ.js → chunk-KB5SMG3F.js} +3 -3
- package/dist/{chunk-2NB4QILF.js → chunk-XFNCTOW7.js} +2 -2
- package/dist/cli/index.js +9 -9
- package/dist/{inbox-JLT5G7TL.js → inbox-P26DDMWC.js} +3 -3
- package/dist/index.d.ts +33 -0
- package/dist/index.js +104 -20
- package/dist/index.js.map +1 -1
- package/dist/{migrate-WDVFHUP7.js → migrate-D4VKAKYT.js} +3 -3
- package/dist/{orchestrator-2ZLU7RGE.js → orchestrator-EUTZ3KG6.js} +10 -8
- package/dist/{pool-B34NTH6D.js → pool-UTXQJJ5C.js} +3 -3
- package/dist/{snapshot-JQDJ346Z.js → snapshot-K5VHETTK.js} +4 -4
- package/package.json +83 -83
- package/dist/chunk-7TW6DD6Q.js +0 -208
- package/dist/chunk-7TW6DD6Q.js.map +0 -1
- package/dist/chunk-HT57FOEF.js.map +0 -1
- /package/dist/{chunk-BQCXYE7N.js.map → chunk-3MDBU6WY.js.map} +0 -0
- /package/dist/{chunk-OYVNWB5G.js.map → chunk-CUOSICYJ.js.map} +0 -0
- /package/dist/{chunk-WRJCINZ7.js.map → chunk-IG6YMUHW.js.map} +0 -0
- /package/dist/{chunk-KOOQOMQY.js.map → chunk-JDH2LDFS.js.map} +0 -0
- /package/dist/{chunk-QOQ7EPZZ.js.map → chunk-KB5SMG3F.js.map} +0 -0
- /package/dist/{chunk-2NB4QILF.js.map → chunk-XFNCTOW7.js.map} +0 -0
- /package/dist/{inbox-JLT5G7TL.js.map → inbox-P26DDMWC.js.map} +0 -0
- /package/dist/{migrate-WDVFHUP7.js.map → migrate-D4VKAKYT.js.map} +0 -0
- /package/dist/{orchestrator-2ZLU7RGE.js.map → orchestrator-EUTZ3KG6.js.map} +0 -0
- /package/dist/{pool-B34NTH6D.js.map → pool-UTXQJJ5C.js.map} +0 -0
- /package/dist/{snapshot-JQDJ346Z.js.map → snapshot-K5VHETTK.js.map} +0 -0
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
collectMigrationEntries,
|
|
7
7
|
decryptContainer,
|
|
8
8
|
encryptContainer
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-XFNCTOW7.js";
|
|
10
|
+
import "./chunk-K5Y6JP2B.js";
|
|
11
11
|
import "./chunk-WRUTATW4.js";
|
|
12
12
|
export {
|
|
13
13
|
MIGRATE_FILES,
|
|
@@ -18,4 +18,4 @@ export {
|
|
|
18
18
|
decryptContainer,
|
|
19
19
|
encryptContainer
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=migrate-
|
|
21
|
+
//# sourceMappingURL=migrate-D4VKAKYT.js.map
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
homeSessionId,
|
|
12
12
|
isContextOverflowError,
|
|
13
13
|
loadCursors,
|
|
14
|
+
looksPermanentResumeFailure,
|
|
14
15
|
markHomeRotateIfOverflow,
|
|
15
16
|
parseJsonBlock,
|
|
16
17
|
pickSpokenLine,
|
|
@@ -22,15 +23,15 @@ import {
|
|
|
22
23
|
shouldRotateHome,
|
|
23
24
|
spokeTextSince,
|
|
24
25
|
startOrchestrator
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
26
|
+
} from "./chunk-AJ5HLAL7.js";
|
|
27
|
+
import "./chunk-IG6YMUHW.js";
|
|
27
28
|
import "./chunk-3QJJRXIR.js";
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-JDH2LDFS.js";
|
|
30
|
+
import "./chunk-3MDBU6WY.js";
|
|
30
31
|
import "./chunk-IV2ZWQA3.js";
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
33
|
-
import "./chunk-
|
|
32
|
+
import "./chunk-KB5SMG3F.js";
|
|
33
|
+
import "./chunk-CUOSICYJ.js";
|
|
34
|
+
import "./chunk-K5Y6JP2B.js";
|
|
34
35
|
import "./chunk-WRUTATW4.js";
|
|
35
36
|
export {
|
|
36
37
|
ENGINE_ROOM_EXTRA_TOOLS,
|
|
@@ -45,6 +46,7 @@ export {
|
|
|
45
46
|
homeSessionId,
|
|
46
47
|
isContextOverflowError,
|
|
47
48
|
loadCursors,
|
|
49
|
+
looksPermanentResumeFailure,
|
|
48
50
|
markHomeRotateIfOverflow,
|
|
49
51
|
parseJsonBlock,
|
|
50
52
|
pickSpokenLine,
|
|
@@ -57,4 +59,4 @@ export {
|
|
|
57
59
|
spokeTextSince,
|
|
58
60
|
startOrchestrator
|
|
59
61
|
};
|
|
60
|
-
//# sourceMappingURL=orchestrator-
|
|
62
|
+
//# sourceMappingURL=orchestrator-EUTZ3KG6.js.map
|
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
savePool,
|
|
17
17
|
seedsFilePath,
|
|
18
18
|
surfaceSeed
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JDH2LDFS.js";
|
|
20
20
|
import "./chunk-IV2ZWQA3.js";
|
|
21
|
-
import "./chunk-
|
|
21
|
+
import "./chunk-K5Y6JP2B.js";
|
|
22
22
|
import "./chunk-WRUTATW4.js";
|
|
23
23
|
export {
|
|
24
24
|
SEED_CATEGORY_CAPS,
|
|
@@ -39,4 +39,4 @@ export {
|
|
|
39
39
|
seedsFilePath,
|
|
40
40
|
surfaceSeed
|
|
41
41
|
};
|
|
42
|
-
//# sourceMappingURL=pool-
|
|
42
|
+
//# sourceMappingURL=pool-UTXQJJ5C.js.map
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
snapshotDue,
|
|
4
4
|
snapshotIfDue,
|
|
5
5
|
snapshotProfile
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-KB5SMG3F.js";
|
|
7
|
+
import "./chunk-CUOSICYJ.js";
|
|
8
|
+
import "./chunk-K5Y6JP2B.js";
|
|
9
9
|
import "./chunk-WRUTATW4.js";
|
|
10
10
|
export {
|
|
11
11
|
SNAPSHOT_THRESHOLD,
|
|
@@ -13,4 +13,4 @@ export {
|
|
|
13
13
|
snapshotIfDue,
|
|
14
14
|
snapshotProfile
|
|
15
15
|
};
|
|
16
|
-
//# sourceMappingURL=snapshot-
|
|
16
|
+
//# sourceMappingURL=snapshot-K5VHETTK.js.map
|
package/package.json
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@kanadego/dsh-heartbeat",
|
|
3
|
-
"version": "1.9.
|
|
4
|
-
"description": "Heartbeat plugin for DeepSeek Harness: scheduled autonomous reflection loop with user profile, material pool, pace gate, and gated proactive expression.",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/Kanadego/dsh-heartbeat.git"
|
|
8
|
-
},
|
|
9
|
-
"homepage": "https://github.com/Kanadego/dsh-heartbeat",
|
|
10
|
-
"bugs": {
|
|
11
|
-
"url": "https://github.com/Kanadego/dsh-heartbeat/issues"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
"dsh",
|
|
15
|
-
"dsh-plugin",
|
|
16
|
-
"deepseek-harness",
|
|
17
|
-
"heartbeat",
|
|
18
|
-
"proactive",
|
|
19
|
-
"agent"
|
|
20
|
-
],
|
|
21
|
-
"publishConfig": {
|
|
22
|
-
"registry": "https://registry.npmjs.org"
|
|
23
|
-
},
|
|
24
|
-
"type": "module",
|
|
25
|
-
"main": "dist/index.js",
|
|
26
|
-
"types": "dist/index.d.ts",
|
|
27
|
-
"exports": {
|
|
28
|
-
".": {
|
|
29
|
-
"types": "./dist/index.d.ts",
|
|
30
|
-
"default": "./dist/index.js"
|
|
31
|
-
},
|
|
32
|
-
"./cli": {
|
|
33
|
-
"types": "./dist/cli/index.d.ts",
|
|
34
|
-
"default": "./dist/cli/index.js"
|
|
35
|
-
},
|
|
36
|
-
"./client": "./client.js",
|
|
37
|
-
"./package.json": "./package.json",
|
|
38
|
-
"./cordis.patch.yml": "./cordis.patch.yml"
|
|
39
|
-
},
|
|
40
|
-
"files": [
|
|
41
|
-
"dist",
|
|
42
|
-
"config",
|
|
43
|
-
"assets",
|
|
44
|
-
"client.js",
|
|
45
|
-
"cordis.patch.yml",
|
|
46
|
-
"README.md",
|
|
47
|
-
"LICENSE"
|
|
48
|
-
],
|
|
49
|
-
"engines": {
|
|
50
|
-
"node": ">=22.19.0"
|
|
51
|
-
},
|
|
52
|
-
"os": [
|
|
53
|
-
"win32"
|
|
54
|
-
],
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"@deepseek-ai/dsh-settings": "^0.1.1-rc.2 || ^0.1.5-rc.2 || ^0.1.7-rc.1 || ^0.2.0-rc.1"
|
|
57
|
-
},
|
|
58
|
-
"peerDependencies": {
|
|
59
|
-
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2 || ^0.1.5-rc.2 || ^0.1.7-rc.1 || ^0.2.0-rc.1"
|
|
60
|
-
},
|
|
61
|
-
"devDependencies": {
|
|
62
|
-
"@deepseek-ai/dsh-llm": "^0.1.7-rc.1",
|
|
63
|
-
"@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
|
|
64
|
-
"@deepseek-ai/schemastery": "^3.18.2",
|
|
65
|
-
"@types/node": "^24.0.0",
|
|
66
|
-
"tsup": "^8.3.0",
|
|
67
|
-
"tsx": "^4.19.0",
|
|
68
|
-
"typescript": "^5.7.0"
|
|
69
|
-
},
|
|
70
|
-
"scripts": {
|
|
71
|
-
"build": "tsup",
|
|
72
|
-
"typecheck": "tsc --noEmit",
|
|
73
|
-
"test": "node --import tsx --test \"tests/*.test.ts\""
|
|
74
|
-
},
|
|
75
|
-
"dsh": {
|
|
76
|
-
"bundle": {
|
|
77
|
-
"patch": "./cordis.patch.yml"
|
|
78
|
-
},
|
|
79
|
-
"client": {
|
|
80
|
-
"platform": "web"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@kanadego/dsh-heartbeat",
|
|
3
|
+
"version": "1.9.2",
|
|
4
|
+
"description": "Heartbeat plugin for DeepSeek Harness: scheduled autonomous reflection loop with user profile, material pool, pace gate, and gated proactive expression.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Kanadego/dsh-heartbeat.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/Kanadego/dsh-heartbeat",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/Kanadego/dsh-heartbeat/issues"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"dsh",
|
|
15
|
+
"dsh-plugin",
|
|
16
|
+
"deepseek-harness",
|
|
17
|
+
"heartbeat",
|
|
18
|
+
"proactive",
|
|
19
|
+
"agent"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"registry": "https://registry.npmjs.org"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./cli": {
|
|
33
|
+
"types": "./dist/cli/index.d.ts",
|
|
34
|
+
"default": "./dist/cli/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./client": "./client.js",
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
"./cordis.patch.yml": "./cordis.patch.yml"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"config",
|
|
43
|
+
"assets",
|
|
44
|
+
"client.js",
|
|
45
|
+
"cordis.patch.yml",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE"
|
|
48
|
+
],
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22.19.0"
|
|
51
|
+
},
|
|
52
|
+
"os": [
|
|
53
|
+
"win32"
|
|
54
|
+
],
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@deepseek-ai/dsh-settings": "^0.1.1-rc.2 || ^0.1.5-rc.2 || ^0.1.7-rc.1 || ^0.2.0-rc.1"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2 || ^0.1.5-rc.2 || ^0.1.7-rc.1 || ^0.2.0-rc.1"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
|
|
64
|
+
"@deepseek-ai/schemastery": "^3.18.2",
|
|
65
|
+
"@types/node": "^24.0.0",
|
|
66
|
+
"tsup": "^8.3.0",
|
|
67
|
+
"tsx": "^4.19.0",
|
|
68
|
+
"typescript": "^5.7.0"
|
|
69
|
+
},
|
|
70
|
+
"scripts": {
|
|
71
|
+
"build": "tsup",
|
|
72
|
+
"typecheck": "tsc --noEmit",
|
|
73
|
+
"test": "node --import tsx --test \"tests/*.test.ts\""
|
|
74
|
+
},
|
|
75
|
+
"dsh": {
|
|
76
|
+
"bundle": {
|
|
77
|
+
"patch": "./cordis.patch.yml"
|
|
78
|
+
},
|
|
79
|
+
"client": {
|
|
80
|
+
"platform": "web"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
package/dist/chunk-7TW6DD6Q.js
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
burnFileSync
|
|
3
|
-
} from "./chunk-WRUTATW4.js";
|
|
4
|
-
|
|
5
|
-
// src/core/paths.ts
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import { fileURLToPath } from "url";
|
|
9
|
-
var resolved = null;
|
|
10
|
-
function findPackageRoot(startFile) {
|
|
11
|
-
let dir = path.dirname(path.resolve(startFile));
|
|
12
|
-
for (; ; ) {
|
|
13
|
-
if (fs.existsSync(path.join(dir, "package.json"))) return dir;
|
|
14
|
-
const parent = path.dirname(dir);
|
|
15
|
-
if (parent === dir) throw new Error("package.json not found above " + startFile);
|
|
16
|
-
dir = parent;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function packageRoot() {
|
|
20
|
-
return findPackageRoot(fileURLToPath(import.meta.url));
|
|
21
|
-
}
|
|
22
|
-
function initWorkspace(config = {}) {
|
|
23
|
-
if (resolved) return resolved;
|
|
24
|
-
const root = packageRoot();
|
|
25
|
-
const dataDir = path.resolve(
|
|
26
|
-
process.env.HEARTBEAT_DATA_DIR || config.dataDir || path.join(root, "data")
|
|
27
|
-
);
|
|
28
|
-
const paths = {
|
|
29
|
-
dataDir,
|
|
30
|
-
settingsDir: path.join(dataDir, "settings"),
|
|
31
|
-
logsDir: path.join(dataDir, "logs"),
|
|
32
|
-
tmpDir: path.join(dataDir, "tmp"),
|
|
33
|
-
exportsDir: path.join(dataDir, "exports"),
|
|
34
|
-
packageRoot: root,
|
|
35
|
-
configDir: path.join(root, "config"),
|
|
36
|
-
assetsDir: path.join(root, "assets")
|
|
37
|
-
};
|
|
38
|
-
for (const dir of [
|
|
39
|
-
paths.dataDir,
|
|
40
|
-
paths.settingsDir,
|
|
41
|
-
paths.logsDir,
|
|
42
|
-
paths.tmpDir,
|
|
43
|
-
paths.exportsDir
|
|
44
|
-
]) {
|
|
45
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
46
|
-
}
|
|
47
|
-
resolved = paths;
|
|
48
|
-
return paths;
|
|
49
|
-
}
|
|
50
|
-
function workspace() {
|
|
51
|
-
if (!resolved) throw new Error("workspace not initialized: call initWorkspace() first");
|
|
52
|
-
return resolved;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/vault/vault.ts
|
|
56
|
-
import fs2 from "fs";
|
|
57
|
-
import path2 from "path";
|
|
58
|
-
import { spawnSync } from "child_process";
|
|
59
|
-
import { randomUUID } from "crypto";
|
|
60
|
-
var MAGIC = Buffer.from("KHBV1", "ascii");
|
|
61
|
-
var VAULT_TIMEOUT_MS = 3e4;
|
|
62
|
-
var cachedScriptPath = null;
|
|
63
|
-
function vaultScriptPath() {
|
|
64
|
-
if (cachedScriptPath) return cachedScriptPath;
|
|
65
|
-
const script = path2.join(workspace().assetsDir, "vault.ps1");
|
|
66
|
-
if (!fs2.existsSync(script)) throw new Error(`vault script missing: ${script}`);
|
|
67
|
-
cachedScriptPath = script;
|
|
68
|
-
return script;
|
|
69
|
-
}
|
|
70
|
-
function tmpPlainName(target) {
|
|
71
|
-
return path2.join(workspace().tmpDir, `.${path2.basename(target)}.${randomUUID().slice(0, 8)}.plain`);
|
|
72
|
-
}
|
|
73
|
-
function tmpEncName(target) {
|
|
74
|
-
return path2.join(workspace().tmpDir, `.${path2.basename(target)}.${randomUUID().slice(0, 8)}.enc`);
|
|
75
|
-
}
|
|
76
|
-
function runVault(guard, args) {
|
|
77
|
-
const r = spawnSync(
|
|
78
|
-
"powershell.exe",
|
|
79
|
-
["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", vaultScriptPath(), ...args],
|
|
80
|
-
{ timeout: VAULT_TIMEOUT_MS, encoding: "utf8" }
|
|
81
|
-
);
|
|
82
|
-
if (r.error) throw new Error(`vault spawn failed: ${String(r.error)}`);
|
|
83
|
-
if (r.status !== 0) {
|
|
84
|
-
const detail = (r.stderr || r.stdout || "").trim().split("\n").slice(-3).join("; ");
|
|
85
|
-
throw new Error(`vault ${args[0]} failed (exit ${r.status}): ${detail}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function isEncrypted(file) {
|
|
89
|
-
if (!fs2.existsSync(file)) return false;
|
|
90
|
-
const fd = fs2.openSync(file, "r");
|
|
91
|
-
try {
|
|
92
|
-
const hdr = Buffer.alloc(MAGIC.length);
|
|
93
|
-
const read = fs2.readSync(fd, hdr, 0, hdr.length, 0);
|
|
94
|
-
return read === MAGIC.length && hdr.equals(MAGIC);
|
|
95
|
-
} finally {
|
|
96
|
-
fs2.closeSync(fd);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function loadJson(guard, file) {
|
|
100
|
-
const f = guard.assert(file);
|
|
101
|
-
if (!fs2.existsSync(f)) return null;
|
|
102
|
-
if (!isEncrypted(f)) {
|
|
103
|
-
try {
|
|
104
|
-
return JSON.parse(fs2.readFileSync(f, "utf8"));
|
|
105
|
-
} catch {
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
const tmp = tmpPlainName(f);
|
|
110
|
-
try {
|
|
111
|
-
runVault(guard, ["unprotect", "-InFile", f, "-OutFile", tmp]);
|
|
112
|
-
return JSON.parse(fs2.readFileSync(tmp, "utf8"));
|
|
113
|
-
} finally {
|
|
114
|
-
burnFileSync(tmp);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function saveJson(guard, file, value) {
|
|
118
|
-
const f = guard.assert(file);
|
|
119
|
-
fs2.mkdirSync(path2.dirname(f), { recursive: true });
|
|
120
|
-
const plain = tmpPlainName(f);
|
|
121
|
-
const enc = tmpEncName(f);
|
|
122
|
-
try {
|
|
123
|
-
fs2.writeFileSync(plain, JSON.stringify(value, null, 2), "utf8");
|
|
124
|
-
runVault(guard, ["protect", "-InFile", plain, "-OutFile", enc]);
|
|
125
|
-
fs2.renameSync(enc, f);
|
|
126
|
-
} finally {
|
|
127
|
-
burnFileSync(plain);
|
|
128
|
-
fs2.rmSync(enc, { force: true });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
function readText(guard, file, fallback = "") {
|
|
132
|
-
const f = guard.assert(file);
|
|
133
|
-
try {
|
|
134
|
-
return fs2.readFileSync(f, "utf8");
|
|
135
|
-
} catch {
|
|
136
|
-
return fallback;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
function writeText(guard, file, content) {
|
|
140
|
-
const f = guard.assert(file);
|
|
141
|
-
fs2.mkdirSync(path2.dirname(f), { recursive: true });
|
|
142
|
-
const tmp = tmpPlainName(f);
|
|
143
|
-
try {
|
|
144
|
-
fs2.writeFileSync(tmp, content, "utf8");
|
|
145
|
-
fs2.renameSync(tmp, f);
|
|
146
|
-
} finally {
|
|
147
|
-
burnFileSync(tmp);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function loadEncryptedText(guard, file) {
|
|
151
|
-
const f = guard.assert(file);
|
|
152
|
-
if (!fs2.existsSync(f)) return null;
|
|
153
|
-
if (!isEncrypted(f)) return fs2.readFileSync(f, "utf8");
|
|
154
|
-
const tmp = tmpPlainName(f);
|
|
155
|
-
try {
|
|
156
|
-
runVault(guard, ["unprotect", "-InFile", f, "-OutFile", tmp]);
|
|
157
|
-
return fs2.readFileSync(tmp, "utf8");
|
|
158
|
-
} finally {
|
|
159
|
-
burnFileSync(tmp);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function saveEncryptedText(guard, file, content) {
|
|
163
|
-
const f = guard.assert(file);
|
|
164
|
-
fs2.mkdirSync(path2.dirname(f), { recursive: true });
|
|
165
|
-
const plain = tmpPlainName(f);
|
|
166
|
-
const enc = tmpEncName(f);
|
|
167
|
-
try {
|
|
168
|
-
fs2.writeFileSync(plain, content, "utf8");
|
|
169
|
-
runVault(guard, ["protect", "-InFile", plain, "-OutFile", enc]);
|
|
170
|
-
fs2.renameSync(enc, f);
|
|
171
|
-
} finally {
|
|
172
|
-
burnFileSync(plain);
|
|
173
|
-
fs2.rmSync(enc, { force: true });
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
function encryptFile(guard, inFile, outFile) {
|
|
177
|
-
const inPath = guard.assert(inFile);
|
|
178
|
-
const outPath = guard.assert(outFile);
|
|
179
|
-
fs2.mkdirSync(path2.dirname(outPath), { recursive: true });
|
|
180
|
-
const enc = tmpEncName(outPath);
|
|
181
|
-
try {
|
|
182
|
-
runVault(guard, ["protect", "-InFile", inPath, "-OutFile", enc]);
|
|
183
|
-
fs2.renameSync(enc, outPath);
|
|
184
|
-
} finally {
|
|
185
|
-
fs2.rmSync(enc, { force: true });
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
function decryptFile(guard, inFile, outFile) {
|
|
189
|
-
const inPath = guard.assert(inFile);
|
|
190
|
-
const outPath = guard.assert(outFile);
|
|
191
|
-
fs2.mkdirSync(path2.dirname(outPath), { recursive: true });
|
|
192
|
-
runVault(guard, ["unprotect", "-InFile", inPath, "-OutFile", outPath]);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export {
|
|
196
|
-
initWorkspace,
|
|
197
|
-
workspace,
|
|
198
|
-
isEncrypted,
|
|
199
|
-
loadJson,
|
|
200
|
-
saveJson,
|
|
201
|
-
readText,
|
|
202
|
-
writeText,
|
|
203
|
-
loadEncryptedText,
|
|
204
|
-
saveEncryptedText,
|
|
205
|
-
encryptFile,
|
|
206
|
-
decryptFile
|
|
207
|
-
};
|
|
208
|
-
//# sourceMappingURL=chunk-7TW6DD6Q.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/paths.ts","../src/vault/vault.ts"],"sourcesContent":["// Workspace/data directory resolution and package asset location.\n//\n// The data dir is the ONLY directory the plugin writes to at runtime\n// (requirement 8). Resolution order: env override > plugin config > default\n// (packageRoot/data). All fs writes must go through the path guard created\n// from this dir (see core/path-guard.ts).\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport interface WorkspacePaths {\n /** Guard boundary and the only writable tree at runtime. */\n dataDir: string;\n settingsDir: string;\n logsDir: string;\n tmpDir: string;\n exportsDir: string;\n /** Package root (where package.json lives). Read-only at runtime. */\n packageRoot: string;\n configDir: string;\n assetsDir: string;\n}\n\nexport interface WorkspaceConfigInput {\n dataDir?: string | null;\n}\n\nlet resolved: WorkspacePaths | null = null;\n\n/** Walk up from a module file to the directory containing package.json. */\nexport function findPackageRoot(startFile: string): string {\n let dir = path.dirname(path.resolve(startFile));\n for (;;) {\n if (fs.existsSync(path.join(dir, 'package.json'))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) throw new Error('package.json not found above ' + startFile);\n dir = parent;\n }\n}\n\nexport function packageRoot(): string {\n return findPackageRoot(fileURLToPath(import.meta.url));\n}\n\n/**\n * Resolve and create the workspace layout. Idempotent; must be called once\n * from the plugin entry before any fs write happens.\n */\nexport function initWorkspace(config: WorkspaceConfigInput = {}): WorkspacePaths {\n if (resolved) return resolved;\n const root = packageRoot();\n const dataDir = path.resolve(\n process.env.HEARTBEAT_DATA_DIR || config.dataDir || path.join(root, 'data'),\n );\n const paths: WorkspacePaths = {\n dataDir,\n settingsDir: path.join(dataDir, 'settings'),\n logsDir: path.join(dataDir, 'logs'),\n tmpDir: path.join(dataDir, 'tmp'),\n exportsDir: path.join(dataDir, 'exports'),\n packageRoot: root,\n configDir: path.join(root, 'config'),\n assetsDir: path.join(root, 'assets'),\n };\n // Bootstrap creation happens before the guard exists; creating exactly one\n // directory tree at a known location is the safe window for this.\n for (const dir of [\n paths.dataDir,\n paths.settingsDir,\n paths.logsDir,\n paths.tmpDir,\n paths.exportsDir,\n ]) {\n fs.mkdirSync(dir, { recursive: true });\n }\n resolved = paths;\n return paths;\n}\n\n/** Access already-initialized paths. Throws if initWorkspace was not called. */\nexport function workspace(): WorkspacePaths {\n if (!resolved) throw new Error('workspace not initialized: call initWorkspace() first');\n return resolved;\n}\n\n/** Test-only: forget the resolved singleton so a later init re-resolves. */\nexport function resetWorkspaceForTest(): void {\n resolved = null;\n}\n","// Transparent encryption read/write layer (port of v1 lib/vault.mjs).\n//\n// Mechanism: Node <-> vault.ps1 hand off through temp files (plain text\n// windows are millisecond-scale). v2 hardening over v1:\n// - plaintext temp files live ONLY under data/tmp (never beside targets);\n// - every path passes the workspace guard before reaching PowerShell;\n// - encrypted output lands via same-volume rename (atomic replace).\n// Encryption failure is fail-closed: throw, never fall back to plaintext.\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport type { PathGuard } from '../core/path-guard.js';\nimport { workspace } from '../core/paths.js';\nimport { burnFileSync } from '../core/atomic-fs.js';\n\nconst MAGIC = Buffer.from('KHBV1', 'ascii');\nconst VAULT_TIMEOUT_MS = 30_000;\n\nlet cachedScriptPath: string | null = null;\n\nfunction vaultScriptPath(): string {\n if (cachedScriptPath) return cachedScriptPath;\n const script = path.join(workspace().assetsDir, 'vault.ps1');\n if (!fs.existsSync(script)) throw new Error(`vault script missing: ${script}`);\n cachedScriptPath = script;\n return script;\n}\n\nfunction tmpPlainName(target: string): string {\n return path.join(workspace().tmpDir, `.${path.basename(target)}.${randomUUID().slice(0, 8)}.plain`);\n}\n\nfunction tmpEncName(target: string): string {\n return path.join(workspace().tmpDir, `.${path.basename(target)}.${randomUUID().slice(0, 8)}.enc`);\n}\n\nfunction runVault(guard: PathGuard, args: string[]): void {\n const r = spawnSync(\n 'powershell.exe',\n ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', vaultScriptPath(), ...args],\n { timeout: VAULT_TIMEOUT_MS, encoding: 'utf8' },\n );\n if (r.error) throw new Error(`vault spawn failed: ${String(r.error)}`);\n if (r.status !== 0) {\n const detail = (r.stderr || r.stdout || '').trim().split('\\n').slice(-3).join('; ');\n throw new Error(`vault ${args[0]} failed (exit ${r.status}): ${detail}`);\n }\n}\n\n/** KHBV1 header check without reading the whole file. */\nexport function isEncrypted(file: string): boolean {\n if (!fs.existsSync(file)) return false;\n const fd = fs.openSync(file, 'r');\n try {\n const hdr = Buffer.alloc(MAGIC.length);\n const read = fs.readSync(fd, hdr, 0, hdr.length, 0);\n return read === MAGIC.length && hdr.equals(MAGIC);\n } finally {\n fs.closeSync(fd);\n }\n}\n\n/**\n * Read JSON: encrypted files are decrypted to a data/tmp plaintext window\n * that is shredded immediately after parse; plaintext stays compatible.\n */\nexport function loadJson<T>(guard: PathGuard, file: string): T | null {\n const f = guard.assert(file);\n if (!fs.existsSync(f)) return null;\n if (!isEncrypted(f)) {\n try {\n return JSON.parse(fs.readFileSync(f, 'utf8')) as T;\n } catch {\n return null;\n }\n }\n const tmp = tmpPlainName(f);\n try {\n runVault(guard, ['unprotect', '-InFile', f, '-OutFile', tmp]);\n return JSON.parse(fs.readFileSync(tmp, 'utf8')) as T;\n } finally {\n burnFileSync(tmp);\n }\n}\n\n/** Write JSON: plaintext window in data/tmp -> DPAPI encrypt -> atomic rename into place. */\nexport function saveJson(guard: PathGuard, file: string, value: unknown): void {\n const f = guard.assert(file);\n fs.mkdirSync(path.dirname(f), { recursive: true });\n const plain = tmpPlainName(f);\n const enc = tmpEncName(f);\n try {\n fs.writeFileSync(plain, JSON.stringify(value, null, 2), 'utf8');\n runVault(guard, ['protect', '-InFile', plain, '-OutFile', enc]);\n fs.renameSync(enc, f);\n } finally {\n burnFileSync(plain);\n fs.rmSync(enc, { force: true });\n }\n}\n\n/** Read a plaintext UTF-8 text file (ledger etc.), with fallback. */\nexport function readText(guard: PathGuard, file: string, fallback = ''): string {\n const f = guard.assert(file);\n try {\n return fs.readFileSync(f, 'utf8');\n } catch {\n return fallback;\n }\n}\n\n/** Write a plaintext UTF-8 text file atomically (ledger etc.). */\nexport function writeText(guard: PathGuard, file: string, content: string): void {\n const f = guard.assert(file);\n fs.mkdirSync(path.dirname(f), { recursive: true });\n const tmp = tmpPlainName(f);\n try {\n fs.writeFileSync(tmp, content, 'utf8');\n fs.renameSync(tmp, f);\n } finally {\n burnFileSync(tmp);\n }\n}\n\n/** Read an encrypted UTF-8 text file (e.g. seeds.jsonl). Missing -> null. */\nexport function loadEncryptedText(guard: PathGuard, file: string): string | null {\n const f = guard.assert(file);\n if (!fs.existsSync(f)) return null;\n if (!isEncrypted(f)) return fs.readFileSync(f, 'utf8');\n const tmp = tmpPlainName(f);\n try {\n runVault(guard, ['unprotect', '-InFile', f, '-OutFile', tmp]);\n return fs.readFileSync(tmp, 'utf8');\n } finally {\n burnFileSync(tmp);\n }\n}\n\n/** Write an encrypted UTF-8 text file atomically. */\nexport function saveEncryptedText(guard: PathGuard, file: string, content: string): void {\n const f = guard.assert(file);\n fs.mkdirSync(path.dirname(f), { recursive: true });\n const plain = tmpPlainName(f);\n const enc = tmpEncName(f);\n try {\n fs.writeFileSync(plain, content, 'utf8');\n runVault(guard, ['protect', '-InFile', plain, '-OutFile', enc]);\n fs.renameSync(enc, f);\n } finally {\n burnFileSync(plain);\n fs.rmSync(enc, { force: true });\n }\n}\n\n/** Encrypt any binary file (e.g. screenshot): inFile -> encrypted outFile. */\nexport function encryptFile(guard: PathGuard, inFile: string, outFile: string): void {\n const inPath = guard.assert(inFile);\n const outPath = guard.assert(outFile);\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n const enc = tmpEncName(outPath);\n try {\n runVault(guard, ['protect', '-InFile', inPath, '-OutFile', enc]);\n fs.renameSync(enc, outPath);\n } finally {\n fs.rmSync(enc, { force: true });\n }\n}\n\n/**\n * Decrypt an encrypted file to a plaintext output (caller must place the\n * output under data/tmp and delete it after use; \"use then burn\" discipline).\n */\nexport function decryptFile(guard: PathGuard, inFile: string, outFile: string): void {\n const inPath = guard.assert(inFile);\n const outPath = guard.assert(outFile);\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n runVault(guard, ['unprotect', '-InFile', inPath, '-OutFile', outPath]);\n}\n"],"mappings":"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","names":["fs","path","path","fs"]}
|