refactor(*): 插件身份 - 将旧插件统一更名为 yingce

This commit is contained in:
ddCat
2026-08-22 14:48:10 +08:00
parent 8428c66c5a
commit bcfb87c98c
14 changed files with 33 additions and 33 deletions

View File

@@ -47,14 +47,14 @@ Canvas Agent 默认只监听 `127.0.0.1`。网页第一次带正确 token 连接
### Codex app 插件
仓库内提供了 Codex app 插件:`plugins/infinite-canvas`。该插件尚未上架公共插件目录,直接搜索不会显示;在 Codex app 中添加本仓库的 marketplace 后即可安装。插件会注册同一个 `infinite-canvas` MCP,并带上画布操作说明。
仓库内提供了 Codex app 插件:`plugins/yingce`。该插件尚未上架公共插件目录,直接搜索不会显示;在 Codex app 中添加本仓库的 marketplace 后即可安装。插件会注册 `yingce` MCP,并带上画布操作说明。
添加本地 marketplace 时建议使用仓库绝对路径,避免 Codex 从其他工作目录解析失败:
```bash
cd /path/to/infinite-canvas
cd /path/to/open-ai-canvas
codex plugin marketplace add "$(pwd)"
codex plugin add infinite-canvas@infinite-canvas-local
codex plugin add yingce@yingce-local
```
插件默认通过 npm 启动 MCP:
@@ -68,13 +68,13 @@ npx -y @ddcat666/open-ai-canvas-agent mcp
Canvas Agent 启动后,给 Codex 添加 MCP:
```bash
codex mcp add infinite-canvas -- npx -y @ddcat666/open-ai-canvas-agent mcp
codex mcp add yingce -- npx -y @ddcat666/open-ai-canvas-agent mcp
```
本仓库开发时可以改成,实际使用建议替换为本机绝对路径:
```bash
codex mcp add infinite-canvas -- node /path/to/infinite-canvas/canvas-agent/dist/index.js mcp
codex mcp add yingce -- node /path/to/open-ai-canvas/canvas-agent/dist/index.js mcp
```
Canvas Agent 源码使用 TypeScript 编写,MCP 协议层使用官方 `@modelcontextprotocol/sdk`,工具入参使用 `zod` 描述。
@@ -82,7 +82,7 @@ Canvas Agent 源码使用 TypeScript 编写,MCP 协议层使用官方 `@modelc
如果希望终端里的 Codex 不被 MCP 审批卡住,可以在 `~/.codex/config.toml` 里给这个 MCP 设置自动放行:
```toml
[mcp_servers.infinite-canvas]
[mcp_servers.yingce]
command = "npx"
args = ["-y", "@ddcat666/open-ai-canvas-agent", "mcp"]
default_tools_approval_mode = "approve"
@@ -115,7 +115,7 @@ default_tools_approval_mode = "approve"
## 侧边栏 Codex
本地面板会把提示词发送给 Canvas Agent。Canvas Agent 使用官方 `@openai/codex` CLI 的 `codex app-server --stdio` 启动并复用同一个 Codex thread,启动时会注入 `infinite-canvas` MCP 配置并自动放行 MCP 审批,真正执行画布修改前仍由网页侧边栏二次确认。
本地面板会把提示词发送给 Canvas Agent。Canvas Agent 使用官方 `@openai/codex` CLI 的 `codex app-server --stdio` 启动并复用同一个 Codex thread,启动时会注入 `yingce` MCP 配置并自动放行 MCP 审批,真正执行画布修改前仍由网页侧边栏二次确认。
侧边栏会展示 Codex 返回的 `thread.started`、`turn.started`、`item.*`、`turn.completed` 等结构化事件;收到 app-server 的 `item/agentMessage/delta` 时,Canvas Agent 会转成 `item.updated`,网页会用同一条消息做真实流式更新,并把工具细节收进运行日志。
@@ -128,13 +128,13 @@ Claude Code Adapter 代码暂时保留,但当前网页侧边栏只开放 Codex
如果希望 Claude Code 也能操作画布,需要给 Claude Code 添加同一个 MCP。建议用 user scope,避免 Canvas Agent 从不同目录启动时找不到配置:
```bash
claude mcp add --scope user --transport stdio infinite-canvas -- npx -y @ddcat666/open-ai-canvas-agent mcp
claude mcp add --scope user --transport stdio yingce -- npx -y @ddcat666/open-ai-canvas-agent mcp
```
本仓库开发时可以改成:
```bash
claude mcp add --scope user --transport stdio infinite-canvas -- node /path/to/infinite-canvas/canvas-agent/dist/index.js mcp
claude mcp add --scope user --transport stdio yingce -- node /path/to/open-ai-canvas/canvas-agent/dist/index.js mcp
```
Canvas Agent 调用 Claude Code 时会默认带上 `--allowedTools mcp__infinite-canvas__*`,画布写操作仍由网页侧边栏确认。
Canvas Agent 调用 Claude Code 时会默认带上 `--allowedTools mcp__yingce__*`,画布写操作仍由网页侧边栏确认。

View File

