移除错误报告手动入口
删除 /bug-report 聊天命令与崩溃页报告按钮 同步项目摘要文案和 AGC 错误报告方案
This commit is contained in:
@@ -3,14 +3,13 @@ import {
|
||||
type ErrorInfo,
|
||||
type FormEvent,
|
||||
type ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import type { AuthUser } from '../../../../packages/shared/src/contracts/auth';
|
||||
import brandIcon from '../../../../packages/shared/src/icons/taonier-product-ip.png';
|
||||
import { ErrorReportDialog } from '../components/error-report/ErrorReportDialog';
|
||||
import { ErrorReportCenter } from '../components/error-report/ErrorReportDialog';
|
||||
import {
|
||||
clearStoredAuthAccessToken,
|
||||
getClientAuthErrorMessage,
|
||||
@@ -34,7 +33,7 @@ import {
|
||||
import {
|
||||
captureClientError,
|
||||
installWebviewLogBridge,
|
||||
OPEN_ERROR_REPORT_EVENT,
|
||||
shouldCaptureClientError,
|
||||
} from '../services/errorReporting';
|
||||
import {
|
||||
beginPlatformSessionClearTransition,
|
||||
@@ -50,7 +49,6 @@ import {
|
||||
type ClientRuntimeErrorBoundaryProps = {
|
||||
children: ReactNode;
|
||||
onLogout: () => void;
|
||||
onReport?: () => void;
|
||||
};
|
||||
|
||||
type ClientRuntimeErrorBoundaryState = {
|
||||
@@ -95,11 +93,6 @@ export class ClientRuntimeErrorBoundary extends Component<
|
||||
<button type="button" onClick={this.props.onLogout}>
|
||||
返回登录
|
||||
</button>
|
||||
{this.props.onReport ? (
|
||||
<button type="button" onClick={this.props.onReport}>
|
||||
报告问题
|
||||
</button>
|
||||
) : null}
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
@@ -123,7 +116,6 @@ export function AuthenticatedClient({
|
||||
const [loginBusy, setLoginBusy] = useState(false);
|
||||
const [codeBusy, setCodeBusy] = useState(false);
|
||||
const [codeCooldownSeconds, setCodeCooldownSeconds] = useState(0);
|
||||
const [errorReportOpen, setErrorReportOpen] = useState(false);
|
||||
const initialServerSelection = getClientServerSelection();
|
||||
const [serverSelection, setServerSelection] = useState<ClientServerSelection>(
|
||||
initialServerSelection,
|
||||
@@ -131,13 +123,6 @@ export function AuthenticatedClient({
|
||||
const [customServerUrl, setCustomServerUrl] = useState(
|
||||
initialServerSelection.customBaseUrl,
|
||||
);
|
||||
const openManualErrorReport = useCallback(async () => {
|
||||
await captureClientError(new Error('用户主动报告问题'), {
|
||||
source: 'manual',
|
||||
});
|
||||
setErrorReportOpen(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const uninstallWebviewLogBridge = installWebviewLogBridge();
|
||||
const handleError = (event: ErrorEvent) => {
|
||||
@@ -157,15 +142,6 @@ export function AuthenticatedClient({
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener(OPEN_ERROR_REPORT_EVENT, openManualErrorReport);
|
||||
return () =>
|
||||
window.removeEventListener(
|
||||
OPEN_ERROR_REPORT_EVENT,
|
||||
openManualErrorReport,
|
||||
);
|
||||
}, [openManualErrorReport]);
|
||||
|
||||
function persistServerSelection() {
|
||||
try {
|
||||
const next = setClientServerSelection({
|
||||
@@ -357,10 +333,11 @@ export function AuthenticatedClient({
|
||||
setCodeCooldownSeconds(Math.max(0, Math.floor(response.cooldownSeconds)));
|
||||
setLoginStatus(`验证码已发送,${response.expiresInSeconds} 秒内有效`);
|
||||
} catch (error) {
|
||||
void captureClientError(error, {
|
||||
source: 'auth',
|
||||
action: 'send-login-code',
|
||||
});
|
||||
if (shouldCaptureClientError(error))
|
||||
void captureClientError(error, {
|
||||
source: 'auth',
|
||||
action: 'send-login-code',
|
||||
});
|
||||
setLoginStatus(error instanceof Error ? error.message : String(error));
|
||||
} finally {
|
||||
setCodeBusy(false);
|
||||
@@ -419,7 +396,8 @@ export function AuthenticatedClient({
|
||||
setCode('');
|
||||
setPassword('');
|
||||
} catch (error) {
|
||||
void captureClientError(error, { source: 'auth', action: 'login' });
|
||||
if (shouldCaptureClientError(error))
|
||||
void captureClientError(error, { source: 'auth', action: 'login' });
|
||||
setLoginStatus(error instanceof Error ? error.message : String(error));
|
||||
} finally {
|
||||
setLoginBusy(false);
|
||||
@@ -589,16 +567,10 @@ export function AuthenticatedClient({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ClientRuntimeErrorBoundary
|
||||
onLogout={logout}
|
||||
onReport={() => void openManualErrorReport()}
|
||||
>
|
||||
<ClientRuntimeErrorBoundary onLogout={logout}>
|
||||
{children({ user: authUser, logout })}
|
||||
</ClientRuntimeErrorBoundary>
|
||||
<ErrorReportDialog
|
||||
open={errorReportOpen}
|
||||
onClose={() => setErrorReportOpen(false)}
|
||||
/>
|
||||
<ErrorReportCenter />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ export function summarizeProjectKnownIssues(
|
||||
};预览 ${previewSummary}`,
|
||||
`- 已知问题:${knownIssueSummary}`,
|
||||
'- 试玩限制:本地 Web 原型;小范围 5-10 分钟试玩;不承诺账号、云存档、排行榜、付费或长期兼容',
|
||||
'- 反馈入口:单个问题走 /bug-report;整体体验走 /feedback;版本变化走 /release-notes',
|
||||
'- 反馈入口:客户端问题由自动诊断提示;整体体验走 /feedback;版本变化走 /release-notes',
|
||||
'- 发送前检查:可试玩状态先 /run;交付口径看 /share;对外资料看 /media-kit',
|
||||
'- 边界:只准备已知问题清单;不读取文件;不启动或打开预览;不导出试玩包;不上传云端;不发布作品;不写项目',
|
||||
`- 建议:${draftCommand}`,
|
||||
|
||||
@@ -75,7 +75,6 @@ export function summarizeNextProjectActions(
|
||||
addSuggestion('查看隐私与导出边界', '/privacy');
|
||||
addSuggestion('查看首批试玩对象', '/audience');
|
||||
addSuggestion('准备试玩邀请文案', '/invite');
|
||||
addSuggestion('报告问题', '/bug-report');
|
||||
addSuggestion('准备试玩问卷问题', '/survey');
|
||||
addSuggestion('准备封面与缩略图检查', '/cover');
|
||||
addSuggestion('准备宣传截图清单', '/screenshots');
|
||||
|
||||
@@ -290,8 +290,8 @@ export function summarizeProjectPlaytestSurvey(
|
||||
'- 使用场景:发给首批 3-5 位测试者;每人 5-10 分钟;先自由玩一局再回答',
|
||||
'- 问题清单:1. 30 秒内你觉得目标是什么?2. 第一次操作哪里最卡?3. 胜负/重开是否清楚?4. 难度/节奏感觉如何?5. 最想保留和最想改的各一项?',
|
||||
'- 记录格式:每题 1-5 分 + 一句话;补充设备、输入方式、是否愿意再玩一局',
|
||||
'- 追踪方式:单个问题走 /bug-report;整体反馈走 /feedback;下一轮改动走 /revise',
|
||||
'- 参考:/invite;/audience;/feedback;/bug-report',
|
||||
'- 追踪方式:客户端问题由自动诊断提示;整体反馈走 /feedback;下一轮改动走 /revise',
|
||||
'- 参考:/invite;/audience;/feedback',
|
||||
'- 边界:只准备试玩问卷;不读取文件;不启动或打开预览;不导出试玩包;不写项目',
|
||||
`- 建议:${draftCommand}`,
|
||||
].join('\n'),
|
||||
@@ -557,7 +557,7 @@ export function summarizeProjectPlaytestFaq(
|
||||
};预览 ${previewSummary}`,
|
||||
'- 问答清单:1. 这是什么?2. 怎么开始和重开?3. 需要反馈什么?4. 打不开或卡住怎么办?5. 能不能转发或公开?',
|
||||
'- 回答口径:早期本地 Web 原型;5-10 分钟试玩;重点反馈目标理解、操作手感、难度、bug 和还想不想再玩',
|
||||
'- 测试者提醒:先自由玩一局;不要评价完成度;问卷走 /survey;单个问题走 /bug-report',
|
||||
'- 测试者提醒:先自由玩一局;不要评价完成度;问卷走 /survey;客户端问题由自动诊断提示',
|
||||
'- 交付搭配:/invite;/share;/screenshots;/trailer',
|
||||
'- 边界:只准备试玩常见问答;不读取文件;不启动或打开预览;不导出试玩包;不写项目',
|
||||
`- 建议:${draftCommand}`,
|
||||
@@ -624,7 +624,7 @@ export function summarizeProjectCommunityPost(
|
||||
`- 短文案:我做了一个早期 Web 小游戏原型《${nextManifest.name}》,核心目标是${goal}。想找 3-5 位朋友试玩 5 分钟,重点看能不能理解目标、操作顺不顺、还想不想再来一局。`,
|
||||
'- 长文案结构:一句玩法目标;一张截图或短视频;试玩方式;希望收到的三类反馈;已知限制',
|
||||
'- 标签建议:#Web小游戏 #原型试玩 #AI游戏创作 #本地试玩',
|
||||
'- CTA:愿意试玩请回复;遇到问题按 /faq 或 /bug-report 的口径反馈',
|
||||
'- CTA:愿意试玩请回复;遇到问题按 /faq 的口径反馈,客户端问题会自动提示',
|
||||
'- 参考:/faq;/screenshots;/trailer;/store;/share',
|
||||
'- 边界:只准备社区发布文案;不上传云端;不发布作品;不读取文件;不启动或打开预览;不导出试玩包;不写项目',
|
||||
`- 建议:${draftCommand}`,
|
||||
|
||||
@@ -290,7 +290,7 @@ export function summarizeProjectCompatibilityNotes(
|
||||
`- 输入兼容:${inputSummary}`,
|
||||
'- 推荐环境:桌面 Chrome / Edge 最新版;本机 127.0.0.1 预览;移动浏览器只做早期体验',
|
||||
'- 不承诺:旧浏览器、低端设备、离线模式、云存档、账号同步、手柄或多端数据一致',
|
||||
'- 反馈口径:设备 / 浏览器 / 输入方式 / 截图或录屏;问题记录走 /bug-report',
|
||||
'- 反馈口径:设备 / 浏览器 / 输入方式 / 截图或录屏;客户端检测到问题时会自动提示',
|
||||
'- 参考:/mobile;/accessibility;/performance;/known-issues',
|
||||
'- 边界:只准备兼容性说明;不读取文件;不启动或打开预览;不导出试玩包;不上传云端;不发布作品;不写项目',
|
||||
`- 建议:${draftCommand}`,
|
||||
|
||||
@@ -123,7 +123,6 @@ export const chatCommandHelp = [
|
||||
'/privacy:查看隐私与导出边界',
|
||||
'/audience:查看首批试玩对象',
|
||||
'/invite:准备试玩邀请文案',
|
||||
'/bug-report:报告问题',
|
||||
'/survey:准备试玩问卷问题',
|
||||
'/cover:准备封面与缩略图检查',
|
||||
'/screenshots:准备宣传截图清单',
|
||||
|
||||
@@ -9,7 +9,6 @@ import type {
|
||||
AgentStatusCard,
|
||||
ChatMessage,
|
||||
} from '../../app/types';
|
||||
import { OPEN_ERROR_REPORT_EVENT } from '../../services/errorReporting';
|
||||
import {
|
||||
summarizeAgentReviewState,
|
||||
summarizeAgentRunBudget,
|
||||
@@ -506,20 +505,6 @@ export function handleProjectSummaryChatCommand({
|
||||
return true;
|
||||
}
|
||||
|
||||
if (prompt === '/bug-report') {
|
||||
setMessages((current) => [
|
||||
...current,
|
||||
{
|
||||
role: 'assistant',
|
||||
text: '已打开“报告问题”面板,请填写遇到的问题。',
|
||||
},
|
||||
]);
|
||||
if (typeof window !== 'undefined') {
|
||||
window.dispatchEvent(new CustomEvent(OPEN_ERROR_REPORT_EVENT));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (prompt === '/survey') {
|
||||
if (!requireChatProjectForUserAction()) {
|
||||
return true;
|
||||
|
||||
@@ -5072,7 +5072,6 @@ export function registerDeveloperToolsTests() {
|
||||
expect(screen.getByText(/\/privacy:查看隐私与导出边界/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/audience:查看首批试玩对象/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/invite:准备试玩邀请文案/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/bug-report:报告问题/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/survey:准备试玩问卷问题/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/cover:准备封面与缩略图检查/)).not.toBeNull();
|
||||
expect(screen.getByText(/\/screenshots:准备宣传截图清单/)).not.toBeNull();
|
||||
|
||||
+5
-21
@@ -1,4 +1,3 @@
|
||||
import { OPEN_ERROR_REPORT_EVENT } from '../../../../src/services/errorReporting';
|
||||
import { expect, fireEvent, screen, submitChat, within } from '../../harness';
|
||||
import type { PreviewShortcutInvoke } from './invoke-mock';
|
||||
|
||||
@@ -47,7 +46,6 @@ export async function assertPlaytestAndReleaseShortcutFlow(
|
||||
expect(screen.getByText(/查看隐私与导出边界:\/privacy/)).not.toBeNull();
|
||||
expect(screen.getByText(/查看首批试玩对象:\/audience/)).not.toBeNull();
|
||||
expect(screen.getByText(/准备试玩邀请文案:\/invite/)).not.toBeNull();
|
||||
expect(screen.getByText(/报告问题:\/bug-report/)).not.toBeNull();
|
||||
expect(screen.getByText(/准备试玩问卷问题:\/survey/)).not.toBeNull();
|
||||
expect(screen.getByText(/准备封面与缩略图检查:\/cover/)).not.toBeNull();
|
||||
expect(screen.getByText(/准备宣传截图清单:\/screenshots/)).not.toBeNull();
|
||||
@@ -648,20 +646,6 @@ export async function assertPlaytestAndReleaseShortcutFlow(
|
||||
([command]) => command === 'control_agent_run',
|
||||
).length,
|
||||
};
|
||||
let openedErrorReport = false;
|
||||
const onErrorReportOpen = () => {
|
||||
openedErrorReport = true;
|
||||
};
|
||||
window.addEventListener(OPEN_ERROR_REPORT_EVENT, onErrorReportOpen);
|
||||
try {
|
||||
submitChat('/bug-report');
|
||||
expect(
|
||||
await screen.findByText('已打开“报告问题”面板,请填写遇到的问题。'),
|
||||
).not.toBeNull();
|
||||
expect(openedErrorReport).toBe(true);
|
||||
} finally {
|
||||
window.removeEventListener(OPEN_ERROR_REPORT_EVENT, onErrorReportOpen);
|
||||
}
|
||||
expect(
|
||||
invoke.mock.calls.filter(
|
||||
([command]) => command === 'get_local_game_manifest',
|
||||
@@ -753,10 +737,10 @@ export async function assertPlaytestAndReleaseShortcutFlow(
|
||||
'记录格式:每题 1-5 分 + 一句话;补充设备、输入方式、是否愿意再玩一局',
|
||||
);
|
||||
expect(surveyMessage.textContent).toContain(
|
||||
'追踪方式:单个问题走 /bug-report;整体反馈走 /feedback;下一轮改动走 /revise',
|
||||
'追踪方式:客户端问题由自动诊断提示;整体反馈走 /feedback;下一轮改动走 /revise',
|
||||
);
|
||||
expect(surveyMessage.textContent).toContain(
|
||||
'参考:/invite;/audience;/feedback;/bug-report',
|
||||
'参考:/invite;/audience;/feedback',
|
||||
);
|
||||
expect(surveyMessage.textContent).toContain(
|
||||
'边界:只准备试玩问卷;不读取文件;不启动或打开预览;不导出试玩包;不写项目',
|
||||
@@ -1185,7 +1169,7 @@ export async function assertPlaytestAndReleaseShortcutFlow(
|
||||
'回答口径:早期本地 Web 原型;5-10 分钟试玩;重点反馈目标理解、操作手感、难度、bug 和还想不想再玩',
|
||||
);
|
||||
expect(faqMessage.textContent).toContain(
|
||||
'测试者提醒:先自由玩一局;不要评价完成度;问卷走 /survey;单个问题走 /bug-report',
|
||||
'测试者提醒:先自由玩一局;不要评价完成度;问卷走 /survey;客户端问题由自动诊断提示',
|
||||
);
|
||||
expect(faqMessage.textContent).toContain(
|
||||
'交付搭配:/invite;/share;/screenshots;/trailer',
|
||||
@@ -1296,7 +1280,7 @@ export async function assertPlaytestAndReleaseShortcutFlow(
|
||||
'标签建议:#Web小游戏 #原型试玩 #AI游戏创作 #本地试玩',
|
||||
);
|
||||
expect(postMessage.textContent).toContain(
|
||||
'CTA:愿意试玩请回复;遇到问题按 /faq 或 /bug-report 的口径反馈',
|
||||
'CTA:愿意试玩请回复;遇到问题按 /faq 的口径反馈,客户端问题会自动提示',
|
||||
);
|
||||
expect(postMessage.textContent).toContain(
|
||||
'参考:/faq;/screenshots;/trailer;/store;/share',
|
||||
@@ -1735,7 +1719,7 @@ export async function assertPlaytestAndReleaseShortcutFlow(
|
||||
'试玩限制:本地 Web 原型;小范围 5-10 分钟试玩;不承诺账号、云存档、排行榜、付费或长期兼容',
|
||||
);
|
||||
expect(knownIssueMessage.textContent).toContain(
|
||||
'反馈入口:单个问题走 /bug-report;整体体验走 /feedback;版本变化走 /release-notes',
|
||||
'反馈入口:客户端问题由自动诊断提示;整体体验走 /feedback;版本变化走 /release-notes',
|
||||
);
|
||||
expect(knownIssueMessage.textContent).toContain(
|
||||
'发送前检查:可试玩状态先 /run;交付口径看 /share;对外资料看 /media-kit',
|
||||
|
||||
+1
-1
@@ -916,7 +916,7 @@ export async function assertProjectAndDesignShortcutFlow(
|
||||
'不承诺:旧浏览器、低端设备、离线模式、云存档、账号同步、手柄或多端数据一致',
|
||||
);
|
||||
expect(compatibilityMessage.textContent).toContain(
|
||||
'反馈口径:设备 / 浏览器 / 输入方式 / 截图或录屏;问题记录走 /bug-report',
|
||||
'反馈口径:设备 / 浏览器 / 输入方式 / 截图或录屏;客户端检测到问题时会自动提示',
|
||||
);
|
||||
expect(compatibilityMessage.textContent).toContain(
|
||||
'参考:/mobile;/accessibility;/performance;/known-issues',
|
||||
|
||||
@@ -11,7 +11,8 @@ AI Game Creator Shell 采用 IDEA 风格的当前进程错误报告:错误事
|
||||
- 指纹计算可使用调用方的 page/action 及脱敏后的首个调用点作为进程内区分输入,但这些上下文不会作为事件字段上传;消息与 stack 在入池前统一脱敏,WebCrypto 失败时降级为稳定可读指纹,采集本身不得产生新的未处理拒绝。
|
||||
- 客户端 API 自动采集只覆盖网络错误、408 和 5xx;预期的 4xx 登录/鉴权失败不进入错误报告池。
|
||||
- Rust 侧通过 `app_log!` 将普通文本日志同时输出到 stderr 和 AppData `diagnostics/application.log`,超出 256 KiB 滚动到 `application.previous.log`;WebView 的 console 输出通过 `append_application_log` 镜像到同一 raw log,并在客户端桥接处再次脱敏;`read_diagnostic_logs` 只读取应用级日志。
|
||||
- 报告面板允许填写最多 2,000 字中文描述并取消日志附件;本版本不支持截图或任意文件附件。
|
||||
- 报告面板只由自动诊断通知中的“查看并报告”打开,不提供聊天命令、崩溃页按钮或其他手动入口;默认选中最新事件,其他事件可勾选。允许填写最多 2,000 字中文描述并取消日志附件;本版本不支持截图或任意文件附件。
|
||||
- 错误事件先在当前进程内存池按 fingerprint 合并,经过 5 秒聚合后只显示一条非阻塞通知;通知支持“查看并报告”和“忽略”,同一 fingerprint 在本次运行中只提醒一次。通知不直接打开阻塞式报告面板。
|
||||
- 上传失败只在当前进程显示失败并允许用户再次提交,不跨重启恢复事件池,不后台自动重试。
|
||||
|
||||
## HTTP 与存储
|
||||
|
||||
Reference in New Issue
Block a user