@mseep/anything-analyzer 3.6.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/.codeartsdoer/.codebaseignore +0 -0
  2. package/.codeartsdoer/AGENTS.md +12 -0
  3. package/.github/workflows/build.yml +146 -0
  4. package/README.en.md +264 -0
  5. package/README.md +276 -0
  6. package/RELEASE_NOTES.md +16 -0
  7. package/USAGE.md +490 -0
  8. package/color-preview-r3.html +414 -0
  9. package/color-preview.html +414 -0
  10. package/dev-app-update.yml +3 -0
  11. package/electron-builder.yml +36 -0
  12. package/electron.vite.config.ts +40 -0
  13. package/package.json +53 -0
  14. package/report-2026-04-13-copilot-claude-sonnet-4.6.md +955 -0
  15. package/resources/doloffer-logo.png +0 -0
  16. package/resources/entitlements.mac.plist +12 -0
  17. package/resources/icon.ico +0 -0
  18. package/resources/icon.png +0 -0
  19. package/src/main/ai/ai-analyzer.ts +517 -0
  20. package/src/main/ai/crypto-script-extractor.ts +206 -0
  21. package/src/main/ai/data-assembler.ts +205 -0
  22. package/src/main/ai/llm-router.ts +1120 -0
  23. package/src/main/ai/prompt-builder.ts +349 -0
  24. package/src/main/ai/scene-detector.ts +302 -0
  25. package/src/main/capture/capture-engine.ts +130 -0
  26. package/src/main/capture/interaction-recorder.ts +171 -0
  27. package/src/main/capture/js-injector.ts +57 -0
  28. package/src/main/capture/replay-engine.ts +256 -0
  29. package/src/main/capture/storage-collector.ts +76 -0
  30. package/src/main/cdp/cdp-manager.ts +233 -0
  31. package/src/main/db/database.ts +41 -0
  32. package/src/main/db/migrations.ts +235 -0
  33. package/src/main/db/repositories.ts +574 -0
  34. package/src/main/fingerprint/http-spoofing.ts +48 -0
  35. package/src/main/fingerprint/presets.ts +173 -0
  36. package/src/main/fingerprint/profile-generator.ts +115 -0
  37. package/src/main/fingerprint/profile-store.ts +52 -0
  38. package/src/main/index.ts +260 -0
  39. package/src/main/ipc.ts +856 -0
  40. package/src/main/logger.ts +42 -0
  41. package/src/main/mcp/mcp-config.ts +66 -0
  42. package/src/main/mcp/mcp-manager.ts +155 -0
  43. package/src/main/mcp/mcp-server.ts +1038 -0
  44. package/src/main/prompt-templates.ts +170 -0
  45. package/src/main/proxy/ca-manager.ts +204 -0
  46. package/src/main/proxy/cert-download-page.ts +171 -0
  47. package/src/main/proxy/cert-installer.ts +242 -0
  48. package/src/main/proxy/mitm-proxy-config.ts +37 -0
  49. package/src/main/proxy/mitm-proxy-server.ts +1085 -0
  50. package/src/main/proxy/system-proxy.ts +248 -0
  51. package/src/main/session/session-manager.ts +724 -0
  52. package/src/main/tab-manager.ts +582 -0
  53. package/src/main/updater.ts +111 -0
  54. package/src/main/window.ts +235 -0
  55. package/src/preload/hook-script.ts +270 -0
  56. package/src/preload/index.ts +211 -0
  57. package/src/preload/interaction-hook.ts +286 -0
  58. package/src/preload/stealth-script.ts +302 -0
  59. package/src/preload/target-preload.ts +15 -0
  60. package/src/renderer/App.tsx +656 -0
  61. package/src/renderer/components/AiLogDetail.tsx +173 -0
  62. package/src/renderer/components/AiLogList.tsx +101 -0
  63. package/src/renderer/components/AiLogView.module.css +364 -0
  64. package/src/renderer/components/AiLogView.tsx +86 -0
  65. package/src/renderer/components/AnalyzeBar.module.css +79 -0
  66. package/src/renderer/components/AnalyzeBar.tsx +104 -0
  67. package/src/renderer/components/BrowserPanel.module.css +67 -0
  68. package/src/renderer/components/BrowserPanel.tsx +90 -0
  69. package/src/renderer/components/ControlBar.module.css +47 -0
  70. package/src/renderer/components/ControlBar.tsx +205 -0
  71. package/src/renderer/components/HookLog.tsx +132 -0
  72. package/src/renderer/components/InteractionLog.tsx +183 -0
  73. package/src/renderer/components/MCPServerModal.tsx +427 -0
  74. package/src/renderer/components/PromptTemplateModal.tsx +254 -0
  75. package/src/renderer/components/ReportView.module.css +413 -0
  76. package/src/renderer/components/ReportView.tsx +429 -0
  77. package/src/renderer/components/RequestDetail.module.css +191 -0
  78. package/src/renderer/components/RequestDetail.tsx +202 -0
  79. package/src/renderer/components/RequestLog.module.css +69 -0
  80. package/src/renderer/components/RequestLog.tsx +208 -0
  81. package/src/renderer/components/SessionList.module.css +245 -0
  82. package/src/renderer/components/SessionList.tsx +247 -0
  83. package/src/renderer/components/SettingsModal.tsx +100 -0
  84. package/src/renderer/components/StatusBar.module.css +44 -0
  85. package/src/renderer/components/StatusBar.tsx +102 -0
  86. package/src/renderer/components/StorageView.module.css +41 -0
  87. package/src/renderer/components/StorageView.tsx +178 -0
  88. package/src/renderer/components/TabBar.module.css +88 -0
  89. package/src/renderer/components/TabBar.tsx +70 -0
  90. package/src/renderer/components/Titlebar.module.css +254 -0
  91. package/src/renderer/components/Titlebar.tsx +169 -0
  92. package/src/renderer/components/settings/FingerprintSection.tsx +198 -0
  93. package/src/renderer/components/settings/GeneralSection.tsx +164 -0
  94. package/src/renderer/components/settings/LLMSection.tsx +148 -0
  95. package/src/renderer/components/settings/MCPServerSection.tsx +136 -0
  96. package/src/renderer/components/settings/MitmProxySection.tsx +320 -0
  97. package/src/renderer/components/settings/ProxySection.tsx +110 -0
  98. package/src/renderer/css-modules.d.ts +4 -0
  99. package/src/renderer/hooks/useCapture.ts +383 -0
  100. package/src/renderer/hooks/useConfirm.tsx +91 -0
  101. package/src/renderer/hooks/useSession.ts +136 -0
  102. package/src/renderer/hooks/useTabs.ts +103 -0
  103. package/src/renderer/i18n/en.ts +167 -0
  104. package/src/renderer/i18n/index.ts +47 -0
  105. package/src/renderer/i18n/zh.ts +170 -0
  106. package/src/renderer/index.html +12 -0
  107. package/src/renderer/main.tsx +15 -0
  108. package/src/renderer/styles/global.css +144 -0
  109. package/src/renderer/styles/themes/ayu-dark.css +59 -0
  110. package/src/renderer/styles/themes/catppuccin.css +59 -0
  111. package/src/renderer/styles/themes/discord.css +59 -0
  112. package/src/renderer/styles/themes/dracula.css +59 -0
  113. package/src/renderer/styles/themes/github-dark.css +59 -0
  114. package/src/renderer/styles/themes/gruvbox.css +59 -0
  115. package/src/renderer/styles/themes/index.css +11 -0
  116. package/src/renderer/styles/themes/light.css +59 -0
  117. package/src/renderer/styles/themes/nord.css +59 -0
  118. package/src/renderer/styles/themes/one-dark.css +59 -0
  119. package/src/renderer/styles/themes/tokyo-night.css +59 -0
  120. package/src/renderer/styles/tokens.css +137 -0
  121. package/src/renderer/theme.ts +31 -0
  122. package/src/renderer/ui/Badge.module.css +38 -0
  123. package/src/renderer/ui/Badge.tsx +36 -0
  124. package/src/renderer/ui/Button.module.css +142 -0
  125. package/src/renderer/ui/Button.tsx +46 -0
  126. package/src/renderer/ui/Collapse.module.css +49 -0
  127. package/src/renderer/ui/Collapse.tsx +57 -0
  128. package/src/renderer/ui/CopyableBlock.module.css +56 -0
  129. package/src/renderer/ui/CopyableBlock.tsx +42 -0
  130. package/src/renderer/ui/Empty.module.css +19 -0
  131. package/src/renderer/ui/Empty.tsx +34 -0
  132. package/src/renderer/ui/Icons.tsx +346 -0
  133. package/src/renderer/ui/Input.module.css +103 -0
  134. package/src/renderer/ui/Input.tsx +94 -0
  135. package/src/renderer/ui/InputNumber.module.css +68 -0
  136. package/src/renderer/ui/InputNumber.tsx +104 -0
  137. package/src/renderer/ui/Modal.module.css +83 -0
  138. package/src/renderer/ui/Modal.tsx +67 -0
  139. package/src/renderer/ui/Popconfirm.module.css +73 -0
  140. package/src/renderer/ui/Popconfirm.tsx +74 -0
  141. package/src/renderer/ui/Progress.module.css +35 -0
  142. package/src/renderer/ui/Progress.tsx +30 -0
  143. package/src/renderer/ui/Select.module.css +91 -0
  144. package/src/renderer/ui/Select.tsx +100 -0
  145. package/src/renderer/ui/Spinner.module.css +44 -0
  146. package/src/renderer/ui/Spinner.tsx +27 -0
  147. package/src/renderer/ui/Switch.module.css +39 -0
  148. package/src/renderer/ui/Switch.tsx +43 -0
  149. package/src/renderer/ui/Tabs.module.css +76 -0
  150. package/src/renderer/ui/Tabs.tsx +53 -0
  151. package/src/renderer/ui/Tag.module.css +66 -0
  152. package/src/renderer/ui/Tag.tsx +47 -0
  153. package/src/renderer/ui/Timeline.module.css +42 -0
  154. package/src/renderer/ui/Timeline.tsx +29 -0
  155. package/src/renderer/ui/Toast.module.css +99 -0
  156. package/src/renderer/ui/Toast.tsx +90 -0
  157. package/src/renderer/ui/Tooltip.module.css +26 -0
  158. package/src/renderer/ui/Tooltip.tsx +23 -0
  159. package/src/renderer/ui/VirtualTable.module.css +230 -0
  160. package/src/renderer/ui/VirtualTable.tsx +416 -0
  161. package/src/renderer/ui/index.ts +55 -0
  162. package/src/shared/types.ts +695 -0
  163. package/tests/main/ai/crypto-script-extractor.test.ts +281 -0
  164. package/tests/main/ai/llm-router.test.ts +1537 -0
  165. package/tests/main/ai/prompt-builder.test.ts +178 -0
  166. package/tests/main/ai/scene-detector.test.ts +212 -0
  167. package/tests/main/db/migrations.test.ts +134 -0
  168. package/tests/main/release-workflow.test.ts +59 -0
  169. package/tsconfig.json +7 -0
  170. package/tsconfig.node.json +23 -0
  171. package/tsconfig.web.json +24 -0
  172. package/vitest.config.ts +13 -0
