Skip to content

Promote dev to master: update-check ping + notification dedupe (#778)#813

Merged
jaylfc merged 7 commits into
masterfrom
dev
Jun 12, 2026
Merged

Promote dev to master: update-check ping + notification dedupe (#778)#813
jaylfc merged 7 commits into
masterfrom
dev

Conversation

@jaylfc

@jaylfc jaylfc commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Carries #811: the hourly update check now pings the taos.my version endpoint (the anonymous install count from #778) with TAOS_NO_UPDATE_PING and a Settings opt-out, degrading silently when the endpoint is unreachable. The git-based update check remains authoritative, so updates work with the website offline. Also regression-tests the existing notification dedupe.

Summary by CodeRabbit

  • New Features

    • Added copy-to-clipboard buttons for code blocks and messages in the desktop UI
    • Added support for fenced code block rendering in messages
    • Added anonymous daily install count ping (opt-out via settings or TAOS_NO_UPDATE_PING=1)
  • Bug Fixes

    • Improved server self-healing when LiteLLM proxy is unavailable
  • Documentation

    • Restructured and expanded agent manual with comprehensive reference sections including identity rules, facts table, app descriptions, and troubleshooting guides

jaylfc added 2 commits June 12, 2026 15:00
…, dedupe update notifications (#778) (#811)

Add a per-cycle version-check ping to the hourly auto-update loop.
The request (GET /api/v1/version-check?v=...&platform=...) lets the
server count a daily-salted aggregate of active installs; nothing is
stored per caller. The response's latest_version is logged at DEBUG
alongside the existing git-based update check, which remains the
authoritative signal.

Two opt-out layers:
- TAOS_NO_UPDATE_PING=1 env var (operator/system level)
- update_ping_enabled pref in the auto-update namespace (Settings UI)

All network failures (DNS, timeout, bad status, etc.) degrade silently
to debug logging and never surface as user-visible errors or block the
git check. The endpoint URL defaults to https://taos.my/api/v1/version-check
and is overridable via TAOS_UPDATE_CHECK_URL.

Notification dedupe was already in place via last_notified_commit; this
commit verifies it works correctly and adds regression tests.

Version source: tinyagentos.__version__ (set to "1.0.0-beta" in
tinyagentos/__init__.py, matching pyproject.toml).

Adds 12 new tests in tests/test_auto_update_ping.py (20 total across
the three auto_update test files, all green).
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jaylfc, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 17 minutes and 27 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d0a07137-7d80-4b59-b021-1b59031d9cc9

📥 Commits

Reviewing files that changed from the base of the PR and between 9789800 and 1291491.

📒 Files selected for processing (28)
  • CONTRIBUTING.md
  • README.md
  • desktop/src/apps/AgentMessagesPanel.tsx
  • desktop/src/apps/AgentsApp.tsx
  • desktop/src/apps/MessagesApp.tsx
  • desktop/src/apps/chat/MessageOverflowMenu.tsx
  • desktop/src/components/CodeBlock.tsx
  • desktop/src/components/TaosAssistantPanel.tsx
  • docs/STATUS.md
  • docs/agent-manual/00-identity.md
  • docs/agent-manual/01-rules.md
  • docs/agent-manual/02-what-is-taos.md
  • docs/agent-manual/03-facts.md
  • docs/agent-manual/04-apps.md
  • docs/agent-manual/05-chat.md
  • docs/agent-manual/06-updates-privacy.md
  • docs/agent-manual/07-after-update.md
  • docs/agent-manual/08-answer-templates.md
  • docs/agent-manual/index.md
  • docs/getting-started.md
  • docs/taos-agent-manual.md
  • scripts/build-agent-manual.py
  • tests/test_agent_manual_compiled.py
  • tests/test_auto_update_ping.py
  • tests/test_taos_agent_chat.py
  • tinyagentos/auto_update.py
  • tinyagentos/routes/taos_agent.py
  • tinyagentos/taos_agent_runtime.py
📝 Walkthrough

Walkthrough

This PR consolidates four related delivery areas: a compiled agent manual system with build automation, anonymous install-count update telemetry with user opt-out, desktop message copy-to-clipboard functionality, and agent runtime self-healing when the LLM proxy recovers after degraded startup.

Changes

Integrated Feature Release

Layer / File(s) Summary
Agent Manual Source Structure and Compilation System
docs/agent-manual/00-identity.md through 08-answer-templates.md, docs/agent-manual/index.md, scripts/build-agent-manual.py, tests/test_agent_manual_compiled.py, docs/taos-agent-manual.md, CONTRIBUTING.md
New templated source markdown files define agent identity, rules, facts, apps, chat behavior, update/privacy guidance, post-update troubleshooting, and answer templates. Deterministic Python build script discovers, cleans, and concatenates sources into taos-agent-manual.md with whitespace normalization and single trailing newline; test suite validates byte-for-byte output matching, enforces character limits, and checks for required content substrings. CONTRIBUTING.md documents the build workflow for contributors.
Anonymous Install-Count Update Ping with Privacy Opt-Out
tinyagentos/auto_update.py, tests/test_auto_update_ping.py, README.md, docs/getting-started.md, docs/STATUS.md
New send_version_ping() function sends hourly anonymous install-count query (version, platform, stable per-install ID from .install_id file) to https://taos.my/api/v1/version-check. Opt-out via TAOS_NO_UPDATE_PING=1 environment variable or update_ping_enabled=False user preference; both gates control execution in AutoUpdateService._run_once(). Comprehensive async tests validate query parameters, install ID persistence across calls, network error resilience, opt-out behavior, and notification deduplication. README and docs describe the ping, clarify that no PII is collected, and document the disable mechanism.
Desktop Message Copy-to-Clipboard and Text Selection
desktop/src/components/CodeBlock.tsx, desktop/src/apps/AgentMessagesPanel.tsx, desktop/src/apps/MessagesApp.tsx, desktop/src/apps/chat/MessageOverflowMenu.tsx, desktop/src/components/TaosAssistantPanel.tsx, desktop/src/apps/AgentsApp.tsx
New CodeBlock component renders code with overlay copy button, toggles transient "Copied" state on success, and silently degrades on clipboard errors. AgentMessagesPanel introduces PreBlock helper for JSON pretty-printing with copy controls on tool calls/results/reasoning. MessagesApp parses triple-backtick fences in content, renders fenced blocks via CodeBlock, applies inline markdown to non-fenced segments, and adds per-message "Copy text" overflow action. TaosAssistantPanel similarly parses bubble content for code blocks and shows copy UI on non-streaming messages. UI-wide class updates remove select-none from detail panel wrappers while adding select-text to inner content areas; MessageOverflowMenu accepts optional onCopyText callback.
Agent Server Self-Healing and Chat Streaming Empty-Reply Fix
tinyagentos/taos_agent_runtime.py, tinyagentos/routes/taos_agent.py, tests/test_taos_agent_chat.py
ensure_taos_opencode_server tracks taos_opencode_born_degraded state when LiteLLM proxy is unavailable at startup; on subsequent calls, if the proxy is now running, the degraded server is stopped and rebuilt transparently so model/key scoping applies correctly. Chat streaming generator now tracks content_frame_yielded flag and emits a fallback error frame if the adapter produces no content before the terminal done marker. Tests verify degraded-birth detection, self-heal recovery cycle, and proper error frame emission for empty vs. normal streams.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

The PR spans four distinct subsystems (documentation automation, backend telemetry, desktop UI, and runtime resilience) with moderate-to-high density logic in the auto-update ping implementation (persistent ID generation, opt-out gating, error resilience) and agent server self-healing state machine. Desktop UI changes follow consistent copy-to-clipboard patterns across multiple components. The 60-range scope and heterogeneous file spread across docs, scripts, tests, desktop, and backend require careful cross-layer understanding, though most individual changes follow clear patterns.

Possibly related issues

Possibly related PRs

  • jaylfc/taOS#817: Overlapping persistent install-id implementation (tinyagentos/auto_update.py .install_id generation and send_version_ping(..., data_dir) handling) and corresponding test coverage.
  • jaylfc/taOS#816: Overlapping chat empty-reply error frame fix in tinyagentos/routes/taos_agent.py and agent server degraded-birth/self-heal logic in tinyagentos/taos_agent_runtime.py.
  • jaylfc/taOS#812: Overlapping desktop copy-to-clipboard and text selection UI changes across AgentMessagesPanel.tsx, AgentsApp.tsx, MessagesApp.tsx, MessageOverflowMenu.tsx, CodeBlock.tsx, and TaosAssistantPanel.tsx.

Poem

🐰 A rabbit scripts and schemas bound,
To build and ping and copy—round and round!
Self-healing servers rise from degraded sleep,
While agent secrets, safe and deep, we keep.
Opt-out or stay—the choice is thee,
Now manual-made, and forever free!

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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 and usage tips.

@github-actions

Copy link
Copy Markdown

👋 Thanks for the PR! This one targets master, which is our
stable branch (it's what live installs track). Please retarget it to
dev — click Edit next to the PR title and change the base
branch dropdown from master to dev. Your commits and any review
carry over, nothing is lost.

See CONTRIBUTING.md for the branch model.

logger.debug(
"version-check ping: status=%s url=%s", resp.status_code, url
)
if 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.

WARNING: Non-200 responses are not read or closed before returning.

send_version_ping reuses the shared http_client when available. If the version-check endpoint returns a non-200 response, the response body is never read and the response is not explicitly closed, which can hold connection-pool resources until garbage collection. Read or close the response for all statuses so failures still release the connection cleanly.


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

Comment thread README.md
- **Agent Logs.** Real-time log viewer with auto-refresh
- **Backup & Restore.** Downloadable config backup, one-click restore, scheduled auto-backup (daily/weekly)
- **System Updates.** Pull latest from GitHub via Settings page
- **System Updates.** Pull latest from GitHub via Settings page. taOS periodically checks for updates and reports an anonymous install count (a daily aggregate estimate, no identifiers); disable with `TAOS_NO_UPDATE_PING=1` or in Settings.

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: Documentation claims a Settings UI opt-out that this PR does not add.

The backend now checks update_ping_enabled, but the diff does not update desktop/src/apps/SettingsApp/UpdatesPanel.tsx or /api/settings/update-status to expose or persist that setting. Users will not have the documented Settings control unless this PR includes additional UI/API changes.


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

@kilo-code-bot

kilo-code-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 8 Issues Found | Recommendation: Address before merge

Overview

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

CRITICAL

File Line Issue

WARNING

File Line Issue
docs/agent-manual/02-what-is-taos.md 7 Product description says nothing leaves the user's network unless they connect a cloud provider, contradicting the default update ping to taos.my.
docs/agent-manual/06-updates-privacy.md 8 Update-ping privacy and Settings opt-out claims are inaccurate or unsupported: the code sends a persistent install id plus v and platform; no Settings UI/API control is added, and IP-address storage is not guaranteed by this repo.
docs/STATUS.md 11 Release sequencing dependency is not enforced: the note says #817 must land before #813 promotes, but this PR is #813 targeting master.
README.md 310 Documentation claims a Settings UI opt-out that this PR does not add; the backend checks update_ping_enabled, but the diff does not expose or persist that setting in the Settings UI/API.
tinyagentos/auto_update.py 96 Install id is accepted from any existing file contents; _install_id returns raw stripped contents from <data_dir>/.install_id without validating that it is the generated UUID/hex string, which could leak local data or break the counter.
tinyagentos/auto_update.py 130 Non-200 responses are not read or closed before returning, which can hold connection-pool resources when using the shared http_client.
tinyagentos/taos_agent_runtime.py 116 Key-scope re-scope failure is treated as a rebuild trigger rather than a hard runtime degradation or fallback; update_agent_key() can return False and the stored key is still used.
tinyagentos/routes/taos_agent.py 482 Adapter errors produce a second generic error frame; error frames are not counted as output, so a specific adapter error is followed by the fallback "backend returned no output" error before done.
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
PR #813 base branch Existing GitHub Actions comment asks to retarget this PR from master to dev; this review did not validate that process requirement.
docs/STATUS.md 26 Public status includes a local token-file path and real-token testing details; this line is unchanged/context in the PR diff, so it is called out here instead of as an inline comment.
Files Reviewed (9 files)
  • tests/test_auto_update_ping.py - 0 issues
  • tests/test_taos_agent_chat.py - 0 issues
  • tinyagentos/auto_update.py - 2 issues
  • tinyagentos/routes/taos_agent.py - 1 issue
  • tinyagentos/taos_agent_runtime.py - 1 issue
  • README.md - 1 issue
  • docs/agent-manual/02-what-is-taos.md - 1 issue
  • docs/agent-manual/06-updates-privacy.md - 1 issue
  • docs/STATUS.md - 1 issue

Fix these issues in Kilo Cloud


Reviewed by nex-n2-pro:free · 931,526 tokens

jaylfc added 2 commits June 12, 2026 15:54
* fix(desktop): agent text is selectable and copyable on every chat surface (#801)

- AgentsApp: remove select-none from root detail containers; add select-none
  to back-header/toolbar only; add select-text to content regions so
  AgentDetailPanel and AgentMessagesPanel output is always selectable
- AgentMessagesPanel: add select-text to message text and reasoning blocks;
  replace raw <pre> blocks for tool calls/results with a PreBlock helper
  that has a hover-reveal copy button (keyboard accessible, ARIA-labelled)
- TaosAssistantPanel/TaosAssistantWindow: add select-text to MessageBubble;
  add per-message copy button (hover-reveal, ARIA-labelled, 1.5s feedback);
  render triple-backtick fenced code via shared CodeBlock component
- MessagesApp renderContent: split on fenced code blocks first, render each
  via CodeBlock; inline markdown applied to non-code segments only
- MessageOverflowMenu: add onCopyText prop and "Copy text" menu item
  (copies raw message content; available for all messages unconditionally)
- CodeBlock: new shared component (no new deps) - styled mono block with
  hover-reveal copy button, 1.5s check-mark feedback, keyboard accessible

* fix(desktop): segment-prefixed render keys cannot collide; Copy text renders only when a handler is wired

## What taOS is (for your answers)

taOS is a self-hosted operating system for AI agents. It runs on the user's own hardware (a single-board computer, a PC, a Mac) and serves a full desktop in the browser. Agents run in isolated containers, share chat channels with the user, and keep long-term memory. Nothing leaves the user's network unless they connect a cloud provider. The web desktop is at port 6969 on the host.

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: Product description contradicts the update ping.

This manual says nothing leaves the user's network unless they connect a cloud provider, but the update-ping flow sends data to taos.my by default. Agents using this manual could give users an incorrect privacy answer.

Suggested change
taOS is a self-hosted operating system for AI agents. It runs on the user's own hardware (a single-board computer, a PC, a Mac) and serves a full desktop in the browser. Agents run in isolated containers, share chat channels with the user, and keep long-term memory. Nothing leaves the user's network unless they connect a cloud provider. The web desktop is at port 6969 on the host.
taOS is a self-hosted operating system for AI agents. It runs on the user's own hardware (a single-board computer, a PC, a Mac) and serves a full desktop in the browser. Agents run in isolated containers, share chat channels with the user, and keep long-term memory. Only cloud model calls and the optional anonymous update ping leave the user's network. The web desktop is at port 6969 on the host.

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

## Updates (and the privacy question)

- taOS checks for updates about once an hour and shows a notification when one is ready. Install it via Settings then Updates then Install Update.
- The update check also reports an anonymous install count to taos.my: a random ID, the version, and the platform. No names, no emails, no IP addresses are stored. Turn it off in Settings or with `TAOS_NO_UPDATE_PING=1`. Updates keep working either way.

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: Update-ping privacy and Settings opt-out claims are inaccurate or unsupported.

The code sends only v and platform; no random ID is generated or sent, and this PR does not add a Settings UI/API control for update_ping_enabled. The line also claims no IP addresses are stored, which this repository cannot guarantee for the taos.my endpoint unless server-side logging is explicitly disabled. Qualify or remove these claims.

Suggested change
- The update check also reports an anonymous install count to taos.my: a random ID, the version, and the platform. No names, no emails, no IP addresses are stored. Turn it off in Settings or with `TAOS_NO_UPDATE_PING=1`. Updates keep working either way.
- The update check also reports an anonymous install count to taos.my: the version and platform. No names or emails are sent. Turn it off with `TAOS_NO_UPDATE_PING=1`; add a Settings toggle before documenting a Settings opt-out. Updates keep working either way.

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

Comment thread docs/STATUS.md

**Last updated:** 2026-06-12 ~14:30 BST, freshness sweep by @taOS (Orange Pi session). docs/AGENT_HANDOFF.md committed (was local-only). STATUS.md footer tips fixed. 5h window ~8%, resets 13:20 UTC; resume pair armed (14:23/14:42 BST).
**Last updated:** 2026-06-12 ~16:30 BST, by @taOS (Mac session). PR TRAIN IN FLIGHT (sequencing matters):
- #817 (persistent install id in the update ping) MUST land on dev BEFORE #813 promotes, else the taos.my counter counts nothing. #813 head=dev so merging #817 folds in automatically; then #813 promotes the install counter to master.

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: PR promotion sequencing dependency is not enforced.

This status note says #817 must land on dev before #813 promotes, but this PR is #813 targeting master. If merged before #817, the promoted update ping may ship without the persistent install id the counter depends on. Treat #817 as a hard prerequisite or hold this promotion until the dependency is satisfied.


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

…teLLM was ready; surface empty streams as errors (#816)
"taos_agent_runtime: re-scoping the taOS agent key returned False "
"(key scope may be stale)"
)
born_degraded = True

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: Key-scope re-scope failure is treated as a rebuild trigger

update_agent_key() can return False when the key scope could not be updated. This still starts opencode with the stored key, so later model calls may fail with authorization/model errors instead of degrading early. Treat re-scope failure as a hard runtime degradation or fall back to the master key.


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

exc = drive_task.exception()
if exc is not None:
logger.error("taos-agent: drive task raised %r", exc)
if not content_frame_yielded:

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: Adapter errors produce a second generic error frame

Error frames are not counted as output, so a specific adapter error is followed by this fallback "backend returned no output" error before done. Track any non-_DONE frame as output, or use a separate error_frame_yielded flag, so clients receive the specific error only.


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

jaylfc added 2 commits June 12, 2026 16:24
…818)

The taOS agent manual was a single flat file. This commit introduces a
library-plus-compile design:

- docs/agent-manual/ holds nine focused source files (identity, rules,
  product description, facts, apps, chat, updates/privacy, post-update
  troubleshooting, answer templates) and an index that defines compile order.
- scripts/build-agent-manual.py concatenates them into the single flat
  docs/taos-agent-manual.md that the runtime already loads unchanged.
- tests/test_agent_manual_compiled.py fails CI if a contributor edits the
  source library but forgets to rebuild (builds into a temp file and diffs).
- CONTRIBUTING.md gets a one-liner pointing contributors to the source files.

No change to taos_agent.py or any runtime path. The compiled file stays
the injection target so weak models always have the full prompt in context.
@jaylfc jaylfc merged commit 99cf786 into master Jun 12, 2026
1 check was pending
@github-project-automation github-project-automation Bot moved this from Todo to Done in TinyAgentOS Roadmap Jun 12, 2026
if path.exists():
existing = path.read_text(encoding="utf-8").strip()
if existing:
return existing

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: Persistent install id is sent without validation

_install_id returns any non-empty contents of <data_dir>/.install_id and immediately includes it in the external update ping. Because the data directory is user-writable, a malformed/truncated id can corrupt the server-side count, and PII or an overly long value could be exfiltrated if written there. Validate the generated UUID format/length before reusing an existing file, and regenerate when invalid.


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

)
born_degraded = True
except Exception:
logger.debug("taos_agent_runtime: re-scoping stored key failed", exc_info=True)

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: Re-scope exceptions leave stale key without degraded flag

The update_agent_key() exception path uses the stored key unchanged, but unlike the False return path it leaves born_degraded false. The next call will reuse the cached server instead of rebuilding with a fresh scoped key, so stale model permissions can persist silently. Mark degradation or fall back/remint on exception as well.


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

if path.exists():
existing = path.read_text(encoding="utf-8").strip()
if existing:
return existing

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: Install id is accepted from any existing file contents

_install_id documents a random UUID, but if <data_dir>/.install_id already exists it returns the raw stripped contents without validating format. A corrupted or attacker-written file could be sent as the id query parameter to the update-check endpoint, leaking local data and breaking the install counter. Validate that the persisted value is a UUID/hex string before sending it.

Suggested change
return existing
if existing and len(existing) == 32 and set(existing) <= set("0123456789abcdef"):

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant