@ccpocket/bridge 1.48.1 → 1.49.0
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/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/parser.d.ts +51 -0
- package/dist/parser.js +82 -0
- package/dist/parser.js.map +1 -1
- package/dist/prompt-history-store.d.ts +82 -0
- package/dist/prompt-history-store.js +322 -0
- package/dist/prompt-history-store.js.map +1 -0
- package/dist/websocket.d.ts +5 -0
- package/dist/websocket.js +175 -5
- package/dist/websocket.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
const DEFAULT_STORE_FILE = join(homedir(), ".ccpocket", "prompt-history-v2.json");
|
|
6
|
+
const DEFAULT_BRIDGE_PORT = 8765;
|
|
7
|
+
export function promptHistoryStoreFileForPort(port, explicitFile) {
|
|
8
|
+
if (explicitFile?.trim())
|
|
9
|
+
return explicitFile.trim();
|
|
10
|
+
const parsedPort = typeof port === "number" ? port : Number.parseInt(port ?? "", 10);
|
|
11
|
+
if (!Number.isInteger(parsedPort) || parsedPort === DEFAULT_BRIDGE_PORT) {
|
|
12
|
+
return DEFAULT_STORE_FILE;
|
|
13
|
+
}
|
|
14
|
+
return join(homedir(), ".ccpocket", `prompt-history-v2-${parsedPort}.json`);
|
|
15
|
+
}
|
|
16
|
+
function isoNow() {
|
|
17
|
+
return new Date().toISOString();
|
|
18
|
+
}
|
|
19
|
+
function maxIso(left, right) {
|
|
20
|
+
if (!left)
|
|
21
|
+
return right ?? isoNow();
|
|
22
|
+
if (!right)
|
|
23
|
+
return left;
|
|
24
|
+
return left >= right ? left : right;
|
|
25
|
+
}
|
|
26
|
+
function minIso(left, right) {
|
|
27
|
+
if (!left)
|
|
28
|
+
return right ?? isoNow();
|
|
29
|
+
if (!right)
|
|
30
|
+
return left;
|
|
31
|
+
return left <= right ? left : right;
|
|
32
|
+
}
|
|
33
|
+
function normalizeText(text) {
|
|
34
|
+
return text.trim().replace(/\r\n/g, "\n");
|
|
35
|
+
}
|
|
36
|
+
function normalizeProjectPath(projectPath) {
|
|
37
|
+
return (projectPath ?? "").trim();
|
|
38
|
+
}
|
|
39
|
+
export function promptHistoryId(text, projectPath = "") {
|
|
40
|
+
const stableKey = `${normalizeProjectPath(projectPath)}\u0000${normalizeText(text)}`;
|
|
41
|
+
const digest = createHash("sha256").update(stableKey).digest("hex");
|
|
42
|
+
return `ph_${digest.slice(0, 24)}`;
|
|
43
|
+
}
|
|
44
|
+
export function detectPromptCommandKind(text) {
|
|
45
|
+
const trimmed = text.trimStart();
|
|
46
|
+
if (trimmed.startsWith("$"))
|
|
47
|
+
return "skill";
|
|
48
|
+
if (trimmed.startsWith("/"))
|
|
49
|
+
return "slash";
|
|
50
|
+
const commandMatch = /<command-name>\s*(.*?)\s*<\/command-name>/s.exec(text);
|
|
51
|
+
const commandName = commandMatch?.[1]?.trim();
|
|
52
|
+
if (commandName?.startsWith("$"))
|
|
53
|
+
return "skill";
|
|
54
|
+
if (commandName?.startsWith("/"))
|
|
55
|
+
return "slash";
|
|
56
|
+
return "none";
|
|
57
|
+
}
|
|
58
|
+
function cloneEntry(entry) {
|
|
59
|
+
return {
|
|
60
|
+
...entry,
|
|
61
|
+
clientStats: { ...entry.clientStats },
|
|
62
|
+
sessionStats: { ...entry.sessionStats },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export class PromptHistoryStore {
|
|
66
|
+
data = {
|
|
67
|
+
version: 2,
|
|
68
|
+
bridgeInstanceId: randomUUID(),
|
|
69
|
+
revision: 0,
|
|
70
|
+
entries: [],
|
|
71
|
+
};
|
|
72
|
+
filePath;
|
|
73
|
+
constructor(filePath) {
|
|
74
|
+
this.filePath = filePath ?? DEFAULT_STORE_FILE;
|
|
75
|
+
}
|
|
76
|
+
async init() {
|
|
77
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
78
|
+
try {
|
|
79
|
+
const raw = await readFile(this.filePath, "utf-8");
|
|
80
|
+
const parsed = JSON.parse(raw);
|
|
81
|
+
if (parsed.version === 2 && Array.isArray(parsed.entries)) {
|
|
82
|
+
this.data = {
|
|
83
|
+
version: 2,
|
|
84
|
+
bridgeInstanceId: typeof parsed.bridgeInstanceId === "string" &&
|
|
85
|
+
parsed.bridgeInstanceId.length > 0
|
|
86
|
+
? parsed.bridgeInstanceId
|
|
87
|
+
: randomUUID(),
|
|
88
|
+
revision: Number.isInteger(parsed.revision) ? parsed.revision : 0,
|
|
89
|
+
entries: parsed.entries.map((entry) => ({
|
|
90
|
+
...entry,
|
|
91
|
+
clientStats: entry.clientStats ?? {},
|
|
92
|
+
sessionStats: entry.sessionStats ?? {},
|
|
93
|
+
commandKind: entry.commandKind ?? detectPromptCommandKind(entry.text),
|
|
94
|
+
})),
|
|
95
|
+
};
|
|
96
|
+
if (!parsed.bridgeInstanceId)
|
|
97
|
+
await this.save();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
this.data = {
|
|
102
|
+
version: 2,
|
|
103
|
+
bridgeInstanceId: randomUUID(),
|
|
104
|
+
revision: 0,
|
|
105
|
+
entries: [],
|
|
106
|
+
};
|
|
107
|
+
await this.save();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
get revision() {
|
|
111
|
+
return this.data.revision;
|
|
112
|
+
}
|
|
113
|
+
get bridgeInstanceId() {
|
|
114
|
+
return this.data.bridgeInstanceId;
|
|
115
|
+
}
|
|
116
|
+
list(includeDeleted = false) {
|
|
117
|
+
return this.data.entries
|
|
118
|
+
.filter((entry) => includeDeleted || !entry.deletedAt)
|
|
119
|
+
.map(cloneEntry);
|
|
120
|
+
}
|
|
121
|
+
async record(input) {
|
|
122
|
+
const text = normalizeText(input.text);
|
|
123
|
+
if (!text)
|
|
124
|
+
throw new Error("Prompt text is required");
|
|
125
|
+
const projectPath = normalizeProjectPath(input.projectPath);
|
|
126
|
+
const id = promptHistoryId(text, projectPath);
|
|
127
|
+
const usedAt = input.usedAt ?? isoNow();
|
|
128
|
+
const existing = this.findMutable(id);
|
|
129
|
+
if (existing) {
|
|
130
|
+
existing.totalUseCount += 1;
|
|
131
|
+
existing.lastUsedAt = maxIso(existing.lastUsedAt, usedAt);
|
|
132
|
+
existing.updatedAt = maxIso(existing.updatedAt, usedAt);
|
|
133
|
+
existing.deletedAt = undefined;
|
|
134
|
+
this.incrementClientStat(existing, input.clientId, input.clientName, usedAt, 1);
|
|
135
|
+
if (input.sessionId)
|
|
136
|
+
this.incrementSessionStat(existing, input.sessionId, usedAt, 1);
|
|
137
|
+
await this.saveBumped();
|
|
138
|
+
return cloneEntry(existing);
|
|
139
|
+
}
|
|
140
|
+
const entry = {
|
|
141
|
+
id,
|
|
142
|
+
text,
|
|
143
|
+
projectPath,
|
|
144
|
+
totalUseCount: 1,
|
|
145
|
+
isFavorite: false,
|
|
146
|
+
createdAt: usedAt,
|
|
147
|
+
lastUsedAt: usedAt,
|
|
148
|
+
updatedAt: usedAt,
|
|
149
|
+
commandKind: detectPromptCommandKind(text),
|
|
150
|
+
clientStats: {},
|
|
151
|
+
sessionStats: {},
|
|
152
|
+
};
|
|
153
|
+
this.incrementClientStat(entry, input.clientId, input.clientName, usedAt, 1);
|
|
154
|
+
if (input.sessionId)
|
|
155
|
+
this.incrementSessionStat(entry, input.sessionId, usedAt, 1);
|
|
156
|
+
this.data.entries.push(entry);
|
|
157
|
+
await this.saveBumped();
|
|
158
|
+
return cloneEntry(entry);
|
|
159
|
+
}
|
|
160
|
+
async mutate(input) {
|
|
161
|
+
const id = input.id ?? (input.text ? promptHistoryId(input.text, input.projectPath ?? "") : undefined);
|
|
162
|
+
if (!id)
|
|
163
|
+
return null;
|
|
164
|
+
const entry = this.findMutable(id);
|
|
165
|
+
if (!entry)
|
|
166
|
+
return null;
|
|
167
|
+
const updatedAt = input.updatedAt ?? isoNow();
|
|
168
|
+
switch (input.action) {
|
|
169
|
+
case "favorite":
|
|
170
|
+
entry.isFavorite = input.isFavorite ?? !entry.isFavorite;
|
|
171
|
+
entry.favoriteUpdatedAt = updatedAt;
|
|
172
|
+
entry.updatedAt = maxIso(entry.updatedAt, updatedAt);
|
|
173
|
+
break;
|
|
174
|
+
case "delete":
|
|
175
|
+
entry.deletedAt = updatedAt;
|
|
176
|
+
entry.updatedAt = maxIso(entry.updatedAt, updatedAt);
|
|
177
|
+
break;
|
|
178
|
+
case "restore":
|
|
179
|
+
entry.deletedAt = undefined;
|
|
180
|
+
entry.updatedAt = maxIso(entry.updatedAt, updatedAt);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
await this.saveBumped();
|
|
184
|
+
return cloneEntry(entry);
|
|
185
|
+
}
|
|
186
|
+
async importEntries(entries, clientId, clientName) {
|
|
187
|
+
this.data.entries = [];
|
|
188
|
+
let imported = 0;
|
|
189
|
+
for (const raw of entries) {
|
|
190
|
+
const text = normalizeText(raw.text);
|
|
191
|
+
if (!text)
|
|
192
|
+
continue;
|
|
193
|
+
const projectPath = normalizeProjectPath(raw.projectPath);
|
|
194
|
+
const id = raw.id ?? promptHistoryId(text, projectPath);
|
|
195
|
+
const now = isoNow();
|
|
196
|
+
const useCount = Math.max(1, raw.totalUseCount ?? raw.useCount ?? 1);
|
|
197
|
+
const createdAt = raw.createdAt ?? now;
|
|
198
|
+
const lastUsedAt = raw.lastUsedAt ?? raw.updatedAt ?? now;
|
|
199
|
+
const updatedAt = raw.updatedAt ?? lastUsedAt;
|
|
200
|
+
const incoming = {
|
|
201
|
+
id,
|
|
202
|
+
text,
|
|
203
|
+
projectPath,
|
|
204
|
+
totalUseCount: useCount,
|
|
205
|
+
isFavorite: raw.isFavorite ?? false,
|
|
206
|
+
createdAt,
|
|
207
|
+
lastUsedAt,
|
|
208
|
+
updatedAt,
|
|
209
|
+
favoriteUpdatedAt: raw.favoriteUpdatedAt ?? (raw.isFavorite ? updatedAt : undefined),
|
|
210
|
+
deletedAt: raw.deletedAt,
|
|
211
|
+
commandKind: raw.commandKind ?? detectPromptCommandKind(text),
|
|
212
|
+
clientStats: raw.clientStats ?? {},
|
|
213
|
+
sessionStats: raw.sessionStats ?? {},
|
|
214
|
+
};
|
|
215
|
+
this.incrementClientStat(incoming, clientId, clientName, lastUsedAt, useCount);
|
|
216
|
+
this.mergeEntry(incoming);
|
|
217
|
+
imported += 1;
|
|
218
|
+
}
|
|
219
|
+
await this.saveBumped();
|
|
220
|
+
return { imported, entries: this.list() };
|
|
221
|
+
}
|
|
222
|
+
async mergeClientEntries(entries) {
|
|
223
|
+
if (entries.length === 0)
|
|
224
|
+
return;
|
|
225
|
+
for (const raw of entries) {
|
|
226
|
+
const text = normalizeText(raw.text);
|
|
227
|
+
if (!text)
|
|
228
|
+
continue;
|
|
229
|
+
const projectPath = normalizeProjectPath(raw.projectPath);
|
|
230
|
+
this.mergeEntry({
|
|
231
|
+
id: raw.id ?? promptHistoryId(text, projectPath),
|
|
232
|
+
text,
|
|
233
|
+
projectPath,
|
|
234
|
+
totalUseCount: Math.max(1, raw.totalUseCount ?? raw.useCount ?? 1),
|
|
235
|
+
isFavorite: raw.isFavorite ?? false,
|
|
236
|
+
createdAt: raw.createdAt ?? isoNow(),
|
|
237
|
+
lastUsedAt: raw.lastUsedAt ?? raw.updatedAt ?? isoNow(),
|
|
238
|
+
updatedAt: raw.updatedAt ?? raw.lastUsedAt ?? isoNow(),
|
|
239
|
+
favoriteUpdatedAt: raw.favoriteUpdatedAt,
|
|
240
|
+
deletedAt: raw.deletedAt,
|
|
241
|
+
commandKind: raw.commandKind ?? detectPromptCommandKind(text),
|
|
242
|
+
clientStats: raw.clientStats ?? {},
|
|
243
|
+
sessionStats: raw.sessionStats ?? {},
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
await this.saveBumped();
|
|
247
|
+
}
|
|
248
|
+
findMutable(id) {
|
|
249
|
+
return this.data.entries.find((entry) => entry.id === id);
|
|
250
|
+
}
|
|
251
|
+
incrementClientStat(entry, clientId, clientName, lastUsedAt, increment) {
|
|
252
|
+
const current = entry.clientStats[clientId] ?? { useCount: 0, lastUsedAt };
|
|
253
|
+
entry.clientStats[clientId] = {
|
|
254
|
+
useCount: current.useCount + increment,
|
|
255
|
+
lastUsedAt: maxIso(current.lastUsedAt, lastUsedAt),
|
|
256
|
+
clientName: clientName ?? current.clientName,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
incrementSessionStat(entry, sessionId, lastUsedAt, increment) {
|
|
260
|
+
const current = entry.sessionStats[sessionId] ?? { useCount: 0, lastUsedAt };
|
|
261
|
+
entry.sessionStats[sessionId] = {
|
|
262
|
+
useCount: current.useCount + increment,
|
|
263
|
+
lastUsedAt: maxIso(current.lastUsedAt, lastUsedAt),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
mergeEntry(incoming) {
|
|
267
|
+
const existing = this.findMutable(incoming.id);
|
|
268
|
+
if (!existing) {
|
|
269
|
+
this.data.entries.push(cloneEntry(incoming));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
existing.totalUseCount += incoming.totalUseCount;
|
|
273
|
+
existing.createdAt = minIso(existing.createdAt, incoming.createdAt);
|
|
274
|
+
existing.lastUsedAt = maxIso(existing.lastUsedAt, incoming.lastUsedAt);
|
|
275
|
+
existing.updatedAt = maxIso(existing.updatedAt, incoming.updatedAt);
|
|
276
|
+
existing.commandKind =
|
|
277
|
+
existing.commandKind === "none" ? incoming.commandKind : existing.commandKind;
|
|
278
|
+
if (incoming.favoriteUpdatedAt &&
|
|
279
|
+
(!existing.favoriteUpdatedAt ||
|
|
280
|
+
incoming.favoriteUpdatedAt >= existing.favoriteUpdatedAt)) {
|
|
281
|
+
existing.isFavorite = incoming.isFavorite;
|
|
282
|
+
existing.favoriteUpdatedAt = incoming.favoriteUpdatedAt;
|
|
283
|
+
}
|
|
284
|
+
else if (incoming.isFavorite && !existing.favoriteUpdatedAt) {
|
|
285
|
+
existing.isFavorite = true;
|
|
286
|
+
existing.favoriteUpdatedAt = incoming.updatedAt;
|
|
287
|
+
}
|
|
288
|
+
if (incoming.deletedAt && (!existing.deletedAt || incoming.deletedAt >= existing.deletedAt)) {
|
|
289
|
+
existing.deletedAt = incoming.deletedAt;
|
|
290
|
+
}
|
|
291
|
+
for (const [clientId, stat] of Object.entries(incoming.clientStats)) {
|
|
292
|
+
const current = existing.clientStats[clientId];
|
|
293
|
+
existing.clientStats[clientId] = current
|
|
294
|
+
? {
|
|
295
|
+
useCount: current.useCount + stat.useCount,
|
|
296
|
+
lastUsedAt: maxIso(current.lastUsedAt, stat.lastUsedAt),
|
|
297
|
+
clientName: stat.clientName ?? current.clientName,
|
|
298
|
+
}
|
|
299
|
+
: { ...stat };
|
|
300
|
+
}
|
|
301
|
+
for (const [sessionId, stat] of Object.entries(incoming.sessionStats)) {
|
|
302
|
+
const current = existing.sessionStats[sessionId];
|
|
303
|
+
existing.sessionStats[sessionId] = current
|
|
304
|
+
? {
|
|
305
|
+
useCount: current.useCount + stat.useCount,
|
|
306
|
+
lastUsedAt: maxIso(current.lastUsedAt, stat.lastUsedAt),
|
|
307
|
+
}
|
|
308
|
+
: { ...stat };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async saveBumped() {
|
|
312
|
+
this.data.revision += 1;
|
|
313
|
+
await this.save();
|
|
314
|
+
}
|
|
315
|
+
async save() {
|
|
316
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
317
|
+
const tmp = `${this.filePath}.${randomUUID()}.tmp`;
|
|
318
|
+
await writeFile(tmp, JSON.stringify(this.data, null, 2), "utf-8");
|
|
319
|
+
await rename(tmp, this.filePath);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=prompt-history-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-history-store.js","sourceRoot":"","sources":["../src/prompt-history-store.ts"],"names":[],"mappings":"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"}
|
package/dist/websocket.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { DebugTraceStore } from "./debug-trace-store.js";
|
|
|
6
6
|
import { RecordingStore } from "./recording-store.js";
|
|
7
7
|
import type { FirebaseAuthClient } from "./firebase-auth.js";
|
|
8
8
|
import type { PromptHistoryBackupStore } from "./prompt-history-backup.js";
|
|
9
|
+
import type { PromptHistoryStore } from "./prompt-history-store.js";
|
|
9
10
|
export interface BridgeServerOptions {
|
|
10
11
|
server: HttpServer;
|
|
11
12
|
apiKey?: string;
|
|
@@ -17,6 +18,7 @@ export interface BridgeServerOptions {
|
|
|
17
18
|
recordingStore?: RecordingStore;
|
|
18
19
|
firebaseAuth?: FirebaseAuthClient;
|
|
19
20
|
promptHistoryBackup?: PromptHistoryBackupStore;
|
|
21
|
+
promptHistoryStore?: PromptHistoryStore;
|
|
20
22
|
platform?: NodeJS.Platform;
|
|
21
23
|
}
|
|
22
24
|
export declare class BridgeWebSocketServer {
|
|
@@ -34,6 +36,7 @@ export declare class BridgeWebSocketServer {
|
|
|
34
36
|
private worktreeStore;
|
|
35
37
|
private pushRelay;
|
|
36
38
|
private promptHistoryBackup;
|
|
39
|
+
private promptHistoryStore;
|
|
37
40
|
private recentSessionsRequestId;
|
|
38
41
|
private debugEvents;
|
|
39
42
|
private notifiedPermissionToolUses;
|
|
@@ -83,8 +86,10 @@ export declare class BridgeWebSocketServer {
|
|
|
83
86
|
private resolveSession;
|
|
84
87
|
private getFirstSession;
|
|
85
88
|
private sendSessionList;
|
|
89
|
+
private sendPromptHistoryStatus;
|
|
86
90
|
/** Broadcast session list to all connected clients. */
|
|
87
91
|
private broadcastSessionList;
|
|
92
|
+
private broadcastPromptHistoryStatus;
|
|
88
93
|
private broadcastSessionMessage;
|
|
89
94
|
private listRecentSessions;
|
|
90
95
|
private refreshCodexProfiles;
|
package/dist/websocket.js
CHANGED
|
@@ -38,6 +38,10 @@ const CODEX_MODELS = [
|
|
|
38
38
|
"gpt-5.3-codex",
|
|
39
39
|
"gpt-5.3-codex-spark",
|
|
40
40
|
];
|
|
41
|
+
const OPT_IN_SERVER_MESSAGES = new Set([
|
|
42
|
+
"conversation_queue",
|
|
43
|
+
"prompt_history_status",
|
|
44
|
+
]);
|
|
41
45
|
// ---- Codex mode mapping helpers ----
|
|
42
46
|
/** Map unified PermissionMode to Codex approval_policy.
|
|
43
47
|
* Only "bypassPermissions" maps to "never"; all others use "on-request". */
|
|
@@ -166,6 +170,7 @@ export class BridgeWebSocketServer {
|
|
|
166
170
|
worktreeStore;
|
|
167
171
|
pushRelay;
|
|
168
172
|
promptHistoryBackup;
|
|
173
|
+
promptHistoryStore;
|
|
169
174
|
recentSessionsRequestId = 0;
|
|
170
175
|
debugEvents = new Map();
|
|
171
176
|
notifiedPermissionToolUses = new Map();
|
|
@@ -181,7 +186,7 @@ export class BridgeWebSocketServer {
|
|
|
181
186
|
platform;
|
|
182
187
|
clientSupportedServerMessages = new WeakMap();
|
|
183
188
|
constructor(options) {
|
|
184
|
-
const { server, apiKey, allowedDirs, imageStore, galleryStore, projectHistory, debugTraceStore, recordingStore, firebaseAuth, promptHistoryBackup, platform, } = options;
|
|
189
|
+
const { server, apiKey, allowedDirs, imageStore, galleryStore, projectHistory, debugTraceStore, recordingStore, firebaseAuth, promptHistoryBackup, promptHistoryStore, platform, } = options;
|
|
185
190
|
this.apiKey = apiKey ?? null;
|
|
186
191
|
this.allowedDirs = allowedDirs ?? [];
|
|
187
192
|
this.imageStore = imageStore ?? null;
|
|
@@ -192,6 +197,7 @@ export class BridgeWebSocketServer {
|
|
|
192
197
|
this.worktreeStore = new WorktreeStore();
|
|
193
198
|
this.pushRelay = new PushRelayClient({ firebaseAuth });
|
|
194
199
|
this.promptHistoryBackup = promptHistoryBackup ?? null;
|
|
200
|
+
this.promptHistoryStore = promptHistoryStore ?? null;
|
|
195
201
|
this.platform = platform ?? process.platform;
|
|
196
202
|
this.archiveStore = new ArchiveStore();
|
|
197
203
|
void this.debugTraceStore.init().catch((err) => {
|
|
@@ -544,6 +550,7 @@ export class BridgeWebSocketServer {
|
|
|
544
550
|
async handleClientMessage(msg, ws) {
|
|
545
551
|
if (msg.type === "client_capabilities") {
|
|
546
552
|
this.clientSupportedServerMessages.set(ws, new Set(msg.supportedServerMessages ?? []));
|
|
553
|
+
this.sendPromptHistoryStatus(ws);
|
|
547
554
|
return;
|
|
548
555
|
}
|
|
549
556
|
const incomingSessionId = this.extractSessionIdFromClientMessage(msg);
|
|
@@ -3205,6 +3212,144 @@ export class BridgeWebSocketServer {
|
|
|
3205
3212
|
});
|
|
3206
3213
|
break;
|
|
3207
3214
|
}
|
|
3215
|
+
case "record_prompt_history": {
|
|
3216
|
+
if (!this.promptHistoryStore) {
|
|
3217
|
+
this.send(ws, {
|
|
3218
|
+
type: "prompt_history_mutation_result",
|
|
3219
|
+
success: false,
|
|
3220
|
+
error: "Prompt history store not available",
|
|
3221
|
+
});
|
|
3222
|
+
break;
|
|
3223
|
+
}
|
|
3224
|
+
try {
|
|
3225
|
+
const entry = await this.promptHistoryStore.record({
|
|
3226
|
+
text: msg.text,
|
|
3227
|
+
projectPath: msg.projectPath,
|
|
3228
|
+
clientId: msg.clientId,
|
|
3229
|
+
clientName: msg.clientName,
|
|
3230
|
+
sessionId: msg.sessionId,
|
|
3231
|
+
usedAt: msg.usedAt,
|
|
3232
|
+
});
|
|
3233
|
+
this.send(ws, {
|
|
3234
|
+
type: "prompt_history_mutation_result",
|
|
3235
|
+
success: true,
|
|
3236
|
+
bridgeInstanceId: this.promptHistoryStore.bridgeInstanceId,
|
|
3237
|
+
revision: this.promptHistoryStore.revision,
|
|
3238
|
+
entry,
|
|
3239
|
+
});
|
|
3240
|
+
this.broadcastPromptHistoryStatus();
|
|
3241
|
+
}
|
|
3242
|
+
catch (err) {
|
|
3243
|
+
this.send(ws, {
|
|
3244
|
+
type: "prompt_history_mutation_result",
|
|
3245
|
+
success: false,
|
|
3246
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3247
|
+
});
|
|
3248
|
+
}
|
|
3249
|
+
break;
|
|
3250
|
+
}
|
|
3251
|
+
case "sync_prompt_history": {
|
|
3252
|
+
if (!this.promptHistoryStore) {
|
|
3253
|
+
this.send(ws, {
|
|
3254
|
+
type: "prompt_history_sync_result",
|
|
3255
|
+
success: false,
|
|
3256
|
+
error: "Prompt history store not available",
|
|
3257
|
+
});
|
|
3258
|
+
break;
|
|
3259
|
+
}
|
|
3260
|
+
try {
|
|
3261
|
+
if (msg.entries?.length) {
|
|
3262
|
+
await this.promptHistoryStore.mergeClientEntries(msg.entries);
|
|
3263
|
+
}
|
|
3264
|
+
this.send(ws, {
|
|
3265
|
+
type: "prompt_history_sync_result",
|
|
3266
|
+
success: true,
|
|
3267
|
+
bridgeInstanceId: this.promptHistoryStore.bridgeInstanceId,
|
|
3268
|
+
revision: this.promptHistoryStore.revision,
|
|
3269
|
+
syncedAt: new Date().toISOString(),
|
|
3270
|
+
fullSnapshot: true,
|
|
3271
|
+
entries: this.promptHistoryStore.list(msg.includeDeleted ?? true),
|
|
3272
|
+
});
|
|
3273
|
+
this.broadcastPromptHistoryStatus();
|
|
3274
|
+
}
|
|
3275
|
+
catch (err) {
|
|
3276
|
+
this.send(ws, {
|
|
3277
|
+
type: "prompt_history_sync_result",
|
|
3278
|
+
success: false,
|
|
3279
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3280
|
+
});
|
|
3281
|
+
}
|
|
3282
|
+
break;
|
|
3283
|
+
}
|
|
3284
|
+
case "mutate_prompt_history": {
|
|
3285
|
+
if (!this.promptHistoryStore) {
|
|
3286
|
+
this.send(ws, {
|
|
3287
|
+
type: "prompt_history_mutation_result",
|
|
3288
|
+
success: false,
|
|
3289
|
+
error: "Prompt history store not available",
|
|
3290
|
+
});
|
|
3291
|
+
break;
|
|
3292
|
+
}
|
|
3293
|
+
try {
|
|
3294
|
+
const entry = await this.promptHistoryStore.mutate({
|
|
3295
|
+
id: msg.id,
|
|
3296
|
+
text: msg.text,
|
|
3297
|
+
projectPath: msg.projectPath,
|
|
3298
|
+
action: msg.action,
|
|
3299
|
+
isFavorite: msg.isFavorite,
|
|
3300
|
+
updatedAt: msg.updatedAt,
|
|
3301
|
+
});
|
|
3302
|
+
this.send(ws, {
|
|
3303
|
+
type: "prompt_history_mutation_result",
|
|
3304
|
+
success: entry != null,
|
|
3305
|
+
bridgeInstanceId: this.promptHistoryStore.bridgeInstanceId,
|
|
3306
|
+
revision: this.promptHistoryStore.revision,
|
|
3307
|
+
entry: entry ?? undefined,
|
|
3308
|
+
error: entry == null ? "Prompt not found" : undefined,
|
|
3309
|
+
});
|
|
3310
|
+
if (entry)
|
|
3311
|
+
this.broadcastPromptHistoryStatus();
|
|
3312
|
+
}
|
|
3313
|
+
catch (err) {
|
|
3314
|
+
this.send(ws, {
|
|
3315
|
+
type: "prompt_history_mutation_result",
|
|
3316
|
+
success: false,
|
|
3317
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3318
|
+
});
|
|
3319
|
+
}
|
|
3320
|
+
break;
|
|
3321
|
+
}
|
|
3322
|
+
case "import_prompt_history_v1": {
|
|
3323
|
+
if (!this.promptHistoryStore) {
|
|
3324
|
+
this.send(ws, {
|
|
3325
|
+
type: "prompt_history_sync_result",
|
|
3326
|
+
success: false,
|
|
3327
|
+
error: "Prompt history store not available",
|
|
3328
|
+
});
|
|
3329
|
+
break;
|
|
3330
|
+
}
|
|
3331
|
+
try {
|
|
3332
|
+
const result = await this.promptHistoryStore.importEntries(msg.entries, msg.clientId, msg.clientName);
|
|
3333
|
+
this.send(ws, {
|
|
3334
|
+
type: "prompt_history_sync_result",
|
|
3335
|
+
success: true,
|
|
3336
|
+
bridgeInstanceId: this.promptHistoryStore.bridgeInstanceId,
|
|
3337
|
+
revision: this.promptHistoryStore.revision,
|
|
3338
|
+
syncedAt: new Date().toISOString(),
|
|
3339
|
+
fullSnapshot: true,
|
|
3340
|
+
entries: result.entries,
|
|
3341
|
+
});
|
|
3342
|
+
this.broadcastPromptHistoryStatus();
|
|
3343
|
+
}
|
|
3344
|
+
catch (err) {
|
|
3345
|
+
this.send(ws, {
|
|
3346
|
+
type: "prompt_history_sync_result",
|
|
3347
|
+
success: false,
|
|
3348
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3349
|
+
});
|
|
3350
|
+
}
|
|
3351
|
+
break;
|
|
3352
|
+
}
|
|
3208
3353
|
case "rename_session": {
|
|
3209
3354
|
const name = msg.name || null;
|
|
3210
3355
|
await this.handleRenameSession(ws, msg.sessionId, name, msg);
|
|
@@ -3308,6 +3453,19 @@ export class BridgeWebSocketServer {
|
|
|
3308
3453
|
bridgeVersion: getPackageVersion(),
|
|
3309
3454
|
});
|
|
3310
3455
|
}
|
|
3456
|
+
sendPromptHistoryStatus(ws) {
|
|
3457
|
+
if (!this.promptHistoryStore)
|
|
3458
|
+
return;
|
|
3459
|
+
const entries = this.promptHistoryStore.list(true);
|
|
3460
|
+
const updatedAt = entries.reduce((latest, entry) => !latest || entry.updatedAt > latest ? entry.updatedAt : latest, undefined);
|
|
3461
|
+
this.send(ws, {
|
|
3462
|
+
type: "prompt_history_status",
|
|
3463
|
+
bridgeInstanceId: this.promptHistoryStore.bridgeInstanceId,
|
|
3464
|
+
revision: this.promptHistoryStore.revision,
|
|
3465
|
+
entryCount: entries.filter((entry) => !entry.deletedAt).length,
|
|
3466
|
+
updatedAt,
|
|
3467
|
+
});
|
|
3468
|
+
}
|
|
3311
3469
|
/** Broadcast session list to all connected clients. */
|
|
3312
3470
|
broadcastSessionList() {
|
|
3313
3471
|
this.pruneDebugEvents();
|
|
@@ -3323,6 +3481,19 @@ export class BridgeWebSocketServer {
|
|
|
3323
3481
|
bridgeVersion: getPackageVersion(),
|
|
3324
3482
|
});
|
|
3325
3483
|
}
|
|
3484
|
+
broadcastPromptHistoryStatus() {
|
|
3485
|
+
if (!this.promptHistoryStore)
|
|
3486
|
+
return;
|
|
3487
|
+
const entries = this.promptHistoryStore.list(true);
|
|
3488
|
+
const updatedAt = entries.reduce((latest, entry) => !latest || entry.updatedAt > latest ? entry.updatedAt : latest, undefined);
|
|
3489
|
+
this.broadcast({
|
|
3490
|
+
type: "prompt_history_status",
|
|
3491
|
+
bridgeInstanceId: this.promptHistoryStore.bridgeInstanceId,
|
|
3492
|
+
revision: this.promptHistoryStore.revision,
|
|
3493
|
+
entryCount: entries.filter((entry) => !entry.deletedAt).length,
|
|
3494
|
+
updatedAt,
|
|
3495
|
+
});
|
|
3496
|
+
}
|
|
3326
3497
|
broadcastSessionMessage(sessionId, msg) {
|
|
3327
3498
|
this.maybeSendPushNotification(sessionId, msg);
|
|
3328
3499
|
this.recordDebugEvent(sessionId, {
|
|
@@ -3681,11 +3852,10 @@ export class BridgeWebSocketServer {
|
|
|
3681
3852
|
}
|
|
3682
3853
|
}
|
|
3683
3854
|
shouldSendToClient(ws, msg) {
|
|
3684
|
-
|
|
3855
|
+
const type = typeof msg.type === "string" ? msg.type : "";
|
|
3856
|
+
if (!OPT_IN_SERVER_MESSAGES.has(type))
|
|
3685
3857
|
return true;
|
|
3686
|
-
return (this.clientSupportedServerMessages
|
|
3687
|
-
.get(ws)
|
|
3688
|
-
?.has("conversation_queue") ?? false);
|
|
3858
|
+
return (this.clientSupportedServerMessages.get(ws)?.has(type) ?? false);
|
|
3689
3859
|
}
|
|
3690
3860
|
hasInputConflictSince(sessionId, baseSeq) {
|
|
3691
3861
|
const delta = this.sessionManager.getHistorySince(sessionId, baseSeq);
|