Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
7fafe5f
fix(store): rkllama model install when backend runs but is unregister…
jaylfc Jun 13, 2026
e8810f4
docs: rename brand to taOS + brand contact to info@taos.my (#847)
jaylfc Jun 13, 2026
9e1462a
feat(theme): add the Light theme - Apple-grade light counterpart to D…
jaylfc Jun 13, 2026
6502b93
chore(deps): bump esbuild to 0.28.1 (fixes RCE advisory), raise build…
jaylfc Jun 13, 2026
a711418
feat(agent): unify the taOS Agent chat composer (attach/screenshot in…
jaylfc Jun 13, 2026
51ae91d
fix(update): reset desktop/package-lock.json before the ff-only pull …
jaylfc Jun 13, 2026
3679e94
feat(agents): redesign the Agents app to Apple-grade cards (#851)
jaylfc Jun 13, 2026
cb0ee72
feat(chat): Slack-polish the message rows (avatar gutter, grouped fol…
jaylfc Jun 13, 2026
9624892
feat(agents): top-bar agent kill switch (#132) (#857)
jaylfc Jun 13, 2026
86c5636
docs(status): freshness sweep 2026-06-13 -- sync branch tips, open PR…
jaylfc Jun 13, 2026
5225fdf
docs(getting-started): rename TinyAgentOS to taOS throughout
jaylfc Jun 13, 2026
244f183
docs(contributing): rename TinyAgentOS to taOS in title and intro
jaylfc Jun 13, 2026
09a497a
docs(readme): remove parenthetical TinyAgentOS from product description
jaylfc Jun 13, 2026
d9aab97
docs(status): correct -- #857 already merged, #859 new, dev=09a497a2 …
jaylfc Jun 13, 2026
d4147c4
docs(status): freshness sweep -- add PR #860, correct dev tip to d9aa…
jaylfc Jun 13, 2026
f56efcb
docs(status): restore correct dev content, add PR #860, fix dev tip t…
jaylfc Jun 13, 2026
4038830
docs(agent-qmd-serve-setup): rename TinyAgentOS to taOS
jaylfc Jun 13, 2026
9c7c91f
docs(mirror-policy): rename TinyAgentOS to taOS
jaylfc Jun 13, 2026
2464b9c
docs(status): freshness sweep complete -- dev=9c7c91fe (18 ahead), do…
jaylfc Jun 13, 2026
7b6eae8
fix(agents): kill switch surfaces failures (Gitar review follow-up on…
jaylfc Jun 13, 2026
d09b100
feat(theme): two themes only - taOS Dark and taOS Light (remove Matri…
jaylfc Jun 13, 2026
794d35f
fix(agents): model chip on every agent + aligned row columns (#861)
jaylfc Jun 13, 2026
44fcd16
feat(github): Device-Flow connect for GitHub identities in Secrets (#…
jaylfc Jun 13, 2026
8c272cb
docs(status): wind-down at 92% 5h usage; wake queue = macOS-dark pale…
jaylfc Jun 13, 2026
7f14fc8
fix(agents): remove the 'System agent' label + even out card spacing …
jaylfc Jun 13, 2026
1c0aa90
docs(status): resumed post-reset; #863 merged, #867+#868 open, queue …
jaylfc Jun 13, 2026
9ccfd7d
fix(theme): repaint backdrop-filter layers on theme switch (Safari bl…
jaylfc Jun 13, 2026
865f278
feat(theme): macOS-dark graphite palette + live neural wallpaper (#86…
jaylfc Jun 13, 2026
421663c
docs(status): #867 + #868 merged to dev; promo/store program active
jaylfc Jun 13, 2026
5756489
fix(theme): neutralise old-indigo popover + widget backgrounds to gra…
jaylfc Jun 13, 2026
4f2259a
feat(wallpaper): graphite-regraded neural wallpaper as default (scree…
jaylfc Jun 13, 2026
0c367e2
docs(status): wind-down at 5h 93%; real-desktop next then live-wallpa…
jaylfc Jun 13, 2026
82a9a9c
docs(status): real-desktop #873 + store #871 fixes done (autonomous);…
jaylfc Jun 14, 2026
15eaac0
feat(store): App Store redesign (hero, popular, community, real logos…
jaylfc Jun 14, 2026
a3671f0
docs(status): #871 store merged to dev; #872/#873/#874 baking; slider…
jaylfc Jun 14, 2026
94529f4
docs(readme): taOSmd section -- add arctic-embed-s low-tier default +…
jaylfc Jun 14, 2026
34b96bb
feat(desktop): real desktop (FS-backed icons, inline New Folder/renam…
jaylfc Jun 14, 2026
99ab354
feat(desktop): programmatic desktop control API (window.taosDesktop) …
jaylfc Jun 14, 2026
dc20fd2
docs(status): #874 merged, #872 rebased+baking, storybook offline-dem…
jaylfc Jun 14, 2026
4ecc796
feat(wallpaper): live particle-network wallpaper (tsParticles, select…
jaylfc Jun 14, 2026
b0c03f7
docs(status): #872/#873/#874 all merged; esbuild alert stale; fedora …
jaylfc Jun 14, 2026
15656d8
docs(status): agent-OS-control spec written; offline drive+vision res…
jaylfc Jun 14, 2026
eeb413b
docs(status): live-state capture — Pi deploy loop authorized, #877 tr…
jaylfc Jun 14, 2026
fcb75f4
feat(desktop): controller→browser command channel for agent OS contro…
jaylfc Jun 14, 2026
0152353
docs(status): morning must-do (offline eval on box-free), 3 PRs bakin…
jaylfc Jun 14, 2026
5f2a472
feat(agent): open_app + arrange_windows tools — agent OS control (pha…
jaylfc Jun 14, 2026
4f0f195
style(theme): purge purple from the dark theme (#879)
jaylfc Jun 14, 2026
25efe39
docs(status): agent OS control framework + purple purge merged & depl…
jaylfc Jun 14, 2026
4947cb1
feat(messages): polish the mobile channel list (avatars, theme tokens…
jaylfc Jun 14, 2026
51df5c2
fix(chat-pwa): apply the persisted theme on boot so it respects light…
jaylfc Jun 14, 2026
f37b5ac
docs(status): #880 mobile chat + #881 pwa-theme merged & deployed; al…
jaylfc Jun 14, 2026
1754794
docs(status): agent OS control framework feature-complete (Phase 1-3)…
jaylfc Jun 14, 2026
1e60737
feat(agent): project data tools (create_project, add_task, canvas_add…
jaylfc Jun 14, 2026
805b0f0
docs(status): agent OS control framework merged+deployed+verified on …
jaylfc Jun 14, 2026
2a011d6
docs(status): offline-agent eval running on Fedora (full roster tool-…
jaylfc Jun 14, 2026
67dceb6
docs(status): offline-agent eval DONE -- all local models run the ful…
jaylfc Jun 14, 2026
ee4a0a5
docs(status): freshness sweep -- fix stale branch tip and open PRs
jaylfc Jun 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,4 @@ docs/AGENT_HANDOFF.md
docs/audit/
.understand-anything/
docs/agent-jobs/
.design/
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ representative at an online or offline event.

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
jaylfc25@gmail.com.
info@taos.my.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing to TinyAgentOS
# Contributing to taOS

Welcome — and thanks for your interest in contributing. TinyAgentOS is a self-hosted AI agent platform for low-power hardware. Before diving in, please read the [README](README.md) for a project overview.
Welcome — and thanks for your interest in contributing. taOS is a self-hosted AI agent platform for low-power hardware. Before diving in, please read the [README](README.md) for a project overview.

> **Note:** The project is in early development. APIs and interfaces may change. That is fine — contributions of all sizes are welcome.

Expand Down Expand Up @@ -233,4 +233,4 @@ Routes are registered in `app.py`. Route modules access stores via `request.app.

## Contact

Questions not suited for a GitHub issue? Email jaylfc25@gmail.com.
Questions not suited for a GitHub issue? Email info@taos.my.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ free of charge and is not a Commercial Purpose, provided the Software (and
anything built on it) is not offered, sold, hosted, or otherwise made available
to any third party.

To obtain a commercial license, contact JAN LABS LTD at jaylfc25@gmail.com.
To obtain a commercial license, contact JAN LABS LTD at info@taos.my.

4. Trademarks

Expand Down
42 changes: 24 additions & 18 deletions README.md

Large diffs are not rendered by default.

724 changes: 610 additions & 114 deletions desktop/package-lock.json

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tldraw/tldraw": "^4.5.10",
"@tsparticles/engine": "^3.9.1",
"@tsparticles/react": "^3.0.0",
"@tsparticles/slim": "^3.9.1",
"@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
Expand Down Expand Up @@ -68,6 +71,7 @@
"vitest": "^4.1.0"
},
"overrides": {
"dompurify": "^3.4.0"
"dompurify": "^3.4.0",
"esbuild": "^0.28.1"
}
}
21 changes: 19 additions & 2 deletions desktop/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useState, useCallback, useEffect } from "react";
import { TopBar } from "@/components/TopBar";
import { Desktop } from "@/components/Desktop";
import { Dock } from "@/components/Dock";
import { ParticlesWallpaper } from "@/components/ParticlesWallpaper";
import { WallpaperTextOverlay } from "@/components/WallpaperTextOverlay";
import { Launchpad } from "@/components/Launchpad";
import { SearchPalette } from "@/components/SearchPalette";
import { ShortcutProvider, useShortcut } from "@/hooks/use-shortcut-registry";
Expand Down Expand Up @@ -125,6 +127,19 @@ export function App() {
const wallpaperImage = useThemeStore((s) => s.wallpaperImage);
const wallpaperMobileImage = useThemeStore((s) => s.wallpaperMobileImage);
const wallpaperFallback = useThemeStore((s) => s.wallpaperFallback);
const wallpaperLightImage = useThemeStore((s) => s.wallpaperLightImage);
const wallpaperLightMobileImage = useThemeStore((s) => s.wallpaperLightMobileImage);
const wallpaperLightFallback = useThemeStore((s) => s.wallpaperLightFallback);
const scheme = useThemeStore((s) => s.scheme);
const wallpaperKind = useThemeStore((s) => s.wallpaperKind);
const wallpaperComponent = useThemeStore((s) => s.wallpaperComponent);
const wallpaperOverlayText = useThemeStore((s) => s.wallpaperOverlayText);
const showOverlayText = useThemeStore((s) => s.showOverlayText);
const isAnimatedWallpaper = wallpaperKind === "animated";
const useLightWallpaper = scheme === "light" && !!wallpaperLightImage;
const effWallpaperImage = useLightWallpaper ? wallpaperLightImage : wallpaperImage;
const effWallpaperMobile = useLightWallpaper ? wallpaperLightMobileImage : wallpaperMobileImage;
const effWallpaperFallback = useLightWallpaper ? wallpaperLightFallback : wallpaperFallback;
const windows = useProcessStore((s) => s.windows);
const openWindow = useProcessStore((s) => s.openWindow);
const closeWindow = useProcessStore((s) => s.closeWindow);
Expand Down Expand Up @@ -288,11 +303,13 @@ export function App() {
<ShortcutProvider>
<SystemShortcuts toggleSearch={toggleSearch} toggleLaunchpad={toggleLaunchpad} toggleAssistant={toggleAssistant} />
<LoginGate>
<div className={`taos-wallpaper h-screen w-screen flex flex-col text-shell-text${isBrowserMobile ? " taos-browser" : ""}`} style={{ backgroundColor: wallpaperFallback, ["--wallpaper-desktop" as never]: wallpaperImage, ["--wallpaper-mobile" as never]: wallpaperMobileImage }}>
<div className={`taos-wallpaper relative h-screen w-screen flex flex-col text-shell-text${isBrowserMobile ? " taos-browser" : ""}`} style={{ backgroundColor: effWallpaperFallback, ["--wallpaper-desktop" as never]: isAnimatedWallpaper ? "none" : effWallpaperImage, ["--wallpaper-mobile" as never]: isAnimatedWallpaper ? "none" : effWallpaperMobile }}>
{isAnimatedWallpaper && wallpaperComponent === "particles" && <ParticlesWallpaper />}
{showOverlayText && wallpaperOverlayText && <WallpaperTextOverlay text={wallpaperOverlayText} />}
<EffectsLayer />
{/* Install banner — shown in browser mode, hidden in PWA */}
{isBrowserMobile && <InstallPromptBanner />}
<div className={`flex-1 flex flex-col overflow-hidden transition-all duration-500 ${launched ? "opacity-100 scale-100" : "opacity-0 scale-95"}`}>
<div className={`relative z-[1] flex-1 flex flex-col overflow-hidden transition-all duration-500 ${launched ? "opacity-100 scale-100" : "opacity-0 scale-95"}`}>
<MobileTopBar
onHome={handleMobileHome}
onSearch={() => { setCardSwitcherOpen(false); setSearchOpen((v) => !v); }}
Expand Down
16 changes: 8 additions & 8 deletions desktop/src/apps/ActivityApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
{capabilities.map((c) => (
<span
key={`${w.name}-c-${c}`}
className="text-[9px] px-1.5 py-0.5 rounded-full bg-violet-500/15 text-violet-200 font-medium"
className="text-[9px] px-1.5 py-0.5 rounded-full bg-cyan-500/15 text-cyan-200 font-medium"
aria-label={`Current capability: ${c}`}
>
{c}
Expand Down Expand Up @@ -699,7 +699,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
<CardContent className="p-0">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<Network size={14} className="text-indigo-400" />
<Network size={14} className="text-cyan-400" />
<h3 className="text-xs font-semibold text-shell-text">Network</h3>
</div>
</div>
Expand All @@ -726,7 +726,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
<CardContent className="p-0">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<Activity size={14} className="text-violet-400" />
<Activity size={14} className="text-cyan-400" />
<h3 className="text-xs font-semibold text-shell-text">Scheduler</h3>
</div>
<div className="flex items-center gap-3 text-[10px] text-shell-text-tertiary tabular-nums">
Expand All @@ -747,7 +747,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
const tierLabel = ["GPU", "NPU", "CPU", "CLUSTER"][r.tier] ?? "?";
const tierColor = [
"text-emerald-400 bg-emerald-500/10",
"text-violet-400 bg-violet-500/10",
"text-cyan-400 bg-cyan-500/10",
"text-sky-400 bg-sky-500/10",
"text-amber-400 bg-amber-500/10",
][r.tier] ?? "text-shell-text-tertiary bg-white/5";
Expand Down Expand Up @@ -791,7 +791,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
{r.capabilities.map((c) => (
<span
key={`ready-${c}`}
className="text-[9px] px-1.5 py-0.5 rounded-full bg-violet-500/20 text-violet-200 font-medium"
className="text-[9px] px-1.5 py-0.5 rounded-full bg-cyan-500/20 text-cyan-200 font-medium"
title="Ready now — backend is loaded"
>
{c}
Expand Down Expand Up @@ -841,7 +841,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
const tierLabels = ["GPU", "NPU", "CPU"];
const tierColors = [
"text-emerald-400 bg-emerald-500/10",
"text-violet-400 bg-violet-500/10",
"text-cyan-400 bg-cyan-500/10",
"text-sky-400 bg-sky-500/10",
];

Expand Down Expand Up @@ -877,7 +877,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
...(w.capabilities || []).map((c) => (
<span
key={`worker-ready-${c}`}
className="text-[9px] px-1.5 py-0.5 rounded-full bg-violet-500/20 text-violet-200 font-medium"
className="text-[9px] px-1.5 py-0.5 rounded-full bg-cyan-500/20 text-cyan-200 font-medium"
title="Ready now — backend is loaded"
>
{c}
Expand Down Expand Up @@ -907,7 +907,7 @@ export function ActivityApp({ windowId: _windowId }: { windowId: string }) {
t.status === "complete"
? "text-emerald-400"
: t.status === "running"
? "text-violet-400"
? "text-cyan-400"
: t.status === "error"
? "text-red-400"
: t.status === "rejected"
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/apps/AgentSkillsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const CATEGORY_COLORS: Record<string, string> = {
media: "bg-pink-500/20 text-pink-400",
browser: "bg-cyan-500/20 text-cyan-400",
data: "bg-emerald-500/20 text-emerald-400",
comms: "bg-indigo-500/20 text-indigo-400",
comms: "bg-cyan-500/20 text-cyan-400",
system: "bg-slate-500/20 text-slate-400",
};

Expand Down
83 changes: 51 additions & 32 deletions desktop/src/apps/AgentsApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,33 @@ const TAOS_AGENT_STUB: Agent = {
name: "taos-agent",
display_name: "taOS agent",
host: "localhost",
color: "#6366f1",
color: "#06b6d4",
emoji: "🤖",
status: "running",
vectors: 0,
framework: "opencode",
paused: false,
};

/** Placeholder card shown while the agent list is loading. Matches the
* AgentRow shape (identity tile + two-line stack + trailing metric) with a
* shimmer that respects prefers-reduced-motion (see tokens.css). */
function AgentRowSkeleton() {
return (
<div
className="flex items-center gap-3 px-4 py-3.5 rounded-xl border border-shell-border bg-shell-surface shadow-[var(--shadow-card)]"
aria-hidden="true"
>
<div className="taos-shimmer h-9 w-9 rounded-lg bg-shell-surface-active shrink-0" />
<div className="flex-1 min-w-0 space-y-2">
<div className="taos-shimmer h-3.5 w-40 max-w-[60%] rounded bg-shell-surface-active" />
<div className="taos-shimmer h-2.5 w-24 max-w-[40%] rounded bg-shell-surface-active" />
</div>
<div className="taos-shimmer h-3 w-16 rounded bg-shell-surface-active shrink-0" />
</div>
);
}

export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
const [agents, setAgents] = useState<Agent[]>([]);
const [archived, setArchived] = useState<ArchivedAgent[]>([]);
Expand All @@ -45,9 +64,9 @@ export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
const [diskStates, setDiskStates] = useState<Record<string, DiskState>>({});
const [quotaErrors, setQuotaErrors] = useState<Record<string, string>>({});
const [latestByFramework, setLatestByFramework] = useState<Record<string, LatestVersion>>({});
// Hydrate the taOS agent stub with live model info (display only the detail
// panel fetches its own config on open). We only use this to show the current
// model in the row's framework pill area; failures are silently ignored.
// Hydrate the taOS agent stub with live model info (display only; the detail
// panel fetches its own config on open). Shown as the model indicator line on
// the system agent's card; failures are silently ignored.
const [taosModel, setTaosModel] = useState<string | undefined>(undefined);
const isMobile = useIsMobile();
const openWindow = useProcessStore((s) => s.openWindow);
Expand All @@ -70,6 +89,7 @@ export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
status: String(a.status ?? "stopped") as Agent["status"],
vectors: Number(a.vectors ?? 0),
framework: a.framework ? String(a.framework) : undefined,
model: a.model ? String(a.model) : undefined,
paused: Boolean(a.paused),
on_worker_failure: (a.on_worker_failure as Agent["on_worker_failure"]) ?? "pause",
fallback_models: Array.isArray(a.fallback_models) ? (a.fallback_models as string[]) : [],
Expand Down Expand Up @@ -469,15 +489,16 @@ export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
{/* Content */}
<div className="flex-1 overflow-auto">
{loading ? (
<div className="flex items-center justify-center h-full text-shell-text-tertiary text-sm">
Loading agents...
<div className="p-4 space-y-2" aria-busy="true" aria-label="Loading agents">
{[0, 1, 2].map((i) => (
<AgentRowSkeleton key={i} />
))}
</div>
) : agents.length === 0 && archived.length === 0 ? (
<div className="flex flex-col h-full min-h-0">
<div className="p-4">
<p className="text-xs font-medium text-shell-text-tertiary uppercase tracking-wider mb-2">System agent</p>
<AgentRow
agent={{ ...TAOS_AGENT_STUB, display_name: taosModel ? `taOS agent — ${taosModel}` : "taOS agent" }}
agent={{ ...TAOS_AGENT_STUB, model: taosModel }}
diskState={null}
latestByFramework={latestByFramework}
onViewLogs={() => setTaosDetailOpen(true)}
Expand All @@ -488,31 +509,29 @@ export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
protected
/>
</div>
<div className="flex flex-col items-center justify-center flex-1 gap-4 text-shell-text-tertiary px-4 pb-8">
<div className="w-20 h-20 rounded-2xl flex items-center justify-center"
style={{ background: "linear-gradient(135deg, rgba(139,146,163,0.15), rgba(91,97,112,0.08))" }}
>
<Bot size={36} className="text-accent/50" />
<div className="flex flex-col items-center justify-center flex-1 gap-4 px-4 pb-8">
<div className="w-16 h-16 rounded-lg flex items-center justify-center bg-shell-surface border border-shell-border">
<Bot size={30} className="text-shell-text-tertiary" />
</div>
<div className="text-center">
<p className="text-base font-medium text-shell-text-secondary mb-1">No agents deployed yet</p>
<p className="text-xs text-shell-text-tertiary max-w-xs">Deploy your first AI agent to start automating tasks on your device.</p>
<p className="text-base font-medium text-shell-text mb-1">No agents deployed yet</p>
<p className="text-sm text-shell-text-secondary max-w-xs">Deploy your first AI agent to start automating tasks on your device.</p>
</div>
<Button
onClick={() => setWizardOpen(true)}
className="text-white shadow-lg hover:shadow-xl hover:-translate-y-0.5 hover:brightness-110 border-0 mt-1"
style={{ background: "linear-gradient(135deg, #8b92a3, #5b6170)" }}
aria-label="Deploy agent"
>
<Plus size={15} />
Deploy your first agent
Deploy Agent
</Button>
</div>
</div>
) : agents.length === 0 ? (
<div className="p-4">
<p className="text-xs font-medium text-shell-text-tertiary uppercase tracking-wider mb-2">System agent</p>
<AgentRow
agent={{ ...TAOS_AGENT_STUB, display_name: taosModel ? `taOS agent — ${taosModel}` : "taOS agent" }}
agent={{ ...TAOS_AGENT_STUB, model: taosModel }}
diskState={null}
latestByFramework={latestByFramework}
onViewLogs={() => setTaosDetailOpen(true)}
Expand All @@ -531,19 +550,19 @@ export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
</div>
) : (
<div className="p-4">
{/* System agent — always shown above the deployed agents list */}
<p className="text-xs font-medium text-shell-text-tertiary uppercase tracking-wider mb-2">System agent</p>
<AgentRow
agent={{ ...TAOS_AGENT_STUB, display_name: taosModel ? `taOS agent — ${taosModel}` : "taOS agent" }}
diskState={null}
latestByFramework={latestByFramework}
onViewLogs={() => setTaosDetailOpen(true)}
onViewSkills={() => setTaosDetailOpen(true)}
onViewMessages={() => setTaosDetailOpen(true)}
onDelete={() => {}}
onResume={() => {}}
protected
/>
<div className="mb-3">
<AgentRow
agent={{ ...TAOS_AGENT_STUB, model: taosModel }}
diskState={null}
latestByFramework={latestByFramework}
onViewLogs={() => setTaosDetailOpen(true)}
onViewSkills={() => setTaosDetailOpen(true)}
onViewMessages={() => setTaosDetailOpen(true)}
onDelete={() => {}}
onResume={() => {}}
protected
/>
</div>

{/* Disk quota notification cards */}
{agents
Expand Down Expand Up @@ -594,7 +613,7 @@ export function AgentsApp({ windowId: _windowId }: { windowId: string }) {
</div>
);
})}
<div className="space-y-2" role="list" aria-label="Agent list">
<div className="space-y-3" role="list" aria-label="Agent list">
{agents.map((agent) => (
<AgentRow
key={agent.name}
Expand Down
Loading
Loading