browser-cookie-bridge 1.5.4 → 1.5.6
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/extension-template/manifest.json +1 -1
- package/macos-app/Info.plist +2 -2
- package/macos-app/Sources/BraveCodexSyncApp/BraveCodexSyncApp.swift +66 -4
- package/macos-app/Sources/BraveCodexSyncApp/SyncModel.swift +32 -5
- package/package.json +1 -1
- package/src/cli.js +3 -5
- package/src/grok-bot-export.js +5 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Browser Cookie Bridge",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.6",
|
|
5
5
|
"description": "Transfers selected browser data locally between supported browsers and embedded app browsers.",
|
|
6
6
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5o6lDkXzU/23Jm2QRk4mfuxNnr3VlEIjRHcZr93Gdo7PI7asHJQhigaMGT6UOz0lkaTn1F+TGIPlsJo9GNBSsxbCfxWoBSXcFQFrPolY5LEfKaMtZQQ6eb4UAnp+bbUwb1den4On0piWU47Yzl6i0Jcdg4EG5H1kCSF/6nJsbKgF7OTaR/3drULu40yRvflzSXRhly3UDO7c5mgHJsaMwVV+VILsxbcPOoRINjuo3zDC737HFs67dpf38xF3tjSVL0HURAWKKobMvfABiDfVEm5O0Lvf+57d1Ib12QLT2qtVXNDy3iYwX+w2S0wH2vIMsfvoFPlRdmeqft70kZOqXwIDAQAB",
|
|
7
7
|
"permissions": ["alarms", "cookies", "history"],
|
package/macos-app/Info.plist
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
|
|
11
11
|
<key>CFBundleName</key><string>Browser Cookie Bridge</string>
|
|
12
12
|
<key>CFBundlePackageType</key><string>APPL</string>
|
|
13
|
-
<key>CFBundleShortVersionString</key><string>1.5.
|
|
14
|
-
<key>CFBundleVersion</key><string>
|
|
13
|
+
<key>CFBundleShortVersionString</key><string>1.5.6</string>
|
|
14
|
+
<key>CFBundleVersion</key><string>43</string>
|
|
15
15
|
<key>LSMinimumSystemVersion</key><string>13.5</string>
|
|
16
16
|
<key>NSHighResolutionCapable</key><true/>
|
|
17
17
|
</dict>
|
|
@@ -34,6 +34,7 @@ struct BraveCodexSyncApp: App {
|
|
|
34
34
|
final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|
35
35
|
weak var model: SyncModel?
|
|
36
36
|
private weak var mainWindow: NSWindow?
|
|
37
|
+
private var grokBotResultPanel: NSPanel?
|
|
37
38
|
private var statusItem: NSStatusItem?
|
|
38
39
|
private var syncMenuItem: NSMenuItem?
|
|
39
40
|
private var updateMenuItem: NSMenuItem?
|
|
@@ -63,6 +64,18 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|
|
63
64
|
name: .syncStateChanged,
|
|
64
65
|
object: nil
|
|
65
66
|
)
|
|
67
|
+
NotificationCenter.default.addObserver(
|
|
68
|
+
self,
|
|
69
|
+
selector: #selector(showMainWindowNotification(_:)),
|
|
70
|
+
name: .showMainWindow,
|
|
71
|
+
object: nil
|
|
72
|
+
)
|
|
73
|
+
NotificationCenter.default.addObserver(
|
|
74
|
+
self,
|
|
75
|
+
selector: #selector(presentGrokBotResultNotification(_:)),
|
|
76
|
+
name: .presentGrokBotResult,
|
|
77
|
+
object: nil
|
|
78
|
+
)
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { false }
|
|
@@ -186,8 +199,56 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|
|
186
199
|
}
|
|
187
200
|
}
|
|
188
201
|
|
|
202
|
+
@objc private func showMainWindowNotification(_ notification: Notification) {
|
|
203
|
+
showMainWindow()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@objc private func presentGrokBotResultNotification(_ notification: Notification) {
|
|
207
|
+
guard let model else { return }
|
|
208
|
+
showMainWindow()
|
|
209
|
+
grokBotResultPanel?.close()
|
|
210
|
+
grokBotResultPanel = nil
|
|
211
|
+
DispatchQueue.main.async { [weak self] in
|
|
212
|
+
guard let self, let model = self.model else { return }
|
|
213
|
+
self.presentGrokBotResultPanel(model: model)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private func presentGrokBotResultPanel(model: SyncModel) {
|
|
218
|
+
let panel = NSPanel(
|
|
219
|
+
contentRect: NSRect(x: 0, y: 0, width: 520, height: 520),
|
|
220
|
+
styleMask: [.titled, .closable, .fullSizeContentView],
|
|
221
|
+
backing: .buffered,
|
|
222
|
+
defer: false
|
|
223
|
+
)
|
|
224
|
+
panel.title = "Grok Bot transfer ready"
|
|
225
|
+
panel.titlebarAppearsTransparent = false
|
|
226
|
+
panel.isFloatingPanel = true
|
|
227
|
+
panel.level = .modalPanel
|
|
228
|
+
panel.collectionBehavior = [.moveToActiveSpace, .fullScreenAuxiliary]
|
|
229
|
+
panel.isReleasedWhenClosed = false
|
|
230
|
+
panel.center()
|
|
231
|
+
let dismissPanel = { [weak self] in
|
|
232
|
+
self?.grokBotResultPanel?.close()
|
|
233
|
+
self?.grokBotResultPanel = nil
|
|
234
|
+
}
|
|
235
|
+
panel.contentView = NSHostingView(
|
|
236
|
+
rootView: GrokBotResultSheet(onDone: dismissPanel).environmentObject(model)
|
|
237
|
+
)
|
|
238
|
+
panel.makeKeyAndOrderFront(nil)
|
|
239
|
+
NSApp.activate(ignoringOtherApps: true)
|
|
240
|
+
grokBotResultPanel = panel
|
|
241
|
+
}
|
|
242
|
+
|
|
189
243
|
private func showMainWindow() {
|
|
190
244
|
NSApp.setActivationPolicy(.regular)
|
|
245
|
+
if mainWindow == nil || mainWindow?.isVisible == false {
|
|
246
|
+
let candidate = NSApp.windows.first(where: { $0.canBecomeMain && $0.title == "Browser Cookie Bridge" })
|
|
247
|
+
?? NSApp.windows.first(where: { $0.canBecomeMain })
|
|
248
|
+
?? NSApp.windows.first
|
|
249
|
+
mainWindow = candidate
|
|
250
|
+
mainWindow?.delegate = self
|
|
251
|
+
}
|
|
191
252
|
mainWindow?.makeKeyAndOrderFront(nil)
|
|
192
253
|
NSApp.activate(ignoringOtherApps: true)
|
|
193
254
|
}
|
|
@@ -241,9 +302,6 @@ struct ContentView: View {
|
|
|
241
302
|
.sheet(isPresented: $model.showingBrowserlessSetup) {
|
|
242
303
|
BrowserlessSetupSheet().environmentObject(model)
|
|
243
304
|
}
|
|
244
|
-
.sheet(isPresented: $model.showingGrokBotResult) {
|
|
245
|
-
GrokBotResultSheet().environmentObject(model)
|
|
246
|
-
}
|
|
247
305
|
}
|
|
248
306
|
|
|
249
307
|
private var header: some View {
|
|
@@ -1170,6 +1228,7 @@ enum Theme {
|
|
|
1170
1228
|
struct GrokBotResultSheet: View {
|
|
1171
1229
|
@EnvironmentObject private var model: SyncModel
|
|
1172
1230
|
@Environment(\.dismiss) private var dismiss
|
|
1231
|
+
var onDone: (() -> Void)?
|
|
1173
1232
|
|
|
1174
1233
|
var body: some View {
|
|
1175
1234
|
VStack(alignment: .leading, spacing: 16) {
|
|
@@ -1228,7 +1287,10 @@ struct GrokBotResultSheet: View {
|
|
|
1228
1287
|
NSPasteboard.general.setString(model.grokBotPrompt, forType: .string)
|
|
1229
1288
|
}
|
|
1230
1289
|
Spacer()
|
|
1231
|
-
Button("Done") {
|
|
1290
|
+
Button("Done") {
|
|
1291
|
+
onDone?()
|
|
1292
|
+
dismiss()
|
|
1293
|
+
}
|
|
1232
1294
|
.keyboardShortcut(.defaultAction)
|
|
1233
1295
|
}
|
|
1234
1296
|
.controlSize(.regular)
|
|
@@ -8,6 +8,8 @@ extension Notification.Name {
|
|
|
8
8
|
static let nativeAlert = Notification.Name("BraveCodexSync.nativeAlert")
|
|
9
9
|
static let updateStateChanged = Notification.Name("BraveCodexSync.updateStateChanged")
|
|
10
10
|
static let syncStateChanged = Notification.Name("BraveCodexSync.syncStateChanged")
|
|
11
|
+
static let showMainWindow = Notification.Name("BraveCodexSync.showMainWindow")
|
|
12
|
+
static let presentGrokBotResult = Notification.Name("BraveCodexSync.presentGrokBotResult")
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
struct NativeAlert {
|
|
@@ -99,7 +101,6 @@ final class SyncModel: ObservableObject {
|
|
|
99
101
|
@Published var browserlessOnlyDomains = ""
|
|
100
102
|
@Published var grokBotOnlyDomains = ""
|
|
101
103
|
@Published var showingBrowserlessSetup = false
|
|
102
|
-
@Published var showingGrokBotResult = false
|
|
103
104
|
@Published var grokBotPrompt = ""
|
|
104
105
|
@Published var grokBotOutputPath = ""
|
|
105
106
|
@Published var browserlessAssessment: BrowserlessProfileAssessment?
|
|
@@ -118,6 +119,16 @@ final class SyncModel: ObservableObject {
|
|
|
118
119
|
private var appLoginAgent: URL { home.appending(path: "Library/LaunchAgents/com.apoorvdarshan.brave-codex-cookie-sync.app-login.plist") }
|
|
119
120
|
private var endpointStatusTimer: Timer?
|
|
120
121
|
private var updateTimer: Timer?
|
|
122
|
+
private var activeGrokBotOutputPath: String?
|
|
123
|
+
|
|
124
|
+
private static let grokBotFallbackPrompt = """
|
|
125
|
+
On your Grok Bot cloud computer only — do not access my local Mac and do not print cookie values.
|
|
126
|
+
|
|
127
|
+
1. Save the attached GrokBot-Import.bcbx to the cloud computer.
|
|
128
|
+
2. Unzip it: unzip -o GrokBot-Import.bcbx -d bcb-import && cd bcb-import
|
|
129
|
+
3. Run: node import.mjs
|
|
130
|
+
4. Report only how many cookies were imported per domain, then delete the bcb-import folder and any copies of the bundle.
|
|
131
|
+
"""
|
|
121
132
|
private var didCheckAfterLaunch = false
|
|
122
133
|
private var didConsumeUpdateResult = false
|
|
123
134
|
private var assessedBrowserID: String?
|
|
@@ -725,7 +736,10 @@ final class SyncModel: ObservableObject {
|
|
|
725
736
|
var environment: [String: String] = [:]
|
|
726
737
|
var arguments = ["sync", "--timeout", isBrowserlessTarget ? "900" : "300"]
|
|
727
738
|
if let grokBotOutputPath {
|
|
739
|
+
activeGrokBotOutputPath = grokBotOutputPath
|
|
728
740
|
arguments.append(contentsOf: ["--output", grokBotOutputPath])
|
|
741
|
+
} else {
|
|
742
|
+
activeGrokBotOutputPath = nil
|
|
729
743
|
}
|
|
730
744
|
if isBrowserlessTarget {
|
|
731
745
|
guard let token = BrowserlessCredentialStore.read() else {
|
|
@@ -758,10 +772,14 @@ final class SyncModel: ObservableObject {
|
|
|
758
772
|
self.secondaryStatus = "No cloud profile was changed; temporary profile data was removed"
|
|
759
773
|
} else if success {
|
|
760
774
|
self.state = partial ? .warning : .success
|
|
761
|
-
if self.isGrokBotTarget
|
|
762
|
-
|
|
763
|
-
self.grokBotOutputPath
|
|
764
|
-
|
|
775
|
+
if self.isGrokBotTarget {
|
|
776
|
+
let parsed = self.parseGrokBotResult(from: output)
|
|
777
|
+
let outputPath = parsed?.outputPath ?? self.activeGrokBotOutputPath ?? grokBotOutputPath ?? self.grokBotOutputPath
|
|
778
|
+
let prompt = parsed?.prompt ?? Self.grokBotFallbackPrompt
|
|
779
|
+
if !outputPath.isEmpty {
|
|
780
|
+
self.presentGrokBotResultSheet(prompt: prompt, outputPath: outputPath)
|
|
781
|
+
}
|
|
782
|
+
self.activeGrokBotOutputPath = nil
|
|
765
783
|
self.primaryStatus = partial ? "Grok Bot transfer created with warnings" : "Grok Bot transfer file ready"
|
|
766
784
|
self.secondaryStatus = self.lastMeaningfulLine(output) ?? "Attach the .bcbx file to any Grok Bot and paste the prompt"
|
|
767
785
|
} else {
|
|
@@ -1183,6 +1201,15 @@ final class SyncModel: ObservableObject {
|
|
|
1183
1201
|
return try? JSONDecoder().decode(GrokBotResultPayload.self, from: data)
|
|
1184
1202
|
}
|
|
1185
1203
|
|
|
1204
|
+
private func presentGrokBotResultSheet(prompt: String, outputPath: String) {
|
|
1205
|
+
grokBotPrompt = prompt
|
|
1206
|
+
grokBotOutputPath = outputPath
|
|
1207
|
+
NSPasteboard.general.clearContents()
|
|
1208
|
+
NSPasteboard.general.setString(prompt, forType: .string)
|
|
1209
|
+
NotificationCenter.default.post(name: .showMainWindow, object: nil)
|
|
1210
|
+
NotificationCenter.default.post(name: .presentGrokBotResult, object: nil)
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1186
1213
|
private func updateEndpointRunningStatus() {
|
|
1187
1214
|
let wasDirectTargetRunning = directTargetRunning
|
|
1188
1215
|
codexRunning = NSWorkspace.shared.runningApplications.contains {
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -13,6 +13,7 @@ import { isChromiumBrowserRunning, readChromiumProfile } from "./chromium-reader
|
|
|
13
13
|
import { uploadBrowserlessProfile } from "./browserless.js";
|
|
14
14
|
import { inspectBrowserlessProfile } from "./browserless-preflight.js";
|
|
15
15
|
import {
|
|
16
|
+
formatGrokBotResultLine,
|
|
16
17
|
grokBotSummary,
|
|
17
18
|
writeGrokBotBundle,
|
|
18
19
|
} from "./grok-bot-export.js";
|
|
@@ -310,13 +311,10 @@ async function sync(args, { signal } = {}) {
|
|
|
310
311
|
});
|
|
311
312
|
result.sourceCookieSkipped = payload.cookieStats.skipped;
|
|
312
313
|
console.log(grokBotSummary(result));
|
|
313
|
-
console.log(
|
|
314
|
+
console.log(formatGrokBotResultLine({
|
|
314
315
|
outputPath: result.outputPath,
|
|
315
|
-
cookieCount: result.cookieCount,
|
|
316
|
-
domainCount: result.domainCount,
|
|
317
|
-
domains: result.domains,
|
|
318
316
|
prompt: result.prompt,
|
|
319
|
-
})
|
|
317
|
+
}));
|
|
320
318
|
return result;
|
|
321
319
|
}
|
|
322
320
|
if (target === "browserless") {
|
package/src/grok-bot-export.js
CHANGED
|
@@ -157,6 +157,11 @@ export function grokBotSummary(result) {
|
|
|
157
157
|
return `Grok Bot transfer file created: ${result.cookieCount} cookies across ${domainNote} from ${result.sourceBrowser}.${skipped} Attach ${path.basename(result.outputPath)} to any Grok Bot and paste the prompt. The bundle includes the decryption key—treat the file as credentials and do not share it.`;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
/** Machine-readable sync result for the macOS app (keep small — no domain lists). */
|
|
161
|
+
export function formatGrokBotResultLine({ outputPath, prompt }) {
|
|
162
|
+
return `BCB_GROK_RESULT ${JSON.stringify({ outputPath, prompt })}`;
|
|
163
|
+
}
|
|
164
|
+
|
|
160
165
|
export function filterCookies(cookies, onlyDomains = []) {
|
|
161
166
|
const domains = normalizeDomainFilters(onlyDomains);
|
|
162
167
|
if (!domains.length) return cookies;
|