@sumicom/quicksave 0.6.2 → 0.6.4
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 +27 -0
- package/dist/ai/cardBuilder.d.ts.map +1 -1
- package/dist/ai/cardBuilder.js +72 -5
- package/dist/ai/cardBuilder.js.map +1 -1
- package/dist/ai/claudeCliProvider.d.ts +1 -0
- package/dist/ai/claudeCliProvider.d.ts.map +1 -1
- package/dist/ai/claudeCliProvider.js +187 -21
- package/dist/ai/claudeCliProvider.js.map +1 -1
- package/dist/ai/claudeSdkProvider.d.ts.map +1 -1
- package/dist/ai/claudeSdkProvider.js +17 -6
- package/dist/ai/claudeSdkProvider.js.map +1 -1
- package/dist/ai/commitSummary.d.ts.map +1 -1
- package/dist/ai/commitSummary.js +37 -9
- package/dist/ai/commitSummary.js.map +1 -1
- package/dist/ai/commitSummaryCli.d.ts +67 -0
- package/dist/ai/commitSummaryCli.d.ts.map +1 -0
- package/dist/ai/commitSummaryCli.js +416 -0
- package/dist/ai/commitSummaryCli.js.map +1 -0
- package/dist/ai/commitSummaryStore.d.ts +53 -0
- package/dist/ai/commitSummaryStore.d.ts.map +1 -0
- package/dist/ai/commitSummaryStore.js +136 -0
- package/dist/ai/commitSummaryStore.js.map +1 -0
- 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/provider.d.ts +7 -2
- package/dist/ai/provider.d.ts.map +1 -1
- package/dist/ai/sessionManager.d.ts +14 -2
- package/dist/ai/sessionManager.d.ts.map +1 -1
- package/dist/ai/sessionManager.js +143 -31
- 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 +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -15
- package/dist/config.js.map +1 -1
- package/dist/handlers/messageHandler.d.ts +34 -0
- package/dist/handlers/messageHandler.d.ts.map +1 -1
- package/dist/handlers/messageHandler.js +513 -161
- package/dist/handlers/messageHandler.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/service/ipcClient.js +1 -1
- package/dist/service/pushClient.d.ts +69 -0
- package/dist/service/pushClient.d.ts.map +1 -0
- package/dist/service/pushClient.js +119 -0
- package/dist/service/pushClient.js.map +1 -0
- package/dist/service/run.d.ts.map +1 -1
- package/dist/service/run.js +102 -15
- package/dist/service/run.js.map +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.d.ts +1 -0
- package/dist/service/types.d.ts.map +1 -1
- package/dist/service/types.js +1 -1
- package/dist/service/types.js.map +1 -1
- package/dist/storage/eventStore.d.ts +65 -0
- package/dist/storage/eventStore.d.ts.map +1 -0
- package/dist/storage/eventStore.js +122 -0
- package/dist/storage/eventStore.js.map +1 -0
- package/package.json +6 -3
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event store — append-only SQLite log of session activity.
|
|
3
|
+
*
|
|
4
|
+
* Storage: ~/.quicksave/state/quicksave.db
|
|
5
|
+
*
|
|
6
|
+
* Schema:
|
|
7
|
+
* events (id, time, session_id, cwd, type, data)
|
|
8
|
+
* Indexes on (session_id, time), (type, time), (time).
|
|
9
|
+
*
|
|
10
|
+
* Intended as a long-lived audit/analytics log. Derived stats (cumulative
|
|
11
|
+
* tokens, cost, last prompt time) are computed via aggregate queries.
|
|
12
|
+
*/
|
|
13
|
+
import Database from 'better-sqlite3';
|
|
14
|
+
import { mkdirSync, existsSync } from 'fs';
|
|
15
|
+
import { join, dirname } from 'path';
|
|
16
|
+
import { getStateDir } from '../service/singleton.js';
|
|
17
|
+
export class EventStore {
|
|
18
|
+
db;
|
|
19
|
+
insertStmt;
|
|
20
|
+
statsStmt;
|
|
21
|
+
lastPromptStmt;
|
|
22
|
+
sessionEventsStmt;
|
|
23
|
+
lastTurnStmt;
|
|
24
|
+
constructor(dbPath) {
|
|
25
|
+
const dir = dirname(dbPath);
|
|
26
|
+
if (!existsSync(dir))
|
|
27
|
+
mkdirSync(dir, { recursive: true });
|
|
28
|
+
this.db = new Database(dbPath);
|
|
29
|
+
this.db.pragma('journal_mode = WAL');
|
|
30
|
+
this.db.pragma('synchronous = NORMAL');
|
|
31
|
+
this.db.exec(`
|
|
32
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
33
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
34
|
+
time INTEGER NOT NULL,
|
|
35
|
+
session_id TEXT,
|
|
36
|
+
cwd TEXT,
|
|
37
|
+
type TEXT NOT NULL,
|
|
38
|
+
data TEXT
|
|
39
|
+
);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_events_session_time ON events(session_id, time);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_events_type_time ON events(type, time);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_events_time ON events(time);
|
|
43
|
+
`);
|
|
44
|
+
this.insertStmt = this.db.prepare('INSERT INTO events (time, session_id, cwd, type, data) VALUES (?, ?, ?, ?, ?)');
|
|
45
|
+
this.statsStmt = this.db.prepare(`
|
|
46
|
+
SELECT
|
|
47
|
+
COUNT(*) AS turnCount,
|
|
48
|
+
COALESCE(SUM(CAST(json_extract(data, '$.inputTokens') AS INTEGER)), 0) AS totalInputTokens,
|
|
49
|
+
COALESCE(SUM(CAST(json_extract(data, '$.outputTokens') AS INTEGER)), 0) AS totalOutputTokens,
|
|
50
|
+
COALESCE(SUM(CAST(json_extract(data, '$.costUsd') AS REAL)), 0) AS totalCostUsd,
|
|
51
|
+
MAX(time) AS lastTurnEndedAt
|
|
52
|
+
FROM events
|
|
53
|
+
WHERE session_id = ? AND type = 'turn_ended'
|
|
54
|
+
`);
|
|
55
|
+
this.lastPromptStmt = this.db.prepare(`SELECT MAX(time) AS lastPromptAt FROM events WHERE session_id = ? AND type = 'prompt_sent'`);
|
|
56
|
+
this.sessionEventsStmt = this.db.prepare(`SELECT id, time, session_id, cwd, type, data FROM events WHERE session_id = ? ORDER BY time ASC, id ASC LIMIT ? OFFSET ?`);
|
|
57
|
+
this.lastTurnStmt = this.db.prepare(`SELECT time, data FROM events WHERE session_id = ? AND type = 'turn_ended' ORDER BY time DESC, id DESC LIMIT 1`);
|
|
58
|
+
}
|
|
59
|
+
record(params) {
|
|
60
|
+
const time = params.time ?? Date.now();
|
|
61
|
+
const data = params.data === undefined ? null : JSON.stringify(params.data);
|
|
62
|
+
this.insertStmt.run(time, params.sessionId ?? null, params.cwd ?? null, params.type, data);
|
|
63
|
+
}
|
|
64
|
+
getSessionStats(sessionId) {
|
|
65
|
+
const turnRow = this.statsStmt.get(sessionId);
|
|
66
|
+
const promptRow = this.lastPromptStmt.get(sessionId);
|
|
67
|
+
return {
|
|
68
|
+
turnCount: turnRow.turnCount,
|
|
69
|
+
totalInputTokens: turnRow.totalInputTokens,
|
|
70
|
+
totalOutputTokens: turnRow.totalOutputTokens,
|
|
71
|
+
totalCostUsd: turnRow.totalCostUsd,
|
|
72
|
+
lastPromptAt: promptRow.lastPromptAt,
|
|
73
|
+
lastTurnEndedAt: turnRow.lastTurnEndedAt,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
getSessionEvents(sessionId, limit = 500, offset = 0) {
|
|
77
|
+
const rows = this.sessionEventsStmt.all(sessionId, limit, offset);
|
|
78
|
+
return rows.map(rowToRecord);
|
|
79
|
+
}
|
|
80
|
+
getLastTurn(sessionId) {
|
|
81
|
+
const row = this.lastTurnStmt.get(sessionId);
|
|
82
|
+
if (!row)
|
|
83
|
+
return null;
|
|
84
|
+
const data = row.data ? JSON.parse(row.data) : {};
|
|
85
|
+
return {
|
|
86
|
+
time: row.time,
|
|
87
|
+
inputTokens: Number(data.inputTokens ?? 0),
|
|
88
|
+
outputTokens: Number(data.outputTokens ?? 0),
|
|
89
|
+
cacheCreationTokens: Number(data.cacheCreationTokens ?? 0),
|
|
90
|
+
cacheReadTokens: Number(data.cacheReadTokens ?? 0),
|
|
91
|
+
costUsd: Number(data.costUsd ?? 0),
|
|
92
|
+
contextUsage: data.contextUsage ?? undefined,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
close() {
|
|
96
|
+
this.db.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function rowToRecord(row) {
|
|
100
|
+
return {
|
|
101
|
+
id: row.id,
|
|
102
|
+
time: row.time,
|
|
103
|
+
sessionId: row.session_id,
|
|
104
|
+
cwd: row.cwd,
|
|
105
|
+
type: row.type,
|
|
106
|
+
data: row.data ? JSON.parse(row.data) : null,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
let instance = null;
|
|
110
|
+
export function getEventStore() {
|
|
111
|
+
if (!instance) {
|
|
112
|
+
instance = new EventStore(join(getStateDir(), 'quicksave.db'));
|
|
113
|
+
}
|
|
114
|
+
return instance;
|
|
115
|
+
}
|
|
116
|
+
/** Reset the singleton — only for tests. */
|
|
117
|
+
export function resetEventStore() {
|
|
118
|
+
if (instance)
|
|
119
|
+
instance.close();
|
|
120
|
+
instance = null;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=eventStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventStore.js","sourceRoot":"","sources":["../../src/storage/eventStore.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sumicom/quicksave",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Quicksave agent - remote git control CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,14 +34,17 @@
|
|
|
34
34
|
"@anthropic-ai/sdk": "^0.71.2",
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
36
36
|
"@openai/codex-sdk": "^0.120.0",
|
|
37
|
+
"better-sqlite3": "^12.9.0",
|
|
37
38
|
"commander": "^12.0.0",
|
|
38
39
|
"qrcode-terminal": "^0.12.0",
|
|
39
40
|
"simple-git": "^3.22.0",
|
|
41
|
+
"tweetnacl": "^1.0.3",
|
|
40
42
|
"ws": "^8.16.0",
|
|
41
43
|
"zod": "^4.3.6",
|
|
42
|
-
"@sumicom/quicksave-shared": "0.6.
|
|
44
|
+
"@sumicom/quicksave-shared": "0.6.4"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
47
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
45
48
|
"@types/node": "^20.11.0",
|
|
46
49
|
"@types/ws": "^8.5.10",
|
|
47
50
|
"@vitest/coverage-v8": "^1.6.1",
|
|
@@ -51,7 +54,7 @@
|
|
|
51
54
|
},
|
|
52
55
|
"scripts": {
|
|
53
56
|
"dev": "tsx watch src/index.ts",
|
|
54
|
-
"build": "tsc",
|
|
57
|
+
"build": "tsc && node scripts/stamp-build-id.js",
|
|
55
58
|
"start": "node dist/index.js",
|
|
56
59
|
"typecheck": "tsc --noEmit",
|
|
57
60
|
"test": "vitest run",
|