@@ -0,0 +1,103 @@
1
+ import { useState, useEffect, useCallback } from "react";
2
+ import type { BrowserTab } from "@shared/types";
3
+
4
+ export interface UseTabsReturn {
5
+ tabs: BrowserTab[];
6
+ activeTabId: string | null;
7
+ activeTabUrl: string;
8
+ isActiveTabLoading: boolean;
9
+ activateTab: (tabId: string) => void;
10
+ closeTab: (tabId: string) => void;
11
+ createTab: (url?: string) => void;
12
+ }
13
+
14
+ /**
15
+ * useTabs — React hook for managing browser tab state.
16
+ * Synchronizes with the main process TabManager via IPC events.
17
+ */
18
+ export function useTabs(): UseTabsReturn {
19
+ const [tabs, setTabs] = useState<BrowserTab[]>([]);
20
+ const [activeTabId, setActiveTabId] = useState<string | null>(null);
21
+
22
+ // Derive active tab URL
23
+ const activeTabUrl = tabs.find((t) => t.id === activeTabId)?.url || "";
24
+ const isActiveTabLoading = tabs.find((t) => t.id === activeTabId)?.isLoading || false;
25
+
26
+ // Load initial tab state
27
+ useEffect(() => {
28
+ window.electronAPI.listTabs().then((initialTabs) => {
29
+ setTabs(initialTabs);
30
+ const active = initialTabs.find((t) => t.isActive);
31
+ if (active) setActiveTabId(active.id);
32
+ });
33
+ }, []);
34
+
35
+ // Listen for tab events from main process
36
+ useEffect(() => {
37
+ window.electronAPI.onTabCreated((tab: BrowserTab) => {
38
+ setTabs((prev) => {
39
+ // Avoid duplicates
40
+ if (prev.some((t) => t.id === tab.id)) return prev;
41
+ return [
42
+ ...prev.map((t) => ({ ...t, isActive: false })),
43
+ { ...tab, isActive: true },
44
+ ];
45
+ });
46
+ setActiveTabId(tab.id);
47
+ });
48
+
49
+ window.electronAPI.onTabClosed((data: { tabId: string }) => {
50
+ setTabs((prev) => prev.filter((t) => t.id !== data.tabId));
51
+ setActiveTabId((prev) => (prev === data.tabId ? null : prev));
52
+ });
53
+
54
+ window.electronAPI.onTabActivated(
55
+ (data: { tabId: string; url: string; title: string }) => {
56
+ setTabs((prev) =>
57
+ prev.map((t) => ({
58
+ ...t,
59
+ isActive: t.id === data.tabId,
60
+ })),
61
+ );
62
+ setActiveTabId(data.tabId);
63
+ },
64
+ );
65
+
66
+ window.electronAPI.onTabUpdated(
67
+ (data: { tabId: string; url?: string; title?: string; isLoading?: boolean }) => {
68
+ setTabs((prev) =>
69
+ prev.map((t) => {
70
+ if (t.id !== data.tabId) return t;
71
+ return {
72
+ ...t,
73
+ url: data.url ?? t.url,
74
+ title: data.title ?? t.title,
75
+ isLoading: data.isLoading ?? t.isLoading,
76
+ };
77
+ }),
78
+ );
79
+ },
80
+ );
81
+
82
+ return () => {
83
+ window.electronAPI.removeAllListeners("tabs:created");
84
+ window.electronAPI.removeAllListeners("tabs:closed");
85
+ window.electronAPI.removeAllListeners("tabs:activated");
86
+ window.electronAPI.removeAllListeners("tabs:updated");
87
+ };
88
+ }, []);
89
+
90
+ const activateTab = useCallback((tabId: string) => {
91
+ window.electronAPI.activateTab(tabId);
92
+ }, []);
93
+
94
+ const closeTab = useCallback((tabId: string) => {
95
+ window.electronAPI.closeTab(tabId);
96
+ }, []);
97
+
98
+ const createTab = useCallback((url?: string) => {
99
+ window.electronAPI.createTab(url);
100
+ }, []);
101
+
102
+ return { tabs, activeTabId, activeTabUrl, isActiveTabLoading, activateTab, closeTab, createTab };
103
+ }
@@ -0,0 +1,167 @@
1
+ export const en = {
2
+ // NavBar
3
+ 'nav.browser': 'Browser',
4
+ 'nav.inspector': 'Inspector',
5
+ 'nav.report': 'AI Report',
6
+
7
+ // Titlebar
8
+ 'titlebar.switchToEn': 'Switch to English',
9
+ 'titlebar.switchToZh': '切换到中文',
10
+ 'titlebar.lightMode': 'Light Mode',
11
+ 'titlebar.darkMode': 'Dark Mode',
12
+
13
+ // Sessions
14
+ 'session.title': 'Sessions',
15
+ 'session.newSession': '+ New Session',
16
+ 'session.createTitle': 'Create Session',
17
+ 'session.name': 'Session Name',
18
+ 'session.namePlaceholder': 'Enter session name',
19
+ 'session.targetUrl': 'Target URL',
20
+ 'session.targetUrlPlaceholder': 'https://example.com',
21
+ 'session.cancel': 'Cancel',
22
+ 'session.create': 'Create',
23
+ 'session.selectOrCreate': 'Select or create a session to get started',
24
+ 'session.selectForReport': 'Select a session to view reports',
25
+ 'session.emptyTitle': 'Welcome to Anything',
26
+ 'session.emptyStep1': 'Create a new session in the sidebar',
27
+ 'session.emptyStep2': 'Visit the target website in the browser',
28
+ 'session.emptyStep3': 'Start capturing and interact with the site',
29
+ 'session.emptyStep4': 'Use AI to analyze captured protocol data',
30
+
31
+ // ControlBar
32
+ 'capture.start': 'Start Capture',
33
+ 'capture.pause': 'Pause',
34
+ 'capture.resume': 'Resume',
35
+ 'capture.stop': 'Stop',
36
+ 'capture.analyze': 'Analyze',
37
+ 'capture.analyzeSelected': 'Analyze Selected ({count})',
38
+ 'capture.autoDetect': 'Auto Detect',
39
+ 'capture.custom': 'Custom...',
40
+ 'capture.customPurpose': 'Enter analysis purpose...',
41
+ 'capture.stopped': 'Stopped',
42
+ 'capture.running': 'Running',
43
+ 'capture.paused': 'Paused',
44
+
45
+ // Data panel tabs
46
+ 'data.requests': 'Requests',
47
+ 'data.hooks': 'Hooks',
48
+ 'data.storage': 'Storage',
49
+ 'data.export': 'Export',
50
+ 'data.clearData': 'Clear Data',
51
+ 'data.clearEnv': 'Clear Env',
52
+ 'data.clearDataConfirm': 'Clear all capture data for this session? This cannot be undone.',
53
+ 'data.clearEnvConfirm': 'Clear all browser cookies, storage and cache? Login state will be lost.',
54
+ 'data.clear': 'Clear',
55
+ 'data.selected': 'Selected',
56
+ 'data.total': 'Total',
57
+
58
+ // Browser view
59
+ 'browser.start': 'Start',
60
+ 'browser.pause': 'Pause',
61
+ 'browser.stop': 'Stop',
62
+ 'browser.resume': 'Resume',
63
+ 'browser.requests': '{count} requests',
64
+
65
+ // StatusBar
66
+ 'status.session': 'Session',
67
+ 'status.requests': 'Requests',
68
+ 'status.hooks': 'Hooks',
69
+
70
+ // Report
71
+ 'report.title': 'Protocol Analysis Report',
72
+ 'report.export': 'Export .md',
73
+ 'report.reanalyze': 'Re-analyze',
74
+ 'report.stopAnalysis': 'Stop Analysis',
75
+ 'report.startAnalysis': 'Start AI Analysis',
76
+ 'report.noReport': 'No analysis report yet',
77
+ 'report.analyzing': 'AI is analyzing captured data...',
78
+ 'report.preparing': 'Preparing analysis...',
79
+ 'report.thinking': 'Thinking...',
80
+ 'report.analysisFailed': 'Analysis failed',
81
+ 'report.followUpFailed': 'Follow-up failed',
82
+ 'report.askFollowUp': 'Ask a follow-up...',
83
+ 'report.genPython': 'Generate Python reproduction code',
84
+ 'report.explainCrypto': 'Explain encryption/signing flow',
85
+ 'report.securityRisks': 'Analyze potential security risks',
86
+ 'report.listApiParams': 'List all API params and response structures',
87
+
88
+ // Settings
89
+ 'settings.title': 'Settings',
90
+
91
+ // Common
92
+ 'common.cancel': 'Cancel',
93
+ 'common.ok': 'OK',
94
+ 'common.reset': 'Reset',
95
+ 'common.noData': 'No data',
96
+
97
+ // Toast messages
98
+ 'toast.envCleared': 'Browser environment cleared',
99
+ 'toast.envClearFailed': 'Failed to clear browser environment',
100
+ 'toast.dataCleared': 'Capture data cleared',
101
+ 'toast.dataClearFailed': 'Failed to clear data',
102
+
103
+ // Fingerprint settings
104
+ 'fingerprint.title': 'Fingerprint',
105
+ 'fingerprint.noSession': 'Select a session first',
106
+ 'fingerprint.summary': 'Current Fingerprint Summary',
107
+ 'fingerprint.platform': 'Platform',
108
+ 'fingerprint.screen': 'Screen Resolution',
109
+ 'fingerprint.dpr': 'Device Pixel Ratio',
110
+ 'fingerprint.cpu': 'CPU Cores',
111
+ 'fingerprint.memory': 'Memory (GB)',
112
+ 'fingerprint.webgl': 'WebGL Renderer',
113
+ 'fingerprint.timezone': 'Timezone',
114
+ 'fingerprint.languages': 'Languages',
115
+ 'fingerprint.webrtc': 'WebRTC Policy',
116
+ 'fingerprint.canvas': 'Canvas Noise Seed',
117
+ 'fingerprint.audio': 'Audio Noise Seed',
118
+ 'fingerprint.ua': 'User-Agent',
119
+ 'fingerprint.regenerate': 'Regenerate Fingerprint',
120
+ 'fingerprint.save': 'Save Changes',
121
+ 'fingerprint.saved': 'Fingerprint saved',
122
+ 'fingerprint.regenerated': 'New fingerprint generated',
123
+ 'fingerprint.detail': 'Details',
124
+ 'fingerprint.testLinks': 'Test Links',
125
+ // Interaction Recording
126
+ 'data.interactions': 'Interactions',
127
+ 'interaction.noData': 'No interaction data yet. Start capture and operate the page to record.',
128
+ 'interaction.click': 'Click',
129
+ 'interaction.dblclick': 'DblClick',
130
+ 'interaction.input': 'Input',
131
+ 'interaction.scroll': 'Scroll',
132
+ 'interaction.navigate': 'Navigate',
133
+ 'interaction.hover': 'Move',
134
+ 'interaction.element': 'Element',
135
+ 'interaction.position': 'Position',
136
+ 'interaction.value': 'Value',
137
+ 'interaction.path': 'Path Points',
138
+ 'interaction.selector': 'Selector',
139
+ 'interaction.url': 'Page',
140
+ 'interaction.clear': 'Clear',
141
+ 'interaction.clearConfirm': 'Clear all interaction recordings for this session?',
142
+ 'interaction.recording': 'Recording',
143
+ 'interaction.points': '{count} points',
144
+ // AI Request Log
145
+ 'aiLog.title': 'AI Request Log',
146
+ 'aiLog.backToReport': '← Back to Report',
147
+ 'aiLog.viewAllSessions': 'View All Sessions',
148
+ 'aiLog.backToSession': '← Back to Session',
149
+ 'aiLog.searchPlaceholder': 'Search model, URL...',
150
+ 'aiLog.filterAll': 'All',
151
+ 'aiLog.filterAnalyze': 'analyze',
152
+ 'aiLog.filterChat': 'chat',
153
+ 'aiLog.filterFilter': 'filter',
154
+ 'aiLog.noData': 'No AI request logs yet. Run an analysis to start recording.',
155
+ 'aiLog.tabRequest': 'Request Body',
156
+ 'aiLog.tabResponse': 'Response Body',
157
+ 'aiLog.tabHeaders': 'Headers',
158
+ 'aiLog.tabMeta': 'Meta',
159
+ 'aiLog.copy': 'Copy',
160
+ 'aiLog.copied': 'Copied',
161
+ 'aiLog.tokens': 'tokens',
162
+ 'aiLog.error': 'Error',
163
+ 'aiLog.requestHeaders': 'Request Headers',
164
+ 'aiLog.responseHeaders': 'Response Headers',
165
+ 'aiLog.session': 'Session',
166
+ 'aiLog.globalMode': 'Global Mode',
167
+ } as const
@@ -0,0 +1,47 @@
1
+ import React, { createContext, useContext, useCallback } from 'react'
2
+ import { zh } from './zh'
3
+ import { en } from './en'
4
+ import type { LocaleKey } from './zh'
5
+
6
+ export type Locale = 'zh' | 'en'
7
+
8
+ const localeMap: Record<Locale, Record<string, string>> = { zh, en }
9
+
10
+ interface LocaleContextValue {
11
+ locale: Locale
12
+ t: (key: LocaleKey, vars?: Record<string, string | number>) => string
13
+ }
14
+
15
+ const LocaleContext = createContext<LocaleContextValue>({
16
+ locale: 'zh',
17
+ t: (key) => key,
18
+ })
19
+
20
+ export function LocaleProvider({
21
+ locale,
22
+ children,
23
+ }: {
24
+ locale: Locale
25
+ children: React.ReactNode
26
+ }) {
27
+ const t = useCallback(
28
+ (key: LocaleKey, vars?: Record<string, string | number>) => {
29
+ let text = localeMap[locale]?.[key] ?? localeMap.zh[key] ?? key
30
+ if (vars) {
31
+ Object.entries(vars).forEach(([k, v]) => {
32
+ text = text.replace(`{${k}}`, String(v))
33
+ })
34
+ }
35
+ return text
36
+ },
37
+ [locale]
38
+ )
39
+
40
+ return React.createElement(LocaleContext.Provider, { value: { locale, t } }, children)
41
+ }
42
+
43
+ export function useLocale() {
44
+ return useContext(LocaleContext)
45
+ }
46
+
47
+ export type { LocaleKey }
@@ -0,0 +1,170 @@
1
+ export const zh = {
2
+ // NavBar
3
+ 'nav.browser': '浏览器',
4
+ 'nav.inspector': '检查器',
5
+ 'nav.report': 'AI 报告',
6
+
7
+ // Titlebar
8
+ 'titlebar.switchToEn': 'Switch to English',
9
+ 'titlebar.switchToZh': '切换到中文',
10
+ 'titlebar.lightMode': '浅色模式',
11
+ 'titlebar.darkMode': '深色模式',
12
+
13
+ // Sessions
14
+ 'session.title': '会话列表',
15
+ 'session.newSession': '+ 新建会话',
16
+ 'session.createTitle': '创建新会话',
17
+ 'session.name': '会话名称',
18
+ 'session.namePlaceholder': '输入会话名称',
19
+ 'session.targetUrl': '目标 URL',
20
+ 'session.targetUrlPlaceholder': 'https://example.com',
21
+ 'session.cancel': '取消',
22
+ 'session.create': '创建',
23
+ 'session.selectOrCreate': '选择或创建一个会话开始',
24
+ 'session.selectForReport': '选择一个会话查看报告',
25
+ 'session.emptyTitle': '欢迎使用 Anything',
26
+ 'session.emptyStep1': '在左侧创建一个新会话',
27
+ 'session.emptyStep2': '在浏览器中访问目标网站',
28
+ 'session.emptyStep3': '开始抓包,操作网站触发请求',
29
+ 'session.emptyStep4': '使用 AI 分析捕获的协议数据',
30
+
31
+ // ControlBar
32
+ 'capture.start': '开始抓包',
33
+ 'capture.pause': '暂停',
34
+ 'capture.resume': '恢复',
35
+ 'capture.stop': '停止',
36
+ 'capture.analyze': '分析',
37
+ 'capture.analyzeSelected': '分析选中 ({count})',
38
+ 'capture.autoDetect': '自动识别',
39
+ 'capture.custom': '自定义...',
40
+ 'capture.customPurpose': '输入分析目的...',
41
+ 'capture.stopped': '已停止',
42
+ 'capture.running': '运行中',
43
+ 'capture.paused': '已暂停',
44
+
45
+ // Data panel tabs
46
+ 'data.requests': '请求',
47
+ 'data.hooks': 'Hooks',
48
+ 'data.storage': '存储',
49
+ 'data.export': '导出',
50
+ 'data.clearData': '清除数据',
51
+ 'data.clearEnv': '清除环境',
52
+ 'data.clearDataConfirm': '清除此会话的所有抓包数据?此操作不可撤销。',
53
+ 'data.clearEnvConfirm': '清除所有浏览器 Cookie、存储和缓存?登录状态将丢失。',
54
+ 'data.clear': '清除',
55
+ 'data.selected': '已选',
56
+ 'data.total': '共',
57
+
58
+ // Browser view
59
+ 'browser.start': '开始',
60
+ 'browser.pause': '暂停',
61
+ 'browser.stop': '停止',
62
+ 'browser.resume': '恢复',
63
+ 'browser.requests': '{count} 个请求',
64
+
65
+ // StatusBar
66
+ 'status.session': '会话',
67
+ 'status.requests': '请求',
68
+ 'status.hooks': 'Hooks',
69
+
70
+ // Report
71
+ 'report.title': '协议分析报告',
72
+ 'report.export': '导出 .md',
73
+ 'report.reanalyze': '重新分析',
74
+ 'report.stopAnalysis': '停止分析',
75
+ 'report.startAnalysis': '开始 AI 分析',
76
+ 'report.noReport': '暂无分析报告',
77
+ 'report.analyzing': 'AI 正在分析捕获的数据...',
78
+ 'report.preparing': '准备分析中...',
79
+ 'report.thinking': '思考中...',
80
+ 'report.analysisFailed': '分析失败',
81
+ 'report.followUpFailed': '追问失败',
82
+ 'report.askFollowUp': '输入追问...',
83
+ 'report.genPython': '生成 Python 复现代码',
84
+ 'report.explainCrypto': '详解加密/签名流程',
85
+ 'report.securityRisks': '分析潜在安全风险',
86
+ 'report.listApiParams': '列出所有 API 参数和响应结构',
87
+
88
+ // Settings
89
+ 'settings.title': '设置',
90
+
91
+ // Common
92
+ 'common.cancel': '取消',
93
+ 'common.ok': '确定',
94
+ 'common.reset': '重置',
95
+ 'common.noData': '暂无数据',
96
+
97
+ // Toast messages
98
+ 'toast.envCleared': '浏览器环境已清除',
99
+ 'toast.envClearFailed': '清除浏览器环境失败',
100
+ 'toast.dataCleared': '抓包数据已清除',
101
+ 'toast.dataClearFailed': '清除数据失败',
102
+
103
+ // Fingerprint settings
104
+ 'fingerprint.title': '指纹环境',
105
+ 'fingerprint.noSession': '请先选择一个会话',
106
+ 'fingerprint.summary': '当前指纹概要',
107
+ 'fingerprint.platform': '平台',
108
+ 'fingerprint.screen': '屏幕分辨率',
109
+ 'fingerprint.dpr': '设备像素比',
110
+ 'fingerprint.cpu': 'CPU 核心数',
111
+ 'fingerprint.memory': '内存 (GB)',
112
+ 'fingerprint.webgl': 'WebGL 渲染器',
113
+ 'fingerprint.timezone': '时区',
114
+ 'fingerprint.languages': '语言',
115
+ 'fingerprint.webrtc': 'WebRTC 策略',
116
+ 'fingerprint.canvas': 'Canvas 噪声种子',
117
+ 'fingerprint.audio': '音频噪声种子',
118
+ 'fingerprint.ua': 'User-Agent',
119
+ 'fingerprint.regenerate': '随机生成新指纹',
120
+ 'fingerprint.save': '保存修改',
121
+ 'fingerprint.saved': '指纹配置已保存',
122
+ 'fingerprint.regenerated': '已生成新指纹',
123
+ 'fingerprint.detail': '详细配置',
124
+ 'fingerprint.testLinks': '自测链接',
125
+ // Interaction Recording
126
+ 'data.interactions': '交互录制',
127
+ 'interaction.noData': '暂无交互录制数据。开始抓包并操作页面即可自动录制。',
128
+ 'interaction.click': '点击',
129
+ 'interaction.dblclick': '双击',
130
+ 'interaction.input': '输入',
131
+ 'interaction.scroll': '滚动',
132
+ 'interaction.navigate': '导航',
133
+ 'interaction.hover': '移动轨迹',
134
+ 'interaction.element': '元素',
135
+ 'interaction.position': '坐标',
136
+ 'interaction.value': '值',
137
+ 'interaction.path': '轨迹点',
138
+ 'interaction.selector': '选择器',
139
+ 'interaction.url': '页面',
140
+ 'interaction.clear': '清除录制',
141
+ 'interaction.clearConfirm': '清除此会话的所有交互录制数据?',
142
+ 'interaction.recording': '录制中',
143
+ 'interaction.points': '{count} 个点',
144
+
145
+ // AI Request Log
146
+ 'aiLog.title': 'AI 请求日志',
147
+ 'aiLog.backToReport': '← 返回报告',
148
+ 'aiLog.viewAllSessions': '查看所有 Session',
149
+ 'aiLog.backToSession': '← 返回当前 Session',
150
+ 'aiLog.searchPlaceholder': '搜索模型、URL...',
151
+ 'aiLog.filterAll': '全部',
152
+ 'aiLog.filterAnalyze': 'analyze',
153
+ 'aiLog.filterChat': 'chat',
154
+ 'aiLog.filterFilter': 'filter',
155
+ 'aiLog.noData': '暂无 AI 请求日志。运行一次分析即可开始记录。',
156
+ 'aiLog.tabRequest': 'Request Body',
157
+ 'aiLog.tabResponse': 'Response Body',
158
+ 'aiLog.tabHeaders': 'Headers',
159
+ 'aiLog.tabMeta': 'Meta',
160
+ 'aiLog.copy': '复制',
161
+ 'aiLog.copied': '已复制',
162
+ 'aiLog.tokens': 'tokens',
163
+ 'aiLog.error': '错误',
164
+ 'aiLog.requestHeaders': '请求头',
165
+ 'aiLog.responseHeaders': '响应头',
166
+ 'aiLog.session': 'Session',
167
+ 'aiLog.globalMode': '全局模式',
168
+ } as const
169
+
170
+ export type LocaleKey = keyof typeof zh
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>AnythingRegister</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="./main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,15 @@
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import { ToastProvider } from './ui/Toast'
4
+ import App from './App'
5
+ import './styles/tokens.css'
6
+ import './styles/themes/index.css'
7
+ import './styles/global.css'
8
+
9
+ ReactDOM.createRoot(document.getElementById('root')!).render(
10
+ <React.StrictMode>
11
+ <ToastProvider>
12
+ <App />
13
+ </ToastProvider>
14
+ </React.StrictMode>
15
+ )
@@ -0,0 +1,144 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ html, body, #root {
8
+ width: 100%;
9
+ height: 100%;
10
+ overflow: hidden;
11
+ background: var(--color-content);
12
+ font-family: var(--font-sans);
13
+ }
14
+
15
+ ::-webkit-scrollbar {
16
+ width: 10px;
17
+ height: 10px;
18
+ }
19
+
20
+ ::-webkit-scrollbar-track {
21
+ background: transparent;
22
+ /* 右侧留出 2px 安全距离,避免与窗口 resize handle 重叠 */
23
+ border-right: 2px solid transparent;
24
+ }
25
+
26
+ ::-webkit-scrollbar-thumb {
27
+ background: var(--text-disabled);
28
+ border-radius: 5px;
29
+ /* 用透明 border 收缩可视区域,thumb 实际绘制宽度 ≈ 6px,但点击区域是完整 10px */
30
+ border: 2px solid transparent;
31
+ background-clip: padding-box;
32
+ }
33
+
34
+ ::-webkit-scrollbar-thumb:hover {
35
+ background: var(--text-muted);
36
+ border: 2px solid transparent;
37
+ background-clip: padding-box;
38
+ }
39
+
40
+ /* ---- Markdown content styling (used in ReportView) ---- */
41
+ .report-markdown-content h1 {
42
+ font-size: var(--font-size-2xl);
43
+ color: var(--text-primary);
44
+ font-weight: 600;
45
+ margin: 20px 0 10px;
46
+ }
47
+
48
+ .report-markdown-content h2 {
49
+ font-size: var(--font-size-lg);
50
+ color: var(--text-primary);
51
+ font-weight: 600;
52
+ margin: 16px 0 8px;
53
+ padding-bottom: 6px;
54
+ border-bottom: 1px solid var(--color-border);
55
+ }
56
+
57
+ .report-markdown-content h3 {
58
+ font-size: var(--font-size-md);
59
+ color: var(--text-secondary);
60
+ font-weight: 600;
61
+ margin: 12px 0 6px;
62
+ }
63
+
64
+ .report-markdown-content p {
65
+ font-size: var(--font-size-base);
66
+ color: var(--text-secondary);
67
+ line-height: var(--line-height-relaxed);
68
+ margin-bottom: var(--space-lg);
69
+ }
70
+
71
+ .report-markdown-content ul,
72
+ .report-markdown-content ol {
73
+ padding-left: 20px;
74
+ margin-bottom: var(--space-lg);
75
+ }
76
+
77
+ .report-markdown-content li {
78
+ font-size: var(--font-size-base);
79
+ color: var(--text-secondary);
80
+ line-height: var(--line-height-relaxed);
81
+ margin-bottom: var(--space-xs);
82
+ }
83
+
84
+ .report-markdown-content code {
85
+ font-family: var(--font-mono);
86
+ font-size: var(--font-size-sm);
87
+ background: var(--color-surface);
88
+ padding: 1px 4px;
89
+ border-radius: 3px;
90
+ color: var(--color-warning);
91
+ }
92
+
93
+ .report-markdown-content pre {
94
+ background: var(--color-surface);
95
+ border: 1px solid var(--color-border-subtle);
96
+ border-radius: var(--radius-button);
97
+ padding: 10px 14px;
98
+ margin: 10px 0;
99
+ overflow-x: auto;
100
+ }
101
+
102
+ .report-markdown-content pre code {
103
+ background: none;
104
+ padding: 0;
105
+ color: var(--text-secondary);
106
+ font-size: var(--font-size-sm);
107
+ line-height: 1.6;
108
+ }
109
+
110
+ .report-markdown-content table {
111
+ width: 100%;
112
+ border-collapse: collapse;
113
+ margin: 10px 0;
114
+ }
115
+
116
+ .report-markdown-content th,
117
+ .report-markdown-content td {
118
+ border: 1px solid var(--color-border);
119
+ padding: 6px 10px;
120
+ font-size: var(--font-size-base);
121
+ color: var(--text-secondary);
122
+ }
123
+
124
+ .report-markdown-content th {
125
+ background: var(--color-surface);
126
+ color: var(--text-primary);
127
+ font-weight: 600;
128
+ }
129
+
130
+ .report-markdown-content blockquote {
131
+ border-left: 3px solid var(--color-border-hover);
132
+ padding: 4px 12px;
133
+ margin: 10px 0;
134
+ color: var(--text-muted);
135
+ }
136
+
137
+ .report-markdown-content a {
138
+ color: var(--color-info);
139
+ text-decoration: none;
140
+ }
141
+
142
+ .report-markdown-content a:hover {
143
+ text-decoration: underline;
144
+ }