源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
const PREFERRED_STRUCTURED_TEXT_KEYS = [
|
||||
"plan",
|
||||
"text",
|
||||
"summary",
|
||||
"result",
|
||||
"output",
|
||||
"error",
|
||||
"message",
|
||||
"detail",
|
||||
"details",
|
||||
"reason",
|
||||
"description",
|
||||
"stdout",
|
||||
"stderr",
|
||||
"query",
|
||||
"path",
|
||||
"file",
|
||||
"filePath",
|
||||
"file_path",
|
||||
"url",
|
||||
"cmd",
|
||||
"command",
|
||||
"content",
|
||||
"data",
|
||||
"response",
|
||||
"status",
|
||||
"account",
|
||||
"usage"
|
||||
] as const;
|
||||
|
||||
const MAX_STRUCTURED_TEXT_DEPTH = 5;
|
||||
const MAX_STRUCTURED_TEXT_ITEMS = 32;
|
||||
const MAX_STRUCTURED_TEXT_LENGTH = 16_000;
|
||||
|
||||
/**
|
||||
* Extracts a bounded human-readable value from provider-shaped tool data.
|
||||
* Provider error envelopes are not stable across adapters, so this helper
|
||||
* intentionally follows a small set of semantic keys instead of serializing
|
||||
* arbitrary payloads. Nested provider envelopes are covered by the same keys
|
||||
* at each bounded depth.
|
||||
*/
|
||||
export function structuredToolText(value: unknown): string | null {
|
||||
const text = visitStructuredToolText(value, 0, new WeakSet<object>());
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
return text.length > MAX_STRUCTURED_TEXT_LENGTH
|
||||
? text.slice(0, MAX_STRUCTURED_TEXT_LENGTH)
|
||||
: text;
|
||||
}
|
||||
|
||||
function visitStructuredToolText(
|
||||
value: unknown,
|
||||
depth: number,
|
||||
seen: WeakSet<object>
|
||||
): string | null {
|
||||
if (typeof value === "string" && value.trim()) {
|
||||
return value.trim();
|
||||
}
|
||||
if (typeof value === "number" || typeof value === "boolean") {
|
||||
return String(value);
|
||||
}
|
||||
if (
|
||||
!value ||
|
||||
typeof value !== "object" ||
|
||||
depth > MAX_STRUCTURED_TEXT_DEPTH
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (seen.has(value)) {
|
||||
return null;
|
||||
}
|
||||
seen.add(value);
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
const parts = value
|
||||
.slice(0, MAX_STRUCTURED_TEXT_ITEMS)
|
||||
.map((entry) => visitStructuredToolText(entry, depth + 1, seen))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
return parts.length > 0 ? parts.join("\n\n") : null;
|
||||
}
|
||||
|
||||
const record = value as Record<string, unknown>;
|
||||
for (const key of PREFERRED_STRUCTURED_TEXT_KEYS) {
|
||||
const text = visitStructuredToolText(record[key], depth + 1, seen);
|
||||
if (text) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user