1555 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
e04337342f fix(desktop): drop the installed-skills locale keys the rollback restored
b64069a3 removed the installed-skills overview and its nine
market.installedSkills.* / market.section.installed keys from all five
locales. e9b53f68, its immediate child, reverted the locale files
wholesale -- and because the overview (8061b9b2) predates the shadcn
migration those keys were inside the range being restored, so they came
straight back.

The component that read them is gone, and nothing else references them:
`git grep -E "market\.installedSkills|market\.section\.installed"`
outside the locale files returns nothing. Every locale kept the same
key count, so a parity check has no way to notice.

Re-applies b64069a3's deletion, and adds a test that fails if the keys
reappear -- the previous deletion was undone by a mechanical revert, so
a guard is worth more here than the removal itself.
2026-07-25 22:02:10 +08:00
程序员阿江(Relakkes)
8678e49a4d fix(desktop): rebuild the preview-agent bundle after the UI rollback
`preview-agent.js` is a tracked build artifact, bundled from
desktop/src/preview-agent/ by build:preview-agent and shipped as a
packaged resource. The rollback (e9b53f68) deleted that source's
theme.ts and trimmed editBubble.ts, but never rebuilt the artifact --
it appears in neither revert's file list, so the committed blob was
last produced at ad597ffe.

The result is a bundle built from source that no longer exists: it
still carries all 12 --cc-haha-* custom properties the deleted theme.ts
defined, plus the shadcn-era brand hex, and lacks the literal styling
the current source emits. It is internally consistent so nothing
crashes -- the packaged app just renders styling that diverges from
what the repository says it should.

Rebuilt from the current source. Verified byte-stable across repeated
builds, so this does not reintroduce artifact drift.
2026-07-25 22:00:09 +08:00
程序员阿江(Relakkes)
e9b53f6848 revert(desktop): roll back the shadcn UI migration, keep backend hardening
The shadcn migration (ad597ffe) and its follow-up (5b4e224f) were
mega-commits: only ~16% of the insertions were UI work. Rolling either
one back wholesale also deletes ~3400 lines of unrelated server,
Electron, and store hardening -- and because each of those changes
shipped with its own tests, the suite stays green while the hardening
silently disappears.

This rolls back the UI layer only.

