forkoff 1.0.17 → 1.0.19
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/LICENSE +11 -7
- package/README.md +77 -118
- package/dist/approval.d.ts +1 -0
- package/dist/approval.js +9 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +62 -16
- package/dist/crypto/e2eeManager.d.ts +49 -52
- package/dist/crypto/e2eeManager.js +256 -181
- package/dist/crypto/encryption.d.ts +8 -10
- package/dist/crypto/encryption.js +29 -94
- package/dist/crypto/index.d.ts +10 -0
- package/dist/crypto/index.js +22 -0
- package/dist/crypto/keyExchange.d.ts +6 -20
- package/dist/crypto/keyExchange.js +18 -110
- package/dist/crypto/keyGeneration.d.ts +2 -13
- package/dist/crypto/keyGeneration.js +14 -88
- package/dist/crypto/keyStorage.d.ts +32 -5
- package/dist/crypto/keyStorage.js +152 -8
- package/dist/crypto/sessionPersistence.d.ts +7 -13
- package/dist/crypto/sessionPersistence.js +108 -33
- package/dist/crypto/types.d.ts +24 -3
- package/dist/crypto/types.js +2 -1
- package/dist/crypto/websocketE2EE.d.ts +6 -17
- package/dist/crypto/websocketE2EE.js +21 -38
- package/dist/index.js +203 -280
- package/dist/integration.d.ts +0 -1
- package/dist/integration.js +2 -4
- package/dist/logger.d.ts +15 -0
- package/dist/logger.js +209 -1
- package/dist/server.d.ts +30 -0
- package/dist/server.js +162 -0
- package/dist/startup.js +15 -6
- package/dist/terminal.d.ts +1 -0
- package/dist/terminal.js +94 -1
- package/dist/tools/claude-process.d.ts +8 -0
- package/dist/tools/claude-process.js +199 -26
- package/dist/tools/claude-sessions.d.ts +1 -0
- package/dist/tools/claude-sessions.js +36 -10
- package/dist/tools/detector.js +11 -3
- package/dist/tools/permission-hook.js +94 -27
- package/dist/tools/permission-ipc.d.ts +1 -0
- package/dist/tools/permission-ipc.js +61 -14
- package/dist/transcript-streamer.d.ts +1 -0
- package/dist/transcript-streamer.js +18 -4
- package/dist/usage-tracker.d.ts +45 -0
- package/dist/usage-tracker.js +243 -0
- package/dist/websocket.d.ts +43 -12
- package/dist/websocket.js +418 -214
- package/package.json +5 -4
- package/dist/__tests__/cli-commands.test.d.ts +0 -6
- package/dist/__tests__/cli-commands.test.d.ts.map +0 -1
- package/dist/__tests__/cli-commands.test.js +0 -213
- package/dist/__tests__/cli-commands.test.js.map +0 -1
- package/dist/__tests__/crypto/e2e-integration.test.d.ts +0 -17
- package/dist/__tests__/crypto/e2e-integration.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/e2e-integration.test.js +0 -338
- package/dist/__tests__/crypto/e2e-integration.test.js.map +0 -1
- package/dist/__tests__/crypto/e2eeManager.test.d.ts +0 -2
- package/dist/__tests__/crypto/e2eeManager.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/e2eeManager.test.js +0 -242
- package/dist/__tests__/crypto/e2eeManager.test.js.map +0 -1
- package/dist/__tests__/crypto/encryption.test.d.ts +0 -2
- package/dist/__tests__/crypto/encryption.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/encryption.test.js +0 -116
- package/dist/__tests__/crypto/encryption.test.js.map +0 -1
- package/dist/__tests__/crypto/keyExchange.test.d.ts +0 -2
- package/dist/__tests__/crypto/keyExchange.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/keyExchange.test.js +0 -84
- package/dist/__tests__/crypto/keyExchange.test.js.map +0 -1
- package/dist/__tests__/crypto/keyGeneration.test.d.ts +0 -2
- package/dist/__tests__/crypto/keyGeneration.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/keyGeneration.test.js +0 -61
- package/dist/__tests__/crypto/keyGeneration.test.js.map +0 -1
- package/dist/__tests__/crypto/keyStorage.test.d.ts +0 -2
- package/dist/__tests__/crypto/keyStorage.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/keyStorage.test.js +0 -133
- package/dist/__tests__/crypto/keyStorage.test.js.map +0 -1
- package/dist/__tests__/crypto/websocketIntegration.test.d.ts +0 -2
- package/dist/__tests__/crypto/websocketIntegration.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/websocketIntegration.test.js +0 -259
- package/dist/__tests__/crypto/websocketIntegration.test.js.map +0 -1
- package/dist/__tests__/startup.test.d.ts +0 -11
- package/dist/__tests__/startup.test.d.ts.map +0 -1
- package/dist/__tests__/startup.test.js +0 -241
- package/dist/__tests__/startup.test.js.map +0 -1
- package/dist/__tests__/tools/claude-process.test.d.ts +0 -8
- package/dist/__tests__/tools/claude-process.test.d.ts.map +0 -1
- package/dist/__tests__/tools/claude-process.test.js +0 -430
- package/dist/__tests__/tools/claude-process.test.js.map +0 -1
- package/dist/__tests__/tools/permission-hook.test.d.ts +0 -17
- package/dist/__tests__/tools/permission-hook.test.d.ts.map +0 -1
- package/dist/__tests__/tools/permission-hook.test.js +0 -616
- package/dist/__tests__/tools/permission-hook.test.js.map +0 -1
- package/dist/__tests__/tools/permission-ipc.test.d.ts +0 -11
- package/dist/__tests__/tools/permission-ipc.test.d.ts.map +0 -1
- package/dist/__tests__/tools/permission-ipc.test.js +0 -612
- package/dist/__tests__/tools/permission-ipc.test.js.map +0 -1
- package/dist/__tests__/websocket.test.d.ts +0 -13
- package/dist/__tests__/websocket.test.d.ts.map +0 -1
- package/dist/__tests__/websocket.test.js +0 -204
- package/dist/__tests__/websocket.test.js.map +0 -1
- package/dist/api.d.ts +0 -44
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -76
- package/dist/api.js.map +0 -1
- package/dist/approval.d.ts.map +0 -1
- package/dist/approval.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/crypto/e2eeManager.d.ts.map +0 -1
- package/dist/crypto/e2eeManager.js.map +0 -1
- package/dist/crypto/encryption.d.ts.map +0 -1
- package/dist/crypto/encryption.js.map +0 -1
- package/dist/crypto/keyExchange.d.ts.map +0 -1
- package/dist/crypto/keyExchange.js.map +0 -1
- package/dist/crypto/keyGeneration.d.ts.map +0 -1
- package/dist/crypto/keyGeneration.js.map +0 -1
- package/dist/crypto/keyStorage.d.ts.map +0 -1
- package/dist/crypto/keyStorage.js.map +0 -1
- package/dist/crypto/sessionPersistence.d.ts.map +0 -1
- package/dist/crypto/sessionPersistence.js.map +0 -1
- package/dist/crypto/types.d.ts.map +0 -1
- package/dist/crypto/types.js.map +0 -1
- package/dist/crypto/websocketE2EE.d.ts.map +0 -1
- package/dist/crypto/websocketE2EE.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integration.d.ts.map +0 -1
- package/dist/integration.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/startup.d.ts.map +0 -1
- package/dist/startup.js.map +0 -1
- package/dist/terminal.d.ts.map +0 -1
- package/dist/terminal.js.map +0 -1
- package/dist/tools/__tests__/claude-sessions.test.d.ts +0 -2
- package/dist/tools/__tests__/claude-sessions.test.d.ts.map +0 -1
- package/dist/tools/__tests__/claude-sessions.test.js +0 -306
- package/dist/tools/__tests__/claude-sessions.test.js.map +0 -1
- package/dist/tools/claude-hooks.d.ts.map +0 -1
- package/dist/tools/claude-hooks.js.map +0 -1
- package/dist/tools/claude-process.d.ts.map +0 -1
- package/dist/tools/claude-process.js.map +0 -1
- package/dist/tools/claude-sessions.d.ts.map +0 -1
- package/dist/tools/claude-sessions.js.map +0 -1
- package/dist/tools/detector.d.ts.map +0 -1
- package/dist/tools/detector.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/permission-hook.d.ts.map +0 -1
- package/dist/tools/permission-hook.js.map +0 -1
- package/dist/tools/permission-ipc.d.ts.map +0 -1
- package/dist/tools/permission-ipc.js.map +0 -1
- package/dist/transcript-streamer.d.ts.map +0 -1
- package/dist/transcript-streamer.js.map +0 -1
- package/dist/websocket.d.ts.map +0 -1
- package/dist/websocket.js.map +0 -1
- package/jest.config.js +0 -18
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.UsageTracker = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
function getConfigDir() {
|
|
41
|
+
return process.platform === 'win32'
|
|
42
|
+
? path.join(process.env.APPDATA || os.homedir(), 'forkoff-cli')
|
|
43
|
+
: path.join(os.homedir(), '.config', 'forkoff-cli');
|
|
44
|
+
}
|
|
45
|
+
function getTodayKey() {
|
|
46
|
+
return new Date().toISOString().split('T')[0]; // "YYYY-MM-DD"
|
|
47
|
+
}
|
|
48
|
+
class UsageTracker {
|
|
49
|
+
constructor() {
|
|
50
|
+
this.saveTimer = null;
|
|
51
|
+
this.dirty = false;
|
|
52
|
+
const configDir = getConfigDir();
|
|
53
|
+
if (!fs.existsSync(configDir)) {
|
|
54
|
+
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
55
|
+
}
|
|
56
|
+
this.filePath = path.join(configDir, 'usage.json');
|
|
57
|
+
this.data = this.load();
|
|
58
|
+
}
|
|
59
|
+
load() {
|
|
60
|
+
try {
|
|
61
|
+
if (fs.existsSync(this.filePath)) {
|
|
62
|
+
return JSON.parse(fs.readFileSync(this.filePath, 'utf-8'));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Corrupted file — start fresh
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
daily: {},
|
|
70
|
+
totalInputTokens: 0,
|
|
71
|
+
totalOutputTokens: 0,
|
|
72
|
+
totalSessionCount: 0,
|
|
73
|
+
activeDays: [],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
scheduleSave() {
|
|
77
|
+
this.dirty = true;
|
|
78
|
+
if (this.saveTimer)
|
|
79
|
+
return;
|
|
80
|
+
this.saveTimer = setTimeout(() => {
|
|
81
|
+
this.saveTimer = null;
|
|
82
|
+
if (this.dirty) {
|
|
83
|
+
this.saveNow();
|
|
84
|
+
}
|
|
85
|
+
}, 2000);
|
|
86
|
+
}
|
|
87
|
+
saveNow() {
|
|
88
|
+
try {
|
|
89
|
+
const tmpFile = this.filePath + '.tmp.' + process.pid;
|
|
90
|
+
fs.writeFileSync(tmpFile, JSON.stringify(this.data, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
91
|
+
fs.renameSync(tmpFile, this.filePath);
|
|
92
|
+
this.dirty = false;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
console.error(`[UsageTracker] Failed to save: ${err.message}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
ensureDay(dateKey) {
|
|
99
|
+
if (!this.data.daily[dateKey]) {
|
|
100
|
+
this.data.daily[dateKey] = { inputTokens: 0, outputTokens: 0, sessionCount: 0 };
|
|
101
|
+
if (!this.data.activeDays.includes(dateKey)) {
|
|
102
|
+
this.data.activeDays.push(dateKey);
|
|
103
|
+
this.data.activeDays.sort();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return this.data.daily[dateKey];
|
|
107
|
+
}
|
|
108
|
+
recordUsage(inputTokens, outputTokens) {
|
|
109
|
+
const today = getTodayKey();
|
|
110
|
+
const day = this.ensureDay(today);
|
|
111
|
+
day.inputTokens += inputTokens;
|
|
112
|
+
day.outputTokens += outputTokens;
|
|
113
|
+
this.data.totalInputTokens += inputTokens;
|
|
114
|
+
this.data.totalOutputTokens += outputTokens;
|
|
115
|
+
this.scheduleSave();
|
|
116
|
+
}
|
|
117
|
+
recordSessionStart() {
|
|
118
|
+
const today = getTodayKey();
|
|
119
|
+
const day = this.ensureDay(today);
|
|
120
|
+
day.sessionCount += 1;
|
|
121
|
+
this.data.totalSessionCount += 1;
|
|
122
|
+
this.scheduleSave();
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get usage stats matching the mobile UsageStats type.
|
|
126
|
+
*/
|
|
127
|
+
getUsageStats(period = 'all') {
|
|
128
|
+
const now = new Date();
|
|
129
|
+
let startDate = null;
|
|
130
|
+
if (period === 'day') {
|
|
131
|
+
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
132
|
+
}
|
|
133
|
+
else if (period === 'week') {
|
|
134
|
+
startDate = new Date(now);
|
|
135
|
+
startDate.setDate(startDate.getDate() - 7);
|
|
136
|
+
}
|
|
137
|
+
else if (period === 'month') {
|
|
138
|
+
startDate = new Date(now);
|
|
139
|
+
startDate.setMonth(startDate.getMonth() - 1);
|
|
140
|
+
}
|
|
141
|
+
let inputTokens = 0;
|
|
142
|
+
let outputTokens = 0;
|
|
143
|
+
let sessionCount = 0;
|
|
144
|
+
if (!startDate) {
|
|
145
|
+
// 'all' — use totals directly
|
|
146
|
+
inputTokens = this.data.totalInputTokens;
|
|
147
|
+
outputTokens = this.data.totalOutputTokens;
|
|
148
|
+
sessionCount = this.data.totalSessionCount;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const startKey = startDate.toISOString().split('T')[0];
|
|
152
|
+
for (const [dateKey, day] of Object.entries(this.data.daily)) {
|
|
153
|
+
if (dateKey >= startKey) {
|
|
154
|
+
inputTokens += day.inputTokens;
|
|
155
|
+
outputTokens += day.outputTokens;
|
|
156
|
+
sessionCount += day.sessionCount;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const totalTokens = inputTokens + outputTokens;
|
|
161
|
+
// Rough cost estimate: $3/M input, $15/M output (Claude Sonnet pricing)
|
|
162
|
+
const estimatedCostUsd = (inputTokens * 3 + outputTokens * 15) / 1000000;
|
|
163
|
+
return {
|
|
164
|
+
totalInputTokens: String(inputTokens),
|
|
165
|
+
totalOutputTokens: String(outputTokens),
|
|
166
|
+
totalTokens: String(totalTokens),
|
|
167
|
+
totalSessionCount: sessionCount,
|
|
168
|
+
estimatedCostUsd: Math.round(estimatedCostUsd * 100) / 100,
|
|
169
|
+
period,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get daily usage matching the mobile TokenUsageDaily[] type.
|
|
174
|
+
*/
|
|
175
|
+
getDailyUsage(startDate, endDate) {
|
|
176
|
+
const result = [];
|
|
177
|
+
const sortedDays = Object.keys(this.data.daily).sort();
|
|
178
|
+
for (const dateKey of sortedDays) {
|
|
179
|
+
if (startDate && dateKey < startDate)
|
|
180
|
+
continue;
|
|
181
|
+
if (endDate && dateKey > endDate)
|
|
182
|
+
continue;
|
|
183
|
+
const day = this.data.daily[dateKey];
|
|
184
|
+
const total = day.inputTokens + day.outputTokens;
|
|
185
|
+
const cost = (day.inputTokens * 3 + day.outputTokens * 15) / 1000000;
|
|
186
|
+
result.push({
|
|
187
|
+
date: dateKey,
|
|
188
|
+
inputTokens: String(day.inputTokens),
|
|
189
|
+
outputTokens: String(day.outputTokens),
|
|
190
|
+
totalTokens: String(total),
|
|
191
|
+
sessionCount: day.sessionCount,
|
|
192
|
+
estimatedCostUsd: Math.round(cost * 100) / 100,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get streak info matching the mobile StreakInfo type.
|
|
199
|
+
*/
|
|
200
|
+
getStreakInfo() {
|
|
201
|
+
const activeDays = this.data.activeDays;
|
|
202
|
+
const totalActiveDays = activeDays.length;
|
|
203
|
+
if (totalActiveDays === 0) {
|
|
204
|
+
return { currentStreak: 0, totalActiveDays: 0 };
|
|
205
|
+
}
|
|
206
|
+
// Calculate current streak from today backwards
|
|
207
|
+
const today = getTodayKey();
|
|
208
|
+
let currentStreak = 0;
|
|
209
|
+
let checkDate = new Date(today + 'T00:00:00');
|
|
210
|
+
// Allow today or yesterday as the start of the streak
|
|
211
|
+
const todayInList = activeDays.includes(today);
|
|
212
|
+
if (!todayInList) {
|
|
213
|
+
checkDate.setDate(checkDate.getDate() - 1);
|
|
214
|
+
const yesterday = checkDate.toISOString().split('T')[0];
|
|
215
|
+
if (!activeDays.includes(yesterday)) {
|
|
216
|
+
return { currentStreak: 0, totalActiveDays };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
while (true) {
|
|
220
|
+
const key = checkDate.toISOString().split('T')[0];
|
|
221
|
+
if (activeDays.includes(key)) {
|
|
222
|
+
currentStreak++;
|
|
223
|
+
checkDate.setDate(checkDate.getDate() - 1);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return { currentStreak, totalActiveDays };
|
|
230
|
+
}
|
|
231
|
+
/** Flush pending writes immediately (call before exit). */
|
|
232
|
+
flush() {
|
|
233
|
+
if (this.saveTimer) {
|
|
234
|
+
clearTimeout(this.saveTimer);
|
|
235
|
+
this.saveTimer = null;
|
|
236
|
+
}
|
|
237
|
+
if (this.dirty) {
|
|
238
|
+
this.saveNow();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
exports.UsageTracker = UsageTracker;
|
|
243
|
+
//# sourceMappingURL=usage-tracker.js.map
|
package/dist/websocket.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
+
import { E2EEManager } from './crypto/e2eeManager';
|
|
3
|
+
import type { UsageTracker } from './usage-tracker';
|
|
2
4
|
type DeviceStatus = 'online' | 'offline' | 'busy' | 'syncing';
|
|
3
5
|
interface ClaudeSessionUpdate {
|
|
4
6
|
sessionKey: string;
|
|
5
7
|
directory: string;
|
|
8
|
+
name?: string;
|
|
6
9
|
state: 'active' | 'inactive';
|
|
7
10
|
lastUsedAt: string;
|
|
8
11
|
transcriptPath?: string;
|
|
@@ -28,20 +31,52 @@ interface ClaudeApprovalRequest {
|
|
|
28
31
|
context: string[];
|
|
29
32
|
options: string[];
|
|
30
33
|
promptText: string;
|
|
34
|
+
toolName?: string;
|
|
35
|
+
toolInput?: any;
|
|
31
36
|
}
|
|
32
37
|
export declare class WebSocketClient extends EventEmitter {
|
|
33
|
-
private
|
|
34
|
-
private reconnectAttempts;
|
|
38
|
+
private server;
|
|
35
39
|
private heartbeatInterval;
|
|
36
40
|
private _sessionId;
|
|
41
|
+
private e2eeManager;
|
|
42
|
+
private e2eeInitialized;
|
|
43
|
+
private e2eePeerDeviceId;
|
|
44
|
+
private pendingSensitiveMessages;
|
|
45
|
+
private static readonly SENSITIVE_QUEUE_TTL_MS;
|
|
46
|
+
private static readonly MAX_PENDING_SENSITIVE;
|
|
47
|
+
private usageTracker;
|
|
37
48
|
get sessionId(): string;
|
|
38
|
-
|
|
49
|
+
/** Start the embedded relay server and wire up event forwarding */
|
|
50
|
+
startServer(port: number): Promise<void>;
|
|
51
|
+
/** Set pairing code on the embedded server for in-process validation */
|
|
52
|
+
setPairingCode(code: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Initialize E2EE manager: generate/load keys.
|
|
55
|
+
* Called automatically on startServer. Non-blocking.
|
|
56
|
+
*/
|
|
57
|
+
private initE2EE;
|
|
58
|
+
/**
|
|
59
|
+
* Send a sensitive event: encrypt if E2EE session exists with the target device.
|
|
60
|
+
* For events in ENFORCED_SENSITIVE_EVENTS, plaintext fallback is REFUSED — messages
|
|
61
|
+
* are queued until E2EE session establishes, or dropped after timeout.
|
|
62
|
+
*/
|
|
63
|
+
emitSensitive(event: string, data: any, targetDeviceId?: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Flush queued sensitive messages now that E2EE session is established.
|
|
66
|
+
* Drops messages older than SENSITIVE_QUEUE_TTL_MS.
|
|
67
|
+
*/
|
|
68
|
+
private flushSensitiveQueue;
|
|
69
|
+
/** Get the E2EE manager (for external key exchange initiation) */
|
|
70
|
+
getE2EEManager(): E2EEManager | null;
|
|
71
|
+
/** Check if E2EE session is active with a device */
|
|
72
|
+
isE2EEActive(deviceId: string): boolean;
|
|
73
|
+
/** SECURITY: Check if plaintext inbound events should be dropped (E2EE active with peer) */
|
|
74
|
+
private shouldDropPlaintextInbound;
|
|
39
75
|
disconnect(): void;
|
|
40
76
|
private startHeartbeat;
|
|
41
77
|
private stopHeartbeat;
|
|
42
78
|
sendHeartbeat(status?: DeviceStatus): void;
|
|
43
79
|
updateStatus(status: DeviceStatus): void;
|
|
44
|
-
setSyncing(syncing: boolean): void;
|
|
45
80
|
sendClaudeSessionUpdate(session: ClaudeSessionUpdate): void;
|
|
46
81
|
sendClaudeSessions(sessions: ClaudeSessionUpdate[]): void;
|
|
47
82
|
sendToolStatusUpdate(toolType: string, status: 'active' | 'inactive' | 'error'): void;
|
|
@@ -95,14 +130,6 @@ export declare class WebSocketClient extends EventEmitter {
|
|
|
95
130
|
sessionKey: string;
|
|
96
131
|
entry: TranscriptEntry;
|
|
97
132
|
}): void;
|
|
98
|
-
sendRpcResponse(data: {
|
|
99
|
-
requestId: string;
|
|
100
|
-
result?: any;
|
|
101
|
-
error?: {
|
|
102
|
-
code: number;
|
|
103
|
-
message: string;
|
|
104
|
-
};
|
|
105
|
-
}): void;
|
|
106
133
|
sendClaudeApprovalRequest(data: ClaudeApprovalRequest): void;
|
|
107
134
|
sendToolActivity(data: {
|
|
108
135
|
terminalSessionId: string;
|
|
@@ -164,6 +191,10 @@ export declare class WebSocketClient extends EventEmitter {
|
|
|
164
191
|
ephemeralPublicKey: string;
|
|
165
192
|
}): void;
|
|
166
193
|
emitEncryptedMessage(data: any): void;
|
|
194
|
+
/** Set the usage tracker instance (called from index.ts after instantiation) */
|
|
195
|
+
setUsageTracker(tracker: UsageTracker): void;
|
|
196
|
+
/** Send all usage stats to mobile (called after E2EE established and on request) */
|
|
197
|
+
sendAllUsageStats(): void;
|
|
167
198
|
sendClaudeSessionEvent(data: {
|
|
168
199
|
sessionKey: string;
|
|
169
200
|
event: {
|