dsh-read-url 1.7.0 → 1.8.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/CHANGELOG.md +27 -0
- package/README.md +17 -7
- package/README.zh.md +17 -7
- package/index.js +537 -323
- package/package.json +1 -1
- package/proxy-fallback.js +22 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-read-url",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "DeepSeek Harness URL reader: fetch any webpage (HTML/JSON/RSS/Atom), auto-detect encoding (UTF-16 BOM/GBK/Big5/Shift-JIS), extract clean main content with auto-pagination, output compact text/Markdown to save tokens. Zero runtime dependencies, no API key, drop-in. Follows meta-refresh shells, reads JSON-LD metadata, honors base href.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
package/proxy-fallback.js
CHANGED
|
@@ -23,6 +23,19 @@ import { execFile, execFileSync } from 'node:child_process'
|
|
|
23
23
|
export function looksBinary(buffer) {
|
|
24
24
|
const n = Math.min(buffer.length, 512)
|
|
25
25
|
if (!n) return false
|
|
26
|
+
const utf16le = buffer[0] === 0xff && buffer[1] === 0xfe
|
|
27
|
+
const utf16be = buffer[0] === 0xfe && buffer[1] === 0xff
|
|
28
|
+
if ((utf16le || utf16be) && buffer.length % 2 === 0) {
|
|
29
|
+
let controls = 0
|
|
30
|
+
let units = 0
|
|
31
|
+
for (let i = 2; i + 1 < n; i += 2) {
|
|
32
|
+
const code = utf16le ? buffer[i] | (buffer[i + 1] << 8) : (buffer[i] << 8) | buffer[i + 1]
|
|
33
|
+
if (code === 0) return true
|
|
34
|
+
if (code < 9 || (code > 13 && code < 32)) controls++
|
|
35
|
+
units++
|
|
36
|
+
}
|
|
37
|
+
return units > 0 && controls / units > 0.3
|
|
38
|
+
}
|
|
26
39
|
let ctrl = 0
|
|
27
40
|
for (let i = 0; i < n; i++) {
|
|
28
41
|
const b = buffer[i]
|
|
@@ -32,6 +45,14 @@ export function looksBinary(buffer) {
|
|
|
32
45
|
return ctrl / n > 0.3
|
|
33
46
|
}
|
|
34
47
|
|
|
48
|
+
// Shared by direct and proxy retrieval so a document's route cannot change
|
|
49
|
+
// which text formats are accepted. Structured suffixes include vendor APIs.
|
|
50
|
+
export function isFetchableContentType(contentType) {
|
|
51
|
+
const mime = (contentType || '').split(';', 1)[0].trim().toLowerCase()
|
|
52
|
+
return ['text/html', 'application/xhtml+xml', 'text/plain', 'text/markdown', 'text/csv', 'application/json', 'text/json', 'application/xml', 'text/xml'].includes(mime) ||
|
|
53
|
+
/^[a-z][a-z0-9!#$&^_.+-]{0,63}\/(?:[a-z0-9!#$&^_.+-]{1,127}\+)?(?:json|xml)$/.test(mime)
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
let sysProxyCache = null // '' = checked & absent; string = proxy URL
|
|
36
57
|
let sysProxyCheckedAt = 0 // cache timestamp; a failed read is re-tried after 60s
|
|
37
58
|
const SYS_PROXY_RETRY_MS = 60 * 1000
|
|
@@ -129,7 +150,7 @@ export async function fetchViaCurlProxy(url, cfg, externalSignal, proxyOverride)
|
|
|
129
150
|
}
|
|
130
151
|
}
|
|
131
152
|
if (!(code >= 200 && code < 300)) return { error: `HTTP ${code}` }
|
|
132
|
-
if (contentType &&
|
|
153
|
+
if (contentType && !isFetchableContentType(contentType)) {
|
|
133
154
|
return { error: `Unsupported content-type: ${contentType.split(';')[0]}` }
|
|
134
155
|
}
|
|
135
156
|
return { buffer: body, contentType, finalUrl: finalUrlEff, viaProxy: proxy }
|