Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion plugins/minimax-ai/minimax-pet/.minimax-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"schemaVersion": 1,
"name": "minimax-pet",
"displayName": "MiniMax Pet",
"version": "0.8.0",
"version": "0.9.0",
"description": "轻量桌宠,聚合主窗口可见会话的任务状态、需要回答的提醒和最新结果,支持外观切换及图集导入。",
"author": "MiniMax",
"icon": "icon.png",
Expand Down
14 changes: 11 additions & 3 deletions plugins/minimax-ai/minimax-pet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@

English | [简体中文](README.zh-CN.md)

A lightweight desktop companion for MiniMax Code, by **MiniMax**. It shows visible conversation activity, answer-needed reminders and recent results without creating another chat. The interface is currently in Chinese.
A lightweight desktop companion for MiniMax Code, by **MiniMax**. It shows visible conversation activity, answer-needed reminders and recent results without creating another chat. The interface is available in Simplified Chinese and English.

## Features

- **Appearance:** preview and select pets, import compatible pet JSON and spritesheets, and remove imported pets.
- **Tasks:** recent reminders, visible user conversations, and a scrollable latest reply rendered as Markdown. Desktop cards preview up to five lines. Clicking a card keeps the pet visible; observed `ask_user` calls show “需要你回答” (needs your answer).
- **Open the conversation:** on MiniMax Code 3.1.11 or later, a task's detail, in the panel and on the desktop, has a **打开对话** (open conversation) button, labelled **去回答** (go answer) while the task needs an answer. It brings the MiniMax Code main window forward on that conversation. Older clients do not show the button.
- **Settings:** pet size, page-local reminder dismissal and mute, connection status, and reconnect.
- **Language:** the panel and desktop copy follow the MiniMax Code interface language on 3.1.11 or later, or the system language when the client does not report one, and can be pinned in **Settings**. Older clients fall back to the system language.
- **Settings:** pet size, interface language, how long desktop cards stay, page-local reminder dismissal and mute, connection status, and reconnect.
- **Desktop window:** a draggable transparent pet with compact notification cards. Return it to the main panel to use the three tabs.
- **Theme:** on MiniMax Code 3.1.11 or later the panel and desktop cards follow the client's light or dark theme; older clients follow the system setting.

The pet does not run Agent turns, create independent chats, write to chat inputs, comment on every session, stop tasks, or answer questionnaires. Selecting a task only reads its details; the main window switches only when you click **打开对话** or **去回答**.

Version **0.9.0** adds two settings. **Task notifications** sets how many seconds a desktop card stays after a task finishes or fails, entered as a number and saved on the device; the default is 10 and **0** keeps the card until you close it. A card hiding never marks the task read, cards that need your answer never hide, and pointing at or focusing the cards pauses the countdown. **Language** follows the MiniMax Code interface language by default and can be pinned to 简体中文 or English; the whole panel and desktop copy switch, while conversation titles and replies stay as the Agent wrote them.

Version **0.9.0** also gives the desktop window one fixed size, tall enough for the open card. Earlier versions grew the window when a card opened, which moved it on screen and made the pet jump for a frame; now opening or closing a card only shows or hides it. The area above the pet is transparent and passes clicks through to whatever is behind it.

Version **0.8.1** fixes the desktop card: the title truncates to one line, only the reply scrolls, and the actions stay pinned, so a long title or reply no longer pushes 返回任务 / 打开对话 out of the card. Expanding the card also grows the window instead of squeezing the reply into one line.

Version **0.8.0** aligns the panel with the MiniMax Code design language: 24px page margins and section gaps, 14px/22px body copy with 12px/18px supporting text, 32px minimum control height, 12px cards and 8px controls, 0.5px borders on desktop overlays, and press/focus states. The desktop pet keeps its 280px layout with the same tokens.

Version **0.7.0** renders each task's latest reply as Markdown: headings, emphasis, lists, task lists, fenced code, tables, quotes and links, with raw HTML shown as inert text and images as a label instead of a remote request. Notification cards and reminder previews stay plain text. Parsing uses a vendored bundle of unified, remark-parse and remark-gfm (MIT) built by `npm run build:markdown`; the page never builds an HTML string from model output. The bundle makes no network request and runs entirely in the page.
Expand All @@ -39,6 +46,7 @@ Earlier local prototypes use a different plugin ID. The Host gives `minimax-pet`
- **打开对话** / **去回答** uses `host.navigation.open` and the theme uses `host.ui.subscribe`, both added in MiniMax Code **3.1.11**; on 2026-11-10 the macOS and Windows installers of 3.1.11 answered on both production CDNs. Both calls were checked against the MiniMax Code source: opening a conversation the Mini App already holds needs no `hostAccess` and no extra grant, must start inside a click, and brings the main window forward.
- An earlier UI version was exercised on macOS in a MiniMax Code development build: three tabs, wide/narrow layouts, task reading, real session/ask activity, import/delete, and desktop round trips. Version 0.6.0 has Node/DOM tests (including the open and theme paths against a simulated Host), an isolated HTTP smoke test, and a browser check of the panel layout outside the Host.
- The default atlas is checked by actual PNG decoding, frame coverage and deterministic rebuild tests. The separate octopus icon is checked by PNG decoding and visual review. On 2026-10-26, the packaged Skill was exercised with a real Agent in the macOS development build to create, validate, preview and import a custom v2 pet; all nine animation previews and the four cardinal mouse-look directions were checked. This does not replace released-client acceptance.
- Version 0.9.0 has Node/DOM tests for the card timer, the preference round trip and the copy of both languages (every key the page uses must exist in both), plus a browser check of the panel and desktop window in both languages against a simulated Host. Not verified for 0.9.0: the language the real client reports on any given install, and both languages inside a real MiniMax Code window.
- Not verified for 0.6.0: opening a conversation or following the theme inside a real MiniMax Code 3.1.11+ window (panel or desktop pet), any Windows GUI, and released-client installation or GUI acceptance on 3.1.6. Automated tests use synthetic data and do not prove those paths.

