Skip to content

feat(apps): trigger method, role wording, avatars, calmer card colors - #7

Merged
squarezw merged 1 commit into
mainfrom
feat/trigger-and-role
Aug 3, 2026
Merged

feat(apps): trigger method, role wording, avatars, calmer card colors#7
squarezw merged 1 commit into
mainfrom
feat/trigger-and-role

Conversation

@squarezw

@squarezw squarezw commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Needs ragent-service#66 (the avatar_url field and the Plugin platform value).

类型 → 触发方式

The picker now offers 聊天 / 定时任务 / 邮件 / 自定义 and answers "what triggers this employee". 订阅 folds into 定时任务 in the label only — the stored value stays Subscription, because isStreamApp reads it in eight places to decide whether to show feed management. Plugin moves to the platform picker where it belongs.

Legacy Tool/Plugin values still render: when an app already has one it appears as an extra option, so the select never shows up blank.

Agent.md → 角色设定

The editor title is now just 角色设定 — no filename, no colored tag. The help text was rewritten for people who don't know what a prompt is. Revert-to-prompt is gone: now that every new app is born with an Agent.md there is nothing to revert to, so the button only ever led to a dead end.

The 提示词 dropdown is gone from the edit dialog as well. The role is the single source of truth, so there is no template to pick from. prompt_id is still submitted (null) as the rollback anchor; the now-unused /api/prompts fetch went with it — one fewer request on first paint.

Avatars

Eight built-in avatars plus upload, shown in the edit dialog and rendered in list, card and detail views.

Built-ins are SVG rather than images: the whole UI is lucide, so the same glyph family looks native, scales cleanly at any size and carries no licensing baggage. They live in public/ so every deployment has them and an offline install doesn't render blanks.

Colour ownership — if the user picked an avatar (built-in or uploaded) it renders untouched; that was their choice, not ours to theme. Only the unset case falls back to initial + brand colour, so it follows whatever primary colour a tenant configures. AppAvatar is shared by all four call sites so the rule isn't reimplemented four times and slowly drifting.

Uploads get a UUID filename first. The OSS object key is <category>/<yyyymm>/<filename> with no server-side dedupe — verified by calling presign twice with the same name and getting the same key back. Avatars are exactly where names collide (avatar.png, logo.png, 头像.png), and a collision doesn't error: it silently swaps one employee's face for another's, and the person who uploaded first never finds out.

Note: the same collision exists for the existing knowledge / SOP / system-logo uploads. Not touched here — worth a separate decision.

Card colours

Trigger and platform tags are neutral now. They used to be purple / green / yellow / blue / emerald / orange, one hue per value, and the hues meant nothing — 聊天 was purple and Web was purple too, so a reader has to check whether the colour is saying something before discovering it isn't.

Colour is left to the things that actually say something: review-status badges (draft / pending / rejected), the destructive action, and the avatar. Both colour maps were deleted rather than filled with one repeated value — a map whose every value is identical isn't a map.

Tests

216 passing (+8). tsc unchanged at the existing baseline apart from the new test files' pre-existing TS5097 class.

The avatar tests pin the two directions that fail silently: every entry in BUILTIN_AVATARS has a file on disk and every file on disk is registered (an unregistered one can never be picked). One asserts the SVGs carry their own colours and don't use currentColor — loaded via <img> they can't reach page CSS variables, so a stripped colour isn't an error, just an invisible tile. Both were mutation verified.

Verified in the browser

Not just unit tests: picked a built-in avatar → saved → confirmed the value in the database → confirmed the card re-rendered with it. Uploaded a real PNG and confirmed the object key got a UUID, the file came back with content-type: image/png, and the image rendered.

🤖 Generated with Claude Code

## 类型 → 触发方式

The picker now offers 聊天 / 定时任务 / 邮件 / 自定义 and answers "what triggers
this employee". 订阅 folds into 定时任务 in the label only — the stored value is
still `Subscription`, because `isStreamApp` reads it in eight places to decide
whether to show feed management. `Plugin` moves to the platform picker, where it
actually belongs. Legacy `Tool`/`Plugin` values still render (they appear as an
extra option when an app already has one) instead of showing an empty select.

## Agent.md → 角色设定

The editor's title is now just 角色设定 — no filename, no colored tag. The help
text was rewritten for people who don't know what a prompt is. The revert-to-
prompt action is gone: with every new app born with an Agent.md there is nothing
to revert to, and the button only ever led to a dead end.

The 提示词 dropdown is gone from the edit dialog too. The role is the single
source of truth, so there is no template to pick from; `prompt_id` is still sent
(null) as the rollback anchor. Its `/api/prompts` fetch went with it — one fewer
request on first paint.

## Avatars

New field with eight built-in avatars plus upload. Built-ins are SVG rather than
images: the whole UI is lucide, so the same glyph family looks native, scales
cleanly and carries no licensing baggage. They live in `public/` so every
deployment has them and an offline install doesn't render blanks.

Colour ownership: if the user picked an avatar (built-in or uploaded) it renders
untouched — their choice, not ours to theme. Only the unset case falls back to
initial + brand colour, so it follows a tenant's primary colour. `AppAvatar` is
shared by list, card, detail and dialog so the rule isn't reimplemented four
times and slowly drifting.

Uploads get a UUID filename first. The OSS object key is
`<category>/<yyyymm>/<filename>` with no server-side dedupe (verified: two
presigns for the same name return the same key), and avatars are exactly where
names collide — avatar.png, logo.png. A collision doesn't error, it silently
swaps one employee's face for another's.

## Card colours

Trigger and platform tags are neutral now. They used to be purple/green/yellow/
blue/emerald/orange, one hue per value, and the hues meant nothing — 聊天 purple,
Web purple too. Colour is left to the things that are actually saying something:
review-status badges, the destructive action, and the avatar.

Both colour maps were deleted rather than filled with one repeated value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@squarezw
squarezw merged commit c51a59c into main Aug 3, 2026
1 check passed
@squarezw
squarezw deleted the feat/trigger-and-role branch August 3, 2026 09:40
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