Reverted (back to c2774fc1):
- desktop/src/components, pages, features, theme, i18n
- components/ui/**, components.json, src/lib/utils.ts (cn helper)
- radix-ui, class-variance-authority, tailwind-merge deps
- src-tauri/src/lib.rs hardening: dead code, nothing compiles it
  (no @tauri-apps dep, no cargo invocation anywhere, and
  scripts/pr/release-workflow.test.ts asserts Tauri's absence)

Kept (identical to main):
- src/** -- WhatsApp authDir escape allowing arbitrary recursive
  directory removal, computer-use tier bypass granting every
  pre-authorized app full tier, plugin uninstall keepData inversion
  that deleted data when asked to keep it, plugin project-scope
  writing to the sidecar cwd, diagnostics share leaking provider
  config, memory API TOCTOU plus atomic writes
- desktop/electron/** -- PTY leak on renderer destruction, IPC
  boundary validation rejecting NaN and unbounded input
- desktop/src/stores/** -- request-id race guards
- desktop/src/api, lib/desktopHost -- kept in step with the stores

Follows main's b64069a3 in dropping the installed-skills overview.

Updated two memorySettings assertions to expect the optimistic-lock
fields the retained memory store sends.

check:desktop pass (lint clean, 225 files / 2519 passed / 1 skipped,
build ok). check:server pass (224 files / 2375 passed / 0 failed).
2026-07-25 21:05:02 +08:00
程序员阿江(Relakkes)
b64069a301 revert(desktop): drop the installed-skills overview from the market
The overview added in #1098 duplicated Settings -> Skills: same
useSkillStore, same fetchSkills/fetchSkillDetail, and it even reused the
settings.skills.* translation keys. Its only new logic collapsed the five
skill sources into a personal/system pair, while "is it installed?" was
already answered by InstallStateBadge on each market card. In exchange it
pushed the actual catalog below the fold behind a 93-row list.

Also reverts f82b596f, which existed solely to give that overview a
working detail view; with the entry point gone it was dead code.

Restores desktop/src/pages/Market.tsx and MarketHome to their pre-#1098
shape (verified: empty diff against f82b596f^ and 6b7e90ae^1), and drops
the nine market.installedSkills.* keys from all five locales.
2026-07-25 20:31:49 +08:00
程序员阿江(Relakkes)
4be4d3a4ca fix(skills): resolve a skill name to one file across every root
A skill name is a single slash command, but three code paths disagreed on
which file it pointed at once the same name existed in more than one root.

The CLI loader deduped by `${scopeKey}\0${name}`, so it only collapsed a
collision inside one scope. Across scopes both entries survived, and the
slash command menu has no dedup of its own -- typing `/` listed two identical
rows, and only the first was ever executable.

The desktop menu builds its list separately, in listSkillSlashCommands, where
a plain `byName.set()` made the last writer win. Its input runs user roots
before project roots, so the project copy took the name. The kernel resolves
the same call through findCommand, which takes the first match and therefore
picked the user copy. A user with `deploy` in both ~/.agents/skills and the
repository's .claude/skills read the project description in the menu and ran
the .agents body on click.

Both paths now share outranksClaimedSkill: `.claude` outranks `.agents` in
every scope, including across them, and any other pairing leaves the incumbent
in place so the existing root order still decides. This repository is the
Claude Code CLI, so a skill installed for us stays authoritative over one
another client dropped into the shared .agents space. Plugin and legacy
/commands/ entries carry no flavor and neither displace nor get displaced on
flavor alone -- which also settles a second disagreement, where the desktop
list let a plugin skill take a name the CLI gave to the user's own.

The --bare branch loads only --add-dir roots and had its own scoped helper;
it now runs the same rule, so two added directories holding one name collapse
like everywhere else.

Behavior change: a name repeated across scopes used to produce two entries,
and a regression test pinned that. Two identical rows give the reader no way
to tell them apart while only one can run, so the pair now collapses; the
test is replaced by the cross-scope cases that assert the surviving copy.

Verified end to end in a sandbox HOME plus project: for same-scope,
cross-flavor, and cross-scope-same-flavor collisions, the desktop menu, the
CLI menu, and findCommand all land on one file and agree on which.
2026-07-25 17:25:07 +08:00
程序员阿江(Relakkes)
f5591b5226 Merge remote-tracking branch 'cchaha/main' 2026-07-25 16:25:03 +08:00
程序员阿江(Relakkes)
f82b596fbb fix(desktop): open installed skill details from the market overview
Clicking an installed skill in the Skills Market only wrote
skillStore.selectedSkill, but the page renders details exclusively
off marketStore.selectedId, so the click had no visible effect.
Render the shared SkillDetail when an installed selection exists,
mirroring the Settings -> Skills wiring: hidden (not unmounted)
market home to preserve search/collapse state, and the same
active-project context guard that drops stale details.

Follow-up to #1098.
2026-07-25 16:23:52 +08:00
程序员阿江(Relakkes)
441979aa2d test(desktop): make the dev launcher tests install-independent
The resolveElectronExecutable case asserted against the real
node_modules/electron/dist, which bun never downloads without the
electron postinstall, so it failed on macOS/Linux dev machines.
Point the tests at a self-built fixture desktop root instead and
extend coverage to the darwin/linux candidates and the missing-
executable error path.

Follow-up to #1096.
2026-07-25 16:23:39 +08:00
程序员阿江(Relakkes)
6b7e90aec7 Merge pull request #1098 from RaspberryLee/feat/installed-skills-overview
feat(desktop): show installed skills in the Skills Market
2026-07-25 16:11:43 +08:00
程序员阿江(Relakkes)
cfd13f9883 Merge pull request #1096 from RaspberryLee/fix/windows-electron-dev-launcher
fix(desktop): make the Electron dev launcher work on Windows
2026-07-25 16:11:43 +08:00
程序员阿江-Relakkes
4dfeb26c25
Merge pull request #1098 from RaspberryLee/feat/installed-skills-overview
feat(desktop): show installed skills in the Skills Market
2026-07-25 16:09:13 +08:00
程序员阿江-Relakkes
c4334c3d12
Merge pull request #1096 from RaspberryLee/fix/windows-electron-dev-launcher
fix(desktop): make the Electron dev launcher work on Windows
2026-07-25 16:08:52 +08:00
程序员阿江(Relakkes)
2b89d4a678 fix(skills): correct the .agents badge, doctor, and listing safety
Follow-ups to 9ef170bb, where the discovery path itself is sound but three
surfaces around it are not.

The desktop badge showed the same tooltip for both scopes, and that tooltip
names ~/.agents/skills. A skill that ships inside a checked-out repository was
therefore described as one the user had installed in their own home directory
-- the least trusted source presented as the most trusted. Project-scope
skills now get their own copy, in all five locales.

The doctor listed both .agents targets unconditionally, so a user who set
disableAgentSkillsDirectory (or the env var) still saw them reported, with an
entry count if the directory had contents. That reads as "these skills are in
use" when the loader is ignoring them.

Skill directory names went into the catalog the model sees verbatim, one
`- name: description` line per skill, with no validation. A name containing a
line break writes entries of its own -- and .agents/skills is a directory
other clients and repositories write into, so the name is not necessarily the
user's. Names carrying control characters are now skipped. Deliberately
narrower than the Agent Skills spec's lowercase-and-hyphens rule: existing
.claude/skills directories predate it, and silently dropping one of those
would be the worse failure.

Also collapses the two spellings of the scoped dedup key -- the main loader
joined with a raw NUL byte embedded in the source, the --add-dir path with a
space -- into one helper, so the comment claiming both apply the same rule is
true and the invisible byte is gone.

Adds coverage for the two scopes 9ef170bb claimed but left untested: the
hot-reload watcher (no test file existed for it at all) and on-demand monorepo
discovery. Both were already correct; nothing was holding them that way.
2026-07-25 15:56:55 +08:00
程序员阿江(Relakkes)
ced096c894 fix(desktop): keep the dragged pet at the display edge across restarts
8a3ea62b taught dragging to clamp against the mascot rather than the whole
window, so a saved edge position deliberately leaves the transparent padding
off-screen. Recreating the window re-clamps that position against the whole
window again, and the reposition-on-restore step that undoes it was gated on
darwin -- so on Windows and Linux the mascot walked inwards by the padding
width on every hide/show, not just on restart. The gate only existed because
visibleDragRegion used to be darwin-only; the region now arrives everywhere,
so the repositioning runs everywhere.

e24d59fe restated the recorded window size on every drag tick to stop
setPosition from growing the window, but sampled that size from getBounds().
Chromium converts window rects between physical pixels and DIP with ceil in
both directions, so the sampled value has already been rounded up once and
restating it rounds up again: stable within a drag, a pixel per drag across
them. The window is created non-resizable at the nominal size, so restating
the constants is idempotent instead -- and heals a window that already drifted.
Both call sites now go through movePetWindow.

petWindowContentExtent fell back to the nominal constants when
getContentBounds returned an empty rect, which silently reinstates the exact
clamp it exists to avoid. Fall through to the live window box first.

The fake window in the tests returned one object for both getBounds and
getContentBounds, and modelled setBounds as inherently size-neutral -- so
neither "clamp to the content box" nor "size-neutral drag" was actually
proven: reverting either left all 33 tests green. It now models the ceil/ceil
DIP round trip and carries a distinct content box, and covers the previously
untested paths: cross-platform restore, multi-region shapes, the region
normalization bounds, and the getContentBounds fallbacks.
2026-07-25 15:56:39 +08:00
程序员阿江(Relakkes)
5b4e224f2e fix(desktop): address shadcn migration review findings
- Prevent EmptySession crash when settings have not loaded: fall back
  to the default permission-mode display and an empty model list, and
  stop undefined models responses from poisoning the settings store
- Sync Tauri terminal hardening with Electron: owner binding, input
  limits, window-destroy session cleanup, malformed config fallback
- Fix Sheet/MobileBottomSheet z-order so dialogs render above sheets
- Migrate ConfirmPopover to the shadcn Button; remove dead legacy
  shared form components and unused mockup pages
- Keep underscores readable in shared diagnostics, redact provider
  models only on secret-scanner hits, clean stale WhatsApp login
  staging dirs, and add recovery hints for corrupt computer-use config
- Token-ize find-in-page highlight colors, restore the indeterminate
  progress slide animation, and tidy a11y/displayName details
2026-07-25 15:07:00 +08:00
程序员阿江(Relakkes)
9ef170bb42 feat(skills): discover the cross-client .agents/skills convention #1093
Skills installed by Codex, Cursor, Gemini CLI, or opencode live under
`.agents/skills/` -- the convention documented at agentskills.io -- so users
had to keep a duplicate copy in `.claude/skills/` before cc-haha could see
them. The spec only constrains SKILL.md itself, which we already parse, so
this is purely a directory-discovery gap.

Scan both conventions at every scope: user (`~/.agents/skills`), project
(every level up to the repo root), `--add-dir` roots, on-demand monorepo
discovery, and the hot-reload watcher. skillRoots.ts is the single source of
truth for those paths; the REST API now reports which convention a skill came
from and the desktop list badges the `.agents` ones.

`.claude` is always ordered first, so first-wins dedup keeps a user's own
skills authoritative rather than letting an externally installed same-named
skill shadow them. Name collisions are collapsed per scope, which covers
copy-based sync -- symlink-based sync was already handled by the existing
realpath dedup. Collisions across different scopes, such as a user skill and
a project skill sharing a name, keep their existing behavior, and the shadowed
file's identity is recorded so overlapping roots (CLAUDE_CONFIG_DIR pointing
inside the project) cannot reintroduce it under the other scope.

getProjectDirsUpToHome is untouched -- it is shared by commands, agents,
output-styles, and workflows. Only its directory walk is extracted so the
skill resolver reuses the same submodule/worktree stop boundary. Writes stay
where they were: market installs and /skillify still target
`~/.claude/skills`.

`.agents` is anchored at $HOME rather than CLAUDE_CONFIG_DIR, since it is a
space shared with other tools that read $HOME. Note that Bun snapshots
os.homedir() at startup while Node re-reads $HOME per call, so the resolver
reads the env var explicitly.

Opt out with `disableAgentSkillsDirectory` in settings.json or
CLAUDE_CODE_DISABLE_AGENT_SKILLS_DIR=1; no `.agents` root is produced at all
then, so there is not even a failed stat.

(cherry picked from commit ba9338f85d6beaba237753e42e823c87b59633d4)
2026-07-25 02:50:21 +08:00
程序员阿江(Relakkes)
8a3ea62b9b fix(desktop): let the dragged pet reach display edges on Windows
setInteractiveRegions only recorded visibleDragRegion inside the darwin
branch, so on Windows and Linux it stayed null and dragging fell back to
clamping against the whole PET_WINDOW_WIDTH x PET_WINDOW_HEIGHT window. That
window is mostly transparent padding around a mascot anchored bottom center,
so the mascot stopped short of every display edge by the width of that
padding and could not be dragged into a corner. Record the region on all
platforms; the reposition-on-restore step stays darwin-only.

Normalizing the region also clamped against the nominal constants. Renderer
regions are measured against the live viewport, so clamp against the real
content box instead -- the same petWindowContentExtent the shape clamp
already uses -- and let the shape clamp reuse that one normalizer.
2026-07-25 02:38:19 +08:00
程序员阿江(Relakkes)
e24d59fe92 fix(desktop): stop clipping the dragged pet on Windows #1099 #1104
The Windows shape clamp used the nominal PET_WINDOW_HEIGHT constant. Renderer
regions are measured against the live viewport, so once the content area was
taller than that constant the mascot -- which sits flush with the viewport
bottom -- got sliced off from below, while the task badge kept its own
unclamped rect and stayed visible. Clamp the shape to the real content box.

Dragging also moved the window with setPosition, which Windows resolves as
getSize() + setBounds(); that DIP round trip grows the window a pixel at a
time on fractional display scaling, and the drag timer fires every 16ms.
Restate the recorded size on every tick so dragging stays size-neutral.
2026-07-25 02:12:10 +08:00
程序员阿江(Relakkes)
cc768b87c2 merge: unify desktop UI with shadcn components (#1089)
合入 shadcn/ui 全量迁移。该提交同时包含:
- 桌面端手写组件 -> shadcn/ui (radix-ui + Tailwind v4) 全量替换
- Electron 壳层加固: 终端 owner 绑定/IPC 校验/诊断写盘防逃逸
- server/utils 安全加固与修复: 诊断脱敏、Memory 乐观锁、Computer Use fail-closed、stats UTC 等

合并前已经 merge-tree 预演 + 落盘实证: 与 #1086/#1091 无文本冲突, 功能代码零损失。
2026-07-25 00:49:46 +08:00
程序员阿江(Relakkes)
ad597ffe0b feat(desktop): unify UI with shadcn components (#1089) 2026-07-24 23:59:48 +08:00
RaspberryLee
0e0ac28d0b
Merge branch 'main' into feat/installed-skills-overview 2026-07-24 16:08:39 +08:00
RaspberryLee
f4b1d8a384
Merge branch 'main' into fix/windows-electron-dev-launcher 2026-07-24 14:49:20 +08:00
程序员阿江(Relakkes)
c2774fc170 fix(desktop): support pasted file attachments #1086 2026-07-24 05:30:38 +08:00
程序员阿江(Relakkes)
8e9c104514 fix(desktop): handle missing Windows taskkill #1091 2026-07-24 05:13:36 +08:00
程序员阿江(Relakkes)
27901ee311 fix(site): reference the app icon png directly
The svg icon is only a wrapper around app-icon.png, and the nested
reference is invisible to the static copy step, so the image stayed
invisible on production even after the svg itself deployed.
2026-07-24 04:53:17 +08:00
程序员阿江(Relakkes)
6342070a27 fix(site): include code-referenced images in static output
The docs header logo and favicon 404 on production because the
static copy step only scanned markdown for image references. Scan
site sources as well and fail the build when one goes missing.
2026-07-24 04:48:57 +08:00
程序员阿江(Relakkes)
d1757bfaf5 feat(site): editorial redesign with rewritten landing copy
- rebuild home and docs UI around serif display type, warm paper,
  and a single vermilion accent
- rewrite zh/en landing copy around user value
- fix white screen on the last docs page (adjacent-doc out of bounds)
- curate sidebar labels and add TOC scroll-spy
2026-07-24 04:42:17 +08:00
程序员阿江(Relakkes)
c2fd674662 docs: rebuild documentation site with React 2026-07-23 20:46:33 +08:00
lichengshuo
8061b9b2a5 feat(desktop): show installed skills in the market 2026-07-23 16:57:36 +08:00
lichengshuo
0f22792861 fix(desktop): make electron:dev launcher work on Windows
`new URL('..', import.meta.url).pathname` yields a leading-slash path like
/E:/... on Windows, so Bun.spawn failed with ENOENT. Resolve desktopRoot via
fileURLToPath, start Vite through its Node API instead of spawning `bun run
dev`, and resolve the Electron binary directly per platform.

Recovered from the discarded wip/capabilities snapshot (cb1208c9) as a
standalone fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 16:33:39 +08:00
程序员阿江(Relakkes)
f70fa017ef release: prepare v0.4.11 v0.4.11 2026-07-23 03:30:42 +08:00
程序员阿江(Relakkes)
2240a07088 feat(desktop): improve pet motion and interactions 2026-07-23 03:03:05 +08:00
程序员阿江(Relakkes)
ca0342d252 Merge remote-tracking branch 'origin/main' 2026-07-23 00:31:40 +08:00
Relakkes Yang
3b2e750c6e fix(desktop): polish pet status and agent tools 2026-07-23 00:24:18 +08:00
Relakkes Yang
20b7753281 fix: sync pet status and finish agent editor 2026-07-22 22:12:27 +08:00
Relakkes Yang
a07e68839c fix: harden desktop runtime and pet interactions 2026-07-22 20:46:34 +08:00
程序员阿江(Relakkes)
29b17c8028 fix(models): expose current Claude official lineup 2026-07-22 17:42:19 +08:00
程序员阿江(Relakkes)
91829e91a4 fix(chat): preserve attachment context across resume 2026-07-21 04:05:01 +08:00
程序员阿江(Relakkes)
7f6fdadaa3 feat(agents): add per-agent model and effort controls #1062 2026-07-21 00:16:11 +08:00
程序员阿江(Relakkes)
1270ced4b4 fix(tasks): keep task state reliable across providers #1075 2026-07-20 23:53:46 +08:00
程序员阿江(Relakkes)
727bcea077 fix(desktop): harden Windows crash recovery #1064 #1065 #1071 2026-07-20 22:06:34 +08:00
程序员阿江(Relakkes)
ba8917f1db fix(desktop): decouple provider creation from presets request #1078 2026-07-20 20:39:40 +08:00
程序员阿江(Relakkes)
7d272e0f96 fix(server): handle tool denial interruption #1070 2026-07-20 20:38:45 +08:00
程序员阿江(Relakkes)
6b725a0b6f fix(desktop): show live SubAgent run details #1077 2026-07-20 20:30:33 +08:00
程序员阿江(Relakkes)
bf128cb9c0 fix(desktop): dedupe attachment message replay #1069 2026-07-20 20:28:18 +08:00
程序员阿江(Relakkes)
8995f56d1f fix(server): preserve context estimates for empty usage #1063 2026-07-20 20:20:25 +08:00
程序员阿江(Relakkes)
71dc2fd4cf fix(provider): update Kimi Code preset to K3 2026-07-20 19:25:20 +08:00
程序员阿江(Relakkes)
36560c09d5 feat(pets): add interactive desktop companions 2026-07-20 19:20:18 +08:00
程序员阿江(Relakkes)
100a2b25b8 fix(release): remove environment-dependent alias fixture v0.4.10 2026-07-18 20:25:42 +08:00
程序员阿江(Relakkes)
f8cccb096f fix(release): stabilize Windows recovery self-test 2026-07-18 20:20:34 +08:00