## Data & access
Expand All @@ -49,7 +57,7 @@ Earlier local prototypes use a different plugin ID. The Host gives `minimax-pet`
- **Local files:** the Node service serves packaged assets and stores preferences and user-imported JSON/WebP/PNG spritesheets under opaque `context.dataDir`. Imports, replacement recovery and deletion are limited to that plugin data. Browser storage is used only to migrate old view preferences.
- **Rendered replies:** the latest reply is parsed as Markdown by the vendored parser and rebuilt as DOM nodes under the page's own stylesheet. Raw HTML in a reply is displayed as literal text, never executed or inserted as markup; links show their target on hover and are not opened; images are not fetched and appear as a text label.
- **Host navigation:** only when you click **打开对话** or **去回答**, the page calls `host.navigation.open({ id: 'session', sessionId, source: 'local' })` for a conversation it already lists through `session.read`. It does not declare `hostAccess` and never reads which page of MiniMax Code you are on. It writes nothing to chat inputs and sends no message.
- **Display preferences:** `host.ui.subscribe` reports the client theme, which the page applies; the reported language is ignored. No grant is involved.
- **Display preferences:** `host.ui.subscribe` reports the client theme and interface language; the page applies the theme and, while the language setting is **Follow MiniMax Code**, the language. Choosing 简体中文 or English overrides it. The preference is stored with the other settings in the plugin data directory. No grant is involved.
- **Network:** the plugin has no hard-coded external runtime endpoint; its own HTTP requests use its assigned loopback origin.
- **Microphone, camera and notifications:** not used and not declared.
- **Processes and Agent turns:** the Host starts one Node process. The plugin spawns no additional runtime process, launches no shell command, offers no MCP server, and never calls `agent.run`.
Expand Down
10 changes: 9 additions & 1 deletion plugins/minimax-ai/minimax-pet/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@

将仓库 `plugins/minimax-ai/minimax-pet/` 完整复制到 `<dataDir>/plugins/minimax-pet/`,包括隐藏的 `.minimax-plugin`;默认 `<dataDir>` 为 `~/.minimax`,自定义数据目录时采用实际配置。不要复制外层作者目录。重启 MiniMax Code、确认插件启用后,从 MiniApp 列表打开“MiniMax Pet”,或对 Agent 说“打开 MiniMax Pet”。点击“放到桌面”显示透明桌宠窗口。

外观页支持选择、导入预览和删除已导入宠物;任务页显示提醒、全部可见任务和按 Markdown 渲染的最近回复;设置页提供大小、提醒管理和重连。桌面通知最多预览五行,点击后可滚动读完整内容,桌宠保持可见。观察到 ask 时显示“需要你回答”。
外观页支持选择、导入预览和删除已导入宠物;任务页显示提醒、全部可见任务和按 Markdown 渲染的最近回复;设置页提供大小、语言、通知时长、提醒管理和重连。

面板和桌面文案在 MiniMax Code 3.1.11 及以上跟随客户端界面语言;客户端不报告语言时跟随系统语言,也可以在设置页固定为简体中文或 English。旧版本客户端跟随系统语言。桌面通知最多预览五行,点击后可滚动读完整内容,桌宠保持可见。观察到 ask 时显示“需要你回答”。

在 MiniMax Code 3.1.11 及以上版本,面板和桌面上的任务详情都有“打开对话”按钮,任务需要回答时显示为“去回答”;点一下会把 MiniMax Code 主窗口切到这个对话。面板和桌面卡片的明暗也跟随 MiniMax Code 的主题。旧版本客户端不显示该按钮,明暗跟随系统设置。

**0.5.10** 新增可选内置宠物 **麦芽糖**,是一位珊瑚粉触手长发的 Q 版全身章鱼娘。在“外观 → 选择宠物”中选择她,预览下方会显示她的自述;薄荷色机器人仍为默认宠物。麦芽糖采用现有 v2 图集,包含九种动作和十六个视线方向,沿用六帧、6.6 秒一轮的慢速待机,不新增权限或改变播放器。图集已通过校验,并在 Linux 的本地插件界面完成导入和选择;这不代表正式客户端的 bundled 安装或透明桌面窗口已验收。AI 创作流程和贡献者许可见[素材说明](ARTWORK.md)。

