@ccpocket/bridge 0.1.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/README.md +54 -0
- package/dist/claude-process.d.ts +108 -0
- package/dist/claude-process.js +471 -0
- package/dist/claude-process.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +42 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-process.d.ts +46 -0
- package/dist/codex-process.js +420 -0
- package/dist/codex-process.js.map +1 -0
- package/dist/debug-trace-store.d.ts +15 -0
- package/dist/debug-trace-store.js +78 -0
- package/dist/debug-trace-store.js.map +1 -0
- package/dist/firebase-auth.d.ts +35 -0
- package/dist/firebase-auth.js +132 -0
- package/dist/firebase-auth.js.map +1 -0
- package/dist/gallery-store.d.ts +66 -0
- package/dist/gallery-store.js +310 -0
- package/dist/gallery-store.js.map +1 -0
- package/dist/image-store.d.ts +22 -0
- package/dist/image-store.js +113 -0
- package/dist/image-store.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +153 -0
- package/dist/index.js.map +1 -0
- package/dist/mdns.d.ts +6 -0
- package/dist/mdns.js +42 -0
- package/dist/mdns.js.map +1 -0
- package/dist/parser.d.ts +381 -0
- package/dist/parser.js +218 -0
- package/dist/parser.js.map +1 -0
- package/dist/project-history.d.ts +10 -0
- package/dist/project-history.js +73 -0
- package/dist/project-history.js.map +1 -0
- package/dist/prompt-history-backup.d.ts +15 -0
- package/dist/prompt-history-backup.js +46 -0
- package/dist/prompt-history-backup.js.map +1 -0
- package/dist/push-relay.d.ts +27 -0
- package/dist/push-relay.js +69 -0
- package/dist/push-relay.js.map +1 -0
- package/dist/recording-store.d.ts +51 -0
- package/dist/recording-store.js +158 -0
- package/dist/recording-store.js.map +1 -0
- package/dist/screenshot.d.ts +28 -0
- package/dist/screenshot.js +98 -0
- package/dist/screenshot.js.map +1 -0
- package/dist/sdk-process.d.ts +151 -0
- package/dist/sdk-process.js +740 -0
- package/dist/sdk-process.js.map +1 -0
- package/dist/session.d.ts +126 -0
- package/dist/session.js +550 -0
- package/dist/session.js.map +1 -0
- package/dist/sessions-index.d.ts +86 -0
- package/dist/sessions-index.js +1027 -0
- package/dist/sessions-index.js.map +1 -0
- package/dist/setup-launchd.d.ts +8 -0
- package/dist/setup-launchd.js +109 -0
- package/dist/setup-launchd.js.map +1 -0
- package/dist/startup-info.d.ts +8 -0
- package/dist/startup-info.js +78 -0
- package/dist/startup-info.js.map +1 -0
- package/dist/usage.d.ts +17 -0
- package/dist/usage.js +236 -0
- package/dist/usage.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.js +39 -0
- package/dist/version.js.map +1 -0
- package/dist/websocket.d.ts +71 -0
- package/dist/websocket.js +1487 -0
- package/dist/websocket.js.map +1 -0
- package/dist/worktree-store.d.ts +25 -0
- package/dist/worktree-store.js +59 -0
- package/dist/worktree-store.js.map +1 -0
- package/dist/worktree.d.ts +43 -0
- package/dist/worktree.js +295 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +63 -0
package/dist/parser.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// ---- Helpers ----
|
|
2
|
+
/** Normalize tool_result content: may be string or array of content blocks. */
|
|
3
|
+
export function normalizeToolResultContent(content) {
|
|
4
|
+
if (Array.isArray(content)) {
|
|
5
|
+
return content
|
|
6
|
+
.filter((c) => c.type === "text")
|
|
7
|
+
.map((c) => c.text)
|
|
8
|
+
.join("\n");
|
|
9
|
+
}
|
|
10
|
+
return typeof content === "string" ? content : String(content ?? "");
|
|
11
|
+
}
|
|
12
|
+
// ---- Parser ----
|
|
13
|
+
export function parseClientMessage(data) {
|
|
14
|
+
try {
|
|
15
|
+
const msg = JSON.parse(data);
|
|
16
|
+
if (!msg.type || typeof msg.type !== "string")
|
|
17
|
+
return null;
|
|
18
|
+
switch (msg.type) {
|
|
19
|
+
case "start":
|
|
20
|
+
if (typeof msg.projectPath !== "string")
|
|
21
|
+
return null;
|
|
22
|
+
if (msg.model !== undefined && typeof msg.model !== "string")
|
|
23
|
+
return null;
|
|
24
|
+
if (msg.effort !== undefined && !["low", "medium", "high", "max"].includes(String(msg.effort)))
|
|
25
|
+
return null;
|
|
26
|
+
if (msg.maxTurns !== undefined
|
|
27
|
+
&& (!Number.isInteger(msg.maxTurns) || Number(msg.maxTurns) < 1))
|
|
28
|
+
return null;
|
|
29
|
+
if (msg.maxBudgetUsd !== undefined
|
|
30
|
+
&& (typeof msg.maxBudgetUsd !== "number" || !Number.isFinite(msg.maxBudgetUsd) || msg.maxBudgetUsd < 0))
|
|
31
|
+
return null;
|
|
32
|
+
if (msg.fallbackModel !== undefined && typeof msg.fallbackModel !== "string")
|
|
33
|
+
return null;
|
|
34
|
+
if (msg.forkSession !== undefined && typeof msg.forkSession !== "boolean")
|
|
35
|
+
return null;
|
|
36
|
+
if (msg.persistSession !== undefined && typeof msg.persistSession !== "boolean")
|
|
37
|
+
return null;
|
|
38
|
+
if (msg.networkAccessEnabled !== undefined && typeof msg.networkAccessEnabled !== "boolean")
|
|
39
|
+
return null;
|
|
40
|
+
if (msg.modelReasoningEffort !== undefined
|
|
41
|
+
&& !["minimal", "low", "medium", "high", "xhigh"].includes(String(msg.modelReasoningEffort)))
|
|
42
|
+
return null;
|
|
43
|
+
if (msg.webSearchMode !== undefined
|
|
44
|
+
&& !["disabled", "cached", "live"].includes(String(msg.webSearchMode)))
|
|
45
|
+
return null;
|
|
46
|
+
break;
|
|
47
|
+
case "input":
|
|
48
|
+
if (typeof msg.text !== "string")
|
|
49
|
+
return null;
|
|
50
|
+
// imageBase64 requires mimeType
|
|
51
|
+
if (msg.imageBase64 && typeof msg.mimeType !== "string")
|
|
52
|
+
return null;
|
|
53
|
+
break;
|
|
54
|
+
case "push_register":
|
|
55
|
+
if (typeof msg.token !== "string")
|
|
56
|
+
return null;
|
|
57
|
+
if (msg.platform !== "ios" && msg.platform !== "android" && msg.platform !== "web")
|
|
58
|
+
return null;
|
|
59
|
+
break;
|
|
60
|
+
case "push_unregister":
|
|
61
|
+
if (typeof msg.token !== "string")
|
|
62
|
+
return null;
|
|
63
|
+
break;
|
|
64
|
+
case "set_permission_mode":
|
|
65
|
+
if (typeof msg.mode !== "string"
|
|
66
|
+
|| !["default", "acceptEdits", "bypassPermissions", "plan"].includes(msg.mode))
|
|
67
|
+
return null;
|
|
68
|
+
break;
|
|
69
|
+
case "set_sandbox_mode":
|
|
70
|
+
if (typeof msg.sandboxMode !== "string")
|
|
71
|
+
return null;
|
|
72
|
+
break;
|
|
73
|
+
case "approve":
|
|
74
|
+
if (typeof msg.id !== "string")
|
|
75
|
+
return null;
|
|
76
|
+
break;
|
|
77
|
+
case "approve_always":
|
|
78
|
+
if (typeof msg.id !== "string")
|
|
79
|
+
return null;
|
|
80
|
+
break;
|
|
81
|
+
case "reject":
|
|
82
|
+
if (typeof msg.id !== "string")
|
|
83
|
+
return null;
|
|
84
|
+
break;
|
|
85
|
+
case "answer":
|
|
86
|
+
if (typeof msg.toolUseId !== "string" || typeof msg.result !== "string")
|
|
87
|
+
return null;
|
|
88
|
+
break;
|
|
89
|
+
case "list_sessions":
|
|
90
|
+
break;
|
|
91
|
+
case "stop_session":
|
|
92
|
+
if (typeof msg.sessionId !== "string")
|
|
93
|
+
return null;
|
|
94
|
+
break;
|
|
95
|
+
case "get_history":
|
|
96
|
+
if (typeof msg.sessionId !== "string")
|
|
97
|
+
return null;
|
|
98
|
+
break;
|
|
99
|
+
case "list_recent_sessions":
|
|
100
|
+
break;
|
|
101
|
+
case "resume_session":
|
|
102
|
+
if (typeof msg.sessionId !== "string" || typeof msg.projectPath !== "string")
|
|
103
|
+
return null;
|
|
104
|
+
if (msg.provider && msg.provider !== "claude" && msg.provider !== "codex")
|
|
105
|
+
return null;
|
|
106
|
+
if (msg.model !== undefined && typeof msg.model !== "string")
|
|
107
|
+
return null;
|
|
108
|
+
if (msg.effort !== undefined && !["low", "medium", "high", "max"].includes(String(msg.effort)))
|
|
109
|
+
return null;
|
|
110
|
+
if (msg.maxTurns !== undefined
|
|
111
|
+
&& (!Number.isInteger(msg.maxTurns) || Number(msg.maxTurns) < 1))
|
|
112
|
+
return null;
|
|
113
|
+
if (msg.maxBudgetUsd !== undefined
|
|
114
|
+
&& (typeof msg.maxBudgetUsd !== "number" || !Number.isFinite(msg.maxBudgetUsd) || msg.maxBudgetUsd < 0))
|
|
115
|
+
return null;
|
|
116
|
+
if (msg.fallbackModel !== undefined && typeof msg.fallbackModel !== "string")
|
|
117
|
+
return null;
|
|
118
|
+
if (msg.forkSession !== undefined && typeof msg.forkSession !== "boolean")
|
|
119
|
+
return null;
|
|
120
|
+
if (msg.persistSession !== undefined && typeof msg.persistSession !== "boolean")
|
|
121
|
+
return null;
|
|
122
|
+
if (msg.networkAccessEnabled !== undefined && typeof msg.networkAccessEnabled !== "boolean")
|
|
123
|
+
return null;
|
|
124
|
+
if (msg.modelReasoningEffort !== undefined
|
|
125
|
+
&& !["minimal", "low", "medium", "high", "xhigh"].includes(String(msg.modelReasoningEffort)))
|
|
126
|
+
return null;
|
|
127
|
+
if (msg.webSearchMode !== undefined
|
|
128
|
+
&& !["disabled", "cached", "live"].includes(String(msg.webSearchMode)))
|
|
129
|
+
return null;
|
|
130
|
+
break;
|
|
131
|
+
case "list_gallery":
|
|
132
|
+
break;
|
|
133
|
+
case "list_files":
|
|
134
|
+
if (typeof msg.projectPath !== "string")
|
|
135
|
+
return null;
|
|
136
|
+
break;
|
|
137
|
+
case "get_diff":
|
|
138
|
+
if (typeof msg.projectPath !== "string")
|
|
139
|
+
return null;
|
|
140
|
+
break;
|
|
141
|
+
case "interrupt":
|
|
142
|
+
break;
|
|
143
|
+
case "list_project_history":
|
|
144
|
+
break;
|
|
145
|
+
case "remove_project_history":
|
|
146
|
+
if (typeof msg.projectPath !== "string")
|
|
147
|
+
return null;
|
|
148
|
+
break;
|
|
149
|
+
case "list_worktrees":
|
|
150
|
+
if (typeof msg.projectPath !== "string")
|
|
151
|
+
return null;
|
|
152
|
+
break;
|
|
153
|
+
case "remove_worktree":
|
|
154
|
+
if (typeof msg.projectPath !== "string" || typeof msg.worktreePath !== "string")
|
|
155
|
+
return null;
|
|
156
|
+
break;
|
|
157
|
+
case "rewind":
|
|
158
|
+
if (typeof msg.sessionId !== "string" || typeof msg.targetUuid !== "string")
|
|
159
|
+
return null;
|
|
160
|
+
if (msg.mode !== "conversation" && msg.mode !== "code" && msg.mode !== "both")
|
|
161
|
+
return null;
|
|
162
|
+
break;
|
|
163
|
+
case "rewind_dry_run":
|
|
164
|
+
if (typeof msg.sessionId !== "string" || typeof msg.targetUuid !== "string")
|
|
165
|
+
return null;
|
|
166
|
+
break;
|
|
167
|
+
case "list_windows":
|
|
168
|
+
break;
|
|
169
|
+
case "take_screenshot":
|
|
170
|
+
if (msg.mode !== "fullscreen" && msg.mode !== "window")
|
|
171
|
+
return null;
|
|
172
|
+
if (msg.mode === "window" && typeof msg.windowId !== "number")
|
|
173
|
+
return null;
|
|
174
|
+
if (typeof msg.projectPath !== "string")
|
|
175
|
+
return null;
|
|
176
|
+
break;
|
|
177
|
+
case "get_debug_bundle":
|
|
178
|
+
if (typeof msg.sessionId !== "string")
|
|
179
|
+
return null;
|
|
180
|
+
if (msg.traceLimit !== undefined && typeof msg.traceLimit !== "number")
|
|
181
|
+
return null;
|
|
182
|
+
if (msg.includeDiff !== undefined && typeof msg.includeDiff !== "boolean")
|
|
183
|
+
return null;
|
|
184
|
+
break;
|
|
185
|
+
case "get_usage":
|
|
186
|
+
break;
|
|
187
|
+
case "list_recordings":
|
|
188
|
+
break;
|
|
189
|
+
case "get_recording":
|
|
190
|
+
if (typeof msg.sessionId !== "string")
|
|
191
|
+
return null;
|
|
192
|
+
break;
|
|
193
|
+
case "get_message_images":
|
|
194
|
+
if (typeof msg.claudeSessionId !== "string" || typeof msg.messageUuid !== "string")
|
|
195
|
+
return null;
|
|
196
|
+
break;
|
|
197
|
+
case "backup_prompt_history":
|
|
198
|
+
if (typeof msg.data !== "string")
|
|
199
|
+
return null;
|
|
200
|
+
if (typeof msg.appVersion !== "string")
|
|
201
|
+
return null;
|
|
202
|
+
if (typeof msg.dbVersion !== "number" || !Number.isInteger(msg.dbVersion))
|
|
203
|
+
return null;
|
|
204
|
+
break;
|
|
205
|
+
case "restore_prompt_history":
|
|
206
|
+
break;
|
|
207
|
+
case "get_prompt_history_backup_info":
|
|
208
|
+
break;
|
|
209
|
+
default:
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
return msg;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AA6NA,oBAAoB;AAEpB,+EAA+E;AAC/E,MAAM,UAAU,0BAA0B,CAAC,OAA2B;IACpE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAQ,OAA0C;aAC/C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC;aAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,mBAAmB;AAEnB,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QACxD,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3D,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,OAAO;gBACV,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC1E,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC5G,IACE,GAAG,CAAC,QAAQ,KAAK,SAAS;uBACvB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;oBAChE,OAAO,IAAI,CAAC;gBACd,IACE,GAAG,CAAC,YAAY,KAAK,SAAS;uBAC3B,CAAC,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC;oBACvG,OAAO,IAAI,CAAC;gBACd,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC1F,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBACvF,IAAI,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBAC7F,IAAI,GAAG,CAAC,oBAAoB,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,oBAAoB,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBACzG,IACE,GAAG,CAAC,oBAAoB,KAAK,SAAS;uBACnC,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;oBAC5F,OAAO,IAAI,CAAC;gBACd,IACE,GAAG,CAAC,aAAa,KAAK,SAAS;uBAC5B,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBACtE,OAAO,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC9C,gCAAgC;gBAChC,IAAI,GAAG,CAAC,WAAW,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrE,MAAM;YACR,KAAK,eAAe;gBAClB,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC/C,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK;oBAAE,OAAO,IAAI,CAAC;gBAChG,MAAM;YACR,KAAK,iBAAiB;gBACpB,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC/C,MAAM;YACR,KAAK,qBAAqB;gBACxB,IACE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;uBACzB,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;oBAC9E,OAAO,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,kBAAkB;gBACrB,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,MAAM;YACR,KAAK,SAAS;gBACZ,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC5C,MAAM;YACR,KAAK,gBAAgB;gBACnB,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC5C,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC5C,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrF,MAAM;YACR,KAAK,eAAe;gBAClB,MAAM;YACR,KAAK,cAAc;gBACjB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACnD,MAAM;YACR,KAAK,aAAa;gBAChB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACnD,MAAM;YACR,KAAK,sBAAsB;gBACzB,MAAM;YACR,KAAK,gBAAgB;gBACnB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC1F,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO;oBAAE,OAAO,IAAI,CAAC;gBACvF,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC1E,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC5G,IACE,GAAG,CAAC,QAAQ,KAAK,SAAS;uBACvB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;oBAChE,OAAO,IAAI,CAAC;gBACd,IACE,GAAG,CAAC,YAAY,KAAK,SAAS;uBAC3B,CAAC,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC;oBACvG,OAAO,IAAI,CAAC;gBACd,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC1F,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBACvF,IAAI,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBAC7F,IAAI,GAAG,CAAC,oBAAoB,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,oBAAoB,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBACzG,IACE,GAAG,CAAC,oBAAoB,KAAK,SAAS;uBACnC,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;oBAC5F,OAAO,IAAI,CAAC;gBACd,IACE,GAAG,CAAC,aAAa,KAAK,SAAS;uBAC5B,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBACtE,OAAO,IAAI,CAAC;gBACd,MAAM;YACR,KAAK,cAAc;gBACjB,MAAM;YACR,KAAK,YAAY;gBACf,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,MAAM;YACR,KAAK,WAAW;gBACd,MAAM;YACR,KAAK,sBAAsB;gBACzB,MAAM;YACR,KAAK,wBAAwB;gBAC3B,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,MAAM;YACR,KAAK,gBAAgB;gBACnB,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,MAAM;YACR,KAAK,iBAAiB;gBACpB,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC7F,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACzF,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;oBAAE,OAAO,IAAI,CAAC;gBAC3F,MAAM;YACR,KAAK,gBAAgB;gBACnB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACzF,MAAM;YACR,KAAK,cAAc;gBACjB,MAAM;YACR,KAAK,iBAAiB;gBACpB,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACpE,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC3E,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACrD,MAAM;YACR,KAAK,kBAAkB;gBACrB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACnD,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACpF,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,SAAS;oBAAE,OAAO,IAAI,CAAC;gBACvF,MAAM;YACR,KAAK,WAAW;gBACd,MAAM;YACR,KAAK,iBAAiB;gBACpB,MAAM;YACR,KAAK,eAAe;gBAClB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACnD,MAAM;YACR,KAAK,oBAAoB;gBACvB,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAChG,MAAM;YACR,KAAK,uBAAuB;gBAC1B,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC9C,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBACpD,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;oBAAE,OAAO,IAAI,CAAC;gBACvF,MAAM;YACR,KAAK,wBAAwB;gBAC3B,MAAM;YACR,KAAK,gCAAgC;gBACnC,MAAM;YACR;gBACE,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,GAA+B,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class ProjectHistory {
|
|
2
|
+
private projects;
|
|
3
|
+
private readonly filePath;
|
|
4
|
+
constructor(filePath?: string);
|
|
5
|
+
init(): Promise<void>;
|
|
6
|
+
addProject(path: string): void;
|
|
7
|
+
getProjects(): string[];
|
|
8
|
+
removeProject(path: string): void;
|
|
9
|
+
private saveIndex;
|
|
10
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { normalizeWorktreePath } from "./sessions-index.js";
|
|
5
|
+
const DEFAULT_HISTORY_FILE = join(homedir(), ".ccpocket", "project-history.json");
|
|
6
|
+
const MAX_PROJECTS = 20;
|
|
7
|
+
/** Minimum path depth to be considered a valid project path (e.g. /Users/name/project = 3). */
|
|
8
|
+
const MIN_PATH_SEGMENTS = 3;
|
|
9
|
+
function isValidProjectPath(path) {
|
|
10
|
+
if (!path.startsWith("/"))
|
|
11
|
+
return false;
|
|
12
|
+
const segments = path.split("/").filter(Boolean);
|
|
13
|
+
return segments.length >= MIN_PATH_SEGMENTS;
|
|
14
|
+
}
|
|
15
|
+
export class ProjectHistory {
|
|
16
|
+
projects = [];
|
|
17
|
+
filePath;
|
|
18
|
+
constructor(filePath) {
|
|
19
|
+
this.filePath = filePath ?? DEFAULT_HISTORY_FILE;
|
|
20
|
+
}
|
|
21
|
+
async init() {
|
|
22
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
23
|
+
try {
|
|
24
|
+
const data = await readFile(this.filePath, "utf-8");
|
|
25
|
+
const parsed = JSON.parse(data);
|
|
26
|
+
if (Array.isArray(parsed)) {
|
|
27
|
+
const raw = parsed.filter((p) => typeof p === "string");
|
|
28
|
+
// Normalize worktree paths and deduplicate (keep first occurrence)
|
|
29
|
+
const seen = new Set();
|
|
30
|
+
this.projects = raw
|
|
31
|
+
.map(normalizeWorktreePath)
|
|
32
|
+
.filter(isValidProjectPath)
|
|
33
|
+
.filter((p) => seen.has(p) ? false : (seen.add(p), true));
|
|
34
|
+
// Persist cleaned data if invalid entries were removed
|
|
35
|
+
if (this.projects.length < raw.length) {
|
|
36
|
+
this.saveIndex().catch(() => { });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// File doesn't exist or is corrupt — start fresh
|
|
42
|
+
this.projects = [];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
addProject(path) {
|
|
46
|
+
const normalized = normalizeWorktreePath(path);
|
|
47
|
+
if (!isValidProjectPath(normalized))
|
|
48
|
+
return;
|
|
49
|
+
// Remove existing entry (if any) and add to front
|
|
50
|
+
this.projects = this.projects.filter((p) => p !== normalized);
|
|
51
|
+
this.projects.unshift(normalized);
|
|
52
|
+
// Enforce max limit
|
|
53
|
+
if (this.projects.length > MAX_PROJECTS) {
|
|
54
|
+
this.projects = this.projects.slice(0, MAX_PROJECTS);
|
|
55
|
+
}
|
|
56
|
+
this.saveIndex().catch((err) => {
|
|
57
|
+
console.error("[project-history] Failed to save:", err);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
getProjects() {
|
|
61
|
+
return [...this.projects];
|
|
62
|
+
}
|
|
63
|
+
removeProject(path) {
|
|
64
|
+
this.projects = this.projects.filter((p) => p !== path);
|
|
65
|
+
this.saveIndex().catch((err) => {
|
|
66
|
+
console.error("[project-history] Failed to save:", err);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
async saveIndex() {
|
|
70
|
+
await writeFile(this.filePath, JSON.stringify(this.projects, null, 2), "utf-8");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=project-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-history.js","sourceRoot":"","sources":["../src/project-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BackupMeta {
|
|
2
|
+
appVersion: string;
|
|
3
|
+
dbVersion: number;
|
|
4
|
+
backedUpAt: string;
|
|
5
|
+
sizeBytes: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class PromptHistoryBackupStore {
|
|
8
|
+
init(): Promise<void>;
|
|
9
|
+
save(data: Buffer, appVersion: string, dbVersion: number): Promise<BackupMeta>;
|
|
10
|
+
load(): Promise<{
|
|
11
|
+
data: Buffer;
|
|
12
|
+
meta: BackupMeta;
|
|
13
|
+
} | null>;
|
|
14
|
+
getMeta(): Promise<BackupMeta | null>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const BACKUP_DIR = join(homedir(), ".ccpocket", "prompt-history-backup");
|
|
5
|
+
const BACKUP_FILE = join(BACKUP_DIR, "backup.db");
|
|
6
|
+
const META_FILE = join(BACKUP_DIR, "meta.json");
|
|
7
|
+
export class PromptHistoryBackupStore {
|
|
8
|
+
async init() {
|
|
9
|
+
await mkdir(BACKUP_DIR, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
async save(data, appVersion, dbVersion) {
|
|
12
|
+
await mkdir(BACKUP_DIR, { recursive: true });
|
|
13
|
+
await writeFile(BACKUP_FILE, data);
|
|
14
|
+
const meta = {
|
|
15
|
+
appVersion,
|
|
16
|
+
dbVersion,
|
|
17
|
+
backedUpAt: new Date().toISOString(),
|
|
18
|
+
sizeBytes: data.length,
|
|
19
|
+
};
|
|
20
|
+
await writeFile(META_FILE, JSON.stringify(meta, null, 2), "utf-8");
|
|
21
|
+
return meta;
|
|
22
|
+
}
|
|
23
|
+
async load() {
|
|
24
|
+
try {
|
|
25
|
+
const [data, metaRaw] = await Promise.all([
|
|
26
|
+
readFile(BACKUP_FILE),
|
|
27
|
+
readFile(META_FILE, "utf-8"),
|
|
28
|
+
]);
|
|
29
|
+
const meta = JSON.parse(metaRaw);
|
|
30
|
+
return { data, meta };
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async getMeta() {
|
|
37
|
+
try {
|
|
38
|
+
const metaRaw = await readFile(META_FILE, "utf-8");
|
|
39
|
+
return JSON.parse(metaRaw);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=prompt-history-backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-history-backup.js","sourceRoot":"","sources":["../src/prompt-history-backup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AASlC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,uBAAuB,CAAC,CAAC;AACzE,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAEhD,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,UAAkB,EAAE,SAAiB;QAC5D,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACnC,MAAM,IAAI,GAAe;YACvB,UAAU;YACV,SAAS;YACT,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,SAAS,EAAE,IAAI,CAAC,MAAM;SACvB,CAAC;QACF,MAAM,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACxC,QAAQ,CAAC,WAAW,CAAC;gBACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7B,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;YAC/C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FirebaseAuthClient } from "./firebase-auth.js";
|
|
2
|
+
export type PushPlatform = "ios" | "android" | "web";
|
|
3
|
+
export interface PushNotifyPayload {
|
|
4
|
+
eventType: string;
|
|
5
|
+
title: string;
|
|
6
|
+
body: string;
|
|
7
|
+
data?: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
export interface PushRelayClientOptions {
|
|
10
|
+
relayUrl?: string;
|
|
11
|
+
firebaseAuth?: FirebaseAuthClient | null;
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
fetchImpl?: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
export declare class PushRelayClient {
|
|
16
|
+
private readonly relayUrl;
|
|
17
|
+
private readonly firebaseAuth;
|
|
18
|
+
private readonly timeoutMs;
|
|
19
|
+
private readonly fetchImpl;
|
|
20
|
+
constructor(options?: PushRelayClientOptions);
|
|
21
|
+
get isConfigured(): boolean;
|
|
22
|
+
private get bridgeId();
|
|
23
|
+
registerToken(token: string, platform: PushPlatform): Promise<void>;
|
|
24
|
+
unregisterToken(token: string): Promise<void>;
|
|
25
|
+
notify(payload: PushNotifyPayload): Promise<void>;
|
|
26
|
+
private post;
|
|
27
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const DEFAULT_RELAY_URL = "https://us-central1-ccpocket-ca33b.cloudfunctions.net/relay";
|
|
2
|
+
export class PushRelayClient {
|
|
3
|
+
relayUrl;
|
|
4
|
+
firebaseAuth;
|
|
5
|
+
timeoutMs;
|
|
6
|
+
fetchImpl;
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.relayUrl = options.relayUrl ?? DEFAULT_RELAY_URL;
|
|
9
|
+
this.firebaseAuth = options.firebaseAuth ?? null;
|
|
10
|
+
this.timeoutMs = options.timeoutMs ?? 10_000;
|
|
11
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
12
|
+
}
|
|
13
|
+
get isConfigured() {
|
|
14
|
+
return this.firebaseAuth != null;
|
|
15
|
+
}
|
|
16
|
+
get bridgeId() {
|
|
17
|
+
return this.firebaseAuth.uid;
|
|
18
|
+
}
|
|
19
|
+
async registerToken(token, platform) {
|
|
20
|
+
if (!this.isConfigured)
|
|
21
|
+
return;
|
|
22
|
+
await this.post({ op: "register", token, platform, bridgeId: this.bridgeId });
|
|
23
|
+
}
|
|
24
|
+
async unregisterToken(token) {
|
|
25
|
+
if (!this.isConfigured)
|
|
26
|
+
return;
|
|
27
|
+
await this.post({ op: "unregister", token, bridgeId: this.bridgeId });
|
|
28
|
+
}
|
|
29
|
+
async notify(payload) {
|
|
30
|
+
if (!this.isConfigured)
|
|
31
|
+
return;
|
|
32
|
+
await this.post({
|
|
33
|
+
op: "notify",
|
|
34
|
+
bridgeId: this.bridgeId,
|
|
35
|
+
eventType: payload.eventType,
|
|
36
|
+
title: payload.title,
|
|
37
|
+
body: payload.body,
|
|
38
|
+
data: payload.data,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async post(payload) {
|
|
42
|
+
if (!this.isConfigured || !this.firebaseAuth)
|
|
43
|
+
return;
|
|
44
|
+
console.log(`[push-relay] ${payload.op} → ${this.relayUrl} (bridgeId: ${payload.bridgeId})`);
|
|
45
|
+
const idToken = await this.firebaseAuth.getIdToken();
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
48
|
+
try {
|
|
49
|
+
const response = await this.fetchImpl(this.relayUrl, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: {
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
"Authorization": `Bearer ${idToken}`,
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify(payload),
|
|
56
|
+
signal: controller.signal,
|
|
57
|
+
});
|
|
58
|
+
const responseText = (await response.text()).trim().slice(0, 200);
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
throw new Error(`Push relay returned ${response.status}${responseText ? `: ${responseText}` : ""}`);
|
|
61
|
+
}
|
|
62
|
+
console.log(`[push-relay] ${payload.op} OK: ${responseText}`);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=push-relay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-relay.js","sourceRoot":"","sources":["../src/push-relay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ClientMessage, ServerMessage } from "./parser.js";
|
|
2
|
+
export interface RecordingMeta {
|
|
3
|
+
bridgeSessionId: string;
|
|
4
|
+
claudeSessionId?: string;
|
|
5
|
+
projectPath: string;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RecordingFileInfo {
|
|
9
|
+
name: string;
|
|
10
|
+
path: string;
|
|
11
|
+
modified: string;
|
|
12
|
+
sizeBytes: number;
|
|
13
|
+
meta?: RecordingMeta;
|
|
14
|
+
summary?: string;
|
|
15
|
+
firstPrompt?: string;
|
|
16
|
+
lastPrompt?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RecordedEvent {
|
|
19
|
+
ts: string;
|
|
20
|
+
direction: "outgoing" | "incoming";
|
|
21
|
+
message: ServerMessage | ClientMessage;
|
|
22
|
+
}
|
|
23
|
+
export declare class RecordingStore {
|
|
24
|
+
private recordingDir;
|
|
25
|
+
private writeChains;
|
|
26
|
+
constructor(rootDir?: string);
|
|
27
|
+
init(): Promise<void>;
|
|
28
|
+
getFilePath(sessionId: string): string;
|
|
29
|
+
private getMetaPath;
|
|
30
|
+
/** Save or update session metadata alongside the recording. */
|
|
31
|
+
saveMeta(sessionId: string, meta: RecordingMeta): void;
|
|
32
|
+
/** Read session metadata. */
|
|
33
|
+
getMeta(sessionId: string): Promise<RecordingMeta | null>;
|
|
34
|
+
record(sessionId: string, direction: "outgoing" | "incoming", message: ServerMessage | ClientMessage): void;
|
|
35
|
+
/** List all recording files, newest first, with metadata if available. */
|
|
36
|
+
listRecordings(): Promise<RecordingFileInfo[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Extract key info directly from JSONL content without requiring meta or sessions-index.
|
|
39
|
+
* Scans for first/last user input messages and claudeSessionId from system messages.
|
|
40
|
+
*/
|
|
41
|
+
extractInfoFromJsonl(sessionId: string): Promise<{
|
|
42
|
+
firstPrompt?: string;
|
|
43
|
+
lastPrompt?: string;
|
|
44
|
+
claudeSessionId?: string;
|
|
45
|
+
projectPath?: string;
|
|
46
|
+
}>;
|
|
47
|
+
/** Read recording content as string. */
|
|
48
|
+
getRecordingContent(sessionId: string): Promise<string | null>;
|
|
49
|
+
flush(): Promise<void>;
|
|
50
|
+
private enqueue;
|
|
51
|
+
}
|