feat: 深度研究支持独立新报告与原文改写,并完善沙箱、模型管理与全文改写

新报告不再覆盖当前文件卡片,写入时打开沙箱;步骤条仅在改写原文时位于卡片上方。同时补齐改写本地回退、模型管理与会商第三步相关改动。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
董宏凯andCursor committed 2026-08-21 21:46:04 +08:00
1 parent 11f928bc95
commit a5a9c952e8
63 files changed
+4113 -929

No files matched your search

+56 -3
View File
@@ -46,7 +46,7 @@ export async function loadArtifactContent({
return { content: text, url };
}
export function loadArtifactContentFromToolCall({
export function loadArtifactContentFromToolCall({
url: urlString,
thread,
}: {
@@ -66,5 +66,58 @@ export function loadArtifactContentFromToolCall({
return toolCall.args.content;
}
}
}
}
}
}
function normalizeArtifactPath(path: string): string {
let normalized = path.trim();
const first = normalized[0];
const last = normalized.at(-1);
if (
normalized.length >= 2 &&
((first === '"' && last === '"') ||
(first === "'" && last === "'") ||
(first === "`" && last === "`"))
) {
normalized = normalized.slice(1, -1).trim();
}
return normalized.replace(/\\/g, "/").replace(/^\/+/, "");
}
/**
* Last-resort preview for an output whose artifact HTTP request is unavailable.
*
* A completed `write_file` can be selected before its backing sandbox file is
* visible through the artifacts endpoint (or when a deployment temporarily
* serves a stale mount). The original tool arguments still contain the
* Markdown, so use the newest matching write as a read-only display fallback.
*/
export function loadArtifactContentFromLatestWriteFile({
filepath,
thread,
}: {
filepath: string;
thread: BaseStream<AgentThreadState>;
}): string | undefined {
const normalizedFilepath = normalizeArtifactPath(filepath);
if (!normalizedFilepath) return undefined;
for (const message of [...thread.messages].reverse()) {
if (message.type !== "ai" || !message.tool_calls) continue;
for (const toolCall of [...message.tool_calls].reverse()) {
if (toolCall.name !== "write_file") continue;
if (!toolCall.args || typeof toolCall.args !== "object" || Array.isArray(toolCall.args)) {
continue;
}
const args = toolCall.args as { path?: unknown; content?: unknown };
if (
typeof args.path === "string" &&
typeof args.content === "string" &&
normalizeArtifactPath(args.path) === normalizedFilepath
) {
return args.content;
}
}
}
return undefined;
}