@@ -95,7 +95,7 @@ export async function archiveCodexThread(emit: AgentEmit, threadId: string, cwd?
export function runClaudeTurn(prompt: string, emit: AgentEmit) {
if (!prompt.trim()) return;
const child = spawnAgent("claude", ["-p", "--output-format", "stream-json", "--verbose", "--include-partial-messages", "--allowedTools", "mcp__infinite-canvas__*", prompt], ["ignore", "pipe", "pipe"], emit);
const child = spawnAgent("claude", ["-p", "--output-format", "stream-json", "--verbose", "--include-partial-messages", "--allowedTools", "mcp__yingce__*", prompt], ["ignore", "pipe", "pipe"], emit);
if (!child) return;
pipeJsonLines(child, emit, "claude");
}
@@ -277,7 +277,7 @@ export function canvasAgentMcpCommand() {
export function codexConfig(configDir = CONFIG_DIR) {
return {
mcp_servers: {
"infinite-canvas": {
"yingce": {
command: canvasAgentMcp.command,
args: canvasAgentMcp.args,
env: { FRAMEFIELD_LOCAL_RUNTIME_CONFIG_DIR: configDir },

View File

@@ -11,7 +11,7 @@ export const DEFAULT_PORT = LOCAL_RUNTIME_DEFAULT_PORT;
export const CONFIG_DIR = startupConfigDirectory();
export const CONFIG_FILE = path.join(CONFIG_DIR, "canvas-agent.json");
export const VERSION = readPackageVersion();
export const AGENT_PROMPT = "你正在帮助用户操作影策网页画布。需要改动画布时优先使用已配置的 infinite-canvas MCP 工具:先 canvas_get_state 读取当前画布,再根据任务使用 canvas_create_text_node、canvas_generate_text、canvas_generate_image、canvas_generate_video、canvas_generate_audio、canvas_create_generation_flow、canvas_run_generation、canvas_update_node、canvas_connect_nodes 等通用工具;复杂批量改动再用 canvas_apply_ops,删除连线可用 delete_connections。需要生成内容时直接调用对应生成工具,不要绑定特定业务场景。即使用户明确点名 Dreamina/即梦,本机 Canvas Agent 也必须通过 canvas_generate_image 或 canvas_generate_video 进入共享 GenerationTask;本机图片模型使用 model=local:dreamina-cli:5.0 这类产品模型值,用户选择自动分辨率时使用 quality=auto;禁止调用 direct dreamina_cli provider tool。不要模拟鼠标点击,不要要求用户手动复制 JSON。";
export const AGENT_PROMPT = "你正在帮助用户操作影策网页画布。需要改动画布时优先使用已配置的 yingce MCP 工具:先 canvas_get_state 读取当前画布,再根据任务使用 canvas_create_text_node、canvas_generate_text、canvas_generate_image、canvas_generate_video、canvas_generate_audio、canvas_create_generation_flow、canvas_run_generation、canvas_update_node、canvas_connect_nodes 等通用工具;复杂批量改动再用 canvas_apply_ops,删除连线可用 delete_connections。需要生成内容时直接调用对应生成工具,不要绑定特定业务场景。即使用户明确点名 Dreamina/即梦,本机 Canvas Agent 也必须通过 canvas_generate_image 或 canvas_generate_video 进入共享 GenerationTask;本机图片模型使用 model=local:dreamina-cli:5.0 这类产品模型值,用户选择自动分辨率时使用 quality=auto;禁止调用 direct dreamina_cli provider tool。不要模拟鼠标点击,不要要求用户手动复制 JSON。";
export type CanvasWorkspaceConfig = { workspacePath: string; activeThreadId?: string; pinnedThreadIds?: string[] };
export type LocalRuntimeConfig = {

View File

@@ -95,7 +95,7 @@ export function startLocalRuntime(options: StartLocalRuntimeOptions = {}) {
await listening(server);
log("Framefield Local Runtime");
log("Runtime is listening on 127.0.0.1");
log("Codex MCP: codex mcp add infinite-canvas -- npx -y @ddcat666/open-ai-canvas-agent mcp");
log("Codex MCP: codex mcp add yingce -- npx -y @ddcat666/open-ai-canvas-agent mcp");
} catch (startupError) {
sessions.dispose();
const cleanupErrors: unknown[] = [];

View File

@@ -17,7 +17,7 @@ const config: CanvasAgentConfig = {
type CommandFactory = () => { command: string; args: string[] };
type CodexConfigFactory = (configDir?: string) => {
mcp_servers: {
"infinite-canvas": {
"yingce": {
command: string;
args: string[];
env?: Record<string, string>;
@@ -44,7 +44,7 @@ test("internal Codex MCP config binds only the parent Runtime config directory",
assert.equal(typeof configFactory, "function");
if (!configFactory) return;
const configDir = path.resolve("fixture-runtime-config-18871");
const server = configFactory(configDir).mcp_servers["infinite-canvas"];
const server = configFactory(configDir).mcp_servers["yingce"];
assert.deepEqual(server.env, { FRAMEFIELD_LOCAL_RUNTIME_CONFIG_DIR: configDir });
assert.equal(server.args.includes("--canvas-only"), true);
assert.equal(server.args.some((value) => /token|secret/i.test(value)), false);
@@ -55,7 +55,7 @@ test("internal MCP tool timeout covers the Canvas generation continuation window
const configFactory = (agentsModule as unknown as { codexConfig?: CodexConfigFactory }).codexConfig;
assert.equal(typeof configFactory, "function");
if (!configFactory) return;
const timeoutMs = configFactory().mcp_servers["infinite-canvas"].tool_timeout_sec * 1_000;
const timeoutMs = configFactory().mcp_servers["yingce"].tool_timeout_sec * 1_000;
assert.ok(timeoutMs >= 35 * 60 * 1_000, `internal MCP timeout ${timeoutMs}ms must cover the 35-minute generation continuation window`);
assert.ok(timeoutMs > 35 * 60 * 1_000, "internal MCP timeout must leave shutdown/response margin after the Canvas continuation window");
});