@flrande/bak-extension 0.6.3 → 0.6.5
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/.bak-e2e-build-stamp +1 -1
- package/dist/background.global.js +267 -55
- package/dist/manifest.json +1 -1
- package/dist/popup.global.js +92 -2
- package/dist/popup.html +72 -1
- package/package.json +2 -2
- package/public/popup.html +72 -1
- package/src/background.ts +355 -134
- package/src/popup.ts +135 -11
- package/src/session-binding.ts +132 -74
package/dist/popup.global.js
CHANGED
|
@@ -6,18 +6,97 @@
|
|
|
6
6
|
var portInput = document.getElementById("port");
|
|
7
7
|
var debugRichTextInput = document.getElementById("debugRichText");
|
|
8
8
|
var saveBtn = document.getElementById("save");
|
|
9
|
+
var reconnectBtn = document.getElementById("reconnect");
|
|
9
10
|
var disconnectBtn = document.getElementById("disconnect");
|
|
11
|
+
var connectionStateEl = document.getElementById("connectionState");
|
|
12
|
+
var tokenStateEl = document.getElementById("tokenState");
|
|
13
|
+
var reconnectStateEl = document.getElementById("reconnectState");
|
|
14
|
+
var connectionUrlEl = document.getElementById("connectionUrl");
|
|
15
|
+
var lastErrorEl = document.getElementById("lastError");
|
|
16
|
+
var lastBindingUpdateEl = document.getElementById("lastBindingUpdate");
|
|
17
|
+
var extensionVersionEl = document.getElementById("extensionVersion");
|
|
18
|
+
var sessionSummaryEl = document.getElementById("sessionSummary");
|
|
19
|
+
var sessionListEl = document.getElementById("sessionList");
|
|
20
|
+
var latestState = null;
|
|
10
21
|
function setStatus(text, bad = false) {
|
|
11
22
|
statusEl.textContent = text;
|
|
12
23
|
statusEl.style.color = bad ? "#dc2626" : "#0f172a";
|
|
13
24
|
}
|
|
25
|
+
function formatTimeAgo(at) {
|
|
26
|
+
if (typeof at !== "number") {
|
|
27
|
+
return "never";
|
|
28
|
+
}
|
|
29
|
+
const deltaSeconds = Math.max(0, Math.round((Date.now() - at) / 1e3));
|
|
30
|
+
if (deltaSeconds < 5) {
|
|
31
|
+
return "just now";
|
|
32
|
+
}
|
|
33
|
+
if (deltaSeconds < 60) {
|
|
34
|
+
return `${deltaSeconds}s ago`;
|
|
35
|
+
}
|
|
36
|
+
const deltaMinutes = Math.round(deltaSeconds / 60);
|
|
37
|
+
if (deltaMinutes < 60) {
|
|
38
|
+
return `${deltaMinutes}m ago`;
|
|
39
|
+
}
|
|
40
|
+
const deltaHours = Math.round(deltaMinutes / 60);
|
|
41
|
+
return `${deltaHours}h ago`;
|
|
42
|
+
}
|
|
43
|
+
function renderSessionBindings(state) {
|
|
44
|
+
sessionSummaryEl.textContent = `${state.count} sessions, ${state.attachedCount} attached, ${state.tabCount} tabs, ${state.detachedCount} detached`;
|
|
45
|
+
sessionListEl.replaceChildren();
|
|
46
|
+
for (const item of state.items) {
|
|
47
|
+
const li = document.createElement("li");
|
|
48
|
+
const location = item.windowId === null ? "no window" : `window ${item.windowId}`;
|
|
49
|
+
const active = item.activeTabId === null ? "no active tab" : `active ${item.activeTabId}`;
|
|
50
|
+
li.textContent = `${item.label}: ${item.tabCount} tabs, ${location}, ${active}`;
|
|
51
|
+
if (item.detached) {
|
|
52
|
+
li.style.color = "#b45309";
|
|
53
|
+
}
|
|
54
|
+
sessionListEl.appendChild(li);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function renderConnectionDetails(state) {
|
|
58
|
+
connectionStateEl.textContent = state.connectionState;
|
|
59
|
+
tokenStateEl.textContent = state.hasToken ? "configured" : "missing";
|
|
60
|
+
connectionUrlEl.textContent = state.wsUrl;
|
|
61
|
+
extensionVersionEl.textContent = state.extensionVersion;
|
|
62
|
+
if (state.manualDisconnect) {
|
|
63
|
+
reconnectStateEl.textContent = "manual disconnect";
|
|
64
|
+
} else if (typeof state.nextReconnectInMs === "number") {
|
|
65
|
+
const seconds = Math.max(0, Math.ceil(state.nextReconnectInMs / 100) / 10);
|
|
66
|
+
reconnectStateEl.textContent = `attempt ${state.reconnectAttempt}, retry in ${seconds}s`;
|
|
67
|
+
} else if (state.connected) {
|
|
68
|
+
reconnectStateEl.textContent = "connected";
|
|
69
|
+
} else {
|
|
70
|
+
reconnectStateEl.textContent = "idle";
|
|
71
|
+
}
|
|
72
|
+
if (state.lastError) {
|
|
73
|
+
const context = state.lastErrorContext ? `${state.lastErrorContext}: ` : "";
|
|
74
|
+
lastErrorEl.textContent = `${context}${state.lastError} (${formatTimeAgo(state.lastErrorAt)})`;
|
|
75
|
+
} else {
|
|
76
|
+
lastErrorEl.textContent = "none";
|
|
77
|
+
}
|
|
78
|
+
if (state.lastBindingUpdateReason) {
|
|
79
|
+
lastBindingUpdateEl.textContent = `${state.lastBindingUpdateReason} (${formatTimeAgo(state.lastBindingUpdateAt)})`;
|
|
80
|
+
} else {
|
|
81
|
+
lastBindingUpdateEl.textContent = "none";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
14
84
|
async function refreshState() {
|
|
15
85
|
const state = await chrome.runtime.sendMessage({ type: "bak.getState" });
|
|
16
86
|
if (state.ok) {
|
|
87
|
+
latestState = state;
|
|
17
88
|
portInput.value = String(state.port);
|
|
18
89
|
debugRichTextInput.checked = Boolean(state.debugRichText);
|
|
90
|
+
renderConnectionDetails(state);
|
|
91
|
+
renderSessionBindings(state.sessionBindings);
|
|
19
92
|
if (state.connected) {
|
|
20
93
|
setStatus("Connected to bak CLI");
|
|
94
|
+
} else if (state.connectionState === "missing-token") {
|
|
95
|
+
setStatus("Pair token is required", true);
|
|
96
|
+
} else if (state.connectionState === "manual") {
|
|
97
|
+
setStatus("Disconnected manually");
|
|
98
|
+
} else if (state.connectionState === "reconnecting") {
|
|
99
|
+
setStatus("Reconnecting to bak CLI", true);
|
|
21
100
|
} else if (state.lastError) {
|
|
22
101
|
setStatus(`Disconnected: ${state.lastError}`, true);
|
|
23
102
|
} else {
|
|
@@ -28,7 +107,7 @@
|
|
|
28
107
|
saveBtn.addEventListener("click", async () => {
|
|
29
108
|
const token = tokenInput.value.trim();
|
|
30
109
|
const port = Number.parseInt(portInput.value.trim(), 10);
|
|
31
|
-
if (!token) {
|
|
110
|
+
if (!token && latestState?.hasToken !== true) {
|
|
32
111
|
setStatus("Pair token is required", true);
|
|
33
112
|
return;
|
|
34
113
|
}
|
|
@@ -38,10 +117,15 @@
|
|
|
38
117
|
}
|
|
39
118
|
await chrome.runtime.sendMessage({
|
|
40
119
|
type: "bak.updateConfig",
|
|
41
|
-
token,
|
|
120
|
+
...token ? { token } : {},
|
|
42
121
|
port,
|
|
43
122
|
debugRichText: debugRichTextInput.checked
|
|
44
123
|
});
|
|
124
|
+
tokenInput.value = "";
|
|
125
|
+
await refreshState();
|
|
126
|
+
});
|
|
127
|
+
reconnectBtn.addEventListener("click", async () => {
|
|
128
|
+
await chrome.runtime.sendMessage({ type: "bak.reconnectNow" });
|
|
45
129
|
await refreshState();
|
|
46
130
|
});
|
|
47
131
|
disconnectBtn.addEventListener("click", async () => {
|
|
@@ -49,4 +133,10 @@
|
|
|
49
133
|
await refreshState();
|
|
50
134
|
});
|
|
51
135
|
void refreshState();
|
|
136
|
+
var refreshInterval = window.setInterval(() => {
|
|
137
|
+
void refreshState();
|
|
138
|
+
}, 1e3);
|
|
139
|
+
window.addEventListener("unload", () => {
|
|
140
|
+
window.clearInterval(refreshInterval);
|
|
141
|
+
});
|
|
52
142
|
})();
|
package/dist/popup.html
CHANGED
|
@@ -70,9 +70,50 @@
|
|
|
70
70
|
background: #e2e8f0;
|
|
71
71
|
color: #0f172a;
|
|
72
72
|
}
|
|
73
|
+
#reconnect {
|
|
74
|
+
background: #dbeafe;
|
|
75
|
+
color: #1d4ed8;
|
|
76
|
+
}
|
|
73
77
|
#status {
|
|
74
78
|
margin-top: 10px;
|
|
75
79
|
font-size: 12px;
|
|
80
|
+
font-weight: 600;
|
|
81
|
+
}
|
|
82
|
+
.panel {
|
|
83
|
+
margin-top: 12px;
|
|
84
|
+
padding: 10px;
|
|
85
|
+
border: 1px solid #cbd5e1;
|
|
86
|
+
border-radius: 8px;
|
|
87
|
+
background: rgba(255, 255, 255, 0.8);
|
|
88
|
+
}
|
|
89
|
+
.panel h2 {
|
|
90
|
+
margin: 0 0 8px;
|
|
91
|
+
font-size: 12px;
|
|
92
|
+
}
|
|
93
|
+
.meta-grid {
|
|
94
|
+
display: grid;
|
|
95
|
+
grid-template-columns: auto 1fr;
|
|
96
|
+
gap: 6px 10px;
|
|
97
|
+
font-size: 11px;
|
|
98
|
+
}
|
|
99
|
+
.meta-grid dt {
|
|
100
|
+
color: #475569;
|
|
101
|
+
}
|
|
102
|
+
.meta-grid dd {
|
|
103
|
+
margin: 0;
|
|
104
|
+
color: #0f172a;
|
|
105
|
+
word-break: break-word;
|
|
106
|
+
}
|
|
107
|
+
#sessionList {
|
|
108
|
+
margin: 0;
|
|
109
|
+
padding-left: 16px;
|
|
110
|
+
font-size: 11px;
|
|
111
|
+
color: #0f172a;
|
|
112
|
+
}
|
|
113
|
+
#sessionList:empty::before {
|
|
114
|
+
content: "No tracked sessions";
|
|
115
|
+
color: #64748b;
|
|
116
|
+
margin-left: -16px;
|
|
76
117
|
}
|
|
77
118
|
.hint {
|
|
78
119
|
margin-top: 10px;
|
|
@@ -85,7 +126,7 @@
|
|
|
85
126
|
<h1>Browser Agent Kit</h1>
|
|
86
127
|
<label>
|
|
87
128
|
Pair token
|
|
88
|
-
<input id="token" placeholder="paste token from `bak pair`" />
|
|
129
|
+
<input id="token" placeholder="paste token from `bak pair` or leave blank to keep the saved token" />
|
|
89
130
|
</label>
|
|
90
131
|
<label>
|
|
91
132
|
CLI port
|
|
@@ -97,9 +138,39 @@
|
|
|
97
138
|
</label>
|
|
98
139
|
<div class="row">
|
|
99
140
|
<button id="save">Save & Connect</button>
|
|
141
|
+
<button id="reconnect">Reconnect</button>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="row">
|
|
100
144
|
<button id="disconnect">Disconnect</button>
|
|
101
145
|
</div>
|
|
102
146
|
<div id="status">Checking...</div>
|
|
147
|
+
<div class="panel">
|
|
148
|
+
<h2>Connection</h2>
|
|
149
|
+
<dl class="meta-grid">
|
|
150
|
+
<dt>State</dt>
|
|
151
|
+
<dd id="connectionState">-</dd>
|
|
152
|
+
<dt>Token</dt>
|
|
153
|
+
<dd id="tokenState">-</dd>
|
|
154
|
+
<dt>Reconnect</dt>
|
|
155
|
+
<dd id="reconnectState">-</dd>
|
|
156
|
+
<dt>CLI URL</dt>
|
|
157
|
+
<dd id="connectionUrl">-</dd>
|
|
158
|
+
<dt>Last error</dt>
|
|
159
|
+
<dd id="lastError">-</dd>
|
|
160
|
+
<dt>Last binding</dt>
|
|
161
|
+
<dd id="lastBindingUpdate">-</dd>
|
|
162
|
+
<dt>Extension</dt>
|
|
163
|
+
<dd id="extensionVersion">-</dd>
|
|
164
|
+
</dl>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="panel">
|
|
167
|
+
<h2>Sessions</h2>
|
|
168
|
+
<dl class="meta-grid">
|
|
169
|
+
<dt>Tracked</dt>
|
|
170
|
+
<dd id="sessionSummary">-</dd>
|
|
171
|
+
</dl>
|
|
172
|
+
<ul id="sessionList"></ul>
|
|
173
|
+
</div>
|
|
103
174
|
<div class="hint">Extension only connects to ws://127.0.0.1</div>
|
|
104
175
|
<script src="./popup.global.js"></script>
|
|
105
176
|
</body>
|
package/package.json
CHANGED
package/public/popup.html
CHANGED
|
@@ -70,9 +70,50 @@
|
|
|
70
70
|
background: #e2e8f0;
|
|
71
71
|
color: #0f172a;
|
|
72
72
|
}
|
|
73
|
+
#reconnect {
|
|
74
|
+
background: #dbeafe;
|
|
75
|
+
color: #1d4ed8;
|
|
76
|
+
}
|
|
73
77
|
#status {
|
|
74
78
|
margin-top: 10px;
|
|
75
79
|
font-size: 12px;
|
|
80
|
+
font-weight: 600;
|
|
81
|
+
}
|
|
82
|
+
.panel {
|
|
83
|
+
margin-top: 12px;
|
|
84
|
+
padding: 10px;
|
|
85
|
+
border: 1px solid #cbd5e1;
|
|
86
|
+
border-radius: 8px;
|
|
87
|
+
background: rgba(255, 255, 255, 0.8);
|
|
88
|
+
}
|
|
89
|
+
.panel h2 {
|
|
90
|
+
margin: 0 0 8px;
|
|
91
|
+
font-size: 12px;
|
|
92
|
+
}
|
|
93
|
+
.meta-grid {
|
|
94
|
+
display: grid;
|
|
95
|
+
grid-template-columns: auto 1fr;
|
|
96
|
+
gap: 6px 10px;
|
|
97
|
+
font-size: 11px;
|
|
98
|
+
}
|
|
99
|
+
.meta-grid dt {
|
|
100
|
+
color: #475569;
|
|
101
|
+
}
|
|
102
|
+
.meta-grid dd {
|
|
103
|
+
margin: 0;
|
|
104
|
+
color: #0f172a;
|
|
105
|
+
word-break: break-word;
|
|
106
|
+
}
|
|
107
|
+
#sessionList {
|
|
108
|
+
margin: 0;
|
|
109
|
+
padding-left: 16px;
|
|
110
|
+
font-size: 11px;
|
|
111
|
+
color: #0f172a;
|
|
112
|
+
}
|
|
113
|
+
#sessionList:empty::before {
|
|
114
|
+
content: "No tracked sessions";
|
|
115
|
+
color: #64748b;
|
|
116
|
+
margin-left: -16px;
|
|
76
117
|
}
|
|
77
118
|
.hint {
|
|
78
119
|
margin-top: 10px;
|
|
@@ -85,7 +126,7 @@
|
|
|
85
126
|
<h1>Browser Agent Kit</h1>
|
|
86
127
|
<label>
|
|
87
128
|
Pair token
|
|
88
|
-
<input id="token" placeholder="paste token from `bak pair`" />
|
|
129
|
+
<input id="token" placeholder="paste token from `bak pair` or leave blank to keep the saved token" />
|
|
89
130
|
</label>
|
|
90
131
|
<label>
|
|
91
132
|
CLI port
|
|
@@ -97,9 +138,39 @@
|
|
|
97
138
|
</label>
|
|
98
139
|
<div class="row">
|
|
99
140
|
<button id="save">Save & Connect</button>
|
|
141
|
+
<button id="reconnect">Reconnect</button>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="row">
|
|
100
144
|
<button id="disconnect">Disconnect</button>
|
|
101
145
|
</div>
|
|
102
146
|
<div id="status">Checking...</div>
|
|
147
|
+
<div class="panel">
|
|
148
|
+
<h2>Connection</h2>
|
|
149
|
+
<dl class="meta-grid">
|
|
150
|
+
<dt>State</dt>
|
|
151
|
+
<dd id="connectionState">-</dd>
|
|
152
|
+
<dt>Token</dt>
|
|
153
|
+
<dd id="tokenState">-</dd>
|
|
154
|
+
<dt>Reconnect</dt>
|
|
155
|
+
<dd id="reconnectState">-</dd>
|
|
156
|
+
<dt>CLI URL</dt>
|
|
157
|
+
<dd id="connectionUrl">-</dd>
|
|
158
|
+
<dt>Last error</dt>
|
|
159
|
+
<dd id="lastError">-</dd>
|
|
160
|
+
<dt>Last binding</dt>
|
|
161
|
+
<dd id="lastBindingUpdate">-</dd>
|
|
162
|
+
<dt>Extension</dt>
|
|
163
|
+
<dd id="extensionVersion">-</dd>
|
|
164
|
+
</dl>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="panel">
|
|
167
|
+
<h2>Sessions</h2>
|
|
168
|
+
<dl class="meta-grid">
|
|
169
|
+
<dt>Tracked</dt>
|
|
170
|
+
<dd id="sessionSummary">-</dd>
|
|
171
|
+
</dl>
|
|
172
|
+
<ul id="sessionList"></ul>
|
|
173
|
+
</div>
|
|
103
174
|
<div class="hint">Extension only connects to ws://127.0.0.1</div>
|
|
104
175
|
<script src="./popup.global.js"></script>
|
|
105
176
|
</body>
|