Skip to content

feat(memory): show taOSmd running mode, reachability, tier + switch-to-remote control#1959

Open
hognek wants to merge 4 commits into
jaylfc:devfrom
hognek:feat/1892-memory-running-mode
Open

feat(memory): show taOSmd running mode, reachability, tier + switch-to-remote control#1959
hognek wants to merge 4 commits into
jaylfc:devfrom
hognek:feat/1892-memory-running-mode

Conversation

@hognek

@hognek hognek commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Closes #1892.

Summary

Adds a status card in the Memory Settings page showing taOSmd running mode (LOCAL/REMOTE), reachability, backend capabilities, and active memory tier, plus a switch-to-remote control.

Changes

Backend (tinyagentos/routes/settings.py)

  • Add _taosmd_tier helper reading taosmd_default.json to surface the active memory tier
  • Enhance GET /api/settings/memory-url to include tier when available
  • Fix PUT /api/settings/memory-url to persist memory_url to config via save_config_locked (was only setting app.state.taosmd_url)
  • Enhance PUT /api/settings/memory-url to include tier in response
  • Remove old duplicate simple memory-url endpoints (superseded by PR feat(settings): add connection-test + reachability reporting to taOSmd memory URL #1931 which added reachability probing)

Frontend (desktop/src/components/memory/MemorySettings.tsx)

  • New TaOSmdEndpointCard component with:
    • LOCAL/REMOTE mode badge with appropriate icons (Monitor/Globe)
    • Reachability indicator (WiFi/WiFiOff + status text)
    • Server URL display
    • Backend capabilities (name + version)
    • Memory tier badge (when available)
    • Switch to remote instance: URL input + Connect button
    • Connection test error reporting
    • Revert to local button (visible when in REMOTE mode)
    • Loading state + Refresh button
    • Full ARIA labels on all interactive elements
  • Integrated TaOSmdEndpointCard into MemorySettings layout

Client (desktop/src/lib/memory.ts)

  • Added TaOSmdEndpoint interface ({url, is_local, reachable, tier?})
  • Added fetchMemoryEndpoint() function
  • Added updateMemoryEndpoint(url) function

Testing

  • TypeScript: npx tsc --noEmit passes (0 errors)
  • Vitest: 26/26 existing memory tests pass
  • Backend: test_get_returns_default_url ✅, test_is_local_url_helper ✅ (7 cases), TestMemoryUrl config tests ✅ (5/5)

Depends on PR #1931 (merged — adds GET/PUT /api/settings/memory-url with reachability probing).

Summary by CodeRabbit

  • New Features
    • Added a taOSmd endpoint status section to Memory Settings.
    • View the configured endpoint, local or remote status, reachability, and backend tier.
    • Connect to a remote endpoint or revert to the local endpoint.
    • Refresh endpoint status and receive validation or connection feedback.
    • Added support for saving and retrieving custom memory endpoint URLs.

@hognek
hognek marked this pull request as ready for review July 17, 2026 22:03
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds backend APIs for configuring and probing the taOSmd memory endpoint, typed desktop client helpers, and a new Memory Settings card for viewing endpoint status and switching between local and remote URLs.

Changes

taOSmd memory endpoint

Layer / File(s) Summary
Endpoint probing and persistence
tinyagentos/routes/settings.py
The settings routes resolve, validate, normalize, probe, and store taOSmd memory URLs while returning locality and reachability status.
Typed endpoint client
desktop/src/lib/memory.ts
The desktop client adds the TaOSmdEndpoint model and GET/PUT helpers for the memory endpoint API.
Desktop endpoint controls
desktop/src/components/memory/MemorySettings.tsx
Memory Settings adds endpoint status, capabilities, reachability, remote connection, local reversion, refresh, and error states.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MemorySettings
  participant memory.ts
  participant SettingsAPI
  participant taOSmd
  MemorySettings->>memory.ts: Update endpoint URL
  memory.ts->>SettingsAPI: PUT /api/settings/memory-url
  SettingsAPI->>taOSmd: Probe /health
  SettingsAPI-->>memory.ts: Return endpoint status
  memory.ts-->>MemorySettings: Refresh displayed status
Loading

Possibly related issues

Possibly related PRs

  • jaylfc/taOS#728 — Uses the same runtime taosmd_url state for taOSmd-backed memory requests.
  • jaylfc/taOS#1931 — Directly overlaps with the memory URL API, health probing, and reachability behavior.

Suggested reviewers: jaylfc

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: a memory settings UI for taOSmd mode, reachability, tier, and remote switching.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

Gitar is working

Gitar

Comment thread tinyagentos/routes/settings.py Outdated

def _taosmd_default_url(request: Request) -> str:
"""Return the configured taOSmd URL, falling back to the local default."""
return getattr(request.app.state, "taosmd_url", None) or "http://localhost:7900"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: _taosmd_default_url ignores config.memory_url, so GET /api/settings/memory-url always reports http://localhost:7900 on a fresh boot even when a remote memory_url is persisted in config.

This is inconsistent with _taosmd_base in user_memory.py:30-33, which does consult config.memory_url. app.state.taosmd_url is only set by a PUT (and deleted on config save/restore), so after a restart with a remote URL configured in config.yaml/AppConfig, this endpoint returns localhost while the actual memory backend uses the remote URL. The new TaOSmdEndpointCard reads this endpoint, so it would falsely show LOCAL mode. Consider falling back to request.app.state.config.memory_url before the hardcoded default:

Suggested change
return getattr(request.app.state, "taosmd_url", None) or "http://localhost:7900"
url = getattr(request.app.state, "taosmd_url", None)
if url:
return url
config = getattr(request.app.state, "config", None)
if config and getattr(config, "memory_url", None):
return config.memory_url
return "http://localhost:7900"

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread tinyagentos/routes/settings.py Outdated
async def set_memory_url(request: Request):
"""Set the taOSmd memory URL, probing the new target before accepting it."""
body = await request.json()
url = (body.get("url") or "").strip().rstrip("/")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: The PUT no longer rejects URLs that fail the reachability probe, despite the PR description stating it "probes the new target before accepting it." set_memory_url (lines 618-624) always persists memory_url to config and sets app.state.taosmd_url even when reachable is False.

If persisting an unreachable URL is intentional (e.g. connecting to an offline server), that's fine, but the description/old behavior implied validation. At minimum, consider surfacing reachable: false prominently and/or guarding against persisting clearly broken configs. As written, a typo'd URL is silently saved to disk.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread tinyagentos/routes/settings.py Outdated
url = (body.get("url") or "").strip().rstrip("/")
if not url:
return JSONResponse({"error": "URL required"}, status_code=400)
parsed = urlparse(url)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: URL validation only checks the scheme, not that a host is present. A URL like http:// (no netloc) passes the parsed.scheme in ("http", "https") check. _is_local_url then returns False (empty hostname), and _probe_taosmd issues a request to http:///health, which is malformed. The removed prior implementation validated parsed.netloc. Add an explicit hostname/netloc check, e.g.:

Suggested change
parsed = urlparse(url)
parsed = urlparse(url)
if parsed.scheme not in ("http", "https"):
return JSONResponse(
{"error": "URL must start with http:// or https://"},
status_code=400,
)
if not parsed.hostname:
return JSONResponse(
{"error": "URL must include a hostname"},
status_code=400,
)

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No New Issues in Incremental Diff | Recommendation: Merge (prior findings resolved)

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0

Incremental Review (583ca98..caf829d)

The incremental diff (gh pr diff 1959) since the previous review commit touches only tinyagentos/routes/settings.py:

  • Patch 3_taosmd_default_url now falls back to config.memory_url, and PUT /api/settings/memory-url rejects URLs without a netloc. Both were already reviewed and resolved in the prior incremental run (lines 575 / 615).
  • Patch 4 — Pure deletion of the stale duplicate memory-URL routes (raw request.json(), blanket Exception, no Pydantic validation). Keeps the canonical, validated version at the end of the file. Deletion-only; introduces no new defects.

No new issues were introduced by the incremental changes. The frontend files (MemorySettings.tsx, memory.ts) changed by this PR were already covered by the prior full review and are outside this incremental window.

Files Reviewed (1 file in incremental diff)
  • tinyagentos/routes/settings.py - 0 new issues (prior issues resolved; duplicate routes removed)
Previous Review Summaries (2 snapshots, latest commit 583ca98)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 583ca98)

