dsh-site-bridge 0.5.1 → 0.5.3
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/manifest.json +1 -1
- package/extension/popup.js +35 -13
- package/extension/sw.js +10 -2
- package/package.json +1 -1
- package/tools/preview-popup.mjs +3 -2
package/extension/manifest.json
CHANGED
package/extension/popup.js
CHANGED
|
@@ -101,7 +101,8 @@ function render(status) {
|
|
|
101
101
|
const targets = Array.isArray(status.targets) ? status.targets : []
|
|
102
102
|
const tabsRow = $('tabs-row')
|
|
103
103
|
const tabsSelect = $('tabs-select')
|
|
104
|
-
|
|
104
|
+
const selfAttached = selfTabId != null && targets.some((item) => item.id === selfTabId)
|
|
105
|
+
$('claim-more').hidden = !hasTarget || selfAttached
|
|
105
106
|
if (targets.length > 1) {
|
|
106
107
|
tabsRow.hidden = false
|
|
107
108
|
tabsSelect.textContent = ''
|
|
@@ -146,8 +147,16 @@ function render(status) {
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
150
|
+
// Which tab this popup is open on: attaching that tab again is a no-op, so the
|
|
151
|
+
// attach button is only offered when the current tab is not attached yet.
|
|
152
|
+
let selfTabId = null
|
|
153
|
+
|
|
149
154
|
async function refresh() {
|
|
150
155
|
try {
|
|
156
|
+
if (chrome.tabs?.query) {
|
|
157
|
+
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
|
|
158
|
+
selfTabId = tab?.id ?? null
|
|
159
|
+
}
|
|
151
160
|
render(await send({ type: 'status' }))
|
|
152
161
|
} catch {
|
|
153
162
|
render(null)
|
|
@@ -230,16 +239,33 @@ $('import-file').addEventListener('change', async (event) => {
|
|
|
230
239
|
}
|
|
231
240
|
})
|
|
232
241
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
242
|
+
async function attachCurrentTab() {
|
|
243
|
+
let tabId = null
|
|
244
|
+
try {
|
|
245
|
+
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
|
|
246
|
+
tabId = tab?.id ?? null
|
|
247
|
+
} catch {
|
|
248
|
+
tabId = null
|
|
249
|
+
}
|
|
250
|
+
if (tabId == null) {
|
|
251
|
+
setNote(t('claimFailed', [t('claimFailedUnknown')]), true)
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
const result = await send({ type: 'claim', tabId })
|
|
256
|
+
if (!result?.ok) {
|
|
257
|
+
setNote(t('claimFailed', [String(result?.error ?? t('claimFailedUnknown'))]), true)
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
setNote('')
|
|
261
|
+
} catch (error) {
|
|
262
|
+
setNote(t('claimFailed', [String(error?.message ?? error)]), true)
|
|
239
263
|
return
|
|
240
264
|
}
|
|
241
265
|
await refresh()
|
|
242
|
-
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
$('claim').addEventListener('click', attachCurrentTab)
|
|
243
269
|
|
|
244
270
|
$('capture').addEventListener('click', async () => {
|
|
245
271
|
const status = await send({ type: 'status' })
|
|
@@ -268,11 +294,7 @@ $('pick').addEventListener('click', async () => {
|
|
|
268
294
|
await refresh()
|
|
269
295
|
})
|
|
270
296
|
|
|
271
|
-
$('claim-more').addEventListener('click',
|
|
272
|
-
const result = await send({ type: 'claim' })
|
|
273
|
-
if (!result?.ok && result?.error) setNote(String(result.error), true)
|
|
274
|
-
await refresh()
|
|
275
|
-
})
|
|
297
|
+
$('claim-more').addEventListener('click', attachCurrentTab)
|
|
276
298
|
|
|
277
299
|
$('tabs-select').addEventListener('change', async (event) => {
|
|
278
300
|
const tabId = Number(event.target.value)
|
package/extension/sw.js
CHANGED
|
@@ -272,11 +272,19 @@ async function attach(tabId) {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
async function claimTab(tabId) {
|
|
275
|
-
|
|
275
|
+
// Without an explicit id, claim whatever tab the user is looking at, so a
|
|
276
|
+
// caller that only knows "this tab" cannot silently pass NaN.
|
|
277
|
+
let id = Number(tabId)
|
|
278
|
+
if (!Number.isFinite(id)) {
|
|
279
|
+
const [active] = await chrome.tabs.query({ active: true, lastFocusedWindow: true })
|
|
280
|
+
id = active?.id
|
|
281
|
+
}
|
|
282
|
+
if (!Number.isFinite(id)) throw new Error('no tab to claim: pass tabId or open a page first')
|
|
283
|
+
const tab = await chrome.tabs.get(id)
|
|
276
284
|
if (!/^https?:|^file:/.test(tab.url ?? '')) {
|
|
277
285
|
throw new Error(`cannot drive ${tab.url || 'this tab'}: only http(s) and file:// pages are supported`)
|
|
278
286
|
}
|
|
279
|
-
return attach(
|
|
287
|
+
return attach(id)
|
|
280
288
|
}
|
|
281
289
|
|
|
282
290
|
chrome.debugger.onDetach.addListener((source, reason) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-site-bridge",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Chrome/Edge MV3 bridge for DeepSeek Harness: capture page markup (DOM, styles, selectors) and BFF traffic (xhr/fetch with headers and bodies) into a workspace snapshot bundle, drive the page with trusted CDP input, and verify injected scripts. Authorization never leaves the browser and is never written to disk.",
|
|
5
5
|
"icon": "./icon.svg",
|
|
6
6
|
"type": "module",
|
package/tools/preview-popup.mjs
CHANGED
|
@@ -22,7 +22,7 @@ const sleep = (ms) => new Promise((done) => setTimeout(done, ms))
|
|
|
22
22
|
|
|
23
23
|
const statuses = {
|
|
24
24
|
'connected-one': {
|
|
25
|
-
ok: true, configured: true, connected: true, port: 47321, recording: false, captured: 0,
|
|
25
|
+
ok: true, configured: true, connected: true, port: 47321, recording: false, captured: 0, selfTabId: 1,
|
|
26
26
|
activeTabId: 1,
|
|
27
27
|
target: { id: 1, title: 'Example Store — Products', url: 'https://shop.example/products' },
|
|
28
28
|
targets: [
|
|
@@ -30,7 +30,7 @@ const statuses = {
|
|
|
30
30
|
]
|
|
31
31
|
},
|
|
32
32
|
connected: {
|
|
33
|
-
ok: true, configured: true, connected: true, port: 47321, recording: true, captured: 12,
|
|
33
|
+
ok: true, configured: true, connected: true, port: 47321, recording: true, captured: 12, selfTabId: 3,
|
|
34
34
|
activeTabId: 1,
|
|
35
35
|
target: { id: 1, title: 'Ozon: Торговая площадка', url: 'https://seller.ozon.ru/app/products' },
|
|
36
36
|
targets: [
|
|
@@ -59,6 +59,7 @@ const stub = `
|
|
|
59
59
|
window.chrome = {
|
|
60
60
|
runtime: { sendMessage: async (m) => (m.type === 'status' ? ${JSON.stringify(statuses[state] ?? statuses.connected)} : { ok: true }) },
|
|
61
61
|
storage: { local: { get: async () => ({ port: 47321, token: 'GWCIveb--rxL_wKChN9Wl-OJmXFGTK4' }), set: async () => {} } },
|
|
62
|
+
tabs: { query: async () => [{ id: ${JSON.stringify(statuses[state]?.selfTabId ?? 1)} }] },
|
|
62
63
|
i18n: {
|
|
63
64
|
getUILanguage: () => ${JSON.stringify(locale.replace('_', '-'))},
|
|
64
65
|
getMessage: (key, subs) => {
|