feat: 崩溃弹窗集成日志分享与 AI 分析
Sync source to CNB / Sync Git ref (push) Skipped

将崩溃弹窗替换为双栏布局:左侧展示诊断摘要与分享入口,
右侧提供日志文件浏览器与 LogAgent 流式分析输出。

- MinecraftCrashModal 改用新版的分享票据、结构化摘要与 AI 事件流
- 新增 minecraft-crash-logs 工具函数,用于筛选与合并崩溃日志
- 事件层新增 logshare_ai_listener 监听 AI 分析进度
- log-share 工具更新为支持 provider 路由的新版
- Button 组件对齐新版(补 icon-only、circular、2xs 与 chip/highlight 变体)
- console 导出 LogViewport,供日志浏览器复用
- 补齐 en-US / zh-CN 相关文案
This commit is contained in:
AxTps committed 2026-10-11 14:05:33 +08:00
1 parent a95153d0b1
commit c71c220446
10 files changed
+1323 -144

No files matched your search

+22 -2
View File
@@ -28,6 +28,13 @@ export function truncateLogToMaxBytes(content: string, maxBytes: number): string
return textDecoder.decode(bytes.subarray(start))
}
/**
* Log sharing providers supported by the launcher. LogShare is the default
* and is implemented in the desktop app through native Tauri commands; mclo.gs
* is the network fallback used when LogShare is unreachable or unselected.
*/
export type LogShareProvider = 'logshare' | 'mclogs'
/**
* Result of sharing log content. `truncated` is set when the content exceeded
* `LOG_SHARE_MAX_BYTES` and only its tail was uploaded.
@@ -39,12 +46,25 @@ export type LogShareResult = {
/**
* Share log content through mclo.gs. Content larger than `LOG_SHARE_MAX_BYTES`
* is trimmed to its last
* `LOG_SHARE_MAX_BYTES` before uploading.
* is trimmed to its last `LOG_SHARE_MAX_BYTES` before uploading.
*/
export async function shareLogs(
client: AbstractModrinthClient,
content: string,
): Promise<LogShareResult> {
return shareLogsWithProvider(client, content, 'mclogs')
}
/**
* Share log content through the given provider. The `logshare` provider is
* only available inside the desktop app (native commands); this shared helper
* routes the `mclogs` fallback so both launcher surfaces can share generic
* log buffers.
*/
export async function shareLogsWithProvider(
client: AbstractModrinthClient,
content: string,
_provider: LogShareProvider = 'mclogs',
): Promise<LogShareResult> {
const uploadContent = truncateLogToMaxBytes(content, LOG_SHARE_MAX_BYTES)
const truncated = uploadContent !== content