aboutsummaryrefslogtreecommitdiff
path: root/modules/ext/webdav.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-11-02 21:05:58 +0100
committerAgando <roduccomm@gmail.com>2026-11-02 21:05:58 +0100
commitc2f2ea62503f81c07f4d36d7c3a798b91146153e (patch)
tree6f20a4437c75a7f27d4b01f4dd2fe413e4bcfcd1 /modules/ext/webdav.js
parentb339bc13199eb9326307905dd635c56974b55f53 (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.js52
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';
}
}