**0.5.11** 新增可选内置宠物 **MMX 章鱼娘**,是一位橙发、白背心、棕格纹短裙的 Q 版全身章鱼娘。在“外观 → 选择宠物”中选择她即可;薄荷色机器人仍为默认宠物。她采用 v1 图集,包含九种动作,不含十六个视线方向,因此鼠标跟随对她不生效;沿用六帧、6.6 秒一轮的慢速待机,不新增权限或改变播放器。图集已通过校验。创作流程和贡献者许可见[素材说明](ARTWORK.md)。

**0.9.0** 新增两项设置。“任务通知”用数字框设置桌面卡片在任务完成或异常后显示多少秒,默认 10 秒,填 0 表示一直显示到手动关闭;设置保存在本机。卡片自动收起不会把任务标记为已读,需要你回答的卡片不会自动收起,鼠标悬停或焦点停留时会暂停计时。“语言”默认跟随 MiniMax Code 的界面语言,也可以固定为简体中文或 English;面板和桌面文案整体切换,对话标题和回复保持 Agent 原文。

**0.9.0** 把桌面窗口固定成一个尺寸,本来就放得下展开的卡片。之前点开卡片会把窗口撑高,窗口在屏幕上跟着移动,桌宠会跳一下;现在开合卡片只显示或隐藏,不动窗口。桌宠上方是透明区域,点击会穿透到底下的窗口。

**0.8.1** 修复桌面卡片:标题单行截断,只有回复区滚动,底部操作固定在卡片内;长标题或长回复不再把「返回任务 / 打开对话」顶出卡片。展开卡片时窗口同步变高,回复不会被压成一行。

**0.8.0** 按 MiniMax Code 的设计语言对齐面板:24px 页边距与区块间距、14px/22px 正文与 12px/18px 辅助文字、控件最小高度 32px、卡片 12px 与控件 8px 圆角、桌面浮层 0.5px 描边,并补齐按下与焦点状态。桌面宠物保持 280px 布局,沿用同一套 token。

**0.7.0** 把任务最近回复按 Markdown 渲染:标题、强调、列表、任务清单、代码块、表格、引用和链接;回复里的原始 HTML 只作为文本显示,图片显示为文字标签而不发起网络请求。通知卡片和提醒预览仍为纯文本。解析使用 `npm run build:markdown` 打包的 unified + remark-parse + remark-gfm(MIT);页面不会把模型输出拼成 HTML 字符串。
Expand Down
5 changes: 3 additions & 2 deletions plugins/minimax-ai/minimax-pet/miniapp/client/activity.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Public Page Agent adapter. No Host activity projection, private IPC or inferred asks/unread state.
import { t } from './i18n.mjs';
export const STATUS_ANIM = Object.freeze({ idle: 'idle', running: 'running', error: 'failed', aborted: 'idle', completed: 'review' });
const RAW_STATUSES = new Set(['idle', 'running', 'error', 'aborted']);
const PRIORITY = ['error', 'completed', 'running', 'aborted', 'idle'];
Expand All @@ -10,7 +11,7 @@ const idOf = (value) => typeof value === 'string' && value.length > 0 && value.l

export function normalizeSession(raw, { detail = false } = {}) {
if (!raw || typeof raw !== 'object' || !idOf(raw.sessionId) || !RAW_STATUSES.has(raw.status) || !Number.isSafeInteger(raw.updatedAtMs) || raw.updatedAtMs < 0 || (raw.title !== undefined && typeof raw.title !== 'string')) throw invalid();
const session = { sessionId: raw.sessionId, title: (raw.title || '未命名对话').slice(0, 1000), status: raw.status, updatedAtMs: raw.updatedAtMs };
const session = { sessionId: raw.sessionId, title: (raw.title || t('desk.untitled')).slice(0, 1000), status: raw.status, updatedAtMs: raw.updatedAtMs };
if (detail) {
if (typeof raw.error?.message === 'string') session.error = raw.error.message;
if (typeof raw.lastAssistantText === 'string') session.lastAssistantText = raw.lastAssistantText;
Expand Down Expand Up @@ -152,7 +153,7 @@ export function createActivitySource({ agent, onChange, pollIntervalMs = 5000, n
removedAt.delete(event.sessionId);
const previous = rows.get(event.sessionId);
const status = outcome === 'finished' ? 'idle' : outcome;
rows.set(event.sessionId, { sessionId: event.sessionId, title: typeof event.title === 'string' && event.title ? event.title.slice(0, 1000) : previous?.title || '未命名对话', status, updatedAtMs: now(), liveCompleted: outcome === 'finished' });
rows.set(event.sessionId, { sessionId: event.sessionId, title: typeof event.title === 'string' && event.title ? event.title.slice(0, 1000) : previous?.title || t('desk.untitled'), status, updatedAtMs: now(), liveCompleted: outcome === 'finished' });
emit({});
if (state.selectedSessionId === event.sessionId) void readDetail(epoch);
}
Expand Down
Loading
Loading