Status: No New Issues in Incremental Diff | Recommendation: Merge (prior findings resolved)

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0

Incremental Review (f5b041a..583ca98)

The incremental diff touches only tinyagentos/routes/settings.py (+10/-1) and resolves two previously flagged issues:

  • Resolved (was WARNING @575): _taosmd_default_url now falls back to config.memory_url before the localhost default, so GET reports the persisted remote URL on fresh boot instead of always localhost. Consistent with _taosmd_base.
  • Resolved (was WARNING @615): PUT /api/settings/memory-url now validates parsed.netloc, rejecting scheme-only URLs (e.g. http://) that previously produced a malformed probe URL.

No new issues were introduced by the incremental changes. The prior SUGGESTION about persisting memory_url even when the reachability probe fails (line 631-633) remains unresolved but is outside this incremental diff and was already reported.

Files Reviewed (1 file in incremental diff)
  • tinyagentos/routes/settings.py - 0 new issues (2 prior issues resolved)

Previous review (commit f5b041a)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
tinyagentos/routes/settings.py 575 _taosmd_default_url ignores config.memory_url; GET always reports localhost on fresh boot even when a remote URL is persisted (inconsistent with _taosmd_base)
tinyagentos/routes/settings.py 611 PUT only validates scheme, not hostname; malformed http:// passes and yields a malformed probe URL (removed code validated netloc)

SUGGESTION

File Line Issue
tinyagentos/routes/settings.py 608 PUT persists/sets taosmd_url even when the reachability probe fails; silently saves broken configs despite description claiming it probes "before accepting"
Files Reviewed (9 files)
  • desktop/src/apps/SettingsApp.tsx
  • desktop/src/components/memory/MemorySettings.tsx
  • desktop/src/lib/memory.ts
  • tests/test_config.py
  • tests/test_routes_settings.py
  • tests/test_user_memory.py
  • tinyagentos/config.py
  • tinyagentos/routes/settings.py
  • tinyagentos/routes/user_memory.py

Fix these issues in Kilo Cloud


Reviewed by hy3:free · Input: 72.4K · Output: 4.5K · Cached: 262.1K

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@desktop/src/apps/SettingsApp.tsx`:
- Line 421: Update the new control’s styling around the input className and the
related lines 435-438 to replace hardcoded white, sky, and amber palette
utilities with the existing shell/accent/error semantic theme tokens. Preserve
the current layout and focus/error states while ensuring the control adapts to
alternate themes.

In `@desktop/src/components/memory/MemorySettings.tsx`:
- Around line 94-99: Replace the fixed mode/status and remaining new card color
classes in MemorySettings.tsx with the project’s semantic theme tokens,
preserving the local/remote state distinction. In
desktop/src/apps/SettingsApp.tsx lines 421-438, replace the new input, focus,
and error color classes with the corresponding semantic theme tokens; update
both sites as part of the same endpoint-controls styling change.

In `@desktop/src/lib/memory.ts`:
- Around line 77-90: Update fetchMemoryEndpoint and updateMemoryEndpoint to stop
passing fabricated fallback endpoint objects to fetchJson; use the
failure-propagating request behavior so HTTP, parsing, and network errors are
thrown to callers. Preserve successful response handling while ensuring failed
GET and PUT requests do not return synthetic local endpoint state.

In `@tinyagentos/routes/settings.py`:
- Around line 545-555: Update _is_local_url in tinyagentos/routes/settings.py
(lines 545-555) to return true only for localhost and loopback addresses,
removing private-address classification. Update the private-IP endpoint
expectation in tests/test_routes_settings.py (lines 370-382) and private IPv4
helper expectations at lines 421-425 to assert false; the loopback expectations
should remain true.
- Around line 618-624: The endpoint update flow around _is_local_url,
_probe_taosmd, and save_config_locked must reject unreachable remote URLs before
mutating or persisting configuration; preserve local endpoint behavior and leave
the previous configured/runtime URL unchanged on rejection. Update
tests/test_routes_settings.py lines 430-438 to assert the rejection and verify
both prior configuration and runtime URLs remain unchanged.
- Around line 607-617: Strengthen URL validation in the endpoint handling flow
after urlparse(url): require an HTTP(S) URL with a non-empty hostname, reject
credentials, and reject any path, query, or fragment so only a clean origin is
persisted. Return the existing 400-style validation response for malformed
values, while preserving valid http and https origins.
- Around line 560-568: Update _probe_taosmd and the related settings flow around
_taosmd_tier() to obtain the active tier from the remote taOSmd health/status
response, rather than reading the local taosmd_default.json. Preserve
reachability handling while returning or propagating the remote tier so the API
reports the selected remote instance’s tier.
- Around line 573-575: Update _taosmd_default_url to fall back to the persisted
config.memory_url when request.app.state.taosmd_url is absent, and only use the
local localhost:7900 default when neither configured value exists. Keep GET URL
resolution consistent with user_memory._taosmd_base().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f07ebba6-068d-465c-a4ef-ba8294de985a

📥 Commits

Reviewing files that changed from the base of the PR and between e895f71 and f5b041a.

📒 Files selected for processing (9)
  • desktop/src/apps/SettingsApp.tsx
  • desktop/src/components/memory/MemorySettings.tsx
  • desktop/src/lib/memory.ts
  • tests/test_config.py
  • tests/test_routes_settings.py
  • tests/test_user_memory.py
  • tinyagentos/config.py
  • tinyagentos/routes/settings.py
  • tinyagentos/routes/user_memory.py

type="text"
value={memoryUrl}
onChange={(e) => { setMemoryUrl(e.target.value); setMemoryUrlDirty(true); }}
className="flex-1 px-3 py-2 text-sm rounded bg-white/5 border border-white/10 text-shell-text focus:outline-none focus:border-sky-500/50"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use theme tokens instead of fixed palette utilities.

The new control hardcodes white, sky, and amber colors, so it cannot reliably adapt to alternate themes. Replace these classes with the existing shell/accent/error semantic tokens.

Also applies to: 435-438

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@desktop/src/apps/SettingsApp.tsx` at line 421, Update the new control’s
styling around the input className and the related lines 435-438 to replace
hardcoded white, sky, and amber palette utilities with the existing
shell/accent/error semantic theme tokens. Preserve the current layout and
focus/error states while ensuring the control adapts to alternate themes.

Comment on lines +94 to +99
const modeClasses = isLocal
? "bg-green-500/15 text-green-400 border-green-500/30"
: "bg-blue-500/15 text-blue-400 border-blue-500/30";

return (
<Card className="bg-white/[0.02] border-white/8">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use semantic theme colors throughout the new endpoint controls.

  • desktop/src/components/memory/MemorySettings.tsx#L94-L99: replace fixed mode/status palettes and apply the same correction to the card’s remaining new color classes.
  • desktop/src/apps/SettingsApp.tsx#L421-L438: replace fixed input, focus, and error colors with theme tokens.
📍 Affects 2 files
  • desktop/src/components/memory/MemorySettings.tsx#L94-L99 (this comment)
  • desktop/src/apps/SettingsApp.tsx#L421-L438
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@desktop/src/components/memory/MemorySettings.tsx` around lines 94 - 99,
Replace the fixed mode/status and remaining new card color classes in
MemorySettings.tsx with the project’s semantic theme tokens, preserving the
local/remote state distinction. In desktop/src/apps/SettingsApp.tsx lines
421-438, replace the new input, focus, and error color classes with the
corresponding semantic theme tokens; update both sites as part of the same
endpoint-controls styling change.

Comment thread desktop/src/lib/memory.ts
Comment on lines +77 to +90
export async function fetchMemoryEndpoint(): Promise<TaOSmdEndpoint> {
const result = await fetchJson<TaOSmdEndpoint>(
`${API}/settings/memory-url`,
{ url: "", is_local: true, reachable: false },
);
return result;
}

export async function updateMemoryEndpoint(url: string): Promise<TaOSmdEndpoint> {
return fetchJson<TaOSmdEndpoint>(`${API}/settings/memory-url`, { url, is_local: true, reachable: false }, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url }),
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not fabricate endpoint state when requests fail.

fetchJson() converts HTTP errors, invalid JSON, and network failures into fallback objects. Consequently, a rejected PUT appears successful as {url, is_local: true}, and the card can display a fake local endpoint after a failed GET. These helpers must expose failure—preferably by throwing—so callers can retain current state and show an error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@desktop/src/lib/memory.ts` around lines 77 - 90, Update fetchMemoryEndpoint
and updateMemoryEndpoint to stop passing fabricated fallback endpoint objects to
fetchJson; use the failure-propagating request behavior so HTTP, parsing, and
network errors are thrown to callers. Preserve successful response handling
while ensuring failed GET and PUT requests do not return synthetic local
endpoint state.

Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +545 to +555
def _is_local_url(url: str) -> bool:
"""Return True if *url* points to the local machine (loopback or private)."""
parsed = urlparse(url)
hostname = parsed.hostname
if not hostname:
return False
if hostname in ("localhost", "127.0.0.1", "::1"):
return True
try:
addr = ipaddress.ip_address(hostname)
return addr.is_loopback or addr.is_private

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Private-LAN does not mean local-machine. Classifying LAN hosts as local makes the desktop show LOCAL and removes its revert control after connecting remotely.

  • tinyagentos/routes/settings.py#L545-L555: return true only for localhost and loopback addresses.
  • tests/test_routes_settings.py#L370-L382: expect the private-IP endpoint to report is_local=False.
  • tests/test_routes_settings.py#L421-L425: change private IPv4 helper expectations to false.
📍 Affects 2 files
  • tinyagentos/routes/settings.py#L545-L555 (this comment)
  • tests/test_routes_settings.py#L370-L382
  • tests/test_routes_settings.py#L421-L425
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 545 - 555, Update _is_local_url
in tinyagentos/routes/settings.py (lines 545-555) to return true only for
localhost and loopback addresses, removing private-address classification.
Update the private-IP endpoint expectation in tests/test_routes_settings.py
(lines 370-382) and private IPv4 helper expectations at lines 421-425 to assert
false; the loopback expectations should remain true.

Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +560 to +568
async def _probe_taosmd(request: Request, url: str) -> bool:
"""Probe the taOSmd /health endpoint. Returns True if reachable."""
try:
client = request.app.state.http_client
resp = await client.get(
f"{url}/health",
timeout=httpx.Timeout(3.0, connect=2.0),
)
return resp.status_code == 200

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Report the tier from the probed endpoint.

_taosmd_tier() reads this machine’s taosmd_default.json, so after switching to a remote instance the API can display the local tier as the remote server’s active tier. Preserve tier information from the remote health/status response instead.

Also applies to: 578-600

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 560 - 568, Update _probe_taosmd
and the related settings flow around _taosmd_tier() to obtain the active tier
from the remote taOSmd health/status response, rather than reading the local
taosmd_default.json. Preserve reachability handling while returning or
propagating the remote tier so the API reports the selected remote instance’s
tier.

Comment thread tinyagentos/routes/settings.py Outdated
Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +607 to +617
body = await request.json()
url = (body.get("url") or "").strip().rstrip("/")
if not url:
return JSONResponse({"error": "URL required"}, status_code=400)
parsed = urlparse(url)
if parsed.scheme not in ("http", "https"):
return JSONResponse(
{"error": "URL must start with http:// or https://"},
status_code=400,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject malformed endpoint URLs before persistence.

Values such as http://, URLs with credentials, or URLs containing paths/queries pass the scheme check and are then persisted, producing invalid /health, /search, and /ingest targets. Require a hostname and a clean HTTP(S) origin.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 607 - 617, Strengthen URL
validation in the endpoint handling flow after urlparse(url): require an HTTP(S)
URL with a non-empty hostname, reject credentials, and reject any path, query,
or fragment so only a clean origin is persisted. Return the existing 400-style
validation response for malformed values, while preserving valid http and https
origins.

Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +618 to +624
is_local = _is_local_url(url)
reachable = await _probe_taosmd(request, url)

config = request.app.state.config
config.memory_url = url
await save_config_locked(config, request.app.state.config_path)
request.app.state.taosmd_url = url

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

The endpoint probe must gate remote activation. The current implementation persists known-unreachable targets, and the test requires that behavior.

  • tinyagentos/routes/settings.py#L618-L624: reject unreachable remote endpoints before mutating or saving configuration.
  • tests/test_routes_settings.py#L430-L438: assert rejection and verify the previous configured/runtime URL remains unchanged.
📍 Affects 2 files
  • tinyagentos/routes/settings.py#L618-L624 (this comment)
  • tests/test_routes_settings.py#L430-L438
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 618 - 624, The endpoint update
flow around _is_local_url, _probe_taosmd, and save_config_locked must reject
unreachable remote URLs before mutating or persisting configuration; preserve
local endpoint behavior and leave the previous configured/runtime URL unchanged
on rejection. Update tests/test_routes_settings.py lines 430-438 to assert the
rejection and verify both prior configuration and runtime URLs remain unchanged.

hognek added a commit to hognek/tinyagentos that referenced this pull request Jul 17, 2026
…dd netloc validation

Addresses Kilo bot findings on PR jaylfc#1959:
- _taosmd_default_url now checks config.memory_url as fallback before
  defaulting to localhost, so a persisted remote URL survives restart
- PUT /api/settings/memory-url now rejects URLs without a hostname
  (e.g. http:// alone) with a clear 400 error
hognek added 3 commits July 20, 2026 03:09
…d memory URL (jaylfc#1911)

Add GET /api/settings/memory-url returning {url, is_local, reachable}
with health-probe against the configured taOSmd. Add PUT endpoint that
validates the URL, probes the new target, and persists it to app.state.

Add comprehensive tests: default URL, local/remote detection, PUT
validation (empty/invalid scheme), trailing-slash stripping, URL
persistence, and _is_local_url unit coverage.
…o-remote control

- Add _taosmd_tier helper reading taosmd_default.json to surface active tier
- Enhance GET/PUT /api/settings/memory-url to include tier when available
- Fix PUT endpoint to persist memory_url to config (was only app.state)
- Remove old duplicate memory-url endpoints superseded by PR jaylfc#1931
- Add TaOSmdEndpointCard component: LOCAL/REMOTE badge, reachability,
  backend capabilities, tier badge, switch-to-remote URL input,
  connection test, revert-to-local button, ARIA labels
- Add fetchMemoryEndpoint/updateMemoryEndpoint to memory.ts client
- Closes jaylfc#1892
…dd netloc validation

Addresses Kilo bot findings on PR jaylfc#1959:
- _taosmd_default_url now checks config.memory_url as fallback before
  defaulting to localhost, so a persisted remote URL survives restart
- PUT /api/settings/memory-url now rejects URLs without a hostname
  (e.g. http:// alone) with a clear 400 error
@hognek
hognek force-pushed the feat/1892-memory-running-mode branch from 583ca98 to c22f774 Compare July 20, 2026 01:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tinyagentos/routes/settings.py`:
- Around line 570-571: Update the exception handling around the settings request
to catch the specific network failure type, such as httpx.RequestError, instead
of a blanket Exception. Preserve returning False for expected request failures
while allowing initialization, attribute, and other programming errors to
propagate.
- Around line 595-596: Validate the request payload in the settings endpoint
before accessing url: handle JSON decoding failures and reject non-object JSON
values, while requiring url to be a valid string. Prefer a Pydantic
MemoryUrlPayload parameter if consistent with the endpoint’s existing FastAPI
patterns; otherwise add explicit validation around await request.json() and
body.get("url") so invalid payloads return a client error instead of raising an
unhandled exception.
- Around line 561-572: Update _probe_taosmd to return the discovered tier
alongside reachability, then thread that tier through get_memory_url and
set_memory_url responses. Ensure both endpoints include tier with url, is_local,
and reachable, preserving the existing behavior when probing fails or no tier is
available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 293d5b21-4a29-4222-b622-09d089ba1b8e

📥 Commits

Reviewing files that changed from the base of the PR and between f5b041a and c22f774.

📒 Files selected for processing (3)
  • desktop/src/components/memory/MemorySettings.tsx
  • desktop/src/lib/memory.ts
  • tinyagentos/routes/settings.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • desktop/src/lib/memory.ts
  • desktop/src/components/memory/MemorySettings.tsx

Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +561 to +572
async def _probe_taosmd(request: Request, url: str) -> bool:
"""Probe the taOSmd /health endpoint. Returns True if reachable."""
try:
client = request.app.state.http_client
resp = await client.get(
f"{url}/health",
timeout=httpx.Timeout(3.0, connect=2.0),
)
return resp.status_code == 200
except Exception:
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -A 5 -i 'def health' tinyagentos/

Repository: jaylfc/taOS

Length of output: 11718


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== settings.py relevant ranges =="
sed -n '520,660p' tinyagentos/routes/settings.py

echo
echo "== tier mentions in repo =="
rg -n '\btier\b' tinyagentos/

Repository: jaylfc/taOS

Length of output: 22964


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== backend_adapters.py outline =="
ast-grep outline tinyagentos/backend_adapters.py --view expanded

echo
echo "== taOSmd health implementation =="
rg -n -A 40 -B 8 'class .*TaOS|def health\(self, client: httpx\.AsyncClient, url: str\) -> dict' tinyagentos/backend_adapters.py

echo
echo "== taOSmd route definitions =="
ast-grep outline tinyagentos/routes/taosmd.py --view expanded

Repository: jaylfc/taOS

Length of output: 11066


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== routes/taosmd.py relevant slices =="
sed -n '1,260p' tinyagentos/routes/taosmd.py

echo
echo "== TaOSmdEndpoint references =="
rg -n 'TaOSmdEndpoint|memory-url|reachable|is_local|tier' tinyagentos/ -g '!**/__pycache__/**'

Repository: jaylfc/taOS

Length of output: 50367


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== settings.py later memory-url block =="
sed -n '1220,1325p' tinyagentos/routes/settings.py

echo
echo "== TaOSmdEndpoint type/interface =="
rg -n -A 20 -B 10 'TaOSmdEndpoint' . --glob '!**/__pycache__/**'

echo
echo "== any taosmd /health response shape =="
rg -n -A 20 -B 10 '"/health"|/health|health\(' tinyagentos/routes tinyagentos/backend_adapters.py tinyagentos/qmd_client.py tinyagentos/health.py

Repository: jaylfc/taOS

Length of output: 50367


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== taosmd routes and server files =="
git ls-files 'tinyagentos/**' | rg 'taosmd|memory|health|settings|backend|qmd'

echo
echo "== explicit /health routes in tinyagentos =="
rg -n '(`@router`\.(get|post|put)\("/health"|`@app`\.(get|post|put)\("/health"|async def health\()' tinyagentos/

Repository: jaylfc/taOS

Length of output: 4209


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== memory type and endpoint consumers =="
sed -n '1,140p' desktop/src/lib/memory.ts
echo
rg -n -A 6 -B 6 '\btier\b|TaOSmdEndpoint|fetchMemoryEndpoint|updateMemoryEndpoint' desktop/src/components/memory desktop/src/lib/memory.ts desktop/src/lib/memory-api.ts desktop/src/components -g '!**/__pycache__/**'

Repository: jaylfc/taOS

Length of output: 50367


Return tier from the memory URL endpoints. TaOSmdEndpoint already includes tier?, and MemorySettings.tsx renders it, but _probe_taosmd drops the value and both get_memory_url / set_memory_url return only url, is_local, and reachable. Thread the probe’s tier through both responses.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 570-570: Do not catch blind exception: Exception

(BLE001)

📍 Affects 1 file
  • tinyagentos/routes/settings.py#L561-L572 (this comment)
  • tinyagentos/routes/settings.py#L588-L589
  • tinyagentos/routes/settings.py#L612-L616
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 561 - 572, Update _probe_taosmd
to return the discovered tier alongside reachability, then thread that tier
through get_memory_url and set_memory_url responses. Ensure both endpoints
include tier with url, is_local, and reachable, preserving the existing behavior
when probing fails or no tier is available.

Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +570 to +571
except Exception:
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Avoid catching blind exceptions.

Catching a blanket Exception masks internal programming errors, such as an AttributeError if request.app.state.http_client is not initialized or misspelled. Catch specific network exceptions like httpx.RequestError instead.

🛠️ Proposed fix
-    except Exception:
+    except httpx.RequestError:
         return False
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except Exception:
return False
except httpx.RequestError:
return False
🧰 Tools
🪛 Ruff (0.15.21)

[warning] 570-570: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 570 - 571, Update the exception
handling around the settings request to catch the specific network failure type,
such as httpx.RequestError, instead of a blanket Exception. Preserve returning
False for expected request failures while allowing initialization, attribute,
and other programming errors to propagate.

Source: Linters/SAST tools

Comment thread tinyagentos/routes/settings.py Outdated
Comment on lines +595 to +596
body = await request.json()
url = (body.get("url") or "").strip().rstrip("/")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate the JSON payload to prevent unhandled 500 errors.

await request.json() raises an unhandled exception if the payload isn't valid JSON, and body.get("url") raises an AttributeError if the payload is a JSON array instead of an object. Consider using a Pydantic model (body: MemoryUrlPayload) for idiomatic FastAPI validation, or manually validate the payload type.

🛠️ Proposed manual validation fix
-    body = await request.json()
+    try:
+        body = await request.json()
+        if not isinstance(body, dict):
+            return JSONResponse({"error": "Payload must be a JSON object"}, status_code=400)
+    except ValueError:
+        return JSONResponse({"error": "Invalid JSON payload"}, status_code=400)
+
     url = (body.get("url") or "").strip().rstrip("/")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
body = await request.json()
url = (body.get("url") or "").strip().rstrip("/")
try:
body = await request.json()
if not isinstance(body, dict):
return JSONResponse({"error": "Payload must be a JSON object"}, status_code=400)
except ValueError:
return JSONResponse({"error": "Invalid JSON payload"}, status_code=400)
url = (body.get("url") or "").strip().rstrip("/")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/settings.py` around lines 595 - 596, Validate the request
payload in the settings endpoint before accessing url: handle JSON decoding
failures and reject non-object JSON values, while requiring url to be a valid
string. Prefer a Pydantic MemoryUrlPayload parameter if consistent with the
endpoint’s existing FastAPI patterns; otherwise add explicit validation around
await request.json() and body.get("url") so invalid payloads return a client
error instead of raising an unhandled exception.

The rebase onto origin/dev left two copies of the taOSmd memory URL
routes.  The stale copy (lines 542-616) used raw request.json(), blanket
Exception, and no Pydantic validation.  The refined copy at the end of
the file already had MemoryUrlUpdate, specific httpx.RequestError
handling, probe caching with FIFO eviction, and save_config_locked.

Remove the stale duplicate; the canonical version is the one already
present at the end of settings.py.

Fixes CodeRabbit findings: specific exception catch (httpx.RequestError
instead of Exception) and request payload validation (Pydantic model).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant