@sumicom/quicksave 0.6.2 → 0.6.3
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/dist/ai/cardBuilder.d.ts.map +1 -1
- package/dist/ai/cardBuilder.js +3 -5
- package/dist/ai/cardBuilder.js.map +1 -1
- package/dist/ai/claudeCliProvider.d.ts.map +1 -1
- package/dist/ai/claudeCliProvider.js +52 -3
- package/dist/ai/claudeCliProvider.js.map +1 -1
- package/dist/ai/debugLogger.d.ts.map +1 -1
- package/dist/ai/debugLogger.js +3 -4
- package/dist/ai/debugLogger.js.map +1 -1
- package/dist/ai/sessionManager.d.ts.map +1 -1
- package/dist/ai/sessionManager.js +2 -1
- package/dist/ai/sessionManager.js.map +1 -1
- package/dist/ai/sessionRegistry.d.ts +2 -0
- package/dist/ai/sessionRegistry.d.ts.map +1 -1
- package/dist/ai/sessionRegistry.js +4 -0
- package/dist/ai/sessionRegistry.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -10
- package/dist/config.js.map +1 -1
- package/dist/handlers/messageHandler.d.ts +2 -0
- package/dist/handlers/messageHandler.d.ts.map +1 -1
- package/dist/handlers/messageHandler.js +132 -2
- package/dist/handlers/messageHandler.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/service/ipcClient.js +1 -1
- package/dist/service/run.js +1 -1
- package/dist/service/singleton.d.ts +18 -1
- package/dist/service/singleton.d.ts.map +1 -1
- package/dist/service/singleton.js +43 -18
- package/dist/service/singleton.js.map +1 -1
- package/dist/service/types.js +1 -1
- package/package.json +3 -3
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Singleton lock for ensuring exactly one daemon per user.
|
|
3
3
|
*
|
|
4
|
-
* Uses an exclusive lock file at
|
|
4
|
+
* Uses an exclusive lock file at <quicksaveDir>/run/service.lock.
|
|
5
5
|
* The lock is held via an open file descriptor — if the process crashes,
|
|
6
6
|
* the OS releases the lock automatically.
|
|
7
|
+
*
|
|
8
|
+
* All paths derive from a single configurable base directory:
|
|
9
|
+
* - Default: ~/.quicksave
|
|
10
|
+
* - Override: QUICKSAVE_HOME env var, or setQuicksaveDir() for tests
|
|
7
11
|
*/
|
|
8
12
|
import { openSync, closeSync, writeSync, readFileSync, mkdirSync, existsSync, unlinkSync, constants } from 'fs';
|
|
9
13
|
import { join } from 'path';
|
|
10
14
|
import { homedir } from 'os';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
let _quicksaveDir = process.env.QUICKSAVE_HOME || join(homedir(), '.quicksave');
|
|
16
|
+
/**
|
|
17
|
+
* Get the quicksave base directory.
|
|
18
|
+
* All other paths derive from this.
|
|
19
|
+
*/
|
|
20
|
+
export function getQuicksaveDir() {
|
|
21
|
+
return _quicksaveDir;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Override the base directory. Primarily for tests.
|
|
25
|
+
* Call before any other path function to ensure consistency.
|
|
26
|
+
*/
|
|
27
|
+
export function setQuicksaveDir(dir) {
|
|
28
|
+
_quicksaveDir = dir;
|
|
29
|
+
}
|
|
15
30
|
export function getRunDir() {
|
|
16
|
-
return
|
|
31
|
+
return join(_quicksaveDir, 'run');
|
|
17
32
|
}
|
|
18
33
|
export function getSocketPath() {
|
|
19
|
-
return
|
|
34
|
+
return join(getRunDir(), 'service.sock');
|
|
20
35
|
}
|
|
21
36
|
export function getLockPath() {
|
|
22
|
-
return
|
|
37
|
+
return join(getRunDir(), 'service.lock');
|
|
23
38
|
}
|
|
24
39
|
export function getStateDir() {
|
|
25
|
-
return join(
|
|
40
|
+
return join(_quicksaveDir, 'state');
|
|
26
41
|
}
|
|
27
42
|
export function getSessionsDir() {
|
|
28
43
|
return join(getStateDir(), 'sessions');
|
|
@@ -31,13 +46,22 @@ export function getSessionRegistryDir() {
|
|
|
31
46
|
return join(getStateDir(), 'session-registry');
|
|
32
47
|
}
|
|
33
48
|
export function getLogsDir() {
|
|
34
|
-
return join(
|
|
49
|
+
return join(_quicksaveDir, 'logs');
|
|
50
|
+
}
|
|
51
|
+
export function getDebugDir() {
|
|
52
|
+
return join(_quicksaveDir, 'debug');
|
|
53
|
+
}
|
|
54
|
+
export function getConfigFile() {
|
|
55
|
+
return join(_quicksaveDir, 'agent.json');
|
|
56
|
+
}
|
|
57
|
+
export function getCardHistoryDir() {
|
|
58
|
+
return join(getStateDir(), 'card-history');
|
|
35
59
|
}
|
|
36
60
|
/**
|
|
37
61
|
* Ensure all required directories exist.
|
|
38
62
|
*/
|
|
39
63
|
export function ensureDirectories() {
|
|
40
|
-
for (const dir of [
|
|
64
|
+
for (const dir of [getRunDir(), getStateDir(), getSessionsDir(), getSessionRegistryDir(), getLogsDir()]) {
|
|
41
65
|
if (!existsSync(dir)) {
|
|
42
66
|
mkdirSync(dir, { recursive: true });
|
|
43
67
|
}
|
|
@@ -52,32 +76,33 @@ export function ensureDirectories() {
|
|
|
52
76
|
*/
|
|
53
77
|
export function acquireLock() {
|
|
54
78
|
ensureDirectories();
|
|
79
|
+
const lockFile = getLockPath();
|
|
55
80
|
// Check for stale lock: if lock file exists but PID is dead, remove it
|
|
56
|
-
if (existsSync(
|
|
81
|
+
if (existsSync(lockFile)) {
|
|
57
82
|
try {
|
|
58
|
-
const pidStr = readFileSync(
|
|
83
|
+
const pidStr = readFileSync(lockFile, 'utf-8').trim();
|
|
59
84
|
const pid = parseInt(pidStr, 10);
|
|
60
85
|
if (!isNaN(pid) && !isProcessAlive(pid)) {
|
|
61
86
|
// Stale lock — previous daemon crashed
|
|
62
|
-
unlinkSync(
|
|
87
|
+
unlinkSync(lockFile);
|
|
63
88
|
}
|
|
64
89
|
}
|
|
65
90
|
catch {
|
|
66
91
|
// Can't read lock file — remove it and retry
|
|
67
92
|
try {
|
|
68
|
-
unlinkSync(
|
|
93
|
+
unlinkSync(lockFile);
|
|
69
94
|
}
|
|
70
95
|
catch { /* ignore */ }
|
|
71
96
|
}
|
|
72
97
|
}
|
|
73
98
|
try {
|
|
74
|
-
const fd = openSync(
|
|
99
|
+
const fd = openSync(lockFile, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600);
|
|
75
100
|
// Write our PID so future processes can detect stale locks
|
|
76
101
|
writeSync(fd, Buffer.from(String(process.pid)));
|
|
77
102
|
return () => {
|
|
78
103
|
try {
|
|
79
104
|
closeSync(fd);
|
|
80
|
-
unlinkSync(
|
|
105
|
+
unlinkSync(lockFile);
|
|
81
106
|
}
|
|
82
107
|
catch {
|
|
83
108
|
// Best-effort cleanup
|
|
@@ -95,7 +120,7 @@ export function acquireLock() {
|
|
|
95
120
|
* Remove stale runtime files (lock, socket) when we detect a dead daemon.
|
|
96
121
|
*/
|
|
97
122
|
export function cleanStaleRuntime() {
|
|
98
|
-
for (const file of [
|
|
123
|
+
for (const file of [getLockPath(), getSocketPath()]) {
|
|
99
124
|
try {
|
|
100
125
|
unlinkSync(file);
|
|
101
126
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleton.js","sourceRoot":"","sources":["../../src/service/singleton.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"singleton.js","sourceRoot":"","sources":["../../src/service/singleton.ts"],"names":[],"mappings":"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"}
|
package/dist/service/types.js
CHANGED
|
@@ -18,7 +18,7 @@ export const IPC_VERSION = 1;
|
|
|
18
18
|
* In dev mode (placeholder unreplaced), hashes source file mtimes so the
|
|
19
19
|
* value only changes when code actually changes — avoids spurious daemon restarts.
|
|
20
20
|
*/
|
|
21
|
-
const _PLACEHOLDER = '
|
|
21
|
+
const _PLACEHOLDER = '41525c7e5f3f';
|
|
22
22
|
export const BUILD_ID = _PLACEHOLDER === '__BUILD' + '_ID__'
|
|
23
23
|
? devBuildId()
|
|
24
24
|
: _PLACEHOLDER;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sumicom/quicksave",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Quicksave agent - remote git control CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"simple-git": "^3.22.0",
|
|
40
40
|
"ws": "^8.16.0",
|
|
41
41
|
"zod": "^4.3.6",
|
|
42
|
-
"@sumicom/quicksave-shared": "0.6.
|
|
42
|
+
"@sumicom/quicksave-shared": "0.6.3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^20.11.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"dev": "tsx watch src/index.ts",
|
|
54
|
-
"build": "tsc",
|
|
54
|
+
"build": "tsc && node scripts/stamp-build-id.js",
|
|
55
55
|
"start": "node dist/index.js",
|
|
56
56
|
"typecheck": "tsc --noEmit",
|
|
57
57
|
"test": "vitest run",
|