Skip to content
Open
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
40 changes: 40 additions & 0 deletions plugins/stevenjj33/workflow-console/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,46 @@ engine's own database and is not affected by the change.
Running real workflows still requires a working `mcode` CLI: the engine orchestrates agents through
it. The demo executor works without it.

## Prerequisites

The console itself needs nothing: no configuration step, no build step, and no other plugin
installed. It ships the Workflow Studio engine and starts it as a child process.

**The `mcode` CLI is a prerequisite for real runs only.** The engine drives agents through the
`mcode` CLI, so a run on the real executor needs that CLI installed, logged in, and able to call a
model. Everything else works without it:

| | needs `mcode` CLI |
| --- | --- |
| Opening the page, starting the engine, choosing a project directory | no |
| Approving a draft, pausing, cancelling, resuming | no |
| A run on the **demo** executor (placeholder results, no model call) | no |
| A run on the **real** executor (`mcode`, actual agent calls) | **yes** |

A new workflow starts in **demo** mode: the Studio's execution-mode picker defaults to demo, so
creating and running a workflow needs no CLI at all. Switch it to "MCode · real agents" only when
you want real agents — that is the point where the CLI becomes required.

Note that the MiniMax Code desktop app does **not** bundle the CLI. The CLI is a separate
`@minimax-ai/code` install (npm prefix `~/.minimax-code`), so having the desktop app installed is
not the same as having the CLI.

Where the engine looks for the CLI, in the order it tries:

1. `mcode` on `PATH`;
2. the official user install — `~/.minimax-code/bin/mcode` on macOS and Linux,
`~/.minimax-code/mcode.cmd` on Windows. `MCODE_INSTALL_DIR` replaces `~/.minimax-code`
as that root, so the engine then looks for `$MCODE_INSTALL_DIR/bin/mcode`;
3. a workflow-managed toolchain, if that directory has been populated —
`~/.mcode-dynamic-workflows/toolchain/lib/node_modules/@minimax-ai/code/cli.js` on macOS and
Linux, `~/.mcode-dynamic-workflows/toolchain/node_modules/@minimax-ai/code/cli.js` on Windows.

The status line reports "MCode CLI 可用/不可用". That flag only means **the executable was found** —
it says nothing about whether the CLI is logged in or still has model quota, which the CLI itself
decides when a real run starts. When the CLI is missing, the console says so in a banner and
refuses to start a real run instead of failing halfway through; the engine's own error for that
case is "找不到 MCode CLI,请安装并登录后开始。"

## Skill

The package ships one Skill, `skills/workflow-console/SKILL.md`. It tells the Agent how to drive
Expand Down
37 changes: 37 additions & 0 deletions plugins/stevenjj33/workflow-console/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,43 @@ Apache-2.0)。

跑真实工作流仍然需要本机 `mcode` CLI 可用:引擎通过它去编排 Agent。demo 执行器不需要。

## 前置条件

控制台本身不需要任何东西:不用配置、不用构建,也不用另外装插件——它自带 Workflow Studio 引擎,
直接作为子进程拉起来。

**`mcode` CLI 只是「真实执行」的前置条件。** 引擎通过 `mcode` CLI 驱动 Agent,所以用真实执行器
跑一次工作流,需要这个 CLI 已安装、已登录、且能调用模型。其余环节都不需要它:

| 环节 | 需要 `mcode` CLI |
| --- | --- |
| 打开页面、启动引擎、选定项目目录 | 不需要 |
| 审核草稿、暂停、取消、恢复 | 不需要 |
| **演示执行器**的运行(只返回占位结果,不调模型) | 不需要 |
| **真实执行器**(`mcode`,真正调度 Agent)的运行 | **需要** |

新建工作流默认是**演示**执行方式:Studio 的「执行方式」下拉框默认选中 demo,所以创建并运行一条
工作流全程不需要 CLI。只有当你要用真实 Agent 时,才需要把执行方式改成「MCode · 真实执行」——
那一步才让 CLI 变成硬前置。

另外注意:MiniMax Code 桌面版**不自带** CLI。CLI 是单独的 `@minimax-ai/code` 安装
(npm prefix 是 `~/.minimax-code`),所以装了桌面版不等于装了 CLI。

