sync: 鍚屾灞€鍩熺綉鏈€鏂颁唬鐮?(source master @ b69568e4)

This commit is contained in:
gozeros committed 2026-10-21 14:51:31 +08:00
1 parent 4f7f07504a
commit 8bc8b0e082
1651 files changed
+278599 -11416

No files matched your search

+90 -86
View File
@@ -3,6 +3,7 @@ import type { BaseStream } from "@langchain/langgraph-sdk/react";
import { apiFetch } from "../api";
import type { AgentThreadState } from "../threads";
import { resolveStreamingWriteFileArgs } from "./parse-partial-json";
import { urlOfArtifact } from "./utils";
export async function loadArtifactContent({
@@ -19,34 +20,34 @@ export async function loadArtifactContent({
let enhancedFilepath = filepath;
if (filepath.endsWith(".skill")) {
enhancedFilepath = filepath + "/SKILL.md";
}
const url = urlOfArtifact({ filepath: enhancedFilepath, threadId, isMock, publicShareCode });
const response = await apiFetch(url);
const text = await response.text();
if (!response.ok) {
let detail = text.trim();
try {
const parsed = JSON.parse(text) as { detail?: unknown; message?: unknown };
const parsedDetail =
typeof parsed.detail === "string"
? parsed.detail
: typeof parsed.message === "string"
? parsed.message
: "";
if (parsedDetail) {
detail = parsedDetail;
}
} catch {
// Keep the raw response text as the diagnostic detail.
}
throw new Error(
`Failed to load artifact (${response.status})${detail ? `: ${detail}` : ""}`,
);
}
return { content: text, url };
}
}
const url = urlOfArtifact({ filepath: enhancedFilepath, threadId, isMock, publicShareCode });
const response = await apiFetch(url);
const text = await response.text();
if (!response.ok) {
let detail = text.trim();
try {
const parsed = JSON.parse(text) as { detail?: unknown; message?: unknown };
const parsedDetail =
typeof parsed.detail === "string"
? parsed.detail
: typeof parsed.message === "string"
? parsed.message
: "";
if (parsedDetail) {
detail = parsedDetail;
}
} catch {
// Keep the raw response text as the diagnostic detail.
}
throw new Error(
`Failed to load artifact (${response.status})${detail ? `: ${detail}` : ""}`,
);
}
return { content: text, url };
}
export function loadArtifactContentFromToolCall({
export function loadArtifactContentFromToolCall({
url: urlString,
thread,
}: {
@@ -58,66 +59,69 @@ export function loadArtifactContentFromToolCall({
const messageId = url.searchParams.get("message_id");
if (messageId && toolCallId) {
const message = thread.messages.find((message) => message.id === messageId);
if (message?.type === "ai" && message.tool_calls) {
const toolCall = message.tool_calls.find(
(toolCall) => toolCall.id === toolCallId,
if (message?.type === "ai") {
const toolCall = message.tool_calls?.find(
(candidate) => candidate.id === toolCallId,
);
if (toolCall) {
return toolCall.args.content;
const { content } = resolveStreamingWriteFileArgs(message, toolCall);
if (content) return content;
}
const chunkOnly = resolveStreamingWriteFileArgs(message, {
id: toolCallId,
name: "write_file",
});
if (chunkOnly.content) return chunkOnly.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") continue;
for (const toolCall of [...(message.tool_calls ?? [])].reverse()) {
if (toolCall.name !== "write_file") continue;
const args = resolveStreamingWriteFileArgs(message, toolCall);
if (
args.path &&
args.content &&
normalizeArtifactPath(args.path) === normalizedFilepath
) {
return 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;
}
}
return undefined;
}