Conversation
…readability and consistency
…velte components into the frontend
…nd integrate routing
…or improved performance
…to codebase brought to you by slopcoder5000 the worlds best model for massive refactors.
…nhance conversation viewer with contact filtering and telemetry item selection
…ing archive listing, viewer, and export functionality
…cross multiple modules
… and update linting tasks
…ive session, audio settings, contacts tab, history panel, overlay, phonebook, and phone tab
…agement, including dialer, active session, voicemail, and tab navigation
…t related references in ESLint and TypeScript configurations
… coordinate formatting in map features
…ainability, and improve archive routes with database checks
…mentation, and standardize TypeScript file extensions
…ader bar, sidebar panel, and overlays
…eadability and consistency across app shell and map features
…nd remote management across multiple languages
…om vue/js to svelte/ts and updating docs and other improvements/fixes
…ies and adjust typecheck command
| } else if (url.startsWith(":")) { | ||
| path = url.slice(1); | ||
| } | ||
| if (path.startsWith("media/")) { |
| out = out.replace(EXPLICIT_RE, (match, body) => geoAnchor(body.trim(), body.trim())); | ||
|
|
||
| // Maidenhead locators, 6+ chars only for auto-linking to avoid noise. | ||
| out = out.replace(MAIDENHEAD_RE, (match) => geoAnchor(match, match)); |
| * Ported and simplified from meshchatx/src/backend/markdown_renderer.py | ||
| */ | ||
| static render(text) { | ||
| return cachedRender(text, MarkdownRenderer._renderUncached); |
| const info = readImage(container); | ||
| const index = container.getAttribute("data-mu-image-index"); | ||
| post({ | ||
| type: "image-action", |
| for (const key of NUMERIC_KEYS) { | ||
| const value = String(draft[key] ?? "").trim(); | ||
| if (value) { | ||
| patch[key] = Number(value); |
| quality = MEDIA_QUALITY | ||
| max_dimension = MEDIA_MAX_DIMENSION | ||
| if isinstance(data, dict): | ||
| quality = int(data.get("quality", quality)) |
There was a problem hiding this comment.
WARNING: Uncaught int() on remote-controlled quality
quality = int(data.get("quality", quality)) has no try/except, while the sibling max_dimension cast three lines below is wrapped. A remote peer sending {"quality": "high"} (or null) raises ValueError/TypeError inside the RNS response generator; every other remote-input parse in this class fails closed. Wrap it like the max_dimension cast.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| continue | ||
| return None | ||
|
|
||
| def _media_cache_key(self, source_path, quality, max_dimension): |
There was a problem hiding this comment.
WARNING: Unbounded, remote-controlled media cache keys → disk/CPU DoS
quality and max_dimension come from the remote peer as arbitrary ints with no range validation and flow into the cache filename used by _get_converted_media_path. Any peer holding a file-access grant (granted just by loading one page) can request the same image with thousands of distinct values; each unique combo spawns a conversion subprocess (10 s timeout, serialized on the media lock) and writes a permanent cache file with no eviction — a straightforward remote disk-fill and CPU-exhaustion vector. Clamp quality (e.g. 1–100) and max_dimension to a sane maximum and bound/evict the cache.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| "--rrc-hub", | ||
| rrc_cfg["hub"], | ||
| "--rrc-rooms", | ||
| ",".join(rrc_cfg["rooms"]), |
There was a problem hiding this comment.
SUGGESTION: RRC room names containing commas round-trip lossily through CLI args
normalize_rrc_bot_config accepts room names up to 64 chars without rejecting commas, but rooms are serialized as ",".join(rrc_cfg["rooms"]) here and re-split on "," in bot_process.py — a configured room "lobby,secret" silently becomes two rooms and the stored config diverges from the running bot. Reject commas in the room-name validation loop in normalize_rrc_bot_config.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| } else if (url.startsWith(":")) { | ||
| path = url.slice(1); | ||
| } | ||
| if (path.startsWith("media/")) { |
There was a problem hiding this comment.
WARNING: Hash-qualified and :/-relative image URLs are never accepted
extractMicronImageFilePath splits on ":/" (line ~785), so for hash:/media/x.png and :/media/x.png the resulting path is /media/x.png (leading slash). The checks here only accept path.startsWith("media/") / "file/", so both documented forms (the comment above says "Accept hash:/media/... ... and relative :/media/...") return null; only a bare media/x.png — a shape Nomad URLs never produce — parses. The common nomadnetwork://<hash>:/media/... image URL never renders an image placeholder. Strip the leading / after splitting (or accept both forms in the prefix checks).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| out = out.replace(EXPLICIT_RE, (match, body) => geoAnchor(body.trim(), body.trim())); | ||
|
|
||
| // Maidenhead locators, 6+ chars only for auto-linking to avoid noise. | ||
| out = out.replace(MAIDENHEAD_RE, (match) => geoAnchor(match, match)); |
There was a problem hiding this comment.
WARNING: Later passes re-match earlier passes' generated markup
linkifyGeoRefs runs EXPLICIT → MAIDENHEAD → LATLON sequentially over the output of the previous pass. An explicit link like grid:FN31pr first becomes <a ... data-geo-text="FN31pr">FN31pr</a>, then the MAIDENHEAD pass matches FN31pr inside the attribute value and the anchor text, injecting a full anchor template into the attribute (breaking it). Same for geo:51.5, -0.1 with the LATLON pass. The result is nested anchors and a corrupted data-geo-text attribute rendered into @html in relay chat. Protect/placeholder earlier anchors (as LinkUtils.protectAnchors does) before subsequent passes.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| * Ported and simplified from meshchatx/src/backend/markdown_renderer.py | ||
| */ | ||
| static render(text) { | ||
| return cachedRender(text, MarkdownRenderer._renderUncached); |
There was a problem hiding this comment.
WARNING: Shared render cache across render() and renderBasic()
Both pipelines call cachedRender with the same module-level renderCache keyed only by raw text. The same string rendered by both (e.g. posted to an LXMF conversation and an RRC room) returns whichever pipeline cached first — headers/paragraphs vs. inline-only markup. The output also depends on GlobalState.config (via LinkUtils.renderAllLinks → defaultNomadPagePath()), so cached link hrefs go stale after a config/identity change despite the "pure function of the input" comment. Key the cache per pipeline (and per relevant config) or only cache within _renderUncached.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| const info = readImage(container); | ||
| const index = container.getAttribute("data-mu-image-index"); | ||
| post({ | ||
| type: "image-action", |
There was a problem hiding this comment.
WARNING: "Load image" button posts a message with no handler — dead control
The frame posts { type: "image-action", ... }, and the frame itself handles a set-image reply (line ~465), but nothing outside the frame ever sends set-image (the parent bridge handles only ready/pong/render-*/shell-background/aborted/navigate, and the new images field on render-done is dropped by the bridge). Clicking "Load image" is inert end-to-end. Add the parent-side wiring or gate the placeholder until it exists.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| for (const key of NUMERIC_KEYS) { | ||
| const value = String(draft[key] ?? "").trim(); | ||
| if (value) { | ||
| patch[key] = Number(value); |
There was a problem hiding this comment.
SUGGESTION: Non-numeric input silently becomes null
patch[key] = Number(value) has no NaN guard: typing abc in e.g. cooldown yields NaN, which JSON.stringify serializes as null and the backend treats as "clear the override" — garbage input silently deletes the bot's setting instead of erroring. Guard with Number.isFinite.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Apply master's route behavior across the split route packages: bounded
JSON reads, canonical HTTP error helpers, streamed multipart uploads via
write_field_to_path, blocking work moved off the event loop, and input
validation for map export, path probe, stickers, and telephone audio.
Add master endpoints GET /api/v1/identity/{identity_hash}/lxmf-address,
GET /api/v1/rrc/search, GET /api/v1/rrc/servers/{hub_id}/stats, and the
nomadnet archives export route, and regenerate the HTTP route fixture.
Align nomad ws download handlers with master's started-before-schedule
ordering and private-download archive skip, and repoint stale flat-module
patch targets in interface discovery and nomad ws order tests to the
live-name resolution point.
Replace the inline start modal flow with master's dedicated setup page at /bots/new so template selection, lxmf config, icon, custom commands, and rrc options are configured before starting. Add BotSetupPage with BotCustomCommandsEditor and BotRrcFields, draft builders in botDrafts, and icon/custom/rrc fields on the bot api payload and record types. Fix the stale BotsPage chat test which queried the i18n key while the registered fallback returns the translated title.
Convert master's RelayBotsPage and RelaySearchPage to Svelte 5 and wire them into RelayChatPage's bots and search tabs, including the shared SearchInput component and the rrc bot record and known-hub types.
Convert master's MapTabContextMenu to Svelte 5 and wire rename, publish, and remove actions into MapBrowser and MapTabBar.
Convert master's PublishSiteModal to Svelte 5 with the micronPublish helper and wire it into MicronEditorPage and the publish dropdown.
Move ColourPickerDropdown from the profile feature into ui/svelte so it can back the bot icon editor, extract reusable hex helpers into colorUtils, and update the profile icon page and module ownership test.
Annotate micron parser helpers whose null defaults collapsed to narrow literal types, type the indexeddb void promises, narrow optional geo coordinates before use, declare the sandbox card abi field, and pass an undefined-safe id to the bits-ui switch root.
The flat-module-to-package split dropped the helper from the public surface that master exposes and test_rrc_bot imports.
The privacy toggle renders as a switch role button after the bits-ui migration so .checked no longer exists on the element.
Migrate window and document listeners, matchMedia change handlers, and stable element scroll listeners to runed useEventListener across pages and shared components. MediaQueryList targets stay in state so the effect rebinds once assigned on mount. Kept the transient pointermove and pointerup pane-resize listeners in MessagesPage since always-on binding would persist panes on every pointerup.
Restore master's per-handler try/catch in dispatchWsEvent so one faulty listener cannot starve later ones, and render the landlock kernel ABI chip on about security cards like the Vue version did.
Drive demo prefs and identity readiness through GlobalState now that the pinia stores are gone, rewrite the SettingsNav and ToolsPage cases that still called Vue mount helpers, switch settings section assertions to the switch role semantics of the bits-ui toggle, and raise the relay and nomad page regression caps and leaf allowlist for the ported views.
Bring next to dev parity outside the frontend: AppContainer window object grants with init-failure fallback, the AppContainer child-launch self-check probe, backend manifest verification in packaging and CI, Android startup failure surfacing, the rngit release helper, rns 1.5.4 and lxst 0.5.3 with refreshed license data, and the 4.9.1 version bump with its changelog entries.
| """Download the filtered archive set as a single zip bundle.""" | ||
| query = request.query.get("q", "").strip() | ||
| destination_hash = request.query.get("destination_hash", "").strip() or None | ||
| rows = app.database.misc.get_archived_pages_paginated( |
There was a problem hiding this comment.
WARNING: Missing require_database guard and exception handling
Every sibling archives route (e.g. pages.py) calls require_database(app) before touching app.database and wraps DB calls with http_for_database_exception. Here, if app.database is None during an identity switch, app.database.misc raises AttributeError → unstructured 500 instead of a 503; a retryable sqlite error also surfaces as a raw 500 instead of the sanitizing 503 convention.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| } | ||
| }); | ||
|
|
||
| worker.addEventListener("error", (err) => this.onerror(err as unknown as Error)); |
There was a problem hiding this comment.
WARNING: Worker failure never rejects pending calls — translation hangs forever
The error listener only forwards to this.onerror; the pending entries in the pending map are never rejected. If the vendored worker fails to load or WASM instantiation fails, await call("initialize", ...) on line 115 never settles, so TranslationService.translate never resolves and the Translate button in TranslatorPage.svelte spins with isTranslating stuck true. There is also no timeout. Reject all pending (and future-failing) calls on error/messageerror events.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| * Default publish filename for a tab: sanitized tab name, keeping an existing | ||
| * allowed extension or appending .mu. | ||
| */ | ||
| export function defaultPublishFilename(tab: MicronTab, index: number): string { |
There was a problem hiding this comment.
WARNING: publishSite flow has no filename-collision check — pages silently overwrite each other
sanitizePublishFilename collapses distinct tab names to the same filename (e.g. "My: Page" and "My Page" both → My_Page.mu; home.mu vs Home.mu). The single-page flow dedupes against existing pages via resolvePublishPageBase, but the site flow (MicronEditorPage.publishSite) posts each entry with no intra-batch or server-side collision check: later pages overwrite earlier ones, published still counts them as successes, and the success toast reports published/total as if all pages were distinct.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| window.location.hash = `#/bots/new?template=${encodeURIComponent(template.id)}`; | ||
| } | ||
|
|
||
| async function handleStartBot(bot: BotRecord): Promise<void> { |
There was a problem hiding this comment.
WARNING: handleStartBot never sets actionInProgress
Unlike every sibling handler (handleStopBot/handleRestartBot/handleDeleteBot), start does not set/clear actionInProgress, and BotCard receives it to disable buttons. The Start button stays enabled while the request is in flight, so a double-click fires the start endpoint twice (restart semantics — the second call kills and restarts the fresh process).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| const hubObj = hubs.find((h) => h.hub_hash === target.hubHash); | ||
| if (hubObj) { | ||
| selectRoom(hubObj, { name: target.room }); | ||
| } else { |
There was a problem hiding this comment.
WARNING: Search-result fallback navigates to a room that can never render
When the hit's hub_hash is not in the connected hubs list, this branch sets selectedHubHash/selectedRoomName and loads messages, but selectedRoom is derived from hubs.find(...) (line 100) and stays null — and the chat pane is max-md:hidden with no header when selectedRoom is null (lines 592-596). The user is switched to the chat tab with an empty pane and no feedback. Hits for removed/disconnected hubs silently do nothing.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| } | ||
| </script> | ||
|
|
||
| <Dialog.Root bind:open onOpenChange={handleOpenChange}> |
There was a problem hiding this comment.
WARNING: Focus restoration lost in the bits-ui rewrite
The old implementation saved document.activeElement on open and re-focused it on destroy (the removed lines here). The rewrite delegates to bits-ui, but this modal is opened programmatically with no Dialog.Trigger in the tree, so bits-ui has nothing to restore focus to and focus falls to <body> on close — a keyboard/AT regression (WCAG 2.4.3) versus the pre-change behavior. Consider capturing the previously focused element and restoring it on close.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| }); | ||
| lastSavedName = (response.data as { name?: string })?.name || page.name; | ||
| published++; | ||
| } catch { |
There was a problem hiding this comment.
SUGGESTION: Per-page publish failures are swallowed to console
A site where most pages fail to upload still closes the modal and shows a success toast (2/10 pages to {server}) plus the "open in NomadNet" confirm; the failures are only visible in the console. Surface per-page or aggregate failure state to the user.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
…rgets Star imports drop underscore names, so route slices that referenced private helpers raised NameError at request time. Point the auth security handlers at the public is_loopback_bind_host from path_utils (matching master), fix the live-name entry that resolved a nonexistent meshchat attribute, rename the sticker document size cap to a public constant, and import list_host_network_interfaces directly in the interfaces crud slice. Re-export PluginSecurityError and MINIMAL_PLUGIN_WAT from the plugin_manager package, and repoint tests that patched pre-split module paths.
run_self_test lost the umsgpack, LXST telephony, audio codec, miniaudio, and translation pack checks when it moved out of meshchat.py, so the self-test response no longer matched the JSON contract. Add env_set, env_unset, and env_restore helpers so bot lifecycle and the AppContainer launch probe stop reading and writing os.environ directly, and pass the probe marker through argv for the -c path. Add the missing appcontainer_launch property to the self-test schema.
Port the master Nomad image-loading policy to the Svelte nomad page: per-node image policies, cached image downloads with relative and absolute URL resolution, and renderer metadata for image actions. From dev, port the crash tab iframe teleport to document.body with a rect-sync loop, transition-aware geometry filtering, and parked frame visibility gating. Preserve the browse list context so navigation from a list keeps the list tab instead of closing it, restore the last sidebar tab on remount, and add the mobile URL row.
From dev, port the conversation soft-resync merge that restashes the fresh first page and merges newer messages without clobbering scroll, the prefetch drop on delivery events, relay room back-navigation that restores the prior view, the hidden overflow tabs on narrow widths, and the announce interval input that accepts human durations such as hours and days across all locales.
RelayChatPage and ConversationViewer grew past their regression caps after the dev resync and relay view ports. Raise both caps and run prettier over three committed files that were not formatted.
|
|
||
| p_sd = ctypes.c_void_p() | ||
| p_dacl = ctypes.c_void_p() | ||
| get_status = user32.GetSecurityInfo( |
There was a problem hiding this comment.
CRITICAL: GetSecurityInfo / SetSecurityInfo are bound to user32, but these Win32 APIs are exported by advapi32.dll — user32 has no such exports, so user32.GetSecurityInfo raises AttributeError: function 'GetSecurityInfo' not found the first time grant_winstation_desktop_access runs on Windows.
The sibling _set_path_access correctly loads GetNamedSecurityInfoW from advapi32 (line 569), so this looks like a copy mistake. The caller at line 1170 only catches OSError, so the AttributeError propagates out of launch_backend_sandboxed and crashes the launcher before CreateProcessW — every MESHCHAT_APPCONTAINER auto/forced launch on Windows would fail. Same defect applies to user32.SetSecurityInfo at line 692. The unit tests miss it because they monkeypatch grant_winstation_desktop_access entirely.
Fix: load both functions from advapi32 (GetProcessWindowStation, OpenWindowStationW, GetThreadDesktop, OpenDesktopW, etc. legitimately live in user32; the usages at 722+ are fine).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| "import sys; open(sys.argv[1], 'w').write('ok')", | ||
| marker, | ||
| ] | ||
| result = ac.launch_backend_sandboxed( |
There was a problem hiding this comment.
WARNING: check_appcontainer_launch is the only self-check with no try/except Exception around its launch/verify body — every sibling check (e.g. check_public_assets, check_translation_pack_import) catches Exception and returns _status(False, ...).
Here ac.launch_backend_sandboxed(...) at line 399 runs bare with only a finally: env_restore. Any non-OSError exception (concretely, the user32.GetSecurityInfo AttributeError in appcontainer_sandbox/core.py:663, or any unexpected error in the marker-read block at 410-426) propagates out of the check and aborts the whole run_self_test, killing all remaining rows instead of reporting one failed "AppContainer Launch" row.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| return false; | ||
| } | ||
| const downloadId = json.download_id as number | string | undefined; | ||
| if (body!.status === "chunk") { |
There was a problem hiding this comment.
WARNING: chunk/started events are claimed based only on this.callbacks[imageId] presence, with no ownership check on those statuses (ownsNomadImageDownloadEvent runs only for the non-chunk paths).
When cancelStaleDownloads() (called from onImages/clear() during quick navigation) deletes the callback for an in-flight image, the backend's subsequent nomadnet.file.download events for that cancelled image fall through (handleFileDownloadEvent returns false) into the generic handler onNomadFileDownloadEvent in nomadPageDownloadEvents.ts. There, with currentFileDownloadId == null, chunk events set isDownloadingNodeFile: true + progress UI, and a late success would save the image bytes as a phantom user download; a late failure leaves the file-download state stuck since loadPage() does not reset it. A request-id (or download-id) check on the chunk/started branch would close the hole.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| this.deps.setImage(imageId, "loaded", { dataUrl, actualSize }); | ||
| } | ||
|
|
||
| private onDownloadFailure(imageId: number, reason: unknown): void { |
There was a problem hiding this comment.
WARNING: Buffered chunks are never freed on failure or cancel. appendDownloadChunk (line 379) stores partial base64 image bytes in the shared page-level nomadFileDownloadChunkBuffers, but onDownloadFailure (here), cancelStaleDownloads() (line 436) and clear() (line 452) never call discardDownloadChunks — only a chunked success consumes them.
Compare the generic handler's failure path in nomadPageDownloadEvents.ts:257-259, which explicitly discards. Every failed or cancelled image download permanently leaks its buffered bytes in the page's chunk-buffer map until component teardown.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| } | ||
| const cached = this.cache.get(nomadImageCacheKey(destinationHash, filePath)); | ||
| if (cached) { | ||
| this.deps.setImage(index, "loaded", { dataUrl: cached.dataUrl, actualSize: cached.size }); |
There was a problem hiding this comment.
SUGGESTION: A success with empty/absent file_bytes yields getNomadImageDataUrl() → null, which is cached as {dataUrl: null, size: "0 B"} in onDownloadSuccess (lines 419-422). Subsequent load() calls hit this cache (lines 343-345) and report "loaded" with dataUrl: null — the placeholder claims success and shows nothing, with no error surface. Consider treating an empty payload as a failure instead of caching the null result.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| ? 'bg-sem-canvas text-sem-fg font-semibold' | ||
| : 'text-sem-fg-muted hover:bg-sem-surface/80'}" | ||
| onclick={() => { | ||
| overflowMenuOpen = !overflowMenuOpen; |
There was a problem hiding this comment.
SUGGESTION: overflowMenuOpen has no outside-click or Escape dismissal, and pinned-tab clicks (the onclick on the tab buttons above only sets view) do not close it. On phones the dropdown overlay stays open covering the chat pane until the user re-taps the overflow button. A svelte:window keydown/outside-click handler or closing it on any tab onclick would fix it.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| const s = String(text ?? "") | ||
| .trim() | ||
| .toLowerCase() | ||
| .replace(",", "."); |
There was a problem hiding this comment.
SUGGESTION: .replace(",", ".") runs before the bare-integer fast path, so a thousands-separated value like "1,440" becomes "1.440" and parses to Math.round(1.44) = 1 minute — the user's intended 24 h interval silently collapses to 1 min. Decimal-comma support and thousands-separator input collide; consider rejecting bare numbers containing both a comma and a grouped digit triad, or only applying comma→dot when a unit suffix is present.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| fail(f"artifacts directory {out} does not exist; run build first") | ||
| if not any(p.is_file() for p in out.iterdir()): | ||
| fail(f"artifacts directory {out} is empty") | ||
| clean_generated_sidecars(out) |
There was a problem hiding this comment.
SUGGESTION: cmd_create calls clean_generated_sidecars(out) before resolve_notes(args, tag); if the user forgot notes in non-interactive mode, resolve_notes calls fail() — but the artifacts directory has already had its manifest.rsm/*.rsg sidecars permanently deleted. Cleaning after notes resolution (or only on rngit success) would avoid stripping signatures on a validation failure.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
|
|
||
| def write_editor_shim(notes_text: str) -> Path: | ||
| """Create a temp editor that replaces rngit's notes template with our text.""" | ||
| tmpdir = Path(tempfile.mkdtemp(prefix="rngit-release-")) |
There was a problem hiding this comment.
SUGGESTION: write_editor_shim allocates tempfile.mkdtemp(prefix="rngit-release-") and never cleans it up; every notes-bearing create/release run leaks a temp directory containing notes.md and an executable shim. Consider a try/finally with shutil.rmtree(tmpdir) after run_rngit consumes the shim.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| issues.push(`Missing: ${relPath}`); | ||
| continue; | ||
| } | ||
| if (sha256(fullPath) !== expectedHash) { |
There was a problem hiding this comment.
SUGGESTION: sha256(fullPath) calls readFileSync unguarded; if a manifest entry collides with a directory in the packaged tree (or the file is unreadable), the script dies with an uncaught EISDIR/EACCES stack trace instead of reporting a clean Modified:/Unreadable: issue and exiting 1, weakening the CI signal this script exists to provide. A try/catch that pushes an issue would keep the failure actionable.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Clamp remote-controlled quality and max_dimension before they reach media cache keys so peers cannot spawn unbounded conversions, and wrap the quality int cast like its siblings. Reject commas in RRC room names so CLI serialization round-trips. Add the require_database guard and database exception mapping to the archives export route, and pass the identity hash rather than the identity object to RRCServerManager in the shared fixture so owner auto-trust matches production.
Stop microphone recording and revoke preview URLs when the composer unmounts mid-session, reset virtual-list height measurements when the conversation changes and cap the record size, scope relay discovery to the rrc.hub aspect and warn instead of opening a blank pane for disconnected hubs, re-apply nomad route targets when keep-alive pushes new route props, accept leading-slash micron image URLs, protect generated anchors from later geo-linkify passes, key the markdown render cache per pipeline and clear it on config change, reject pending bergamot calls on worker failure, dedupe publish-site filenames and surface per-page failures, disable the bot start button while a start is in flight, and restore focus to the invoker when programmatic modals close.
Replace the O(n) visible-row scan in both virtual message lists with a binary search over the sorted layout, defer loading the wasm-backed translation service until translation is actually used, and skip conversation and folder poll ticks while the previous request is still in flight.
Annotate the announce interval parser regexes with the bounded-input justification used elsewhere, run prettier over the generated license manifests and fixtures, and allowlist the nomad browser host leaf that grew past its cap after the image policy and route-restore ports.
|
|
||
| // Link rendering reads live GlobalState config (for example the default nomad | ||
| // page path), so cached output must be dropped when GlobalState mutates. | ||
| subscribeGlobalState(() => { |
There was a problem hiding this comment.
WARNING: Render LRU is wiped by every high-frequency GlobalState mutation
subscribeGlobalState fires for the whole state object, not just config: unreadConversationsCount is reassigned on every conversation poll, alongside relayChatUnreadCount, missedCallsCount, activeCallTab, networkDegraded, and so on. Each of those mutations now clears the entire 800-entry render cache — defeating the memoization exactly during busy chat, which is what this cache exists for. The nomad_default_page_path dependency only needs invalidation on config changes; clear the cache only when a config key mutates (e.g. in the mergeGlobalConfig path) instead of on any state write.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| try: | ||
| quality = int(quality) | ||
| except (TypeError, ValueError): | ||
| quality = MEDIA_QUALITY |
There was a problem hiding this comment.
SUGGESTION: OverflowError escapes the new quality clamp
int(quality) catches only (TypeError, ValueError), but Python's JSON parser accepts Infinity/NaN literals, so a remote peer sending "quality": Infinity makes int(float('inf')) raise OverflowError — escaping this clamp and the responder's parse at line 1048, which has the same except tuple. Since this clamp was added precisely to sanitize untrusted peer input, add OverflowError to both except tuples (note int(float('nan')) already lands in the covered ValueError path).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| }); | ||
| if (!session) return; | ||
| if (destroyed) { | ||
| // Unmounted while getUserMedia was still resolving; release the mic. |
There was a problem hiding this comment.
SUGGESTION: Preview object URL leaks in the unmount-mid-start path
stopAudioRecordingSession(session) here discards the resolved ComposeAudio, whose audio_preview_url was just created with URL.createObjectURL — it is never revoked. The destroyed branch at line 193 handles this correctly; mirror it, e.g. .then((r) => r?.audio_preview_url && URL.revokeObjectURL(r.audio_preview_url)), so the mic-release path doesn't leak the blob URL (and skip codec2's decode work too).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| for (const entry of entries) { | ||
| entry.reject(error); | ||
| } | ||
| this.onerror(error); |
There was a problem hiding this comment.
SUGGESTION: Calls after a fatal worker error hang again, and onerror may be undefined
Two edges in the new failure path: (1) failPending drains only the in-flight batch — after the worker dies once, the exports proxy stays live and every later call() posts into a dead worker and creates new pending entries that no further error event will ever reject (a worker fires error typically once). Consider a failed latch that rejects future calls immediately. (2) this.onerror(error) is invoked unguarded; TranslationService constructs new BergamotBacking() without an onerror option, so if the vendor base class doesn't default it, this throws inside the listener. this.onerror?.(error) is cheap insurance.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| // it back on close for WCAG 2.4.3 focus order. | ||
| let previouslyFocused: HTMLElement | null = null; | ||
|
|
||
| $effect.pre(() => { |
There was a problem hiding this comment.
SUGGESTION: Focus restore never runs when an open modal is unmounted
Capture and restore both depend on open transitioning while this component is alive. When a parent unmounts the Modal while open (keepAlive page teardowns do exactly this), the restore $effect is torn down rather than re-run with open=false, so previouslyFocused is dropped and focus falls to <body> — the same WCAG 2.4.3 gap this change set out to close. Register the restore inside the effect's cleanup ($effect(() => { if (!open) return; ...; return () => { if (!open) el?.focus?.(); } }) or equivalent) so destroy-while-open also restores.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| if (!hubObj) { | ||
| // The hub is not in the local list (never added or disconnected), | ||
| // so selecting it would leave the pane blank with no feedback. | ||
| ToastUtils.warning(t("relay_chat.hub_not_added")); |
There was a problem hiding this comment.
SUGGESTION: Misleading "not added" toast when the hubs list is merely stale
openSearchResult now hard-gates on the client-side hubs array. If fetchHubs() hasn't resolved yet (or its catch emptied the list), clicking a search result for a genuinely connected hub shows "Add this hub to your list before opening a room" and silently does nothing. Search hits originate from the same server-side hub set, so a refetch-before-give-up (or falling back to the previous direct-open path) would avoid blaming the user for a transient empty list.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Why? Better maintainability and opportunity to break down all those "god" files into components and more maintainable frontend. I am more experienced with Svelte and Typescript.
This will also feature large backend refactors to break down meshchat.py.
Using various open-weight models.