mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-06 01:14:36 +08:00
feat(version): bump version to 0.2.0 and update image ratio parsing functions
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## v0.7.0 - 2026-07-14
|
||||||
|
|
||||||
+ [新增] Agent 对话消息改用 streamdown 流式渲染,提升Markdown 内容展示效果。
|
+ [新增] Agent 对话消息改用 streamdown 流式渲染,提升Markdown 内容展示效果。
|
||||||
+ [新增] Agent 新增画布、工作台、提示词库和素材等站点级工具。
|
+ [新增] Agent 新增画布、工作台、提示词库和素材等站点级工具。
|
||||||
+ [新增] Agent 面板改为全站常驻右侧栏,开关时同步推动顶栏和页面内容,并保留独立入口按钮。
|
+ [新增] Agent 面板改为全站常驻右侧栏,开关时同步推动顶栏和页面内容,并保留独立入口按钮。
|
||||||
@@ -16,6 +18,7 @@
|
|||||||
+ [调整] 画布节点顶部工具条改为点击选中节点后显示,避免鼠标经过节点时频繁弹出。
|
+ [调整] 画布节点顶部工具条改为点击选中节点后显示,避免鼠标经过节点时频繁弹出。
|
||||||
+ [优化] 本地 Agent 连接说明明确区分插件 / 手动 MCP 才会增加 Codex token 消耗。
|
+ [优化] 本地 Agent 连接说明明确区分插件 / 手动 MCP 才会增加 Codex token 消耗。
|
||||||
+ [优化] 优化本地 Agent 连接说明,区分 Codex 插件启动和直接运行 Agent 两种方式。
|
+ [优化] 优化本地 Agent 连接说明,区分 Codex 插件启动和直接运行 Agent 两种方式。
|
||||||
|
+ [修复] 修复 Gemini 格式生图时因内置比例列表触发误报导致生成失败的问题。
|
||||||
|
|
||||||
## v0.6.0 - 2026-07-09
|
## v0.6.0 - 2026-07-09
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@basketikun/canvas-agent",
|
"name": "@basketikun/canvas-agent",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "rea
|
|||||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||||
import { App, Button, Input, Segmented, Tooltip } from "antd";
|
import { App, Button, Input, Segmented, Tooltip } from "antd";
|
||||||
import copyToClipboard from "copy-to-clipboard";
|
import copyToClipboard from "copy-to-clipboard";
|
||||||
import { Copy, FolderOpen, History, KeyRound, Link2, LoaderCircle, PlugZap, Plus, RefreshCw, RotateCcw, Square, Terminal, Trash2 } from "lucide-react";
|
import { Copy, FolderOpen, History, KeyRound, Link2, LoaderCircle, PlugZap, Plus, RefreshCw, Square, Terminal, Trash2 } from "lucide-react";
|
||||||
|
|
||||||
import { canvasThemes } from "@/lib/canvas-theme";
|
import { canvasThemes } from "@/lib/canvas-theme";
|
||||||
import { useThemeStore } from "@/stores/use-theme-store";
|
import { useThemeStore } from "@/stores/use-theme-store";
|
||||||
@@ -320,14 +320,6 @@ export function CanvasLocalAgentPanel({ embedded, headless, autoConnect }: { emb
|
|||||||
await runToolCall(endpoint, token, tool);
|
await runToolCall(endpoint, token, tool);
|
||||||
};
|
};
|
||||||
|
|
||||||
const undoLastTool = () => {
|
|
||||||
const restored = canvasContextRef.current?.undoOps() || null;
|
|
||||||
if (!restored) return;
|
|
||||||
setAgentState({ activity: "已撤销" });
|
|
||||||
addMessage({ role: "tool", title: "已撤销", text: "上一次工具操作", detail: restored });
|
|
||||||
if (connected) void postState(endpoint, token, clientIdRef.current, restored);
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleAgentConnection = async ({ silent = false }: { silent?: boolean } = {}) => {
|
const toggleAgentConnection = async ({ silent = false }: { silent?: boolean } = {}) => {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
clearAgentSession({ enabled: false, connected: false, activity: "离线", connectError: "" });
|
clearAgentSession({ enabled: false, connected: false, activity: "离线", connectError: "" });
|
||||||
@@ -513,8 +505,8 @@ export function CanvasLocalAgentPanel({ embedded, headless, autoConnect }: { emb
|
|||||||
}}
|
}}
|
||||||
right={
|
right={
|
||||||
<>
|
<>
|
||||||
<Button size="small" type="text" disabled={!canvasContext?.canUndo} icon={<RotateCcw className="size-3.5" />} onClick={undoLastTool}>
|
<Button size="small" type="text" disabled={!connected || loadingThreads} icon={<Plus className="size-3.5" />} onClick={startNewThread}>
|
||||||
撤销
|
新对话
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,16 +146,21 @@ function resolveSize(quality: string | undefined, ratio: string): string {
|
|||||||
return `${width}x${height}`;
|
return `${width}x${height}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseImageRatio(value: string) {
|
function parseRatioValue(value: string) {
|
||||||
const parts = value.split(":");
|
const parts = value.split(":");
|
||||||
if (parts.length !== 2) throw new Error("图像尺寸格式不支持,请使用 auto、9:16 或 1024x1024");
|
if (parts.length !== 2) throw new Error("图像尺寸格式不支持,请使用 auto、9:16 或 1024x1024");
|
||||||
const w = Number(parts[0]);
|
const w = Number(parts[0]);
|
||||||
const h = Number(parts[1]);
|
const h = Number(parts[1]);
|
||||||
if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) throw new Error("图像比例必须是正数,例如 9:16");
|
if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) throw new Error("图像比例必须是正数,例如 9:16");
|
||||||
if (Math.max(w, h) / Math.min(w, h) > IMAGE_MAX_RATIO) throw new Error("图像宽高比不能超过 3:1,请调整尺寸");
|
|
||||||
return { width: w, height: h };
|
return { width: w, height: h };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseImageRatio(value: string) {
|
||||||
|
const ratio = parseRatioValue(value);
|
||||||
|
if (Math.max(ratio.width, ratio.height) / Math.min(ratio.width, ratio.height) > IMAGE_MAX_RATIO) throw new Error("图像宽高比不能超过 3:1,请调整尺寸");
|
||||||
|
return ratio;
|
||||||
|
}
|
||||||
|
|
||||||
function parseImageDimensions(value: string) {
|
function parseImageDimensions(value: string) {
|
||||||
const match = value.match(/^(\d+)x(\d+)$/i);
|
const match = value.match(/^(\d+)x(\d+)$/i);
|
||||||
if (!match) return null;
|
if (!match) return null;
|
||||||
@@ -197,8 +202,8 @@ function closestGeminiAspectRatio(value: string) {
|
|||||||
const ratio = parseImageRatio(value);
|
const ratio = parseImageRatio(value);
|
||||||
const target = ratio.width / ratio.height;
|
const target = ratio.width / ratio.height;
|
||||||
return GEMINI_SUPPORTED_RATIOS.reduce((best, item) => {
|
return GEMINI_SUPPORTED_RATIOS.reduce((best, item) => {
|
||||||
const current = parseImageRatio(item);
|
const current = parseRatioValue(item);
|
||||||
const bestRatio = parseImageRatio(best);
|
const bestRatio = parseRatioValue(best);
|
||||||
return Math.abs(current.width / current.height - target) < Math.abs(bestRatio.width / bestRatio.height - target) ? item : best;
|
return Math.abs(current.width / current.height - target) < Math.abs(bestRatio.width / bestRatio.height - target) ? item : best;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user