diff options
| author | Agando <roduccomm@gmail.com> | 2026-11-02 21:05:58 +0100 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-11-02 21:05:58 +0100 |
| commit | c2f2ea62503f81c07f4d36d7c3a798b91146153e (patch) | |
| tree | 6f20a4437c75a7f27d4b01f4dd2fe413e4bcfcd1 /modules/ext/webdav.js | |
| parent | b339bc13199eb9326307905dd635c56974b55f53 (diff) | |
fix(newos4): WebDAV listing sizes + pull, and five MemoryGraph defects
Closes STEER-20261102-205416-facd and STEER-20261102-204031-f82a.
WebDAV (modules/ext/webdav.js):
- listings showed "21 B" for a 21 KB file: nginx emits humanised sizes
(autoindex_exact_size off, vhost :412) and _parseAutoindex did parseInt("21K").
_parseAutoindexSize() handles K/M/G, decimals, lowercase and "-"; PROPFIND's
exact getcontentlength path is untouched.
- webdav-pull into a missing local directory printed "Pulled: ... (N bytes)" and
wrote nothing: it ignored fs.writeFile's false return (virtual-fs.js:561).
It now creates the parent chain, checks the write, and only reports success
after a confirmed write. The byte count uses TextEncoder, not .length
(a Cyrillic file under-reported ~2x).
- _formatSize gained the GB branch the parser already accepted (3 GB printed
"3072.0 MB") and no longer prints "NaN MB" for a missing size.
MemoryGraph (modules/core/module-memory-graph.js):
- addEdge averages weights, so every repeat pulled a strong edge toward the
call site's constant (0.9 -> 0.7 -> 0.6). Now Math.max, with decay left to
applyDecay(); prune() untouched.
- task ids were `task-${Date.now()}`, so re-submitting a task never deduped:
now a hash of agent + normalised text.
- recordFileAccess no longer records the graph's own /.memory_graph/ store.
- failed tool calls were weighted 0.8 vs success 0.5, so showStats ranked
failures as strongest: now 0.2. Legacy 0.8 failures are capped on load.
- concept ids keep punctuation ("concept:(v2!),"): slugged, and the slug uses
\p{L}\p{N} so Cyrillic/CJK/accented text still yields nodes -- an a-z0-9 slug
silently produced none.
Review findings folded in from the regression pass: the non-Latin regression
(a-z0-9 slug), the GB formatter asymmetry, and the pull byte count were all
found by review, not by the patch authors, and each now has a test.
Tests: test-webdav-sizes.js 27 (was RED 15/24 before the fix), test-memory-graph.js
37 (RED 17/32), both auto-discovered by newos4-maintain -- 26/26 node tests.
Live on v4.6.140: _parseAutoindexSize('21K') 21504, _formatSize -> "21.0 KB",
_formatSize(2GiB) "2.0 GB", slug Cyrillic "исправить-парсер-ошибок", 0 console errors.
Diffstat (limited to 'modules/ext/webdav.js')
| -rw-r--r-- | modules/ext/webdav.js | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/modules/ext/webdav.js b/modules/ext/webdav.js index 7f3e7a7..e78e876 100644 --- a/modules/ext/webdav.js +++ b/modules/ext/webdav.js @@ -453,7 +453,7 @@ class WebDAVModule { const isDir = href.endsWith('/'); let size = 0; if (!isDir && sizeStr !== '-') { - size = parseInt(sizeStr) || 0; + size = this._parseAutoindexSize(sizeStr); } entries.push({ name: name, @@ -506,6 +506,25 @@ class WebDAVModule { return entries; } + // nginx autoindex with `autoindex_exact_size off` (our template) emits + // HUMANISED sizes: '512', '21K', '45K', '1.2M'. parseInt() read the leading + // digits and dropped the suffix, so a 21 397-byte file was reported as 21 B. + // Parse the suffix here, 1024-based, to match _formatSize() below. + _parseAutoindexSize(sizeStr) { + if (sizeStr === null || sizeStr === undefined) return 0; + const s = String(sizeStr).trim(); + const m = s.match(/^(\d+(?:\.\d+)?)\s*([KMG]?)i?B?$/i); + if (!m) return 0; + const num = parseFloat(m[1]); + if (!isFinite(num) || num < 0) return 0; + const unit = (m[2] || '').toUpperCase(); + const mult = unit === 'K' ? 1024 + : unit === 'M' ? 1024 * 1024 + : unit === 'G' ? 1024 * 1024 * 1024 + : 1; + return Math.round(num * mult); + } + _parseNginxDate(dateStr) { if (!dateStr) return null; // nginx default: 02-Aug-2026 14:30 @@ -1095,8 +1114,26 @@ class WebDAVModule { const resp = await self._webdavRequest('GET', remotePath); if (!resp.ok) throw new Error('HTTP ' + resp.status); const content = await resp.text(); - self.terminal.fs.writeFile(vfsPath, content); - self.terminal.print('Pulled: ' + remotePath + ' → ' + vfsPath + ' (' + content.length + ' bytes)', 'success'); + // Create the local parent chain FIRST: fs.writeFile() returns false + // when the parent directory is missing (_resolvePath bails), and the + // old code ignored that return and printed a success line for a + // write that never happened. + const slash = vfsPath.lastIndexOf('/'); + const parentDir = slash > 0 ? vfsPath.slice(0, slash) : ''; + if (parentDir && typeof self.terminal.fs.mkdirRecursive === 'function') { + if (self.terminal.fs.mkdirRecursive(parentDir) === false) { + self.terminal.print('Pull failed: cannot create local directory ' + parentDir, 'error'); + return; + } + } + const wrote = self.terminal.fs.writeFile(vfsPath, content); + if (!wrote) { + self.terminal.print('Pull failed: cannot write local file ' + vfsPath + + ' (missing directory or path is a directory) — nothing saved', 'error'); + return; + } + const _bytes = (typeof TextEncoder !== 'undefined') ? new TextEncoder().encode(content).length : content.length; + self.terminal.print('Pulled: ' + remotePath + ' → ' + vfsPath + ' (' + _bytes + ' bytes)', 'success'); } catch (e) { self.terminal.print('Pull error: ' + e.message, 'error'); } @@ -2442,8 +2479,11 @@ class WebDAVModule { } _formatSize(bytes) { - if (bytes < 1024) return bytes + ' B'; - if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; - return (bytes / (1024 * 1024)).toFixed(1) + ' MB'; + const n = Number(bytes); + if (!Number.isFinite(n) || n < 0) return '—'; + if (n < 1024) return n + ' B'; + if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB'; + if (n < 1024 * 1024 * 1024) return (n / (1024 * 1024)).toFixed(1) + ' MB'; + return (n / (1024 * 1024 * 1024)).toFixed(1) + ' GB'; } } |