引擎按这个顺序找 CLI:

1. `PATH` 里的 `mcode`;
2. 官方用户安装位置——macOS 与 Linux 是 `~/.minimax-code/bin/mcode`,Windows 是
`~/.minimax-code/mcode.cmd`;设了 `MCODE_INSTALL_DIR` 时,它顶替 `~/.minimax-code` 当根目录,
引擎找的就是 `$MCODE_INSTALL_DIR/bin/mcode`;
3. 工作流托管的工具链(该目录已就位时才会命中)——macOS 与 Linux 是
`~/.mcode-dynamic-workflows/toolchain/lib/node_modules/@minimax-ai/code/cli.js`,Windows 是
`~/.mcode-dynamic-workflows/toolchain/node_modules/@minimax-ai/code/cli.js`。

状态栏上的「MCode CLI 可用/不可用」**只表示找到了这个可执行文件**——它不说明 CLI 有没有登录、
还剩多少模型额度,那两件事要等 CLI 真正跑起来时自己判断。CLI 缺失时,控制台会在横幅上写明,
并且拒绝启动真实执行,而不是让它跑到一半失败;引擎那边对应的报错是
「找不到 MCode CLI,请安装并登录后开始。」

## Skill

本包附带一个 Skill:`skills/workflow-console/SKILL.md`。它告诉 Agent 怎么用这个控制台——
Expand Down
80 changes: 63 additions & 17 deletions plugins/stevenjj33/workflow-console/miniapp/client/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,25 +259,49 @@ function toast(message, tone = 'success') {

const THEMES = ['system', 'light', 'dark'];
const THEME_LABEL = { system: '跟随系统', light: '浅色', dark: '深色' };
const THEME_STORAGE_KEY = 'wf-console-theme';
/* 系统配色偏好。跟随系统时由它决定实际是浅色还是深色;系统换配色时页面也跟着换。 */
const systemDark = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;

function storedTheme() {
try {
const saved = window.localStorage.getItem(THEME_STORAGE_KEY);
return THEMES.includes(saved) ? saved : 'system';
} catch {
/* 忽略存储不可用 */
}
return 'system';
}

/* 跟随系统 → 按系统偏好解析成浅色或深色;显式选择 → 用用户选的那个。
data-theme 一律设成具体值,CSS 只认 light/dark 两种;
早先这里是「system 就删掉 data-theme」,结果永远退回浅色。 */
function applyTheme(theme) {
if (theme === 'system') document.documentElement.removeAttribute('data-theme');
else document.documentElement.setAttribute('data-theme', theme);
const resolved = theme === 'system' ? (systemDark && systemDark.matches ? 'dark' : 'light') : theme;
document.documentElement.setAttribute('data-theme', resolved);
dom.themeToggle.textContent = `主题:${THEME_LABEL[theme]}`;
dom.themeToggle.dataset.theme = theme;
try {
window.localStorage.setItem('wf-console-theme', theme);
window.localStorage.setItem(THEME_STORAGE_KEY, theme);
} catch {
/* 忽略存储不可用 */
}
}

dom.themeToggle.addEventListener('click', () => {
const current = window.localStorage.getItem('wf-console-theme') || 'system';
const next = THEMES[(THEMES.indexOf(current) + 1) % THEMES.length];
const next = THEMES[(THEMES.indexOf(storedTheme()) + 1) % THEMES.length];
applyTheme(next);
});

/* 用户选的是「跟随系统」时,系统配色一变就跟着变。 */
if (systemDark) {
const onSystemThemeChange = () => {
if (storedTheme() === 'system') applyTheme('system');
};
if (systemDark.addEventListener) systemDark.addEventListener('change', onSystemThemeChange);
else if (systemDark.addListener) systemDark.addListener(onSystemThemeChange);
}

/* ---------------- engine status ---------------- */

/* 控制台只有一个后端:它自己内置的 Workflow Studio 引擎。
Expand All @@ -286,8 +310,13 @@ dom.themeToggle.addEventListener('click', () => {

let lastEngineSignature = '';

/** 当前这台控制台唯一的后端:它自己内置的 Workflow Studio 引擎。 */
function activeEngine() {
return state.services.find((service) => service.id === state.activeServiceId) || null;
}

function renderEngine() {
const active = state.services.find((service) => service.id === state.activeServiceId) || null;
const active = activeEngine();
const signature = active
? [
active.id,
Expand Down Expand Up @@ -323,21 +352,38 @@ function renderEngine() {
` · 并发 ${scheduler.active ?? 0}/${scheduler.limit ?? '—'}`;
}

if (live) {
if (live && active && active.mcodeAvailable === false) {
/* 引擎起来了,但真实执行器还差 MCode CLI:这时只有演示执行器能跑。 */
dom.serviceBanner.hidden = false;
dom.serviceBanner.textContent = '';
dom.serviceBanner.append(
node('strong', { text: '未找到 MCode CLI。' }),
node('span', {
text: ' 演示执行器(demo)不受影响,但用真实执行器跑工作流需要先安装并登录 MCode CLI,' +
'否则运行会在启动时失败。安装位置见 README 的「前置条件」。',
}),
);
} else if (live) {
dom.serviceBanner.hidden = true;
} else {
dom.serviceBanner.hidden = false;
dom.serviceBanner.textContent = '';
const starting = Boolean(active?.starting);
dom.serviceBanner.append(
node('strong', {
text: needsWorkspace ? '还没有选择项目目录。' : '内置引擎未能启动。',
text: needsWorkspace
? '还没有选择项目目录。'
: starting
? '内置引擎正在启动…'
: '内置引擎未能启动。',
}),
node('span', {
text: needsWorkspace
? ' 内置引擎不会在用户主目录或系统临时目录里运行——那样一次运行就能改写整个家目录。' +
'请在下方填写项目的绝对路径,保存后引擎会自动启动。'
: ' 控制台会自动重试;若持续失败,请确认 MCode CLI 可用(需要登录且模型可调用),' +
'并查看 dataDir/engine/service.log 里的引擎日志。',
: starting
? ' 控制台会拉起内置引擎,稍等即可;期间还不能开始执行。'
: ' 控制台会自动重试;若持续失败,请查看 dataDir/engine/service.log 里的引擎日志。',
}),
);
}
Expand Down Expand Up @@ -1567,6 +1613,12 @@ async function confirmStart(runId) {
}
const nodeCount = Array.isArray(run.topology?.nodes) ? run.topology.nodes.length : 0;
const real = run.executor !== 'demo';
/* 真实执行器要靠 MCode CLI 调度 Agent:CLI 根本不在时,运行一定起不来,
与其让它跑到一半失败,不如在这里说清楚。演示执行器不需要 CLI。 */
if (real && activeEngine()?.mcodeAvailable === false) {
toast('未找到 MCode CLI,真实执行无法启动;请先安装并登录 MCode CLI,或改用演示执行器。', 'danger');
return;
}
const answer = await askConfirm({
title: '开始执行该工作流',
note:
Expand Down Expand Up @@ -1985,13 +2037,7 @@ async function loadBootstrap() {
}

async function boot() {
let theme = 'system';
try {
theme = window.localStorage.getItem('wf-console-theme') || 'system';
} catch {
theme = 'system';
}
applyTheme(THEMES.includes(theme) ? theme : 'system');
applyTheme(storedTheme());

try {
await loadBootstrap();
Expand Down
17 changes: 17 additions & 0 deletions plugins/stevenjj33/workflow-console/miniapp/client/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@
--mcode-primary-action-text: #171717;
}

/* 实际配色由 data-theme 决定:脚本把「跟随系统」解析成 light/dark 落到这个属性上。
color-scheme 决定原生控件(输入框、滚动条)用哪一套配色,别让它们跟页面脱节。 */
[data-theme='light'] {
color-scheme: light;
}

[data-theme='dark'] {
color-scheme: dark;
}

/* 脚本还没跑(首屏那一瞬)时,原生控件先按系统偏好走。 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
color-scheme: dark;
}
}

* {
box-sizing: border-box;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,48 @@
需要人工确认的步骤会让那个节点直接失败,而不是停下来等人。
控制台的「开始执行」确认框和 README 都写明了这一点。

### 上游是怎么选执行器的(升级时必看)

引擎只有两个执行器,真实执行**没有第二条路径**:

- `demoExecute` —— 不调模型,延时后返回占位结果;
- `mcodeExecute` —— 直接 spawn `mcode exec --input - --cwd … --output-format stream-json --permission smart …`。

有一处极易看错:**`/api/config` 里的 `executor` 字段是 CLI 命令名**
(`engine.options.command`,值就是 `"mcode"`),**不是某次运行用的执行方式**。
真正的执行方式是每次运行单独指定的 `request.executor`(取值 `demo` 或 `mcode`),
引擎用 `check(["demo","mcode"].includes(request.executor), "executor 必须为 demo 或 mcode")`
强制它存在。

而新建工作流时**默认是 demo**:Studio 的「执行方式」下拉框第一项就是 demo,
`showCreate()` 只调 `form.reset()`、从不覆盖这个选择。
所以「MCode CLI 是硬前置」这句话只对**真实执行**成立,默认路径并不需要它。

上游查找 CLI 的顺序是三处:`PATH` 里的 `mcode` → 官方用户安装位置
(根目录是 `$MCODE_INSTALL_DIR`,没设时是 `~/.minimax-code`;macOS/Linux 找其下的 `bin/mcode`,
Windows 找 `mcode.cmd`)→ 工作流托管的工具链
(`~/.mcode-dynamic-workflows/toolchain/lib/node_modules/@minimax-ai/code/cli.js`,Windows 少一层 `lib`,
只在该目录已就位时命中,引擎只检查文件存在,不负责安装)。

**升级上游时如果动了这一段**(执行器选择、`resolveMcode()` 的查找顺序),
README 的「前置条件 / Prerequisites」章节必须跟着改——两处是同一件事的两个视角,
只改一边,两份文档就会自相矛盾。

### 怎么自己确认「CLI 缺失」这个信号是真的

别只读源码就相信某个分支可达。起一个隔离环境就能复现:

```sh
TMP=$(mktemp -d); mkdir -p "$TMP/ws" "$TMP/data" "$TMP/fakehome" "$TMP/emptyroot"
env -i HOME="$TMP/fakehome" PATH="/usr/bin:/bin" MCODE_INSTALL_DIR="$TMP/emptyroot" \
"$(command -v node)" miniapp/node/vendor/dynamic-workflows/dist/main.mjs \
--workspace "$TMP/ws" --data-dir "$TMP/data"
```

`HOME` 指向空目录 → `~/.minimax-code` 不存在;`PATH` 里没有 `mcode`;
`MCODE_INSTALL_DIR` 指向空目录。引擎照常启动,`/api/config` 返回
`"mcodeAvailable": false`——这正是控制台横幅和「拒绝启动真实执行」所依赖的信号。

## 更新方式(怎么跟上上游)

副本锁定在 `6481e4ae1e0375a4ddb3d5e9b29845354ab1cead`,不会自动跟随上游升级。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ description: "运行、查看与管控 MiniMax Code 动态工作流(多 Agent
页面上 `mcodeAvailable: true` 只说明 `mcode` 可执行文件存在,**不代表它登录了或还有额度**。
真实执行失败时先查登录和额度,别直接归因给工作流本身。

CLI 找不到时,控制台会在横幅上写明并**拒绝启动真实执行**——这时候别反复重试,让用户先装好并登录,
或改用 demo 执行器(Studio 的「执行方式」默认就是 demo,不调模型,所以没有 CLI 也能把工作流
创建并跑起来)。引擎查找 CLI 的顺序:`PATH` 里的 `mcode` → 官方用户安装位置
(根目录是 `$MCODE_INSTALL_DIR`,没设时是 `~/.minimax-code`;macOS/Linux 找其下的 `bin/mcode`,
Windows 找 `mcode.cmd`)→ 工作流托管的工具链
(`~/.mcode-dynamic-workflows/toolchain/lib/node_modules/@minimax-ai/code/cli.js`,Windows 少一层 `lib`)。

## 数据与边界

- 引擎只监听 `127.0.0.1`,控制台只代理到它:不连外网,也不连别的本地服务。
Expand Down
Loading